Exemplo n.º 1
0
int amqp_basic_publish(amqp_connection_state_t state,
		       amqp_channel_t channel,
		       amqp_bytes_t exchange,
		       amqp_bytes_t routing_key,
		       amqp_boolean_t mandatory,
		       amqp_boolean_t immediate,
		       amqp_basic_properties_t const *properties,
		       amqp_bytes_t body)
{
  amqp_frame_t f;
  size_t body_offset;
  size_t usable_body_payload_size = state->frame_max - (HEADER_SIZE + FOOTER_SIZE);

  amqp_basic_publish_t m =
    (amqp_basic_publish_t) {
      .exchange = exchange,
      .routing_key = routing_key,
      .mandatory = mandatory,
      .immediate = immediate
    };

  amqp_basic_properties_t default_properties;

  AMQP_CHECK_RESULT(amqp_send_method(state, channel, AMQP_BASIC_PUBLISH_METHOD, &m));

  if (properties == NULL) {
    memset(&default_properties, 0, sizeof(default_properties));
    properties = &default_properties;
  }

  f.frame_type = AMQP_FRAME_HEADER;
  f.channel = channel;
  f.payload.properties.class_id = AMQP_BASIC_CLASS;
  f.payload.properties.body_size = body.len;
  f.payload.properties.decoded = (void *) properties;
  AMQP_CHECK_RESULT(amqp_send_frame(state, &f));

  body_offset = 0;
  while (1) {
    int remaining = body.len - body_offset;
    assert(remaining >= 0);

    if (remaining == 0)
      break;

    f.frame_type = AMQP_FRAME_BODY;
    f.channel = channel;
    f.payload.body_fragment.bytes = BUF_AT(body, body_offset);
    if (remaining >= usable_body_payload_size) {
      f.payload.body_fragment.len = usable_body_payload_size;
    } else {
      f.payload.body_fragment.len = remaining;
    }

    body_offset += f.payload.body_fragment.len;
    AMQP_CHECK_RESULT(amqp_send_frame(state, &f));
  }

  return 0;
}
Exemplo n.º 2
0
int amqp_basic_reject(amqp_connection_state_t state,
                      amqp_channel_t channel,
                      uint64_t delivery_tag,
                      amqp_boolean_t requeue)
{
  amqp_basic_reject_t req;
  req.delivery_tag = delivery_tag;
  req.requeue = requeue;
  return amqp_send_method(state, channel, AMQP_BASIC_REJECT_METHOD, &req);
}
Exemplo n.º 3
0
int amqp_basic_ack(amqp_connection_state_t state,
                   amqp_channel_t channel,
                   uint64_t delivery_tag,
                   amqp_boolean_t multiple)
{
  amqp_basic_ack_t m;
  m.delivery_tag = delivery_tag;
  m.multiple = multiple;
  return amqp_send_method(state, channel, AMQP_BASIC_ACK_METHOD, &m);
}
Exemplo n.º 4
0
static int amqp_login_inner(amqp_connection_state_t state,
                            int channel_max,
                            int frame_max,
                            int heartbeat,
                            amqp_sasl_method_enum sasl_method,
                            va_list vl)
{
    struct timeval hb;
    amqp_method_t method;
    uint32_t server_frame_max;
    uint16_t server_channel_max;
    uint16_t server_heartbeat;

    if(heartbeat != 0) {
        hb.tv_sec = 2*heartbeat;
        hb.tv_usec = 0;
        (void)setsockopt(state->sockfd, SOL_SOCKET, SO_RCVTIMEO, &hb, sizeof(hb));
        (void)setsockopt(state->sockfd, SOL_SOCKET, SO_SNDTIMEO, &hb, sizeof(hb));
    }

    amqp_send_header(state);

    (void)AMQP_CHECK_EOF_RESULT(amqp_simple_wait_method(state, 0, AMQP_CONNECTION_START_METHOD, &method));
    {
        amqp_connection_start_t *s = (amqp_connection_start_t *) method.decoded;
        if ((s->version_major != AMQP_PROTOCOL_VERSION_MAJOR) ||
                (s->version_minor != AMQP_PROTOCOL_VERSION_MINOR)) {
            return -EPROTOTYPE;
        }

        /* TODO: check that our chosen SASL mechanism is in the list of
           acceptable mechanisms. Or even let the application choose from
           the list! */
    }

    {
        amqp_bytes_t response_bytes = sasl_response(&state->decoding_pool, sasl_method, vl);
        amqp_connection_start_ok_t s =
        (amqp_connection_start_ok_t) {
            .client_properties = {.num_entries = 0, .entries = NULL},
             .mechanism = sasl_method_name(sasl_method),
              .response = response_bytes,
               .locale = {.len = 5, .bytes = "en_US"}
        };
        (void)AMQP_CHECK_RESULT(amqp_send_method(state, 0, AMQP_CONNECTION_START_OK_METHOD, &s));
    }
Exemplo n.º 5
0
void Channel::BasicReject(const Envelope::DeliveryInfo &info, bool requeue, bool multiple)
{
    m_impl->CheckIsConnected();
    // Delivery tag is local to the channel, so its important to use
    // that channel, sadly this can cause the channel to throw an exception
    // which will show up as an unrelated exception in a different method
    // that actually waits for a response from the broker
    amqp_channel_t channel = info.delivery_channel;
    if (!m_impl->IsChannelOpen(channel))
    {
        throw std::runtime_error("The channel that the message was delivered on has been closed");
    }
    amqp_basic_nack_t req;
    req.delivery_tag = info.delivery_tag;
    req.multiple = multiple;
    req.requeue = requeue;

    m_impl->CheckForError(amqp_send_method(m_impl->m_connection, channel, AMQP_BASIC_NACK_METHOD, &req));
}
Exemplo n.º 6
0
/**
 * Internal function used to initialize the connection to 
 * the RabbitMQ server. Also used to reconnect to the server
 * in case the connection fails and to redeclare exchanges
 * and queues if they are lost
 * 
 */
static int 
init_conn(MQ_INSTANCE *my_instance)
{ 
  int rval = 0;
  int amqp_ok = AMQP_STATUS_OK;

  if(my_instance->use_ssl){

    if((my_instance->sock = amqp_ssl_socket_new(my_instance->conn)) != NULL){

      if((amqp_ok = amqp_ssl_socket_set_cacert(my_instance->sock,my_instance->ssl_CA_cert)) != AMQP_STATUS_OK){
	skygw_log_write(LOGFILE_ERROR,
			"Error : Failed to set CA certificate: %s", amqp_error_string2(amqp_ok));
	goto cleanup;
      }
      if((amqp_ok = amqp_ssl_socket_set_key(my_instance->sock,
					    my_instance->ssl_client_cert,
					    my_instance->ssl_client_key)) != AMQP_STATUS_OK){
	skygw_log_write(LOGFILE_ERROR,
			"Error : Failed to set client certificate and key: %s", amqp_error_string2(amqp_ok));
	goto cleanup;
      }
    }else{

      amqp_ok = AMQP_STATUS_SSL_CONNECTION_FAILED;
      skygw_log_write(LOGFILE_ERROR,
		      "Error : SSL socket creation failed.");
      goto cleanup;
    }

    /**SSL is not used, falling back to TCP*/
  }else if((my_instance->sock = amqp_tcp_socket_new(my_instance->conn)) == NULL){
    skygw_log_write(LOGFILE_ERROR,
		    "Error : TCP socket creation failed.");
    goto cleanup;    

  }

  /**Socket creation was successful, trying to open the socket*/
  if((amqp_ok = amqp_socket_open(my_instance->sock,my_instance->hostname,my_instance->port)) != AMQP_STATUS_OK){
    skygw_log_write(LOGFILE_ERROR,
		    "Error : Failed to open socket: %s", amqp_error_string2(amqp_ok));
    goto cleanup;
  }
  amqp_rpc_reply_t reply;
  reply = amqp_login(my_instance->conn,my_instance->vhost,0,AMQP_DEFAULT_FRAME_SIZE,0,AMQP_SASL_METHOD_PLAIN,my_instance->username,my_instance->password);
  if(reply.reply_type != AMQP_RESPONSE_NORMAL){
    skygw_log_write(LOGFILE_ERROR,
		    "Error : Login to RabbitMQ server failed.");
    
    goto cleanup;
  }
  amqp_channel_open(my_instance->conn,my_instance->channel);
  reply = amqp_get_rpc_reply(my_instance->conn);  
  if(reply.reply_type != AMQP_RESPONSE_NORMAL){
    skygw_log_write(LOGFILE_ERROR,
		    "Error : Channel creation failed.");
    goto cleanup;
  }

  amqp_exchange_declare(my_instance->conn,my_instance->channel,
			amqp_cstring_bytes(my_instance->exchange),
			amqp_cstring_bytes(my_instance->exchange_type),
			0, 1,
			amqp_empty_table);

  reply = amqp_get_rpc_reply(my_instance->conn);  

  if(reply.reply_type != AMQP_RESPONSE_NORMAL){
    skygw_log_write(LOGFILE_ERROR,
		    "Error : Exchange declaration failed,trying to redeclare the exchange.");
    if(reply.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION){
      if(reply.reply.id == AMQP_CHANNEL_CLOSE_METHOD){
	amqp_send_method(my_instance->conn,my_instance->channel,AMQP_CHANNEL_CLOSE_OK_METHOD,NULL);
      }else if(reply.reply.id == AMQP_CONNECTION_CLOSE_METHOD){
	amqp_send_method(my_instance->conn,my_instance->channel,AMQP_CONNECTION_CLOSE_OK_METHOD,NULL);
      }
      
      my_instance->channel++;
      amqp_channel_open(my_instance->conn,my_instance->channel);
    
      amqp_exchange_delete(my_instance->conn,my_instance->channel,amqp_cstring_bytes(my_instance->exchange),0);
      amqp_exchange_declare(my_instance->conn,my_instance->channel,
			    amqp_cstring_bytes(my_instance->exchange),
			    amqp_cstring_bytes(my_instance->exchange_type),
			    0, 1,
			    amqp_empty_table);
      reply = amqp_get_rpc_reply(my_instance->conn);  
    }
    if(reply.reply_type != AMQP_RESPONSE_NORMAL){
      skygw_log_write(LOGFILE_ERROR,
		      "Error : Exchange redeclaration failed.");
      goto cleanup;
    }
  }

  if(my_instance->queue){

    

    amqp_queue_declare(my_instance->conn,my_instance->channel,
		       amqp_cstring_bytes(my_instance->queue),
		       0, 1, 0, 0,
		       amqp_empty_table);
    reply = amqp_get_rpc_reply(my_instance->conn);  
    if(reply.reply_type != AMQP_RESPONSE_NORMAL){
      skygw_log_write(LOGFILE_ERROR,
		      "Error : Queue declaration failed.");
      goto cleanup;
    }

 
    amqp_queue_bind(my_instance->conn,my_instance->channel,
		    amqp_cstring_bytes(my_instance->queue),
		    amqp_cstring_bytes(my_instance->exchange),
		    amqp_cstring_bytes(my_instance->key),
		    amqp_empty_table);
    reply = amqp_get_rpc_reply(my_instance->conn);  
    if(reply.reply_type != AMQP_RESPONSE_NORMAL){
      skygw_log_write(LOGFILE_ERROR,
		      "Error : Failed to bind queue to exchange.");
      goto cleanup;
    }
  }
  rval = 1;

 cleanup:

  return rval;
 
}
Exemplo n.º 7
0
int amqp_basic_publish(amqp_connection_state_t state,
                       amqp_channel_t channel,
                       amqp_bytes_t exchange,
                       amqp_bytes_t routing_key,
                       amqp_boolean_t mandatory,
                       amqp_boolean_t immediate,
                       amqp_basic_properties_t const *properties,
                       amqp_bytes_t body)
{
  amqp_frame_t f;
  size_t body_offset;
  size_t usable_body_payload_size = state->frame_max - (HEADER_SIZE + FOOTER_SIZE);
  int res;

  amqp_basic_publish_t m;
  amqp_basic_properties_t default_properties;

  m.exchange = exchange;
  m.routing_key = routing_key;
  m.mandatory = mandatory;
  m.immediate = immediate;
  m.ticket = 0;

  res = amqp_send_method(state, channel, AMQP_BASIC_PUBLISH_METHOD, &m);
  if (res < 0) {
    return res;
  }

  if (properties == NULL) {
    memset(&default_properties, 0, sizeof(default_properties));
    properties = &default_properties;
  }

  f.frame_type = AMQP_FRAME_HEADER;
  f.channel = channel;
  f.payload.properties.class_id = AMQP_BASIC_CLASS;
  f.payload.properties.body_size = body.len;
  f.payload.properties.decoded = (void *) properties;

  res = amqp_send_frame(state, &f);
  if (res < 0) {
    return res;
  }

  body_offset = 0;
  while (body_offset < body.len) {
    size_t remaining = body.len - body_offset;

    if (remaining == 0) {
      break;
    }

    f.frame_type = AMQP_FRAME_BODY;
    f.channel = channel;
    f.payload.body_fragment.bytes = amqp_offset(body.bytes, body_offset);
    if (remaining >= usable_body_payload_size) {
      f.payload.body_fragment.len = usable_body_payload_size;
    } else {
      f.payload.body_fragment.len = remaining;
    }

    body_offset += f.payload.body_fragment.len;
    res = amqp_send_frame(state, &f);
    if (res < 0) {
      return res;
    }
  }

  return 0;
}
Exemplo n.º 8
0
		    amqp_basic_consume_t,
		    0, queue, consumer_tag, no_local, no_ack, exclusive, 0);
  return RPC_REPLY(amqp_basic_consume_ok_t);
}

int amqp_basic_ack(amqp_connection_state_t state,
		   amqp_channel_t channel,
		   uint64_t delivery_tag,
		   amqp_boolean_t multiple)
{
  amqp_basic_ack_t m =
    (amqp_basic_ack_t) {
      .delivery_tag = delivery_tag,
      .multiple = multiple
    };
  AMQP_CHECK_RESULT(amqp_send_method(state, channel, AMQP_BASIC_ACK_METHOD, &m));
  return 0;
}

amqp_queue_purge_ok_t *amqp_queue_purge(amqp_connection_state_t state,
					amqp_channel_t channel,
					amqp_bytes_t queue,
					amqp_boolean_t no_wait)
{
  state->most_recent_api_result =
    AMQP_SIMPLE_RPC(state, channel, QUEUE, PURGE, PURGE_OK,
		    amqp_queue_purge_t,
		    0, queue, no_wait);
  return RPC_REPLY(amqp_queue_purge_ok_t);
}
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
static int amqp_login_inner(amqp_connection_state_t state,
			    int channel_max,
			    int frame_max,
			    int heartbeat,
			    amqp_sasl_method_enum sasl_method,
			    va_list vl)
{
  int res;
  amqp_method_t method;
  int server_frame_max;
  uint16_t server_channel_max;
  uint16_t server_heartbeat;

  amqp_send_header(state);

  res = amqp_simple_wait_method(state, 0, AMQP_CONNECTION_START_METHOD,
				&method);
  if (res < 0)
    return res;

  {
    amqp_connection_start_t *s = (amqp_connection_start_t *) method.decoded;
    if ((s->version_major != AMQP_PROTOCOL_VERSION_MAJOR) ||
	(s->version_minor != AMQP_PROTOCOL_VERSION_MINOR)) {
      return -ERROR_INCOMPATIBLE_AMQP_VERSION;
    }

    /* TODO: check that our chosen SASL mechanism is in the list of
       acceptable mechanisms. Or even let the application choose from
       the list! */
  }

  {
    amqp_table_entry_t properties[2];
    amqp_connection_start_ok_t s;
    amqp_bytes_t response_bytes = sasl_response(&state->decoding_pool,
						sasl_method, vl);

    if (response_bytes.bytes == NULL)
      return -ERROR_NO_MEMORY;

    properties[0].key = amqp_cstring_bytes("product");
    properties[0].value.kind = AMQP_FIELD_KIND_UTF8;
    properties[0].value.value.bytes
      = amqp_cstring_bytes("rabbitmq-c");

    properties[1].key = amqp_cstring_bytes("information");
    properties[1].value.kind = AMQP_FIELD_KIND_UTF8;
    properties[1].value.value.bytes
      = amqp_cstring_bytes("See http://hg.rabbitmq.com/rabbitmq-c/");

    s.client_properties.num_entries = 2;
    s.client_properties.entries = properties;
    s.mechanism = sasl_method_name(sasl_method);
    s.response = response_bytes;
    s.locale.bytes = "en_US";
    s.locale.len = 5;

    res = amqp_send_method(state, 0, AMQP_CONNECTION_START_OK_METHOD, &s);
    if (res < 0)
      return res;
  }

  amqp_release_buffers(state);

  res = amqp_simple_wait_method(state, 0, AMQP_CONNECTION_TUNE_METHOD,
				&method);
  if (res < 0)
    return res;

  {
    amqp_connection_tune_t *s = (amqp_connection_tune_t *) method.decoded;
    server_channel_max = s->channel_max;
    server_frame_max = s->frame_max;
    server_heartbeat = s->heartbeat;
  }

  if (server_channel_max != 0 && server_channel_max < channel_max)
    channel_max = server_channel_max;

  if (server_frame_max != 0 && server_frame_max < frame_max)
    frame_max = server_frame_max;

  if (server_heartbeat != 0 && server_heartbeat < heartbeat)
    heartbeat = server_heartbeat;

  res = amqp_tune_connection(state, channel_max, frame_max, heartbeat);
  if (res < 0)
    return res;

  {
    amqp_connection_tune_ok_t s;
    s.frame_max = frame_max;
    s.channel_max = channel_max;
    s.heartbeat = heartbeat;

    res = amqp_send_method(state, 0, AMQP_CONNECTION_TUNE_OK_METHOD, &s);
    if (res < 0)
      return res;
  }

  amqp_release_buffers(state);

  return 0;
}
int php_amqp_connection_resource_error(amqp_rpc_reply_t reply, char **message, amqp_connection_resource *resource, amqp_channel_t channel_id TSRMLS_DC)
{
	assert (resource != NULL);

	switch (reply.reply_type) {
		case AMQP_RESPONSE_NORMAL:
			return PHP_AMQP_RESOURCE_RESPONSE_OK;

		case AMQP_RESPONSE_NONE:
			spprintf(message, 0, "Missing RPC reply type.");
			return PHP_AMQP_RESOURCE_RESPONSE_ERROR;

		case AMQP_RESPONSE_LIBRARY_EXCEPTION:
			spprintf(message, 0, "Library error: %s", amqp_error_string2(reply.library_error));
			return PHP_AMQP_RESOURCE_RESPONSE_ERROR;

		case AMQP_RESPONSE_SERVER_EXCEPTION:
			switch (reply.reply.id) {
				case AMQP_CONNECTION_CLOSE_METHOD: {
					amqp_connection_close_t *m = (amqp_connection_close_t *)reply.reply.decoded;

					spprintf(message, 0, "Server connection error: %d, message: %.*s",
						m->reply_code,
						(PHP5to7_param_str_len_type_t) m->reply_text.len,
						(char *) m->reply_text.bytes
					);

					/*
					 *    - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception
					 *      occurred, cast r.reply.decoded to amqp_connection_close_t* to see
					 *      details of the exception. The client amqp_send_method() a
					 *      amqp_connection_close_ok_t and disconnect from the broker.
					 */

					amqp_connection_close_ok_t *decoded = (amqp_connection_close_ok_t *) NULL;

					amqp_send_method(
						resource->connection_state,
						0, /* NOTE: 0-channel is reserved for things like this */
						AMQP_CONNECTION_CLOSE_OK_METHOD,
						&decoded
					);

					/* Prevent finishing AMQP connection in connection resource destructor */
					resource->is_connected = '\0';

					return PHP_AMQP_RESOURCE_RESPONSE_ERROR_CONNECTION_CLOSED;
				}
				case AMQP_CHANNEL_CLOSE_METHOD: {
					assert(channel_id > 0 && channel_id <= resource->max_slots);

					amqp_channel_close_t *m = (amqp_channel_close_t *) reply.reply.decoded;

					spprintf(message, 0, "Server channel error: %d, message: %.*s",
						m->reply_code,
						(PHP5to7_param_str_len_type_t) m->reply_text.len,
						(char *)m->reply_text.bytes
					);

					/*
					 *    - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception
					 *      occurred, cast r.reply.decoded to amqp_channel_close_t* to see details
					 *      of the exception. The client should amqp_send_method() a
					 *      amqp_channel_close_ok_t. The channel must be re-opened before it
					 *      can be used again. Any resources associated with the channel
					 *      (auto-delete exchanges, auto-delete queues, consumers) are invalid
					 *      and must be recreated before attempting to use them again.
					 */

					amqp_channel_close_ok_t *decoded = (amqp_channel_close_ok_t *) NULL;

					amqp_send_method(
						resource->connection_state,
						channel_id,
						AMQP_CHANNEL_CLOSE_OK_METHOD,
						&decoded
					);

					return PHP_AMQP_RESOURCE_RESPONSE_ERROR_CHANNEL_CLOSED;
				}
			}
		/* Default for the above switch should be handled by the below default. */
		default:
			spprintf(message, 0, "Unknown server error, method id 0x%08X",	reply.reply.id);
			return PHP_AMQP_RESOURCE_RESPONSE_ERROR;
	}

	/* Should not never get here*/
}
Exemplo n.º 12
0
void ChannelImpl::FinishCloseConnection()
{
    SetIsConnected(false);
    amqp_connection_close_ok_t close_ok;
    amqp_send_method(m_connection, 0, AMQP_CONNECTION_CLOSE_OK_METHOD, &close_ok);
}
Exemplo n.º 13
0
void ChannelImpl::FinishCloseChannel(amqp_channel_t channel)
{
    amqp_channel_close_ok_t close_ok;
    m_open_channels.erase(channel);
    CheckForError(amqp_send_method(m_connection, channel, AMQP_CHANNEL_CLOSE_OK_METHOD, &close_ok));
}