A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Tue Mar 20 10:29:38 2018 -0700
Revision:
41:0e723f9cbd89
Parent:
38:7631b92cc772
Child:
43:4c1e4e94cdd3
1.2.1

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"
AzureIoTClient 41:0e723f9cbd89 15 #include "azure_uamqp_c/amqpvalue.h"
Azure.IoT Build 0:6ae2f7bca550 16 #include "azure_uamqp_c/amqp_frame_codec.h"
Azure.IoT Build 0:6ae2f7bca550 17 #include "azure_uamqp_c/amqp_definitions.h"
Azure.IoT Build 0:6ae2f7bca550 18 #include "azure_uamqp_c/amqpvalue_to_string.h"
Azure.IoT Build 0:6ae2f7bca550 19
Azure.IoT Build 0:6ae2f7bca550 20 /* Requirements satisfied by the virtue of implementing the ISO:*/
Azure.IoT Build 0:6ae2f7bca550 21 /* 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 22 /* 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 23
AzureIoTClient 16:22a72cf8e416 24 /* 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 25 static const unsigned char amqp_header[] = { 'A', 'M', 'Q', 'P', 0, 1, 0, 0 };
Azure.IoT Build 0:6ae2f7bca550 26
Azure.IoT Build 0:6ae2f7bca550 27 typedef enum RECEIVE_FRAME_STATE_TAG
Azure.IoT Build 0:6ae2f7bca550 28 {
AzureIoTClient 4:98007eb79fa8 29 RECEIVE_FRAME_STATE_FRAME_SIZE,
AzureIoTClient 4:98007eb79fa8 30 RECEIVE_FRAME_STATE_FRAME_DATA
Azure.IoT Build 0:6ae2f7bca550 31 } RECEIVE_FRAME_STATE;
Azure.IoT Build 0:6ae2f7bca550 32
Azure.IoT Build 0:6ae2f7bca550 33 typedef struct ENDPOINT_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 34 {
AzureIoTClient 4:98007eb79fa8 35 uint16_t incoming_channel;
AzureIoTClient 4:98007eb79fa8 36 uint16_t outgoing_channel;
AzureIoTClient 4:98007eb79fa8 37 ON_ENDPOINT_FRAME_RECEIVED on_endpoint_frame_received;
AzureIoTClient 4:98007eb79fa8 38 ON_CONNECTION_STATE_CHANGED on_connection_state_changed;
AzureIoTClient 4:98007eb79fa8 39 void* callback_context;
AzureIoTClient 4:98007eb79fa8 40 CONNECTION_HANDLE connection;
Azure.IoT Build 0:6ae2f7bca550 41 } ENDPOINT_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 42
Azure.IoT Build 0:6ae2f7bca550 43 typedef struct CONNECTION_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 44 {
AzureIoTClient 4:98007eb79fa8 45 XIO_HANDLE io;
AzureIoTClient 4:98007eb79fa8 46 size_t header_bytes_received;
AzureIoTClient 4:98007eb79fa8 47 CONNECTION_STATE connection_state;
AzureIoTClient 4:98007eb79fa8 48 FRAME_CODEC_HANDLE frame_codec;
AzureIoTClient 4:98007eb79fa8 49 AMQP_FRAME_CODEC_HANDLE amqp_frame_codec;
AzureIoTClient 4:98007eb79fa8 50 ENDPOINT_INSTANCE** endpoints;
AzureIoTClient 4:98007eb79fa8 51 uint32_t endpoint_count;
AzureIoTClient 4:98007eb79fa8 52 char* host_name;
AzureIoTClient 4:98007eb79fa8 53 char* container_id;
AzureIoTClient 4:98007eb79fa8 54 TICK_COUNTER_HANDLE tick_counter;
AzureIoTClient 4:98007eb79fa8 55 uint32_t remote_max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 56
AzureIoTClient 4:98007eb79fa8 57 ON_SEND_COMPLETE on_send_complete;
AzureIoTClient 4:98007eb79fa8 58 void* on_send_complete_callback_context;
Azure.IoT Build 0:6ae2f7bca550 59
AzureIoTClient 4:98007eb79fa8 60 ON_NEW_ENDPOINT on_new_endpoint;
AzureIoTClient 4:98007eb79fa8 61 void* on_new_endpoint_callback_context;
Azure.IoT Build 0:6ae2f7bca550 62
Azure.IoT Build 0:6ae2f7bca550 63 ON_CONNECTION_STATE_CHANGED on_connection_state_changed;
Azure.IoT Build 0:6ae2f7bca550 64 void* on_connection_state_changed_callback_context;
Azure.IoT Build 0:6ae2f7bca550 65 ON_IO_ERROR on_io_error;
Azure.IoT Build 0:6ae2f7bca550 66 void* on_io_error_callback_context;
Azure.IoT Build 0:6ae2f7bca550 67
AzureIoTClient 4:98007eb79fa8 68 /* options */
AzureIoTClient 4:98007eb79fa8 69 uint32_t max_frame_size;
AzureIoTClient 4:98007eb79fa8 70 uint16_t channel_max;
AzureIoTClient 4:98007eb79fa8 71 milliseconds idle_timeout;
AzureIoTClient 4:98007eb79fa8 72 milliseconds remote_idle_timeout;
AzureIoTClient 35:d0bed2404ee9 73 milliseconds remote_idle_timeout_send_frame_millisecond;
AzureIoTClient 35:d0bed2404ee9 74 double idle_timeout_empty_frame_send_ratio;
Azure.IoT.Build 14:0b0e28c75ded 75 tickcounter_ms_t last_frame_received_time;
Azure.IoT.Build 14:0b0e28c75ded 76 tickcounter_ms_t last_frame_sent_time;
AzureIoTClient 41:0e723f9cbd89 77 fields properties;
Azure.IoT Build 0:6ae2f7bca550 78
AzureIoTClient 4:98007eb79fa8 79 unsigned int is_underlying_io_open : 1;
AzureIoTClient 4:98007eb79fa8 80 unsigned int idle_timeout_specified : 1;
AzureIoTClient 4:98007eb79fa8 81 unsigned int is_remote_frame_received : 1;
AzureIoTClient 4:98007eb79fa8 82 unsigned int is_trace_on : 1;
Azure.IoT Build 0:6ae2f7bca550 83 } CONNECTION_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 84
Azure.IoT Build 0:6ae2f7bca550 85 /* Codes_SRS_CONNECTION_01_258: [on_connection_state_changed shall be invoked whenever the connection state changes.]*/
AzureIoTClient 24:2c59c2d43ebf 86 static void connection_set_state(CONNECTION_HANDLE connection, CONNECTION_STATE connection_state)
Azure.IoT Build 0:6ae2f7bca550 87 {
AzureIoTClient 4:98007eb79fa8 88 uint64_t i;
Azure.IoT Build 0:6ae2f7bca550 89
AzureIoTClient 24:2c59c2d43ebf 90 CONNECTION_STATE previous_state = connection->connection_state;
AzureIoTClient 24:2c59c2d43ebf 91 connection->connection_state = connection_state;
Azure.IoT Build 0:6ae2f7bca550 92
Azure.IoT Build 0:6ae2f7bca550 93 /* Codes_SRS_CONNECTION_22_001: [If a connection state changed occurs and a callback is registered the callback shall be called.] */
AzureIoTClient 24:2c59c2d43ebf 94 if (connection->on_connection_state_changed)
Azure.IoT Build 0:6ae2f7bca550 95 {
AzureIoTClient 24:2c59c2d43ebf 96 connection->on_connection_state_changed(connection->on_connection_state_changed_callback_context, connection_state, previous_state);
Azure.IoT Build 0:6ae2f7bca550 97 }
Azure.IoT Build 0:6ae2f7bca550 98
AzureIoTClient 16:22a72cf8e416 99 /* Codes_SRS_CONNECTION_01_260: [Each endpoint's on_connection_state_changed shall be called.] */
AzureIoTClient 24:2c59c2d43ebf 100 for (i = 0; i < connection->endpoint_count; i++)
AzureIoTClient 4:98007eb79fa8 101 {
AzureIoTClient 4:98007eb79fa8 102 /* Codes_SRS_CONNECTION_01_259: [The callback_context passed in connection_create_endpoint.] */
AzureIoTClient 24:2c59c2d43ebf 103 connection->endpoints[i]->on_connection_state_changed(connection->endpoints[i]->callback_context, connection_state, previous_state);
AzureIoTClient 4:98007eb79fa8 104 }
Azure.IoT Build 0:6ae2f7bca550 105 }
Azure.IoT Build 0:6ae2f7bca550 106
AzureIoTClient 38:7631b92cc772 107 // This callback usage needs to be either verified and commented or integrated into
AzureIoTClient 38:7631b92cc772 108 // the state machine.
AzureIoTClient 38:7631b92cc772 109 static void unchecked_on_send_complete(void* context, IO_SEND_RESULT send_result)
AzureIoTClient 38:7631b92cc772 110 {
AzureIoTClient 38:7631b92cc772 111 (void)context;
AzureIoTClient 38:7631b92cc772 112 (void)send_result;
AzureIoTClient 38:7631b92cc772 113 }
AzureIoTClient 38:7631b92cc772 114
AzureIoTClient 24:2c59c2d43ebf 115 static int send_header(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 116 {
AzureIoTClient 4:98007eb79fa8 117 int result;
Azure.IoT Build 0:6ae2f7bca550 118
AzureIoTClient 16:22a72cf8e416 119 /* 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 120 /* Codes_SRS_CONNECTION_01_104: [Sending the protocol header shall be done by using xio_send.] */
AzureIoTClient 38:7631b92cc772 121 if (xio_send(connection->io, amqp_header, sizeof(amqp_header), unchecked_on_send_complete, NULL) != 0)
AzureIoTClient 4:98007eb79fa8 122 {
AzureIoTClient 4:98007eb79fa8 123 /* Codes_SRS_CONNECTION_01_106: [When sending the protocol header fails, the connection shall be immediately closed.] */
AzureIoTClient 28:add19eb7defa 124 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 125 {
AzureIoTClient 28:add19eb7defa 126 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 127 }
Azure.IoT Build 0:6ae2f7bca550 128
AzureIoTClient 4:98007eb79fa8 129 /* 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 24:2c59c2d43ebf 130 connection_set_state(connection, CONNECTION_STATE_END);
Azure.IoT Build 0:6ae2f7bca550 131
AzureIoTClient 4:98007eb79fa8 132 /* Codes_SRS_CONNECTION_01_105: [When xio_send fails, connection_dowork shall return a non-zero value.] */
AzureIoTClient 19:000ab4e6a2c1 133 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 134 }
AzureIoTClient 4:98007eb79fa8 135 else
AzureIoTClient 4:98007eb79fa8 136 {
AzureIoTClient 24:2c59c2d43ebf 137 if (connection->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 138 {
AzureIoTClient 16:22a72cf8e416 139 LOG(AZ_LOG_TRACE, LOG_LINE, "-> Header (AMQP 0.1.0.0)");
AzureIoTClient 4:98007eb79fa8 140 }
Azure.IoT Build 0:6ae2f7bca550 141
AzureIoTClient 4:98007eb79fa8 142 /* 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 24:2c59c2d43ebf 143 connection_set_state(connection, CONNECTION_STATE_HDR_SENT);
AzureIoTClient 4:98007eb79fa8 144 result = 0;
AzureIoTClient 4:98007eb79fa8 145 }
Azure.IoT Build 0:6ae2f7bca550 146
AzureIoTClient 4:98007eb79fa8 147 return result;
Azure.IoT Build 0:6ae2f7bca550 148 }
Azure.IoT Build 0:6ae2f7bca550 149
Azure.IoT Build 0:6ae2f7bca550 150 static const char* get_frame_type_as_string(AMQP_VALUE descriptor)
Azure.IoT Build 0:6ae2f7bca550 151 {
AzureIoTClient 4:98007eb79fa8 152 const char* result;
Azure.IoT Build 0:6ae2f7bca550 153
AzureIoTClient 4:98007eb79fa8 154 if (is_open_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 155 {
AzureIoTClient 4:98007eb79fa8 156 result = "[OPEN]";
AzureIoTClient 4:98007eb79fa8 157 }
AzureIoTClient 4:98007eb79fa8 158 else if (is_begin_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 159 {
AzureIoTClient 4:98007eb79fa8 160 result = "[BEGIN]";
AzureIoTClient 4:98007eb79fa8 161 }
AzureIoTClient 4:98007eb79fa8 162 else if (is_attach_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 163 {
AzureIoTClient 4:98007eb79fa8 164 result = "[ATTACH]";
AzureIoTClient 4:98007eb79fa8 165 }
AzureIoTClient 4:98007eb79fa8 166 else if (is_flow_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 167 {
AzureIoTClient 4:98007eb79fa8 168 result = "[FLOW]";
AzureIoTClient 4:98007eb79fa8 169 }
AzureIoTClient 4:98007eb79fa8 170 else if (is_disposition_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 171 {
AzureIoTClient 4:98007eb79fa8 172 result = "[DISPOSITION]";
AzureIoTClient 4:98007eb79fa8 173 }
AzureIoTClient 4:98007eb79fa8 174 else if (is_transfer_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 175 {
AzureIoTClient 4:98007eb79fa8 176 result = "[TRANSFER]";
AzureIoTClient 4:98007eb79fa8 177 }
AzureIoTClient 4:98007eb79fa8 178 else if (is_detach_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 179 {
AzureIoTClient 4:98007eb79fa8 180 result = "[DETACH]";
AzureIoTClient 4:98007eb79fa8 181 }
AzureIoTClient 4:98007eb79fa8 182 else if (is_end_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 183 {
AzureIoTClient 4:98007eb79fa8 184 result = "[END]";
AzureIoTClient 4:98007eb79fa8 185 }
AzureIoTClient 4:98007eb79fa8 186 else if (is_close_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 187 {
AzureIoTClient 4:98007eb79fa8 188 result = "[CLOSE]";
AzureIoTClient 4:98007eb79fa8 189 }
AzureIoTClient 4:98007eb79fa8 190 else
AzureIoTClient 4:98007eb79fa8 191 {
AzureIoTClient 4:98007eb79fa8 192 result = "[Unknown]";
AzureIoTClient 4:98007eb79fa8 193 }
Azure.IoT Build 0:6ae2f7bca550 194
AzureIoTClient 4:98007eb79fa8 195 return result;
Azure.IoT Build 0:6ae2f7bca550 196 }
Azure.IoT Build 0:6ae2f7bca550 197
Azure.IoT Build 5:ae49385aff34 198 static void log_incoming_frame(AMQP_VALUE performative)
Azure.IoT Build 0:6ae2f7bca550 199 {
AzureIoTClient 9:c22db038556c 200 #ifdef NO_LOGGING
AzureIoTClient 9:c22db038556c 201 UNUSED(performative);
AzureIoTClient 9:c22db038556c 202 #else
AzureIoTClient 4:98007eb79fa8 203 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
AzureIoTClient 28:add19eb7defa 204 if (descriptor == NULL)
AzureIoTClient 28:add19eb7defa 205 {
AzureIoTClient 28:add19eb7defa 206 LogError("Error getting performative descriptor");
AzureIoTClient 28:add19eb7defa 207 }
AzureIoTClient 28:add19eb7defa 208 else
AzureIoTClient 28:add19eb7defa 209 {
AzureIoTClient 28:add19eb7defa 210 char* performative_as_string;
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 25:1101516ee67d 213 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 5:ae49385aff34 223 static void log_outgoing_frame(AMQP_VALUE performative)
Azure.IoT Build 0:6ae2f7bca550 224 {
AzureIoTClient 9:c22db038556c 225 #ifdef NO_LOGGING
AzureIoTClient 9:c22db038556c 226 UNUSED(performative);
AzureIoTClient 9:c22db038556c 227 #else
AzureIoTClient 4:98007eb79fa8 228 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
AzureIoTClient 28:add19eb7defa 229 if (descriptor == NULL)
AzureIoTClient 28:add19eb7defa 230 {
AzureIoTClient 28:add19eb7defa 231 LogError("Error getting performative descriptor");
AzureIoTClient 28:add19eb7defa 232 }
AzureIoTClient 28:add19eb7defa 233 else
AzureIoTClient 28:add19eb7defa 234 {
AzureIoTClient 28:add19eb7defa 235 char* performative_as_string;
AzureIoTClient 28:add19eb7defa 236 LOG(AZ_LOG_TRACE, 0, "-> ");
AzureIoTClient 16:22a72cf8e416 237 LOG(AZ_LOG_TRACE, 0, (char*)get_frame_type_as_string(descriptor));
AzureIoTClient 25:1101516ee67d 238 performative_as_string = NULL;
AzureIoTClient 16:22a72cf8e416 239 LOG(AZ_LOG_TRACE, LOG_LINE, (performative_as_string = amqpvalue_to_string(performative)));
AzureIoTClient 4:98007eb79fa8 240 if (performative_as_string != NULL)
AzureIoTClient 4:98007eb79fa8 241 {
AzureIoTClient 21:f9c433d8e6ca 242 free(performative_as_string);
AzureIoTClient 4:98007eb79fa8 243 }
AzureIoTClient 4:98007eb79fa8 244 }
AzureIoTClient 9:c22db038556c 245 #endif
Azure.IoT Build 0:6ae2f7bca550 246 }
Azure.IoT Build 0:6ae2f7bca550 247
Azure.IoT Build 0:6ae2f7bca550 248 static void on_bytes_encoded(void* context, const unsigned char* bytes, size_t length, bool encode_complete)
Azure.IoT Build 0:6ae2f7bca550 249 {
AzureIoTClient 24:2c59c2d43ebf 250 CONNECTION_HANDLE connection = (CONNECTION_HANDLE)context;
AzureIoTClient 38:7631b92cc772 251 if (xio_send(connection->io, bytes, length,
AzureIoTClient 38:7631b92cc772 252 (encode_complete && connection->on_send_complete != NULL) ? connection->on_send_complete : unchecked_on_send_complete,
AzureIoTClient 38:7631b92cc772 253 connection->on_send_complete_callback_context) != 0)
AzureIoTClient 4:98007eb79fa8 254 {
AzureIoTClient 28:add19eb7defa 255 LogError("Cannot send encoded bytes");
AzureIoTClient 24:2c59c2d43ebf 256
AzureIoTClient 28:add19eb7defa 257 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 258 {
AzureIoTClient 28:add19eb7defa 259 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 260 }
AzureIoTClient 24:2c59c2d43ebf 261
AzureIoTClient 24:2c59c2d43ebf 262 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 263 }
Azure.IoT Build 0:6ae2f7bca550 264 }
Azure.IoT Build 0:6ae2f7bca550 265
AzureIoTClient 24:2c59c2d43ebf 266 static int send_open_frame(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 267 {
AzureIoTClient 4:98007eb79fa8 268 int result;
Azure.IoT Build 0:6ae2f7bca550 269
AzureIoTClient 4:98007eb79fa8 270 /* 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 24:2c59c2d43ebf 271 if (frame_codec_set_max_frame_size(connection->frame_codec, connection->max_frame_size) != 0)
AzureIoTClient 4:98007eb79fa8 272 {
AzureIoTClient 28:add19eb7defa 273 LogError("Cannot set max frame size");
AzureIoTClient 24:2c59c2d43ebf 274
AzureIoTClient 4:98007eb79fa8 275 /* 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 28:add19eb7defa 276 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 277 {
AzureIoTClient 28:add19eb7defa 278 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 279 }
AzureIoTClient 24:2c59c2d43ebf 280
AzureIoTClient 28:add19eb7defa 281 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 282 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 283 }
AzureIoTClient 4:98007eb79fa8 284 else
AzureIoTClient 4:98007eb79fa8 285 {
AzureIoTClient 4:98007eb79fa8 286 /* Codes_SRS_CONNECTION_01_134: [The container id field shall be filled with the container id specified in connection_create.] */
AzureIoTClient 24:2c59c2d43ebf 287 OPEN_HANDLE open_performative = open_create(connection->container_id);
AzureIoTClient 4:98007eb79fa8 288 if (open_performative == NULL)
AzureIoTClient 4:98007eb79fa8 289 {
AzureIoTClient 28:add19eb7defa 290 LogError("Cannot create OPEN performative");
AzureIoTClient 28:add19eb7defa 291
AzureIoTClient 28:add19eb7defa 292 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 28:add19eb7defa 293 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 294 {
AzureIoTClient 28:add19eb7defa 295 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 296 }
AzureIoTClient 24:2c59c2d43ebf 297
AzureIoTClient 28:add19eb7defa 298 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 299 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 300 }
AzureIoTClient 4:98007eb79fa8 301 else
AzureIoTClient 4:98007eb79fa8 302 {
AzureIoTClient 4:98007eb79fa8 303 /* 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 24:2c59c2d43ebf 304 if (open_set_max_frame_size(open_performative, connection->max_frame_size) != 0)
AzureIoTClient 4:98007eb79fa8 305 {
AzureIoTClient 28:add19eb7defa 306 LogError("Cannot set max frame size");
AzureIoTClient 24:2c59c2d43ebf 307
AzureIoTClient 28:add19eb7defa 308 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 28:add19eb7defa 309 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 310 {
AzureIoTClient 28:add19eb7defa 311 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 312 }
AzureIoTClient 24:2c59c2d43ebf 313
AzureIoTClient 28:add19eb7defa 314 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 315 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 316 }
AzureIoTClient 4:98007eb79fa8 317 /* Codes_SRS_CONNECTION_01_139: [The channel_max connection setting shall be set in the open frame by using open_set_channel_max.] */
AzureIoTClient 24:2c59c2d43ebf 318 else if (open_set_channel_max(open_performative, connection->channel_max) != 0)
AzureIoTClient 4:98007eb79fa8 319 {
AzureIoTClient 28:add19eb7defa 320 LogError("Cannot set max channel");
AzureIoTClient 24:2c59c2d43ebf 321
AzureIoTClient 28:add19eb7defa 322 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 28:add19eb7defa 323 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 324 {
AzureIoTClient 28:add19eb7defa 325 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 326 }
AzureIoTClient 24:2c59c2d43ebf 327
AzureIoTClient 28:add19eb7defa 328 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 329 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 330 }
AzureIoTClient 4:98007eb79fa8 331 /* 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 24:2c59c2d43ebf 332 else if ((connection->idle_timeout_specified) &&
AzureIoTClient 4:98007eb79fa8 333 /* 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 24:2c59c2d43ebf 334 (open_set_idle_time_out(open_performative, connection->idle_timeout) != 0))
AzureIoTClient 4:98007eb79fa8 335 {
AzureIoTClient 4:98007eb79fa8 336 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 28:add19eb7defa 337 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 338 {
AzureIoTClient 28:add19eb7defa 339 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 340 }
AzureIoTClient 24:2c59c2d43ebf 341
AzureIoTClient 28:add19eb7defa 342 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 343 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 344 }
AzureIoTClient 4:98007eb79fa8 345 /* 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 24:2c59c2d43ebf 346 else if ((connection->host_name != NULL) &&
AzureIoTClient 4:98007eb79fa8 347 /* 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 24:2c59c2d43ebf 348 (open_set_hostname(open_performative, connection->host_name) != 0))
AzureIoTClient 4:98007eb79fa8 349 {
AzureIoTClient 28:add19eb7defa 350 LogError("Cannot set hostname");
AzureIoTClient 24:2c59c2d43ebf 351
AzureIoTClient 28:add19eb7defa 352 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 28:add19eb7defa 353 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 354 {
AzureIoTClient 28:add19eb7defa 355 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 356 }
AzureIoTClient 24:2c59c2d43ebf 357
AzureIoTClient 28:add19eb7defa 358 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 359 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 360 }
AzureIoTClient 41:0e723f9cbd89 361 /* Codes_SRS_CONNECTION_01_243: [If no properties value has been specified, no value shall be stamped in the open frame (no call to open_set_properties shall be made).] */
AzureIoTClient 41:0e723f9cbd89 362 else if ((connection->properties != NULL) &&
AzureIoTClient 41:0e723f9cbd89 363 /* Codes_SRS_CONNECTION_01_244: [If properties has been specified by a call to connection_set_properties, then that value shall be stamped in the open frame.] */
AzureIoTClient 41:0e723f9cbd89 364 (open_set_properties(open_performative, connection->properties) != 0))
AzureIoTClient 41:0e723f9cbd89 365 {
AzureIoTClient 41:0e723f9cbd89 366 LogError("Cannot set properties");
AzureIoTClient 41:0e723f9cbd89 367
AzureIoTClient 41:0e723f9cbd89 368 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 41:0e723f9cbd89 369 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 41:0e723f9cbd89 370 {
AzureIoTClient 41:0e723f9cbd89 371 LogError("xio_close failed");
AzureIoTClient 41:0e723f9cbd89 372 }
AzureIoTClient 41:0e723f9cbd89 373
AzureIoTClient 41:0e723f9cbd89 374 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 41:0e723f9cbd89 375 result = __FAILURE__;
AzureIoTClient 41:0e723f9cbd89 376 }
AzureIoTClient 4:98007eb79fa8 377 else
AzureIoTClient 4:98007eb79fa8 378 {
AzureIoTClient 4:98007eb79fa8 379 AMQP_VALUE open_performative_value = amqpvalue_create_open(open_performative);
AzureIoTClient 4:98007eb79fa8 380 if (open_performative_value == NULL)
AzureIoTClient 4:98007eb79fa8 381 {
AzureIoTClient 28:add19eb7defa 382 LogError("Cannot create OPEN AMQP value");
AzureIoTClient 24:2c59c2d43ebf 383
AzureIoTClient 28:add19eb7defa 384 /* Codes_SRS_CONNECTION_01_208: [If the open frame cannot be constructed, the connection shall be closed and set to the END state.] */
AzureIoTClient 28:add19eb7defa 385 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 386 {
AzureIoTClient 28:add19eb7defa 387 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 388 }
AzureIoTClient 24:2c59c2d43ebf 389
AzureIoTClient 28:add19eb7defa 390 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 391 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 392 }
AzureIoTClient 4:98007eb79fa8 393 else
AzureIoTClient 4:98007eb79fa8 394 {
AzureIoTClient 4:98007eb79fa8 395 /* Codes_SRS_CONNECTION_01_002: [Each AMQP connection begins with an exchange of capabilities and limitations, including the maximum frame size.] */
AzureIoTClient 4:98007eb79fa8 396 /* 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 397 /* Codes_SRS_CONNECTION_01_005: [The open frame describes the capabilities and limits of that peer.] */
AzureIoTClient 4:98007eb79fa8 398 /* 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 399 /* Codes_SRS_CONNECTION_01_006: [The open frame can only be sent on channel 0.] */
AzureIoTClient 28:add19eb7defa 400 connection->on_send_complete = NULL;
AzureIoTClient 28:add19eb7defa 401 connection->on_send_complete_callback_context = NULL;
AzureIoTClient 24:2c59c2d43ebf 402 if (amqp_frame_codec_encode_frame(connection->amqp_frame_codec, 0, open_performative_value, NULL, 0, on_bytes_encoded, connection) != 0)
AzureIoTClient 4:98007eb79fa8 403 {
AzureIoTClient 28:add19eb7defa 404 LogError("amqp_frame_codec_encode_frame failed");
AzureIoTClient 24:2c59c2d43ebf 405
AzureIoTClient 28:add19eb7defa 406 /* Codes_SRS_CONNECTION_01_206: [If sending the frame fails, the connection shall be closed and state set to END.] */
AzureIoTClient 28:add19eb7defa 407 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 408 {
AzureIoTClient 28:add19eb7defa 409 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 410 }
AzureIoTClient 24:2c59c2d43ebf 411
AzureIoTClient 28:add19eb7defa 412 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 413 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 414 }
AzureIoTClient 4:98007eb79fa8 415 else
AzureIoTClient 4:98007eb79fa8 416 {
AzureIoTClient 24:2c59c2d43ebf 417 if (connection->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 418 {
Azure.IoT Build 5:ae49385aff34 419 log_outgoing_frame(open_performative_value);
AzureIoTClient 4:98007eb79fa8 420 }
Azure.IoT Build 0:6ae2f7bca550 421
AzureIoTClient 4:98007eb79fa8 422 /* 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 24:2c59c2d43ebf 423 connection_set_state(connection, CONNECTION_STATE_OPEN_SENT);
AzureIoTClient 4:98007eb79fa8 424 result = 0;
AzureIoTClient 4:98007eb79fa8 425 }
Azure.IoT Build 0:6ae2f7bca550 426
AzureIoTClient 4:98007eb79fa8 427 amqpvalue_destroy(open_performative_value);
AzureIoTClient 4:98007eb79fa8 428 }
AzureIoTClient 4:98007eb79fa8 429 }
Azure.IoT Build 0:6ae2f7bca550 430
AzureIoTClient 4:98007eb79fa8 431 open_destroy(open_performative);
AzureIoTClient 4:98007eb79fa8 432 }
AzureIoTClient 4:98007eb79fa8 433 }
Azure.IoT Build 0:6ae2f7bca550 434
AzureIoTClient 4:98007eb79fa8 435 return result;
Azure.IoT Build 0:6ae2f7bca550 436 }
Azure.IoT Build 0:6ae2f7bca550 437
AzureIoTClient 24:2c59c2d43ebf 438 static int send_close_frame(CONNECTION_HANDLE connection, ERROR_HANDLE error_handle)
Azure.IoT Build 0:6ae2f7bca550 439 {
AzureIoTClient 4:98007eb79fa8 440 int result;
AzureIoTClient 4:98007eb79fa8 441 CLOSE_HANDLE close_performative;
Azure.IoT Build 0:6ae2f7bca550 442
AzureIoTClient 4:98007eb79fa8 443 /* Codes_SRS_CONNECTION_01_217: [The CLOSE frame shall be constructed by using close_create.] */
AzureIoTClient 4:98007eb79fa8 444 close_performative = close_create();
AzureIoTClient 4:98007eb79fa8 445 if (close_performative == NULL)
AzureIoTClient 4:98007eb79fa8 446 {
AzureIoTClient 28:add19eb7defa 447 LogError("Cannot create close performative");
AzureIoTClient 28:add19eb7defa 448 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 449 }
AzureIoTClient 4:98007eb79fa8 450 else
AzureIoTClient 4:98007eb79fa8 451 {
AzureIoTClient 4:98007eb79fa8 452 if ((error_handle != NULL) &&
AzureIoTClient 4:98007eb79fa8 453 /* Codes_SRS_CONNECTION_01_238: [If set, this field indicates that the connection is being closed due to an error condition.] */
AzureIoTClient 4:98007eb79fa8 454 (close_set_error(close_performative, error_handle) != 0))
AzureIoTClient 4:98007eb79fa8 455 {
AzureIoTClient 28:add19eb7defa 456 LogError("Cannot set error on CLOSE");
AzureIoTClient 28:add19eb7defa 457 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 458 }
AzureIoTClient 4:98007eb79fa8 459 else
AzureIoTClient 4:98007eb79fa8 460 {
AzureIoTClient 4:98007eb79fa8 461 AMQP_VALUE close_performative_value = amqpvalue_create_close(close_performative);
AzureIoTClient 4:98007eb79fa8 462 if (close_performative_value == NULL)
AzureIoTClient 4:98007eb79fa8 463 {
AzureIoTClient 28:add19eb7defa 464 LogError("Cannot create AMQP CLOSE performative value");
AzureIoTClient 28:add19eb7defa 465 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 466 }
AzureIoTClient 4:98007eb79fa8 467 else
AzureIoTClient 4:98007eb79fa8 468 {
AzureIoTClient 4:98007eb79fa8 469 /* 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 470 /* Codes_SRS_CONNECTION_01_013: [However, implementations SHOULD send it on channel 0] */
AzureIoTClient 28:add19eb7defa 471 connection->on_send_complete = NULL;
AzureIoTClient 28:add19eb7defa 472 connection->on_send_complete_callback_context = NULL;
AzureIoTClient 24:2c59c2d43ebf 473 if (amqp_frame_codec_encode_frame(connection->amqp_frame_codec, 0, close_performative_value, NULL, 0, on_bytes_encoded, connection) != 0)
AzureIoTClient 4:98007eb79fa8 474 {
AzureIoTClient 28:add19eb7defa 475 LogError("amqp_frame_codec_encode_frame failed");
AzureIoTClient 28:add19eb7defa 476 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 477 }
AzureIoTClient 4:98007eb79fa8 478 else
AzureIoTClient 4:98007eb79fa8 479 {
AzureIoTClient 24:2c59c2d43ebf 480 if (connection->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 481 {
Azure.IoT Build 5:ae49385aff34 482 log_outgoing_frame(close_performative_value);
AzureIoTClient 4:98007eb79fa8 483 }
Azure.IoT Build 5:ae49385aff34 484
AzureIoTClient 4:98007eb79fa8 485 result = 0;
AzureIoTClient 4:98007eb79fa8 486 }
Azure.IoT Build 0:6ae2f7bca550 487
AzureIoTClient 4:98007eb79fa8 488 amqpvalue_destroy(close_performative_value);
AzureIoTClient 4:98007eb79fa8 489 }
AzureIoTClient 4:98007eb79fa8 490 }
Azure.IoT Build 0:6ae2f7bca550 491
AzureIoTClient 4:98007eb79fa8 492 close_destroy(close_performative);
AzureIoTClient 4:98007eb79fa8 493 }
Azure.IoT Build 0:6ae2f7bca550 494
AzureIoTClient 4:98007eb79fa8 495 return result;
Azure.IoT Build 0:6ae2f7bca550 496 }
Azure.IoT Build 0:6ae2f7bca550 497
AzureIoTClient 24:2c59c2d43ebf 498 static void close_connection_with_error(CONNECTION_HANDLE connection, const char* condition_value, const char* description)
Azure.IoT Build 0:6ae2f7bca550 499 {
AzureIoTClient 4:98007eb79fa8 500 ERROR_HANDLE error_handle = error_create(condition_value);
AzureIoTClient 4:98007eb79fa8 501 if (error_handle == NULL)
AzureIoTClient 4:98007eb79fa8 502 {
AzureIoTClient 4:98007eb79fa8 503 /* 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 28:add19eb7defa 504 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 505 {
AzureIoTClient 28:add19eb7defa 506 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 507 }
AzureIoTClient 24:2c59c2d43ebf 508
AzureIoTClient 28:add19eb7defa 509 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 510 }
AzureIoTClient 4:98007eb79fa8 511 else
AzureIoTClient 4:98007eb79fa8 512 {
AzureIoTClient 4:98007eb79fa8 513 /* Codes_SRS_CONNECTION_01_219: [The error description shall be set to an implementation defined string.] */
AzureIoTClient 28:add19eb7defa 514 if (error_set_description(error_handle, description) != 0)
AzureIoTClient 28:add19eb7defa 515 {
AzureIoTClient 28:add19eb7defa 516 LogError("Cannot set error description on CLOSE frame");
AzureIoTClient 24:2c59c2d43ebf 517
AzureIoTClient 28:add19eb7defa 518 /* 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 28:add19eb7defa 519 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 520 {
AzureIoTClient 28:add19eb7defa 521 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 522 }
AzureIoTClient 24:2c59c2d43ebf 523
AzureIoTClient 28:add19eb7defa 524 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 28:add19eb7defa 525 }
AzureIoTClient 28:add19eb7defa 526 else if (send_close_frame(connection, error_handle) != 0)
AzureIoTClient 28:add19eb7defa 527 {
AzureIoTClient 28:add19eb7defa 528 LogError("Cannot send CLOSE frame");
AzureIoTClient 24:2c59c2d43ebf 529
AzureIoTClient 28:add19eb7defa 530 /* 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 28:add19eb7defa 531 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 532 {
AzureIoTClient 28:add19eb7defa 533 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 534 }
AzureIoTClient 24:2c59c2d43ebf 535
AzureIoTClient 24:2c59c2d43ebf 536 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 537 }
AzureIoTClient 4:98007eb79fa8 538 else
AzureIoTClient 4:98007eb79fa8 539 {
AzureIoTClient 4:98007eb79fa8 540 /* 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 541 /* 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 542 /* 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 24:2c59c2d43ebf 543 connection_set_state(connection, CONNECTION_STATE_DISCARDING);
AzureIoTClient 4:98007eb79fa8 544 }
Azure.IoT Build 0:6ae2f7bca550 545
AzureIoTClient 4:98007eb79fa8 546 error_destroy(error_handle);
AzureIoTClient 4:98007eb79fa8 547 }
Azure.IoT Build 0:6ae2f7bca550 548 }
Azure.IoT Build 0:6ae2f7bca550 549
AzureIoTClient 24:2c59c2d43ebf 550 static ENDPOINT_INSTANCE* find_session_endpoint_by_outgoing_channel(CONNECTION_HANDLE connection, uint16_t outgoing_channel)
Azure.IoT Build 0:6ae2f7bca550 551 {
AzureIoTClient 4:98007eb79fa8 552 uint32_t i;
AzureIoTClient 4:98007eb79fa8 553 ENDPOINT_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 554
AzureIoTClient 4:98007eb79fa8 555 for (i = 0; i < connection->endpoint_count; i++)
AzureIoTClient 4:98007eb79fa8 556 {
AzureIoTClient 4:98007eb79fa8 557 if (connection->endpoints[i]->outgoing_channel == outgoing_channel)
AzureIoTClient 4:98007eb79fa8 558 {
AzureIoTClient 4:98007eb79fa8 559 break;
AzureIoTClient 4:98007eb79fa8 560 }
AzureIoTClient 4:98007eb79fa8 561 }
Azure.IoT Build 0:6ae2f7bca550 562
AzureIoTClient 4:98007eb79fa8 563 if (i == connection->endpoint_count)
AzureIoTClient 4:98007eb79fa8 564 {
AzureIoTClient 28:add19eb7defa 565 LogError("Cannot find session endpoint for channel %u", (unsigned int)outgoing_channel);
AzureIoTClient 28:add19eb7defa 566 result = NULL;
AzureIoTClient 4:98007eb79fa8 567 }
AzureIoTClient 4:98007eb79fa8 568 else
AzureIoTClient 4:98007eb79fa8 569 {
AzureIoTClient 4:98007eb79fa8 570 result = connection->endpoints[i];
AzureIoTClient 4:98007eb79fa8 571 }
Azure.IoT Build 0:6ae2f7bca550 572
AzureIoTClient 4:98007eb79fa8 573 return result;
Azure.IoT Build 0:6ae2f7bca550 574 }
Azure.IoT Build 0:6ae2f7bca550 575
AzureIoTClient 24:2c59c2d43ebf 576 static ENDPOINT_INSTANCE* find_session_endpoint_by_incoming_channel(CONNECTION_HANDLE connection, uint16_t incoming_channel)
Azure.IoT Build 0:6ae2f7bca550 577 {
AzureIoTClient 4:98007eb79fa8 578 uint32_t i;
AzureIoTClient 4:98007eb79fa8 579 ENDPOINT_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 580
AzureIoTClient 4:98007eb79fa8 581 for (i = 0; i < connection->endpoint_count; i++)
AzureIoTClient 4:98007eb79fa8 582 {
AzureIoTClient 4:98007eb79fa8 583 if (connection->endpoints[i]->incoming_channel == incoming_channel)
AzureIoTClient 4:98007eb79fa8 584 {
AzureIoTClient 4:98007eb79fa8 585 break;
AzureIoTClient 4:98007eb79fa8 586 }
AzureIoTClient 4:98007eb79fa8 587 }
Azure.IoT Build 0:6ae2f7bca550 588
AzureIoTClient 4:98007eb79fa8 589 if (i == connection->endpoint_count)
AzureIoTClient 4:98007eb79fa8 590 {
AzureIoTClient 28:add19eb7defa 591 LogError("Cannot find session endpoint for channel %u", (unsigned int)incoming_channel);
AzureIoTClient 28:add19eb7defa 592 result = NULL;
AzureIoTClient 4:98007eb79fa8 593 }
AzureIoTClient 4:98007eb79fa8 594 else
AzureIoTClient 4:98007eb79fa8 595 {
AzureIoTClient 4:98007eb79fa8 596 result = connection->endpoints[i];
AzureIoTClient 4:98007eb79fa8 597 }
Azure.IoT Build 0:6ae2f7bca550 598
AzureIoTClient 4:98007eb79fa8 599 return result;
Azure.IoT Build 0:6ae2f7bca550 600 }
Azure.IoT Build 0:6ae2f7bca550 601
AzureIoTClient 24:2c59c2d43ebf 602 static int connection_byte_received(CONNECTION_HANDLE connection, unsigned char b)
Azure.IoT Build 0:6ae2f7bca550 603 {
AzureIoTClient 4:98007eb79fa8 604 int result;
Azure.IoT Build 0:6ae2f7bca550 605
AzureIoTClient 24:2c59c2d43ebf 606 switch (connection->connection_state)
AzureIoTClient 4:98007eb79fa8 607 {
AzureIoTClient 4:98007eb79fa8 608 default:
AzureIoTClient 28:add19eb7defa 609 LogError("Unknown connection state: %d", (int)connection->connection_state);
AzureIoTClient 28:add19eb7defa 610 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 611 break;
Azure.IoT Build 0:6ae2f7bca550 612
AzureIoTClient 4:98007eb79fa8 613 /* 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 614 case CONNECTION_STATE_START:
Azure.IoT Build 0:6ae2f7bca550 615
AzureIoTClient 4:98007eb79fa8 616 /* 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 617 case CONNECTION_STATE_HDR_SENT:
AzureIoTClient 24:2c59c2d43ebf 618 if (b != amqp_header[connection->header_bytes_received])
AzureIoTClient 4:98007eb79fa8 619 {
AzureIoTClient 4:98007eb79fa8 620 /* Codes_SRS_CONNECTION_01_089: [If the incoming and outgoing protocol headers do not match, both peers MUST close their outgoing stream] */
AzureIoTClient 28:add19eb7defa 621 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 622 {
AzureIoTClient 28:add19eb7defa 623 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 624 }
AzureIoTClient 24:2c59c2d43ebf 625
AzureIoTClient 28:add19eb7defa 626 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 627 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 628 }
AzureIoTClient 4:98007eb79fa8 629 else
AzureIoTClient 4:98007eb79fa8 630 {
AzureIoTClient 28:add19eb7defa 631 connection->header_bytes_received++;
AzureIoTClient 24:2c59c2d43ebf 632 if (connection->header_bytes_received == sizeof(amqp_header))
AzureIoTClient 4:98007eb79fa8 633 {
AzureIoTClient 24:2c59c2d43ebf 634 if (connection->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 635 {
AzureIoTClient 16:22a72cf8e416 636 LOG(AZ_LOG_TRACE, LOG_LINE, "<- Header (AMQP 0.1.0.0)");
AzureIoTClient 4:98007eb79fa8 637 }
Azure.IoT Build 0:6ae2f7bca550 638
AzureIoTClient 24:2c59c2d43ebf 639 connection_set_state(connection, CONNECTION_STATE_HDR_EXCH);
Azure.IoT Build 0:6ae2f7bca550 640
AzureIoTClient 24:2c59c2d43ebf 641 if (send_open_frame(connection) != 0)
AzureIoTClient 4:98007eb79fa8 642 {
AzureIoTClient 28:add19eb7defa 643 LogError("Cannot send open frame");
AzureIoTClient 28:add19eb7defa 644 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 645 }
AzureIoTClient 4:98007eb79fa8 646 }
Azure.IoT Build 0:6ae2f7bca550 647
AzureIoTClient 4:98007eb79fa8 648 result = 0;
AzureIoTClient 4:98007eb79fa8 649 }
AzureIoTClient 4:98007eb79fa8 650 break;
Azure.IoT Build 0:6ae2f7bca550 651
AzureIoTClient 4:98007eb79fa8 652 /* 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 653 case CONNECTION_STATE_HDR_RCVD:
Azure.IoT Build 0:6ae2f7bca550 654
AzureIoTClient 4:98007eb79fa8 655 /* 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 656 /* 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 657 case CONNECTION_STATE_HDR_EXCH:
Azure.IoT Build 0:6ae2f7bca550 658
AzureIoTClient 4:98007eb79fa8 659 /* 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 660 case CONNECTION_STATE_OPEN_RCVD:
Azure.IoT Build 0:6ae2f7bca550 661
AzureIoTClient 4:98007eb79fa8 662 /* 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 663 case CONNECTION_STATE_OPEN_SENT:
Azure.IoT Build 0:6ae2f7bca550 664
AzureIoTClient 4:98007eb79fa8 665 /* 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 666 case CONNECTION_STATE_OPENED:
AzureIoTClient 4:98007eb79fa8 667 /* 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 24:2c59c2d43ebf 668 if (frame_codec_receive_bytes(connection->frame_codec, &b, 1) != 0)
AzureIoTClient 4:98007eb79fa8 669 {
AzureIoTClient 28:add19eb7defa 670 LogError("Cannot process received bytes");
AzureIoTClient 28:add19eb7defa 671 /* 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 672 /* Codes_SRS_CONNECTION_01_219: [The error description shall be set to an implementation defined string.] */
AzureIoTClient 24:2c59c2d43ebf 673 close_connection_with_error(connection, "amqp:internal-error", "connection_byte_received::frame_codec_receive_bytes failed");
AzureIoTClient 19:000ab4e6a2c1 674 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 675 }
AzureIoTClient 4:98007eb79fa8 676 else
AzureIoTClient 4:98007eb79fa8 677 {
AzureIoTClient 4:98007eb79fa8 678 result = 0;
AzureIoTClient 4:98007eb79fa8 679 }
Azure.IoT Build 0:6ae2f7bca550 680
AzureIoTClient 4:98007eb79fa8 681 break;
AzureIoTClient 4:98007eb79fa8 682 }
AzureIoTClient 4:98007eb79fa8 683
AzureIoTClient 4:98007eb79fa8 684 return result;
Azure.IoT Build 0:6ae2f7bca550 685 }
Azure.IoT Build 0:6ae2f7bca550 686
Azure.IoT Build 0:6ae2f7bca550 687 static void connection_on_bytes_received(void* context, const unsigned char* buffer, size_t size)
Azure.IoT Build 0:6ae2f7bca550 688 {
AzureIoTClient 4:98007eb79fa8 689 size_t i;
Azure.IoT Build 0:6ae2f7bca550 690
AzureIoTClient 4:98007eb79fa8 691 for (i = 0; i < size; i++)
AzureIoTClient 4:98007eb79fa8 692 {
AzureIoTClient 24:2c59c2d43ebf 693 if (connection_byte_received((CONNECTION_HANDLE)context, buffer[i]) != 0)
AzureIoTClient 4:98007eb79fa8 694 {
AzureIoTClient 28:add19eb7defa 695 LogError("Cannot process received bytes");
AzureIoTClient 28:add19eb7defa 696 break;
AzureIoTClient 4:98007eb79fa8 697 }
AzureIoTClient 4:98007eb79fa8 698 }
Azure.IoT Build 0:6ae2f7bca550 699 }
Azure.IoT Build 0:6ae2f7bca550 700
Azure.IoT Build 0:6ae2f7bca550 701 static void connection_on_io_open_complete(void* context, IO_OPEN_RESULT io_open_result)
Azure.IoT Build 0:6ae2f7bca550 702 {
AzureIoTClient 24:2c59c2d43ebf 703 CONNECTION_HANDLE connection = (CONNECTION_HANDLE)context;
Azure.IoT Build 0:6ae2f7bca550 704
AzureIoTClient 4:98007eb79fa8 705 if (io_open_result == IO_OPEN_OK)
AzureIoTClient 4:98007eb79fa8 706 {
AzureIoTClient 4:98007eb79fa8 707 /* Codes_SRS_CONNECTION_01_084: [The connection_instance state machine implementing the protocol requirements shall be run as part of connection_dowork.] */
AzureIoTClient 24:2c59c2d43ebf 708 switch (connection->connection_state)
AzureIoTClient 4:98007eb79fa8 709 {
AzureIoTClient 4:98007eb79fa8 710 default:
AzureIoTClient 28:add19eb7defa 711 LogError("Unknown connection state: %d", (int)connection->connection_state);
AzureIoTClient 28:add19eb7defa 712 break;
Azure.IoT Build 0:6ae2f7bca550 713
AzureIoTClient 4:98007eb79fa8 714 case CONNECTION_STATE_START:
AzureIoTClient 4:98007eb79fa8 715 /* 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 716 /* 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 28:add19eb7defa 717 if (send_header(connection) != 0)
AzureIoTClient 28:add19eb7defa 718 {
AzureIoTClient 28:add19eb7defa 719 LogError("Cannot send header");
AzureIoTClient 28:add19eb7defa 720 }
AzureIoTClient 4:98007eb79fa8 721 break;
Azure.IoT Build 0:6ae2f7bca550 722
AzureIoTClient 4:98007eb79fa8 723 case CONNECTION_STATE_HDR_SENT:
AzureIoTClient 4:98007eb79fa8 724 case CONNECTION_STATE_OPEN_SENT:
AzureIoTClient 4:98007eb79fa8 725 case CONNECTION_STATE_OPENED:
AzureIoTClient 4:98007eb79fa8 726 break;
Azure.IoT Build 0:6ae2f7bca550 727
AzureIoTClient 4:98007eb79fa8 728 case CONNECTION_STATE_HDR_EXCH:
AzureIoTClient 4:98007eb79fa8 729 /* 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 730 /* 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 731 /* Codes_SRS_CONNECTION_01_005: [The open frame describes the capabilities and limits of that peer.] */
AzureIoTClient 24:2c59c2d43ebf 732 if (send_open_frame(connection) != 0)
AzureIoTClient 4:98007eb79fa8 733 {
AzureIoTClient 28:add19eb7defa 734 LogError("Cannot send OPEN frame");
AzureIoTClient 28:add19eb7defa 735 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 736 }
AzureIoTClient 4:98007eb79fa8 737 break;
Azure.IoT Build 0:6ae2f7bca550 738
AzureIoTClient 4:98007eb79fa8 739 case CONNECTION_STATE_OPEN_RCVD:
AzureIoTClient 4:98007eb79fa8 740 break;
AzureIoTClient 4:98007eb79fa8 741 }
AzureIoTClient 4:98007eb79fa8 742 }
AzureIoTClient 4:98007eb79fa8 743 else
AzureIoTClient 4:98007eb79fa8 744 {
AzureIoTClient 24:2c59c2d43ebf 745 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 746 }
Azure.IoT Build 0:6ae2f7bca550 747 }
Azure.IoT Build 0:6ae2f7bca550 748
Azure.IoT Build 0:6ae2f7bca550 749 static void connection_on_io_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 750 {
AzureIoTClient 28:add19eb7defa 751 CONNECTION_HANDLE connection = (CONNECTION_HANDLE)context;
Azure.IoT Build 0:6ae2f7bca550 752
Azure.IoT Build 0:6ae2f7bca550 753 /* 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.] */
AzureIoTClient 24:2c59c2d43ebf 754 if (connection->on_io_error)
Azure.IoT Build 0:6ae2f7bca550 755 {
AzureIoTClient 28:add19eb7defa 756 connection->on_io_error(connection->on_io_error_callback_context);
Azure.IoT Build 0:6ae2f7bca550 757 }
Azure.IoT Build 0:6ae2f7bca550 758
AzureIoTClient 24:2c59c2d43ebf 759 if (connection->connection_state != CONNECTION_STATE_END)
AzureIoTClient 4:98007eb79fa8 760 {
AzureIoTClient 4:98007eb79fa8 761 /* 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 24:2c59c2d43ebf 762 connection_set_state(connection, CONNECTION_STATE_ERROR);
AzureIoTClient 28:add19eb7defa 763 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 764 {
AzureIoTClient 28:add19eb7defa 765 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 766 }
AzureIoTClient 28:add19eb7defa 767 }
Azure.IoT Build 0:6ae2f7bca550 768 }
Azure.IoT Build 0:6ae2f7bca550 769
Azure.IoT Build 0:6ae2f7bca550 770 static void on_empty_amqp_frame_received(void* context, uint16_t channel)
Azure.IoT Build 0:6ae2f7bca550 771 {
AzureIoTClient 28:add19eb7defa 772 CONNECTION_HANDLE connection = (CONNECTION_HANDLE)context;
AzureIoTClient 28:add19eb7defa 773 /* It does not matter on which channel we received the frame */
AzureIoTClient 28:add19eb7defa 774 (void)channel;
AzureIoTClient 24:2c59c2d43ebf 775
AzureIoTClient 28:add19eb7defa 776 if (connection->is_trace_on == 1)
AzureIoTClient 6:641a9672db08 777 {
AzureIoTClient 16:22a72cf8e416 778 LOG(AZ_LOG_TRACE, LOG_LINE, "<- Empty frame");
AzureIoTClient 6:641a9672db08 779 }
AzureIoTClient 24:2c59c2d43ebf 780 if (tickcounter_get_current_ms(connection->tick_counter, &connection->last_frame_received_time) != 0)
AzureIoTClient 4:98007eb79fa8 781 {
AzureIoTClient 28:add19eb7defa 782 LogError("Cannot get tickcounter value");
AzureIoTClient 28:add19eb7defa 783 }
Azure.IoT Build 0:6ae2f7bca550 784 }
Azure.IoT Build 0:6ae2f7bca550 785
Azure.IoT Build 0:6ae2f7bca550 786 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 787 {
AzureIoTClient 24:2c59c2d43ebf 788 CONNECTION_HANDLE connection = (CONNECTION_HANDLE)context;
AzureIoTClient 24:2c59c2d43ebf 789
AzureIoTClient 28:add19eb7defa 790 (void)channel;
Azure.IoT Build 0:6ae2f7bca550 791
AzureIoTClient 24:2c59c2d43ebf 792 if (tickcounter_get_current_ms(connection->tick_counter, &connection->last_frame_received_time) != 0)
AzureIoTClient 4:98007eb79fa8 793 {
AzureIoTClient 28:add19eb7defa 794 LogError("Cannot get tickcounter value");
AzureIoTClient 28:add19eb7defa 795 close_connection_with_error(connection, "amqp:internal-error", "cannot get current tick count");
AzureIoTClient 4:98007eb79fa8 796 }
AzureIoTClient 4:98007eb79fa8 797 else
AzureIoTClient 4:98007eb79fa8 798 {
AzureIoTClient 24:2c59c2d43ebf 799 if (connection->is_underlying_io_open)
AzureIoTClient 4:98007eb79fa8 800 {
AzureIoTClient 24:2c59c2d43ebf 801 switch (connection->connection_state)
AzureIoTClient 4:98007eb79fa8 802 {
AzureIoTClient 4:98007eb79fa8 803 default:
AzureIoTClient 4:98007eb79fa8 804 if (performative == NULL)
AzureIoTClient 4:98007eb79fa8 805 {
AzureIoTClient 28:add19eb7defa 806 /* 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 24:2c59c2d43ebf 807 close_connection_with_error(connection, "amqp:internal-error", "connection_endpoint_frame_received::NULL performative");
AzureIoTClient 28:add19eb7defa 808 LogError("connection_endpoint_frame_received::NULL performative");
AzureIoTClient 28:add19eb7defa 809 }
AzureIoTClient 4:98007eb79fa8 810 else
AzureIoTClient 4:98007eb79fa8 811 {
AzureIoTClient 4:98007eb79fa8 812 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
AzureIoTClient 4:98007eb79fa8 813 uint64_t performative_ulong;
Azure.IoT Build 0:6ae2f7bca550 814
AzureIoTClient 24:2c59c2d43ebf 815 if (connection->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 816 {
Azure.IoT Build 5:ae49385aff34 817 log_incoming_frame(performative);
AzureIoTClient 4:98007eb79fa8 818 }
Azure.IoT Build 0:6ae2f7bca550 819
AzureIoTClient 4:98007eb79fa8 820 if (is_open_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 821 {
AzureIoTClient 4:98007eb79fa8 822 if (channel != 0)
AzureIoTClient 4:98007eb79fa8 823 {
AzureIoTClient 28:add19eb7defa 824 /* Codes_SRS_CONNECTION_01_006: [The open frame can only be sent on channel 0.] */
AzureIoTClient 4:98007eb79fa8 825 /* 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 24:2c59c2d43ebf 826 close_connection_with_error(connection, "amqp:not-allowed", "OPEN frame received on a channel that is not 0");
AzureIoTClient 28:add19eb7defa 827 LogError("OPEN frame received on a channel that is not 0");
AzureIoTClient 28:add19eb7defa 828 }
Azure.IoT Build 0:6ae2f7bca550 829
AzureIoTClient 24:2c59c2d43ebf 830 if (connection->connection_state == CONNECTION_STATE_OPENED)
AzureIoTClient 4:98007eb79fa8 831 {
AzureIoTClient 4:98007eb79fa8 832 /* 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 24:2c59c2d43ebf 833 close_connection_with_error(connection, "amqp:illegal-state", "OPEN frame received in the OPENED state");
AzureIoTClient 28:add19eb7defa 834 LogError("OPEN frame received in the OPENED state");
AzureIoTClient 28:add19eb7defa 835 }
AzureIoTClient 24:2c59c2d43ebf 836 else if ((connection->connection_state == CONNECTION_STATE_OPEN_SENT) ||
AzureIoTClient 24:2c59c2d43ebf 837 (connection->connection_state == CONNECTION_STATE_HDR_EXCH))
AzureIoTClient 4:98007eb79fa8 838 {
AzureIoTClient 4:98007eb79fa8 839 OPEN_HANDLE open_handle;
AzureIoTClient 4:98007eb79fa8 840 if (amqpvalue_get_open(performative, &open_handle) != 0)
AzureIoTClient 4:98007eb79fa8 841 {
AzureIoTClient 4:98007eb79fa8 842 /* 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 843 /* Codes_SRS_CONNECTION_01_220: [The error amqp:invalid-field shall be set in the error.condition field of the CLOSE frame.] */
AzureIoTClient 24:2c59c2d43ebf 844 close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing OPEN frame");
AzureIoTClient 28:add19eb7defa 845 LogError("connection_endpoint_frame_received::failed parsing OPEN frame");
AzureIoTClient 28:add19eb7defa 846 }
AzureIoTClient 4:98007eb79fa8 847 else
AzureIoTClient 4:98007eb79fa8 848 {
AzureIoTClient 35:d0bed2404ee9 849 if (open_get_idle_time_out(open_handle, &connection->remote_idle_timeout) == 0)
AzureIoTClient 35:d0bed2404ee9 850 {
AzureIoTClient 35:d0bed2404ee9 851 /* since we obtained the remote_idle_timeout, compute at what millisecond we should send the empty frame */
AzureIoTClient 35:d0bed2404ee9 852 connection->remote_idle_timeout_send_frame_millisecond = (milliseconds)(connection->idle_timeout_empty_frame_send_ratio * connection->remote_idle_timeout);
AzureIoTClient 35:d0bed2404ee9 853 }
AzureIoTClient 35:d0bed2404ee9 854
AzureIoTClient 24:2c59c2d43ebf 855 if ((open_get_max_frame_size(open_handle, &connection->remote_max_frame_size) != 0) ||
AzureIoTClient 4:98007eb79fa8 856 /* Codes_SRS_CONNECTION_01_167: [Both peers MUST accept frames of up to 512 (MIN-MAX-FRAME-SIZE) octets.] */
AzureIoTClient 24:2c59c2d43ebf 857 (connection->remote_max_frame_size < 512))
AzureIoTClient 4:98007eb79fa8 858 {
AzureIoTClient 4:98007eb79fa8 859 /* 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 860 /* Codes_SRS_CONNECTION_01_220: [The error amqp:invalid-field shall be set in the error.condition field of the CLOSE frame.] */
AzureIoTClient 24:2c59c2d43ebf 861 close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing OPEN frame");
AzureIoTClient 28:add19eb7defa 862 LogError("connection_endpoint_frame_received::failed parsing OPEN frame");
AzureIoTClient 28:add19eb7defa 863 }
AzureIoTClient 4:98007eb79fa8 864 else
AzureIoTClient 4:98007eb79fa8 865 {
AzureIoTClient 24:2c59c2d43ebf 866 if (connection->connection_state == CONNECTION_STATE_OPEN_SENT)
AzureIoTClient 4:98007eb79fa8 867 {
AzureIoTClient 24:2c59c2d43ebf 868 connection_set_state(connection, CONNECTION_STATE_OPENED);
AzureIoTClient 4:98007eb79fa8 869 }
AzureIoTClient 4:98007eb79fa8 870 else
AzureIoTClient 4:98007eb79fa8 871 {
AzureIoTClient 24:2c59c2d43ebf 872 if (send_open_frame(connection) != 0)
AzureIoTClient 4:98007eb79fa8 873 {
AzureIoTClient 24:2c59c2d43ebf 874 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 875 }
AzureIoTClient 4:98007eb79fa8 876 else
AzureIoTClient 4:98007eb79fa8 877 {
AzureIoTClient 24:2c59c2d43ebf 878 connection_set_state(connection, CONNECTION_STATE_OPENED);
AzureIoTClient 4:98007eb79fa8 879 }
AzureIoTClient 4:98007eb79fa8 880 }
AzureIoTClient 4:98007eb79fa8 881 }
Azure.IoT Build 0:6ae2f7bca550 882
AzureIoTClient 4:98007eb79fa8 883 open_destroy(open_handle);
AzureIoTClient 4:98007eb79fa8 884 }
AzureIoTClient 4:98007eb79fa8 885 }
AzureIoTClient 4:98007eb79fa8 886 else
AzureIoTClient 4:98007eb79fa8 887 {
AzureIoTClient 4:98007eb79fa8 888 /* do nothing for now ... */
AzureIoTClient 4:98007eb79fa8 889 }
AzureIoTClient 4:98007eb79fa8 890 }
AzureIoTClient 4:98007eb79fa8 891 else if (is_close_type_by_descriptor(descriptor))
AzureIoTClient 4:98007eb79fa8 892 {
AzureIoTClient 4:98007eb79fa8 893 /* 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 894 /* 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 895
AzureIoTClient 4:98007eb79fa8 896 /* Codes_SRS_CONNECTION_01_225: [HDR_RCVD HDR OPEN] */
AzureIoTClient 24:2c59c2d43ebf 897 if ((connection->connection_state == CONNECTION_STATE_HDR_RCVD) ||
AzureIoTClient 4:98007eb79fa8 898 /* Codes_SRS_CONNECTION_01_227: [HDR_EXCH OPEN OPEN] */
AzureIoTClient 24:2c59c2d43ebf 899 (connection->connection_state == CONNECTION_STATE_HDR_EXCH) ||
AzureIoTClient 4:98007eb79fa8 900 /* Codes_SRS_CONNECTION_01_228: [OPEN_RCVD OPEN *] */
AzureIoTClient 24:2c59c2d43ebf 901 (connection->connection_state == CONNECTION_STATE_OPEN_RCVD) ||
AzureIoTClient 4:98007eb79fa8 902 /* Codes_SRS_CONNECTION_01_235: [CLOSE_SENT - * TCP Close for Write] */
AzureIoTClient 24:2c59c2d43ebf 903 (connection->connection_state == CONNECTION_STATE_CLOSE_SENT) ||
AzureIoTClient 4:98007eb79fa8 904 /* Codes_SRS_CONNECTION_01_236: [DISCARDING - * TCP Close for Write] */
AzureIoTClient 24:2c59c2d43ebf 905 (connection->connection_state == CONNECTION_STATE_DISCARDING))
AzureIoTClient 4:98007eb79fa8 906 {
AzureIoTClient 28:add19eb7defa 907 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 908 {
AzureIoTClient 28:add19eb7defa 909 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 910 }
AzureIoTClient 28:add19eb7defa 911 }
AzureIoTClient 4:98007eb79fa8 912 else
AzureIoTClient 4:98007eb79fa8 913 {
AzureIoTClient 4:98007eb79fa8 914 CLOSE_HANDLE close_handle;
Azure.IoT Build 0:6ae2f7bca550 915
AzureIoTClient 4:98007eb79fa8 916 /* Codes_SRS_CONNECTION_01_012: [A close frame MAY be received on any channel up to the maximum channel number negotiated in open.] */
AzureIoTClient 24:2c59c2d43ebf 917 if (channel > connection->channel_max)
AzureIoTClient 4:98007eb79fa8 918 {
AzureIoTClient 24:2c59c2d43ebf 919 close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing CLOSE frame");
AzureIoTClient 28:add19eb7defa 920 LogError("connection_endpoint_frame_received::failed parsing CLOSE frame");
AzureIoTClient 28:add19eb7defa 921 }
AzureIoTClient 4:98007eb79fa8 922 else
AzureIoTClient 4:98007eb79fa8 923 {
AzureIoTClient 4:98007eb79fa8 924 if (amqpvalue_get_close(performative, &close_handle) != 0)
AzureIoTClient 4:98007eb79fa8 925 {
AzureIoTClient 24:2c59c2d43ebf 926 close_connection_with_error(connection, "amqp:invalid-field", "connection_endpoint_frame_received::failed parsing CLOSE frame");
AzureIoTClient 28:add19eb7defa 927 LogError("connection_endpoint_frame_received::failed parsing CLOSE frame");
AzureIoTClient 28:add19eb7defa 928 }
AzureIoTClient 4:98007eb79fa8 929 else
AzureIoTClient 4:98007eb79fa8 930 {
AzureIoTClient 4:98007eb79fa8 931 close_destroy(close_handle);
Azure.IoT Build 0:6ae2f7bca550 932
AzureIoTClient 24:2c59c2d43ebf 933 connection_set_state(connection, CONNECTION_STATE_CLOSE_RCVD);
Azure.IoT Build 0:6ae2f7bca550 934
AzureIoTClient 28:add19eb7defa 935 if (send_close_frame(connection, NULL) != 0)
AzureIoTClient 28:add19eb7defa 936 {
AzureIoTClient 28:add19eb7defa 937 LogError("Cannot send CLOSE frame");
AzureIoTClient 28:add19eb7defa 938 }
AzureIoTClient 24:2c59c2d43ebf 939
AzureIoTClient 4:98007eb79fa8 940 /* 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 28:add19eb7defa 941 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 942 {
AzureIoTClient 28:add19eb7defa 943 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 944 }
Azure.IoT Build 0:6ae2f7bca550 945
AzureIoTClient 24:2c59c2d43ebf 946 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 947 }
AzureIoTClient 4:98007eb79fa8 948 }
AzureIoTClient 4:98007eb79fa8 949 }
AzureIoTClient 4:98007eb79fa8 950 }
AzureIoTClient 4:98007eb79fa8 951 else
AzureIoTClient 4:98007eb79fa8 952 {
AzureIoTClient 4:98007eb79fa8 953 amqpvalue_get_ulong(descriptor, &performative_ulong);
Azure.IoT Build 0:6ae2f7bca550 954
AzureIoTClient 4:98007eb79fa8 955 switch (performative_ulong)
AzureIoTClient 4:98007eb79fa8 956 {
AzureIoTClient 4:98007eb79fa8 957 default:
AzureIoTClient 28:add19eb7defa 958 LogError("Bad performative: %02x", performative);
AzureIoTClient 4:98007eb79fa8 959 break;
Azure.IoT Build 0:6ae2f7bca550 960
AzureIoTClient 4:98007eb79fa8 961 case AMQP_BEGIN:
AzureIoTClient 4:98007eb79fa8 962 {
AzureIoTClient 4:98007eb79fa8 963 BEGIN_HANDLE begin;
Azure.IoT Build 0:6ae2f7bca550 964
AzureIoTClient 24:2c59c2d43ebf 965 if (amqpvalue_get_begin(performative, &begin) != 0)
AzureIoTClient 4:98007eb79fa8 966 {
AzureIoTClient 28:add19eb7defa 967 LogError("Cannot get begin performative");
AzureIoTClient 28:add19eb7defa 968 }
AzureIoTClient 4:98007eb79fa8 969 else
AzureIoTClient 4:98007eb79fa8 970 {
AzureIoTClient 4:98007eb79fa8 971 uint16_t remote_channel;
AzureIoTClient 4:98007eb79fa8 972 ENDPOINT_HANDLE new_endpoint = NULL;
AzureIoTClient 4:98007eb79fa8 973 bool remote_begin = false;
Azure.IoT Build 0:6ae2f7bca550 974
AzureIoTClient 4:98007eb79fa8 975 if (begin_get_remote_channel(begin, &remote_channel) != 0)
AzureIoTClient 4:98007eb79fa8 976 {
AzureIoTClient 28:add19eb7defa 977 remote_begin = true;
AzureIoTClient 24:2c59c2d43ebf 978 if (connection->on_new_endpoint != NULL)
AzureIoTClient 4:98007eb79fa8 979 {
AzureIoTClient 24:2c59c2d43ebf 980 new_endpoint = connection_create_endpoint(connection);
AzureIoTClient 24:2c59c2d43ebf 981 if (!connection->on_new_endpoint(connection->on_new_endpoint_callback_context, new_endpoint))
AzureIoTClient 4:98007eb79fa8 982 {
AzureIoTClient 4:98007eb79fa8 983 connection_destroy_endpoint(new_endpoint);
AzureIoTClient 4:98007eb79fa8 984 new_endpoint = NULL;
AzureIoTClient 4:98007eb79fa8 985 }
AzureIoTClient 4:98007eb79fa8 986 }
AzureIoTClient 4:98007eb79fa8 987 }
Azure.IoT Build 0:6ae2f7bca550 988
AzureIoTClient 4:98007eb79fa8 989 if (!remote_begin)
AzureIoTClient 4:98007eb79fa8 990 {
AzureIoTClient 24:2c59c2d43ebf 991 ENDPOINT_INSTANCE* session_endpoint = find_session_endpoint_by_outgoing_channel(connection, remote_channel);
AzureIoTClient 4:98007eb79fa8 992 if (session_endpoint == NULL)
AzureIoTClient 4:98007eb79fa8 993 {
AzureIoTClient 28:add19eb7defa 994 LogError("Cannot create session endpoint");
AzureIoTClient 28:add19eb7defa 995 }
AzureIoTClient 4:98007eb79fa8 996 else
AzureIoTClient 4:98007eb79fa8 997 {
AzureIoTClient 4:98007eb79fa8 998 session_endpoint->incoming_channel = channel;
AzureIoTClient 4:98007eb79fa8 999 session_endpoint->on_endpoint_frame_received(session_endpoint->callback_context, performative, payload_size, payload_bytes);
AzureIoTClient 4:98007eb79fa8 1000 }
AzureIoTClient 4:98007eb79fa8 1001 }
AzureIoTClient 4:98007eb79fa8 1002 else
AzureIoTClient 4:98007eb79fa8 1003 {
Azure.IoT Build 0:6ae2f7bca550 1004 if (new_endpoint != NULL)
Azure.IoT Build 0:6ae2f7bca550 1005 {
Azure.IoT Build 0:6ae2f7bca550 1006 new_endpoint->incoming_channel = channel;
Azure.IoT Build 0:6ae2f7bca550 1007 new_endpoint->on_endpoint_frame_received(new_endpoint->callback_context, performative, payload_size, payload_bytes);
Azure.IoT Build 0:6ae2f7bca550 1008 }
AzureIoTClient 4:98007eb79fa8 1009 }
Azure.IoT Build 0:6ae2f7bca550 1010
AzureIoTClient 4:98007eb79fa8 1011 begin_destroy(begin);
AzureIoTClient 4:98007eb79fa8 1012 }
Azure.IoT Build 0:6ae2f7bca550 1013
AzureIoTClient 4:98007eb79fa8 1014 break;
AzureIoTClient 4:98007eb79fa8 1015 }
Azure.IoT Build 0:6ae2f7bca550 1016
AzureIoTClient 4:98007eb79fa8 1017 case AMQP_FLOW:
AzureIoTClient 4:98007eb79fa8 1018 case AMQP_TRANSFER:
AzureIoTClient 4:98007eb79fa8 1019 case AMQP_DISPOSITION:
AzureIoTClient 4:98007eb79fa8 1020 case AMQP_END:
AzureIoTClient 4:98007eb79fa8 1021 case AMQP_ATTACH:
AzureIoTClient 4:98007eb79fa8 1022 case AMQP_DETACH:
AzureIoTClient 4:98007eb79fa8 1023 {
AzureIoTClient 24:2c59c2d43ebf 1024 ENDPOINT_INSTANCE* session_endpoint = find_session_endpoint_by_incoming_channel(connection, channel);
AzureIoTClient 4:98007eb79fa8 1025 if (session_endpoint == NULL)
AzureIoTClient 4:98007eb79fa8 1026 {
AzureIoTClient 28:add19eb7defa 1027 LogError("Cannot find session endpoint for channel %u", (unsigned int)channel);
AzureIoTClient 28:add19eb7defa 1028 }
AzureIoTClient 4:98007eb79fa8 1029 else
AzureIoTClient 4:98007eb79fa8 1030 {
AzureIoTClient 4:98007eb79fa8 1031 session_endpoint->on_endpoint_frame_received(session_endpoint->callback_context, performative, payload_size, payload_bytes);
AzureIoTClient 4:98007eb79fa8 1032 }
Azure.IoT Build 0:6ae2f7bca550 1033
AzureIoTClient 4:98007eb79fa8 1034 break;
AzureIoTClient 4:98007eb79fa8 1035 }
AzureIoTClient 4:98007eb79fa8 1036 }
AzureIoTClient 4:98007eb79fa8 1037 }
AzureIoTClient 4:98007eb79fa8 1038 }
AzureIoTClient 4:98007eb79fa8 1039 break;
Azure.IoT Build 0:6ae2f7bca550 1040
AzureIoTClient 4:98007eb79fa8 1041 case CONNECTION_STATE_START:
AzureIoTClient 4:98007eb79fa8 1042 /* Codes_SRS_CONNECTION_01_224: [START HDR HDR] */
AzureIoTClient 4:98007eb79fa8 1043 case CONNECTION_STATE_HDR_SENT:
AzureIoTClient 4:98007eb79fa8 1044 /* Codes_SRS_CONNECTION_01_226: [HDR_SENT OPEN HDR] */
AzureIoTClient 4:98007eb79fa8 1045 case CONNECTION_STATE_OPEN_PIPE:
AzureIoTClient 4:98007eb79fa8 1046 /* Codes_SRS_CONNECTION_01_230: [OPEN_PIPE ** HDR] */
AzureIoTClient 4:98007eb79fa8 1047 case CONNECTION_STATE_OC_PIPE:
AzureIoTClient 4:98007eb79fa8 1048 /* Codes_SRS_CONNECTION_01_232: [OC_PIPE - HDR TCP Close for Write] */
AzureIoTClient 4:98007eb79fa8 1049 case CONNECTION_STATE_CLOSE_RCVD:
AzureIoTClient 4:98007eb79fa8 1050 /* Codes_SRS_CONNECTION_01_234: [CLOSE_RCVD * - TCP Close for Read] */
AzureIoTClient 4:98007eb79fa8 1051 case CONNECTION_STATE_END:
AzureIoTClient 4:98007eb79fa8 1052 /* Codes_SRS_CONNECTION_01_237: [END - - TCP Close] */
AzureIoTClient 28:add19eb7defa 1053 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 1054 {
AzureIoTClient 28:add19eb7defa 1055 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 1056 }
AzureIoTClient 28:add19eb7defa 1057 break;
AzureIoTClient 4:98007eb79fa8 1058 }
AzureIoTClient 4:98007eb79fa8 1059 }
AzureIoTClient 4:98007eb79fa8 1060 }
Azure.IoT Build 0:6ae2f7bca550 1061 }
Azure.IoT Build 0:6ae2f7bca550 1062
Azure.IoT Build 0:6ae2f7bca550 1063 static void frame_codec_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 1064 {
AzureIoTClient 6:641a9672db08 1065 /* Bug: some error handling should happen here
AzureIoTClient 6:641a9672db08 1066 Filed: uAMQP: frame_codec error and amqp_frame_codec_error should handle the errors */
AzureIoTClient 28:add19eb7defa 1067 LogError("A frame_codec_error occured");
AzureIoTClient 28:add19eb7defa 1068 (void)context;
Azure.IoT Build 0:6ae2f7bca550 1069 }
Azure.IoT Build 0:6ae2f7bca550 1070
Azure.IoT Build 0:6ae2f7bca550 1071 static void amqp_frame_codec_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 1072 {
AzureIoTClient 6:641a9672db08 1073 /* Bug: some error handling should happen here
AzureIoTClient 6:641a9672db08 1074 Filed: uAMQP: frame_codec error and amqp_frame_codec_error should handle the errors */
AzureIoTClient 28:add19eb7defa 1075 LogError("An amqp_frame_codec_error occured");
AzureIoTClient 28:add19eb7defa 1076 (void)context;
Azure.IoT Build 0:6ae2f7bca550 1077 }
Azure.IoT Build 0:6ae2f7bca550 1078
Azure.IoT Build 0:6ae2f7bca550 1079 /* Codes_SRS_CONNECTION_01_001: [connection_create shall open a new connection to a specified host/port.] */
Azure.IoT Build 0:6ae2f7bca550 1080 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 1081 {
Azure.IoT Build 5:ae49385aff34 1082 return connection_create2(xio, hostname, container_id, on_new_endpoint, callback_context, NULL, NULL, NULL, NULL);
Azure.IoT Build 0:6ae2f7bca550 1083 }
Azure.IoT Build 0:6ae2f7bca550 1084
Azure.IoT Build 0:6ae2f7bca550 1085 /* Codes_SRS_CONNECTION_01_001: [connection_create shall open a new connection to a specified host/port.] */
Azure.IoT Build 0:6ae2f7bca550 1086 /* Codes_SRS_CONNECTION_22_002: [connection_create shall allow registering connections state and io error callbacks.] */
Azure.IoT Build 5:ae49385aff34 1087 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 1088 {
AzureIoTClient 35:d0bed2404ee9 1089 CONNECTION_HANDLE connection;
Azure.IoT Build 0:6ae2f7bca550 1090
AzureIoTClient 4:98007eb79fa8 1091 if ((xio == NULL) ||
AzureIoTClient 4:98007eb79fa8 1092 (container_id == NULL))
AzureIoTClient 4:98007eb79fa8 1093 {
AzureIoTClient 4:98007eb79fa8 1094 /* Codes_SRS_CONNECTION_01_071: [If xio or container_id is NULL, connection_create shall return NULL.] */
AzureIoTClient 28:add19eb7defa 1095 LogError("Bad arguments: xio = %p, container_id = %p",
AzureIoTClient 28:add19eb7defa 1096 xio, container_id);
AzureIoTClient 35:d0bed2404ee9 1097 connection = NULL;
AzureIoTClient 4:98007eb79fa8 1098 }
AzureIoTClient 4:98007eb79fa8 1099 else
AzureIoTClient 4:98007eb79fa8 1100 {
AzureIoTClient 35:d0bed2404ee9 1101 connection = (CONNECTION_HANDLE)malloc(sizeof(CONNECTION_INSTANCE));
AzureIoTClient 4:98007eb79fa8 1102 /* Codes_SRS_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
AzureIoTClient 35:d0bed2404ee9 1103 if (connection == NULL)
AzureIoTClient 28:add19eb7defa 1104 {
AzureIoTClient 28:add19eb7defa 1105 LogError("Cannot allocate memory for connection");
AzureIoTClient 28:add19eb7defa 1106 }
AzureIoTClient 28:add19eb7defa 1107 else
AzureIoTClient 28:add19eb7defa 1108 {
AzureIoTClient 35:d0bed2404ee9 1109 connection->io = xio;
Azure.IoT Build 0:6ae2f7bca550 1110
AzureIoTClient 4:98007eb79fa8 1111 /* Codes_SRS_CONNECTION_01_082: [connection_create shall allocate a new frame_codec instance to be used for frame encoding/decoding.] */
AzureIoTClient 35:d0bed2404ee9 1112 connection->frame_codec = frame_codec_create(frame_codec_error, connection);
AzureIoTClient 35:d0bed2404ee9 1113 if (connection->frame_codec == NULL)
AzureIoTClient 4:98007eb79fa8 1114 {
AzureIoTClient 4:98007eb79fa8 1115 /* Codes_SRS_CONNECTION_01_083: [If frame_codec_create fails then connection_create shall return NULL.] */
AzureIoTClient 28:add19eb7defa 1116 LogError("Cannot create frame_codec");
AzureIoTClient 35:d0bed2404ee9 1117 free(connection);
AzureIoTClient 35:d0bed2404ee9 1118 connection = NULL;
AzureIoTClient 4:98007eb79fa8 1119 }
AzureIoTClient 4:98007eb79fa8 1120 else
AzureIoTClient 4:98007eb79fa8 1121 {
AzureIoTClient 35:d0bed2404ee9 1122 connection->amqp_frame_codec = amqp_frame_codec_create(connection->frame_codec, on_amqp_frame_received, on_empty_amqp_frame_received, amqp_frame_codec_error, connection);
AzureIoTClient 35:d0bed2404ee9 1123 if (connection->amqp_frame_codec == NULL)
AzureIoTClient 4:98007eb79fa8 1124 {
AzureIoTClient 4:98007eb79fa8 1125 /* Codes_SRS_CONNECTION_01_108: [If amqp_frame_codec_create fails, connection_create shall return NULL.] */
AzureIoTClient 28:add19eb7defa 1126 LogError("Cannot create amqp_frame_codec");
AzureIoTClient 35:d0bed2404ee9 1127 frame_codec_destroy(connection->frame_codec);
AzureIoTClient 35:d0bed2404ee9 1128 free(connection);
AzureIoTClient 35:d0bed2404ee9 1129 connection = NULL;
AzureIoTClient 4:98007eb79fa8 1130 }
AzureIoTClient 4:98007eb79fa8 1131 else
AzureIoTClient 4:98007eb79fa8 1132 {
AzureIoTClient 4:98007eb79fa8 1133 if (hostname != NULL)
AzureIoTClient 4:98007eb79fa8 1134 {
AzureIoTClient 23:1111ee8bcba4 1135 size_t hostname_length = strlen(hostname);
AzureIoTClient 35:d0bed2404ee9 1136 connection->host_name = (char*)malloc(hostname_length + 1);
AzureIoTClient 35:d0bed2404ee9 1137 if (connection->host_name == NULL)
AzureIoTClient 4:98007eb79fa8 1138 {
AzureIoTClient 4:98007eb79fa8 1139 /* Codes_SRS_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
AzureIoTClient 28:add19eb7defa 1140 LogError("Cannot allocate memory for host name");
AzureIoTClient 35:d0bed2404ee9 1141 amqp_frame_codec_destroy(connection->amqp_frame_codec);
AzureIoTClient 35:d0bed2404ee9 1142 frame_codec_destroy(connection->frame_codec);
AzureIoTClient 35:d0bed2404ee9 1143 free(connection);
AzureIoTClient 35:d0bed2404ee9 1144 connection = NULL;
AzureIoTClient 4:98007eb79fa8 1145 }
AzureIoTClient 4:98007eb79fa8 1146 else
AzureIoTClient 4:98007eb79fa8 1147 {
AzureIoTClient 35:d0bed2404ee9 1148 (void)memcpy(connection->host_name, hostname, hostname_length + 1);
AzureIoTClient 4:98007eb79fa8 1149 }
AzureIoTClient 4:98007eb79fa8 1150 }
AzureIoTClient 4:98007eb79fa8 1151 else
AzureIoTClient 4:98007eb79fa8 1152 {
AzureIoTClient 35:d0bed2404ee9 1153 connection->host_name = NULL;
AzureIoTClient 4:98007eb79fa8 1154 }
Azure.IoT Build 0:6ae2f7bca550 1155
AzureIoTClient 35:d0bed2404ee9 1156 if (connection != NULL)
AzureIoTClient 4:98007eb79fa8 1157 {
AzureIoTClient 23:1111ee8bcba4 1158 size_t container_id_length = strlen(container_id);
AzureIoTClient 35:d0bed2404ee9 1159 connection->container_id = (char*)malloc(container_id_length + 1);
AzureIoTClient 35:d0bed2404ee9 1160 if (connection->container_id == NULL)
AzureIoTClient 4:98007eb79fa8 1161 {
AzureIoTClient 4:98007eb79fa8 1162 /* Codes_SRS_CONNECTION_01_081: [If allocating the memory for the connection fails then connection_create shall return NULL.] */
AzureIoTClient 28:add19eb7defa 1163 LogError("Cannot allocate memory for container_id");
AzureIoTClient 35:d0bed2404ee9 1164 free(connection->host_name);
AzureIoTClient 35:d0bed2404ee9 1165 amqp_frame_codec_destroy(connection->amqp_frame_codec);
AzureIoTClient 35:d0bed2404ee9 1166 frame_codec_destroy(connection->frame_codec);
AzureIoTClient 35:d0bed2404ee9 1167 free(connection);
AzureIoTClient 35:d0bed2404ee9 1168 connection = NULL;
AzureIoTClient 4:98007eb79fa8 1169 }
AzureIoTClient 4:98007eb79fa8 1170 else
AzureIoTClient 4:98007eb79fa8 1171 {
AzureIoTClient 35:d0bed2404ee9 1172 connection->tick_counter = tickcounter_create();
AzureIoTClient 35:d0bed2404ee9 1173 if (connection->tick_counter == NULL)
AzureIoTClient 4:98007eb79fa8 1174 {
AzureIoTClient 28:add19eb7defa 1175 LogError("Cannot create tick counter");
AzureIoTClient 35:d0bed2404ee9 1176 free(connection->container_id);
AzureIoTClient 35:d0bed2404ee9 1177 free(connection->host_name);
AzureIoTClient 35:d0bed2404ee9 1178 amqp_frame_codec_destroy(connection->amqp_frame_codec);
AzureIoTClient 35:d0bed2404ee9 1179 frame_codec_destroy(connection->frame_codec);
AzureIoTClient 35:d0bed2404ee9 1180 free(connection);
AzureIoTClient 35:d0bed2404ee9 1181 connection = NULL;
AzureIoTClient 4:98007eb79fa8 1182 }
AzureIoTClient 4:98007eb79fa8 1183 else
AzureIoTClient 4:98007eb79fa8 1184 {
AzureIoTClient 35:d0bed2404ee9 1185 (void)memcpy(connection->container_id, container_id, container_id_length + 1);
Azure.IoT Build 0:6ae2f7bca550 1186
AzureIoTClient 4:98007eb79fa8 1187 /* Codes_SRS_CONNECTION_01_173: [<field name="max-frame-size" type="uint" default="4294967295"/>] */
AzureIoTClient 35:d0bed2404ee9 1188 connection->max_frame_size = 4294967295u;
AzureIoTClient 4:98007eb79fa8 1189 /* Codes: [<field name="channel-max" type="ushort" default="65535"/>] */
AzureIoTClient 35:d0bed2404ee9 1190 connection->channel_max = 65535;
Azure.IoT Build 0:6ae2f7bca550 1191
AzureIoTClient 4:98007eb79fa8 1192 /* Codes_SRS_CONNECTION_01_175: [<field name="idle-time-out" type="milliseconds"/>] */
AzureIoTClient 4:98007eb79fa8 1193 /* Codes_SRS_CONNECTION_01_192: [A value of zero is the same as if it was not set (null).] */
AzureIoTClient 35:d0bed2404ee9 1194 connection->idle_timeout = 0;
AzureIoTClient 35:d0bed2404ee9 1195 connection->remote_idle_timeout = 0;
AzureIoTClient 35:d0bed2404ee9 1196 connection->remote_idle_timeout_send_frame_millisecond = 0;
AzureIoTClient 35:d0bed2404ee9 1197 connection->idle_timeout_empty_frame_send_ratio = 0.5;
Azure.IoT Build 0:6ae2f7bca550 1198
AzureIoTClient 35:d0bed2404ee9 1199 connection->endpoint_count = 0;
AzureIoTClient 35:d0bed2404ee9 1200 connection->endpoints = NULL;
AzureIoTClient 35:d0bed2404ee9 1201 connection->header_bytes_received = 0;
AzureIoTClient 35:d0bed2404ee9 1202 connection->is_remote_frame_received = 0;
AzureIoTClient 41:0e723f9cbd89 1203 connection->properties = NULL;
Azure.IoT Build 0:6ae2f7bca550 1204
AzureIoTClient 35:d0bed2404ee9 1205 connection->is_underlying_io_open = 0;
AzureIoTClient 35:d0bed2404ee9 1206 connection->remote_max_frame_size = 512;
AzureIoTClient 35:d0bed2404ee9 1207 connection->is_trace_on = 0;
Azure.IoT Build 0:6ae2f7bca550 1208
AzureIoTClient 4:98007eb79fa8 1209 /* Mark that settings have not yet been set by the user */
AzureIoTClient 35:d0bed2404ee9 1210 connection->idle_timeout_specified = 0;
Azure.IoT Build 0:6ae2f7bca550 1211
AzureIoTClient 35:d0bed2404ee9 1212 connection->on_new_endpoint = on_new_endpoint;
AzureIoTClient 35:d0bed2404ee9 1213 connection->on_new_endpoint_callback_context = callback_context;
Azure.IoT Build 0:6ae2f7bca550 1214
AzureIoTClient 35:d0bed2404ee9 1215 connection->on_io_error = on_io_error;
AzureIoTClient 35:d0bed2404ee9 1216 connection->on_io_error_callback_context = on_io_error_context;
AzureIoTClient 35:d0bed2404ee9 1217 connection->on_connection_state_changed = on_connection_state_changed;
AzureIoTClient 35:d0bed2404ee9 1218 connection->on_connection_state_changed_callback_context = on_connection_state_changed_context;
Azure.IoT Build 0:6ae2f7bca550 1219
AzureIoTClient 35:d0bed2404ee9 1220 if (tickcounter_get_current_ms(connection->tick_counter, &connection->last_frame_received_time) != 0)
AzureIoTClient 20:206846c14c80 1221 {
AzureIoTClient 20:206846c14c80 1222 LogError("Could not retrieve time for last frame received time");
AzureIoTClient 35:d0bed2404ee9 1223 tickcounter_destroy(connection->tick_counter);
AzureIoTClient 35:d0bed2404ee9 1224 free(connection->container_id);
AzureIoTClient 35:d0bed2404ee9 1225 free(connection->host_name);
AzureIoTClient 35:d0bed2404ee9 1226 amqp_frame_codec_destroy(connection->amqp_frame_codec);
AzureIoTClient 35:d0bed2404ee9 1227 frame_codec_destroy(connection->frame_codec);
AzureIoTClient 35:d0bed2404ee9 1228 free(connection);
AzureIoTClient 35:d0bed2404ee9 1229 connection = NULL;
AzureIoTClient 20:206846c14c80 1230 }
AzureIoTClient 20:206846c14c80 1231 else
AzureIoTClient 20:206846c14c80 1232 {
AzureIoTClient 35:d0bed2404ee9 1233 connection->last_frame_sent_time = connection->last_frame_received_time;
AzureIoTClient 20:206846c14c80 1234
AzureIoTClient 20:206846c14c80 1235 /* Codes_SRS_CONNECTION_01_072: [When connection_create succeeds, the state of the connection shall be CONNECTION_STATE_START.] */
AzureIoTClient 35:d0bed2404ee9 1236 connection_set_state(connection, CONNECTION_STATE_START);
AzureIoTClient 20:206846c14c80 1237 }
AzureIoTClient 4:98007eb79fa8 1238 }
AzureIoTClient 4:98007eb79fa8 1239 }
AzureIoTClient 4:98007eb79fa8 1240 }
AzureIoTClient 4:98007eb79fa8 1241 }
AzureIoTClient 4:98007eb79fa8 1242 }
AzureIoTClient 4:98007eb79fa8 1243 }
AzureIoTClient 4:98007eb79fa8 1244 }
Azure.IoT Build 0:6ae2f7bca550 1245
AzureIoTClient 35:d0bed2404ee9 1246 return connection;
Azure.IoT Build 0:6ae2f7bca550 1247 }
Azure.IoT Build 0:6ae2f7bca550 1248
Azure.IoT Build 0:6ae2f7bca550 1249 void connection_destroy(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 1250 {
AzureIoTClient 4:98007eb79fa8 1251 /* Codes_SRS_CONNECTION_01_079: [If handle is NULL, connection_destroy shall do nothing.] */
AzureIoTClient 28:add19eb7defa 1252 if (connection == NULL)
AzureIoTClient 28:add19eb7defa 1253 {
AzureIoTClient 28:add19eb7defa 1254 LogError("NULL connection");
AzureIoTClient 28:add19eb7defa 1255 }
AzureIoTClient 28:add19eb7defa 1256 else
AzureIoTClient 28:add19eb7defa 1257 {
AzureIoTClient 4:98007eb79fa8 1258 /* Codes_SRS_CONNECTION_01_073: [connection_destroy shall free all resources associated with a connection.] */
AzureIoTClient 4:98007eb79fa8 1259 if (connection->is_underlying_io_open)
AzureIoTClient 4:98007eb79fa8 1260 {
AzureIoTClient 24:2c59c2d43ebf 1261 (void)connection_close(connection, NULL, NULL);
AzureIoTClient 4:98007eb79fa8 1262 }
Azure.IoT Build 0:6ae2f7bca550 1263
AzureIoTClient 4:98007eb79fa8 1264 amqp_frame_codec_destroy(connection->amqp_frame_codec);
AzureIoTClient 4:98007eb79fa8 1265 frame_codec_destroy(connection->frame_codec);
AzureIoTClient 4:98007eb79fa8 1266 tickcounter_destroy(connection->tick_counter);
AzureIoTClient 41:0e723f9cbd89 1267 if (connection->properties != NULL)
AzureIoTClient 41:0e723f9cbd89 1268 {
AzureIoTClient 41:0e723f9cbd89 1269 amqpvalue_destroy(connection->properties);
AzureIoTClient 41:0e723f9cbd89 1270 }
Azure.IoT Build 0:6ae2f7bca550 1271
AzureIoTClient 21:f9c433d8e6ca 1272 free(connection->host_name);
AzureIoTClient 21:f9c433d8e6ca 1273 free(connection->container_id);
Azure.IoT Build 0:6ae2f7bca550 1274
AzureIoTClient 4:98007eb79fa8 1275 /* Codes_SRS_CONNECTION_01_074: [connection_destroy shall close the socket connection.] */
AzureIoTClient 21:f9c433d8e6ca 1276 free(connection);
AzureIoTClient 4:98007eb79fa8 1277 }
Azure.IoT Build 0:6ae2f7bca550 1278 }
Azure.IoT Build 0:6ae2f7bca550 1279
Azure.IoT Build 0:6ae2f7bca550 1280 int connection_open(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 1281 {
AzureIoTClient 4:98007eb79fa8 1282 int result;
Azure.IoT Build 0:6ae2f7bca550 1283
AzureIoTClient 4:98007eb79fa8 1284 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1285 {
AzureIoTClient 28:add19eb7defa 1286 LogError("NULL connection");
AzureIoTClient 28:add19eb7defa 1287 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1288 }
AzureIoTClient 4:98007eb79fa8 1289 else
AzureIoTClient 4:98007eb79fa8 1290 {
AzureIoTClient 4:98007eb79fa8 1291 if (!connection->is_underlying_io_open)
AzureIoTClient 4:98007eb79fa8 1292 {
AzureIoTClient 4:98007eb79fa8 1293 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 1294 {
AzureIoTClient 28:add19eb7defa 1295 LogError("Opening the underlying IO failed");
AzureIoTClient 28:add19eb7defa 1296 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 1297 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1298 }
AzureIoTClient 4:98007eb79fa8 1299 else
AzureIoTClient 4:98007eb79fa8 1300 {
AzureIoTClient 4:98007eb79fa8 1301 connection->is_underlying_io_open = 1;
Azure.IoT Build 0:6ae2f7bca550 1302
AzureIoTClient 4:98007eb79fa8 1303 connection_set_state(connection, CONNECTION_STATE_START);
Azure.IoT Build 0:6ae2f7bca550 1304
AzureIoTClient 4:98007eb79fa8 1305 result = 0;
AzureIoTClient 4:98007eb79fa8 1306 }
AzureIoTClient 4:98007eb79fa8 1307 }
AzureIoTClient 4:98007eb79fa8 1308 else
AzureIoTClient 4:98007eb79fa8 1309 {
AzureIoTClient 4:98007eb79fa8 1310 result = 0;
AzureIoTClient 4:98007eb79fa8 1311 }
AzureIoTClient 4:98007eb79fa8 1312 }
Azure.IoT Build 0:6ae2f7bca550 1313
AzureIoTClient 4:98007eb79fa8 1314 return result;
Azure.IoT Build 0:6ae2f7bca550 1315 }
Azure.IoT Build 0:6ae2f7bca550 1316
Azure.IoT Build 0:6ae2f7bca550 1317 int connection_listen(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 1318 {
AzureIoTClient 4:98007eb79fa8 1319 int result;
Azure.IoT Build 0:6ae2f7bca550 1320
AzureIoTClient 4:98007eb79fa8 1321 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1322 {
AzureIoTClient 28:add19eb7defa 1323 LogError("NULL connection");
AzureIoTClient 28:add19eb7defa 1324 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1325 }
AzureIoTClient 4:98007eb79fa8 1326 else
AzureIoTClient 4:98007eb79fa8 1327 {
AzureIoTClient 4:98007eb79fa8 1328 if (!connection->is_underlying_io_open)
AzureIoTClient 4:98007eb79fa8 1329 {
AzureIoTClient 4:98007eb79fa8 1330 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 1331 {
AzureIoTClient 28:add19eb7defa 1332 LogError("Opening the underlying IO failed");
AzureIoTClient 28:add19eb7defa 1333 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 19:000ab4e6a2c1 1334 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1335 }
AzureIoTClient 4:98007eb79fa8 1336 else
AzureIoTClient 4:98007eb79fa8 1337 {
AzureIoTClient 4:98007eb79fa8 1338 connection->is_underlying_io_open = 1;
Azure.IoT Build 0:6ae2f7bca550 1339
AzureIoTClient 4:98007eb79fa8 1340 connection_set_state(connection, CONNECTION_STATE_HDR_EXCH);
Azure.IoT Build 0:6ae2f7bca550 1341
AzureIoTClient 4:98007eb79fa8 1342 result = 0;
AzureIoTClient 4:98007eb79fa8 1343 }
AzureIoTClient 4:98007eb79fa8 1344 }
AzureIoTClient 4:98007eb79fa8 1345 else
AzureIoTClient 4:98007eb79fa8 1346 {
AzureIoTClient 4:98007eb79fa8 1347 result = 0;
AzureIoTClient 4:98007eb79fa8 1348 }
AzureIoTClient 4:98007eb79fa8 1349 }
Azure.IoT Build 0:6ae2f7bca550 1350
AzureIoTClient 4:98007eb79fa8 1351 return result;
Azure.IoT Build 0:6ae2f7bca550 1352 }
Azure.IoT Build 0:6ae2f7bca550 1353
Azure.IoT Build 0:6ae2f7bca550 1354 int connection_close(CONNECTION_HANDLE connection, const char* condition_value, const char* description)
Azure.IoT Build 0:6ae2f7bca550 1355 {
AzureIoTClient 4:98007eb79fa8 1356 int result;
Azure.IoT Build 0:6ae2f7bca550 1357
AzureIoTClient 4:98007eb79fa8 1358 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1359 {
AzureIoTClient 28:add19eb7defa 1360 LogError("NULL connection");
AzureIoTClient 28:add19eb7defa 1361 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1362 }
AzureIoTClient 4:98007eb79fa8 1363 else
AzureIoTClient 4:98007eb79fa8 1364 {
AzureIoTClient 4:98007eb79fa8 1365 if (condition_value != NULL)
AzureIoTClient 4:98007eb79fa8 1366 {
AzureIoTClient 4:98007eb79fa8 1367 close_connection_with_error(connection, condition_value, description);
AzureIoTClient 4:98007eb79fa8 1368 }
AzureIoTClient 4:98007eb79fa8 1369 else
AzureIoTClient 4:98007eb79fa8 1370 {
AzureIoTClient 28:add19eb7defa 1371 if (send_close_frame(connection, NULL) != 0)
AzureIoTClient 28:add19eb7defa 1372 {
AzureIoTClient 28:add19eb7defa 1373 LogError("Sending CLOSE frame failed");
AzureIoTClient 28:add19eb7defa 1374 }
AzureIoTClient 24:2c59c2d43ebf 1375
AzureIoTClient 4:98007eb79fa8 1376 connection_set_state(connection, CONNECTION_STATE_END);
AzureIoTClient 4:98007eb79fa8 1377 }
Azure.IoT Build 0:6ae2f7bca550 1378
AzureIoTClient 28:add19eb7defa 1379 if (xio_close(connection->io, NULL, NULL) != 0)
AzureIoTClient 28:add19eb7defa 1380 {
AzureIoTClient 28:add19eb7defa 1381 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 1382 }
AzureIoTClient 24:2c59c2d43ebf 1383
AzureIoTClient 28:add19eb7defa 1384 connection->is_underlying_io_open = 1;
Azure.IoT Build 0:6ae2f7bca550 1385
Azure.IoT Build 0:6ae2f7bca550 1386 result = 0;
AzureIoTClient 4:98007eb79fa8 1387 }
Azure.IoT Build 0:6ae2f7bca550 1388
AzureIoTClient 4:98007eb79fa8 1389 return result;
Azure.IoT Build 0:6ae2f7bca550 1390 }
Azure.IoT Build 0:6ae2f7bca550 1391
Azure.IoT Build 0:6ae2f7bca550 1392 int connection_set_max_frame_size(CONNECTION_HANDLE connection, uint32_t max_frame_size)
Azure.IoT Build 0:6ae2f7bca550 1393 {
AzureIoTClient 4:98007eb79fa8 1394 int result;
Azure.IoT Build 0:6ae2f7bca550 1395
AzureIoTClient 4:98007eb79fa8 1396 /* Codes_SRS_CONNECTION_01_163: [If connection is NULL, connection_set_max_frame_size shall fail and return a non-zero value.] */
AzureIoTClient 28:add19eb7defa 1397 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1398 {
AzureIoTClient 28:add19eb7defa 1399 LogError("NULL connection");
AzureIoTClient 28:add19eb7defa 1400 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 1401 }
AzureIoTClient 28:add19eb7defa 1402 /* 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 28:add19eb7defa 1403 /* Codes_SRS_CONNECTION_01_167: [Both peers MUST accept frames of up to 512 (MIN-MAX-FRAME-SIZE) octets.] */
AzureIoTClient 28:add19eb7defa 1404 else if (max_frame_size < 512)
AzureIoTClient 28:add19eb7defa 1405 {
AzureIoTClient 28:add19eb7defa 1406 LogError("max_frame_size too small");
AzureIoTClient 28:add19eb7defa 1407 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1408 }
AzureIoTClient 4:98007eb79fa8 1409 else
AzureIoTClient 4:98007eb79fa8 1410 {
AzureIoTClient 4:98007eb79fa8 1411 /* 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 1412 if (connection->connection_state != CONNECTION_STATE_START)
AzureIoTClient 4:98007eb79fa8 1413 {
AzureIoTClient 28:add19eb7defa 1414 LogError("Connection already open");
AzureIoTClient 28:add19eb7defa 1415 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1416 }
AzureIoTClient 4:98007eb79fa8 1417 else
AzureIoTClient 4:98007eb79fa8 1418 {
AzureIoTClient 4:98007eb79fa8 1419 /* Codes_SRS_CONNECTION_01_148: [connection_set_max_frame_size shall set the max_frame_size associated with a connection.] */
AzureIoTClient 4:98007eb79fa8 1420 /* Codes_SRS_CONNECTION_01_164: [If connection_set_max_frame_size fails, the previous max_frame_size setting shall be retained.] */
AzureIoTClient 4:98007eb79fa8 1421 connection->max_frame_size = max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 1422
AzureIoTClient 4:98007eb79fa8 1423 /* Codes_SRS_CONNECTION_01_149: [On success connection_set_max_frame_size shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1424 result = 0;
AzureIoTClient 4:98007eb79fa8 1425 }
AzureIoTClient 4:98007eb79fa8 1426 }
Azure.IoT Build 0:6ae2f7bca550 1427
AzureIoTClient 4:98007eb79fa8 1428 return result;
Azure.IoT Build 0:6ae2f7bca550 1429 }
Azure.IoT Build 0:6ae2f7bca550 1430
Azure.IoT Build 0:6ae2f7bca550 1431 int connection_get_max_frame_size(CONNECTION_HANDLE connection, uint32_t* max_frame_size)
Azure.IoT Build 0:6ae2f7bca550 1432 {
AzureIoTClient 4:98007eb79fa8 1433 int result;
Azure.IoT Build 0:6ae2f7bca550 1434
AzureIoTClient 4:98007eb79fa8 1435 /* 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 1436 if ((connection == NULL) ||
AzureIoTClient 4:98007eb79fa8 1437 (max_frame_size == NULL))
AzureIoTClient 4:98007eb79fa8 1438 {
AzureIoTClient 28:add19eb7defa 1439 LogError("Bad arguments: connection = %p, max_frame_size = %p",
AzureIoTClient 28:add19eb7defa 1440 connection, max_frame_size);
AzureIoTClient 28:add19eb7defa 1441 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1442 }
AzureIoTClient 4:98007eb79fa8 1443 else
AzureIoTClient 4:98007eb79fa8 1444 {
AzureIoTClient 4:98007eb79fa8 1445 /* 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 1446 *max_frame_size = connection->max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 1447
AzureIoTClient 4:98007eb79fa8 1448 /* Codes_SRS_CONNECTION_01_169: [On success, connection_get_max_frame_size shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1449 result = 0;
AzureIoTClient 4:98007eb79fa8 1450 }
Azure.IoT Build 0:6ae2f7bca550 1451
AzureIoTClient 4:98007eb79fa8 1452 return result;
Azure.IoT Build 0:6ae2f7bca550 1453 }
Azure.IoT Build 0:6ae2f7bca550 1454
Azure.IoT Build 0:6ae2f7bca550 1455 int connection_set_channel_max(CONNECTION_HANDLE connection, uint16_t channel_max)
Azure.IoT Build 0:6ae2f7bca550 1456 {
AzureIoTClient 4:98007eb79fa8 1457 int result;
Azure.IoT Build 0:6ae2f7bca550 1458
AzureIoTClient 4:98007eb79fa8 1459 /* 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 1460 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1461 {
AzureIoTClient 28:add19eb7defa 1462 LogError("NULL connection");
AzureIoTClient 28:add19eb7defa 1463 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1464 }
AzureIoTClient 4:98007eb79fa8 1465 else
AzureIoTClient 4:98007eb79fa8 1466 {
AzureIoTClient 4:98007eb79fa8 1467 /* 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 1468 if (connection->connection_state != CONNECTION_STATE_START)
AzureIoTClient 4:98007eb79fa8 1469 {
AzureIoTClient 28:add19eb7defa 1470 LogError("Connection already open");
AzureIoTClient 28:add19eb7defa 1471 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1472 }
AzureIoTClient 4:98007eb79fa8 1473 else
AzureIoTClient 4:98007eb79fa8 1474 {
AzureIoTClient 4:98007eb79fa8 1475 /* Codes_SRS_CONNECTION_01_153: [connection_set_channel_max shall set the channel_max associated with a connection.] */
AzureIoTClient 4:98007eb79fa8 1476 /* Codes_SRS_CONNECTION_01_165: [If connection_set_channel_max fails, the previous channel_max setting shall be retained.] */
AzureIoTClient 4:98007eb79fa8 1477 connection->channel_max = channel_max;
Azure.IoT Build 0:6ae2f7bca550 1478
AzureIoTClient 4:98007eb79fa8 1479 /* Codes_SRS_CONNECTION_01_154: [On success connection_set_channel_max shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1480 result = 0;
AzureIoTClient 4:98007eb79fa8 1481 }
AzureIoTClient 4:98007eb79fa8 1482 }
Azure.IoT Build 0:6ae2f7bca550 1483
AzureIoTClient 4:98007eb79fa8 1484 return result;
Azure.IoT Build 0:6ae2f7bca550 1485 }
Azure.IoT Build 0:6ae2f7bca550 1486
Azure.IoT Build 0:6ae2f7bca550 1487 int connection_get_channel_max(CONNECTION_HANDLE connection, uint16_t* channel_max)
Azure.IoT Build 0:6ae2f7bca550 1488 {
AzureIoTClient 4:98007eb79fa8 1489 int result;
Azure.IoT Build 0:6ae2f7bca550 1490
AzureIoTClient 4:98007eb79fa8 1491 /* 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 1492 if ((connection == NULL) ||
AzureIoTClient 4:98007eb79fa8 1493 (channel_max == NULL))
AzureIoTClient 4:98007eb79fa8 1494 {
AzureIoTClient 28:add19eb7defa 1495 LogError("Bad arguments: connection = %p, channel_max = %p",
AzureIoTClient 28:add19eb7defa 1496 connection, channel_max);
AzureIoTClient 28:add19eb7defa 1497 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1498 }
AzureIoTClient 4:98007eb79fa8 1499 else
AzureIoTClient 4:98007eb79fa8 1500 {
AzureIoTClient 4:98007eb79fa8 1501 /* Codes_SRS_CONNECTION_01_182: [connection_get_channel_max shall return in the channel_max argument the current channel_max setting.] */
AzureIoTClient 4:98007eb79fa8 1502 *channel_max = connection->channel_max;
Azure.IoT Build 0:6ae2f7bca550 1503
AzureIoTClient 4:98007eb79fa8 1504 /* Codes_SRS_CONNECTION_01_183: [On success, connection_get_channel_max shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1505 result = 0;
AzureIoTClient 4:98007eb79fa8 1506 }
Azure.IoT Build 0:6ae2f7bca550 1507
AzureIoTClient 4:98007eb79fa8 1508 return result;
Azure.IoT Build 0:6ae2f7bca550 1509 }
Azure.IoT Build 0:6ae2f7bca550 1510
Azure.IoT Build 0:6ae2f7bca550 1511 int connection_set_idle_timeout(CONNECTION_HANDLE connection, milliseconds idle_timeout)
Azure.IoT Build 0:6ae2f7bca550 1512 {
AzureIoTClient 4:98007eb79fa8 1513 int result;
Azure.IoT Build 0:6ae2f7bca550 1514
AzureIoTClient 4:98007eb79fa8 1515 /* Codes_SRS_CONNECTION_01_191: [If connection is NULL, connection_set_idle_timeout shall fail and return a non-zero value.] */
AzureIoTClient 4:98007eb79fa8 1516 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1517 {
AzureIoTClient 28:add19eb7defa 1518 LogError("NULL connection");
AzureIoTClient 28:add19eb7defa 1519 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1520 }
AzureIoTClient 4:98007eb79fa8 1521 else
AzureIoTClient 4:98007eb79fa8 1522 {
AzureIoTClient 4:98007eb79fa8 1523 /* 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 1524 if (connection->connection_state != CONNECTION_STATE_START)
AzureIoTClient 4:98007eb79fa8 1525 {
AzureIoTClient 28:add19eb7defa 1526 LogError("Connection already open");
AzureIoTClient 28:add19eb7defa 1527 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1528 }
AzureIoTClient 4:98007eb79fa8 1529 else
AzureIoTClient 4:98007eb79fa8 1530 {
AzureIoTClient 4:98007eb79fa8 1531 /* Codes_SRS_CONNECTION_01_159: [connection_set_idle_timeout shall set the idle_timeout associated with a connection.] */
AzureIoTClient 4:98007eb79fa8 1532 /* Codes_SRS_CONNECTION_01_166: [If connection_set_idle_timeout fails, the previous idle_timeout setting shall be retained.] */
AzureIoTClient 4:98007eb79fa8 1533 connection->idle_timeout = idle_timeout;
AzureIoTClient 4:98007eb79fa8 1534 connection->idle_timeout_specified = true;
Azure.IoT Build 0:6ae2f7bca550 1535
AzureIoTClient 4:98007eb79fa8 1536 /* Codes_SRS_CONNECTION_01_160: [On success connection_set_idle_timeout shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1537 result = 0;
AzureIoTClient 4:98007eb79fa8 1538 }
AzureIoTClient 4:98007eb79fa8 1539 }
Azure.IoT Build 0:6ae2f7bca550 1540
AzureIoTClient 4:98007eb79fa8 1541 return result;
Azure.IoT Build 0:6ae2f7bca550 1542 }
Azure.IoT Build 0:6ae2f7bca550 1543
Azure.IoT Build 0:6ae2f7bca550 1544 int connection_get_idle_timeout(CONNECTION_HANDLE connection, milliseconds* idle_timeout)
Azure.IoT Build 0:6ae2f7bca550 1545 {
AzureIoTClient 4:98007eb79fa8 1546 int result;
Azure.IoT Build 0:6ae2f7bca550 1547
AzureIoTClient 4:98007eb79fa8 1548 /* 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 1549 if ((connection == NULL) ||
AzureIoTClient 4:98007eb79fa8 1550 (idle_timeout == NULL))
AzureIoTClient 4:98007eb79fa8 1551 {
AzureIoTClient 28:add19eb7defa 1552 LogError("Bad arguments: connection = %p, idle_timeout = %p",
AzureIoTClient 28:add19eb7defa 1553 connection, idle_timeout);
AzureIoTClient 28:add19eb7defa 1554 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1555 }
AzureIoTClient 4:98007eb79fa8 1556 else
AzureIoTClient 4:98007eb79fa8 1557 {
AzureIoTClient 4:98007eb79fa8 1558 /* Codes_SRS_CONNECTION_01_188: [connection_get_idle_timeout shall return in the idle_timeout argument the current idle_timeout setting.] */
AzureIoTClient 4:98007eb79fa8 1559 *idle_timeout = connection->idle_timeout;
Azure.IoT Build 0:6ae2f7bca550 1560
AzureIoTClient 4:98007eb79fa8 1561 /* Codes_SRS_CONNECTION_01_189: [On success, connection_get_idle_timeout shall return 0.] */
AzureIoTClient 4:98007eb79fa8 1562 result = 0;
AzureIoTClient 4:98007eb79fa8 1563 }
Azure.IoT Build 0:6ae2f7bca550 1564
AzureIoTClient 4:98007eb79fa8 1565 return result;
Azure.IoT Build 0:6ae2f7bca550 1566 }
Azure.IoT Build 0:6ae2f7bca550 1567
AzureIoTClient 41:0e723f9cbd89 1568 int connection_set_properties(CONNECTION_HANDLE connection, fields properties)
AzureIoTClient 41:0e723f9cbd89 1569 {
AzureIoTClient 41:0e723f9cbd89 1570 int result;
AzureIoTClient 41:0e723f9cbd89 1571
AzureIoTClient 41:0e723f9cbd89 1572 /* Codes_SRS_CONNECTION_01_261: [If connection is NULL, connection_set_properties shall fail and return a non-zero value.] */
AzureIoTClient 41:0e723f9cbd89 1573 if (connection == NULL)
AzureIoTClient 41:0e723f9cbd89 1574 {
AzureIoTClient 41:0e723f9cbd89 1575 LogError("NULL connection");
AzureIoTClient 41:0e723f9cbd89 1576 result = __FAILURE__;
AzureIoTClient 41:0e723f9cbd89 1577 }
AzureIoTClient 41:0e723f9cbd89 1578 else
AzureIoTClient 41:0e723f9cbd89 1579 {
AzureIoTClient 41:0e723f9cbd89 1580 /* Codes_SRS_CONNECTION_01_262: [If connection_set_properties is called after the initial Open frame has been sent, it shall fail and return a non-zero value.] */
AzureIoTClient 41:0e723f9cbd89 1581 if (connection->connection_state != CONNECTION_STATE_START)
AzureIoTClient 41:0e723f9cbd89 1582 {
AzureIoTClient 41:0e723f9cbd89 1583 LogError("Connection already open");
AzureIoTClient 41:0e723f9cbd89 1584 result = __FAILURE__;
AzureIoTClient 41:0e723f9cbd89 1585 }
AzureIoTClient 41:0e723f9cbd89 1586 else
AzureIoTClient 41:0e723f9cbd89 1587 {
AzureIoTClient 41:0e723f9cbd89 1588 if (properties == NULL)
AzureIoTClient 41:0e723f9cbd89 1589 {
AzureIoTClient 41:0e723f9cbd89 1590 /* Codes_SRS_CONNECTION_01_263: [ If `properties` is NULL, the previously stored properties associated with `connection` shall be freed. ]*/
AzureIoTClient 41:0e723f9cbd89 1591 if (connection->properties != NULL)
AzureIoTClient 41:0e723f9cbd89 1592 {
AzureIoTClient 41:0e723f9cbd89 1593 fields_destroy(connection->properties);
AzureIoTClient 41:0e723f9cbd89 1594 connection->properties = NULL;
AzureIoTClient 41:0e723f9cbd89 1595 }
AzureIoTClient 41:0e723f9cbd89 1596
AzureIoTClient 41:0e723f9cbd89 1597 /* Codes_SRS_CONNECTION_01_264: [ On success it shall return 0. ]*/
AzureIoTClient 41:0e723f9cbd89 1598 result = 0;
AzureIoTClient 41:0e723f9cbd89 1599 }
AzureIoTClient 41:0e723f9cbd89 1600 else
AzureIoTClient 41:0e723f9cbd89 1601 {
AzureIoTClient 41:0e723f9cbd89 1602 fields new_properties;
AzureIoTClient 41:0e723f9cbd89 1603
AzureIoTClient 41:0e723f9cbd89 1604 /* Codes_SRS_CONNECTION_01_265: [ `connection_set_properties` shall copy the contents of `properties` as the properties contents for the connection instance identified by `connection`. ]*/
AzureIoTClient 41:0e723f9cbd89 1605 /* Codes_SRS_CONNECTION_01_266: [ Cloning the properties shall be done by calling `fields_clone`. ]*/
AzureIoTClient 41:0e723f9cbd89 1606 new_properties = fields_clone(properties);
AzureIoTClient 41:0e723f9cbd89 1607 if (new_properties == NULL)
AzureIoTClient 41:0e723f9cbd89 1608 {
AzureIoTClient 41:0e723f9cbd89 1609 /* Codes_SRS_CONNECTION_01_267: [ If `fields_clone` fails, `connection_set_properties` shall fail and return a non-zero value. ]*/
AzureIoTClient 41:0e723f9cbd89 1610 LogError("Cannot clone connection properties");
AzureIoTClient 41:0e723f9cbd89 1611 result = __FAILURE__;
AzureIoTClient 41:0e723f9cbd89 1612 }
AzureIoTClient 41:0e723f9cbd89 1613 else
AzureIoTClient 41:0e723f9cbd89 1614 {
AzureIoTClient 41:0e723f9cbd89 1615 /* Codes_SRS_CONNECTION_01_268: [ If setting the properties fails, the previous value shall be preserved. ]*/
AzureIoTClient 41:0e723f9cbd89 1616 /* Only do the free of the previous value if we could clone the new one*/
AzureIoTClient 41:0e723f9cbd89 1617 if (connection->properties != NULL)
AzureIoTClient 41:0e723f9cbd89 1618 {
AzureIoTClient 41:0e723f9cbd89 1619 fields_destroy(connection->properties);
AzureIoTClient 41:0e723f9cbd89 1620 }
AzureIoTClient 41:0e723f9cbd89 1621
AzureIoTClient 41:0e723f9cbd89 1622 connection->properties = new_properties;
AzureIoTClient 41:0e723f9cbd89 1623
AzureIoTClient 41:0e723f9cbd89 1624 /* Codes_SRS_CONNECTION_01_264: [ On success it shall return 0. ]*/
AzureIoTClient 41:0e723f9cbd89 1625 result = 0;
AzureIoTClient 41:0e723f9cbd89 1626 }
AzureIoTClient 41:0e723f9cbd89 1627 }
AzureIoTClient 41:0e723f9cbd89 1628 }
AzureIoTClient 41:0e723f9cbd89 1629 }
AzureIoTClient 41:0e723f9cbd89 1630
AzureIoTClient 41:0e723f9cbd89 1631 return result;
AzureIoTClient 41:0e723f9cbd89 1632 }
AzureIoTClient 41:0e723f9cbd89 1633
AzureIoTClient 41:0e723f9cbd89 1634 int connection_get_properties(CONNECTION_HANDLE connection, fields* properties)
AzureIoTClient 41:0e723f9cbd89 1635 {
AzureIoTClient 41:0e723f9cbd89 1636 int result;
AzureIoTClient 41:0e723f9cbd89 1637
AzureIoTClient 41:0e723f9cbd89 1638 /* Codes_SRS_CONNECTION_01_269: [If connection or properties is NULL, connection_get_properties shall fail and return a non-zero value.] */
AzureIoTClient 41:0e723f9cbd89 1639 if ((connection == NULL) ||
AzureIoTClient 41:0e723f9cbd89 1640 (properties == NULL))
AzureIoTClient 41:0e723f9cbd89 1641 {
AzureIoTClient 41:0e723f9cbd89 1642 LogError("Bad arguments: connection = %p, properties = %p",
AzureIoTClient 41:0e723f9cbd89 1643 connection, properties);
AzureIoTClient 41:0e723f9cbd89 1644 result = __FAILURE__;
AzureIoTClient 41:0e723f9cbd89 1645 }
AzureIoTClient 41:0e723f9cbd89 1646 else
AzureIoTClient 41:0e723f9cbd89 1647 {
AzureIoTClient 41:0e723f9cbd89 1648 if (connection->properties == NULL)
AzureIoTClient 41:0e723f9cbd89 1649 {
AzureIoTClient 41:0e723f9cbd89 1650 /* Codes_SRS_CONNECTION_01_270: [ If no properties have been set, `connection_get_properties` shall set `properties` to NULL. ]*/
AzureIoTClient 41:0e723f9cbd89 1651 *properties = NULL;
AzureIoTClient 41:0e723f9cbd89 1652
AzureIoTClient 41:0e723f9cbd89 1653 /* Codes_SRS_CONNECTION_01_271: [On success, connection_get_properties shall return 0.] */
AzureIoTClient 41:0e723f9cbd89 1654 result = 0;
AzureIoTClient 41:0e723f9cbd89 1655 }
AzureIoTClient 41:0e723f9cbd89 1656 else
AzureIoTClient 41:0e723f9cbd89 1657 {
AzureIoTClient 41:0e723f9cbd89 1658 /* Codes_SRS_CONNECTION_01_272: [connection_get_properties shall return in the properties argument the current properties setting.] */
AzureIoTClient 41:0e723f9cbd89 1659 /* Codes_SRS_CONNECTION_01_273: [ Cloning the properties shall be done by calling `fields_clone`. ]*/
AzureIoTClient 41:0e723f9cbd89 1660 *properties = fields_clone(connection->properties);
AzureIoTClient 41:0e723f9cbd89 1661 if (*properties == NULL)
AzureIoTClient 41:0e723f9cbd89 1662 {
AzureIoTClient 41:0e723f9cbd89 1663 /* Codes_SRS_CONNECTION_01_274: [ If `fields_clone` fails, `connection_get_properties` shall fail and return a non-zero value. ]*/
AzureIoTClient 41:0e723f9cbd89 1664 LogError("Cannot clone properties");
AzureIoTClient 41:0e723f9cbd89 1665 result = __FAILURE__;
AzureIoTClient 41:0e723f9cbd89 1666 }
AzureIoTClient 41:0e723f9cbd89 1667 else
AzureIoTClient 41:0e723f9cbd89 1668 {
AzureIoTClient 41:0e723f9cbd89 1669 /* Codes_SRS_CONNECTION_01_271: [On success, connection_get_properties shall return 0.] */
AzureIoTClient 41:0e723f9cbd89 1670 result = 0;
AzureIoTClient 41:0e723f9cbd89 1671 }
AzureIoTClient 41:0e723f9cbd89 1672 }
AzureIoTClient 41:0e723f9cbd89 1673 }
AzureIoTClient 41:0e723f9cbd89 1674
AzureIoTClient 41:0e723f9cbd89 1675 return result;
AzureIoTClient 41:0e723f9cbd89 1676 }
AzureIoTClient 41:0e723f9cbd89 1677
Azure.IoT Build 0:6ae2f7bca550 1678 int connection_get_remote_max_frame_size(CONNECTION_HANDLE connection, uint32_t* remote_max_frame_size)
Azure.IoT Build 0:6ae2f7bca550 1679 {
AzureIoTClient 4:98007eb79fa8 1680 int result;
Azure.IoT Build 0:6ae2f7bca550 1681
AzureIoTClient 4:98007eb79fa8 1682 if ((connection == NULL) ||
AzureIoTClient 4:98007eb79fa8 1683 (remote_max_frame_size == NULL))
AzureIoTClient 4:98007eb79fa8 1684 {
AzureIoTClient 28:add19eb7defa 1685 LogError("Bad arguments: connection = %p, remote_max_frame_size = %p",
AzureIoTClient 28:add19eb7defa 1686 connection, remote_max_frame_size);
AzureIoTClient 28:add19eb7defa 1687 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1688 }
AzureIoTClient 4:98007eb79fa8 1689 else
AzureIoTClient 4:98007eb79fa8 1690 {
AzureIoTClient 4:98007eb79fa8 1691 *remote_max_frame_size = connection->remote_max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 1692
AzureIoTClient 4:98007eb79fa8 1693 result = 0;
AzureIoTClient 4:98007eb79fa8 1694 }
Azure.IoT Build 0:6ae2f7bca550 1695
AzureIoTClient 4:98007eb79fa8 1696 return result;
Azure.IoT Build 0:6ae2f7bca550 1697 }
Azure.IoT Build 0:6ae2f7bca550 1698
AzureIoTClient 1:eab586236bfe 1699 uint64_t connection_handle_deadlines(CONNECTION_HANDLE connection)
AzureIoTClient 1:eab586236bfe 1700 {
AzureIoTClient 35:d0bed2404ee9 1701 uint64_t local_deadline = (uint64_t)-1;
AzureIoTClient 1:eab586236bfe 1702 uint64_t remote_deadline = (uint64_t)-1;
AzureIoTClient 1:eab586236bfe 1703
AzureIoTClient 28:add19eb7defa 1704 if (connection == NULL)
AzureIoTClient 28:add19eb7defa 1705 {
AzureIoTClient 28:add19eb7defa 1706 LogError("NULL connection");
AzureIoTClient 28:add19eb7defa 1707 }
AzureIoTClient 28:add19eb7defa 1708 else
AzureIoTClient 28:add19eb7defa 1709 {
Azure.IoT.Build 14:0b0e28c75ded 1710 tickcounter_ms_t current_ms;
AzureIoTClient 1:eab586236bfe 1711
AzureIoTClient 1:eab586236bfe 1712 if (tickcounter_get_current_ms(connection->tick_counter, &current_ms) != 0)
AzureIoTClient 1:eab586236bfe 1713 {
AzureIoTClient 28:add19eb7defa 1714 LogError("Could not get tick counter value");
AzureIoTClient 28:add19eb7defa 1715 close_connection_with_error(connection, "amqp:internal-error", "Could not get tick count");
AzureIoTClient 1:eab586236bfe 1716 }
AzureIoTClient 1:eab586236bfe 1717 else
AzureIoTClient 1:eab586236bfe 1718 {
AzureIoTClient 1:eab586236bfe 1719 if (connection->idle_timeout_specified && (connection->idle_timeout != 0))
AzureIoTClient 1:eab586236bfe 1720 {
AzureIoTClient 1:eab586236bfe 1721 /* Calculate time until configured idle timeout expires */
AzureIoTClient 1:eab586236bfe 1722
AzureIoTClient 1:eab586236bfe 1723 uint64_t time_since_last_received = current_ms - connection->last_frame_received_time;
AzureIoTClient 1:eab586236bfe 1724 if (time_since_last_received < connection->idle_timeout)
AzureIoTClient 1:eab586236bfe 1725 {
AzureIoTClient 1:eab586236bfe 1726 local_deadline = connection->idle_timeout - time_since_last_received;
AzureIoTClient 1:eab586236bfe 1727 }
AzureIoTClient 1:eab586236bfe 1728 else
AzureIoTClient 1:eab586236bfe 1729 {
AzureIoTClient 1:eab586236bfe 1730 local_deadline = 0;
AzureIoTClient 1:eab586236bfe 1731
AzureIoTClient 1:eab586236bfe 1732 /* close connection */
AzureIoTClient 1:eab586236bfe 1733 close_connection_with_error(connection, "amqp:internal-error", "No frame received for the idle timeout");
AzureIoTClient 1:eab586236bfe 1734 }
AzureIoTClient 1:eab586236bfe 1735 }
AzureIoTClient 1:eab586236bfe 1736
AzureIoTClient 1:eab586236bfe 1737 if (local_deadline != 0 && connection->remote_idle_timeout != 0)
AzureIoTClient 1:eab586236bfe 1738 {
AzureIoTClient 1:eab586236bfe 1739 /* Calculate time until remote idle timeout expires */
AzureIoTClient 1:eab586236bfe 1740
AzureIoTClient 35:d0bed2404ee9 1741 uint64_t remote_idle_timeout = connection->remote_idle_timeout_send_frame_millisecond;
AzureIoTClient 1:eab586236bfe 1742 uint64_t time_since_last_sent = current_ms - connection->last_frame_sent_time;
AzureIoTClient 1:eab586236bfe 1743
AzureIoTClient 1:eab586236bfe 1744 if (time_since_last_sent < remote_idle_timeout)
AzureIoTClient 1:eab586236bfe 1745 {
AzureIoTClient 1:eab586236bfe 1746 remote_deadline = remote_idle_timeout - time_since_last_sent;
AzureIoTClient 1:eab586236bfe 1747 }
AzureIoTClient 1:eab586236bfe 1748 else
AzureIoTClient 1:eab586236bfe 1749 {
AzureIoTClient 1:eab586236bfe 1750 connection->on_send_complete = NULL;
AzureIoTClient 1:eab586236bfe 1751 if (amqp_frame_codec_encode_empty_frame(connection->amqp_frame_codec, 0, on_bytes_encoded, connection) != 0)
AzureIoTClient 1:eab586236bfe 1752 {
AzureIoTClient 28:add19eb7defa 1753 LogError("Encoding the empty frame failed");
AzureIoTClient 28:add19eb7defa 1754 /* close connection */
AzureIoTClient 28:add19eb7defa 1755 close_connection_with_error(connection, "amqp:internal-error", "Cannot send empty frame");
AzureIoTClient 1:eab586236bfe 1756 }
AzureIoTClient 1:eab586236bfe 1757 else
AzureIoTClient 1:eab586236bfe 1758 {
AzureIoTClient 6:641a9672db08 1759 if (connection->is_trace_on == 1)
AzureIoTClient 6:641a9672db08 1760 {
AzureIoTClient 16:22a72cf8e416 1761 LOG(AZ_LOG_TRACE, LOG_LINE, "-> Empty frame");
AzureIoTClient 6:641a9672db08 1762 }
AzureIoTClient 1:eab586236bfe 1763
AzureIoTClient 1:eab586236bfe 1764 connection->last_frame_sent_time = current_ms;
AzureIoTClient 1:eab586236bfe 1765
AzureIoTClient 1:eab586236bfe 1766 remote_deadline = remote_idle_timeout;
AzureIoTClient 1:eab586236bfe 1767 }
AzureIoTClient 1:eab586236bfe 1768 }
AzureIoTClient 1:eab586236bfe 1769 }
AzureIoTClient 1:eab586236bfe 1770 }
AzureIoTClient 1:eab586236bfe 1771 }
AzureIoTClient 1:eab586236bfe 1772
AzureIoTClient 1:eab586236bfe 1773 /* Return the shorter of each deadline, or 0 to indicate connection closed */
AzureIoTClient 1:eab586236bfe 1774 return local_deadline > remote_deadline ? remote_deadline : local_deadline;
AzureIoTClient 1:eab586236bfe 1775 }
AzureIoTClient 1:eab586236bfe 1776
Azure.IoT Build 0:6ae2f7bca550 1777 void connection_dowork(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 1778 {
AzureIoTClient 4:98007eb79fa8 1779 /* Codes_SRS_CONNECTION_01_078: [If handle is NULL, connection_dowork shall do nothing.] */
AzureIoTClient 28:add19eb7defa 1780 if (connection == NULL)
AzureIoTClient 28:add19eb7defa 1781 {
AzureIoTClient 28:add19eb7defa 1782 LogError("NULL connection");
AzureIoTClient 28:add19eb7defa 1783 }
AzureIoTClient 28:add19eb7defa 1784 else
AzureIoTClient 28:add19eb7defa 1785 {
AzureIoTClient 1:eab586236bfe 1786 if (connection_handle_deadlines(connection) > 0)
AzureIoTClient 1:eab586236bfe 1787 {
AzureIoTClient 1:eab586236bfe 1788 /* Codes_SRS_CONNECTION_01_076: [connection_dowork shall schedule the underlying IO interface to do its work by calling xio_dowork.] */
AzureIoTClient 1:eab586236bfe 1789 xio_dowork(connection->io);
AzureIoTClient 1:eab586236bfe 1790 }
AzureIoTClient 1:eab586236bfe 1791 }
Azure.IoT Build 0:6ae2f7bca550 1792 }
Azure.IoT Build 0:6ae2f7bca550 1793
Azure.IoT Build 0:6ae2f7bca550 1794 ENDPOINT_HANDLE connection_create_endpoint(CONNECTION_HANDLE connection)
Azure.IoT Build 0:6ae2f7bca550 1795 {
AzureIoTClient 28:add19eb7defa 1796 ENDPOINT_HANDLE result;
Azure.IoT Build 0:6ae2f7bca550 1797
AzureIoTClient 4:98007eb79fa8 1798 /* 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 1799 /* Codes_SRS_CONNECTION_01_193: [The context argument shall be allowed to be NULL.] */
AzureIoTClient 4:98007eb79fa8 1800 if (connection == NULL)
AzureIoTClient 4:98007eb79fa8 1801 {
AzureIoTClient 28:add19eb7defa 1802 LogError("NULL connection");
AzureIoTClient 28:add19eb7defa 1803 result = NULL;
AzureIoTClient 4:98007eb79fa8 1804 }
AzureIoTClient 4:98007eb79fa8 1805 else
AzureIoTClient 4:98007eb79fa8 1806 {
AzureIoTClient 4:98007eb79fa8 1807 /* 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 1808 if (connection->endpoint_count >= connection->channel_max)
AzureIoTClient 4:98007eb79fa8 1809 {
AzureIoTClient 4:98007eb79fa8 1810 result = NULL;
AzureIoTClient 4:98007eb79fa8 1811 }
AzureIoTClient 4:98007eb79fa8 1812 else
AzureIoTClient 4:98007eb79fa8 1813 {
AzureIoTClient 4:98007eb79fa8 1814 uint32_t i = 0;
Azure.IoT Build 0:6ae2f7bca550 1815
AzureIoTClient 4:98007eb79fa8 1816 /* Codes_SRS_CONNECTION_01_128: [The lowest number outgoing channel shall be associated with the newly created endpoint.] */
AzureIoTClient 4:98007eb79fa8 1817 for (i = 0; i < connection->endpoint_count; i++)
AzureIoTClient 4:98007eb79fa8 1818 {
AzureIoTClient 4:98007eb79fa8 1819 if (connection->endpoints[i]->outgoing_channel > i)
AzureIoTClient 4:98007eb79fa8 1820 {
AzureIoTClient 4:98007eb79fa8 1821 /* found a gap in the sorted endpoint array */
AzureIoTClient 4:98007eb79fa8 1822 break;
AzureIoTClient 4:98007eb79fa8 1823 }
AzureIoTClient 4:98007eb79fa8 1824 }
Azure.IoT Build 0:6ae2f7bca550 1825
AzureIoTClient 4:98007eb79fa8 1826 /* Codes_SRS_CONNECTION_01_127: [On success, connection_create_endpoint shall return a non-NULL handle to the newly created endpoint.] */
AzureIoTClient 24:2c59c2d43ebf 1827 result = (ENDPOINT_HANDLE)malloc(sizeof(ENDPOINT_INSTANCE));
AzureIoTClient 4:98007eb79fa8 1828 /* Codes_SRS_CONNECTION_01_196: [If memory cannot be allocated for the new endpoint, connection_create_endpoint shall fail and return NULL.] */
AzureIoTClient 28:add19eb7defa 1829 if (result == NULL)
AzureIoTClient 28:add19eb7defa 1830 {
AzureIoTClient 28:add19eb7defa 1831 LogError("Cannot allocate memory for endpoint");
AzureIoTClient 28:add19eb7defa 1832 }
AzureIoTClient 28:add19eb7defa 1833 else
AzureIoTClient 28:add19eb7defa 1834 {
AzureIoTClient 28:add19eb7defa 1835 ENDPOINT_HANDLE* new_endpoints;
Azure.IoT Build 0:6ae2f7bca550 1836
AzureIoTClient 4:98007eb79fa8 1837 result->on_endpoint_frame_received = NULL;
AzureIoTClient 4:98007eb79fa8 1838 result->on_connection_state_changed = NULL;
AzureIoTClient 4:98007eb79fa8 1839 result->callback_context = NULL;
AzureIoTClient 6:641a9672db08 1840 result->outgoing_channel = (uint16_t)i;
AzureIoTClient 4:98007eb79fa8 1841 result->connection = connection;
Azure.IoT Build 0:6ae2f7bca550 1842
AzureIoTClient 4:98007eb79fa8 1843 /* Codes_SRS_CONNECTION_01_197: [The newly created endpoint shall be added to the endpoints list, so that it can be tracked.] */
AzureIoTClient 24:2c59c2d43ebf 1844 new_endpoints = (ENDPOINT_HANDLE*)realloc(connection->endpoints, sizeof(ENDPOINT_HANDLE) * (connection->endpoint_count + 1));
AzureIoTClient 4:98007eb79fa8 1845 if (new_endpoints == NULL)
AzureIoTClient 4:98007eb79fa8 1846 {
AzureIoTClient 4:98007eb79fa8 1847 /* 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 28:add19eb7defa 1848 LogError("Cannot reallocate memory for connection endpoints");
AzureIoTClient 28:add19eb7defa 1849 free(result);
AzureIoTClient 4:98007eb79fa8 1850 result = NULL;
AzureIoTClient 4:98007eb79fa8 1851 }
AzureIoTClient 4:98007eb79fa8 1852 else
AzureIoTClient 4:98007eb79fa8 1853 {
AzureIoTClient 4:98007eb79fa8 1854 connection->endpoints = new_endpoints;
Azure.IoT Build 0:6ae2f7bca550 1855
AzureIoTClient 4:98007eb79fa8 1856 if (i < connection->endpoint_count)
AzureIoTClient 4:98007eb79fa8 1857 {
AzureIoTClient 4:98007eb79fa8 1858 (void)memmove(&connection->endpoints[i + 1], &connection->endpoints[i], sizeof(ENDPOINT_INSTANCE*) * (connection->endpoint_count - i));
AzureIoTClient 4:98007eb79fa8 1859 }
Azure.IoT Build 0:6ae2f7bca550 1860
AzureIoTClient 4:98007eb79fa8 1861 connection->endpoints[i] = result;
AzureIoTClient 4:98007eb79fa8 1862 connection->endpoint_count++;
Azure.IoT Build 0:6ae2f7bca550 1863
AzureIoTClient 4:98007eb79fa8 1864 /* Codes_SRS_CONNECTION_01_112: [connection_create_endpoint shall create a new endpoint that can be used by a session.] */
AzureIoTClient 4:98007eb79fa8 1865 }
AzureIoTClient 4:98007eb79fa8 1866 }
AzureIoTClient 4:98007eb79fa8 1867 }
AzureIoTClient 4:98007eb79fa8 1868 }
Azure.IoT Build 0:6ae2f7bca550 1869
AzureIoTClient 4:98007eb79fa8 1870 return result;
Azure.IoT Build 0:6ae2f7bca550 1871 }
Azure.IoT Build 0:6ae2f7bca550 1872
Azure.IoT Build 0:6ae2f7bca550 1873 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 1874 {
AzureIoTClient 4:98007eb79fa8 1875 int result;
Azure.IoT Build 0:6ae2f7bca550 1876
AzureIoTClient 4:98007eb79fa8 1877 if ((endpoint == NULL) ||
AzureIoTClient 4:98007eb79fa8 1878 (on_endpoint_frame_received == NULL) ||
AzureIoTClient 4:98007eb79fa8 1879 (on_connection_state_changed == NULL))
AzureIoTClient 4:98007eb79fa8 1880 {
AzureIoTClient 28:add19eb7defa 1881 LogError("Bad arguments: endpoint = %p, on_endpoint_frame_received = %p, on_connection_state_changed = %p",
AzureIoTClient 28:add19eb7defa 1882 endpoint, on_endpoint_frame_received, on_connection_state_changed);
AzureIoTClient 28:add19eb7defa 1883 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1884 }
AzureIoTClient 4:98007eb79fa8 1885 else
AzureIoTClient 4:98007eb79fa8 1886 {
AzureIoTClient 4:98007eb79fa8 1887 endpoint->on_endpoint_frame_received = on_endpoint_frame_received;
AzureIoTClient 4:98007eb79fa8 1888 endpoint->on_connection_state_changed = on_connection_state_changed;
AzureIoTClient 4:98007eb79fa8 1889 endpoint->callback_context = context;
Azure.IoT Build 0:6ae2f7bca550 1890
AzureIoTClient 4:98007eb79fa8 1891 result = 0;
AzureIoTClient 4:98007eb79fa8 1892 }
Azure.IoT Build 0:6ae2f7bca550 1893
AzureIoTClient 4:98007eb79fa8 1894 return result;
Azure.IoT Build 0:6ae2f7bca550 1895 }
Azure.IoT Build 0:6ae2f7bca550 1896
Azure.IoT Build 0:6ae2f7bca550 1897 int connection_endpoint_get_incoming_channel(ENDPOINT_HANDLE endpoint, uint16_t* incoming_channel)
Azure.IoT Build 0:6ae2f7bca550 1898 {
AzureIoTClient 4:98007eb79fa8 1899 int result;
Azure.IoT Build 0:6ae2f7bca550 1900
AzureIoTClient 4:98007eb79fa8 1901 if ((endpoint == NULL) ||
AzureIoTClient 4:98007eb79fa8 1902 (incoming_channel == NULL))
AzureIoTClient 4:98007eb79fa8 1903 {
AzureIoTClient 28:add19eb7defa 1904 LogError("Bad arguments: endpoint = %p, incoming_channel = %p",
AzureIoTClient 28:add19eb7defa 1905 endpoint, incoming_channel);
AzureIoTClient 28:add19eb7defa 1906 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1907 }
AzureIoTClient 4:98007eb79fa8 1908 else
AzureIoTClient 4:98007eb79fa8 1909 {
AzureIoTClient 4:98007eb79fa8 1910 *incoming_channel = endpoint->incoming_channel;
AzureIoTClient 4:98007eb79fa8 1911 result = 0;
AzureIoTClient 4:98007eb79fa8 1912 }
Azure.IoT Build 0:6ae2f7bca550 1913
AzureIoTClient 4:98007eb79fa8 1914 return result;
Azure.IoT Build 0:6ae2f7bca550 1915 }
Azure.IoT Build 0:6ae2f7bca550 1916
Azure.IoT Build 0:6ae2f7bca550 1917 /* 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 1918 void connection_destroy_endpoint(ENDPOINT_HANDLE endpoint)
Azure.IoT Build 0:6ae2f7bca550 1919 {
AzureIoTClient 28:add19eb7defa 1920 if (endpoint == NULL)
AzureIoTClient 28:add19eb7defa 1921 {
AzureIoTClient 28:add19eb7defa 1922 LogError("NULL endpoint");
AzureIoTClient 28:add19eb7defa 1923 }
AzureIoTClient 28:add19eb7defa 1924 else
AzureIoTClient 28:add19eb7defa 1925 {
AzureIoTClient 24:2c59c2d43ebf 1926 CONNECTION_HANDLE connection = (CONNECTION_HANDLE)endpoint->connection;
AzureIoTClient 4:98007eb79fa8 1927 size_t i;
Azure.IoT Build 0:6ae2f7bca550 1928
AzureIoTClient 4:98007eb79fa8 1929 for (i = 0; i < connection->endpoint_count; i++)
AzureIoTClient 4:98007eb79fa8 1930 {
AzureIoTClient 4:98007eb79fa8 1931 if (connection->endpoints[i] == endpoint)
AzureIoTClient 4:98007eb79fa8 1932 {
AzureIoTClient 4:98007eb79fa8 1933 break;
AzureIoTClient 4:98007eb79fa8 1934 }
AzureIoTClient 4:98007eb79fa8 1935 }
Azure.IoT Build 0:6ae2f7bca550 1936
AzureIoTClient 4:98007eb79fa8 1937 /* 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 1938 /* Codes_SRS_CONNECTION_01_131: [Any incoming channel number associated with the endpoint shall be released.] */
AzureIoTClient 28:add19eb7defa 1939 if ((i < connection->endpoint_count) && (i > 0))
AzureIoTClient 28:add19eb7defa 1940 {
AzureIoTClient 28:add19eb7defa 1941 ENDPOINT_HANDLE* new_endpoints;
AzureIoTClient 28:add19eb7defa 1942 (void)memmove(connection->endpoints + i, connection->endpoints + i + 1, sizeof(ENDPOINT_HANDLE) * (connection->endpoint_count - i - 1));
Azure.IoT Build 0:6ae2f7bca550 1943
AzureIoTClient 28:add19eb7defa 1944 new_endpoints = (ENDPOINT_HANDLE*)realloc(connection->endpoints, (connection->endpoint_count - 1) * sizeof(ENDPOINT_HANDLE));
AzureIoTClient 28:add19eb7defa 1945 if (new_endpoints != NULL)
AzureIoTClient 28:add19eb7defa 1946 {
AzureIoTClient 28:add19eb7defa 1947 connection->endpoints = new_endpoints;
AzureIoTClient 28:add19eb7defa 1948 }
Azure.IoT Build 0:6ae2f7bca550 1949
AzureIoTClient 28:add19eb7defa 1950 connection->endpoint_count--;
AzureIoTClient 28:add19eb7defa 1951 }
AzureIoTClient 28:add19eb7defa 1952 else if (connection->endpoint_count == 1)
AzureIoTClient 28:add19eb7defa 1953 {
AzureIoTClient 28:add19eb7defa 1954 free(connection->endpoints);
AzureIoTClient 28:add19eb7defa 1955 connection->endpoints = NULL;
AzureIoTClient 28:add19eb7defa 1956 connection->endpoint_count = 0;
AzureIoTClient 28:add19eb7defa 1957 }
Azure.IoT Build 0:6ae2f7bca550 1958
AzureIoTClient 21:f9c433d8e6ca 1959 free(endpoint);
AzureIoTClient 4:98007eb79fa8 1960 }
Azure.IoT Build 0:6ae2f7bca550 1961 }
Azure.IoT Build 0:6ae2f7bca550 1962
Azure.IoT Build 0:6ae2f7bca550 1963 /* Codes_SRS_CONNECTION_01_247: [connection_encode_frame shall send a frame for a certain endpoint.] */
AzureIoTClient 30:0407b2db334c 1964 int connection_encode_frame(ENDPOINT_HANDLE endpoint, AMQP_VALUE performative, PAYLOAD* payloads, size_t payload_count, ON_SEND_COMPLETE on_send_complete, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 1965 {
AzureIoTClient 4:98007eb79fa8 1966 int result;
Azure.IoT Build 0:6ae2f7bca550 1967
AzureIoTClient 4:98007eb79fa8 1968 /* 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 1969 if ((endpoint == NULL) ||
AzureIoTClient 4:98007eb79fa8 1970 (performative == NULL))
AzureIoTClient 4:98007eb79fa8 1971 {
AzureIoTClient 28:add19eb7defa 1972 LogError("Bad arguments: endpoint = %p, performative = %p",
AzureIoTClient 28:add19eb7defa 1973 endpoint, performative);
AzureIoTClient 28:add19eb7defa 1974 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1975 }
AzureIoTClient 4:98007eb79fa8 1976 else
AzureIoTClient 4:98007eb79fa8 1977 {
AzureIoTClient 28:add19eb7defa 1978 CONNECTION_HANDLE connection = (CONNECTION_HANDLE)endpoint->connection;
AzureIoTClient 4:98007eb79fa8 1979 AMQP_FRAME_CODEC_HANDLE amqp_frame_codec = connection->amqp_frame_codec;
Azure.IoT Build 0:6ae2f7bca550 1980
AzureIoTClient 4:98007eb79fa8 1981 /* 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 1982 if (connection->connection_state != CONNECTION_STATE_OPENED)
AzureIoTClient 4:98007eb79fa8 1983 {
AzureIoTClient 28:add19eb7defa 1984 LogError("Connection not open");
AzureIoTClient 28:add19eb7defa 1985 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 1986 }
AzureIoTClient 4:98007eb79fa8 1987 else
AzureIoTClient 4:98007eb79fa8 1988 {
AzureIoTClient 4:98007eb79fa8 1989 /* 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 1990 /* Codes_SRS_CONNECTION_01_250: [connection_encode_frame shall initiate the frame send by calling amqp_frame_codec_begin_encode_frame.] */
AzureIoTClient 4:98007eb79fa8 1991 /* 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 1992 /* 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 1993 connection->on_send_complete = on_send_complete;
AzureIoTClient 4:98007eb79fa8 1994 connection->on_send_complete_callback_context = callback_context;
AzureIoTClient 4:98007eb79fa8 1995 if (amqp_frame_codec_encode_frame(amqp_frame_codec, endpoint->outgoing_channel, performative, payloads, payload_count, on_bytes_encoded, connection) != 0)
AzureIoTClient 4:98007eb79fa8 1996 {
AzureIoTClient 4:98007eb79fa8 1997 /* 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 28:add19eb7defa 1998 LogError("Encoding AMQP frame failed");
AzureIoTClient 28:add19eb7defa 1999 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 2000 }
AzureIoTClient 4:98007eb79fa8 2001 else
AzureIoTClient 4:98007eb79fa8 2002 {
AzureIoTClient 4:98007eb79fa8 2003 if (connection->is_trace_on == 1)
AzureIoTClient 4:98007eb79fa8 2004 {
Azure.IoT Build 5:ae49385aff34 2005 log_outgoing_frame(performative);
AzureIoTClient 4:98007eb79fa8 2006 }
Azure.IoT Build 5:ae49385aff34 2007
AzureIoTClient 4:98007eb79fa8 2008 if (tickcounter_get_current_ms(connection->tick_counter, &connection->last_frame_sent_time) != 0)
AzureIoTClient 4:98007eb79fa8 2009 {
AzureIoTClient 28:add19eb7defa 2010 LogError("Getting tick counter value failed");
AzureIoTClient 28:add19eb7defa 2011 result = __FAILURE__;
AzureIoTClient 4:98007eb79fa8 2012 }
AzureIoTClient 4:98007eb79fa8 2013 else
AzureIoTClient 4:98007eb79fa8 2014 {
AzureIoTClient 4:98007eb79fa8 2015 /* Codes_SRS_CONNECTION_01_248: [On success it shall return 0.] */
AzureIoTClient 4:98007eb79fa8 2016 result = 0;
AzureIoTClient 4:98007eb79fa8 2017 }
AzureIoTClient 4:98007eb79fa8 2018 }
AzureIoTClient 4:98007eb79fa8 2019 }
AzureIoTClient 4:98007eb79fa8 2020 }
Azure.IoT Build 0:6ae2f7bca550 2021
AzureIoTClient 4:98007eb79fa8 2022 return result;
Azure.IoT Build 0:6ae2f7bca550 2023 }
AzureIoTClient 4:98007eb79fa8 2024
AzureIoTClient 24:2c59c2d43ebf 2025 void connection_set_trace(CONNECTION_HANDLE connection, bool trace_on)
AzureIoTClient 4:98007eb79fa8 2026 {
AzureIoTClient 4:98007eb79fa8 2027 /* Codes_SRS_CONNECTION_07_002: [If connection is NULL then connection_set_trace shall do nothing.] */
AzureIoTClient 28:add19eb7defa 2028 if (connection == NULL)
AzureIoTClient 28:add19eb7defa 2029 {
AzureIoTClient 28:add19eb7defa 2030 LogError("NULL connection");
AzureIoTClient 28:add19eb7defa 2031 }
AzureIoTClient 28:add19eb7defa 2032 else
AzureIoTClient 28:add19eb7defa 2033 {
AzureIoTClient 4:98007eb79fa8 2034 /* Codes_SRS_CONNECTION_07_001: [connection_set_trace shall set the ability to turn on and off trace logging.] */
AzureIoTClient 24:2c59c2d43ebf 2035 connection->is_trace_on = trace_on ? 1 : 0;
AzureIoTClient 4:98007eb79fa8 2036 }
AzureIoTClient 4:98007eb79fa8 2037 }
AzureIoTClient 35:d0bed2404ee9 2038
AzureIoTClient 35:d0bed2404ee9 2039 int connection_set_remote_idle_timeout_empty_frame_send_ratio(CONNECTION_HANDLE connection, double idle_timeout_empty_frame_send_ratio)
AzureIoTClient 35:d0bed2404ee9 2040 {
AzureIoTClient 35:d0bed2404ee9 2041 int result;
AzureIoTClient 35:d0bed2404ee9 2042
AzureIoTClient 35:d0bed2404ee9 2043 if ((connection == NULL) ||
AzureIoTClient 35:d0bed2404ee9 2044 (idle_timeout_empty_frame_send_ratio <= 0.0) ||
AzureIoTClient 35:d0bed2404ee9 2045 (idle_timeout_empty_frame_send_ratio > 1.0))
AzureIoTClient 35:d0bed2404ee9 2046 {
AzureIoTClient 35:d0bed2404ee9 2047 LogError("Bad arguments: connection = %p, idle_timeout_empty_frame_send_ratio = %f",
AzureIoTClient 35:d0bed2404ee9 2048 connection, idle_timeout_empty_frame_send_ratio);
AzureIoTClient 35:d0bed2404ee9 2049 result = __FAILURE__;
AzureIoTClient 35:d0bed2404ee9 2050 }
AzureIoTClient 35:d0bed2404ee9 2051 else
AzureIoTClient 35:d0bed2404ee9 2052 {
AzureIoTClient 35:d0bed2404ee9 2053 connection->idle_timeout_empty_frame_send_ratio = idle_timeout_empty_frame_send_ratio;
AzureIoTClient 35:d0bed2404ee9 2054 result = 0;
AzureIoTClient 35:d0bed2404ee9 2055 }
AzureIoTClient 35:d0bed2404ee9 2056
AzureIoTClient 35:d0bed2404ee9 2057 return result;
AzureIoTClient 35:d0bed2404ee9 2058 }