Пример #1
0
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);
}
Пример #3
0
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);
			}
		}
	}
}
Пример #4
0
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;
    }
}
Пример #5
0
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);
			}
		}
	}
}
Пример #6
0
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;
	}
}
Пример #7
0
/* 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;
}
Пример #8
0
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;
}