A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Sun Apr 24 16:40:31 2016 -0700
Revision:
1:eab586236bfe
Parent:
0:6ae2f7bca550
Child:
4:98007eb79fa8
1.0.5

Who changed what in which revision?

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