static void amqp_value_decoded(void* context, AMQP_VALUE decoded_value) { SASL_FRAME_CODEC_INSTANCE* sasl_frame_codec_instance = (SASL_FRAME_CODEC_INSTANCE*)context; AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(decoded_value); if (descriptor == NULL) { sasl_frame_codec_instance->decode_state = SASL_FRAME_DECODE_ERROR; /* Codes_SRS_SASL_FRAME_CODEC_01_049: [If any error occurs while decoding a frame, the decoder shall call the on_sasl_frame_codec_error and pass to it the callback_context, both of those being the ones given to sasl_frame_codec_create.] */ sasl_frame_codec_instance->on_sasl_frame_codec_error(sasl_frame_codec_instance->callback_context); } else { /* Codes_SRS_SASL_FRAME_CODEC_01_009: [The frame body of a SASL frame MUST contain exactly one AMQP type, whose type encoding MUST have provides=“sasl-frame”.] */ if (!is_sasl_mechanisms_type_by_descriptor(descriptor) && !is_sasl_init_type_by_descriptor(descriptor) && !is_sasl_challenge_type_by_descriptor(descriptor) && !is_sasl_response_type_by_descriptor(descriptor) && !is_sasl_outcome_type_by_descriptor(descriptor)) { sasl_frame_codec_instance->decode_state = SASL_FRAME_DECODE_ERROR; /* Codes_SRS_SASL_FRAME_CODEC_01_049: [If any error occurs while decoding a frame, the decoder shall call the on_sasl_frame_codec_error and pass to it the callback_context, both of those being the ones given to sasl_frame_codec_create.] */ sasl_frame_codec_instance->on_sasl_frame_codec_error(sasl_frame_codec_instance->callback_context); } else { sasl_frame_codec_instance->decoded_sasl_frame_value = decoded_value; } } }
static void on_delivery_settled(void* context, delivery_number delivery_no, LINK_DELIVERY_SETTLE_REASON reason, AMQP_VALUE delivery_state) { MESSAGE_WITH_CALLBACK* message_with_callback = (MESSAGE_WITH_CALLBACK*)context; MESSAGE_SENDER_INSTANCE* message_sender_instance = (MESSAGE_SENDER_INSTANCE*)message_with_callback->message_sender; (void)delivery_no; if (message_with_callback->on_message_send_complete != NULL) { switch (reason) { case LINK_DELIVERY_SETTLE_REASON_DISPOSITION_RECEIVED: if (delivery_state == NULL) { LogError("delivery state not provided"); } else { AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(delivery_state); if (descriptor == NULL) { LogError("Error getting descriptor for delivery state"); } else if (is_accepted_type_by_descriptor(descriptor)) { message_with_callback->on_message_send_complete(message_with_callback->context, MESSAGE_SEND_OK); } else { message_with_callback->on_message_send_complete(message_with_callback->context, MESSAGE_SEND_ERROR); } } break; case LINK_DELIVERY_SETTLE_REASON_SETTLED: message_with_callback->on_message_send_complete(message_with_callback->context, MESSAGE_SEND_OK); break; case LINK_DELIVERY_SETTLE_REASON_NOT_DELIVERED: default: message_with_callback->on_message_send_complete(message_with_callback->context, MESSAGE_SEND_ERROR); break; } } remove_pending_message(message_sender_instance, message_with_callback); }
static void log_outgoing_frame(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance, AMQP_VALUE performative) { if (sasl_client_io_instance->logger_log != NULL) { AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative); if (descriptor != NULL) { LOG(sasl_client_io_instance->logger_log, 0, "-> "); LOG(sasl_client_io_instance->logger_log, 0, (char*)get_frame_type_as_string(descriptor)); char* performative_as_string = NULL; LOG(sasl_client_io_instance->logger_log, LOG_LINE, (performative_as_string = amqpvalue_to_string(performative))); if (performative_as_string != NULL) { amqpalloc_free(performative_as_string); } } } }
static void amqp_value_decoded(void* context, AMQP_VALUE decoded_value) { AMQP_FRAME_CODEC_INSTANCE* amqp_frame_codec_instance = (AMQP_FRAME_CODEC_INSTANCE*)context; uint64_t performative_descriptor_ulong; AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(decoded_value); /* Codes_SRS_AMQP_FRAME_CODEC_01_060: [If any error occurs while decoding a frame, the decoder shall switch to an error state where decoding shall not be possible anymore.] */ if ((descriptor == NULL) || (amqpvalue_get_ulong(descriptor, &performative_descriptor_ulong) != 0) || /* Codes_SRS_AMQP_FRAME_CODEC_01_003: [The performative MUST be one of those defined in section 2.7 and is encoded as a described type in the AMQP type system.] */ (performative_descriptor_ulong < AMQP_OPEN) || (performative_descriptor_ulong > AMQP_CLOSE)) { /* Codes_SRS_AMQP_FRAME_CODEC_01_060: [If any error occurs while decoding a frame, the decoder shall switch to an error state where decoding shall not be possible anymore.] */ amqp_frame_codec_instance->decode_state = AMQP_FRAME_DECODE_ERROR; } else { amqp_frame_codec_instance->decoded_performative = decoded_value; } }
static void on_frame_received(void* context, AMQP_VALUE performative, uint32_t payload_size, const unsigned char* payload_bytes) { SESSION_INSTANCE* session_instance = (SESSION_INSTANCE*)context; AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative); if (is_begin_type_by_descriptor(descriptor)) { BEGIN_HANDLE begin_handle; if (amqpvalue_get_begin(performative, &begin_handle) != 0) { connection_close(session_instance->connection, "amqp:decode-error", "Cannot decode BEGIN frame"); } else { if ((begin_get_incoming_window(begin_handle, &session_instance->remote_incoming_window) != 0) || (begin_get_next_outgoing_id(begin_handle, &session_instance->next_incoming_id) != 0)) { /* error */ begin_destroy(begin_handle); session_set_state(session_instance, SESSION_STATE_DISCARDING); connection_close(session_instance->connection, "amqp:decode-error", "Cannot get incoming windows and next outgoing id"); } else { begin_destroy(begin_handle); if (session_instance->session_state == SESSION_STATE_BEGIN_SENT) { session_set_state(session_instance, SESSION_STATE_MAPPED); } else if(session_instance->session_state == SESSION_STATE_UNMAPPED) { session_set_state(session_instance, SESSION_STATE_BEGIN_RCVD); if (send_begin(session_instance) != 0) { connection_close(session_instance->connection, "amqp:internal-error", "Failed sending BEGIN frame"); session_set_state(session_instance, SESSION_STATE_DISCARDING); } else { session_set_state(session_instance, SESSION_STATE_MAPPED); } } } } } else if (is_attach_type_by_descriptor(descriptor)) { const char* name = NULL; ATTACH_HANDLE attach_handle; if (amqpvalue_get_attach(performative, &attach_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode ATTACH frame"); } else { role role; AMQP_VALUE source; AMQP_VALUE target; if ((attach_get_name(attach_handle, &name) != 0) || (attach_get_role(attach_handle, &role) != 0) || (attach_get_source(attach_handle, &source) != 0) || (attach_get_target(attach_handle, &target) != 0)) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot get link name from ATTACH frame"); } else { LINK_ENDPOINT_INSTANCE* link_endpoint = find_link_endpoint_by_name(session_instance, name); if (link_endpoint == NULL) { /* new link attach */ if (session_instance->on_link_attached != NULL) { LINK_ENDPOINT_HANDLE new_link_endpoint = session_create_link_endpoint(session_instance, name); if (new_link_endpoint == NULL) { end_session_with_error(session_instance, "amqp:internal-error", "Cannot create link endpoint"); } else { if (!session_instance->on_link_attached(session_instance->on_link_attached_callback_context, new_link_endpoint, name, role, source, target)) { session_destroy_link_endpoint(new_link_endpoint); new_link_endpoint = NULL; } else { if (new_link_endpoint->frame_received_callback != NULL) { new_link_endpoint->frame_received_callback(new_link_endpoint->callback_context, performative, payload_size, payload_bytes); } } } } } else { if (attach_get_handle(attach_handle, &link_endpoint->input_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot get input handle from ATTACH frame"); } else { link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes); } } } attach_destroy(attach_handle); } } else if (is_detach_type_by_descriptor(descriptor)) { DETACH_HANDLE detach_handle; if (amqpvalue_get_detach(performative, &detach_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode DETACH frame"); } else { uint32_t remote_handle; if (detach_get_handle(detach_handle, &remote_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot get handle from DETACH frame"); detach_destroy(detach_handle); } else { detach_destroy(detach_handle); LINK_ENDPOINT_INSTANCE* link_endpoint = find_link_endpoint_by_input_handle(session_instance, remote_handle); if (link_endpoint == NULL) { end_session_with_error(session_instance, "amqp:session:unattached-handle", ""); } else { link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes); } } } } else if (is_flow_type_by_descriptor(descriptor)) { FLOW_HANDLE flow_handle; if (amqpvalue_get_flow(performative, &flow_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode FLOW frame"); } else { uint32_t remote_handle; transfer_number flow_next_incoming_id; uint32_t flow_incoming_window; if ((flow_get_next_outgoing_id(flow_handle, &session_instance->next_incoming_id) != 0) || (flow_get_next_incoming_id(flow_handle, &flow_next_incoming_id) != 0) || (flow_get_incoming_window(flow_handle, &flow_incoming_window) != 0)) { flow_destroy(flow_handle); end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode FLOW frame"); } else { LINK_ENDPOINT_INSTANCE* link_endpoint_instance = NULL; session_instance->remote_incoming_window = flow_next_incoming_id + flow_incoming_window - session_instance->next_outgoing_id; if (flow_get_handle(flow_handle, &remote_handle) == 0) { link_endpoint_instance = find_link_endpoint_by_input_handle(session_instance, remote_handle); } flow_destroy(flow_handle); if (link_endpoint_instance != NULL) { link_endpoint_instance->frame_received_callback(link_endpoint_instance->callback_context, performative, payload_size, payload_bytes); } size_t i = 0; while ((session_instance->remote_incoming_window > 0) && (i < session_instance->link_endpoint_count)) { /* notify the caller that it can send here */ if (session_instance->link_endpoints[i]->on_session_flow_on != NULL) { session_instance->link_endpoints[i]->on_session_flow_on(session_instance->link_endpoints[i]->callback_context); } i++; } } } } else if (is_transfer_type_by_descriptor(descriptor)) { TRANSFER_HANDLE transfer_handle; if (amqpvalue_get_transfer(performative, &transfer_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode TRANSFER frame"); } else { uint32_t remote_handle; delivery_number delivery_id; transfer_get_delivery_id(transfer_handle, &delivery_id); if (transfer_get_handle(transfer_handle, &remote_handle) != 0) { transfer_destroy(transfer_handle); end_session_with_error(session_instance, "amqp:decode-error", "Cannot get handle from TRANSFER frame"); } else { transfer_destroy(transfer_handle); session_instance->next_incoming_id++; session_instance->remote_outgoing_window--; session_instance->incoming_window--; LINK_ENDPOINT_INSTANCE* link_endpoint = find_link_endpoint_by_output_handle(session_instance, remote_handle); if (link_endpoint == NULL) { end_session_with_error(session_instance, "amqp:session:unattached-handle", ""); } else { link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes); } if (session_instance->incoming_window == 0) { session_instance->incoming_window = session_instance->desired_incoming_window; send_flow(session_instance); } } } } else if (is_disposition_type_by_descriptor(descriptor)) { uint32_t i; for (i = 0; i < session_instance->link_endpoint_count; i++) { LINK_ENDPOINT_INSTANCE* link_endpoint = session_instance->link_endpoints[i]; link_endpoint->frame_received_callback(link_endpoint->callback_context, performative, payload_size, payload_bytes); } } else if (is_end_type_by_descriptor(descriptor)) { END_HANDLE end_handle; if (amqpvalue_get_end(performative, &end_handle) != 0) { end_session_with_error(session_instance, "amqp:decode-error", "Cannot decode END frame"); } else { if ((session_instance->session_state != SESSION_STATE_END_RCVD) && (session_instance->session_state != SESSION_STATE_DISCARDING)) { session_set_state(session_instance, SESSION_STATE_END_RCVD); if (send_end_frame(session_instance, NULL) != 0) { /* fatal error */ (void)connection_close(session_instance->connection, "amqp:internal-error", "Cannot send END frame."); } session_set_state(session_instance, SESSION_STATE_DISCARDING); } } } }
static void sasl_frame_received_callback(void* context, AMQP_VALUE sasl_frame) { SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context; /* Codes_SRS_SASLCLIENTIO_01_067: [The SASL frame exchange shall be started as soon as the SASL header handshake is done.] */ switch (sasl_client_io_instance->io_state) { default: break; case IO_STATE_OPEN: case IO_STATE_OPENING_UNDERLYING_IO: case IO_STATE_CLOSING: /* Codes_SRS_SASLCLIENTIO_01_117: [If on_sasl_frame_received_callback is called when the state of the IO is OPEN then the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */ handle_error(sasl_client_io_instance); break; case IO_STATE_SASL_HANDSHAKE: if (sasl_client_io_instance->sasl_header_exchange_state != SASL_HEADER_EXCHANGE_HEADER_EXCH) { /* Codes_SRS_SASLCLIENTIO_01_118: [If on_sasl_frame_received_callback is called in the OPENING state but the header exchange has not yet been completed, then the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */ handle_error(sasl_client_io_instance); } else { AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(sasl_frame); if (descriptor == NULL) { /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */ handle_error(sasl_client_io_instance); } else { log_incoming_frame(sasl_client_io_instance, sasl_frame); /* Codes_SRS_SASLCLIENTIO_01_032: [The peer acting as the SASL server MUST announce supported authentication mechanisms using the sasl-mechanisms frame.] */ /* Codes_SRS_SASLCLIENTIO_01_040: [The peer playing the role of the SASL client and the peer playing the role of the SASL server MUST correspond to the TCP client and server respectively.] */ /* Codes_SRS_SASLCLIENTIO_01_034: [<-- SASL-MECHANISMS] */ if (is_sasl_mechanisms_type_by_descriptor(descriptor)) { switch (sasl_client_io_instance->sasl_client_negotiation_state) { case SASL_CLIENT_NEGOTIATION_NOT_STARTED: { SASL_MECHANISMS_HANDLE sasl_mechanisms_handle; if (amqpvalue_get_sasl_mechanisms(sasl_frame, &sasl_mechanisms_handle) != 0) { /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */ handle_error(sasl_client_io_instance); } else { AMQP_VALUE sasl_server_mechanisms; uint32_t mechanisms_count; if ((sasl_mechanisms_get_sasl_server_mechanisms(sasl_mechanisms_handle, &sasl_server_mechanisms) != 0) || (amqpvalue_get_array_item_count(sasl_server_mechanisms, &mechanisms_count) != 0) || (mechanisms_count == 0)) { /* Codes_SRS_SASLCLIENTIO_01_042: [It is invalid for this list to be null or empty.] */ handle_error(sasl_client_io_instance); } else { const char* sasl_mechanism_name = saslmechanism_get_mechanism_name(sasl_client_io_instance->sasl_mechanism); if (sasl_mechanism_name == NULL) { /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */ handle_error(sasl_client_io_instance); } else { uint32_t i; for (i = 0; i < mechanisms_count; i++) { AMQP_VALUE sasl_server_mechanism; sasl_server_mechanism = amqpvalue_get_array_item(sasl_server_mechanisms, i); if (sasl_server_mechanism == NULL) { i = mechanisms_count; } else { const char* sasl_server_mechanism_name; if (amqpvalue_get_symbol(sasl_server_mechanism, &sasl_server_mechanism_name) != 0) { i = mechanisms_count; } else { if (strcmp(sasl_mechanism_name, sasl_server_mechanism_name) == 0) { amqpvalue_destroy(sasl_server_mechanism); break; } } amqpvalue_destroy(sasl_server_mechanism); } } if (i == mechanisms_count) { /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */ handle_error(sasl_client_io_instance); } else { sasl_client_io_instance->sasl_client_negotiation_state = SASL_CLIENT_NEGOTIATION_MECH_RCVD; /* Codes_SRS_SASLCLIENTIO_01_035: [SASL-INIT -->] */ /* Codes_SRS_SASLCLIENTIO_01_033: [The partner MUST then choose one of the supported mechanisms and initiate a sasl exchange.] */ /* Codes_SRS_SASLCLIENTIO_01_054: [Selects the sasl mechanism and provides the initial response if needed.] */ if (send_sasl_init(sasl_client_io_instance, sasl_mechanism_name) != 0) { /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */ handle_error(sasl_client_io_instance); } else { sasl_client_io_instance->sasl_client_negotiation_state = SASL_CLIENT_NEGOTIATION_INIT_SENT; } } } } sasl_mechanisms_destroy(sasl_mechanisms_handle); } break; } } } /* Codes_SRS_SASLCLIENTIO_01_052: [Send the SASL challenge data as defined by the SASL specification.] */ /* Codes_SRS_SASLCLIENTIO_01_036: [<-- SASL-CHALLENGE *] */ /* Codes_SRS_SASLCLIENTIO_01_039: [the SASL challenge/response step can occur zero or more times depending on the details of the SASL mechanism chosen.] */ else if (is_sasl_challenge_type_by_descriptor(descriptor)) { /* Codes_SRS_SASLCLIENTIO_01_032: [The peer acting as the SASL server MUST announce supported authentication mechanisms using the sasl-mechanisms frame.] */ if ((sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_INIT_SENT) && (sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_RESPONSE_SENT)) { handle_error(sasl_client_io_instance); } else { SASL_CHALLENGE_HANDLE sasl_challenge_handle; if (amqpvalue_get_sasl_challenge(sasl_frame, &sasl_challenge_handle) != 0) { /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */ handle_error(sasl_client_io_instance); } else { amqp_binary challenge_binary_value; SASL_MECHANISM_BYTES response_bytes; /* Codes_SRS_SASLCLIENTIO_01_053: [Challenge information, a block of opaque binary data passed to the security mechanism.] */ if (sasl_challenge_get_challenge(sasl_challenge_handle, &challenge_binary_value) != 0) { /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */ handle_error(sasl_client_io_instance); } else { SASL_MECHANISM_BYTES challenge = { challenge_binary_value.bytes, challenge_binary_value.length }; /* Codes_SRS_SASLCLIENTIO_01_057: [The contents of this data are defined by the SASL security mechanism.] */ /* Codes_SRS_SASLCLIENTIO_01_037: [SASL-RESPONSE -->] */ if ((saslmechanism_challenge(sasl_client_io_instance->sasl_mechanism, &challenge, &response_bytes) != 0) || (send_sasl_response(sasl_client_io_instance, response_bytes) != 0)) { /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the SASL client IO state shall be switched to IO_STATE_ERROR and the on_state_changed callback shall be triggered.] */ handle_error(sasl_client_io_instance); } } sasl_challenge_destroy(sasl_challenge_handle); } } } /* Codes_SRS_SASLCLIENTIO_01_058: [This frame indicates the outcome of the SASL dialog.] */ /* Codes_SRS_SASLCLIENTIO_01_038: [<-- SASL-OUTCOME] */ else if (is_sasl_outcome_type_by_descriptor(descriptor)) { /* Codes_SRS_SASLCLIENTIO_01_032: [The peer acting as the SASL server MUST announce supported authentication mechanisms using the sasl-mechanisms frame.] */ if ((sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_INIT_SENT) && (sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_RESPONSE_SENT)) { handle_error(sasl_client_io_instance); } else { SASL_OUTCOME_HANDLE sasl_outcome; sasl_client_io_instance->sasl_client_negotiation_state = SASL_CLIENT_NEGOTIATION_OUTCOME_RCVD; if (amqpvalue_get_sasl_outcome(sasl_frame, &sasl_outcome) != 0) { handle_error(sasl_client_io_instance); } else { sasl_code sasl_code; /* Codes_SRS_SASLCLIENTIO_01_060: [A reply-code indicating the outcome of the SASL dialog.] */ if (sasl_outcome_get_code(sasl_outcome, &sasl_code) != 0) { handle_error(sasl_client_io_instance); } else { switch (sasl_code) { default: case sasl_code_auth: /* Codes_SRS_SASLCLIENTIO_01_063: [1 Connection authentication failed due to an unspecified problem with the supplied credentials.] */ case sasl_code_sys: /* Codes_SRS_SASLCLIENTIO_01_064: [2 Connection authentication failed due to a system error.] */ case sasl_code_sys_perm: /* Codes_SRS_SASLCLIENTIO_01_065: [3 Connection authentication failed due to a system error that is unlikely to be corrected without intervention.] */ case sasl_code_sys_temp: /* Codes_SRS_SASLCLIENTIO_01_066: [4 Connection authentication failed due to a transient system error.] */ handle_error(sasl_client_io_instance); break; case sasl_code_ok: /* Codes_SRS_SASLCLIENTIO_01_059: [Upon successful completion of the SASL dialog the security layer has been established] */ /* Codes_SRS_SASLCLIENTIO_01_062: [0 Connection authentication succeeded.] */ sasl_client_io_instance->io_state = IO_STATE_OPEN; indicate_open_complete(sasl_client_io_instance, IO_OPEN_OK); break; } } sasl_outcome_destroy(sasl_outcome); } } } else { LOG(sasl_client_io_instance->logger_log, LOG_LINE, "Bad SASL frame"); } } } break; } }
/* Codes_SRS_SASL_FRAME_CODEC_01_029: [sasl_frame_codec_encode_frame shall encode the frame header and sasl_frame_value AMQP value in a SASL frame and on success it shall return 0.] */ int sasl_frame_codec_encode_frame(SASL_FRAME_CODEC_HANDLE sasl_frame_codec, const AMQP_VALUE sasl_frame_value, ON_BYTES_ENCODED on_bytes_encoded, void* callback_context) { int result; SASL_FRAME_CODEC_INSTANCE* sasl_frame_codec_instance = (SASL_FRAME_CODEC_INSTANCE*)sasl_frame_codec; /* Codes_SRS_SASL_FRAME_CODEC_01_030: [If sasl_frame_codec or sasl_frame_value is NULL, sasl_frame_codec_encode_frame shall fail and return a non-zero value.] */ if ((sasl_frame_codec == NULL) || (sasl_frame_value == NULL)) { /* Codes_SRS_SASL_FRAME_CODEC_01_034: [If any error occurs during encoding, sasl_frame_codec_encode_frame shall fail and return a non-zero value.] */ result = __LINE__; } else { AMQP_VALUE descriptor; uint64_t sasl_frame_descriptor_ulong; size_t encoded_size; if (((descriptor = amqpvalue_get_inplace_descriptor(sasl_frame_value)) == NULL) || (amqpvalue_get_ulong(descriptor, &sasl_frame_descriptor_ulong) != 0) || /* Codes_SRS_SASL_FRAME_CODEC_01_047: [The frame body of a SASL frame MUST contain exactly one AMQP type, whose type encoding MUST have provides=“sasl-frame”.] */ (sasl_frame_descriptor_ulong < SASL_MECHANISMS) || (sasl_frame_descriptor_ulong > SASL_OUTCOME)) { /* Codes_SRS_SASL_FRAME_CODEC_01_034: [If any error occurs during encoding, sasl_frame_codec_encode_frame shall fail and return a non-zero value.] */ result = __LINE__; } /* Codes_SRS_SASL_FRAME_CODEC_01_032: [The payload frame size shall be computed based on the encoded size of the sasl_frame_value and its fields.] */ /* Codes_SRS_SASL_FRAME_CODEC_01_033: [The encoded size of the sasl_frame_value and its fields shall be obtained by calling amqpvalue_get_encoded_size.] */ else if ((amqpvalue_get_encoded_size(sasl_frame_value, &encoded_size) != 0) || /* Codes_SRS_SASL_FRAME_CODEC_01_016: [The maximum size of a SASL frame is defined by MIN-MAX-FRAME-SIZE.] */ (encoded_size > MIX_MAX_FRAME_SIZE - 8)) { /* Codes_SRS_SASL_FRAME_CODEC_01_034: [If any error occurs during encoding, sasl_frame_codec_encode_frame shall fail and return a non-zero value.] */ result = __LINE__; } else { unsigned char* sasl_frame_bytes = (unsigned char*)amqpalloc_malloc(encoded_size); if (sasl_frame_bytes == NULL) { result = __LINE__; } else { PAYLOAD payload; payload.bytes = sasl_frame_bytes; payload.length = 0; if (amqpvalue_encode(sasl_frame_value, encode_bytes, &payload) != 0) { result = __LINE__; } else { /* Codes_SRS_SASL_FRAME_CODEC_01_031: [sasl_frame_codec_encode_frame shall encode the frame header and its contents by using frame_codec_encode_frame.] */ /* Codes_SRS_SASL_FRAME_CODEC_01_012: [Bytes 6 and 7 of the header are ignored.] */ /* Codes_SRS_SASL_FRAME_CODEC_01_013: [Implementations SHOULD set these to 0x00.] */ /* Codes_SRS_SASL_FRAME_CODEC_01_014: [The extended header is ignored.] */ /* Codes_SRS_SASL_FRAME_CODEC_01_015: [Implementations SHOULD therefore set DOFF to 0x02.] */ if (frame_codec_encode_frame(sasl_frame_codec_instance->frame_codec, FRAME_TYPE_SASL, &payload, 1, NULL, 0, on_bytes_encoded, callback_context) != 0) { /* Codes_SRS_SASL_FRAME_CODEC_01_034: [If any error occurs during encoding, sasl_frame_codec_encode_frame shall fail and return a non-zero value.] */ result = __LINE__; } else { result = 0; } } amqpalloc_free(sasl_frame_bytes); } } } return result; }
int amqp_frame_codec_encode_frame(AMQP_FRAME_CODEC_HANDLE amqp_frame_codec, uint16_t channel, const AMQP_VALUE performative, const PAYLOAD* payloads, size_t payload_count, ON_BYTES_ENCODED on_bytes_encoded, void* callback_context) { int result; /* Codes_SRS_AMQP_FRAME_CODEC_01_024: [If frame_codec, performative or on_bytes_encoded is NULL, amqp_frame_codec_encode_frame shall fail and return a non-zero value.] */ if ((amqp_frame_codec == NULL) || (performative == NULL) || (on_bytes_encoded == NULL)) { result = __LINE__; } else { AMQP_VALUE descriptor; uint64_t performative_ulong; size_t encoded_size; if (((descriptor = amqpvalue_get_inplace_descriptor(performative)) == NULL) || (amqpvalue_get_ulong(descriptor, &performative_ulong) != 0) || /* Codes_SRS_AMQP_FRAME_CODEC_01_008: [The performative MUST be one of those defined in section 2.7 and is encoded as a described type in the AMQP type system.] */ (performative_ulong < AMQP_OPEN) || (performative_ulong > AMQP_CLOSE)) { /* Codes_SRS_AMQP_FRAME_CODEC_01_029: [If any error occurs during encoding, amqp_frame_codec_encode_frame shall fail and return a non-zero value.] */ result = __LINE__; } /* Codes_SRS_AMQP_FRAME_CODEC_01_027: [The encoded size of the performative and its fields shall be obtained by calling amqpvalue_get_encoded_size.] */ else if (amqpvalue_get_encoded_size(performative, &encoded_size) != 0) { /* Codes_SRS_AMQP_FRAME_CODEC_01_029: [If any error occurs during encoding, amqp_frame_codec_encode_frame shall fail and return a non-zero value.] */ result = __LINE__; } else { unsigned char* amqp_performative_bytes = (unsigned char*)amqpalloc_malloc(encoded_size); if (amqp_performative_bytes == NULL) { result = __LINE__; } else { PAYLOAD* new_payloads = (PAYLOAD*)amqpalloc_malloc(sizeof(PAYLOAD) * (payload_count + 1)); if (new_payloads == NULL) { result = __LINE__; } else { /* Codes_SRS_AMQP_FRAME_CODEC_01_070: [The payloads argument for frame_codec_encode_frame shall be made of the payload for the encoded performative and the payloads passed to amqp_frame_codec_encode_frame.] */ /* Codes_SRS_AMQP_FRAME_CODEC_01_028: [The encode result for the performative shall be placed in a PAYLOAD structure.] */ new_payloads[0].bytes = amqp_performative_bytes; new_payloads[0].length = 0; if (payload_count > 0) { (void)memcpy(new_payloads + 1, payloads, sizeof(PAYLOAD) * payload_count); } if (amqpvalue_encode(performative, encode_bytes, &new_payloads[0]) != 0) { result = __LINE__; } else { unsigned char channel_bytes[2]; channel_bytes[0] = channel >> 8; channel_bytes[1] = channel & 0xFF; /* Codes_SRS_AMQP_FRAME_CODEC_01_005: [Bytes 6 and 7 of an AMQP frame contain the channel number ] */ /* Codes_SRS_AMQP_FRAME_CODEC_01_025: [amqp_frame_codec_encode_frame shall encode the frame header by using frame_codec_encode_frame.] */ /* Codes_SRS_AMQP_FRAME_CODEC_01_006: [The frame body is defined as a performative followed by an opaque payload.] */ if (frame_codec_encode_frame(amqp_frame_codec->frame_codec, FRAME_TYPE_AMQP, new_payloads, payload_count + 1, channel_bytes, sizeof(channel_bytes), on_bytes_encoded, callback_context) != 0) { /* Codes_SRS_AMQP_FRAME_CODEC_01_029: [If any error occurs during encoding, amqp_frame_codec_encode_frame shall fail and return a non-zero value.] */ result = __LINE__; } else { /* Codes_SRS_AMQP_FRAME_CODEC_01_022: [amqp_frame_codec_begin_encode_frame shall encode the frame header and AMQP performative in an AMQP frame and on success it shall return 0.] */ result = 0; } } amqpalloc_free(new_payloads); } amqpalloc_free(amqp_performative_bytes); } } } return result; }