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; }
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); }
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); }
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)); }
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)); }
/** * 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; }
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; }
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); }
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; } }
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*/ }
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); }
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)); }