示例#1
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;
  }

}
示例#2
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;
}
示例#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;
}
示例#4
0
static amqp_bytes_t sasl_response(amqp_pool_t *pool,
				  amqp_sasl_method_enum method,
				  va_list args)
{
  amqp_bytes_t response;

  switch (method) {
    case AMQP_SASL_METHOD_PLAIN: {
      char *username = va_arg(args, char *);
      size_t username_len = strlen(username);
      char *password = va_arg(args, char *);
      size_t password_len = strlen(password);
      char *response_buf;

      amqp_pool_alloc_bytes(pool, strlen(username) + strlen(password) + 2, &response);
      if (response.bytes == NULL)
	/* We never request a zero-length block, because of the +2
	   above, so a NULL here really is ENOMEM. */
	return response;

      response_buf = response.bytes;
      response_buf[0] = 0;
      memcpy(response_buf + 1, username, username_len);
      response_buf[username_len + 1] = 0;
      memcpy(response_buf + username_len + 2, password, password_len);
      break;
    }
    default:
      amqp_abort("Invalid SASL method: %d", (int) method);
  }

  return response;
}
示例#5
0
static amqp_bytes_t sasl_method_name(amqp_sasl_method_enum method) {
  switch (method) {
    case AMQP_SASL_METHOD_PLAIN: return (amqp_bytes_t) {.len = 5, .bytes = "PLAIN"};
    default:
      amqp_assert(0, "Invalid SASL method: %d", (int) method);
  }
  abort(); /* unreachable */
}

static amqp_bytes_t sasl_response(amqp_pool_t *pool,
				  amqp_sasl_method_enum method,
				  va_list args)
{
  amqp_bytes_t response;

  switch (method) {
    case AMQP_SASL_METHOD_PLAIN: {
      char *username = va_arg(args, char *);
      size_t username_len = strlen(username);
      char *password = va_arg(args, char *);
      size_t password_len = strlen(password);
      amqp_pool_alloc_bytes(pool, strlen(username) + strlen(password) + 2, &response);
      *BUF_AT(response, 0) = 0;
      memcpy(((char *) response.bytes) + 1, username, username_len);
      *BUF_AT(response, username_len + 1) = 0;
      memcpy(((char *) response.bytes) + username_len + 2, password, password_len);
      break;
    }
    default:
      amqp_assert(0, "Invalid SASL method: %d", (int) method);
  }

  return response;
}
示例#6
0
amqp_field_value_t TableValueImpl::generate_field_value::operator()(const std::string &value) const
{
  amqp_field_value_t v;
  v.kind = AMQP_FIELD_KIND_UTF8;
  amqp_pool_alloc_bytes(&pool, value.size(), &v.value.bytes);
  memcpy(v.value.bytes.bytes, value.data(), v.value.bytes.len);
  return v;
}
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 AMQP_STATUS_OK;
  }

  if (state->state == CONNECTION_STATE_IDLE) {
    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: {
    amqp_channel_t channel;
    amqp_pool_t *channel_pool;
    /* frame length is 3 bytes in */
    channel = amqp_d16(raw_frame, 1);

    state->target_size
      = amqp_d32(raw_frame, 3) + HEADER_SIZE + FOOTER_SIZE;

    if ((size_t)state->frame_max < state->target_size) {
      return AMQP_STATUS_BAD_AMQP_DATA;
    }

    channel_pool = amqp_get_or_create_channel_pool(state, channel);
    if (NULL == channel_pool) {
      return AMQP_STATUS_NO_MEMORY;
    }

    amqp_pool_alloc_bytes(channel_pool, state->target_size, &state->inbound_buffer);
    if (NULL == state->inbound_buffer.bytes) {
      return AMQP_STATUS_NO_MEMORY;
    }
    memcpy(state->inbound_buffer.bytes, state->header_buffer, HEADER_SIZE);
    raw_frame = state->inbound_buffer.bytes;

    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;
    amqp_pool_t *channel_pool;

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

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

    channel_pool = amqp_get_or_create_channel_pool(state, decoded_frame->channel);
    if (NULL == channel_pool) {
      return AMQP_STATUS_NO_MEMORY;
    }

    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,
                               channel_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,
                                   channel_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;
  }
}