A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Apr 21 14:50:32 2017 -0700
Revision:
23:1111ee8bcba4
Parent:
21:f9c433d8e6ca
Child:
24:2c59c2d43ebf
1.1.13

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Azure.IoT Build 0:6ae2f7bca550 1 // Copyright (c) Microsoft. All rights reserved.
Azure.IoT Build 0:6ae2f7bca550 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
Azure.IoT Build 0:6ae2f7bca550 3
Azure.IoT Build 0:6ae2f7bca550 4 #include <stdlib.h>
Azure.IoT Build 0:6ae2f7bca550 5 #include <string.h>
Azure.IoT Build 0:6ae2f7bca550 6
AzureIoTClient 19:000ab4e6a2c1 7 #include "azure_c_shared_utility/optimize_size.h"
AzureIoTClient 21:f9c433d8e6ca 8 #include "azure_c_shared_utility/gballoc.h"
Azure.IoT Build 0:6ae2f7bca550 9 #include "azure_c_shared_utility/xio.h"
Azure.IoT Build 0:6ae2f7bca550 10 #include "azure_c_shared_utility/xlogging.h"
Azure.IoT Build 0:6ae2f7bca550 11 #include "azure_c_shared_utility/tickcounter.h"
Azure.IoT Build 0:6ae2f7bca550 12
Azure.IoT Build 0:6ae2f7bca550 13 #include "azure_uamqp_c/connection.h"
Azure.IoT Build 0:6ae2f7bca550 14 #include "azure_uamqp_c/frame_codec.h"
Azure.IoT Build 0:6ae2f7bca550 15 #include "azure_uamqp_c/amqp_frame_codec.h"
Azure.IoT Build 0:6ae2f7bca550 16 #include "azure_uamqp_c/amqp_definitions.h"
Azure.IoT Build 0:6ae2f7bca550 17 #include "azure_uamqp_c/amqpvalue_to_string.h"
Azure.IoT Build 0:6ae2f7bca550 18
Azure.IoT Build 0:6ae2f7bca550 19 /* Requirements satisfied by the virtue of implementing the ISO:*/
Azure.IoT Build 0:6ae2f7bca550 20 /* Codes_SRS_CONNECTION_01_088: [Any data appearing beyond the protocol header MUST match the version indicated by the protocol header.] */
Azure.IoT Build 0:6ae2f7bca550 21 /* Codes_SRS_CONNECTION_01_015: [Implementations SHOULD NOT expect to be able to reuse open TCP sockets after close performatives have been exchanged.] */
Azure.IoT Build 0:6ae2f7bca550 22
AzureIoTClient 16:22a72cf8e416 23 /* Codes_SRS_CONNECTION_01_087: [The protocol header consists of the upper case ASCII letters "AMQP" followed by a protocol id of zero, followed by three unsigned bytes representing the major, minor, and revision of the protocol version (currently 1 (MAJOR), 0 (MINOR), 0 (REVISION)). In total this is an 8-octet sequence] */
Azure.IoT Build 0:6ae2f7bca550 24 static const unsigned char amqp_header[] = { 'A', 'M', 'Q', 'P', 0, 1, 0, 0 };
Azure.IoT Build 0:6ae2f7bca550 25
Azure.IoT Build 0:6ae2f7bca550 26 typedef enum RECEIVE_FRAME_STATE_TAG
Azure.IoT Build 0:6ae2f7bca550 27 {
AzureIoTClient 4:98007eb79fa8 28 RECEIVE_FRAME_STATE_FRAME_SIZE,
AzureIoTClient 4:98007eb79fa8 29 RECEIVE_FRAME_STATE_FRAME_DATA
Azure.IoT Build 0:6ae2f7bca550 30 } RECEIVE_FRAME_STATE;
Azure.IoT Build 0:6ae2f7bca550 31
Azure.IoT Build 0:6ae2f7bca550 32 typedef struct ENDPOINT_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 33 {
AzureIoTClient 4:98007eb79fa8 34 uint16_t incoming_channel;
AzureIoTClient 4:98007eb79fa8 35 uint16_t outgoing_channel;
AzureIoTClient 4:98007eb79fa8 36 ON_ENDPOINT_FRAME_RECEIVED on_endpoint_frame_received;
AzureIoTClient 4:98007eb79fa8 37 ON_CONNECTION_STATE_CHANGED on_connection_state_changed;
AzureIoTClient 4:98007eb79fa8 38 void* callback_context;
AzureIoTClient 4:98007eb79fa8 39 CONNECTION_HANDLE connection;
Azure.IoT Build 0:6ae2f7bca550 40 } ENDPOINT_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 41
Azure.IoT Build 0:6ae2f7bca550 42 typedef struct CONNECTION_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 43 {
AzureIoTClient 4:98007eb79fa8 44 XIO_HANDLE io;
AzureIoTClient 4:98007eb79fa8 45 size_t header_bytes_received;
AzureIoTClient 4:98007eb79fa8 46 CONNECTION_STATE connection_state;
AzureIoTClient 4:98007eb79fa8 47 FRAME_CODEC_HANDLE frame_codec;
AzureIoTClient 4:98007eb79fa8 48 AMQP_FRAME_CODEC_HANDLE amqp_frame_codec;
AzureIoTClient 4:98007eb79fa8 49 ENDPOINT_INSTANCE** endpoints;
AzureIoTClient 4:98007eb79fa8 50 uint32_t endpoint_count;
AzureIoTClient 4:98007eb79fa8 51 char* host_name;
AzureIoTClient 4:98007eb79fa8 52 char* container_id;
AzureIoTClient 4:98007eb79fa8 53 TICK_COUNTER_HANDLE tick_counter;
AzureIoTClient 4:98007eb79fa8 54 uint32_t remote_max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 55
AzureIoTClient 4:98007eb79fa8 56 ON_SEND_COMPLETE on_send_complete;
AzureIoTClient 4:98007eb79fa8 57 void* on_send_complete_callback_context;
Azure.IoT Build 0:6ae2f7bca550 58
AzureIoTClient 4:98007eb79fa8 59 ON_NEW_ENDPOINT on_new_endpoint;
AzureIoTClient 4:98007eb79fa8 60 void* on_new_endpoint_callback_context;
Azure.IoT Build 0:6ae2f7bca550 61
Azure.IoT Build 0:6ae2f7bca550 62 ON_CONNECTION_STATE_CHANGED on_connection_state_changed;
Azure.IoT Build 0:6ae2f7bca550 63 void* on_connection_state_changed_callback_context;
Azure.IoT Build 0:6ae2f7bca550 64 ON_IO_ERROR on_io_error;
Azure.IoT Build 0:6ae2f7bca550 65 void* on_io_error_callback_context;
Azure.IoT Build 0:6ae2f7bca550 66
AzureIoTClient 4:98007eb79fa8 67 /* options */
AzureIoTClient 4:98007eb79fa8 68 uint32_t max_frame_size;
AzureIoTClient 4:98007eb79fa8 69 uint16_t channel_max;
AzureIoTClient 4:98007eb79fa8 70 milliseconds idle_timeout;
AzureIoTClient 4:98007eb79fa8 71 milliseconds remote_idle_timeout;
Azure.IoT.Build 14:0b0e28c75ded 72 tickcounter_ms_t last_frame_received_time;
Azure.IoT.Build 14:0b0e28c75ded 73 tickcounter_ms_t last_frame_sent_time;
Azure.IoT Build 0:6ae2f7bca550 74
AzureIoTClient 4:98007eb79fa8 75 unsigned int is_underlying_io_open : 1;
AzureIoTClient 4:98007eb79fa8 76 unsigned int idle_timeout_specified : 1;
AzureIoTClient 4:98007eb79fa8 77 unsigned int is_remote_frame_received : 1;
AzureIoTClient 4:98007eb79fa8 78 unsigned int is_trace_on : 1;
Azure.IoT Build 0:6ae2f7bca550 79 } CONNECTION_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 80
Azure.IoT Build 0:6ae2f7bca550 81 /* Codes_SRS_CONNECTION_01_258: [on_connection_state_changed shall be invoked whenever the connection state changes.]*/
Azure.IoT Build 0:6ae2f7bca550 82 static void connection_set_state(CONNECTION_INSTANCE* connection_instance, CONNECTION_STATE connection_state)
Azure.IoT Build 0:6ae2f7bca550 83 {
AzureIoTClient 4:98007eb79fa8 84 uint64_t i;
Azure.IoT Build 0:6ae2f7bca550 85
AzureIoTClient 4:98007eb79fa8 86 CONNECTION_STATE previous_state = connection_instance->connection_state;
AzureIoTClient 4:98007eb79fa8 87 connection_instance->connection_state = connection_state;
Azure.IoT Build 0:6ae2f7bca550 88
Azure.IoT Build 0:6ae2f7bca550 89 /* Codes_SRS_CONNECTION_22_001: [If a connection state changed occurs and a callback is registered the callback shall be called.] */
Azure.IoT Build 0:6ae2f7bca550 90 if (connection_instance->on_connection_state_changed)
Azure.IoT Build 0:6ae2f7bca550 91 {
Azure.IoT Build 0:6ae2f7bca550 92 connection_instance->on_connection_state_changed(connection_instance->on_connection_state_changed_callback_context, connection_state, previous_state);
Azure.IoT Build 0:6ae2f7bca550 93 }
Azure.IoT Build 0:6ae2f7bca550 94
AzureIoTClient 16:22a72cf8e416 95 /* Codes_SRS_CONNECTION_01_260: [Each endpoint's on_connection_state_changed shall be called.] */
AzureIoTClient 4:98007eb79fa8 96 for (i = 0; i < connection_instance->endpoint_count; i++)
AzureIoTClient 4:98007eb79fa8 97 {
AzureIoTClient 4:98007eb79fa8 98 /* Codes_SRS_CONNECTION_01_259: [The callback_context passed in connection_create_endpoint.] */
AzureIoTClient 4:98007eb79fa8 99 connection_instance->endpoints[i]->on_connection_state_changed(connection_instance->endpoints[i]->callback_context, connection_state, previous_state);
AzureIoTClient 4:98007eb79fa8 100 }
Azure.IoT Build 0:6ae2f7bca550 101 }
Azure.IoT Build 0:6ae2f7bca550 102
Azure.IoT Build 0:6ae2f7bca550 103 static int send_header(CONNECTION_INSTANCE* connection_instance)
Azure.IoT Build 0:6ae2f7bca550 104 {
AzureIoTClient 4:98007eb79fa8 105 int result;
Azure.IoT Build 0:6ae2f7bca550 106
AzureIoTClient 16:22a72cf8e416 107 /* Codes_SRS_CONNECTION_01_093: [_ When the client opens a new socket connection to a server, it MUST send a protocol header with the client's preferred protocol version.] */
AzureIoTClient 4:98007eb79fa8 108 /* Codes_SRS_CONNECTION_01_104: [Sending the protocol header shall be done by using xio_send.] */
AzureIoTClient 4:98007eb79fa8 109 if (xio_send(connection_instance->io, amqp_header, sizeof(amqp_header), NULL, NULL) != 0)
AzureIoTClient 4:98007eb79fa8 110 {
AzureIoTClient 4:98007eb79fa8 111 /* Codes_SRS_CONNECTION_01_106: [When sending the protocol header fails, the connection shall be immediately closed.] */
AzureIoTClient 4:98007eb79fa8 112 xio_close(connection_instance->io, NULL, NULL);
Azure.IoT Build 0:6ae2f7bca550 113
AzureIoTClient 4:98007eb79fa8 114 /* Codes_SRS_CONNECTION_01_057: [END In this state it is illegal for either endpoint to write anything more onto the connection. The connection can be safely closed and discarded.] */
AzureIoTClient 4:98007eb79fa8 115 connection_set_state(connection_instance, CONNECTION_STATE_END);
Azure.IoT Build 0:6ae2f7bca550 116
AzureIoTClient 4:98007eb79fa8 117 /* Codes_SRS_CONNECTION_01_105: [When xio_send fails, connection_dowork shall return a non-zero value.] */
AzureIoTClient 19:000ab4e6a2c1 118 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 119 }
AzureIoTClient 4:98007eb79fa8 120 else
AzureIoTClient 4:98007eb79fa8 121 {
AzureIoTClient 4:98007eb79fa8 122 if (connection_instance->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 123 {
AzureIoTClient 16:22a72cf8e416 124 LOG(AZ_LOG_TRACE, LOG_LINE, "-> Header (AMQP 0.1.0.0)");
AzureIoTClient 4:98007eb79fa8 125 }
Azure.IoT Build 0:6ae2f7bca550 126
AzureIoTClient 4:98007eb79fa8 127 /* Codes_SRS_CONNECTION_01_041: [HDR SENT In this state the connection header has been sent to the peer but no connection header has been received.] */
AzureIoTClient 4:98007eb79fa8 128 connection_set_state(connection_instance, CONNECTION_STATE_HDR_SENT);
AzureIoTClient 4:98007eb79fa8 129 result = 0;
AzureIoTClient 4:98007eb79fa8 130 }
Azure.IoT Build 0:6ae2f7bca550 131
AzureIoTClient 4:98007eb79fa8 132 return result;
Azure.IoT Build 0:6ae2f7bca550 133 }
Azure.IoT Build 0:6ae2f7bca550 134
Azure.IoT Build 0:6ae2f7bca550 135 static const char* get_frame_type_as_string(AMQP_VALUE descriptor)
Azure.IoT Build 0:6ae2f7bca550 136 {
AzureIoTClient 4:98007eb79fa8 137 const char* result;
Azure.IoT Build 0:6ae2f7bca550 138
AzureIoTClient 4:98007eb79fa8 139 if (is_open_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 140 {
AzureIoTClient 4:98007eb79fa8 141 result = "[OPEN]";
AzureIoTClient 4:98007eb79fa8 142 }
AzureIoTClient 4:98007eb79fa8 143 else if (is_begin_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 144 {
AzureIoTClient 4:98007eb79fa8 145 result = "[BEGIN]";
AzureIoTClient 4:98007eb79fa8 146 }
AzureIoTClient 4:98007eb79fa8 147 else if (is_attach_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 148 {
AzureIoTClient 4:98007eb79fa8 149 result = "[ATTACH]";
AzureIoTClient 4:98007eb79fa8 150 }
AzureIoTClient 4:98007eb79fa8 151 else if (is_flow_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 152 {
AzureIoTClient 4:98007eb79fa8 153 result = "[FLOW]";
AzureIoTClient 4:98007eb79fa8 154 }
AzureIoTClient 4:98007eb79fa8 155 else if (is_disposition_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 156 {
AzureIoTClient 4:98007eb79fa8 157 result = "[DISPOSITION]";
AzureIoTClient 4:98007eb79fa8 158 }
AzureIoTClient 4:98007eb79fa8 159 else if (is_transfer_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 160 {
AzureIoTClient 4:98007eb79fa8 161 result = "[TRANSFER]";
AzureIoTClient 4:98007eb79fa8 162 }
AzureIoTClient 4:98007eb79fa8 163 else if (is_detach_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 164 {
AzureIoTClient 4:98007eb79fa8 165 result = "[DETACH]";
AzureIoTClient 4:98007eb79fa8 166 }
AzureIoTClient 4:98007eb79fa8 167 else if (is_end_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 168 {
AzureIoTClient 4:98007eb79fa8 169 result = "[END]";
AzureIoTClient 4:98007eb79fa8 170 }
AzureIoTClient 4:98007eb79fa8 171 else if (is_close_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 172 {
AzureIoTClient 4:98007eb79fa8 173 result = "[CLOSE]";
AzureIoTClient 4:98007eb79fa8 174 }
AzureIoTClient 4:98007eb79fa8 175 else
AzureIoTClient 4:98007eb79fa8 176 {
AzureIoTClient 4:98007eb79fa8 177 result = "[Unknown]";
AzureIoTClient 4:98007eb79fa8 178 }
Azure.IoT Build 0:6ae2f7bca550 179
AzureIoTClient 4:98007eb79fa8 180 return result;
Azure.IoT Build 0:6ae2f7bca550 181 }
Azure.IoT Build 0:6ae2f7bca550 182
Azure.IoT Build 5:ae49385aff34 183 static void log_incoming_frame(AMQP_VALUE performative)
Azure.IoT Build 0:6ae2f7bca550 184 {
AzureIoTClient 9:c22db038556c 185 #ifdef NO_LOGGING
AzureIoTClient 9:c22db038556c 186 UNUSED(performative);
AzureIoTClient 9:c22db038556c 187 #else
AzureIoTClient 4:98007eb79fa8 188 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
AzureIoTClient 4:98007eb79fa8 189 if (descriptor != NULL)
AzureIoTClient 4:98007eb79fa8 190 {
AzureIoTClient 16:22a72cf8e416 191 LOG(AZ_LOG_TRACE, 0, "<- ");
AzureIoTClient 16:22a72cf8e416 192 LOG(AZ_LOG_TRACE, 0, (char*)get_frame_type_as_string(descriptor));
AzureIoTClient 4:98007eb79fa8 193 char* performative_as_string = NULL;
AzureIoTClient 16:22a72cf8e416 194 LOG(AZ_LOG_TRACE, LOG_LINE, (performative_as_string = amqpvalue_to_string(performative)));
AzureIoTClient 4:98007eb79fa8 195 if (performative_as_string != NULL)
AzureIoTClient 4:98007eb79fa8 196 {
AzureIoTClient 21:f9c433d8e6ca 197 free(performative_as_string);
AzureIoTClient 4:98007eb79fa8 198 }
AzureIoTClient 4:98007eb79fa8 199 }
AzureIoTClient 9:c22db038556c 200 #endif
Azure.IoT Build 0:6ae2f7bca550 201 }
Azure.IoT Build 0:6ae2f7bca550 202
Azure.IoT Build 5:ae49385aff34 203 static void log_outgoing_frame(AMQP_VALUE performative)
Azure.IoT Build 0:6ae2f7bca550 204 {
AzureIoTClient 9:c22db038556c 205 #ifdef NO_LOGGING
AzureIoTClient 9:c22db038556c 206 UNUSED(performative);
AzureIoTClient 9:c22db038556c 207 #else
AzureIoTClient 4:98007eb79fa8 208 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
AzureIoTClient 4:98007eb79fa8 209 if (descriptor != NULL)
AzureIoTClient 4:98007eb79fa8 210 {
AzureIoTClient 16:22a72cf8e416 211 LOG(AZ_LOG_TRACE, 0, "-> ");
AzureIoTClient 16:22a72cf8e416 212 LOG(AZ_LOG_TRACE, 0, (char*)get_frame_type_as_string(descriptor));
AzureIoTClient 4:98007eb79fa8 213 char* performative_as_string = NULL;
AzureIoTClient 16:22a72cf8e416 214 LOG(AZ_LOG_TRACE, LOG_LINE, (performative_as_string = amqpvalue_to_string(performative)));
AzureIoTClient 4:98007eb79fa8 215 if (performative_as_string != NULL)
AzureIoTClient 4:98007eb79fa8 216 {
AzureIoTClient 21:f9c433d8e6ca 217 free(performative_as_string);
AzureIoTClient 4:98007eb79fa8 218 }
AzureIoTClient 4:98007eb79fa8 219 }
AzureIoTClient 9:c22db038556c 220 #endif
Azure.IoT Build 0:6ae2f7bca550 221 }
Azure.IoT Build 0:6ae2f7bca550 222
Azure.IoT Build 0:6ae2f7bca550 223 static void on_bytes_encoded(void* context, const unsigned char* bytes, size_t length, bool encode_complete)
Azure.IoT Build 0:6ae2f7bca550 224 {
AzureIoTClient 4:98007eb79fa8 225 CONNECTION_INSTANCE* connection_instance = (CONNECTION_INSTANCE*)context;
AzureIoTClient 4:98007eb79fa8 226 if (xio_send(connection_instance->io, bytes, length, encode_complete ? connection_instance->on_send_complete : NULL, connection_instance->on_send_complete_callback_context) != 0)
AzureIoTClient 4:98007eb79fa8 227 {
AzureIoTClient 4:98007eb79fa8 228 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 229 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 230 }
Azure.IoT Build 0:6ae2f7bca550 231 }
Azure.IoT Build 0:6ae2f7bca550 232
Azure.IoT Build 0:6ae2f7bca550 233 static int send_open_frame(CONNECTION_INSTANCE* connection_instance)
Azure.IoT Build 0:6ae2f7bca550 234 {
AzureIoTClient 4:98007eb79fa8 235 int result;
Azure.IoT Build 0:6ae2f7bca550 236
AzureIoTClient 4:98007eb79fa8 237 /* Codes_SRS_CONNECTION_01_151: [The connection max_frame_size setting shall be passed down to the frame_codec when the Open frame is sent.] */
AzureIoTClient 4:98007eb79fa8 238 if (frame_codec_set_max_frame_size(connection_instance->frame_codec, connection_instance->max_frame_size) != 0)
AzureIoTClient 4:98007eb79fa8 239 {
AzureIoTClient 4:98007eb79fa8 240 /* Codes_SRS_CONNECTION_01_207: [If frame_codec_set_max_frame_size fails the connection shall be closed and the state set to END.] */
AzureIoTClient 4:98007eb79fa8 241 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 242 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 243 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 244 }
AzureIoTClient 4:98007eb79fa8 245 else
AzureIoTClient 4:98007eb79fa8 246 {
AzureIoTClient 4:98007eb79fa8 247 /* Codes_SRS_CONNECTION_01_134: [The container id field shall be filled with the container id specified in connection_create.] */
AzureIoTClient 4:98007eb79fa8 248 OPEN_HANDLE open_performative = open_create(connection_instance->container_id);
AzureIoTClient 4:98007eb79fa8 249 if (open_performative == NULL)
AzureIoTClient 4:98007eb79fa8 250 {
AzureIoTClient 4:98007eb79fa8 251 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 4:98007eb79fa8 252 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 253 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 254 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 255 }
AzureIoTClient 4:98007eb79fa8 256 else
AzureIoTClient 4:98007eb79fa8 257 {
AzureIoTClient 4:98007eb79fa8 258 /* Codes_SRS_CONNECTION_01_137: [The max_frame_size connection setting shall be set in the open frame by using open_set_max_frame_size.] */
AzureIoTClient 4:98007eb79fa8 259 if (open_set_max_frame_size(open_performative, connection_instance->max_frame_size) != 0)
AzureIoTClient 4:98007eb79fa8 260 {
AzureIoTClient 4:98007eb79fa8 261 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 4:98007eb79fa8 262 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 263 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 264 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 265 }
AzureIoTClient 4:98007eb79fa8 266 /* Codes_SRS_CONNECTION_01_139: [The channel_max connection setting shall be set in the open frame by using open_set_channel_max.] */
AzureIoTClient 4:98007eb79fa8 267 else if (open_set_channel_max(open_performative, connection_instance->channel_max) != 0)
AzureIoTClient 4:98007eb79fa8 268 {
AzureIoTClient 4:98007eb79fa8 269 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 4:98007eb79fa8 270 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 271 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 272 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 273 }
AzureIoTClient 4:98007eb79fa8 274 /* Codes_SRS_CONNECTION_01_142: [If no idle_timeout value has been specified, no value shall be stamped in the open frame (no call to open_set_idle_time_out shall be made).] */
AzureIoTClient 4:98007eb79fa8 275 else if ((connection_instance->idle_timeout_specified) &&
AzureIoTClient 4:98007eb79fa8 276 /* Codes_SRS_CONNECTION_01_141: [If idle_timeout has been specified by a call to connection_set_idle_timeout, then that value shall be stamped in the open frame.] */
AzureIoTClient 4:98007eb79fa8 277 (open_set_idle_time_out(open_performative, connection_instance->idle_timeout) != 0))
AzureIoTClient 4:98007eb79fa8 278 {
AzureIoTClient 4:98007eb79fa8 279 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 4:98007eb79fa8 280 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 281 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 282 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 283 }
AzureIoTClient 4:98007eb79fa8 284 /* Codes_SRS_CONNECTION_01_136: [If no hostname value has been specified, no value shall be stamped in the open frame (no call to open_set_hostname shall be made).] */
AzureIoTClient 4:98007eb79fa8 285 else if ((connection_instance->host_name != NULL) &&
AzureIoTClient 4:98007eb79fa8 286 /* Codes_SRS_CONNECTION_01_135: [If hostname has been specified by a call to connection_set_hostname, then that value shall be stamped in the open frame.] */
AzureIoTClient 4:98007eb79fa8 287 (open_set_hostname(open_performative, connection_instance->host_name) != 0))
AzureIoTClient 4:98007eb79fa8 288 {
AzureIoTClient 4:98007eb79fa8 289 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 4:98007eb79fa8 290 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 291 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 292 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 293 }
AzureIoTClient 4:98007eb79fa8 294 else
AzureIoTClient 4:98007eb79fa8 295 {
AzureIoTClient 4:98007eb79fa8 296 AMQP_VALUE open_performative_value = amqpvalue_create_open(open_performative);
AzureIoTClient 4:98007eb79fa8 297 if (open_performative_value == NULL)
AzureIoTClient 4:98007eb79fa8 298 {
AzureIoTClient 4:98007eb79fa8 299 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 4:98007eb79fa8 300 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 301 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 302 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 303 }
AzureIoTClient 4:98007eb79fa8 304 else
AzureIoTClient 4:98007eb79fa8 305 {
AzureIoTClient 4:98007eb79fa8 306 /* Codes_SRS_CONNECTION_01_002: [Each AMQP connection begins with an exchange of capabilities and limitations, including the maximum frame size.] */
AzureIoTClient 4:98007eb79fa8 307 /* Codes_SRS_CONNECTION_01_004: [After establishing or accepting a TCP connection and sending the protocol header, each peer MUST send an open frame before sending any other frames.] */
AzureIoTClient 4:98007eb79fa8 308 /* Codes_SRS_CONNECTION_01_005: [The open frame describes the capabilities and limits of that peer.] */
AzureIoTClient 4:98007eb79fa8 309 /* Codes_SRS_CONNECTION_01_205: [Sending the AMQP OPEN frame shall be done by calling amqp_frame_codec_begin_encode_frame with channel number 0, the actual performative payload and 0 as payload_size.] */
AzureIoTClient 4:98007eb79fa8 310 /* Codes_SRS_CONNECTION_01_006: [The open frame can only be sent on channel 0.] */
AzureIoTClient 4:98007eb79fa8 311 connection_instance->on_send_complete = NULL;
AzureIoTClient 4:98007eb79fa8 312 connection_instance->on_send_complete_callback_context = NULL;
AzureIoTClient 4:98007eb79fa8 313 if (amqp_frame_codec_encode_frame(connection_instance->amqp_frame_codec, 0, open_performative_value, NULL, 0, on_bytes_encoded, connection_instance) != 0)
AzureIoTClient 4:98007eb79fa8 314 {
AzureIoTClient 4:98007eb79fa8 315 /* Codes_SRS_CONNECTION_01_206: [If sending the frame fails, the connection shall be closed and state set to END.] */
AzureIoTClient 4:98007eb79fa8 316 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 317 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 318 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 319 }
AzureIoTClient 4:98007eb79fa8 320 else
AzureIoTClient 4:98007eb79fa8 321 {
AzureIoTClient 4:98007eb79fa8 322 if (connection_instance->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 323 {
Azure.IoT Build 5:ae49385aff34 324 log_outgoing_frame(open_performative_value);
AzureIoTClient 4:98007eb79fa8 325 }
Azure.IoT Build 0:6ae2f7bca550 326
AzureIoTClient 4:98007eb79fa8 327 /* Codes_SRS_CONNECTION_01_046: [OPEN SENT In this state the connection headers have been exchanged. An open frame has been sent to the peer but no open frame has yet been received.] */
AzureIoTClient 4:98007eb79fa8 328 connection_set_state(connection_instance, CONNECTION_STATE_OPEN_SENT);
AzureIoTClient 4:98007eb79fa8 329 result = 0;
AzureIoTClient 4:98007eb79fa8 330 }
Azure.IoT Build 0:6ae2f7bca550 331
AzureIoTClient 4:98007eb79fa8 332 amqpvalue_destroy(open_performative_value);
AzureIoTClient 4:98007eb79fa8 333 }
AzureIoTClient 4:98007eb79fa8 334 }
Azure.IoT Build 0:6ae2f7bca550 335
AzureIoTClient 4:98007eb79fa8 336 open_destroy(open_performative);
AzureIoTClient 4:98007eb79fa8 337 }
AzureIoTClient 4:98007eb79fa8 338 }
Azure.IoT Build 0:6ae2f7bca550 339
AzureIoTClient 4:98007eb79fa8 340 return result;
Azure.IoT Build 0:6ae2f7bca550 341 }
Azure.IoT Build 0:6ae2f7bca550 342
Azure.IoT Build 0:6ae2f7bca550 343 static int send_close_frame(CONNECTION_INSTANCE* connection_instance, ERROR_HANDLE error_handle)
Azure.IoT Build 0:6ae2f7bca550 344 {
AzureIoTClient 4:98007eb79fa8 345 int result;
AzureIoTClient 4:98007eb79fa8 346 CLOSE_HANDLE close_performative;
Azure.IoT Build 0:6ae2f7bca550 347
AzureIoTClient 4:98007eb79fa8 348 /* Codes_SRS_CONNECTION_01_217: [The CLOSE frame shall be constructed by using close_create.] */
AzureIoTClient 4:98007eb79fa8 349 close_performative = close_create();
AzureIoTClient 4:98007eb79fa8 350 if (close_performative == NULL)
AzureIoTClient 4:98007eb79fa8 351 {
AzureIoTClient 19:000ab4e6a2c1 352 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 353 }
AzureIoTClient 4:98007eb79fa8 354 else
AzureIoTClient 4:98007eb79fa8 355 {
AzureIoTClient 4:98007eb79fa8 356 if ((error_handle != NULL) &&
AzureIoTClient 4:98007eb79fa8 357 /* Codes_SRS_CONNECTION_01_238: [If set, this field indicates that the connection is being closed due to an error condition.] */
AzureIoTClient 4:98007eb79fa8 358 (close_set_error(close_performative, error_handle) != 0))
AzureIoTClient 4:98007eb79fa8 359 {
AzureIoTClient 19:000ab4e6a2c1 360 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 361 }
AzureIoTClient 4:98007eb79fa8 362 else
AzureIoTClient 4:98007eb79fa8 363 {
AzureIoTClient 4:98007eb79fa8 364 AMQP_VALUE close_performative_value = amqpvalue_create_close(close_performative);
AzureIoTClient 4:98007eb79fa8 365 if (close_performative_value == NULL)
AzureIoTClient 4:98007eb79fa8 366 {
AzureIoTClient 19:000ab4e6a2c1 367 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 368 }
AzureIoTClient 4:98007eb79fa8 369 else
AzureIoTClient 4:98007eb79fa8 370 {
AzureIoTClient 4:98007eb79fa8 371 /* Codes_SRS_CONNECTION_01_215: [Sending the AMQP CLOSE frame shall be done by calling amqp_frame_codec_begin_encode_frame with channel number 0, the actual performative payload and 0 as payload_size.] */
AzureIoTClient 4:98007eb79fa8 372 /* Codes_SRS_CONNECTION_01_013: [However, implementations SHOULD send it on channel 0] */
AzureIoTClient 4:98007eb79fa8 373 connection_instance->on_send_complete = NULL;
AzureIoTClient 4:98007eb79fa8 374 connection_instance->on_send_complete_callback_context = NULL;
AzureIoTClient 4:98007eb79fa8 375 if (amqp_frame_codec_encode_frame(connection_instance->amqp_frame_codec, 0, close_performative_value, NULL, 0, on_bytes_encoded, connection_instance) != 0)
AzureIoTClient 4:98007eb79fa8 376 {
AzureIoTClient 19:000ab4e6a2c1 377 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 378 }
AzureIoTClient 4:98007eb79fa8 379 else
AzureIoTClient 4:98007eb79fa8 380 {
AzureIoTClient 4:98007eb79fa8 381 if (connection_instance->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 382 {
Azure.IoT Build 5:ae49385aff34 383 log_outgoing_frame(close_performative_value);
AzureIoTClient 4:98007eb79fa8 384 }
Azure.IoT Build 5:ae49385aff34 385
AzureIoTClient 4:98007eb79fa8 386 result = 0;
AzureIoTClient 4:98007eb79fa8 387 }
Azure.IoT Build 0:6ae2f7bca550 388
AzureIoTClient 4:98007eb79fa8 389 amqpvalue_destroy(close_performative_value);
AzureIoTClient 4:98007eb79fa8 390 }
AzureIoTClient 4:98007eb79fa8 391 }
Azure.IoT Build 0:6ae2f7bca550 392
AzureIoTClient 4:98007eb79fa8 393 close_destroy(close_performative);
AzureIoTClient 4:98007eb79fa8 394 }
Azure.IoT Build 0:6ae2f7bca550 395
AzureIoTClient 4:98007eb79fa8 396 return result;
Azure.IoT Build 0:6ae2f7bca550 397 }
Azure.IoT Build 0:6ae2f7bca550 398
Azure.IoT Build 0:6ae2f7bca550 399 static void close_connection_with_error(CONNECTION_INSTANCE* connection_instance, const char* condition_value, const char* description)
Azure.IoT Build 0:6ae2f7bca550 400 {
AzureIoTClient 4:98007eb79fa8 401 ERROR_HANDLE error_handle = error_create(condition_value);
AzureIoTClient 4:98007eb79fa8 402 if (error_handle == NULL)
AzureIoTClient 4:98007eb79fa8 403 {
AzureIoTClient 4:98007eb79fa8 404 /* Codes_SRS_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
AzureIoTClient 4:98007eb79fa8 405 (void)xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 406 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 407 }
AzureIoTClient 4:98007eb79fa8 408 else
AzureIoTClient 4:98007eb79fa8 409 {
AzureIoTClient 4:98007eb79fa8 410 /* Codes_SRS_CONNECTION_01_219: [The error description shall be set to an implementation defined string.] */
AzureIoTClient 4:98007eb79fa8 411 if ((error_set_description(error_handle, description) != 0) ||
AzureIoTClient 4:98007eb79fa8 412 (send_close_frame(connection_instance, error_handle) != 0))
AzureIoTClient 4:98007eb79fa8 413 {
AzureIoTClient 4:98007eb79fa8 414 /* Codes_SRS_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
AzureIoTClient 4:98007eb79fa8 415 (void)xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 416 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 417 }
AzureIoTClient 4:98007eb79fa8 418 else
AzureIoTClient 4:98007eb79fa8 419 {
AzureIoTClient 4:98007eb79fa8 420 /* Codes_SRS_CONNECTION_01_213: [When passing the bytes to frame_codec fails, a CLOSE frame shall be sent and the state shall be set to DISCARDING.] */
AzureIoTClient 4:98007eb79fa8 421 /* Codes_SRS_CONNECTION_01_055: [DISCARDING The DISCARDING state is a variant of the CLOSE SENT state where the close is triggered by an error.] */
AzureIoTClient 16:22a72cf8e416 422 /* Codes_SRS_CONNECTION_01_010: [After writing this frame the peer SHOULD continue to read from the connection until it receives the partner's close frame ] */
AzureIoTClient 4:98007eb79fa8 423 connection_set_state(connection_instance, CONNECTION_STATE_DISCARDING);
AzureIoTClient 4:98007eb79fa8 424 }
Azure.IoT Build 0:6ae2f7bca550 425
AzureIoTClient 4:98007eb79fa8 426 error_destroy(error_handle);
AzureIoTClient 4:98007eb79fa8 427 }
Azure.IoT Build 0:6ae2f7bca550 428 }
Azure.IoT Build 0:6ae2f7bca550 429
Azure.IoT Build 0:6ae2f7bca550 430 static ENDPOINT_INSTANCE* find_session_endpoint_by_outgoing_channel(CONNECTION_INSTANCE* connection, uint16_t outgoing_channel)
Azure.IoT Build 0:6ae2f7bca550 431 {
AzureIoTClient 4:98007eb79fa8 432 uint32_t i;
AzureIoTClient 4:98007eb79fa8 433 ENDPOINT_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 434
AzureIoTClient 4:98007eb79fa8 435 for (i = 0; i < connection->endpoint_count; i++)
AzureIoTClient 4:98007eb79fa8 436 {
AzureIoTClient 4:98007eb79fa8 437 if (connection->endpoints[i]->outgoing_channel == outgoing_channel)
AzureIoTClient 4:98007eb79fa8 438 {
AzureIoTClient 4:98007eb79fa8 439 break;
AzureIoTClient 4:98007eb79fa8 440 }
AzureIoTClient 4:98007eb79fa8 441 }
Azure.IoT Build 0:6ae2f7bca550 442
AzureIoTClient 4:98007eb79fa8 443 if (i == connection->endpoint_count)
AzureIoTClient 4:98007eb79fa8 444 {
AzureIoTClient 4:98007eb79fa8 445 result = NULL;
AzureIoTClient 4:98007eb79fa8 446 }
AzureIoTClient 4:98007eb79fa8 447 else
AzureIoTClient 4:98007eb79fa8 448 {
AzureIoTClient 4:98007eb79fa8 449 result = connection->endpoints[i];
AzureIoTClient 4:98007eb79fa8 450 }
Azure.IoT Build 0:6ae2f7bca550 451
AzureIoTClient 4:98007eb79fa8 452 return result;
Azure.IoT Build 0:6ae2f7bca550 453 }
Azure.IoT Build 0:6ae2f7bca550 454
Azure.IoT Build 0:6ae2f7bca550 455 static ENDPOINT_INSTANCE* find_session_endpoint_by_incoming_channel(CONNECTION_INSTANCE* connection, uint16_t incoming_channel)
Azure.IoT Build 0:6ae2f7bca550 456 {
AzureIoTClient 4:98007eb79fa8 457 uint32_t i;
AzureIoTClient 4:98007eb79fa8 458 ENDPOINT_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 459
AzureIoTClient 4:98007eb79fa8 460 for (i = 0; i < connection->endpoint_count; i++)
AzureIoTClient 4:98007eb79fa8 461 {
AzureIoTClient 4:98007eb79fa8 462 if (connection->endpoints[i]->incoming_channel == incoming_channel)
AzureIoTClient 4:98007eb79fa8 463 {
AzureIoTClient 4:98007eb79fa8 464 break;
AzureIoTClient 4:98007eb79fa8 465 }
AzureIoTClient 4:98007eb79fa8 466 }
Azure.IoT Build 0:6ae2f7bca550 467
AzureIoTClient 4:98007eb79fa8 468 if (i == connection->endpoint_count)
AzureIoTClient 4:98007eb79fa8 469 {
AzureIoTClient 4:98007eb79fa8 470 result = NULL;
AzureIoTClient 4:98007eb79fa8 471 }
AzureIoTClient 4:98007eb79fa8 472 else
AzureIoTClient 4:98007eb79fa8 473 {
AzureIoTClient 4:98007eb79fa8 474 result = connection->endpoints[i];
AzureIoTClient 4:98007eb79fa8 475 }
Azure.IoT Build 0:6ae2f7bca550 476
AzureIoTClient 4:98007eb79fa8 477 return result;
Azure.IoT Build 0:6ae2f7bca550 478 }
Azure.IoT Build 0:6ae2f7bca550 479
Azure.IoT Build 0:6ae2f7bca550 480 static int connection_byte_received(CONNECTION_INSTANCE* connection_instance, unsigned char b)
Azure.IoT Build 0:6ae2f7bca550 481 {
AzureIoTClient 4:98007eb79fa8 482 int result;
Azure.IoT Build 0:6ae2f7bca550 483
AzureIoTClient 4:98007eb79fa8 484 switch (connection_instance->connection_state)
AzureIoTClient 4:98007eb79fa8 485 {
AzureIoTClient 4:98007eb79fa8 486 default:
AzureIoTClient 19:000ab4e6a2c1 487 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 488 break;
Azure.IoT Build 0:6ae2f7bca550 489
AzureIoTClient 4:98007eb79fa8 490 /* Codes_SRS_CONNECTION_01_039: [START In this state a connection exists, but nothing has been sent or received. This is the state an implementation would be in immediately after performing a socket connect or socket accept.] */
AzureIoTClient 4:98007eb79fa8 491 case CONNECTION_STATE_START:
Azure.IoT Build 0:6ae2f7bca550 492
AzureIoTClient 4:98007eb79fa8 493 /* Codes_SRS_CONNECTION_01_041: [HDR SENT In this state the connection header has been sent to the peer but no connection header has been received.] */
AzureIoTClient 4:98007eb79fa8 494 case CONNECTION_STATE_HDR_SENT:
AzureIoTClient 4:98007eb79fa8 495 if (b != amqp_header[connection_instance->header_bytes_received])
AzureIoTClient 4:98007eb79fa8 496 {
AzureIoTClient 4:98007eb79fa8 497 /* Codes_SRS_CONNECTION_01_089: [If the incoming and outgoing protocol headers do not match, both peers MUST close their outgoing stream] */
AzureIoTClient 4:98007eb79fa8 498 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 499 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 500 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 501 }
AzureIoTClient 4:98007eb79fa8 502 else
AzureIoTClient 4:98007eb79fa8 503 {
AzureIoTClient 4:98007eb79fa8 504 connection_instance->header_bytes_received++;
AzureIoTClient 4:98007eb79fa8 505 if (connection_instance->header_bytes_received == sizeof(amqp_header))
AzureIoTClient 4:98007eb79fa8 506 {
AzureIoTClient 4:98007eb79fa8 507 if (connection_instance->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 508 {
AzureIoTClient 16:22a72cf8e416 509 LOG(AZ_LOG_TRACE, LOG_LINE, "<- Header (AMQP 0.1.0.0)");
AzureIoTClient 4:98007eb79fa8 510 }
Azure.IoT Build 0:6ae2f7bca550 511
AzureIoTClient 4:98007eb79fa8 512 connection_set_state(connection_instance, CONNECTION_STATE_HDR_EXCH);
Azure.IoT Build 0:6ae2f7bca550 513
AzureIoTClient 4:98007eb79fa8 514 if (send_open_frame(connection_instance) != 0)
AzureIoTClient 4:98007eb79fa8 515 {
AzureIoTClient 4:98007eb79fa8 516 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 517 }
AzureIoTClient 4:98007eb79fa8 518 }
Azure.IoT Build 0:6ae2f7bca550 519
AzureIoTClient 4:98007eb79fa8 520 result = 0;
AzureIoTClient 4:98007eb79fa8 521 }
AzureIoTClient 4:98007eb79fa8 522 break;
Azure.IoT Build 0:6ae2f7bca550 523
AzureIoTClient 4:98007eb79fa8 524 /* Codes_SRS_CONNECTION_01_040: [HDR RCVD In this state the connection header has been received from the peer but a connection header has not been sent.] */
AzureIoTClient 4:98007eb79fa8 525 case CONNECTION_STATE_HDR_RCVD:
Azure.IoT Build 0:6ae2f7bca550 526
AzureIoTClient 4:98007eb79fa8 527 /* Codes_SRS_CONNECTION_01_042: [HDR EXCH In this state the connection header has been sent to the peer and a connection header has been received from the peer.] */
AzureIoTClient 4:98007eb79fa8 528 /* we should not really get into this state, but just in case, we would treat that in the same way as HDR_RCVD */
AzureIoTClient 4:98007eb79fa8 529 case CONNECTION_STATE_HDR_EXCH:
Azure.IoT Build 0:6ae2f7bca550 530
AzureIoTClient 4:98007eb79fa8 531 /* Codes_SRS_CONNECTION_01_045: [OPEN RCVD In this state the connection headers have been exchanged. An open frame has been received from the peer but an open frame has not been sent.] */
AzureIoTClient 4:98007eb79fa8 532 case CONNECTION_STATE_OPEN_RCVD:
Azure.IoT Build 0:6ae2f7bca550 533
AzureIoTClient 4:98007eb79fa8 534 /* Codes_SRS_CONNECTION_01_046: [OPEN SENT In this state the connection headers have been exchanged. An open frame has been sent to the peer but no open frame has yet been received.] */
AzureIoTClient 4:98007eb79fa8 535 case CONNECTION_STATE_OPEN_SENT:
Azure.IoT Build 0:6ae2f7bca550 536
AzureIoTClient 4:98007eb79fa8 537 /* Codes_SRS_CONNECTION_01_048: [OPENED In this state the connection header and the open frame have been both sent and received.] */
AzureIoTClient 4:98007eb79fa8 538 case CONNECTION_STATE_OPENED:
AzureIoTClient 4:98007eb79fa8 539 /* Codes_SRS_CONNECTION_01_212: [After the initial handshake has been done all bytes received from the io instance shall be passed to the frame_codec for decoding by calling frame_codec_receive_bytes.] */
AzureIoTClient 4:98007eb79fa8 540 if (frame_codec_receive_bytes(connection_instance->frame_codec, &b, 1) != 0)
AzureIoTClient 4:98007eb79fa8 541 {
AzureIoTClient 4:98007eb79fa8 542 /* Codes_SRS_CONNECTION_01_218: [The error amqp:internal-error shall be set in the error.condition field of the CLOSE frame.] */
AzureIoTClient 4:98007eb79fa8 543 /* Codes_SRS_CONNECTION_01_219: [The error description shall be set to an implementation defined string.] */
AzureIoTClient 4:98007eb79fa8 544 close_connection_with_error(connection_instance, "amqp:internal-error", "connection_byte_received::frame_codec_receive_bytes failed");
AzureIoTClient 19:000ab4e6a2c1 545 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 546 }
AzureIoTClient 4:98007eb79fa8 547 else
AzureIoTClient 4:98007eb79fa8 548 {
AzureIoTClient 4:98007eb79fa8 549 result = 0;
AzureIoTClient 4:98007eb79fa8 550 }
Azure.IoT Build 0:6ae2f7bca550 551
AzureIoTClient 4:98007eb79fa8 552 break;
AzureIoTClient 4:98007eb79fa8 553 }
AzureIoTClient 4:98007eb79fa8 554
AzureIoTClient 4:98007eb79fa8 555 return result;
Azure.IoT Build 0:6ae2f7bca550 556 }
Azure.IoT Build 0:6ae2f7bca550 557
Azure.IoT Build 0:6ae2f7bca550 558 static void connection_on_bytes_received(void* context, const unsigned char* buffer, size_t size)
Azure.IoT Build 0:6ae2f7bca550 559 {
AzureIoTClient 4:98007eb79fa8 560 size_t i;
Azure.IoT Build 0:6ae2f7bca550 561
AzureIoTClient 4:98007eb79fa8 562 for (i = 0; i < size; i++)
AzureIoTClient 4:98007eb79fa8 563 {
AzureIoTClient 4:98007eb79fa8 564 if (connection_byte_received((CONNECTION_INSTANCE*)context, buffer[i]) != 0)
AzureIoTClient 4:98007eb79fa8 565 {
AzureIoTClient 4:98007eb79fa8 566 break;
AzureIoTClient 4:98007eb79fa8 567 }
AzureIoTClient 4:98007eb79fa8 568 }
Azure.IoT Build 0:6ae2f7bca550 569 }
Azure.IoT Build 0:6ae2f7bca550 570
Azure.IoT Build 0:6ae2f7bca550 571 static void connection_on_io_open_complete(void* context, IO_OPEN_RESULT io_open_result)
Azure.IoT Build 0:6ae2f7bca550 572 {
AzureIoTClient 4:98007eb79fa8 573 CONNECTION_INSTANCE* connection_instance = (CONNECTION_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 574
AzureIoTClient 4:98007eb79fa8 575 if (io_open_result == IO_OPEN_OK)
AzureIoTClient 4:98007eb79fa8 576 {
AzureIoTClient 4:98007eb79fa8 577 /* Codes_SRS_CONNECTION_01_084: [The connection_instance state machine implementing the protocol requirements shall be run as part of connection_dowork.] */
AzureIoTClient 4:98007eb79fa8 578 switch (connection_instance->connection_state)
AzureIoTClient 4:98007eb79fa8 579 {
AzureIoTClient 4:98007eb79fa8 580 default:
AzureIoTClient 4:98007eb79fa8 581 break;
Azure.IoT Build 0:6ae2f7bca550 582
AzureIoTClient 4:98007eb79fa8 583 case CONNECTION_STATE_START:
AzureIoTClient 4:98007eb79fa8 584 /* Codes_SRS_CONNECTION_01_086: [Prior to sending any frames on a connection_instance, each peer MUST start by sending a protocol header that indicates the protocol version used on the connection_instance.] */
AzureIoTClient 4:98007eb79fa8 585 /* Codes_SRS_CONNECTION_01_091: [The AMQP peer which acted in the role of the TCP client (i.e. the peer that actively opened the connection_instance) MUST immediately send its outgoing protocol header on establishment of the TCP connection_instance.] */
AzureIoTClient 4:98007eb79fa8 586 (void)send_header(connection_instance);
AzureIoTClient 4:98007eb79fa8 587 break;
Azure.IoT Build 0:6ae2f7bca550 588
AzureIoTClient 4:98007eb79fa8 589 case CONNECTION_STATE_HDR_SENT:
AzureIoTClient 4:98007eb79fa8 590 case CONNECTION_STATE_OPEN_SENT:
AzureIoTClient 4:98007eb79fa8 591 case CONNECTION_STATE_OPENED:
AzureIoTClient 4:98007eb79fa8 592 break;
Azure.IoT Build 0:6ae2f7bca550 593
AzureIoTClient 4:98007eb79fa8 594 case CONNECTION_STATE_HDR_EXCH:
AzureIoTClient 4:98007eb79fa8 595 /* Codes_SRS_CONNECTION_01_002: [Each AMQP connection_instance begins with an exchange of capabilities and limitations, including the maximum frame size.] */
AzureIoTClient 4:98007eb79fa8 596 /* Codes_SRS_CONNECTION_01_004: [After establishing or accepting a TCP connection_instance and sending the protocol header, each peer MUST send an open frame before sending any other frames.] */
AzureIoTClient 4:98007eb79fa8 597 /* Codes_SRS_CONNECTION_01_005: [The open frame describes the capabilities and limits of that peer.] */
AzureIoTClient 4:98007eb79fa8 598 if (send_open_frame(connection_instance) != 0)
AzureIoTClient 4:98007eb79fa8 599 {
AzureIoTClient 4:98007eb79fa8 600 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 601 }
AzureIoTClient 4:98007eb79fa8 602 break;
Azure.IoT Build 0:6ae2f7bca550 603
AzureIoTClient 4:98007eb79fa8 604 case CONNECTION_STATE_OPEN_RCVD:
AzureIoTClient 4:98007eb79fa8 605 break;
AzureIoTClient 4:98007eb79fa8 606 }
AzureIoTClient 4:98007eb79fa8 607 }
AzureIoTClient 4:98007eb79fa8 608 else
AzureIoTClient 4:98007eb79fa8 609 {
AzureIoTClient 4:98007eb79fa8 610 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 611 }
Azure.IoT Build 0:6ae2f7bca550 612 }
Azure.IoT Build 0:6ae2f7bca550 613
Azure.IoT Build 0:6ae2f7bca550 614 static void connection_on_io_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 615 {
AzureIoTClient 4:98007eb79fa8 616 CONNECTION_INSTANCE* connection_instance = (CONNECTION_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 617
Azure.IoT Build 0:6ae2f7bca550 618 /* Codes_SRS_CONNECTION_22_005: [If the io notifies the connection instance of an IO_STATE_ERROR state and an io error callback is registered, the connection shall call the registered callback.] */
Azure.IoT Build 0:6ae2f7bca550 619 if (connection_instance->on_io_error)
Azure.IoT Build 0:6ae2f7bca550 620 {
Azure.IoT Build 0:6ae2f7bca550 621 connection_instance->on_io_error(connection_instance->on_io_error_callback_context);
Azure.IoT Build 0:6ae2f7bca550 622 }
Azure.IoT Build 0:6ae2f7bca550 623
AzureIoTClient 4:98007eb79fa8 624 if (connection_instance->connection_state != CONNECTION_STATE_END)
AzureIoTClient 4:98007eb79fa8 625 {
AzureIoTClient 4:98007eb79fa8 626 /* Codes_SRS_CONNECTION_01_202: [If the io notifies the connection instance of an IO_STATE_ERROR state the connection shall be closed and the state set to END.] */
AzureIoTClient 4:98007eb79fa8 627 connection_set_state(connection_instance, CONNECTION_STATE_ERROR);
AzureIoTClient 4:98007eb79fa8 628 (void)xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 629 }
Azure.IoT Build 0:6ae2f7bca550 630 }
Azure.IoT Build 0:6ae2f7bca550 631
Azure.IoT Build 0:6ae2f7bca550 632 static void on_empty_amqp_frame_received(void* context, uint16_t channel)
Azure.IoT Build 0:6ae2f7bca550 633 {
AzureIoTClient 6:641a9672db08 634 (void)channel;
AzureIoTClient 6:641a9672db08 635 /* It does not matter on which channel we received the frame */
AzureIoTClient 4:98007eb79fa8 636 CONNECTION_INSTANCE* connection_instance = (CONNECTION_INSTANCE*)context;
AzureIoTClient 6:641a9672db08 637 if (connection_instance->is_trace_on == 1)
AzureIoTClient 6:641a9672db08 638 {
AzureIoTClient 16:22a72cf8e416 639 LOG(AZ_LOG_TRACE, LOG_LINE, "<- Empty frame");
AzureIoTClient 6:641a9672db08 640 }
AzureIoTClient 4:98007eb79fa8 641 if (tickcounter_get_current_ms(connection_instance->tick_counter, &connection_instance->last_frame_received_time) != 0)
AzureIoTClient 4:98007eb79fa8 642 {
AzureIoTClient 4:98007eb79fa8 643 /* error */
AzureIoTClient 4:98007eb79fa8 644 }
Azure.IoT Build 0:6ae2f7bca550 645 }
Azure.IoT Build 0:6ae2f7bca550 646
Azure.IoT Build 0:6ae2f7bca550 647 static void on_amqp_frame_received(void* context, uint16_t channel, AMQP_VALUE performative, const unsigned char* payload_bytes, uint32_t payload_size)
Azure.IoT Build 0:6ae2f7bca550 648 {
AzureIoTClient 6:641a9672db08 649 (void)channel;
AzureIoTClient 4:98007eb79fa8 650 CONNECTION_INSTANCE* connection_instance = (CONNECTION_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 651
AzureIoTClient 4:98007eb79fa8 652 if (tickcounter_get_current_ms(connection_instance->tick_counter, &connection_instance->last_frame_received_time) != 0)
AzureIoTClient 4:98007eb79fa8 653 {
AzureIoTClient 4:98007eb79fa8 654 close_connection_with_error(connection_instance, "amqp:internal-error", "cannot get current tick count");
AzureIoTClient 4:98007eb79fa8 655 }
AzureIoTClient 4:98007eb79fa8 656 else
AzureIoTClient 4:98007eb79fa8 657 {
AzureIoTClient 4:98007eb79fa8 658 if (connection_instance->is_underlying_io_open)
AzureIoTClient 4:98007eb79fa8 659 {
AzureIoTClient 4:98007eb79fa8 660 switch (connection_instance->connection_state)
AzureIoTClient 4:98007eb79fa8 661 {
AzureIoTClient 4:98007eb79fa8 662 default:
AzureIoTClient 4:98007eb79fa8 663 if (performative == NULL)
AzureIoTClient 4:98007eb79fa8 664 {
AzureIoTClient 4:98007eb79fa8 665 /* Codes_SRS_CONNECTION_01_223: [If the on_endpoint_frame_received is called with a NULL performative then the connection shall be closed with the error condition amqp:internal-error and an implementation defined error description.] */
AzureIoTClient 4:98007eb79fa8 666 close_connection_with_error(connection_instance, "amqp:internal-error", "connection_endpoint_frame_received::NULL performative");
AzureIoTClient 4:98007eb79fa8 667 }
AzureIoTClient 4:98007eb79fa8 668 else
AzureIoTClient 4:98007eb79fa8 669 {
AzureIoTClient 4:98007eb79fa8 670 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
AzureIoTClient 4:98007eb79fa8 671 uint64_t performative_ulong;
Azure.IoT Build 0:6ae2f7bca550 672
AzureIoTClient 4:98007eb79fa8 673 if (connection_instance->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 674 {
Azure.IoT Build 5:ae49385aff34 675 log_incoming_frame(performative);
AzureIoTClient 4:98007eb79fa8 676 }
Azure.IoT Build 0:6ae2f7bca550 677
AzureIoTClient 4:98007eb79fa8 678 if (is_open_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 679 {
AzureIoTClient 4:98007eb79fa8 680 if (channel != 0)
AzureIoTClient 4:98007eb79fa8 681 {
AzureIoTClient 4:98007eb79fa8 682 /* Codes_SRS_CONNECTION_01_006: [The open frame can only be sent on channel 0.] */
AzureIoTClient 4:98007eb79fa8 683 /* Codes_SRS_CONNECTION_01_222: [If an Open frame is received in a manner violating the ISO specification, the connection shall be closed with condition amqp:not-allowed and description being an implementation defined string.] */
AzureIoTClient 4:98007eb79fa8 684 close_connection_with_error(connection_instance, "amqp:not-allowed", "OPEN frame received on a channel that is not 0");
AzureIoTClient 4:98007eb79fa8 685 }
Azure.IoT Build 0:6ae2f7bca550 686
AzureIoTClient 4:98007eb79fa8 687 if (connection_instance->connection_state == CONNECTION_STATE_OPENED)
AzureIoTClient 4:98007eb79fa8 688 {
AzureIoTClient 4:98007eb79fa8 689 /* Codes_SRS_CONNECTION_01_239: [If an Open frame is received in the Opened state the connection shall be closed with condition amqp:illegal-state and description being an implementation defined string.] */
AzureIoTClient 4:98007eb79fa8 690 close_connection_with_error(connection_instance, "amqp:illegal-state", "OPEN frame received in the OPENED state");
AzureIoTClient 4:98007eb79fa8 691 }
AzureIoTClient 4:98007eb79fa8 692 else if ((connection_instance->connection_state == CONNECTION_STATE_OPEN_SENT) ||
AzureIoTClient 4:98007eb79fa8 693 (connection_instance->connection_state == CONNECTION_STATE_HDR_EXCH))
AzureIoTClient 4:98007eb79fa8 694 {
AzureIoTClient 4:98007eb79fa8 695 OPEN_HANDLE open_handle;
AzureIoTClient 4:98007eb79fa8 696 if (amqpvalue_get_open(performative, &open_handle) != 0)
AzureIoTClient 4:98007eb79fa8 697 {
AzureIoTClient 4:98007eb79fa8 698 /* Codes_SRS_CONNECTION_01_143: [If any of the values in the received open frame are invalid then the connection shall be closed.] */
AzureIoTClient 4:98007eb79fa8 699 /* Codes_SRS_CONNECTION_01_220: [The error amqp:invalid-field shall be set in the error.condition field of the CLOSE frame.] */
AzureIoTClient 4:98007eb79fa8 700 close_connection_with_error(connection_instance, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing OPEN frame");
AzureIoTClient 4:98007eb79fa8 701 }
AzureIoTClient 4:98007eb79fa8 702 else
AzureIoTClient 4:98007eb79fa8 703 {
AzureIoTClient 4:98007eb79fa8 704 (void)open_get_idle_time_out(open_handle, &connection_instance->remote_idle_timeout);
AzureIoTClient 4:98007eb79fa8 705 if ((open_get_max_frame_size(open_handle, &connection_instance->remote_max_frame_size) != 0) ||
AzureIoTClient 4:98007eb79fa8 706 /* Codes_SRS_CONNECTION_01_167: [Both peers MUST accept frames of up to 512 (MIN-MAX-FRAME-SIZE) octets.] */
AzureIoTClient 4:98007eb79fa8 707 (connection_instance->remote_max_frame_size < 512))
AzureIoTClient 4:98007eb79fa8 708 {
AzureIoTClient 4:98007eb79fa8 709 /* Codes_SRS_CONNECTION_01_143: [If any of the values in the received open frame are invalid then the connection shall be closed.] */
AzureIoTClient 4:98007eb79fa8 710 /* Codes_SRS_CONNECTION_01_220: [The error amqp:invalid-field shall be set in the error.condition field of the CLOSE frame.] */
AzureIoTClient 4:98007eb79fa8 711 close_connection_with_error(connection_instance, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing OPEN frame");
AzureIoTClient 4:98007eb79fa8 712 }
AzureIoTClient 4:98007eb79fa8 713 else
AzureIoTClient 4:98007eb79fa8 714 {
AzureIoTClient 4:98007eb79fa8 715 if (connection_instance->connection_state == CONNECTION_STATE_OPEN_SENT)
AzureIoTClient 4:98007eb79fa8 716 {
AzureIoTClient 4:98007eb79fa8 717 connection_set_state(connection_instance, CONNECTION_STATE_OPENED);
AzureIoTClient 4:98007eb79fa8 718 }
AzureIoTClient 4:98007eb79fa8 719 else
AzureIoTClient 4:98007eb79fa8 720 {
AzureIoTClient 4:98007eb79fa8 721 if (send_open_frame(connection_instance) != 0)
AzureIoTClient 4:98007eb79fa8 722 {
AzureIoTClient 4:98007eb79fa8 723 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 724 }
AzureIoTClient 4:98007eb79fa8 725 else
AzureIoTClient 4:98007eb79fa8 726 {
AzureIoTClient 4:98007eb79fa8 727 connection_set_state(connection_instance, CONNECTION_STATE_OPENED);
AzureIoTClient 4:98007eb79fa8 728 }
AzureIoTClient 4:98007eb79fa8 729 }
AzureIoTClient 4:98007eb79fa8 730 }
Azure.IoT Build 0:6ae2f7bca550 731
AzureIoTClient 4:98007eb79fa8 732 open_destroy(open_handle);
AzureIoTClient 4:98007eb79fa8 733 }
AzureIoTClient 4:98007eb79fa8 734 }
AzureIoTClient 4:98007eb79fa8 735 else
AzureIoTClient 4:98007eb79fa8 736 {
AzureIoTClient 4:98007eb79fa8 737 /* do nothing for now ... */
AzureIoTClient 4:98007eb79fa8 738 }
AzureIoTClient 4:98007eb79fa8 739 }
AzureIoTClient 4:98007eb79fa8 740 else if (is_close_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 741 {
AzureIoTClient 4:98007eb79fa8 742 /* Codes_SRS_CONNECTION_01_012: [A close frame MAY be received on any channel up to the maximum channel number negotiated in open.] */
AzureIoTClient 4:98007eb79fa8 743 /* Codes_SRS_CONNECTION_01_242: [The connection module shall accept CLOSE frames even if they have extra payload bytes besides the Close performative.] */
Azure.IoT Build 0:6ae2f7bca550 744
AzureIoTClient 4:98007eb79fa8 745 /* Codes_SRS_CONNECTION_01_225: [HDR_RCVD HDR OPEN] */
AzureIoTClient 4:98007eb79fa8 746 if ((connection_instance->connection_state == CONNECTION_STATE_HDR_RCVD) ||
AzureIoTClient 4:98007eb79fa8 747 /* Codes_SRS_CONNECTION_01_227: [HDR_EXCH OPEN OPEN] */
AzureIoTClient 4:98007eb79fa8 748 (connection_instance->connection_state == CONNECTION_STATE_HDR_EXCH) ||
AzureIoTClient 4:98007eb79fa8 749 /* Codes_SRS_CONNECTION_01_228: [OPEN_RCVD OPEN *] */
AzureIoTClient 4:98007eb79fa8 750 (connection_instance->connection_state == CONNECTION_STATE_OPEN_RCVD) ||
AzureIoTClient 4:98007eb79fa8 751 /* Codes_SRS_CONNECTION_01_235: [CLOSE_SENT - * TCP Close for Write] */
AzureIoTClient 4:98007eb79fa8 752 (connection_instance->connection_state == CONNECTION_STATE_CLOSE_SENT) ||
AzureIoTClient 4:98007eb79fa8 753 /* Codes_SRS_CONNECTION_01_236: [DISCARDING - * TCP Close for Write] */
AzureIoTClient 4:98007eb79fa8 754 (connection_instance->connection_state == CONNECTION_STATE_DISCARDING))
AzureIoTClient 4:98007eb79fa8 755 {
AzureIoTClient 4:98007eb79fa8 756 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 757 }
AzureIoTClient 4:98007eb79fa8 758 else
AzureIoTClient 4:98007eb79fa8 759 {
AzureIoTClient 4:98007eb79fa8 760 CLOSE_HANDLE close_handle;
Azure.IoT Build 0:6ae2f7bca550 761
AzureIoTClient 4:98007eb79fa8 762 /* Codes_SRS_CONNECTION_01_012: [A close frame MAY be received on any channel up to the maximum channel number negotiated in open.] */
AzureIoTClient 4:98007eb79fa8 763 if (channel > connection_instance->channel_max)
AzureIoTClient 4:98007eb79fa8 764 {
AzureIoTClient 4:98007eb79fa8 765 close_connection_with_error(connection_instance, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing CLOSE frame");
AzureIoTClient 4:98007eb79fa8 766 }
AzureIoTClient 4:98007eb79fa8 767 else
AzureIoTClient 4:98007eb79fa8 768 {
AzureIoTClient 4:98007eb79fa8 769 if (amqpvalue_get_close(performative, &close_handle) != 0)
AzureIoTClient 4:98007eb79fa8 770 {
AzureIoTClient 4:98007eb79fa8 771 close_connection_with_error(connection_instance, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing CLOSE frame");
AzureIoTClient 4:98007eb79fa8 772 }
AzureIoTClient 4:98007eb79fa8 773 else
AzureIoTClient 4:98007eb79fa8 774 {
AzureIoTClient 4:98007eb79fa8 775 close_destroy(close_handle);
Azure.IoT Build 0:6ae2f7bca550 776
AzureIoTClient 4:98007eb79fa8 777 connection_set_state(connection_instance, CONNECTION_STATE_CLOSE_RCVD);
Azure.IoT Build 0:6ae2f7bca550 778
AzureIoTClient 4:98007eb79fa8 779 (void)send_close_frame(connection_instance, NULL);
AzureIoTClient 4:98007eb79fa8 780 /* Codes_SRS_CONNECTION_01_214: [If the close frame cannot be constructed or sent, the connection shall be closed and set to the END state.] */
AzureIoTClient 4:98007eb79fa8 781 (void)xio_close(connection_instance->io, NULL, NULL);
Azure.IoT Build 0:6ae2f7bca550 782
AzureIoTClient 4:98007eb79fa8 783 connection_set_state(connection_instance, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 784 }
AzureIoTClient 4:98007eb79fa8 785 }
AzureIoTClient 4:98007eb79fa8 786 }
AzureIoTClient 4:98007eb79fa8 787 }
AzureIoTClient 4:98007eb79fa8 788 else
AzureIoTClient 4:98007eb79fa8 789 {
AzureIoTClient 4:98007eb79fa8 790 amqpvalue_get_ulong(descriptor, &performative_ulong);
Azure.IoT Build 0:6ae2f7bca550 791
AzureIoTClient 4:98007eb79fa8 792 switch (performative_ulong)
AzureIoTClient 4:98007eb79fa8 793 {
AzureIoTClient 4:98007eb79fa8 794 default:
AzureIoTClient 16:22a72cf8e416 795 LOG(AZ_LOG_ERROR, LOG_LINE, "Bad performative: %02x", performative);
AzureIoTClient 4:98007eb79fa8 796 break;
Azure.IoT Build 0:6ae2f7bca550 797
AzureIoTClient 4:98007eb79fa8 798 case AMQP_BEGIN:
AzureIoTClient 4:98007eb79fa8 799 {
AzureIoTClient 4:98007eb79fa8 800 BEGIN_HANDLE begin;
AzureIoTClient 4:98007eb79fa8 801 amqpvalue_get_begin(performative, &begin);
Azure.IoT Build 0:6ae2f7bca550 802
AzureIoTClient 4:98007eb79fa8 803 if (begin == NULL)
AzureIoTClient 4:98007eb79fa8 804 {
AzureIoTClient 4:98007eb79fa8 805 /* error */
AzureIoTClient 4:98007eb79fa8 806 }
AzureIoTClient 4:98007eb79fa8 807 else
AzureIoTClient 4:98007eb79fa8 808 {
AzureIoTClient 4:98007eb79fa8 809 uint16_t remote_channel;
AzureIoTClient 4:98007eb79fa8 810 ENDPOINT_HANDLE new_endpoint = NULL;
AzureIoTClient 4:98007eb79fa8 811 bool remote_begin = false;
Azure.IoT Build 0:6ae2f7bca550 812
AzureIoTClient 4:98007eb79fa8 813 if (begin_get_remote_channel(begin, &remote_channel) != 0)
AzureIoTClient 4:98007eb79fa8 814 {
AzureIoTClient 4:98007eb79fa8 815 remote_begin = true;
AzureIoTClient 4:98007eb79fa8 816 if (connection_instance->on_new_endpoint != NULL)
AzureIoTClient 4:98007eb79fa8 817 {
AzureIoTClient 4:98007eb79fa8 818 new_endpoint = connection_create_endpoint(connection_instance);
AzureIoTClient 4:98007eb79fa8 819 if (!connection_instance->on_new_endpoint(connection_instance->on_new_endpoint_callback_context, new_endpoint))
AzureIoTClient 4:98007eb79fa8 820 {
AzureIoTClient 4:98007eb79fa8 821 connection_destroy_endpoint(new_endpoint);
AzureIoTClient 4:98007eb79fa8 822 new_endpoint = NULL;
AzureIoTClient 4:98007eb79fa8 823 }
AzureIoTClient 4:98007eb79fa8 824 }
AzureIoTClient 4:98007eb79fa8 825 }
Azure.IoT Build 0:6ae2f7bca550 826
AzureIoTClient 4:98007eb79fa8 827 if (!remote_begin)
AzureIoTClient 4:98007eb79fa8 828 {
AzureIoTClient 4:98007eb79fa8 829 ENDPOINT_INSTANCE* session_endpoint = find_session_endpoint_by_outgoing_channel(connection_instance, remote_channel);
AzureIoTClient 4:98007eb79fa8 830 if (session_endpoint == NULL)
AzureIoTClient 4:98007eb79fa8 831 {
AzureIoTClient 4:98007eb79fa8 832 /* error */
AzureIoTClient 4:98007eb79fa8 833 }
AzureIoTClient 4:98007eb79fa8 834 else
AzureIoTClient 4:98007eb79fa8 835 {
AzureIoTClient 4:98007eb79fa8 836 session_endpoint->incoming_channel = channel;
AzureIoTClient 4:98007eb79fa8 837 session_endpoint->on_endpoint_frame_received(session_endpoint->callback_context, performative, payload_size, payload_bytes);
AzureIoTClient 4:98007eb79fa8 838 }
AzureIoTClient 4:98007eb79fa8 839 }
AzureIoTClient 4:98007eb79fa8 840 else
AzureIoTClient 4:98007eb79fa8 841 {
Azure.IoT Build 0:6ae2f7bca550 842 if (new_endpoint != NULL)
Azure.IoT Build 0:6ae2f7bca550 843 {
Azure.IoT Build 0:6ae2f7bca550 844 new_endpoint->incoming_channel = channel;
Azure.IoT Build 0:6ae2f7bca550 845 new_endpoint->on_endpoint_frame_received(new_endpoint->callback_context, performative, payload_size, payload_bytes);
Azure.IoT Build 0:6ae2f7bca550 846 }
AzureIoTClient 4:98007eb79fa8 847 }
Azure.IoT Build 0:6ae2f7bca550 848
AzureIoTClient 4:98007eb79fa8 849 begin_destroy(begin);
AzureIoTClient 4:98007eb79fa8 850 }
Azure.IoT Build 0:6ae2f7bca550 851
AzureIoTClient 4:98007eb79fa8 852 break;
AzureIoTClient 4:98007eb79fa8 853 }
Azure.IoT Build 0:6ae2f7bca550 854
AzureIoTClient 4:98007eb79fa8 855 case AMQP_FLOW:
AzureIoTClient 4:98007eb79fa8 856 case AMQP_TRANSFER:
AzureIoTClient 4:98007eb79fa8 857 case AMQP_DISPOSITION:
AzureIoTClient 4:98007eb79fa8 858 case AMQP_END:
AzureIoTClient 4:98007eb79fa8 859 case AMQP_ATTACH:
AzureIoTClient 4:98007eb79fa8 860 case AMQP_DETACH:
AzureIoTClient 4:98007eb79fa8 861 {
AzureIoTClient 4:98007eb79fa8 862 ENDPOINT_INSTANCE* session_endpoint = find_session_endpoint_by_incoming_channel(connection_instance, channel);
AzureIoTClient 4:98007eb79fa8 863 if (session_endpoint == NULL)
AzureIoTClient 4:98007eb79fa8 864 {
AzureIoTClient 4:98007eb79fa8 865 /* error */
AzureIoTClient 4:98007eb79fa8 866 }
AzureIoTClient 4:98007eb79fa8 867 else
AzureIoTClient 4:98007eb79fa8 868 {
AzureIoTClient 4:98007eb79fa8 869 session_endpoint->on_endpoint_frame_received(session_endpoint->callback_context, performative, payload_size, payload_bytes);
AzureIoTClient 4:98007eb79fa8 870 }
Azure.IoT Build 0:6ae2f7bca550 871
AzureIoTClient 4:98007eb79fa8 872 break;
AzureIoTClient 4:98007eb79fa8 873 }
AzureIoTClient 4:98007eb79fa8 874 }
AzureIoTClient 4:98007eb79fa8 875 }
AzureIoTClient 4:98007eb79fa8 876 }
AzureIoTClient 4:98007eb79fa8 877 break;
Azure.IoT Build 0:6ae2f7bca550 878
AzureIoTClient 4:98007eb79fa8 879 case CONNECTION_STATE_START:
AzureIoTClient 4:98007eb79fa8 880 /* Codes_SRS_CONNECTION_01_224: [START HDR HDR] */
AzureIoTClient 4:98007eb79fa8 881 case CONNECTION_STATE_HDR_SENT:
AzureIoTClient 4:98007eb79fa8 882 /* Codes_SRS_CONNECTION_01_226: [HDR_SENT OPEN HDR] */
AzureIoTClient 4:98007eb79fa8 883 case CONNECTION_STATE_OPEN_PIPE:
AzureIoTClient 4:98007eb79fa8 884 /* Codes_SRS_CONNECTION_01_230: [OPEN_PIPE ** HDR] */
AzureIoTClient 4:98007eb79fa8 885 case CONNECTION_STATE_OC_PIPE:
AzureIoTClient 4:98007eb79fa8 886 /* Codes_SRS_CONNECTION_01_232: [OC_PIPE - HDR TCP Close for Write] */
AzureIoTClient 4:98007eb79fa8 887 case CONNECTION_STATE_CLOSE_RCVD:
AzureIoTClient 4:98007eb79fa8 888 /* Codes_SRS_CONNECTION_01_234: [CLOSE_RCVD * - TCP Close for Read] */
AzureIoTClient 4:98007eb79fa8 889 case CONNECTION_STATE_END:
AzureIoTClient 4:98007eb79fa8 890 /* Codes_SRS_CONNECTION_01_237: [END - - TCP Close] */
AzureIoTClient 4:98007eb79fa8 891 xio_close(connection_instance->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 892 break;
AzureIoTClient 4:98007eb79fa8 893 }
AzureIoTClient 4:98007eb79fa8 894 }
AzureIoTClient 4:98007eb79fa8 895 }
Azure.IoT Build 0:6ae2f7bca550 896 }
Azure.IoT Build 0:6ae2f7bca550 897
Azure.IoT Build 0:6ae2f7bca550 898 static void frame_codec_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 899 {
AzureIoTClient 6:641a9672db08 900 /* Bug: some error handling should happen here
AzureIoTClient 6:641a9672db08 901 Filed: uAMQP: frame_codec error and amqp_frame_codec_error should handle the errors */
AzureIoTClient 6:641a9672db08 902 (void)context;
Azure.IoT Build 0:6ae2f7bca550 903 }
Azure.IoT Build 0:6ae2f7bca550 904
Azure.IoT Build 0:6ae2f7bca550 905 static void amqp_frame_codec_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 906 {
AzureIoTClient 6:641a9672db08 907 /* Bug: some error handling should happen here
AzureIoTClient 6:641a9672db08 908 Filed: uAMQP: frame_codec error and amqp_frame_codec_error should handle the errors */
AzureIoTClient 6:641a9672db08 909 (void)context;
Azure.IoT Build 0:6ae2f7bca550 910 }
Azure.IoT Build 0:6ae2f7bca550 911
Azure.IoT Build 0:6ae2f7bca550 912 /* Codes_SRS_CONNECTION_01_001: [connection_create shall open a new connection to a specified host/port.] */
Azure.IoT Build 0:6ae2f7bca550 913 CONNECTION_HANDLE connection_create(XIO_HANDLE xio, const char* hostname, const char* container_id, ON_NEW_ENDPOINT on_new_endpoint, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 914 {
Azure.IoT Build 5:ae49385aff34 915 return connection_create2(xio, hostname, container_id, on_new_endpoint, callback_context, NULL, NULL, NULL, NULL);
Azure.IoT Build 0:6ae2f7bca550 916 }
Azure.IoT Build 0:6ae2f7bca550 917
Azure.IoT Build 0:6ae2f7bca550 918 /* Codes_SRS_CONNECTION_01_001: [connection_create shall open a new connection to a specified host/port.] */
Azure.IoT Build 0:6ae2f7bca550 919 /* Codes_SRS_CONNECTION_22_002: [connection_create shall allow registering connections state and io error callbacks.] */
Azure.IoT Build 5:ae49385aff34 920 CONNECTION_HANDLE connection_create2(XIO_HANDLE xio, const char* hostname, const char* container_id, ON_NEW_ENDPOINT on_new_endpoint, void* callback_context, ON_CONNECTION_STATE_CHANGED on_connection_state_changed, void* on_connection_state_changed_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
Azure.IoT Build 0:6ae2f7bca550 921 {
AzureIoTClient 4:98007eb79fa8 922 CONNECTION_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 923
AzureIoTClient 4:98007eb79fa8 924 if ((xio == NULL) ||
AzureIoTClient 4:98007eb79fa8 925 (container_id == NULL))
AzureIoTClient 4:98007eb79fa8 926 {
AzureIoTClient 4:98007eb79fa8 927 /* Codes_SRS_CONNECTION_01_071: [If xio or container_id is NULL, connection_create shall return NULL.] */
AzureIoTClient 4:98007eb79fa8 928 result = NULL;
AzureIoTClient 4:98007eb79fa8 929 }
AzureIoTClient 4:98007eb79fa8 930 else
AzureIoTClient 4:98007eb79fa8 931 {
AzureIoTClient 21:f9c433d8e6ca 932 result = (CONNECTION_INSTANCE*)malloc(sizeof(CONNECTION_INSTANCE));
AzureIoTClient 4:98007eb79fa8 933 /* Codes_SRS_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
AzureIoTClient 4:98007eb79fa8 934 if (result != NULL)
AzureIoTClient 4:98007eb79fa8 935 {
AzureIoTClient 4:98007eb79fa8 936 result->io = xio;
Azure.IoT Build 0:6ae2f7bca550 937
AzureIoTClient 4:98007eb79fa8 938 /* Codes_SRS_CONNECTION_01_082: [connection_create shall allocate a new frame_codec instance to be used for frame encoding/decoding.] */
Azure.IoT Build 5:ae49385aff34 939 result->frame_codec = frame_codec_create(frame_codec_error, result);
AzureIoTClient 4:98007eb79fa8 940 if (result->frame_codec == NULL)
AzureIoTClient 4:98007eb79fa8 941 {
AzureIoTClient 4:98007eb79fa8 942 /* Codes_SRS_CONNECTION_01_083: [If frame_codec_create fails then connection_create shall return NULL.] */
AzureIoTClient 21:f9c433d8e6ca 943 free(result);
AzureIoTClient 4:98007eb79fa8 944 result = NULL;
AzureIoTClient 4:98007eb79fa8 945 }
AzureIoTClient 4:98007eb79fa8 946 else
AzureIoTClient 4:98007eb79fa8 947 {
AzureIoTClient 4:98007eb79fa8 948 result->amqp_frame_codec = amqp_frame_codec_create(result->frame_codec, on_amqp_frame_received, on_empty_amqp_frame_received, amqp_frame_codec_error, result);
AzureIoTClient 4:98007eb79fa8 949 if (result->amqp_frame_codec == NULL)
AzureIoTClient 4:98007eb79fa8 950 {
AzureIoTClient 4:98007eb79fa8 951 /* Codes_SRS_CONNECTION_01_108: [If amqp_frame_codec_create fails, connection_create shall return NULL.] */
AzureIoTClient 4:98007eb79fa8 952 frame_codec_destroy(result->frame_codec);
AzureIoTClient 21:f9c433d8e6ca 953 free(result);
AzureIoTClient 4:98007eb79fa8 954 result = NULL;
AzureIoTClient 4:98007eb79fa8 955 }
AzureIoTClient 4:98007eb79fa8 956 else
AzureIoTClient 4:98007eb79fa8 957 {
AzureIoTClient 4:98007eb79fa8 958 if (hostname != NULL)
AzureIoTClient 4:98007eb79fa8 959 {
AzureIoTClient 23:1111ee8bcba4 960 size_t hostname_length = strlen(hostname);
AzureIoTClient 23:1111ee8bcba4 961 result->host_name = (char*)malloc(hostname_length + 1);
AzureIoTClient 4:98007eb79fa8 962 if (result->host_name == NULL)
AzureIoTClient 4:98007eb79fa8 963 {
AzureIoTClient 4:98007eb79fa8 964 /* Codes_SRS_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
AzureIoTClient 4:98007eb79fa8 965 amqp_frame_codec_destroy(result->amqp_frame_codec);
AzureIoTClient 4:98007eb79fa8 966 frame_codec_destroy(result->frame_codec);
AzureIoTClient 21:f9c433d8e6ca 967 free(result);
AzureIoTClient 4:98007eb79fa8 968 result = NULL;
AzureIoTClient 4:98007eb79fa8 969 }
AzureIoTClient 4:98007eb79fa8 970 else
AzureIoTClient 4:98007eb79fa8 971 {
AzureIoTClient 23:1111ee8bcba4 972 (void)memcpy(result->host_name, hostname, hostname_length + 1);
AzureIoTClient 4:98007eb79fa8 973 }
AzureIoTClient 4:98007eb79fa8 974 }
AzureIoTClient 4:98007eb79fa8 975 else
AzureIoTClient 4:98007eb79fa8 976 {
AzureIoTClient 4:98007eb79fa8 977 result->host_name = NULL;
AzureIoTClient 4:98007eb79fa8 978 }
Azure.IoT Build 0:6ae2f7bca550 979
AzureIoTClient 4:98007eb79fa8 980 if (result != NULL)
AzureIoTClient 4:98007eb79fa8 981 {
AzureIoTClient 23:1111ee8bcba4 982 size_t container_id_length = strlen(container_id);
AzureIoTClient 23:1111ee8bcba4 983 result->container_id = (char*)malloc(container_id_length + 1);
AzureIoTClient 4:98007eb79fa8 984 if (result->container_id == NULL)
AzureIoTClient 4:98007eb79fa8 985 {
AzureIoTClient 4:98007eb79fa8 986 /* Codes_SRS_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
AzureIoTClient 21:f9c433d8e6ca 987 free(result->host_name);
AzureIoTClient 4:98007eb79fa8 988 amqp_frame_codec_destroy(result->amqp_frame_codec);
AzureIoTClient 4:98007eb79fa8 989 frame_codec_destroy(result->frame_codec);
AzureIoTClient 21:f9c433d8e6ca 990 free(result);
AzureIoTClient 4:98007eb79fa8 991 result = NULL;
AzureIoTClient 4:98007eb79fa8 992 }
AzureIoTClient 4:98007eb79fa8 993 else
AzureIoTClient 4:98007eb79fa8 994 {
AzureIoTClient 4:98007eb79fa8 995 result->tick_counter = tickcounter_create();
AzureIoTClient 4:98007eb79fa8 996 if (result->tick_counter == NULL)
AzureIoTClient 4:98007eb79fa8 997 {
AzureIoTClient 21:f9c433d8e6ca 998 free(result->container_id);
AzureIoTClient 21:f9c433d8e6ca 999 free(result->host_name);
AzureIoTClient 4:98007eb79fa8 1000 amqp_frame_codec_destroy(result->amqp_frame_codec);
AzureIoTClient 4:98007eb79fa8 1001 frame_codec_destroy(result->frame_codec);
AzureIoTClient 21:f9c433d8e6ca 1002 free(result);
AzureIoTClient 4:98007eb79fa8 1003 result = NULL;
AzureIoTClient 4:98007eb79fa8 1004 }
AzureIoTClient 4:98007eb79fa8 1005 else
AzureIoTClient 4:98007eb79fa8 1006 {
AzureIoTClient 23:1111ee8bcba4 1007 (void)memcpy(result->container_id, container_id, container_id_length + 1);
Azure.IoT Build 0:6ae2f7bca550 1008
AzureIoTClient 4:98007eb79fa8 1009 /* Codes_SRS_CONNECTION_01_173: [<field name="max-frame-size" type="uint" default="4294967295"/>] */
AzureIoTClient 4:98007eb79fa8 1010 result->max_frame_size = 4294967295u;
AzureIoTClient 4:98007eb79fa8 1011 /* Codes: [<field name="channel-max" type="ushort" default="65535"/>] */
AzureIoTClient 4:98007eb79fa8 1012 result->channel_max = 65535;
Azure.IoT Build 0:6ae2f7bca550 1013
AzureIoTClient 4:98007eb79fa8 1014 /* Codes_SRS_CONNECTION_01_175: [<field name="idle-time-out" type="milliseconds"/>] */
AzureIoTClient 4:98007eb79fa8 1015 /* Codes_SRS_CONNECTION_01_192: [A value of zero is the same as if it was not set (null).] */
AzureIoTClient 4:98007eb79fa8 1016 result->idle_timeout = 0;
AzureIoTClient 4:98007eb79fa8 1017 result->remote_idle_timeout = 0;
Azure.IoT Build 0:6ae2f7bca550 1018
AzureIoTClient 4:98007eb79fa8 1019 result->endpoint_count = 0;
AzureIoTClient 4:98007eb79fa8 1020 result->endpoints = NULL;
AzureIoTClient 4:98007eb79fa8 1021 result->header_bytes_received = 0;
AzureIoTClient 4:98007eb79fa8 1022 result->is_remote_frame_received = 0;
Azure.IoT Build 0:6ae2f7bca550 1023
AzureIoTClient 4:98007eb79fa8 1024 result->is_underlying_io_open = 0;
AzureIoTClient 4:98007eb79fa8 1025 result->remote_max_frame_size = 512;
AzureIoTClient 4:98007eb79fa8 1026 result->is_trace_on = 0;
Azure.IoT Build 0:6ae2f7bca550 1027
AzureIoTClient 4:98007eb79fa8 1028 /* Mark that settings have not yet been set by the user */
AzureIoTClient 4:98007eb79fa8 1029 result->idle_timeout_specified = 0;
Azure.IoT Build 0:6ae2f7bca550 1030
AzureIoTClient 4:98007eb79fa8 1031 result->on_new_endpoint = on_new_endpoint;
AzureIoTClient 4:98007eb79fa8 1032 result->on_new_endpoint_callback_context = callback_context;
Azure.IoT Build 0:6ae2f7bca550 1033
Azure.IoT Build 0:6ae2f7bca550 1034 result->on_io_error = on_io_error;
Azure.IoT Build 0:6ae2f7bca550 1035 result->on_io_error_callback_context = on_io_error_context;
Azure.IoT Build 0:6ae2f7bca550 1036 result->on_connection_state_changed = on_connection_state_changed;
Azure.IoT Build 0:6ae2f7bca550 1037 result->on_connection_state_changed_callback_context = on_connection_state_changed_context;
Azure.IoT Build 0:6ae2f7bca550 1038
AzureIoTClient 20:206846c14c80 1039 if (tickcounter_get_current_ms(result->tick_counter, &result->last_frame_received_time) != 0)
AzureIoTClient 20:206846c14c80 1040 {
AzureIoTClient 20:206846c14c80 1041 LogError("Could not retrieve time for last frame received time");
AzureIoTClient 20:206846c14c80 1042 tickcounter_destroy(result->tick_counter);
AzureIoTClient 21:f9c433d8e6ca 1043 free(result->container_id);
AzureIoTClient 21:f9c433d8e6ca 1044 free(result->host_name);
AzureIoTClient 20:206846c14c80 1045 amqp_frame_codec_destroy(result->amqp_frame_codec);
AzureIoTClient 20:206846c14c80 1046 frame_codec_destroy(result->frame_codec);
AzureIoTClient 21:f9c433d8e6ca 1047 free(result);
AzureIoTClient 20:206846c14c80 1048 result = NULL;
AzureIoTClient 20:206846c14c80 1049 }
AzureIoTClient 20:206846c14c80 1050 else
AzureIoTClient 20:206846c14c80 1051 {
AzureIoTClient 20:206846c14c80 1052 result->last_frame_sent_time = result->last_frame_received_time;
AzureIoTClient 20:206846c14c80 1053
AzureIoTClient 20:206846c14c80 1054 /* Codes_SRS_CONNECTION_01_072: [When connection_create succeeds, the state of the connection shall be CONNECTION_STATE_START.] */
AzureIoTClient 20:206846c14c80 1055 connection_set_state(result, CONNECTION_STATE_START);
AzureIoTClient 20:206846c14c80 1056 }
AzureIoTClient 4:98007eb79fa8 1057 }
AzureIoTClient 4:98007eb79fa8 1058 }
AzureIoTClient 4:98007eb79fa8 1059 }
AzureIoTClient 4:98007eb79fa8 1060 }
AzureIoTClient 4:98007eb79fa8 1061 }
AzureIoTClient 4:98007eb79fa8 1062 }
AzureIoTClient 4:98007eb79fa8 1063 }
Azure.IoT Build 0:6ae2f7bca550 1064
AzureIoTClient 4:98007eb79fa8 1065 return result;
Azure.IoT Build 0:6ae2f7bca550 1066 }
Azure.IoT Build 0:6ae2f7bca550 1067
Azure.IoT Build 0:6ae2f7bca550 1068 void connection_destroy(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 1069 {
AzureIoTClient 4:98007eb79fa8 1070 /* Codes_SRS_CONNECTION_01_079: [If handle is NULL, connection_destroy shall do nothing.] */
AzureIoTClient 4:98007eb79fa8 1071 if (connection != NULL)
AzureIoTClient 4:98007eb79fa8 1072 {
AzureIoTClient 4:98007eb79fa8 1073 /* Codes_SRS_CONNECTION_01_073: [connection_destroy shall free all resources associated with a connection.] */
AzureIoTClient 4:98007eb79fa8 1074 if (connection->is_underlying_io_open)
AzureIoTClient 4:98007eb79fa8 1075 {
AzureIoTClient 4:98007eb79fa8 1076 connection_close(connection, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 1077 }
Azure.IoT Build 0:6ae2f7bca550 1078
AzureIoTClient 4:98007eb79fa8 1079 amqp_frame_codec_destroy(connection->amqp_frame_codec);
AzureIoTClient 4:98007eb79fa8 1080 frame_codec_destroy(connection->frame_codec);
AzureIoTClient 4:98007eb79fa8 1081 tickcounter_destroy(connection->tick_counter);
Azure.IoT Build 0:6ae2f7bca550 1082
AzureIoTClient 21:f9c433d8e6ca 1083 free(connection->host_name);
AzureIoTClient 21:f9c433d8e6ca 1084 free(connection->container_id);
Azure.IoT Build 0:6ae2f7bca550 1085
AzureIoTClient 4:98007eb79fa8 1086 /* Codes_SRS_CONNECTION_01_074: [connection_destroy shall close the socket connection.] */
AzureIoTClient 21:f9c433d8e6ca 1087 free(connection);
AzureIoTClient 4:98007eb79fa8 1088 }
Azure.IoT Build 0:6ae2f7bca550 1089 }
Azure.IoT Build 0:6ae2f7bca550 1090
Azure.IoT Build 0:6ae2f7bca550 1091 int connection_open(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 1092 {
AzureIoTClient 4:98007eb79fa8 1093 int result;
Azure.IoT Build 0:6ae2f7bca550 1094
AzureIoTClient 4:98007eb79fa8 1095 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1096 {
AzureIoTClient 19:000ab4e6a2c1 1097 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1098 }
AzureIoTClient 4:98007eb79fa8 1099 else
AzureIoTClient 4:98007eb79fa8 1100 {
AzureIoTClient 4:98007eb79fa8 1101 if (!connection->is_underlying_io_open)
AzureIoTClient 4:98007eb79fa8 1102 {
AzureIoTClient 4:98007eb79fa8 1103 if (xio_open(connection->io, connection_on_io_open_complete, connection, connection_on_bytes_received, connection, connection_on_io_error, connection) != 0)
AzureIoTClient 4:98007eb79fa8 1104 {
AzureIoTClient 4:98007eb79fa8 1105 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 1106 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1107 }
AzureIoTClient 4:98007eb79fa8 1108 else
AzureIoTClient 4:98007eb79fa8 1109 {
AzureIoTClient 4:98007eb79fa8 1110 connection->is_underlying_io_open = 1;
Azure.IoT Build 0:6ae2f7bca550 1111
AzureIoTClient 4:98007eb79fa8 1112 connection_set_state(connection, CONNECTION_STATE_START);
Azure.IoT Build 0:6ae2f7bca550 1113
AzureIoTClient 4:98007eb79fa8 1114 result = 0;
AzureIoTClient 4:98007eb79fa8 1115 }
AzureIoTClient 4:98007eb79fa8 1116 }
AzureIoTClient 4:98007eb79fa8 1117 else
AzureIoTClient 4:98007eb79fa8 1118 {
AzureIoTClient 4:98007eb79fa8 1119 result = 0;
AzureIoTClient 4:98007eb79fa8 1120 }
AzureIoTClient 4:98007eb79fa8 1121 }
Azure.IoT Build 0:6ae2f7bca550 1122
AzureIoTClient 4:98007eb79fa8 1123 return result;
Azure.IoT Build 0:6ae2f7bca550 1124 }
Azure.IoT Build 0:6ae2f7bca550 1125
Azure.IoT Build 0:6ae2f7bca550 1126 int connection_listen(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 1127 {
AzureIoTClient 4:98007eb79fa8 1128 int result;
Azure.IoT Build 0:6ae2f7bca550 1129
AzureIoTClient 4:98007eb79fa8 1130 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1131 {
AzureIoTClient 19:000ab4e6a2c1 1132 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1133 }
AzureIoTClient 4:98007eb79fa8 1134 else
AzureIoTClient 4:98007eb79fa8 1135 {
AzureIoTClient 4:98007eb79fa8 1136 if (!connection->is_underlying_io_open)
AzureIoTClient 4:98007eb79fa8 1137 {
AzureIoTClient 4:98007eb79fa8 1138 if (xio_open(connection->io, connection_on_io_open_complete, connection, connection_on_bytes_received, connection, connection_on_io_error, connection) != 0)
AzureIoTClient 4:98007eb79fa8 1139 {
AzureIoTClient 4:98007eb79fa8 1140 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 1141 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1142 }
AzureIoTClient 4:98007eb79fa8 1143 else
AzureIoTClient 4:98007eb79fa8 1144 {
AzureIoTClient 4:98007eb79fa8 1145 connection->is_underlying_io_open = 1;
Azure.IoT Build 0:6ae2f7bca550 1146
AzureIoTClient 4:98007eb79fa8 1147 connection_set_state(connection, CONNECTION_STATE_HDR_EXCH);
Azure.IoT Build 0:6ae2f7bca550 1148
AzureIoTClient 4:98007eb79fa8 1149 result = 0;
AzureIoTClient 4:98007eb79fa8 1150 }
AzureIoTClient 4:98007eb79fa8 1151 }
AzureIoTClient 4:98007eb79fa8 1152 else
AzureIoTClient 4:98007eb79fa8 1153 {
AzureIoTClient 4:98007eb79fa8 1154 result = 0;
AzureIoTClient 4:98007eb79fa8 1155 }
AzureIoTClient 4:98007eb79fa8 1156 }
Azure.IoT Build 0:6ae2f7bca550 1157
AzureIoTClient 4:98007eb79fa8 1158 return result;
Azure.IoT Build 0:6ae2f7bca550 1159 }
Azure.IoT Build 0:6ae2f7bca550 1160
Azure.IoT Build 0:6ae2f7bca550 1161 int connection_close(CONNECTION_HANDLE connection, const char* condition_value, const char* description)
Azure.IoT Build 0:6ae2f7bca550 1162 {
AzureIoTClient 4:98007eb79fa8 1163 int result;
Azure.IoT Build 0:6ae2f7bca550 1164
AzureIoTClient 4:98007eb79fa8 1165 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1166 {
AzureIoTClient 19:000ab4e6a2c1 1167 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1168 }
AzureIoTClient 4:98007eb79fa8 1169 else
AzureIoTClient 4:98007eb79fa8 1170 {
AzureIoTClient 4:98007eb79fa8 1171 if (condition_value != NULL)
AzureIoTClient 4:98007eb79fa8 1172 {
AzureIoTClient 4:98007eb79fa8 1173 close_connection_with_error(connection, condition_value, description);
AzureIoTClient 4:98007eb79fa8 1174 }
AzureIoTClient 4:98007eb79fa8 1175 else
AzureIoTClient 4:98007eb79fa8 1176 {
AzureIoTClient 4:98007eb79fa8 1177 (void)send_close_frame(connection, NULL);
AzureIoTClient 4:98007eb79fa8 1178 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 1179 }
Azure.IoT Build 0:6ae2f7bca550 1180
AzureIoTClient 4:98007eb79fa8 1181 (void)xio_close(connection->io, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 1182 connection->is_underlying_io_open = 1;
Azure.IoT Build 0:6ae2f7bca550 1183
Azure.IoT Build 0:6ae2f7bca550 1184 result = 0;
AzureIoTClient 4:98007eb79fa8 1185 }
Azure.IoT Build 0:6ae2f7bca550 1186
AzureIoTClient 4:98007eb79fa8 1187 return result;
Azure.IoT Build 0:6ae2f7bca550 1188 }
Azure.IoT Build 0:6ae2f7bca550 1189
Azure.IoT Build 0:6ae2f7bca550 1190 int connection_set_max_frame_size(CONNECTION_HANDLE connection, uint32_t max_frame_size)
Azure.IoT Build 0:6ae2f7bca550 1191 {
AzureIoTClient 4:98007eb79fa8 1192 int result;
Azure.IoT Build 0:6ae2f7bca550 1193
AzureIoTClient 4:98007eb79fa8 1194 /* Codes_SRS_CONNECTION_01_163: [If connection is NULL, connection_set_max_frame_size shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1195 if ((connection == NULL) ||
AzureIoTClient 4:98007eb79fa8 1196 /* Codes_SRS_CONNECTION_01_150: [If the max_frame_size is invalid then connection_set_max_frame_size shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1197 /* Codes_SRS_CONNECTION_01_167: [Both peers MUST accept frames of up to 512 (MIN-MAX-FRAME-SIZE) octets.] */
AzureIoTClient 4:98007eb79fa8 1198 (max_frame_size < 512))
AzureIoTClient 4:98007eb79fa8 1199 {
AzureIoTClient 19:000ab4e6a2c1 1200 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1201 }
AzureIoTClient 4:98007eb79fa8 1202 else
AzureIoTClient 4:98007eb79fa8 1203 {
AzureIoTClient 4:98007eb79fa8 1204 /* Codes_SRS_CONNECTION_01_157: [If connection_set_max_frame_size is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1205 if (connection->connection_state != CONNECTION_STATE_START)
AzureIoTClient 4:98007eb79fa8 1206 {
AzureIoTClient 19:000ab4e6a2c1 1207 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1208 }
AzureIoTClient 4:98007eb79fa8 1209 else
AzureIoTClient 4:98007eb79fa8 1210 {
AzureIoTClient 4:98007eb79fa8 1211 /* Codes_SRS_CONNECTION_01_148: [connection_set_max_frame_size shall set the max_frame_size associated with a connection.] */
AzureIoTClient 4:98007eb79fa8 1212 /* Codes_SRS_CONNECTION_01_164: [If connection_set_max_frame_size fails, the previous max_frame_size setting shall be retained.] */
AzureIoTClient 4:98007eb79fa8 1213 connection->max_frame_size = max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 1214
AzureIoTClient 4:98007eb79fa8 1215 /* Codes_SRS_CONNECTION_01_149: [On success connection_set_max_frame_size shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1216 result = 0;
AzureIoTClient 4:98007eb79fa8 1217 }
AzureIoTClient 4:98007eb79fa8 1218 }
Azure.IoT Build 0:6ae2f7bca550 1219
AzureIoTClient 4:98007eb79fa8 1220 return result;
Azure.IoT Build 0:6ae2f7bca550 1221 }
Azure.IoT Build 0:6ae2f7bca550 1222
Azure.IoT Build 0:6ae2f7bca550 1223 int connection_get_max_frame_size(CONNECTION_HANDLE connection, uint32_t* max_frame_size)
Azure.IoT Build 0:6ae2f7bca550 1224 {
AzureIoTClient 4:98007eb79fa8 1225 int result;
Azure.IoT Build 0:6ae2f7bca550 1226
AzureIoTClient 4:98007eb79fa8 1227 /* Codes_SRS_CONNECTION_01_170: [If connection or max_frame_size is NULL, connection_get_max_frame_size shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1228 if ((connection == NULL) ||
AzureIoTClient 4:98007eb79fa8 1229 (max_frame_size == NULL))
AzureIoTClient 4:98007eb79fa8 1230 {
AzureIoTClient 19:000ab4e6a2c1 1231 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1232 }
AzureIoTClient 4:98007eb79fa8 1233 else
AzureIoTClient 4:98007eb79fa8 1234 {
AzureIoTClient 4:98007eb79fa8 1235 /* Codes_SRS_CONNECTION_01_168: [connection_get_max_frame_size shall return in the max_frame_size argument the current max frame size setting.] */
AzureIoTClient 4:98007eb79fa8 1236 *max_frame_size = connection->max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 1237
AzureIoTClient 4:98007eb79fa8 1238 /* Codes_SRS_CONNECTION_01_169: [On success, connection_get_max_frame_size shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1239 result = 0;
AzureIoTClient 4:98007eb79fa8 1240 }
Azure.IoT Build 0:6ae2f7bca550 1241
AzureIoTClient 4:98007eb79fa8 1242 return result;
Azure.IoT Build 0:6ae2f7bca550 1243 }
Azure.IoT Build 0:6ae2f7bca550 1244
Azure.IoT Build 0:6ae2f7bca550 1245 int connection_set_channel_max(CONNECTION_HANDLE connection, uint16_t channel_max)
Azure.IoT Build 0:6ae2f7bca550 1246 {
AzureIoTClient 4:98007eb79fa8 1247 int result;
Azure.IoT Build 0:6ae2f7bca550 1248
AzureIoTClient 4:98007eb79fa8 1249 /* Codes_SRS_CONNECTION_01_181: [If connection is NULL then connection_set_channel_max shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1250 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1251 {
AzureIoTClient 19:000ab4e6a2c1 1252 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1253 }
AzureIoTClient 4:98007eb79fa8 1254 else
AzureIoTClient 4:98007eb79fa8 1255 {
AzureIoTClient 4:98007eb79fa8 1256 /* Codes_SRS_CONNECTION_01_156: [If connection_set_channel_max is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1257 if (connection->connection_state != CONNECTION_STATE_START)
AzureIoTClient 4:98007eb79fa8 1258 {
AzureIoTClient 19:000ab4e6a2c1 1259 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1260 }
AzureIoTClient 4:98007eb79fa8 1261 else
AzureIoTClient 4:98007eb79fa8 1262 {
AzureIoTClient 4:98007eb79fa8 1263 /* Codes_SRS_CONNECTION_01_153: [connection_set_channel_max shall set the channel_max associated with a connection.] */
AzureIoTClient 4:98007eb79fa8 1264 /* Codes_SRS_CONNECTION_01_165: [If connection_set_channel_max fails, the previous channel_max setting shall be retained.] */
AzureIoTClient 4:98007eb79fa8 1265 connection->channel_max = channel_max;
Azure.IoT Build 0:6ae2f7bca550 1266
AzureIoTClient 4:98007eb79fa8 1267 /* Codes_SRS_CONNECTION_01_154: [On success connection_set_channel_max shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1268 result = 0;
AzureIoTClient 4:98007eb79fa8 1269 }
AzureIoTClient 4:98007eb79fa8 1270 }
Azure.IoT Build 0:6ae2f7bca550 1271
AzureIoTClient 4:98007eb79fa8 1272 return result;
Azure.IoT Build 0:6ae2f7bca550 1273 }
Azure.IoT Build 0:6ae2f7bca550 1274
Azure.IoT Build 0:6ae2f7bca550 1275 int connection_get_channel_max(CONNECTION_HANDLE connection, uint16_t* channel_max)
Azure.IoT Build 0:6ae2f7bca550 1276 {
AzureIoTClient 4:98007eb79fa8 1277 int result;
Azure.IoT Build 0:6ae2f7bca550 1278
AzureIoTClient 4:98007eb79fa8 1279 /* Codes_SRS_CONNECTION_01_184: [If connection or channel_max is NULL, connection_get_channel_max shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1280 if ((connection == NULL) ||
AzureIoTClient 4:98007eb79fa8 1281 (channel_max == NULL))
AzureIoTClient 4:98007eb79fa8 1282 {
AzureIoTClient 19:000ab4e6a2c1 1283 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1284 }
AzureIoTClient 4:98007eb79fa8 1285 else
AzureIoTClient 4:98007eb79fa8 1286 {
AzureIoTClient 4:98007eb79fa8 1287 /* Codes_SRS_CONNECTION_01_182: [connection_get_channel_max shall return in the channel_max argument the current channel_max setting.] */
AzureIoTClient 4:98007eb79fa8 1288 *channel_max = connection->channel_max;
Azure.IoT Build 0:6ae2f7bca550 1289
AzureIoTClient 4:98007eb79fa8 1290 /* Codes_SRS_CONNECTION_01_183: [On success, connection_get_channel_max shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1291 result = 0;
AzureIoTClient 4:98007eb79fa8 1292 }
Azure.IoT Build 0:6ae2f7bca550 1293
AzureIoTClient 4:98007eb79fa8 1294 return result;
Azure.IoT Build 0:6ae2f7bca550 1295 }
Azure.IoT Build 0:6ae2f7bca550 1296
Azure.IoT Build 0:6ae2f7bca550 1297 int connection_set_idle_timeout(CONNECTION_HANDLE connection, milliseconds idle_timeout)
Azure.IoT Build 0:6ae2f7bca550 1298 {
AzureIoTClient 4:98007eb79fa8 1299 int result;
Azure.IoT Build 0:6ae2f7bca550 1300
AzureIoTClient 4:98007eb79fa8 1301 /* Codes_SRS_CONNECTION_01_191: [If connection is NULL, connection_set_idle_timeout shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1302 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1303 {
AzureIoTClient 19:000ab4e6a2c1 1304 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1305 }
AzureIoTClient 4:98007eb79fa8 1306 else
AzureIoTClient 4:98007eb79fa8 1307 {
AzureIoTClient 4:98007eb79fa8 1308 /* Codes_SRS_CONNECTION_01_158: [If connection_set_idle_timeout is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1309 if (connection->connection_state != CONNECTION_STATE_START)
AzureIoTClient 4:98007eb79fa8 1310 {
AzureIoTClient 19:000ab4e6a2c1 1311 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1312 }
AzureIoTClient 4:98007eb79fa8 1313 else
AzureIoTClient 4:98007eb79fa8 1314 {
AzureIoTClient 4:98007eb79fa8 1315 /* Codes_SRS_CONNECTION_01_159: [connection_set_idle_timeout shall set the idle_timeout associated with a connection.] */
AzureIoTClient 4:98007eb79fa8 1316 /* Codes_SRS_CONNECTION_01_166: [If connection_set_idle_timeout fails, the previous idle_timeout setting shall be retained.] */
AzureIoTClient 4:98007eb79fa8 1317 connection->idle_timeout = idle_timeout;
AzureIoTClient 4:98007eb79fa8 1318 connection->idle_timeout_specified = true;
Azure.IoT Build 0:6ae2f7bca550 1319
AzureIoTClient 4:98007eb79fa8 1320 /* Codes_SRS_CONNECTION_01_160: [On success connection_set_idle_timeout shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1321 result = 0;
AzureIoTClient 4:98007eb79fa8 1322 }
AzureIoTClient 4:98007eb79fa8 1323 }
Azure.IoT Build 0:6ae2f7bca550 1324
AzureIoTClient 4:98007eb79fa8 1325 return result;
Azure.IoT Build 0:6ae2f7bca550 1326 }
Azure.IoT Build 0:6ae2f7bca550 1327
Azure.IoT Build 0:6ae2f7bca550 1328 int connection_get_idle_timeout(CONNECTION_HANDLE connection, milliseconds* idle_timeout)
Azure.IoT Build 0:6ae2f7bca550 1329 {
AzureIoTClient 4:98007eb79fa8 1330 int result;
Azure.IoT Build 0:6ae2f7bca550 1331
AzureIoTClient 4:98007eb79fa8 1332 /* Codes_SRS_CONNECTION_01_190: [If connection or idle_timeout is NULL, connection_get_idle_timeout shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1333 if ((connection == NULL) ||
AzureIoTClient 4:98007eb79fa8 1334 (idle_timeout == NULL))
AzureIoTClient 4:98007eb79fa8 1335 {
AzureIoTClient 19:000ab4e6a2c1 1336 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1337 }
AzureIoTClient 4:98007eb79fa8 1338 else
AzureIoTClient 4:98007eb79fa8 1339 {
AzureIoTClient 4:98007eb79fa8 1340 /* Codes_SRS_CONNECTION_01_188: [connection_get_idle_timeout shall return in the idle_timeout argument the current idle_timeout setting.] */
AzureIoTClient 4:98007eb79fa8 1341 *idle_timeout = connection->idle_timeout;
Azure.IoT Build 0:6ae2f7bca550 1342
AzureIoTClient 4:98007eb79fa8 1343 /* Codes_SRS_CONNECTION_01_189: [On success, connection_get_idle_timeout shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1344 result = 0;
AzureIoTClient 4:98007eb79fa8 1345 }
Azure.IoT Build 0:6ae2f7bca550 1346
AzureIoTClient 4:98007eb79fa8 1347 return result;
Azure.IoT Build 0:6ae2f7bca550 1348 }
Azure.IoT Build 0:6ae2f7bca550 1349
Azure.IoT Build 0:6ae2f7bca550 1350 int connection_get_remote_max_frame_size(CONNECTION_HANDLE connection, uint32_t* remote_max_frame_size)
Azure.IoT Build 0:6ae2f7bca550 1351 {
AzureIoTClient 4:98007eb79fa8 1352 int result;
Azure.IoT Build 0:6ae2f7bca550 1353
AzureIoTClient 4:98007eb79fa8 1354 if ((connection == NULL) ||
AzureIoTClient 4:98007eb79fa8 1355 (remote_max_frame_size == NULL))
AzureIoTClient 4:98007eb79fa8 1356 {
AzureIoTClient 19:000ab4e6a2c1 1357 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1358 }
AzureIoTClient 4:98007eb79fa8 1359 else
AzureIoTClient 4:98007eb79fa8 1360 {
AzureIoTClient 4:98007eb79fa8 1361 *remote_max_frame_size = connection->remote_max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 1362
AzureIoTClient 4:98007eb79fa8 1363 result = 0;
AzureIoTClient 4:98007eb79fa8 1364 }
Azure.IoT Build 0:6ae2f7bca550 1365
AzureIoTClient 4:98007eb79fa8 1366 return result;
Azure.IoT Build 0:6ae2f7bca550 1367 }
Azure.IoT Build 0:6ae2f7bca550 1368
AzureIoTClient 1:eab586236bfe 1369 uint64_t connection_handle_deadlines(CONNECTION_HANDLE connection)
AzureIoTClient 1:eab586236bfe 1370 {
AzureIoTClient 1:eab586236bfe 1371 uint64_t local_deadline = (uint64_t )-1;
AzureIoTClient 1:eab586236bfe 1372 uint64_t remote_deadline = (uint64_t)-1;
AzureIoTClient 1:eab586236bfe 1373
AzureIoTClient 1:eab586236bfe 1374 if (connection != NULL)
AzureIoTClient 1:eab586236bfe 1375 {
Azure.IoT.Build 14:0b0e28c75ded 1376 tickcounter_ms_t current_ms;
AzureIoTClient 1:eab586236bfe 1377
AzureIoTClient 1:eab586236bfe 1378 if (tickcounter_get_current_ms(connection->tick_counter, &current_ms) != 0)
AzureIoTClient 1:eab586236bfe 1379 {
AzureIoTClient 1:eab586236bfe 1380 close_connection_with_error(connection, "amqp:internal-error", "Could not get tick count");
AzureIoTClient 1:eab586236bfe 1381 }
AzureIoTClient 1:eab586236bfe 1382 else
AzureIoTClient 1:eab586236bfe 1383 {
AzureIoTClient 1:eab586236bfe 1384 if (connection->idle_timeout_specified && (connection->idle_timeout != 0))
AzureIoTClient 1:eab586236bfe 1385 {
AzureIoTClient 1:eab586236bfe 1386 /* Calculate time until configured idle timeout expires */
AzureIoTClient 1:eab586236bfe 1387
AzureIoTClient 1:eab586236bfe 1388 uint64_t time_since_last_received = current_ms - connection->last_frame_received_time;
AzureIoTClient 1:eab586236bfe 1389 if (time_since_last_received < connection->idle_timeout)
AzureIoTClient 1:eab586236bfe 1390 {
AzureIoTClient 1:eab586236bfe 1391 local_deadline = connection->idle_timeout - time_since_last_received;
AzureIoTClient 1:eab586236bfe 1392 }
AzureIoTClient 1:eab586236bfe 1393 else
AzureIoTClient 1:eab586236bfe 1394 {
AzureIoTClient 1:eab586236bfe 1395 local_deadline = 0;
AzureIoTClient 1:eab586236bfe 1396
AzureIoTClient 1:eab586236bfe 1397 /* close connection */
AzureIoTClient 1:eab586236bfe 1398 close_connection_with_error(connection, "amqp:internal-error", "No frame received for the idle timeout");
AzureIoTClient 1:eab586236bfe 1399 }
AzureIoTClient 1:eab586236bfe 1400 }
AzureIoTClient 1:eab586236bfe 1401
AzureIoTClient 1:eab586236bfe 1402 if (local_deadline != 0 && connection->remote_idle_timeout != 0)
AzureIoTClient 1:eab586236bfe 1403 {
AzureIoTClient 1:eab586236bfe 1404 /* Calculate time until remote idle timeout expires */
AzureIoTClient 1:eab586236bfe 1405
AzureIoTClient 1:eab586236bfe 1406 uint64_t remote_idle_timeout = (connection->remote_idle_timeout / 2);
AzureIoTClient 1:eab586236bfe 1407 uint64_t time_since_last_sent = current_ms - connection->last_frame_sent_time;
AzureIoTClient 1:eab586236bfe 1408
AzureIoTClient 1:eab586236bfe 1409 if (time_since_last_sent < remote_idle_timeout)
AzureIoTClient 1:eab586236bfe 1410 {
AzureIoTClient 1:eab586236bfe 1411 remote_deadline = remote_idle_timeout - time_since_last_sent;
AzureIoTClient 1:eab586236bfe 1412 }
AzureIoTClient 1:eab586236bfe 1413 else
AzureIoTClient 1:eab586236bfe 1414 {
AzureIoTClient 1:eab586236bfe 1415 connection->on_send_complete = NULL;
AzureIoTClient 1:eab586236bfe 1416 if (amqp_frame_codec_encode_empty_frame(connection->amqp_frame_codec, 0, on_bytes_encoded, connection) != 0)
AzureIoTClient 1:eab586236bfe 1417 {
AzureIoTClient 1:eab586236bfe 1418 /* close connection */
AzureIoTClient 1:eab586236bfe 1419 close_connection_with_error(connection, "amqp:internal-error", "Cannot send empty frame");
AzureIoTClient 1:eab586236bfe 1420 }
AzureIoTClient 1:eab586236bfe 1421 else
AzureIoTClient 1:eab586236bfe 1422 {
AzureIoTClient 6:641a9672db08 1423 if (connection->is_trace_on == 1)
AzureIoTClient 6:641a9672db08 1424 {
AzureIoTClient 16:22a72cf8e416 1425 LOG(AZ_LOG_TRACE, LOG_LINE, "-> Empty frame");
AzureIoTClient 6:641a9672db08 1426 }
AzureIoTClient 1:eab586236bfe 1427
AzureIoTClient 1:eab586236bfe 1428 connection->last_frame_sent_time = current_ms;
AzureIoTClient 1:eab586236bfe 1429
AzureIoTClient 1:eab586236bfe 1430 remote_deadline = remote_idle_timeout;
AzureIoTClient 1:eab586236bfe 1431 }
AzureIoTClient 1:eab586236bfe 1432 }
AzureIoTClient 1:eab586236bfe 1433 }
AzureIoTClient 1:eab586236bfe 1434 }
AzureIoTClient 1:eab586236bfe 1435 }
AzureIoTClient 1:eab586236bfe 1436
AzureIoTClient 1:eab586236bfe 1437 /* Return the shorter of each deadline, or 0 to indicate connection closed */
AzureIoTClient 1:eab586236bfe 1438 return local_deadline > remote_deadline ? remote_deadline : local_deadline;
AzureIoTClient 1:eab586236bfe 1439 }
AzureIoTClient 1:eab586236bfe 1440
Azure.IoT Build 0:6ae2f7bca550 1441 void connection_dowork(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 1442 {
AzureIoTClient 4:98007eb79fa8 1443 /* Codes_SRS_CONNECTION_01_078: [If handle is NULL, connection_dowork shall do nothing.] */
AzureIoTClient 1:eab586236bfe 1444 if (connection != NULL)
AzureIoTClient 1:eab586236bfe 1445 {
AzureIoTClient 1:eab586236bfe 1446 if (connection_handle_deadlines(connection) > 0)
AzureIoTClient 1:eab586236bfe 1447 {
AzureIoTClient 1:eab586236bfe 1448 /* Codes_SRS_CONNECTION_01_076: [connection_dowork shall schedule the underlying IO interface to do its work by calling xio_dowork.] */
AzureIoTClient 1:eab586236bfe 1449 xio_dowork(connection->io);
AzureIoTClient 1:eab586236bfe 1450 }
AzureIoTClient 1:eab586236bfe 1451 }
Azure.IoT Build 0:6ae2f7bca550 1452 }
Azure.IoT Build 0:6ae2f7bca550 1453
Azure.IoT Build 0:6ae2f7bca550 1454 ENDPOINT_HANDLE connection_create_endpoint(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 1455 {
AzureIoTClient 4:98007eb79fa8 1456 ENDPOINT_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 1457
AzureIoTClient 4:98007eb79fa8 1458 /* Codes_SRS_CONNECTION_01_113: [If connection, on_endpoint_frame_received or on_connection_state_changed is NULL, connection_create_endpoint shall fail and return NULL.] */
AzureIoTClient 4:98007eb79fa8 1459 /* Codes_SRS_CONNECTION_01_193: [The context argument shall be allowed to be NULL.] */
AzureIoTClient 4:98007eb79fa8 1460 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1461 {
AzureIoTClient 4:98007eb79fa8 1462 result = NULL;
AzureIoTClient 4:98007eb79fa8 1463 }
AzureIoTClient 4:98007eb79fa8 1464 else
AzureIoTClient 4:98007eb79fa8 1465 {
AzureIoTClient 4:98007eb79fa8 1466 /* Codes_SRS_CONNECTION_01_115: [If no more endpoints can be created due to all channels being used, connection_create_endpoint shall fail and return NULL.] */
AzureIoTClient 4:98007eb79fa8 1467 if (connection->endpoint_count >= connection->channel_max)
AzureIoTClient 4:98007eb79fa8 1468 {
AzureIoTClient 4:98007eb79fa8 1469 result = NULL;
AzureIoTClient 4:98007eb79fa8 1470 }
AzureIoTClient 4:98007eb79fa8 1471 else
AzureIoTClient 4:98007eb79fa8 1472 {
AzureIoTClient 4:98007eb79fa8 1473 uint32_t i = 0;
Azure.IoT Build 0:6ae2f7bca550 1474
AzureIoTClient 4:98007eb79fa8 1475 /* Codes_SRS_CONNECTION_01_128: [The lowest number outgoing channel shall be associated with the newly created endpoint.] */
AzureIoTClient 4:98007eb79fa8 1476 for (i = 0; i < connection->endpoint_count; i++)
AzureIoTClient 4:98007eb79fa8 1477 {
AzureIoTClient 4:98007eb79fa8 1478 if (connection->endpoints[i]->outgoing_channel > i)
AzureIoTClient 4:98007eb79fa8 1479 {
AzureIoTClient 4:98007eb79fa8 1480 /* found a gap in the sorted endpoint array */
AzureIoTClient 4:98007eb79fa8 1481 break;
AzureIoTClient 4:98007eb79fa8 1482 }
AzureIoTClient 4:98007eb79fa8 1483 }
Azure.IoT Build 0:6ae2f7bca550 1484
AzureIoTClient 4:98007eb79fa8 1485 /* Codes_SRS_CONNECTION_01_127: [On success, connection_create_endpoint shall return a non-NULL handle to the newly created endpoint.] */
AzureIoTClient 23:1111ee8bcba4 1486 result = (ENDPOINT_INSTANCE*)malloc(sizeof(ENDPOINT_INSTANCE));
AzureIoTClient 4:98007eb79fa8 1487 /* Codes_SRS_CONNECTION_01_196: [If memory cannot be allocated for the new endpoint, connection_create_endpoint shall fail and return NULL.] */
AzureIoTClient 4:98007eb79fa8 1488 if (result != NULL)
AzureIoTClient 4:98007eb79fa8 1489 {
AzureIoTClient 4:98007eb79fa8 1490 ENDPOINT_INSTANCE** new_endpoints;
Azure.IoT Build 0:6ae2f7bca550 1491
AzureIoTClient 4:98007eb79fa8 1492 result->on_endpoint_frame_received = NULL;
AzureIoTClient 4:98007eb79fa8 1493 result->on_connection_state_changed = NULL;
AzureIoTClient 4:98007eb79fa8 1494 result->callback_context = NULL;
AzureIoTClient 6:641a9672db08 1495 result->outgoing_channel = (uint16_t)i;
AzureIoTClient 4:98007eb79fa8 1496 result->connection = connection;
Azure.IoT Build 0:6ae2f7bca550 1497
AzureIoTClient 4:98007eb79fa8 1498 /* Codes_SRS_CONNECTION_01_197: [The newly created endpoint shall be added to the endpoints list, so that it can be tracked.] */
AzureIoTClient 21:f9c433d8e6ca 1499 new_endpoints = (ENDPOINT_INSTANCE**)realloc(connection->endpoints, sizeof(ENDPOINT_INSTANCE*) * (connection->endpoint_count + 1));
AzureIoTClient 4:98007eb79fa8 1500 if (new_endpoints == NULL)
AzureIoTClient 4:98007eb79fa8 1501 {
AzureIoTClient 4:98007eb79fa8 1502 /* Tests_SRS_CONNECTION_01_198: [If adding the endpoint to the endpoints list tracked by the connection fails, connection_create_endpoint shall fail and return NULL.] */
AzureIoTClient 21:f9c433d8e6ca 1503 free(result);
AzureIoTClient 4:98007eb79fa8 1504 result = NULL;
AzureIoTClient 4:98007eb79fa8 1505 }
AzureIoTClient 4:98007eb79fa8 1506 else
AzureIoTClient 4:98007eb79fa8 1507 {
AzureIoTClient 4:98007eb79fa8 1508 connection->endpoints = new_endpoints;
Azure.IoT Build 0:6ae2f7bca550 1509
AzureIoTClient 4:98007eb79fa8 1510 if (i < connection->endpoint_count)
AzureIoTClient 4:98007eb79fa8 1511 {
AzureIoTClient 4:98007eb79fa8 1512 (void)memmove(&connection->endpoints[i + 1], &connection->endpoints[i], sizeof(ENDPOINT_INSTANCE*) * (connection->endpoint_count - i));
AzureIoTClient 4:98007eb79fa8 1513 }
Azure.IoT Build 0:6ae2f7bca550 1514
AzureIoTClient 4:98007eb79fa8 1515 connection->endpoints[i] = result;
AzureIoTClient 4:98007eb79fa8 1516 connection->endpoint_count++;
Azure.IoT Build 0:6ae2f7bca550 1517
AzureIoTClient 4:98007eb79fa8 1518 /* Codes_SRS_CONNECTION_01_112: [connection_create_endpoint shall create a new endpoint that can be used by a session.] */
AzureIoTClient 4:98007eb79fa8 1519 }
AzureIoTClient 4:98007eb79fa8 1520 }
AzureIoTClient 4:98007eb79fa8 1521 }
AzureIoTClient 4:98007eb79fa8 1522 }
Azure.IoT Build 0:6ae2f7bca550 1523
AzureIoTClient 4:98007eb79fa8 1524 return result;
Azure.IoT Build 0:6ae2f7bca550 1525 }
Azure.IoT Build 0:6ae2f7bca550 1526
Azure.IoT Build 0:6ae2f7bca550 1527 int connection_start_endpoint(ENDPOINT_HANDLE endpoint, ON_ENDPOINT_FRAME_RECEIVED on_endpoint_frame_received, ON_CONNECTION_STATE_CHANGED on_connection_state_changed, void* context)
Azure.IoT Build 0:6ae2f7bca550 1528 {
AzureIoTClient 4:98007eb79fa8 1529 int result;
Azure.IoT Build 0:6ae2f7bca550 1530
AzureIoTClient 4:98007eb79fa8 1531 if ((endpoint == NULL) ||
AzureIoTClient 4:98007eb79fa8 1532 (on_endpoint_frame_received == NULL) ||
AzureIoTClient 4:98007eb79fa8 1533 (on_connection_state_changed == NULL))
AzureIoTClient 4:98007eb79fa8 1534 {
AzureIoTClient 19:000ab4e6a2c1 1535 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1536 }
AzureIoTClient 4:98007eb79fa8 1537 else
AzureIoTClient 4:98007eb79fa8 1538 {
AzureIoTClient 4:98007eb79fa8 1539 endpoint->on_endpoint_frame_received = on_endpoint_frame_received;
AzureIoTClient 4:98007eb79fa8 1540 endpoint->on_connection_state_changed = on_connection_state_changed;
AzureIoTClient 4:98007eb79fa8 1541 endpoint->callback_context = context;
Azure.IoT Build 0:6ae2f7bca550 1542
AzureIoTClient 4:98007eb79fa8 1543 result = 0;
AzureIoTClient 4:98007eb79fa8 1544 }
Azure.IoT Build 0:6ae2f7bca550 1545
AzureIoTClient 4:98007eb79fa8 1546 return result;
Azure.IoT Build 0:6ae2f7bca550 1547 }
Azure.IoT Build 0:6ae2f7bca550 1548
Azure.IoT Build 0:6ae2f7bca550 1549 int connection_endpoint_get_incoming_channel(ENDPOINT_HANDLE endpoint, uint16_t* incoming_channel)
Azure.IoT Build 0:6ae2f7bca550 1550 {
AzureIoTClient 4:98007eb79fa8 1551 int result;
Azure.IoT Build 0:6ae2f7bca550 1552
AzureIoTClient 4:98007eb79fa8 1553 if ((endpoint == NULL) ||
AzureIoTClient 4:98007eb79fa8 1554 (incoming_channel == NULL))
AzureIoTClient 4:98007eb79fa8 1555 {
AzureIoTClient 19:000ab4e6a2c1 1556 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1557 }
AzureIoTClient 4:98007eb79fa8 1558 else
AzureIoTClient 4:98007eb79fa8 1559 {
AzureIoTClient 4:98007eb79fa8 1560 *incoming_channel = endpoint->incoming_channel;
AzureIoTClient 4:98007eb79fa8 1561 result = 0;
AzureIoTClient 4:98007eb79fa8 1562 }
Azure.IoT Build 0:6ae2f7bca550 1563
AzureIoTClient 4:98007eb79fa8 1564 return result;
Azure.IoT Build 0:6ae2f7bca550 1565 }
Azure.IoT Build 0:6ae2f7bca550 1566
Azure.IoT Build 0:6ae2f7bca550 1567 /* Codes_SRS_CONNECTION_01_129: [connection_destroy_endpoint shall free all resources associated with an endpoint created by connection_create_endpoint.] */
Azure.IoT Build 0:6ae2f7bca550 1568 void connection_destroy_endpoint(ENDPOINT_HANDLE endpoint)
Azure.IoT Build 0:6ae2f7bca550 1569 {
AzureIoTClient 4:98007eb79fa8 1570 if (endpoint != NULL)
AzureIoTClient 4:98007eb79fa8 1571 {
AzureIoTClient 4:98007eb79fa8 1572 CONNECTION_INSTANCE* connection = (CONNECTION_INSTANCE*)endpoint->connection;
AzureIoTClient 4:98007eb79fa8 1573 size_t i;
Azure.IoT Build 0:6ae2f7bca550 1574
AzureIoTClient 4:98007eb79fa8 1575 for (i = 0; i < connection->endpoint_count; i++)
AzureIoTClient 4:98007eb79fa8 1576 {
AzureIoTClient 4:98007eb79fa8 1577 if (connection->endpoints[i] == endpoint)
AzureIoTClient 4:98007eb79fa8 1578 {
AzureIoTClient 4:98007eb79fa8 1579 break;
AzureIoTClient 4:98007eb79fa8 1580 }
AzureIoTClient 4:98007eb79fa8 1581 }
Azure.IoT Build 0:6ae2f7bca550 1582
AzureIoTClient 4:98007eb79fa8 1583 /* Codes_SRS_CONNECTION_01_130: [The outgoing channel associated with the endpoint shall be released by removing the endpoint from the endpoint list.] */
AzureIoTClient 4:98007eb79fa8 1584 /* Codes_SRS_CONNECTION_01_131: [Any incoming channel number associated with the endpoint shall be released.] */
AzureIoTClient 11:b9de84324501 1585 if (i < connection->endpoint_count && i > 0)
AzureIoTClient 11:b9de84324501 1586 {
AzureIoTClient 11:b9de84324501 1587 (void)memmove(connection->endpoints + i, connection->endpoints + i + 1, sizeof(ENDPOINT_INSTANCE*) * (connection->endpoint_count - i - 1));
Azure.IoT Build 0:6ae2f7bca550 1588
AzureIoTClient 21:f9c433d8e6ca 1589 ENDPOINT_INSTANCE** new_endpoints = (ENDPOINT_INSTANCE**)realloc(connection->endpoints, (connection->endpoint_count - 1) * sizeof(ENDPOINT_INSTANCE*));
AzureIoTClient 11:b9de84324501 1590 if (new_endpoints != NULL)
AzureIoTClient 11:b9de84324501 1591 {
AzureIoTClient 11:b9de84324501 1592 connection->endpoints = new_endpoints;
AzureIoTClient 11:b9de84324501 1593 }
Azure.IoT Build 0:6ae2f7bca550 1594
AzureIoTClient 11:b9de84324501 1595 connection->endpoint_count--;
AzureIoTClient 11:b9de84324501 1596 }
AzureIoTClient 11:b9de84324501 1597 else if (connection->endpoint_count == 1)
AzureIoTClient 11:b9de84324501 1598 {
AzureIoTClient 21:f9c433d8e6ca 1599 free(connection->endpoints);
AzureIoTClient 11:b9de84324501 1600 connection->endpoints = NULL;
AzureIoTClient 11:b9de84324501 1601 connection->endpoint_count = 0;
AzureIoTClient 11:b9de84324501 1602 }
Azure.IoT Build 0:6ae2f7bca550 1603
AzureIoTClient 21:f9c433d8e6ca 1604 free(endpoint);
AzureIoTClient 4:98007eb79fa8 1605 }
Azure.IoT Build 0:6ae2f7bca550 1606 }
Azure.IoT Build 0:6ae2f7bca550 1607
Azure.IoT Build 0:6ae2f7bca550 1608 /* Codes_SRS_CONNECTION_01_247: [connection_encode_frame shall send a frame for a certain endpoint.] */
Azure.IoT Build 0:6ae2f7bca550 1609 int connection_encode_frame(ENDPOINT_HANDLE endpoint, const AMQP_VALUE performative, PAYLOAD* payloads, size_t payload_count, ON_SEND_COMPLETE on_send_complete, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 1610 {
AzureIoTClient 4:98007eb79fa8 1611 int result;
Azure.IoT Build 0:6ae2f7bca550 1612
AzureIoTClient 4:98007eb79fa8 1613 /* Codes_SRS_CONNECTION_01_249: [If endpoint or performative are NULL, connection_encode_frame shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1614 if ((endpoint == NULL) ||
AzureIoTClient 4:98007eb79fa8 1615 (performative == NULL))
AzureIoTClient 4:98007eb79fa8 1616 {
AzureIoTClient 19:000ab4e6a2c1 1617 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1618 }
AzureIoTClient 4:98007eb79fa8 1619 else
AzureIoTClient 4:98007eb79fa8 1620 {
AzureIoTClient 4:98007eb79fa8 1621 CONNECTION_INSTANCE* connection = (CONNECTION_INSTANCE*)endpoint->connection;
AzureIoTClient 4:98007eb79fa8 1622 AMQP_FRAME_CODEC_HANDLE amqp_frame_codec = connection->amqp_frame_codec;
Azure.IoT Build 0:6ae2f7bca550 1623
AzureIoTClient 4:98007eb79fa8 1624 /* Codes_SRS_CONNECTION_01_254: [If connection_encode_frame is called before the connection is in the OPENED state, connection_encode_frame shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1625 if (connection->connection_state != CONNECTION_STATE_OPENED)
AzureIoTClient 4:98007eb79fa8 1626 {
AzureIoTClient 19:000ab4e6a2c1 1627 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1628 }
AzureIoTClient 4:98007eb79fa8 1629 else
AzureIoTClient 4:98007eb79fa8 1630 {
AzureIoTClient 4:98007eb79fa8 1631 /* Codes_SRS_CONNECTION_01_255: [The payload size shall be computed based on all the payload chunks passed as argument in payloads.] */
AzureIoTClient 4:98007eb79fa8 1632 /* Codes_SRS_CONNECTION_01_250: [connection_encode_frame shall initiate the frame send by calling amqp_frame_codec_begin_encode_frame.] */
AzureIoTClient 4:98007eb79fa8 1633 /* Codes_SRS_CONNECTION_01_251: [The channel number passed to amqp_frame_codec_begin_encode_frame shall be the outgoing channel number associated with the endpoint by connection_create_endpoint.] */
AzureIoTClient 4:98007eb79fa8 1634 /* Codes_SRS_CONNECTION_01_252: [The performative passed to amqp_frame_codec_begin_encode_frame shall be the performative argument of connection_encode_frame.] */
AzureIoTClient 4:98007eb79fa8 1635 connection->on_send_complete = on_send_complete;
AzureIoTClient 4:98007eb79fa8 1636 connection->on_send_complete_callback_context = callback_context;
AzureIoTClient 4:98007eb79fa8 1637 if (amqp_frame_codec_encode_frame(amqp_frame_codec, endpoint->outgoing_channel, performative, payloads, payload_count, on_bytes_encoded, connection) != 0)
AzureIoTClient 4:98007eb79fa8 1638 {
AzureIoTClient 4:98007eb79fa8 1639 /* Codes_SRS_CONNECTION_01_253: [If amqp_frame_codec_begin_encode_frame or amqp_frame_codec_encode_payload_bytes fails, then connection_encode_frame shall fail and return a non-zero value.] */
AzureIoTClient 19:000ab4e6a2c1 1640 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1641 }
AzureIoTClient 4:98007eb79fa8 1642 else
AzureIoTClient 4:98007eb79fa8 1643 {
AzureIoTClient 4:98007eb79fa8 1644 if (connection->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 1645 {
Azure.IoT Build 5:ae49385aff34 1646 log_outgoing_frame(performative);
AzureIoTClient 4:98007eb79fa8 1647 }
Azure.IoT Build 5:ae49385aff34 1648
AzureIoTClient 4:98007eb79fa8 1649 if (tickcounter_get_current_ms(connection->tick_counter, &connection->last_frame_sent_time) != 0)
AzureIoTClient 4:98007eb79fa8 1650 {
AzureIoTClient 19:000ab4e6a2c1 1651 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1652 }
AzureIoTClient 4:98007eb79fa8 1653 else
AzureIoTClient 4:98007eb79fa8 1654 {
AzureIoTClient 4:98007eb79fa8 1655 /* Codes_SRS_CONNECTION_01_248: [On success it shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1656 result = 0;
AzureIoTClient 4:98007eb79fa8 1657 }
AzureIoTClient 4:98007eb79fa8 1658 }
AzureIoTClient 4:98007eb79fa8 1659 }
AzureIoTClient 4:98007eb79fa8 1660 }
Azure.IoT Build 0:6ae2f7bca550 1661
AzureIoTClient 4:98007eb79fa8 1662 return result;
Azure.IoT Build 0:6ae2f7bca550 1663 }
AzureIoTClient 4:98007eb79fa8 1664
AzureIoTClient 4:98007eb79fa8 1665 void connection_set_trace(CONNECTION_HANDLE connection, bool traceOn)
AzureIoTClient 4:98007eb79fa8 1666 {
AzureIoTClient 4:98007eb79fa8 1667 /* Codes_SRS_CONNECTION_07_002: [If connection is NULL then connection_set_trace shall do nothing.] */
AzureIoTClient 4:98007eb79fa8 1668 if (connection != NULL)
AzureIoTClient 4:98007eb79fa8 1669 {
AzureIoTClient 4:98007eb79fa8 1670 /* Codes_SRS_CONNECTION_07_001: [connection_set_trace shall set the ability to turn on and off trace logging.] */
AzureIoTClient 4:98007eb79fa8 1671 connection->is_trace_on = traceOn ? 1 : 0;
AzureIoTClient 4:98007eb79fa8 1672 }
AzureIoTClient 4:98007eb79fa8 1673 }