A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Tue Jun 07 10:49:20 2016 -0700
Revision:
4:98007eb79fa8
Parent:
1:eab586236bfe
Child:
5:ae49385aff34
1.0.8

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