void test_truncated_data()
{
  spdy_frame_t the_frame;
  spdy_frame_t *frame = &the_frame;
  spdy_frame_create(frame);
  int res = spdy_frame_parse(frame, (uint8_t*)test_packet_truncated_data, sizeof(test_packet_truncated_data));
  assert(res == SPDY_FRAME_ERROR_INCOMPLETE);
  
  spdy_frame_destroy(frame);
}
void test_goaway_parse()
{
  spdy_frame_t the_frame;
  spdy_frame_t *frame = &the_frame;
  spdy_frame_create(frame);

  int res = spdy_frame_parse(frame, (uint8_t*)test_packet_goaway, sizeof(test_packet_goaway));
  assert(res > 0);

  assert(frame->frame_type == SPDY_CONTROL_FRAME);
  assert(frame->protocol_version == 2);
  assert(frame->control_frame_type == SPDY_CONTROL_GOAWAY);
  assert(frame->flags == 0);
  assert(frame->data_length == 4);

  assert(frame->control_header.goaway.last_good_stream_id == 1);
}
void test_data_frame_parse()
{
  spdy_frame_t the_frame;
  spdy_frame_t *frame = &the_frame;
  spdy_frame_create(frame);
  int res = spdy_frame_parse(frame, (uint8_t*)test_packet_data_frame, sizeof(test_packet_data_frame));
  assert(res > 0);

  assert(frame->frame_type == SPDY_DATA_FRAME);
  assert(frame->stream_id == 1);  
  assert(frame->flags == 0);
  assert(frame->data_length == 13);

  assert(frame->data != 0);

  assert(memcmp("This is SPDY.", frame->data, frame->data_length) == 0);

  spdy_frame_destroy(frame);
}
void test_ping_parse()
{
  spdy_frame_t the_frame;
  spdy_frame_t *frame = &the_frame;
  spdy_frame_create(frame);

  int res = spdy_frame_parse(frame, (uint8_t*)test_packet_ping, sizeof(test_packet_ping));
  assert(res > 0);

  assert(frame->frame_type == SPDY_CONTROL_FRAME);
  assert(frame->protocol_version == 2);
  assert(frame->control_frame_type == SPDY_CONTROL_PING);
  assert(frame->flags == 0);
  assert(frame->data_length == 4);

  assert(frame->control_header.ping.ping_id == 1);

  spdy_frame_destroy(frame);
}
void test_settings_parse()
{
  spdy_frame_t the_frame;
  spdy_frame_t *frame = &the_frame;
  spdy_frame_create(frame);

  int res = spdy_frame_parse(frame, (uint8_t*)test_packet_settings, sizeof(test_packet_settings));
  assert(res > 0);

  assert(frame->frame_type == SPDY_CONTROL_FRAME);
  assert(frame->protocol_version == 2);
  assert(frame->control_frame_type == SPDY_CONTROL_SETTINGS);
  assert(frame->flags == 0);
  assert(frame->data_length == 12);

  // fixme: extract data

  spdy_frame_destroy(frame);
}
void test_rst_stream_parse()
{
  spdy_frame_t the_frame;
  spdy_frame_t *frame = &the_frame;
  spdy_frame_create(frame);

  int res = spdy_frame_parse(frame, (uint8_t*)test_packet_rst_stream, sizeof(test_packet_rst_stream));
  assert(res > 0);

  assert(frame->frame_type == SPDY_CONTROL_FRAME);
  assert(frame->protocol_version == 2);
  assert(frame->control_frame_type == SPDY_CONTROL_RST_STREAM);
  assert(frame->flags == 0);
  assert(frame->data_length == 8);

  assert(frame->control_header.rst_stream.stream_id == 1);
  assert(frame->control_header.rst_stream.status == 1);

  spdy_frame_destroy(frame);
}
void test_syn_reply_parse()
{
  spdy_frame_t the_frame;
  spdy_frame_t *frame = &the_frame;
  spdy_frame_create(frame);

  int res = spdy_frame_parse(frame, (uint8_t*)test_packet_syn_reply, sizeof(test_packet_syn_reply));
  assert(res > 0);

  assert(frame->frame_type == SPDY_CONTROL_FRAME);
  assert(frame->protocol_version == 2);
  assert(frame->control_frame_type == SPDY_CONTROL_SYN_REPLY);
  assert(frame->flags == 0);

  assert(frame->control_header.syn_reply.stream_id == 1);

  // FIXME: test headers
  
  spdy_frame_destroy(frame);
}
void test_syn_stream()
{
  spdy_frame_t the_frame;
  spdy_frame_t *frame = &the_frame;
  spdy_frame_create(frame);

  int res = spdy_frame_parse(frame, (uint8_t*)test_packet_syn_stream, sizeof(test_packet_syn_stream));
  assert(res > 0);

  assert(frame->frame_type == SPDY_CONTROL_FRAME);
  assert(frame->protocol_version == 2);
  assert(frame->control_frame_type == SPDY_CONTROL_SYN_STREAM);
  assert(frame->flags == 1);

  assert(frame->control_header.syn_stream.stream_id == 1);
  assert(frame->control_header.syn_stream.associated_stream_id == 0);
  assert(frame->control_header.syn_stream.priority == 0);
  assert(frame->control_header.syn_stream.slot == 0);

  // FIXME: test headers
  
  spdy_frame_destroy(frame);
}
Beispiel #9
0
/*
 * Returns information about incoming data, split up for consumption.
 * Subsequent calls will return the next result and so on until there's
 * nothing left to demux - until spindly_phys_incoming() is called again to
 * feed it with more data.
 *
 * When this function returns that there is no more message, it may still hold
 * trailing data that forms the beginning of the subsequent message.
 *
 * 'ptr' must point to the correct struct, read the first 'type' field of that
 * to know how to interpret the rest!
 */
spindly_error_t spindly_phys_demux(struct spindly_phys *phys,
                                   struct spindly_demux *ptr)
{
  struct list_node *n = _spindly_list_first(&phys->inq);
  struct spindly_indata *in= (struct spindly_indata *)n;
  int rc = SPINDLYE_OK;

  assert(ptr != NULL);

  ptr->type = SPINDLY_DX_NONE;

  do {

    if(phys->data.data_end <= phys->data.cursor)
      /* if the previously stored data is all consumed then get the
         current queue data */
      spdy_data_use(&phys->data, in->data, in->datalen);

    /*
     * Parse data. The parsing function wants a full frame to be in a
     * contiguous buffer so unless it is, we must create a full frame from the
     * input we have.
     */
    rc = spdy_frame_parse(&phys->frame, phys, &phys->data);

    if(rc == SPDY_ERROR_NONE) {
      if(phys->frame.type == SPDY_CONTROL_FRAME) {
        spdy_syn_stream *syn;
        spdy_syn_reply *rep;
        struct spindly_stream *stream;
        struct hashnode *n;

        switch(phys->frame.frame.control.type) {
        case SPDY_CTRL_SYN_STREAM:
          /*
           * At this point there's a syn_stream struct that needs to be
           * converted to a full spinly_stream struct!
           *
           * phys->frame.frame.control.obj.syn_stream
           */
          syn = &phys->frame.frame.control.obj.syn_stream;

          rc = _spindly_stream_init(phys, syn->priority, &stream, NULL,
                                    NULL, syn->stream_id);
          if(rc)
            /* TODO: how do we deal with a failure here? */
            break;

          ptr->type = SPINDLY_DX_STREAM_REQ;
          ptr->msg.stream.stream = stream;
          break;
        case SPDY_CTRL_SYN_REPLY:
          /*
           * At this point there's a syn_reply struct that needs to be
           * converted to a full spinly_stream struct!
           *
           * phys->frame.frame.control.obj.syn_reply
           */
          rep = &phys->frame.frame.control.obj.syn_reply;

          n = _spindly_hash_get(&phys->streamhash, rep->stream_id);
          if(!n)
            /* received a SYN_REPLY for an unknown streamid */
            rc = SPINDLYE_PROTOCOL;
          else {
            stream = n->ptr;
            stream->state = STREAM_ACKED;
            ptr->type = SPINDLY_DX_STREAM_ACK;
            ptr->msg.stream.stream = stream;
          }
          break;
        case SPDY_CTRL_RST_STREAM:
          assert(0); /* not implemented yet! */
          break;
        case SPDY_CTRL_SETTINGS:
          assert(0); /* not implemented yet! */
          break;
        case SPDY_CTRL_NOOP:
          assert(0); /* not implemented yet! */
          break;
        case SPDY_CTRL_PING:
          assert(0); /* not implemented yet! */
          break;
        case SPDY_CTRL_GOAWAY:
          assert(0); /* not implemented yet! */
          break;
        case SPDY_CTRL_HEADERS:
          assert(0); /* not implemented yet! */
          break;
        case SPDY_CTRL_WINDOW_UPDATE:
          assert(0); /* not implemented yet! */
          break;
        default:
          assert(0); /* internal error */
          break;
        }
        spdy_frame_destroy(&phys->frame);
      }
      else { /* data */
        ptr->type = SPINDLY_DX_DATA;
      }

      /* TODO: if the complete inq node was consumed, call the callback */

      return SPINDLYE_OK;
    }

    else if(rc == SPDY_ERROR_INSUFFICIENT_DATA) {
      /* if there's too little data to parse, merge the buffer with the next
       * in the queue and loop and parse the bigger one
       */
      bool more;
      rc = parse_append(phys, &more);

      if(!more)
        /* there's no more right now */
        return SPINDLYE_OK;
    }
  } while(!rc);

  return rc;
}