Exemplo n.º 1
0
amqp_table_t TableValueImpl::CopyTableInner(const amqp_table_t &table, amqp_pool_t &pool)
{
  amqp_table_t new_table;

  new_table.num_entries = table.num_entries;
  new_table.entries = (amqp_table_entry_t*)amqp_pool_alloc(&pool,
                                                           sizeof(amqp_table_entry_t)*table.num_entries);
  if (NULL == new_table.entries)
  {
    throw std::bad_alloc();
  }

  for (int i = 0; i < table.num_entries; ++i)
  {
    amqp_table_entry_t *entry = &new_table.entries[i];
    amqp_pool_alloc_bytes(&pool, table.entries[i].key.len, &entry->key);

    if (NULL == entry->key.bytes)
    {
      throw std::bad_alloc();
    }
    memcpy(entry->key.bytes, table.entries[i].key.bytes, entry->key.len);

    entry->value = CopyValue(table.entries[i].value, pool);
  }

  return new_table;
}
Exemplo n.º 2
0
amqp_field_value_t TableValueImpl::CopyValue(const amqp_field_value_t value, amqp_pool_t &pool)
{
  amqp_field_value_t new_value = value;

  switch (value.kind)
  {
    case AMQP_FIELD_KIND_UTF8:
    case AMQP_FIELD_KIND_BYTES:
      amqp_pool_alloc_bytes(&pool, value.value.bytes.len, &new_value.value.bytes);
      memcpy(new_value.value.bytes.bytes, value.value.bytes.bytes, value.value.bytes.len);
      return new_value;
    case AMQP_FIELD_KIND_ARRAY:
    {
      new_value.value.array.entries = (amqp_field_value_t*)amqp_pool_alloc(&pool,
                                                                           sizeof(amqp_field_value_t)*value.value.array.num_entries);
      for (int i = 0; i < value.value.array.num_entries; ++i)
      {
        new_value.value.array.entries[i] = CopyValue(value.value.array.entries[i], pool);
      }
      return new_value;
    }
    case AMQP_FIELD_KIND_TABLE:
      new_value.value.table = CopyTableInner(value.value.table, pool);
      return new_value;
    default:
      return new_value;
  }

}
Exemplo n.º 3
0
amqp_table_t TableValueImpl::CreateAmqpTableInner(const Table &table, amqp_pool_t &pool)
{
  amqp_table_t new_table;

  new_table.num_entries = table.size();

  new_table.entries = (amqp_table_entry_t*)amqp_pool_alloc(&pool, sizeof(amqp_table_entry_t)*table.size());

  if (NULL == new_table.entries)
  {
    throw std::bad_alloc();
  }

  amqp_table_entry_t *output_it = new_table.entries;

  for (Table::const_iterator it = table.begin();
       it != table.end();
       ++it, ++output_it)
  {
    amqp_pool_alloc_bytes(&pool, it->first.size(), &output_it->key);
    if (NULL == output_it->key.bytes)
    {
      throw std::bad_alloc();
    }

    std::copy(it->first.begin(), it->first.end(), (char *)output_it->key.bytes);

    output_it->value = boost::apply_visitor(TableValueImpl::generate_field_value(pool),
                                                  it->second.m_impl->m_value);
  }

  return new_table;
}
Exemplo n.º 4
0
void amqp_create_table(amqp_connection_state_t state,
                       amqp_table_t *output,
                       int initialSize) {

  output->entries = amqp_pool_alloc(&state->frame_pool, initialSize * sizeof(amqp_table_entry_t));
  output->size = initialSize;
  output->num_entries = 0;
}
Exemplo n.º 5
0
amqp_table_entry_t *amqp_table_add_entry( amqp_connection_state_t state,
		amqp_table_t *table,
		amqp_bytes_t key)
{
	amqp_table_entry_t *entry;

    if (table->num_entries == table->size)
	{
		int new_size = table->size * 2;
		amqp_table_entry_t *new_entries = amqp_pool_alloc( &state->frame_pool, new_size * sizeof(amqp_table_entry_t) );
		memcpy( new_entries, table->entries, table->size * sizeof(amqp_table_entry_t) );
		table->size = new_size;
		table->entries = new_entries;
	}

	entry = &table->entries[table->num_entries];
	table->num_entries++;
	entry->key = key;
	return entry;
}
Exemplo n.º 6
0
amqp_field_value_t TableValueImpl::generate_field_value::operator()(const array_t &value) const
{
  amqp_field_value_t v;
  v.kind = AMQP_FIELD_KIND_ARRAY;
  v.value.array.num_entries = value.size();
  v.value.array.entries = (amqp_field_value_t*)amqp_pool_alloc(&pool,
                                                               sizeof(amqp_field_value_t)*value.size());
  if (NULL == v.value.array.entries)
  {
    throw std::bad_alloc();
  }
  
  amqp_field_value_t *output_iterator = v.value.array.entries;
  for (array_t::const_iterator it = value.begin();
       it != value.end(); ++it, ++output_iterator)
  {
    *output_iterator = boost::apply_visitor(generate_field_value(pool),
                                            it->m_impl->m_value);
  }
  return v;
}
Exemplo n.º 7
0
amqp_connection_state_t amqp_new_connection(void) {
  amqp_connection_state_t state =
    (amqp_connection_state_t) calloc(1, sizeof(struct amqp_connection_state_t_));

  if (state == NULL)
    return NULL;

  init_amqp_pool(&state->frame_pool, INITIAL_FRAME_POOL_PAGE_SIZE);
  init_amqp_pool(&state->decoding_pool, INITIAL_DECODING_POOL_PAGE_SIZE);

  if (amqp_tune_connection(state, 0, INITIAL_FRAME_POOL_PAGE_SIZE, 0) != 0)
    goto out_nomem;

  state->inbound_buffer.bytes = amqp_pool_alloc(&state->frame_pool, state->inbound_buffer.len);
  if (state->inbound_buffer.bytes == NULL)
    goto out_nomem;

  state->state = CONNECTION_STATE_INITIAL;
  /* the server protocol version response is 8 bytes, which conveniently
     is also the minimum frame size */
  state->target_size = 8;

  state->sockfd = -1;
  state->sock_inbound_buffer.len = INITIAL_INBOUND_SOCK_BUFFER_SIZE;
  state->sock_inbound_buffer.bytes = malloc(INITIAL_INBOUND_SOCK_BUFFER_SIZE);
  if (state->sock_inbound_buffer.bytes == NULL)
    goto out_nomem;

  return state;

 out_nomem:
  free(state->sock_inbound_buffer.bytes);
  empty_amqp_pool(&state->frame_pool);
  empty_amqp_pool(&state->decoding_pool);
  free(state);
  return NULL;
}
Exemplo n.º 8
0
void amqp_pool_alloc_bytes(amqp_pool_t *pool, size_t amount, amqp_bytes_t *output) {
  output->len = amount;
  output->bytes = amqp_pool_alloc(pool, amount);
}
Exemplo n.º 9
0
amqp_rpc_reply_t amqp_simple_rpc(amqp_connection_state_t state,
                                 amqp_channel_t channel,
                                 amqp_method_number_t request_id,
                                 amqp_method_number_t *expected_reply_ids,
                                 void *decoded_request_method)
{
    int status;
    amqp_rpc_reply_t result;

    memset(&result, 0, sizeof(result));

    status = amqp_send_method(state, channel, request_id, decoded_request_method);
    if (status < 0) {
        result.reply_type = AMQP_RESPONSE_LIBRARY_EXCEPTION;
        result.library_errno = -status;
        return result;
    }

    {
        amqp_frame_t frame;

retry:
        status = wait_frame_inner(state, &frame);
        if (status <= 0) {
            result.reply_type = AMQP_RESPONSE_LIBRARY_EXCEPTION;
            result.library_errno = -status;
            return result;
        }

        /*
         * We store the frame for later processing unless it's something
         * that directly affects us here, namely a method frame that is
         * either
         *  - on the channel we want, and of the expected type, or
         *  - on the channel we want, and a channel.close frame, or
         *  - on channel zero, and a connection.close frame.
         */
        if (!( (frame.frame_type == AMQP_FRAME_METHOD) &&
                (   ((frame.channel == channel) &&
                     ((amqp_id_in_reply_list(frame.payload.method.id, expected_reply_ids)) ||
                      (frame.payload.method.id == AMQP_CHANNEL_CLOSE_METHOD)))
                    ||
                    ((frame.channel == 0) &&
                     (frame.payload.method.id == AMQP_CONNECTION_CLOSE_METHOD))   ) ))
        {
            amqp_frame_t *frame_copy = amqp_pool_alloc(&state->decoding_pool, sizeof(amqp_frame_t));
            amqp_link_t *link = amqp_pool_alloc(&state->decoding_pool, sizeof(amqp_link_t));

            *frame_copy = frame;

            link->next = NULL;
            link->data = frame_copy;

            if (state->last_queued_frame == NULL) {
                state->first_queued_frame = link;
            } else {
                state->last_queued_frame->next = link;
            }
            state->last_queued_frame = link;

            goto retry;
        }

        result.reply_type = (amqp_id_in_reply_list(frame.payload.method.id, expected_reply_ids))
                            ? AMQP_RESPONSE_NORMAL
                            : AMQP_RESPONSE_SERVER_EXCEPTION;

        result.reply = frame.payload.method;
        return result;
    }
}
Exemplo n.º 10
0
int amqp_decode_table(amqp_bytes_t encoded,
		      amqp_pool_t *pool,
		      amqp_table_t *output,
		      int *offsetptr)
{
  int offset = *offsetptr;
  uint32_t tablesize = D_32(encoded, offset);
  int num_entries = 0;
  amqp_table_entry_t *entries = malloc(INITIAL_TABLE_SIZE * sizeof(amqp_table_entry_t));
  int allocated_entries = INITIAL_TABLE_SIZE;
  int limit;

  if (entries == NULL) {
    return -ENOMEM;
  }

  offset += 4;
  limit = offset + tablesize;

  while (offset < limit) {
    size_t keylen;
    amqp_table_entry_t *entry;

    keylen = D_8(encoded, offset);
    offset++;

    if (num_entries >= allocated_entries) {
      void *newentries;
      allocated_entries = allocated_entries * 2;
      newentries = realloc(entries, allocated_entries * sizeof(amqp_table_entry_t));
      if (newentries == NULL) {
	free(entries);
	return -ENOMEM;
      }
      entries = newentries;
    }
    entry = &entries[num_entries];

    entry->key.len = keylen;
    entry->key.bytes = D_BYTES(encoded, offset, keylen);
    offset += keylen;

    entry->kind = D_8(encoded, offset);
    offset++;

    switch (entry->kind) {
      case 'S':
	entry->value.bytes.len = D_32(encoded, offset);
	offset += 4;
	entry->value.bytes.bytes = D_BYTES(encoded, offset, entry->value.bytes.len);
	offset += entry->value.bytes.len;
	break;
      case 'I':
	entry->value.i32 = (int32_t) D_32(encoded, offset);
	offset += 4;
	break;
      case 'D':
	entry->value.decimal.decimals = D_8(encoded, offset);
	offset++;
	entry->value.decimal.value = D_32(encoded, offset);
	offset += 4;
	break;
      case 'T':
	entry->value.u64 = D_64(encoded, offset);
	offset += 8;
	break;
      case 'F':
	AMQP_CHECK_RESULT(amqp_decode_table(encoded, pool, &(entry->value.table), &offset));
	break;
      case 't':
	entry->value.boolean = D_8(encoded, offset);
	offset += 1;
	break;
      default:
	return -EINVAL;
    }

    num_entries++;
  }

  output->num_entries = num_entries;
  output->entries = amqp_pool_alloc(pool, num_entries * sizeof(amqp_table_entry_t));
  output->size = num_entries;
  memcpy(output->entries, entries, num_entries * sizeof(amqp_table_entry_t));

  *offsetptr = offset;
  return 0;
}
Exemplo n.º 11
0
int amqp_handle_input(amqp_connection_state_t state,
		      amqp_bytes_t received_data,
		      amqp_frame_t *decoded_frame)
{
  int total_bytes_consumed = 0;
  int bytes_consumed;

  /* Returning frame_type of zero indicates either insufficient input,
     or a complete, ignored frame was read. */
  decoded_frame->frame_type = 0;

 read_more:
  if (received_data.len == 0) {
    return total_bytes_consumed;
  }

  if (state->state == CONNECTION_STATE_IDLE) {
    state->inbound_buffer.bytes = amqp_pool_alloc(&state->frame_pool, state->inbound_buffer.len);
    if (state->inbound_buffer.bytes == NULL) {
      /* state->inbound_buffer.len is always nonzero, because it
	 corresponds to frame_max, which is not permitted to be less
	 than AMQP_FRAME_MIN_SIZE (currently 4096 bytes). */
      return -ENOMEM;
    }
    state->state = CONNECTION_STATE_WAITING_FOR_HEADER;
  }

  bytes_consumed = state->target_size - state->inbound_offset;
  if (received_data.len < bytes_consumed) {
    bytes_consumed = received_data.len;
  }

  E_BYTES(state->inbound_buffer, state->inbound_offset, bytes_consumed, received_data.bytes);
  state->inbound_offset += bytes_consumed;
  total_bytes_consumed += bytes_consumed;

  assert(state->inbound_offset <= state->target_size);

  if (state->inbound_offset < state->target_size) {
    return total_bytes_consumed;
  }

  switch (state->state) {
    case CONNECTION_STATE_WAITING_FOR_HEADER:
      if (D_8(state->inbound_buffer, 0) == AMQP_PSEUDOFRAME_PROTOCOL_HEADER &&
	  D_16(state->inbound_buffer, 1) == AMQP_PSEUDOFRAME_PROTOCOL_CHANNEL)
      {
	state->target_size = 8;
	state->state = CONNECTION_STATE_WAITING_FOR_PROTOCOL_HEADER;
      } else {
	state->target_size = D_32(state->inbound_buffer, 3) + HEADER_SIZE + FOOTER_SIZE;
	state->state = CONNECTION_STATE_WAITING_FOR_BODY;
      }

      /* Wind buffer forward, and try to read some body out of it. */
      received_data.len -= bytes_consumed;
      received_data.bytes = ((char *) received_data.bytes) + bytes_consumed;
      goto read_more;

    case CONNECTION_STATE_WAITING_FOR_BODY: {
      int frame_type = D_8(state->inbound_buffer, 0);

#if 0
      printf("recving:\n");
      amqp_dump(state->inbound_buffer.bytes, state->target_size);
#endif

      /* Check frame end marker (footer) */
      if (D_8(state->inbound_buffer, state->target_size - 1) != AMQP_FRAME_END) {
	return -EINVAL;
      }

      decoded_frame->channel = D_16(state->inbound_buffer, 1);

      switch (frame_type) {
	case AMQP_FRAME_METHOD: {
	  amqp_bytes_t encoded;

	  /* Four bytes of method ID before the method args. */
	  encoded.len = state->target_size - (HEADER_SIZE + 4 + FOOTER_SIZE);
	  encoded.bytes = D_BYTES(state->inbound_buffer, HEADER_SIZE + 4, encoded.len);

	  decoded_frame->frame_type = AMQP_FRAME_METHOD;
	  decoded_frame->payload.method.id = D_32(state->inbound_buffer, HEADER_SIZE);
	  AMQP_CHECK_RESULT(amqp_decode_method(decoded_frame->payload.method.id,
					       &state->decoding_pool,
					       encoded,
					       &decoded_frame->payload.method.decoded));
	  break;
	}

	case AMQP_FRAME_HEADER: {
	  amqp_bytes_t encoded;

	  /* 12 bytes for properties header. */
	  encoded.len = state->target_size - (HEADER_SIZE + 12 + FOOTER_SIZE);
	  encoded.bytes = D_BYTES(state->inbound_buffer, HEADER_SIZE + 12, encoded.len);

	  decoded_frame->frame_type = AMQP_FRAME_HEADER;
	  decoded_frame->payload.properties.class_id = D_16(state->inbound_buffer, HEADER_SIZE);
	  decoded_frame->payload.properties.body_size = D_64(state->inbound_buffer, HEADER_SIZE+4);
	  decoded_frame->payload.properties.raw = encoded;
	  AMQP_CHECK_RESULT(amqp_decode_properties(decoded_frame->payload.properties.class_id,
						   &state->decoding_pool,
						   encoded,
						   &decoded_frame->payload.properties.decoded));
	  break;
	}

	case AMQP_FRAME_BODY: {
	  size_t fragment_len = state->target_size - (HEADER_SIZE + FOOTER_SIZE);

	  decoded_frame->frame_type = AMQP_FRAME_BODY;
	  decoded_frame->payload.body_fragment.len = fragment_len;
	  decoded_frame->payload.body_fragment.bytes =
	    D_BYTES(state->inbound_buffer, HEADER_SIZE, fragment_len);
	  break;
	}

	case AMQP_FRAME_HEARTBEAT:
	  decoded_frame->frame_type = AMQP_FRAME_HEARTBEAT;
	  break;

	default:
	  /* Ignore the frame by not changing frame_type away from 0. */
	  break;
      }

      return_to_idle(state);
      return total_bytes_consumed;
    }

    case CONNECTION_STATE_WAITING_FOR_PROTOCOL_HEADER:
      decoded_frame->frame_type = AMQP_PSEUDOFRAME_PROTOCOL_HEADER;
      decoded_frame->channel = AMQP_PSEUDOFRAME_PROTOCOL_CHANNEL;
      amqp_assert(D_8(state->inbound_buffer, 3) == (uint8_t) 'P',
		  "Invalid protocol header received");
      decoded_frame->payload.protocol_header.transport_high = D_8(state->inbound_buffer, 4);
      decoded_frame->payload.protocol_header.transport_low = D_8(state->inbound_buffer, 5);
      decoded_frame->payload.protocol_header.protocol_version_major = D_8(state->inbound_buffer, 6);
      decoded_frame->payload.protocol_header.protocol_version_minor = D_8(state->inbound_buffer, 7);

      return_to_idle(state);
      return total_bytes_consumed;

    default:
      amqp_assert(0, "Internal error: invalid amqp_connection_state_t->state %d", state->state);
  }
}
Exemplo n.º 12
0
int amqp_handle_input(amqp_connection_state_t state,
		      amqp_bytes_t received_data,
		      amqp_frame_t *decoded_frame)
{
  size_t bytes_consumed;
  void *raw_frame;

  /* Returning frame_type of zero indicates either insufficient input,
     or a complete, ignored frame was read. */
  decoded_frame->frame_type = 0;

  if (received_data.len == 0)
    return 0;

  if (state->state == CONNECTION_STATE_IDLE) {
    state->inbound_buffer.bytes = amqp_pool_alloc(&state->frame_pool,
						  state->inbound_buffer.len);
    if (state->inbound_buffer.bytes == NULL)
      /* state->inbound_buffer.len is always nonzero, because it
	 corresponds to frame_max, which is not permitted to be less
	 than AMQP_FRAME_MIN_SIZE (currently 4096 bytes). */
      return -ERROR_NO_MEMORY;

    state->state = CONNECTION_STATE_HEADER;
  }

  bytes_consumed = consume_data(state, &received_data);

  /* do we have target_size data yet? if not, return with the
     expectation that more will arrive */
  if (state->inbound_offset < state->target_size)
    return bytes_consumed;

  raw_frame = state->inbound_buffer.bytes;

  switch (state->state) {
  case CONNECTION_STATE_INITIAL:
    /* check for a protocol header from the server */
    if (memcmp(raw_frame, "AMQP", 4) == 0) {
      decoded_frame->frame_type = AMQP_PSEUDOFRAME_PROTOCOL_HEADER;
      decoded_frame->channel = 0;

      decoded_frame->payload.protocol_header.transport_high
                                        = amqp_d8(raw_frame, 4);
      decoded_frame->payload.protocol_header.transport_low
                                        = amqp_d8(raw_frame, 5);
      decoded_frame->payload.protocol_header.protocol_version_major
                                        = amqp_d8(raw_frame, 6);
      decoded_frame->payload.protocol_header.protocol_version_minor
                                        = amqp_d8(raw_frame, 7);

      return_to_idle(state);
      return bytes_consumed;
    }

    /* it's not a protocol header; fall through to process it as a
       regular frame header */

  case CONNECTION_STATE_HEADER:
    /* frame length is 3 bytes in */
    state->target_size
           = amqp_d32(raw_frame, 3) + HEADER_SIZE + FOOTER_SIZE;
    state->state = CONNECTION_STATE_BODY;

    bytes_consumed += consume_data(state, &received_data);

    /* do we have target_size data yet? if not, return with the
       expectation that more will arrive */
    if (state->inbound_offset < state->target_size)
      return bytes_consumed;

    /* fall through to process body */

  case CONNECTION_STATE_BODY: {
    amqp_bytes_t encoded;
    int res;

    /* Check frame end marker (footer) */
    if (amqp_d8(raw_frame, state->target_size - 1) != AMQP_FRAME_END)
      return -ERROR_BAD_AMQP_DATA;

    decoded_frame->frame_type = amqp_d8(raw_frame, 0);
    decoded_frame->channel = amqp_d16(raw_frame, 1);

    switch (decoded_frame->frame_type) {
    case AMQP_FRAME_METHOD:
      decoded_frame->payload.method.id = amqp_d32(raw_frame, HEADER_SIZE);
      encoded.bytes = amqp_offset(raw_frame, HEADER_SIZE + 4);
      encoded.len = state->target_size - HEADER_SIZE - 4 - FOOTER_SIZE;

      res = amqp_decode_method(decoded_frame->payload.method.id,
			       &state->decoding_pool, encoded,
			       &decoded_frame->payload.method.decoded);
      if (res < 0)
	return res;

      break;

    case AMQP_FRAME_HEADER:
      decoded_frame->payload.properties.class_id
                                          = amqp_d16(raw_frame, HEADER_SIZE);
      /* unused 2-byte weight field goes here */
      decoded_frame->payload.properties.body_size
                                      = amqp_d64(raw_frame, HEADER_SIZE + 4);
      encoded.bytes = amqp_offset(raw_frame, HEADER_SIZE + 12);
      encoded.len = state->target_size - HEADER_SIZE - 12 - FOOTER_SIZE;
      decoded_frame->payload.properties.raw = encoded;

      res = amqp_decode_properties(decoded_frame->payload.properties.class_id,
                                   &state->decoding_pool, encoded,
                                   &decoded_frame->payload.properties.decoded);
      if (res < 0)
        return res;

      break;

    case AMQP_FRAME_BODY:
      decoded_frame->payload.body_fragment.len
                            = state->target_size - HEADER_SIZE - FOOTER_SIZE;
      decoded_frame->payload.body_fragment.bytes
                                       = amqp_offset(raw_frame, HEADER_SIZE);
      break;

    case AMQP_FRAME_HEARTBEAT:
      break;

    default:
      /* Ignore the frame */
      decoded_frame->frame_type = 0;
      break;
    }

    return_to_idle(state);
    return bytes_consumed;
  }

  default:
    amqp_abort("Internal error: invalid amqp_connection_state_t->state %d", state->state);
    return bytes_consumed;
  }
}