A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Mon Jun 11 15:39:52 2018 -0700
Revision:
43:4c1e4e94cdd3
Parent:
41:0e723f9cbd89
Child:
45:83b4eda4891c
1.2.5

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