Пример #1
0
int spdy_headers_parse(spdy_headers *headers,
                       spdy_data *data,
                       uint32_t frame_length, spdy_zlib_context *zlib_ctx)
{
  int ret;
  size_t length = data->data_end - data->cursor;
  if(length < SPDY_HEADERS_MIN_LENGTH) {
    data->needed = SPDY_HEADERS_MIN_LENGTH - length;
    SPDYDEBUG("Not enough data for parsing the frame.");
    return SPDY_ERROR_INSUFFICIENT_DATA;
  }

  if((ret = spdy_headers_parse_header(headers, data)) != SPDY_ERROR_NONE) {
    SPDYDEBUG("Failed to parse header.");
    return ret;
  }

  /* Parse NV block. */
  if((ret = spdy_nv_block_inflate_parse(headers->nv_block,
                                        data->cursor,
                                        frame_length,
                                        zlib_ctx)) != SPDY_ERROR_NONE) {
    /* Clean up. */
    SPDYDEBUG("Failed to parse NV block.");
    return ret;
  }
  data->cursor += frame_length - SPDY_HEADERS_MIN_LENGTH;

  return SPDY_ERROR_NONE;
}
Пример #2
0
/**
 * Parse a data frame
 * @param frame - Target data frame.
 * @param data - Data to parse.
 * @see spdy_data_frame
 * @return Errorcode
 */
int spdy_data_frame_parse(spdy_data_frame *frame, spdy_data *data)
{
  int ret;
  size_t length;
  ret = spdy_data_frame_parse_header(frame, data);
  if(ret != SPDY_ERROR_NONE) {
    return ret;
  }

  length = data->data_end - data->cursor;
  if(frame->length > length) {
    data->needed = frame->length - length;
    SPDYDEBUG("Insufficient data for data frame.");
    return SPDY_ERROR_INSUFFICIENT_DATA;
  }

  frame->data = malloc(frame->length);
  if(!frame->data) {
    SPDYDEBUG("Frame payload malloc failed.");
    return SPDY_ERROR_MALLOC_FAILED;
  }
  memcpy(frame->data, data->cursor, frame->length);
  data->cursor += frame->length;

  return SPDY_ERROR_NONE;
}
Пример #3
0
/* TODO: Test & documentation. Do not use yet! */
int spdy_nv_block_inflate_parse(spdy_nv_block *nv_block,
                                unsigned char *data,
                                size_t data_length,
                                spdy_zlib_context *zlib_ctx)
{
  int ret;

  /* Inflate NV block. */
  char *inflate = NULL;
  size_t inflate_size = 0;

  if((ret = spdy_zlib_inflate(zlib_ctx,
                              (char *)data,
                              data_length,
                              &inflate, &inflate_size)) != SPDY_ERROR_NONE) {
    SPDYDEBUG("Failed to inflate data.");
    return ret;
  }

  /* Parse NV block. */
  ret = spdy_nv_block_parse(nv_block, (unsigned char *)inflate, inflate_size);

  free(inflate);

  if(ret != SPDY_ERROR_NONE) {
    /* Clean up. */
    SPDYDEBUG("Failed to parse NV block.");
    return ret;
  }

  return SPDY_ERROR_NONE;
}
Пример #4
0
/**
 * Parse a SYN_STREAM control frame.
 * Parses the header of a SYN_STREAM control frame and extracts the
 * NV block.
 * @param syn_stream - Destination frame.
 * @param hash - Streamid lookup
 * @param data - Data to parse.
 * @param frame_length - Length of the frame.
 * @see spdy_control_frame
 * @see SPDY_SYN_STREAM_MIN_LENGTH
 * @return 0 on success, -1 on failure.
 */
int spdy_syn_stream_parse(spdy_syn_stream *syn_stream,
                          struct spindly_phys *phys,
                          spdy_data *data,
                          uint32_t frame_length)
{
  int ret;
  size_t length = data->data_end - data->cursor;
  struct hashnode *hn;

  assert(phys != NULL);

  if(length < frame_length) {
    data->needed = frame_length - length;
    SPDYDEBUG("Not enough data for parsing the stream.");
    return SPDY_ERROR_INSUFFICIENT_DATA;
  }
  /* TODO: Optimize the double length check away. */
  if(length < SPDY_SYN_STREAM_MIN_LENGTH) {
    data->needed = SPDY_SYN_STREAM_MIN_LENGTH - length;
    SPDYDEBUG("Not enough data for parsing the stream.");
    return SPDY_ERROR_INSUFFICIENT_DATA;
  }

  /* Parse the frame header. */
  ret = spdy_syn_stream_parse_header(syn_stream, data);
  if(ret) {
    SPDYDEBUG("Failed to parse header.");
    return ret;
  }

  /* make sure the incoming streamid isn't already used */
  hn = _spindly_hash_get(&phys->streamhash, syn_stream->stream_id);
  if(hn) {
    SPDYDEBUG("Got a SPDY_STREAM with an exiting id!");
    return SPDY_ERROR_INVALID_DATA;
  }

  /* Init NV block. */
  ret = spdy_nv_block_init(&syn_stream->nv_block);
  if(ret)
    return ret;

  /* Parse NV block. */
  ret = spdy_nv_block_inflate_parse(&syn_stream->nv_block,
                                    data->cursor,
                                    frame_length,
                                    &phys->zlib_in);
  if(ret) {
    /* Clean up. */
    SPDYDEBUG("Failed to parse NV block.");
    return ret;
  }
  data->cursor += frame_length - SPDY_SYN_STREAM_HEADER_MIN_LENGTH;

  return SPDY_ERROR_NONE;
}
Пример #5
0
/**
 * Parse a SYN_STREAM control frame.
 * Parses the header of a SYN_STREAM control frame and extracts the
 * NV block.
 * @param syn_stream - Destination frame.
 * @param data - Data to parse.
 * @param frame_length - Length of the frame.
 * @param zlib_ctx - The zlib context to use.
 * @see spdy_control_frame
 * @see SPDY_SYN_STREAM_MIN_LENGTH
 * @return 0 on success, -1 on failure.
 */
int spdy_syn_stream_parse(spdy_syn_stream *syn_stream,
                          spdy_data *data,
                          uint32_t frame_length, spdy_zlib_context *zlib_ctx)
{
  int ret;
  size_t length = data->data_end - data->cursor;
  if(length < frame_length) {
    data->needed = frame_length - length;
    SPDYDEBUG("Not enough data for parsing the stream.");
    return SPDY_ERROR_INSUFFICIENT_DATA;
  }
  /* TODO: Optimize the double length check away. */
  if(length < SPDY_SYN_STREAM_MIN_LENGTH) {
    data->needed = SPDY_SYN_STREAM_MIN_LENGTH - length;
    SPDYDEBUG("Not enough data for parsing the stream.");
    return SPDY_ERROR_INSUFFICIENT_DATA;
  }

  /* Parse the frame header. */
  if((ret = spdy_syn_stream_parse_header(syn_stream, data)) != SPDY_ERROR_NONE) {
    SPDYDEBUG("Failed to parse header.");
    return ret;
  }

  /* Init NV block. */
  ret = spdy_nv_block_init(&syn_stream->nv_block);
  if(ret) {
    return ret;
  }

  /* Parse NV block. */
  if((ret = spdy_nv_block_inflate_parse(&syn_stream->nv_block,
                                        data->cursor,
                                        frame_length,
                                        zlib_ctx)) != SPDY_ERROR_NONE) {
    /* Clean up. */
    SPDYDEBUG("Failed to parse NV block.");
    return ret;
  }
  data->cursor += frame_length - SPDY_SYN_STREAM_HEADER_MIN_LENGTH;

  return SPDY_ERROR_NONE;
}
Пример #6
0
int spdy_headers_parse_header(spdy_headers *headers, spdy_data *data)
{
  size_t length = data->data_end - data->cursor;
  if(length < SPDY_HEADERS_MIN_LENGTH) {
    SPDYDEBUG("Not enough data for parsing the header.");
    data->needed = SPDY_HEADERS_MIN_LENGTH - length;
    return SPDY_ERROR_INSUFFICIENT_DATA;
  }

  headers->stream_id = BE_LOAD_32(data->cursor) & 0x7FFFFFFF;
  data->cursor += 4;

  return SPDY_ERROR_NONE;
}
Пример #7
0
/**
 * Pack a Name/Value block into a payload for transmitting.
 *
 * Note that this function returns an allocated string in 'dest'.
 *
 * @param dest - Destination buffer.
 * @param dest_size - Pointer for storing the size of the destination buffer.
 * @param nv_block - NV block to pack.
 * @see spdy_nv_block
 * @see spdy_nv_block_parse
 * @todo Multiple value support.
 * @return 0 on success, -1 on failure.
 */
int spdy_nv_block_pack(char **dest, size_t *dest_size, spdy_nv_block *nv_block)
{
  int i;
  char *cursor;

  *dest = NULL;
  /* Two bytes for the number of pairs. */
  *dest_size = 2;
  /* Calculate the size needed for the ouput buffer. */
  for(i = 0; i < nv_block->count; i++) {
    /* Two bytes (length) + stringlength */
    *dest_size += 2 + strlen(nv_block->pairs[i].name);
    *dest_size += 2 + strlen(nv_block->pairs[i].values);
  }

  /* Allocate memory for dest */
  *dest = malloc(*dest_size);
  if(!*dest) {
    SPDYDEBUG("Memoy allocation failed.");
    return SPDY_ERROR_MALLOC_FAILED;
  }
  /* Cursor always points to the location in dest where we're working. */
  cursor = *dest;

  /* 2-bytes for the number of NV-pairs that follow. */
  BE_STORE_16(cursor, nv_block->count);
  cursor += 2;

  for(i = 0; i < nv_block->count; i++) {
    uint16_t length;

    /* Read the length and copy the data of each name/value into the
     * destination buffer. */
    length = strlen(nv_block->pairs[i].name);
    BE_STORE_16(cursor, length);
    memcpy(cursor + 2, nv_block->pairs[i].name, length);
    cursor += length + 2;
    length = strlen(nv_block->pairs[i].values);
    BE_STORE_16(cursor, length);
    memcpy(cursor + 2, nv_block->pairs[i].values, length);
    cursor += length + 2;
  }
  return SPDY_ERROR_NONE;
}
Пример #8
0
/**
 * Parse the header of a SYN_STREAM control frame.
 * This function can be used to parse the header of a SYN_STREAM frame
 * before the whole NV block has been received. (Minimum of bytes needed
 * is stored in SPDY_SYN_STREAM_HEADER_MIN_LENGTH.)
 * @param syn_stream - Destination frame.
 * @param data - Data to parse.
 * @see SPDY_SYN_STREAM_HEADER_MIN_LENGTH
 * @return Errorcode
 */
int spdy_syn_stream_parse_header(spdy_syn_stream *syn_stream, spdy_data *data)
{
  size_t length = data->data_end - data->cursor;
  if(length < SPDY_SYN_STREAM_HEADER_MIN_LENGTH) {
    SPDYDEBUG("Not enough data for parsing the header.");
    data->needed = SPDY_SYN_STREAM_HEADER_MIN_LENGTH - length;
    return SPDY_ERROR_INSUFFICIENT_DATA;
  }

  /* Read the Stream-ID. */
  syn_stream->stream_id = BE_LOAD_32(data->cursor) & 0x7FFFFFFF;
  data->cursor += 4;
  /* Read the 'Associated-To-Stream-ID'. */
  syn_stream->associated_to = BE_LOAD_32(data->cursor) & 0x7FFFFFFF;
  data->cursor += 4;
  /* Read the two priority bits. */
  syn_stream->priority = (data->cursor[0] & 0xC0) >> 6;
  /* Skip the unused block. */
  data->cursor += 2;

  return SPDY_ERROR_NONE;
}
Пример #9
0
/**
 * Parse the header of a data frame. This needs 'stream_id' to be cleared to
 * consider this as the first call.
 *
 * @param frame - Target data frame.
 * @param data - Data to parse.
 * @see spdy_data_frame
 * @return Errorcode
 */
int spdy_data_frame_parse_header(spdy_data_frame *frame, spdy_data *data)
{

  /* Check if the frame header has already been parsed. */
  if(!frame->stream_id) {
    size_t length = data->data_end - data->cursor;
    if(length < SPDY_DATA_FRAME_MIN_LENGTH) {
      SPDYDEBUG("Insufficient data for data frame.");
      data->needed = SPDY_DATA_FRAME_MIN_LENGTH - length;
      return SPDY_ERROR_INSUFFICIENT_DATA;
    }

    /* Read stream id. (AND removes the first type bit.) */
    frame->stream_id = BE_LOAD_32(data->cursor) & 0x7FFFFFFF;
    data->cursor += 4;
    frame->flags = data->cursor[0];
    frame->length = BE_LOAD_32(data->cursor) & 0x00FFFFFF;
    data->cursor += 4;
    frame->data = NULL;         /* no frame payload yet */
  }
  return SPDY_ERROR_NONE;
}
Пример #10
0
/**
 * Parse a Name/Value block payload.
 * @param block - Target block.
 * @param data - Data to parse.
 * @param data_length - Length of data.
 * @see spdy_nv_block
 * @todo Replace mallocs with a single one. (Speed up!)
 * @todo Freeing in the loop.
 * @todo Multiple value support.
 * @return Errorcode
 */
int spdy_nv_block_parse(spdy_nv_block *block, unsigned char *data,
                        size_t data_length)
{
  /* The bounds of data. */
  unsigned char *data_max = data + data_length;

  /* For the for-loop: */

  /* Parsing block pair count */
  if(!block->has_count) {
    /* Data must at least contain the number of NV pairs. */
    if(data_length < 2) {
      SPDYDEBUG("Data to small.");
      return SPDY_ERROR_INSUFFICIENT_DATA;
    }

    /* Read the 16 bit integer containing the number of name/value pairs. */
    block->count = BE_LOAD_16(data);
    block->has_count = 1;
    block->pairs_parsed = 0;
    /* Move forward by two bytes. */
    data += 2;
    if(block->count == 0) {
      block->pairs = NULL;
      return SPDY_ERROR_NONE;
    }

    /* Allocate memory for Name/Value pairs. */
    block->pairs = calloc(block->count, sizeof(spdy_nv_pair));
    /* Malloc failed */
    if(!block->pairs) {
      SPDYDEBUG("Malloc of pairs failed.");
      return SPDY_ERROR_MALLOC_FAILED;
    }
  }
  /* End of parsing block pair count */


  /* Loop through all pairs */
  for(; block->pairs_parsed < block->count; block->pairs_parsed++) {
    size_t size;
    spdy_nv_pair *pair;
    uint16_t tmp_item_length;

    if(data + 2 > data_max) {
      SPDYDEBUG("Data to small.");
      return SPDY_ERROR_INSUFFICIENT_DATA;
    }

    pair = &block->pairs[block->pairs_parsed];

    /* Read Name */
    /* Read length of name */
    tmp_item_length = BE_LOAD_16(data);
    data += 2;
    /* Allocate space for name */
    size = tmp_item_length + 1;
    if(data + tmp_item_length > data_max) {
      SPDYDEBUG("Data to small.");
      return SPDY_ERROR_INSUFFICIENT_DATA;
    }

    pair->name = malloc(size);
    if(!pair->name) {
      SPDYDEBUG("Pair name malloc failed.");
      return SPDY_ERROR_MALLOC_FAILED;
    }
    memcpy(pair->name, data, tmp_item_length);
    pair->name[tmp_item_length] = '\0';
    data += tmp_item_length;
    /* End of read name */

    /* Read Values */
    /* TODO: Support multiple values. */
    /* Read length of value */
    if(data + 2 > data_max) {
      SPDYDEBUG("Data to small.");
      free(pair->name);
      return SPDY_ERROR_INSUFFICIENT_DATA;
    }
    tmp_item_length = BE_LOAD_16(data);
    data += 2;
    /* Allocate space for values */
    size = tmp_item_length + 1;
    if(data + tmp_item_length > data_max) {
      SPDYDEBUG("Insufficient data for block parse.");
      free(pair->name);
      return SPDY_ERROR_INSUFFICIENT_DATA;
    }
    pair->values = malloc(size);
    if(!pair->values) {
      SPDYDEBUG("Pair value malloc failed.");
      free(pair->name);
      return SPDY_ERROR_MALLOC_FAILED;
    }
    memcpy(pair->values, data, tmp_item_length);
    pair->values[tmp_item_length] = '\0';
    data += tmp_item_length;
    /* End of read value */
  }

  return SPDY_ERROR_NONE;
}