A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Tue Jan 30 08:21:55 2018 -0800
Revision:
38:7631b92cc772
Parent:
30:0407b2db334c
Child:
43:4c1e4e94cdd3
1.1.31

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Azure.IoT Build 0:6ae2f7bca550 1 // Copyright (c) Microsoft. All rights reserved.
Azure.IoT Build 0:6ae2f7bca550 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
Azure.IoT Build 0:6ae2f7bca550 3
Azure.IoT Build 0:6ae2f7bca550 4 #include <stdlib.h>
Azure.IoT Build 0:6ae2f7bca550 5 #include <stddef.h>
Azure.IoT Build 0:6ae2f7bca550 6 #include <stdio.h>
Azure.IoT Build 0:6ae2f7bca550 7 #include <string.h>
AzureIoTClient 6:641a9672db08 8 #include <stdbool.h>
AzureIoTClient 23:1111ee8bcba4 9
AzureIoTClient 21:f9c433d8e6ca 10 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 19:000ab4e6a2c1 11 #include "azure_c_shared_utility/optimize_size.h"
Azure.IoT Build 0:6ae2f7bca550 12 #include "azure_uamqp_c/saslclientio.h"
Azure.IoT Build 0:6ae2f7bca550 13 #include "azure_c_shared_utility/xio.h"
Azure.IoT Build 0:6ae2f7bca550 14 #include "azure_c_shared_utility/xlogging.h"
Azure.IoT Build 0:6ae2f7bca550 15 #include "azure_uamqp_c/frame_codec.h"
Azure.IoT Build 0:6ae2f7bca550 16 #include "azure_uamqp_c/sasl_frame_codec.h"
Azure.IoT Build 0:6ae2f7bca550 17 #include "azure_uamqp_c/amqp_definitions.h"
Azure.IoT Build 0:6ae2f7bca550 18 #include "azure_uamqp_c/amqpvalue_to_string.h"
Azure.IoT Build 0:6ae2f7bca550 19
Azure.IoT Build 0:6ae2f7bca550 20 typedef enum IO_STATE_TAG
Azure.IoT Build 0:6ae2f7bca550 21 {
AzureIoTClient 6:641a9672db08 22 IO_STATE_NOT_OPEN,
AzureIoTClient 6:641a9672db08 23 IO_STATE_OPENING_UNDERLYING_IO,
AzureIoTClient 6:641a9672db08 24 IO_STATE_SASL_HANDSHAKE,
AzureIoTClient 6:641a9672db08 25 IO_STATE_OPEN,
AzureIoTClient 6:641a9672db08 26 IO_STATE_CLOSING,
AzureIoTClient 6:641a9672db08 27 IO_STATE_ERROR
Azure.IoT Build 0:6ae2f7bca550 28 } IO_STATE;
Azure.IoT Build 0:6ae2f7bca550 29
AzureIoTClient 23:1111ee8bcba4 30 #define SASL_HEADER_EXCHANGE_STATE_VALUES \
AzureIoTClient 23:1111ee8bcba4 31 SASL_HEADER_EXCHANGE_IDLE, \
AzureIoTClient 23:1111ee8bcba4 32 SASL_HEADER_EXCHANGE_HEADER_SENT, \
AzureIoTClient 23:1111ee8bcba4 33 SASL_HEADER_EXCHANGE_HEADER_RCVD, \
AzureIoTClient 6:641a9672db08 34 SASL_HEADER_EXCHANGE_HEADER_EXCH
AzureIoTClient 23:1111ee8bcba4 35
AzureIoTClient 23:1111ee8bcba4 36 DEFINE_LOCAL_ENUM(SASL_HEADER_EXCHANGE_STATE, SASL_HEADER_EXCHANGE_STATE_VALUES)
Azure.IoT Build 0:6ae2f7bca550 37
AzureIoTClient 23:1111ee8bcba4 38 #define SASL_CLIENT_NEGOTIATION_STATE_VALUES \
AzureIoTClient 23:1111ee8bcba4 39 SASL_CLIENT_NEGOTIATION_NOT_STARTED, \
AzureIoTClient 23:1111ee8bcba4 40 SASL_CLIENT_NEGOTIATION_MECH_RCVD, \
AzureIoTClient 23:1111ee8bcba4 41 SASL_CLIENT_NEGOTIATION_INIT_SENT, \
AzureIoTClient 23:1111ee8bcba4 42 SASL_CLIENT_NEGOTIATION_CHALLENGE_RCVD, \
AzureIoTClient 23:1111ee8bcba4 43 SASL_CLIENT_NEGOTIATION_RESPONSE_SENT, \
AzureIoTClient 23:1111ee8bcba4 44 SASL_CLIENT_NEGOTIATION_OUTCOME_RCVD, \
AzureIoTClient 6:641a9672db08 45 SASL_CLIENT_NEGOTIATION_ERROR
AzureIoTClient 23:1111ee8bcba4 46
AzureIoTClient 23:1111ee8bcba4 47 DEFINE_LOCAL_ENUM(SASL_CLIENT_NEGOTIATION_STATE, SASL_CLIENT_NEGOTIATION_STATE_VALUES)
Azure.IoT Build 0:6ae2f7bca550 48
Azure.IoT Build 0:6ae2f7bca550 49 typedef struct SASL_CLIENT_IO_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 50 {
AzureIoTClient 6:641a9672db08 51 XIO_HANDLE underlying_io;
AzureIoTClient 6:641a9672db08 52 ON_BYTES_RECEIVED on_bytes_received;
AzureIoTClient 6:641a9672db08 53 ON_IO_OPEN_COMPLETE on_io_open_complete;
AzureIoTClient 6:641a9672db08 54 ON_IO_CLOSE_COMPLETE on_io_close_complete;
AzureIoTClient 6:641a9672db08 55 ON_IO_ERROR on_io_error;
Azure.IoT Build 0:6ae2f7bca550 56 void* on_bytes_received_context;
AzureIoTClient 6:641a9672db08 57 void* on_io_open_complete_context;
AzureIoTClient 6:641a9672db08 58 void* on_io_close_complete_context;
Azure.IoT Build 0:6ae2f7bca550 59 void* on_io_error_context;
AzureIoTClient 6:641a9672db08 60 SASL_HEADER_EXCHANGE_STATE sasl_header_exchange_state;
AzureIoTClient 6:641a9672db08 61 SASL_CLIENT_NEGOTIATION_STATE sasl_client_negotiation_state;
AzureIoTClient 6:641a9672db08 62 size_t header_bytes_received;
AzureIoTClient 6:641a9672db08 63 SASL_FRAME_CODEC_HANDLE sasl_frame_codec;
AzureIoTClient 6:641a9672db08 64 FRAME_CODEC_HANDLE frame_codec;
AzureIoTClient 6:641a9672db08 65 IO_STATE io_state;
AzureIoTClient 6:641a9672db08 66 SASL_MECHANISM_HANDLE sasl_mechanism;
AzureIoTClient 6:641a9672db08 67 unsigned int is_trace_on : 1;
AzureIoTClient 30:0407b2db334c 68 unsigned int is_trace_on_set : 1;
Azure.IoT Build 0:6ae2f7bca550 69 } SASL_CLIENT_IO_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 70
AzureIoTClient 16:22a72cf8e416 71 /* Codes_SRS_SASLCLIENTIO_01_002: [The protocol header consists of the upper case ASCII letters "AMQP" followed by a protocol id of three, followed by three unsigned bytes representing the major, minor, and revision of the specification version (currently 1 (SASL-MAJOR), 0 (SASLMINOR), 0 (SASL-REVISION)).] */
Azure.IoT Build 0:6ae2f7bca550 72 /* Codes_SRS_SASLCLIENTIO_01_124: [SASL-MAJOR 1 major protocol version.] */
Azure.IoT Build 0:6ae2f7bca550 73 /* Codes_SRS_SASLCLIENTIO_01_125: [SASL-MINOR 0 minor protocol version.] */
Azure.IoT Build 0:6ae2f7bca550 74 /* Codes_SRS_SASLCLIENTIO_01_126: [SASL-REVISION 0 protocol revision.] */
AzureIoTClient 21:f9c433d8e6ca 75 static const unsigned char sasl_header[] = { 'A', 'M', 'Q', 'P', 3, 1, 0, 0 };
Azure.IoT Build 0:6ae2f7bca550 76
Azure.IoT Build 0:6ae2f7bca550 77 static void indicate_error(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance)
Azure.IoT Build 0:6ae2f7bca550 78 {
AzureIoTClient 6:641a9672db08 79 if (sasl_client_io_instance->on_io_error != NULL)
AzureIoTClient 6:641a9672db08 80 {
AzureIoTClient 6:641a9672db08 81 sasl_client_io_instance->on_io_error(sasl_client_io_instance->on_io_error_context);
AzureIoTClient 6:641a9672db08 82 }
Azure.IoT Build 0:6ae2f7bca550 83 }
Azure.IoT Build 0:6ae2f7bca550 84
Azure.IoT Build 0:6ae2f7bca550 85 static void indicate_open_complete(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance, IO_OPEN_RESULT open_result)
Azure.IoT Build 0:6ae2f7bca550 86 {
AzureIoTClient 6:641a9672db08 87 if (sasl_client_io_instance->on_io_open_complete != NULL)
AzureIoTClient 6:641a9672db08 88 {
AzureIoTClient 6:641a9672db08 89 sasl_client_io_instance->on_io_open_complete(sasl_client_io_instance->on_io_open_complete_context, open_result);
AzureIoTClient 6:641a9672db08 90 }
Azure.IoT Build 0:6ae2f7bca550 91 }
Azure.IoT Build 0:6ae2f7bca550 92
Azure.IoT Build 0:6ae2f7bca550 93 static void indicate_close_complete(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance)
Azure.IoT Build 0:6ae2f7bca550 94 {
AzureIoTClient 6:641a9672db08 95 if (sasl_client_io_instance->on_io_close_complete != NULL)
AzureIoTClient 6:641a9672db08 96 {
AzureIoTClient 6:641a9672db08 97 sasl_client_io_instance->on_io_close_complete(sasl_client_io_instance->on_io_close_complete_context);
AzureIoTClient 6:641a9672db08 98 }
Azure.IoT Build 0:6ae2f7bca550 99 }
Azure.IoT Build 0:6ae2f7bca550 100
Azure.IoT Build 0:6ae2f7bca550 101 static void on_underlying_io_close_complete(void* context)
Azure.IoT Build 0:6ae2f7bca550 102 {
AzureIoTClient 6:641a9672db08 103 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 104
AzureIoTClient 6:641a9672db08 105 switch (sasl_client_io_instance->io_state)
AzureIoTClient 6:641a9672db08 106 {
AzureIoTClient 6:641a9672db08 107 default:
AzureIoTClient 6:641a9672db08 108 break;
Azure.IoT Build 0:6ae2f7bca550 109
AzureIoTClient 6:641a9672db08 110 case IO_STATE_OPENING_UNDERLYING_IO:
AzureIoTClient 6:641a9672db08 111 case IO_STATE_SASL_HANDSHAKE:
AzureIoTClient 6:641a9672db08 112 sasl_client_io_instance->io_state = IO_STATE_NOT_OPEN;
AzureIoTClient 6:641a9672db08 113 indicate_open_complete(sasl_client_io_instance, IO_OPEN_ERROR);
AzureIoTClient 6:641a9672db08 114 break;
Azure.IoT Build 0:6ae2f7bca550 115
AzureIoTClient 6:641a9672db08 116 case IO_STATE_CLOSING:
AzureIoTClient 6:641a9672db08 117 sasl_client_io_instance->io_state = IO_STATE_NOT_OPEN;
AzureIoTClient 6:641a9672db08 118 indicate_close_complete(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 119 break;
AzureIoTClient 6:641a9672db08 120 }
Azure.IoT Build 0:6ae2f7bca550 121 }
Azure.IoT Build 0:6ae2f7bca550 122
Azure.IoT Build 0:6ae2f7bca550 123 static void handle_error(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance)
Azure.IoT Build 0:6ae2f7bca550 124 {
AzureIoTClient 6:641a9672db08 125 switch (sasl_client_io_instance->io_state)
AzureIoTClient 6:641a9672db08 126 {
AzureIoTClient 6:641a9672db08 127 default:
AzureIoTClient 6:641a9672db08 128 case IO_STATE_NOT_OPEN:
AzureIoTClient 6:641a9672db08 129 break;
Azure.IoT Build 0:6ae2f7bca550 130
AzureIoTClient 6:641a9672db08 131 case IO_STATE_OPENING_UNDERLYING_IO:
AzureIoTClient 6:641a9672db08 132 case IO_STATE_SASL_HANDSHAKE:
AzureIoTClient 6:641a9672db08 133 if (xio_close(sasl_client_io_instance->underlying_io, on_underlying_io_close_complete, sasl_client_io_instance) != 0)
AzureIoTClient 6:641a9672db08 134 {
AzureIoTClient 6:641a9672db08 135 sasl_client_io_instance->io_state = IO_STATE_NOT_OPEN;
AzureIoTClient 6:641a9672db08 136 indicate_open_complete(sasl_client_io_instance, IO_OPEN_ERROR);
AzureIoTClient 6:641a9672db08 137 }
AzureIoTClient 6:641a9672db08 138 break;
Azure.IoT Build 0:6ae2f7bca550 139
AzureIoTClient 6:641a9672db08 140 case IO_STATE_OPEN:
AzureIoTClient 6:641a9672db08 141 sasl_client_io_instance->io_state = IO_STATE_ERROR;
AzureIoTClient 6:641a9672db08 142 indicate_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 143 break;
AzureIoTClient 6:641a9672db08 144 }
Azure.IoT Build 0:6ae2f7bca550 145 }
Azure.IoT Build 0:6ae2f7bca550 146
AzureIoTClient 38:7631b92cc772 147 // This callback usage needs to be either verified and commented or integrated into
AzureIoTClient 38:7631b92cc772 148 // the state machine.
AzureIoTClient 38:7631b92cc772 149 static void unchecked_on_send_complete(void* context, IO_SEND_RESULT send_result)
AzureIoTClient 38:7631b92cc772 150 {
AzureIoTClient 38:7631b92cc772 151 (void)context;
AzureIoTClient 38:7631b92cc772 152 (void)send_result;
AzureIoTClient 38:7631b92cc772 153 }
AzureIoTClient 38:7631b92cc772 154
Azure.IoT Build 0:6ae2f7bca550 155 static int send_sasl_header(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance)
Azure.IoT Build 0:6ae2f7bca550 156 {
AzureIoTClient 6:641a9672db08 157 int result;
Azure.IoT Build 0:6ae2f7bca550 158
AzureIoTClient 6:641a9672db08 159 /* Codes_SRS_SASLCLIENTIO_01_078: [SASL client IO shall start the header exchange by sending the SASL header.] */
AzureIoTClient 30:0407b2db334c 160 /* Codes_SRS_SASLCLIENTIO_01_095: [Sending the header shall be done by using `xio_send`.]*/
AzureIoTClient 38:7631b92cc772 161 if (xio_send(sasl_client_io_instance->underlying_io, sasl_header, sizeof(sasl_header), unchecked_on_send_complete, NULL) != 0)
AzureIoTClient 6:641a9672db08 162 {
AzureIoTClient 23:1111ee8bcba4 163 LogError("Sending SASL header failed");
AzureIoTClient 19:000ab4e6a2c1 164 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 165 }
AzureIoTClient 6:641a9672db08 166 else
AzureIoTClient 6:641a9672db08 167 {
AzureIoTClient 30:0407b2db334c 168 if (sasl_client_io_instance->is_trace_on != 0)
AzureIoTClient 6:641a9672db08 169 {
AzureIoTClient 16:22a72cf8e416 170 LOG(AZ_LOG_TRACE, LOG_LINE, "-> Header (AMQP 3.1.0.0)");
AzureIoTClient 6:641a9672db08 171 }
AzureIoTClient 23:1111ee8bcba4 172
AzureIoTClient 6:641a9672db08 173 result = 0;
AzureIoTClient 6:641a9672db08 174 }
Azure.IoT Build 0:6ae2f7bca550 175
AzureIoTClient 6:641a9672db08 176 return result;
Azure.IoT Build 0:6ae2f7bca550 177 }
Azure.IoT Build 0:6ae2f7bca550 178
Azure.IoT Build 0:6ae2f7bca550 179 static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT open_result)
Azure.IoT Build 0:6ae2f7bca550 180 {
AzureIoTClient 6:641a9672db08 181 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 182
AzureIoTClient 6:641a9672db08 183 switch (sasl_client_io_instance->io_state)
AzureIoTClient 6:641a9672db08 184 {
AzureIoTClient 6:641a9672db08 185 default:
AzureIoTClient 23:1111ee8bcba4 186 LogError("Open complete received in unexpected state");
AzureIoTClient 6:641a9672db08 187 break;
Azure.IoT Build 0:6ae2f7bca550 188
AzureIoTClient 30:0407b2db334c 189 case IO_STATE_SASL_HANDSHAKE:
AzureIoTClient 30:0407b2db334c 190 /* Codes_SRS_SASLCLIENTIO_01_110: [raise ERROR] */
AzureIoTClient 30:0407b2db334c 191 case IO_STATE_OPEN:
AzureIoTClient 30:0407b2db334c 192 /* Codes_SRS_SASLCLIENTIO_01_106: [raise error] */
AzureIoTClient 30:0407b2db334c 193 handle_error(sasl_client_io_instance);
AzureIoTClient 30:0407b2db334c 194 break;
AzureIoTClient 30:0407b2db334c 195
AzureIoTClient 6:641a9672db08 196 case IO_STATE_OPENING_UNDERLYING_IO:
AzureIoTClient 6:641a9672db08 197 if (open_result == IO_OPEN_OK)
AzureIoTClient 6:641a9672db08 198 {
AzureIoTClient 6:641a9672db08 199 sasl_client_io_instance->io_state = IO_STATE_SASL_HANDSHAKE;
AzureIoTClient 6:641a9672db08 200 if (sasl_client_io_instance->sasl_header_exchange_state != SASL_HEADER_EXCHANGE_IDLE)
AzureIoTClient 6:641a9672db08 201 {
AzureIoTClient 30:0407b2db334c 202 /* Codes_SRS_SASLCLIENTIO_01_116: [If the underlying IO indicates another open while the after the header exchange has been started an error shall be indicated by calling `on_io_error`.]*/
AzureIoTClient 6:641a9672db08 203 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 204 }
AzureIoTClient 6:641a9672db08 205 else
AzureIoTClient 6:641a9672db08 206 {
AzureIoTClient 6:641a9672db08 207 /* Codes_SRS_SASLCLIENTIO_01_105: [start header exchange] */
AzureIoTClient 6:641a9672db08 208 /* Codes_SRS_SASLCLIENTIO_01_001: [To establish a SASL layer, each peer MUST start by sending a protocol header.] */
AzureIoTClient 6:641a9672db08 209 if (send_sasl_header(sasl_client_io_instance) != 0)
AzureIoTClient 6:641a9672db08 210 {
AzureIoTClient 30:0407b2db334c 211 /* Codes_SRS_SASLCLIENTIO_01_073: [If the handshake fails (i.e. the outcome is an error) the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 30:0407b2db334c 212 /* Codes_SRS_SASLCLIENTIO_01_077: [If sending the SASL header fails, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 6:641a9672db08 213 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 214 }
AzureIoTClient 6:641a9672db08 215 else
AzureIoTClient 6:641a9672db08 216 {
AzureIoTClient 6:641a9672db08 217 sasl_client_io_instance->sasl_header_exchange_state = SASL_HEADER_EXCHANGE_HEADER_SENT;
AzureIoTClient 6:641a9672db08 218 }
AzureIoTClient 6:641a9672db08 219 }
AzureIoTClient 6:641a9672db08 220 }
AzureIoTClient 6:641a9672db08 221 else
AzureIoTClient 6:641a9672db08 222 {
AzureIoTClient 6:641a9672db08 223 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 224 }
Azure.IoT Build 0:6ae2f7bca550 225
AzureIoTClient 6:641a9672db08 226 break;
AzureIoTClient 6:641a9672db08 227 }
Azure.IoT Build 0:6ae2f7bca550 228 }
Azure.IoT Build 0:6ae2f7bca550 229
Azure.IoT Build 0:6ae2f7bca550 230 static void on_underlying_io_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 231 {
AzureIoTClient 6:641a9672db08 232 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 233
AzureIoTClient 6:641a9672db08 234 switch (sasl_client_io_instance->io_state)
AzureIoTClient 6:641a9672db08 235 {
AzureIoTClient 6:641a9672db08 236 default:
AzureIoTClient 23:1111ee8bcba4 237 LogError("Error callback received in unexpected state");
AzureIoTClient 6:641a9672db08 238 break;
Azure.IoT Build 0:6ae2f7bca550 239
AzureIoTClient 6:641a9672db08 240 case IO_STATE_OPENING_UNDERLYING_IO:
AzureIoTClient 6:641a9672db08 241 case IO_STATE_SASL_HANDSHAKE:
AzureIoTClient 30:0407b2db334c 242 /* Codes_SRS_SASLCLIENTIO_01_101: [`on_open_complete` with `IO_OPEN_ERROR`]*/
AzureIoTClient 30:0407b2db334c 243 if (xio_close(sasl_client_io_instance->underlying_io, on_underlying_io_close_complete, sasl_client_io_instance) != 0)
AzureIoTClient 30:0407b2db334c 244 {
AzureIoTClient 30:0407b2db334c 245 sasl_client_io_instance->io_state = IO_STATE_NOT_OPEN;
AzureIoTClient 30:0407b2db334c 246 indicate_open_complete(sasl_client_io_instance, IO_OPEN_ERROR);
AzureIoTClient 30:0407b2db334c 247 }
AzureIoTClient 30:0407b2db334c 248
AzureIoTClient 6:641a9672db08 249 break;
Azure.IoT Build 0:6ae2f7bca550 250
AzureIoTClient 6:641a9672db08 251 case IO_STATE_OPEN:
AzureIoTClient 6:641a9672db08 252 sasl_client_io_instance->io_state = IO_STATE_ERROR;
AzureIoTClient 6:641a9672db08 253 indicate_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 254 break;
AzureIoTClient 6:641a9672db08 255 }
Azure.IoT Build 0:6ae2f7bca550 256 }
Azure.IoT Build 0:6ae2f7bca550 257
Azure.IoT Build 0:6ae2f7bca550 258 static const char* get_frame_type_as_string(AMQP_VALUE descriptor)
Azure.IoT Build 0:6ae2f7bca550 259 {
AzureIoTClient 6:641a9672db08 260 const char* result;
Azure.IoT Build 0:6ae2f7bca550 261
AzureIoTClient 6:641a9672db08 262 if (is_sasl_mechanisms_type_by_descriptor(descriptor))
AzureIoTClient 6:641a9672db08 263 {
AzureIoTClient 6:641a9672db08 264 result = "[SASL MECHANISMS]";
AzureIoTClient 6:641a9672db08 265 }
AzureIoTClient 6:641a9672db08 266 else if (is_sasl_init_type_by_descriptor(descriptor))
AzureIoTClient 6:641a9672db08 267 {
AzureIoTClient 6:641a9672db08 268 result = "[SASL INIT]";
AzureIoTClient 6:641a9672db08 269 }
AzureIoTClient 6:641a9672db08 270 else if (is_sasl_challenge_type_by_descriptor(descriptor))
AzureIoTClient 6:641a9672db08 271 {
AzureIoTClient 6:641a9672db08 272 result = "[SASL CHALLENGE]";
AzureIoTClient 6:641a9672db08 273 }
AzureIoTClient 6:641a9672db08 274 else if (is_sasl_response_type_by_descriptor(descriptor))
AzureIoTClient 6:641a9672db08 275 {
AzureIoTClient 6:641a9672db08 276 result = "[SASL RESPONSE]";
AzureIoTClient 6:641a9672db08 277 }
AzureIoTClient 6:641a9672db08 278 else if (is_sasl_outcome_type_by_descriptor(descriptor))
AzureIoTClient 6:641a9672db08 279 {
AzureIoTClient 6:641a9672db08 280 result = "[SASL OUTCOME]";
AzureIoTClient 6:641a9672db08 281 }
AzureIoTClient 6:641a9672db08 282 else
AzureIoTClient 6:641a9672db08 283 {
AzureIoTClient 6:641a9672db08 284 result = "[Unknown]";
AzureIoTClient 6:641a9672db08 285 }
Azure.IoT Build 0:6ae2f7bca550 286
AzureIoTClient 6:641a9672db08 287 return result;
Azure.IoT Build 0:6ae2f7bca550 288 }
Azure.IoT Build 0:6ae2f7bca550 289
AzureIoTClient 6:641a9672db08 290 static void log_incoming_frame(AMQP_VALUE performative)
Azure.IoT Build 0:6ae2f7bca550 291 {
AzureIoTClient 9:c22db038556c 292 #ifdef NO_LOGGING
AzureIoTClient 9:c22db038556c 293 UNUSED(performative);
AzureIoTClient 9:c22db038556c 294 #else
AzureIoTClient 6:641a9672db08 295 if (xlogging_get_log_function() != NULL)
AzureIoTClient 6:641a9672db08 296 {
AzureIoTClient 6:641a9672db08 297 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
AzureIoTClient 6:641a9672db08 298 if (descriptor != NULL)
AzureIoTClient 6:641a9672db08 299 {
AzureIoTClient 28:add19eb7defa 300 char* performative_as_string;
AzureIoTClient 16:22a72cf8e416 301 LOG(AZ_LOG_TRACE, 0, "<- ");
AzureIoTClient 16:22a72cf8e416 302 LOG(AZ_LOG_TRACE, 0, (char*)get_frame_type_as_string(descriptor));
AzureIoTClient 25:1101516ee67d 303 performative_as_string = NULL;
AzureIoTClient 16:22a72cf8e416 304 LOG(AZ_LOG_TRACE, LOG_LINE, (performative_as_string = amqpvalue_to_string(performative)));
AzureIoTClient 6:641a9672db08 305 if (performative_as_string != NULL)
AzureIoTClient 6:641a9672db08 306 {
AzureIoTClient 21:f9c433d8e6ca 307 free(performative_as_string);
AzureIoTClient 6:641a9672db08 308 }
AzureIoTClient 6:641a9672db08 309 }
AzureIoTClient 6:641a9672db08 310 }
AzureIoTClient 9:c22db038556c 311 #endif
Azure.IoT Build 0:6ae2f7bca550 312 }
Azure.IoT Build 0:6ae2f7bca550 313
AzureIoTClient 6:641a9672db08 314 static void log_outgoing_frame(AMQP_VALUE performative)
Azure.IoT Build 0:6ae2f7bca550 315 {
AzureIoTClient 9:c22db038556c 316 #ifdef NO_LOGGING
AzureIoTClient 9:c22db038556c 317 UNUSED(performative);
AzureIoTClient 9:c22db038556c 318 #else
AzureIoTClient 6:641a9672db08 319 if (xlogging_get_log_function() != NULL)
AzureIoTClient 6:641a9672db08 320 {
AzureIoTClient 6:641a9672db08 321 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(performative);
AzureIoTClient 6:641a9672db08 322 if (descriptor != NULL)
AzureIoTClient 6:641a9672db08 323 {
AzureIoTClient 28:add19eb7defa 324 char* performative_as_string;
AzureIoTClient 16:22a72cf8e416 325 LOG(AZ_LOG_TRACE, 0, "-> ");
AzureIoTClient 16:22a72cf8e416 326 LOG(AZ_LOG_TRACE, 0, (char*)get_frame_type_as_string(descriptor));
AzureIoTClient 25:1101516ee67d 327 performative_as_string = NULL;
AzureIoTClient 16:22a72cf8e416 328 LOG(AZ_LOG_TRACE, LOG_LINE, (performative_as_string = amqpvalue_to_string(performative)));
AzureIoTClient 6:641a9672db08 329 if (performative_as_string != NULL)
AzureIoTClient 6:641a9672db08 330 {
AzureIoTClient 21:f9c433d8e6ca 331 free(performative_as_string);
AzureIoTClient 6:641a9672db08 332 }
AzureIoTClient 6:641a9672db08 333 }
AzureIoTClient 6:641a9672db08 334 }
AzureIoTClient 9:c22db038556c 335 #endif
Azure.IoT Build 0:6ae2f7bca550 336 }
Azure.IoT Build 0:6ae2f7bca550 337
Azure.IoT Build 0:6ae2f7bca550 338 static int saslclientio_receive_byte(SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance, unsigned char b)
Azure.IoT Build 0:6ae2f7bca550 339 {
AzureIoTClient 6:641a9672db08 340 int result;
Azure.IoT Build 0:6ae2f7bca550 341
AzureIoTClient 6:641a9672db08 342 switch (sasl_client_io_instance->sasl_header_exchange_state)
AzureIoTClient 6:641a9672db08 343 {
AzureIoTClient 6:641a9672db08 344 default:
AzureIoTClient 23:1111ee8bcba4 345 LogError("Byte being received in unexpected state: %s", ENUM_TO_STRING(SASL_HEADER_EXCHANGE_STATE, sasl_client_io_instance->sasl_header_exchange_state));
AzureIoTClient 19:000ab4e6a2c1 346 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 347 break;
Azure.IoT Build 0:6ae2f7bca550 348
AzureIoTClient 6:641a9672db08 349 case SASL_HEADER_EXCHANGE_HEADER_EXCH:
AzureIoTClient 6:641a9672db08 350 switch (sasl_client_io_instance->sasl_client_negotiation_state)
AzureIoTClient 6:641a9672db08 351 {
AzureIoTClient 6:641a9672db08 352 case SASL_CLIENT_NEGOTIATION_ERROR:
AzureIoTClient 23:1111ee8bcba4 353 LogError("Byte being received in unexpected state: %s", ENUM_TO_STRING(SASL_CLIENT_NEGOTIATION_STATE, SASL_CLIENT_NEGOTIATION_ERROR));
AzureIoTClient 19:000ab4e6a2c1 354 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 355 break;
Azure.IoT Build 0:6ae2f7bca550 356
AzureIoTClient 6:641a9672db08 357 default:
AzureIoTClient 30:0407b2db334c 358 /* Codes_SRS_SASLCLIENTIO_01_068: [During the SASL frame exchange that constitutes the handshake the received bytes from the underlying IO shall be fed to the frame codec instance created in `saslclientio_create` by calling `frame_codec_receive_bytes`.]*/
AzureIoTClient 6:641a9672db08 359 if (frame_codec_receive_bytes(sasl_client_io_instance->frame_codec, &b, 1) != 0)
AzureIoTClient 6:641a9672db08 360 {
AzureIoTClient 30:0407b2db334c 361 /* Codes_SRS_SASLCLIENTIO_01_088: [If `frame_codec_receive_bytes` fails, the `on_io_error` callback shall be triggered.]*/
AzureIoTClient 19:000ab4e6a2c1 362 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 363 }
AzureIoTClient 6:641a9672db08 364 else
AzureIoTClient 6:641a9672db08 365 {
AzureIoTClient 6:641a9672db08 366 result = 0;
AzureIoTClient 6:641a9672db08 367 }
Azure.IoT Build 0:6ae2f7bca550 368
AzureIoTClient 6:641a9672db08 369 break;
Azure.IoT Build 0:6ae2f7bca550 370
AzureIoTClient 6:641a9672db08 371 case SASL_CLIENT_NEGOTIATION_OUTCOME_RCVD:
AzureIoTClient 6:641a9672db08 372 sasl_client_io_instance->on_bytes_received(sasl_client_io_instance->on_bytes_received_context, &b, 1);
AzureIoTClient 6:641a9672db08 373 result = 0;
AzureIoTClient 6:641a9672db08 374 break;
AzureIoTClient 6:641a9672db08 375 }
Azure.IoT Build 0:6ae2f7bca550 376
AzureIoTClient 6:641a9672db08 377 break;
Azure.IoT Build 0:6ae2f7bca550 378
AzureIoTClient 6:641a9672db08 379 /* Codes_SRS_SASLCLIENTIO_01_003: [Other than using a protocol id of three, the exchange of SASL layer headers follows the same rules specified in the version negotiation section of the transport specification (See Part 2: section 2.2).] */
AzureIoTClient 6:641a9672db08 380 case SASL_HEADER_EXCHANGE_IDLE:
AzureIoTClient 6:641a9672db08 381 case SASL_HEADER_EXCHANGE_HEADER_SENT:
AzureIoTClient 6:641a9672db08 382 if (b != sasl_header[sasl_client_io_instance->header_bytes_received])
AzureIoTClient 6:641a9672db08 383 {
AzureIoTClient 23:1111ee8bcba4 384 LogError("Mismatched SASL header");
AzureIoTClient 19:000ab4e6a2c1 385 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 386 }
AzureIoTClient 6:641a9672db08 387 else
AzureIoTClient 6:641a9672db08 388 {
AzureIoTClient 6:641a9672db08 389 sasl_client_io_instance->header_bytes_received++;
AzureIoTClient 6:641a9672db08 390 if (sasl_client_io_instance->header_bytes_received == sizeof(sasl_header))
AzureIoTClient 6:641a9672db08 391 {
AzureIoTClient 30:0407b2db334c 392 if (sasl_client_io_instance->is_trace_on != 0)
AzureIoTClient 6:641a9672db08 393 {
AzureIoTClient 16:22a72cf8e416 394 LOG(AZ_LOG_TRACE, LOG_LINE, "<- Header (AMQP 3.1.0.0)");
AzureIoTClient 6:641a9672db08 395 }
Azure.IoT Build 0:6ae2f7bca550 396
AzureIoTClient 6:641a9672db08 397 switch (sasl_client_io_instance->sasl_header_exchange_state)
AzureIoTClient 6:641a9672db08 398 {
AzureIoTClient 6:641a9672db08 399 default:
AzureIoTClient 23:1111ee8bcba4 400 LogError("Invalid SASL header exchange state: %s", ENUM_TO_STRING(SASL_HEADER_EXCHANGE_STATE, sasl_client_io_instance->sasl_header_exchange_state));
AzureIoTClient 19:000ab4e6a2c1 401 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 402 break;
AzureIoTClient 6:641a9672db08 403
AzureIoTClient 6:641a9672db08 404 case SASL_HEADER_EXCHANGE_HEADER_SENT:
AzureIoTClient 6:641a9672db08 405 /* from this point on we need to decode SASL frames */
AzureIoTClient 6:641a9672db08 406 sasl_client_io_instance->sasl_header_exchange_state = SASL_HEADER_EXCHANGE_HEADER_EXCH;
AzureIoTClient 6:641a9672db08 407 result = 0;
AzureIoTClient 6:641a9672db08 408 break;
Azure.IoT Build 0:6ae2f7bca550 409
AzureIoTClient 6:641a9672db08 410 case SASL_HEADER_EXCHANGE_IDLE:
AzureIoTClient 6:641a9672db08 411 sasl_client_io_instance->sasl_header_exchange_state = SASL_HEADER_EXCHANGE_HEADER_RCVD;
AzureIoTClient 6:641a9672db08 412 if (send_sasl_header(sasl_client_io_instance) != 0)
AzureIoTClient 6:641a9672db08 413 {
AzureIoTClient 30:0407b2db334c 414 /* Codes_SRS_SASLCLIENTIO_01_077: [If sending the SASL header fails, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 415 LogError("Could not send SASL header");
AzureIoTClient 19:000ab4e6a2c1 416 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 417 }
AzureIoTClient 6:641a9672db08 418 else
AzureIoTClient 6:641a9672db08 419 {
AzureIoTClient 6:641a9672db08 420 result = 0;
AzureIoTClient 6:641a9672db08 421 }
Azure.IoT Build 0:6ae2f7bca550 422
AzureIoTClient 6:641a9672db08 423 break;
AzureIoTClient 6:641a9672db08 424 }
AzureIoTClient 6:641a9672db08 425 }
AzureIoTClient 6:641a9672db08 426 else
AzureIoTClient 6:641a9672db08 427 {
AzureIoTClient 6:641a9672db08 428 result = 0;
AzureIoTClient 6:641a9672db08 429 }
AzureIoTClient 6:641a9672db08 430 }
Azure.IoT Build 0:6ae2f7bca550 431
AzureIoTClient 6:641a9672db08 432 break;
AzureIoTClient 6:641a9672db08 433 }
AzureIoTClient 6:641a9672db08 434
AzureIoTClient 6:641a9672db08 435 return result;
Azure.IoT Build 0:6ae2f7bca550 436 }
Azure.IoT Build 0:6ae2f7bca550 437
Azure.IoT Build 0:6ae2f7bca550 438 static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
Azure.IoT Build 0:6ae2f7bca550 439 {
AzureIoTClient 6:641a9672db08 440 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 441
AzureIoTClient 30:0407b2db334c 442 /* Codes_SRS_SASLCLIENTIO_01_028: [If `buffer` is NULL or `size` is zero, nothing should be indicated as received, the state shall be switched to ERROR and the `on_io_error` callback shall be triggered.]*/
AzureIoTClient 6:641a9672db08 443 if ((buffer == NULL) ||
AzureIoTClient 6:641a9672db08 444 (size == 0))
AzureIoTClient 6:641a9672db08 445 {
AzureIoTClient 23:1111ee8bcba4 446 LogError("Bad buffer received from the underlying IO, buffer = %p, size = %u",
AzureIoTClient 23:1111ee8bcba4 447 buffer, (unsigned int)size);
AzureIoTClient 6:641a9672db08 448 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 449 }
AzureIoTClient 6:641a9672db08 450 else
AzureIoTClient 6:641a9672db08 451 {
AzureIoTClient 6:641a9672db08 452 switch (sasl_client_io_instance->io_state)
AzureIoTClient 6:641a9672db08 453 {
AzureIoTClient 6:641a9672db08 454 default:
AzureIoTClient 6:641a9672db08 455 break;
Azure.IoT Build 0:6ae2f7bca550 456
AzureIoTClient 6:641a9672db08 457 case IO_STATE_OPEN:
AzureIoTClient 30:0407b2db334c 458 /* Codes_SRS_SASLCLIENTIO_01_027: [When the `on_underlying_io_bytes_received` callback passed to the underlying IO is called and the SASL client IO state is `IO_STATE_OPEN`, the bytes shall be indicated to the user of SASL client IO by calling the `on_bytes_received` callback that was passed in `saslclientio_open`.]*/
AzureIoTClient 30:0407b2db334c 459 /* Codes_SRS_SASLCLIENTIO_01_029: [The `context` argument for `on_io_error` shall be set to the `on_io_error_context` passed in `saslclientio_open`.]*/
AzureIoTClient 6:641a9672db08 460 sasl_client_io_instance->on_bytes_received(sasl_client_io_instance->on_bytes_received_context, buffer, size);
AzureIoTClient 6:641a9672db08 461 break;
Azure.IoT Build 0:6ae2f7bca550 462
AzureIoTClient 6:641a9672db08 463 case IO_STATE_SASL_HANDSHAKE:
AzureIoTClient 6:641a9672db08 464 {
AzureIoTClient 6:641a9672db08 465 size_t i;
Azure.IoT Build 0:6ae2f7bca550 466
AzureIoTClient 30:0407b2db334c 467 /* Codes_SRS_SASLCLIENTIO_01_030: [If bytes are received when the SASL client IO state is `IO_STATE_OPENING`, the bytes shall be consumed by the SASL client IO to satisfy the SASL handshake.]*/
AzureIoTClient 6:641a9672db08 468 for (i = 0; i < size; i++)
AzureIoTClient 6:641a9672db08 469 {
AzureIoTClient 6:641a9672db08 470 if (saslclientio_receive_byte(sasl_client_io_instance, buffer[i]) != 0)
AzureIoTClient 6:641a9672db08 471 {
AzureIoTClient 6:641a9672db08 472 break;
AzureIoTClient 6:641a9672db08 473 }
AzureIoTClient 6:641a9672db08 474 }
Azure.IoT Build 0:6ae2f7bca550 475
AzureIoTClient 6:641a9672db08 476 if (i < size)
AzureIoTClient 6:641a9672db08 477 {
AzureIoTClient 30:0407b2db334c 478 /* Codes_SRS_SASLCLIENTIO_01_073: [If the handshake fails (i.e. the outcome is an error) the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 6:641a9672db08 479 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 480 }
Azure.IoT Build 0:6ae2f7bca550 481
AzureIoTClient 6:641a9672db08 482 break;
AzureIoTClient 6:641a9672db08 483 }
Azure.IoT Build 0:6ae2f7bca550 484
AzureIoTClient 6:641a9672db08 485 case IO_STATE_ERROR:
AzureIoTClient 30:0407b2db334c 486 /* Codes_SRS_SASLCLIENTIO_01_031: [If bytes are received when the SASL client IO state is `IO_STATE_ERROR`, SASL client IO shall do nothing.]*/
AzureIoTClient 6:641a9672db08 487 break;
AzureIoTClient 6:641a9672db08 488 }
AzureIoTClient 6:641a9672db08 489 }
Azure.IoT Build 0:6ae2f7bca550 490 }
Azure.IoT Build 0:6ae2f7bca550 491
Azure.IoT Build 0:6ae2f7bca550 492 static void on_bytes_encoded(void* context, const unsigned char* bytes, size_t length, bool encode_complete)
Azure.IoT Build 0:6ae2f7bca550 493 {
AzureIoTClient 25:1101516ee67d 494 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 495
AzureIoTClient 25:1101516ee67d 496 (void)encode_complete;
Azure.IoT Build 0:6ae2f7bca550 497
AzureIoTClient 30:0407b2db334c 498 /* Codes_SRS_SASLCLIENTIO_01_120: [When SASL client IO is notified by `sasl_frame_codec` of bytes that have been encoded via the `on_bytes_encoded` callback and SASL client IO is in the state OPENING, SASL client IO shall send these bytes by using `xio_send`.]*/
AzureIoTClient 38:7631b92cc772 499 if (xio_send(sasl_client_io_instance->underlying_io, bytes, length, unchecked_on_send_complete, NULL) != 0)
AzureIoTClient 6:641a9672db08 500 {
AzureIoTClient 30:0407b2db334c 501 /* Codes_SRS_SASLCLIENTIO_01_121: [If `xio_send` fails, the `on_io_error` callback shall be triggered.]*/
AzureIoTClient 23:1111ee8bcba4 502 LogError("xio_send failed");
AzureIoTClient 6:641a9672db08 503 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 504 }
Azure.IoT Build 0:6ae2f7bca550 505 }
Azure.IoT Build 0:6ae2f7bca550 506
Azure.IoT Build 0:6ae2f7bca550 507 static int send_sasl_init(SASL_CLIENT_IO_INSTANCE* sasl_client_io, const char* sasl_mechanism_name)
Azure.IoT Build 0:6ae2f7bca550 508 {
AzureIoTClient 6:641a9672db08 509 int result;
Azure.IoT Build 0:6ae2f7bca550 510
AzureIoTClient 6:641a9672db08 511 SASL_INIT_HANDLE sasl_init;
AzureIoTClient 6:641a9672db08 512 SASL_MECHANISM_BYTES init_bytes;
Azure.IoT Build 0:6ae2f7bca550 513
AzureIoTClient 30:0407b2db334c 514 init_bytes.length = 0;
AzureIoTClient 30:0407b2db334c 515 init_bytes.bytes = NULL;
AzureIoTClient 30:0407b2db334c 516
AzureIoTClient 6:641a9672db08 517 /* Codes_SRS_SASLCLIENTIO_01_045: [The name of the SASL mechanism used for the SASL exchange.] */
AzureIoTClient 6:641a9672db08 518 sasl_init = sasl_init_create(sasl_mechanism_name);
AzureIoTClient 6:641a9672db08 519 if (sasl_init == NULL)
AzureIoTClient 6:641a9672db08 520 {
AzureIoTClient 30:0407b2db334c 521 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 522 LogError("Could not create sasl_init");
AzureIoTClient 19:000ab4e6a2c1 523 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 524 }
AzureIoTClient 6:641a9672db08 525 else
AzureIoTClient 6:641a9672db08 526 {
AzureIoTClient 6:641a9672db08 527 /* Codes_SRS_SASLCLIENTIO_01_048: [The contents of this data are defined by the SASL security mechanism.] */
AzureIoTClient 6:641a9672db08 528 if (saslmechanism_get_init_bytes(sasl_client_io->sasl_mechanism, &init_bytes) != 0)
AzureIoTClient 6:641a9672db08 529 {
AzureIoTClient 30:0407b2db334c 530 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 531 LogError("Could not get SASL init bytes");
AzureIoTClient 19:000ab4e6a2c1 532 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 533 }
AzureIoTClient 6:641a9672db08 534 else
AzureIoTClient 6:641a9672db08 535 {
AzureIoTClient 6:641a9672db08 536 amqp_binary creds;
AzureIoTClient 6:641a9672db08 537 creds.bytes = init_bytes.bytes;
AzureIoTClient 6:641a9672db08 538 creds.length = init_bytes.length;
AzureIoTClient 6:641a9672db08 539 if ((init_bytes.length > 0) &&
AzureIoTClient 6:641a9672db08 540 /* Codes_SRS_SASLCLIENTIO_01_047: [A block of opaque data passed to the security mechanism.] */
AzureIoTClient 6:641a9672db08 541 (sasl_init_set_initial_response(sasl_init, creds) != 0))
AzureIoTClient 6:641a9672db08 542 {
AzureIoTClient 30:0407b2db334c 543 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 544 LogError("Could not set initial response");
AzureIoTClient 19:000ab4e6a2c1 545 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 546 }
AzureIoTClient 6:641a9672db08 547 else
AzureIoTClient 6:641a9672db08 548 {
AzureIoTClient 6:641a9672db08 549 AMQP_VALUE sasl_init_value = amqpvalue_create_sasl_init(sasl_init);
AzureIoTClient 6:641a9672db08 550 if (sasl_init_value == NULL)
AzureIoTClient 6:641a9672db08 551 {
AzureIoTClient 30:0407b2db334c 552 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 553 LogError("Could not create SASL init");
AzureIoTClient 19:000ab4e6a2c1 554 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 555 }
AzureIoTClient 6:641a9672db08 556 else
AzureIoTClient 6:641a9672db08 557 {
AzureIoTClient 30:0407b2db334c 558 /* Codes_SRS_SASLCLIENTIO_01_070: [When a frame needs to be sent as part of the SASL handshake frame exchange, the send shall be done by calling `sasl_frame_codec_encode_frame`.]*/
AzureIoTClient 6:641a9672db08 559 if (sasl_frame_codec_encode_frame(sasl_client_io->sasl_frame_codec, sasl_init_value, on_bytes_encoded, sasl_client_io) != 0)
AzureIoTClient 6:641a9672db08 560 {
AzureIoTClient 30:0407b2db334c 561 /* Codes_SRS_SASLCLIENTIO_01_071: [If `sasl_frame_codec_encode_frame` fails, then the `on_io_error` callback shall be triggered.]*/
AzureIoTClient 23:1111ee8bcba4 562 LogError("Could not encode SASL init value");
AzureIoTClient 19:000ab4e6a2c1 563 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 564 }
AzureIoTClient 6:641a9672db08 565 else
AzureIoTClient 6:641a9672db08 566 {
AzureIoTClient 30:0407b2db334c 567 if (sasl_client_io->is_trace_on != 0)
AzureIoTClient 6:641a9672db08 568 {
AzureIoTClient 6:641a9672db08 569 log_outgoing_frame(sasl_init_value);
AzureIoTClient 6:641a9672db08 570 }
Azure.IoT Build 0:6ae2f7bca550 571
AzureIoTClient 6:641a9672db08 572 result = 0;
AzureIoTClient 6:641a9672db08 573 }
Azure.IoT Build 0:6ae2f7bca550 574
AzureIoTClient 6:641a9672db08 575 amqpvalue_destroy(sasl_init_value);
AzureIoTClient 6:641a9672db08 576 }
AzureIoTClient 6:641a9672db08 577 }
AzureIoTClient 6:641a9672db08 578 }
Azure.IoT Build 0:6ae2f7bca550 579
AzureIoTClient 6:641a9672db08 580 sasl_init_destroy(sasl_init);
AzureIoTClient 6:641a9672db08 581 }
Azure.IoT Build 0:6ae2f7bca550 582
AzureIoTClient 6:641a9672db08 583 return result;
Azure.IoT Build 0:6ae2f7bca550 584 }
Azure.IoT Build 0:6ae2f7bca550 585
Azure.IoT Build 0:6ae2f7bca550 586 static int send_sasl_response(SASL_CLIENT_IO_INSTANCE* sasl_client_io, SASL_MECHANISM_BYTES sasl_response)
Azure.IoT Build 0:6ae2f7bca550 587 {
AzureIoTClient 6:641a9672db08 588 int result;
Azure.IoT Build 0:6ae2f7bca550 589
AzureIoTClient 6:641a9672db08 590 SASL_RESPONSE_HANDLE sasl_response_handle;
AzureIoTClient 6:641a9672db08 591 amqp_binary response_binary_value;
AzureIoTClient 6:641a9672db08 592
AzureIoTClient 6:641a9672db08 593 response_binary_value.bytes = sasl_response.bytes;
AzureIoTClient 6:641a9672db08 594 response_binary_value.length = sasl_response.length;
Azure.IoT Build 0:6ae2f7bca550 595
AzureIoTClient 6:641a9672db08 596 /* Codes_SRS_SASLCLIENTIO_01_055: [Send the SASL response data as defined by the SASL specification.] */
AzureIoTClient 6:641a9672db08 597 /* Codes_SRS_SASLCLIENTIO_01_056: [A block of opaque data passed to the security mechanism.] */
AzureIoTClient 6:641a9672db08 598 if ((sasl_response_handle = sasl_response_create(response_binary_value)) == NULL)
AzureIoTClient 6:641a9672db08 599 {
AzureIoTClient 23:1111ee8bcba4 600 LogError("Could not create SASL response");
AzureIoTClient 19:000ab4e6a2c1 601 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 602 }
AzureIoTClient 6:641a9672db08 603 else
AzureIoTClient 6:641a9672db08 604 {
AzureIoTClient 6:641a9672db08 605 AMQP_VALUE sasl_response_value = amqpvalue_create_sasl_response(sasl_response_handle);
AzureIoTClient 6:641a9672db08 606 if (sasl_response_value == NULL)
AzureIoTClient 6:641a9672db08 607 {
AzureIoTClient 23:1111ee8bcba4 608 LogError("Could not create SASL response AMQP value");
AzureIoTClient 19:000ab4e6a2c1 609 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 610 }
AzureIoTClient 6:641a9672db08 611 else
AzureIoTClient 6:641a9672db08 612 {
AzureIoTClient 30:0407b2db334c 613 /* Codes_SRS_SASLCLIENTIO_01_070: [When a frame needs to be sent as part of the SASL handshake frame exchange, the send shall be done by calling `sasl_frame_codec_encode_frame`.]*/
AzureIoTClient 6:641a9672db08 614 if (sasl_frame_codec_encode_frame(sasl_client_io->sasl_frame_codec, sasl_response_value, on_bytes_encoded, sasl_client_io) != 0)
AzureIoTClient 6:641a9672db08 615 {
AzureIoTClient 23:1111ee8bcba4 616 LogError("Could not encode SASL response in the frame");
AzureIoTClient 19:000ab4e6a2c1 617 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 618 }
AzureIoTClient 6:641a9672db08 619 else
AzureIoTClient 6:641a9672db08 620 {
AzureIoTClient 30:0407b2db334c 621 if (sasl_client_io->is_trace_on != 0)
AzureIoTClient 6:641a9672db08 622 {
AzureIoTClient 6:641a9672db08 623 log_outgoing_frame(sasl_response_value);
AzureIoTClient 6:641a9672db08 624 }
AzureIoTClient 23:1111ee8bcba4 625
AzureIoTClient 6:641a9672db08 626 result = 0;
AzureIoTClient 6:641a9672db08 627 }
Azure.IoT Build 0:6ae2f7bca550 628
AzureIoTClient 6:641a9672db08 629 amqpvalue_destroy(sasl_response_value);
AzureIoTClient 6:641a9672db08 630 }
Azure.IoT Build 0:6ae2f7bca550 631
AzureIoTClient 6:641a9672db08 632 sasl_response_destroy(sasl_response_handle);
AzureIoTClient 6:641a9672db08 633 }
Azure.IoT Build 0:6ae2f7bca550 634
AzureIoTClient 6:641a9672db08 635 return result;
Azure.IoT Build 0:6ae2f7bca550 636 }
Azure.IoT Build 0:6ae2f7bca550 637
AzureIoTClient 30:0407b2db334c 638 static void on_sasl_frame_received_callback(void* context, AMQP_VALUE sasl_frame)
Azure.IoT Build 0:6ae2f7bca550 639 {
AzureIoTClient 6:641a9672db08 640 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 641
AzureIoTClient 6:641a9672db08 642 /* Codes_SRS_SASLCLIENTIO_01_067: [The SASL frame exchange shall be started as soon as the SASL header handshake is done.] */
AzureIoTClient 6:641a9672db08 643 switch (sasl_client_io_instance->io_state)
AzureIoTClient 6:641a9672db08 644 {
AzureIoTClient 6:641a9672db08 645 default:
AzureIoTClient 23:1111ee8bcba4 646 LogError("SASL frame received while in state %d", (int)sasl_client_io_instance->io_state);
AzureIoTClient 6:641a9672db08 647 break;
Azure.IoT Build 0:6ae2f7bca550 648
AzureIoTClient 6:641a9672db08 649 case IO_STATE_OPEN:
AzureIoTClient 6:641a9672db08 650 case IO_STATE_OPENING_UNDERLYING_IO:
AzureIoTClient 6:641a9672db08 651 case IO_STATE_CLOSING:
AzureIoTClient 30:0407b2db334c 652 /* Codes_SRS_SASLCLIENTIO_01_117: [If `on_sasl_frame_received_callback` is called when the state of the IO is OPEN then the `on_io_error` callback shall be triggered.]*/
AzureIoTClient 6:641a9672db08 653 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 654 break;
Azure.IoT Build 0:6ae2f7bca550 655
AzureIoTClient 6:641a9672db08 656 case IO_STATE_SASL_HANDSHAKE:
AzureIoTClient 6:641a9672db08 657 if (sasl_client_io_instance->sasl_header_exchange_state != SASL_HEADER_EXCHANGE_HEADER_EXCH)
AzureIoTClient 6:641a9672db08 658 {
AzureIoTClient 30:0407b2db334c 659 /* Codes_SRS_SASLCLIENTIO_01_118: [If `on_sasl_frame_received_callback` is called in the OPENING state but the header exchange has not yet been completed, then the `on_io_error` callback shall be triggered.]*/
AzureIoTClient 6:641a9672db08 660 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 661 }
AzureIoTClient 6:641a9672db08 662 else
AzureIoTClient 6:641a9672db08 663 {
AzureIoTClient 6:641a9672db08 664 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(sasl_frame);
AzureIoTClient 6:641a9672db08 665 if (descriptor == NULL)
AzureIoTClient 6:641a9672db08 666 {
AzureIoTClient 30:0407b2db334c 667 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 668 LogError("Could not obtain SASL frame descriptor");
AzureIoTClient 6:641a9672db08 669 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 670 }
AzureIoTClient 6:641a9672db08 671 else
AzureIoTClient 6:641a9672db08 672 {
AzureIoTClient 30:0407b2db334c 673 if (sasl_client_io_instance->is_trace_on != 0)
AzureIoTClient 6:641a9672db08 674 {
AzureIoTClient 6:641a9672db08 675 log_incoming_frame(sasl_frame);
AzureIoTClient 6:641a9672db08 676 }
Azure.IoT Build 0:6ae2f7bca550 677
AzureIoTClient 6:641a9672db08 678 /* Codes_SRS_SASLCLIENTIO_01_032: [The peer acting as the SASL server MUST announce supported authentication mechanisms using the sasl-mechanisms frame.] */
AzureIoTClient 6:641a9672db08 679 /* Codes_SRS_SASLCLIENTIO_01_040: [The peer playing the role of the SASL client and the peer playing the role of the SASL server MUST correspond to the TCP client and server respectively.] */
AzureIoTClient 6:641a9672db08 680 /* Codes_SRS_SASLCLIENTIO_01_034: [<-- SASL-MECHANISMS] */
AzureIoTClient 6:641a9672db08 681 if (is_sasl_mechanisms_type_by_descriptor(descriptor))
AzureIoTClient 6:641a9672db08 682 {
AzureIoTClient 6:641a9672db08 683 switch (sasl_client_io_instance->sasl_client_negotiation_state)
AzureIoTClient 6:641a9672db08 684 {
AzureIoTClient 17:923575db8b2d 685 default:
AzureIoTClient 23:1111ee8bcba4 686 LogError("SASL mechanisms frame received in %s state", ENUM_TO_STRING(SASL_CLIENT_NEGOTIATION_STATE, sasl_client_io_instance->sasl_client_negotiation_state));
AzureIoTClient 17:923575db8b2d 687 handle_error(sasl_client_io_instance);
AzureIoTClient 17:923575db8b2d 688 break;
AzureIoTClient 17:923575db8b2d 689
AzureIoTClient 6:641a9672db08 690 case SASL_CLIENT_NEGOTIATION_NOT_STARTED:
AzureIoTClient 6:641a9672db08 691 {
AzureIoTClient 6:641a9672db08 692 SASL_MECHANISMS_HANDLE sasl_mechanisms_handle;
Azure.IoT Build 0:6ae2f7bca550 693
AzureIoTClient 6:641a9672db08 694 if (amqpvalue_get_sasl_mechanisms(sasl_frame, &sasl_mechanisms_handle) != 0)
AzureIoTClient 6:641a9672db08 695 {
AzureIoTClient 30:0407b2db334c 696 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 697 LogError("Could not get SASL mechanisms");
AzureIoTClient 6:641a9672db08 698 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 699 }
AzureIoTClient 6:641a9672db08 700 else
AzureIoTClient 6:641a9672db08 701 {
AzureIoTClient 6:641a9672db08 702 AMQP_VALUE sasl_server_mechanisms;
AzureIoTClient 6:641a9672db08 703 uint32_t mechanisms_count;
Azure.IoT Build 0:6ae2f7bca550 704
AzureIoTClient 6:641a9672db08 705 if ((sasl_mechanisms_get_sasl_server_mechanisms(sasl_mechanisms_handle, &sasl_server_mechanisms) != 0) ||
AzureIoTClient 6:641a9672db08 706 (amqpvalue_get_array_item_count(sasl_server_mechanisms, &mechanisms_count) != 0) ||
AzureIoTClient 6:641a9672db08 707 (mechanisms_count == 0))
AzureIoTClient 6:641a9672db08 708 {
AzureIoTClient 6:641a9672db08 709 /* Codes_SRS_SASLCLIENTIO_01_042: [It is invalid for this list to be null or empty.] */
AzureIoTClient 23:1111ee8bcba4 710 LogError("Invalid SASL mechanisms list");
AzureIoTClient 6:641a9672db08 711 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 712 }
AzureIoTClient 6:641a9672db08 713 else
AzureIoTClient 6:641a9672db08 714 {
AzureIoTClient 6:641a9672db08 715 const char* sasl_mechanism_name = saslmechanism_get_mechanism_name(sasl_client_io_instance->sasl_mechanism);
AzureIoTClient 6:641a9672db08 716 if (sasl_mechanism_name == NULL)
AzureIoTClient 6:641a9672db08 717 {
AzureIoTClient 30:0407b2db334c 718 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 719 LogError("Cannot get the mechanism name");
AzureIoTClient 6:641a9672db08 720 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 721 }
AzureIoTClient 6:641a9672db08 722 else
AzureIoTClient 6:641a9672db08 723 {
AzureIoTClient 6:641a9672db08 724 uint32_t i;
Azure.IoT Build 0:6ae2f7bca550 725
AzureIoTClient 6:641a9672db08 726 for (i = 0; i < mechanisms_count; i++)
AzureIoTClient 6:641a9672db08 727 {
AzureIoTClient 6:641a9672db08 728 AMQP_VALUE sasl_server_mechanism;
AzureIoTClient 6:641a9672db08 729 sasl_server_mechanism = amqpvalue_get_array_item(sasl_server_mechanisms, i);
AzureIoTClient 6:641a9672db08 730 if (sasl_server_mechanism == NULL)
AzureIoTClient 6:641a9672db08 731 {
AzureIoTClient 23:1111ee8bcba4 732 LogError("Cannot get SASL mechanisms array item for index %u", (unsigned int)i);
AzureIoTClient 6:641a9672db08 733 i = mechanisms_count;
AzureIoTClient 6:641a9672db08 734 }
AzureIoTClient 6:641a9672db08 735 else
AzureIoTClient 6:641a9672db08 736 {
AzureIoTClient 6:641a9672db08 737 const char* sasl_server_mechanism_name;
AzureIoTClient 6:641a9672db08 738 if (amqpvalue_get_symbol(sasl_server_mechanism, &sasl_server_mechanism_name) != 0)
AzureIoTClient 6:641a9672db08 739 {
AzureIoTClient 23:1111ee8bcba4 740 LogError("Error getting server SASL mechanism from array item");
AzureIoTClient 6:641a9672db08 741 i = mechanisms_count;
AzureIoTClient 6:641a9672db08 742 }
AzureIoTClient 6:641a9672db08 743 else
AzureIoTClient 6:641a9672db08 744 {
AzureIoTClient 6:641a9672db08 745 if (strcmp(sasl_mechanism_name, sasl_server_mechanism_name) == 0)
AzureIoTClient 6:641a9672db08 746 {
Azure.IoT Build 0:6ae2f7bca550 747 amqpvalue_destroy(sasl_server_mechanism);
Azure.IoT Build 0:6ae2f7bca550 748 break;
AzureIoTClient 6:641a9672db08 749 }
AzureIoTClient 6:641a9672db08 750 }
Azure.IoT Build 0:6ae2f7bca550 751
Azure.IoT Build 0:6ae2f7bca550 752 amqpvalue_destroy(sasl_server_mechanism);
Azure.IoT Build 0:6ae2f7bca550 753 }
AzureIoTClient 6:641a9672db08 754 }
Azure.IoT Build 0:6ae2f7bca550 755
AzureIoTClient 6:641a9672db08 756 if (i == mechanisms_count)
AzureIoTClient 6:641a9672db08 757 {
AzureIoTClient 30:0407b2db334c 758 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 759 LogError("Could not find desired SASL mechanism in the list presented by server");
AzureIoTClient 6:641a9672db08 760 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 761 }
AzureIoTClient 6:641a9672db08 762 else
AzureIoTClient 6:641a9672db08 763 {
AzureIoTClient 6:641a9672db08 764 sasl_client_io_instance->sasl_client_negotiation_state = SASL_CLIENT_NEGOTIATION_MECH_RCVD;
Azure.IoT Build 0:6ae2f7bca550 765
AzureIoTClient 6:641a9672db08 766 /* Codes_SRS_SASLCLIENTIO_01_035: [SASL-INIT -->] */
AzureIoTClient 6:641a9672db08 767 /* Codes_SRS_SASLCLIENTIO_01_033: [The partner MUST then choose one of the supported mechanisms and initiate a sasl exchange.] */
AzureIoTClient 6:641a9672db08 768 /* Codes_SRS_SASLCLIENTIO_01_054: [Selects the sasl mechanism and provides the initial response if needed.] */
AzureIoTClient 6:641a9672db08 769 if (send_sasl_init(sasl_client_io_instance, sasl_mechanism_name) != 0)
AzureIoTClient 6:641a9672db08 770 {
AzureIoTClient 30:0407b2db334c 771 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 772 LogError("Could not send SASL init");
AzureIoTClient 6:641a9672db08 773 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 774 }
AzureIoTClient 6:641a9672db08 775 else
AzureIoTClient 6:641a9672db08 776 {
AzureIoTClient 6:641a9672db08 777 sasl_client_io_instance->sasl_client_negotiation_state = SASL_CLIENT_NEGOTIATION_INIT_SENT;
AzureIoTClient 6:641a9672db08 778 }
AzureIoTClient 6:641a9672db08 779 }
AzureIoTClient 6:641a9672db08 780 }
AzureIoTClient 6:641a9672db08 781 }
Azure.IoT Build 0:6ae2f7bca550 782
AzureIoTClient 6:641a9672db08 783 sasl_mechanisms_destroy(sasl_mechanisms_handle);
AzureIoTClient 6:641a9672db08 784 }
Azure.IoT Build 0:6ae2f7bca550 785
AzureIoTClient 6:641a9672db08 786 break;
AzureIoTClient 6:641a9672db08 787 }
AzureIoTClient 6:641a9672db08 788 }
AzureIoTClient 6:641a9672db08 789 }
AzureIoTClient 6:641a9672db08 790 /* Codes_SRS_SASLCLIENTIO_01_052: [Send the SASL challenge data as defined by the SASL specification.] */
AzureIoTClient 6:641a9672db08 791 /* Codes_SRS_SASLCLIENTIO_01_036: [<-- SASL-CHALLENGE *] */
AzureIoTClient 6:641a9672db08 792 /* Codes_SRS_SASLCLIENTIO_01_039: [the SASL challenge/response step can occur zero or more times depending on the details of the SASL mechanism chosen.] */
AzureIoTClient 6:641a9672db08 793 else if (is_sasl_challenge_type_by_descriptor(descriptor))
AzureIoTClient 6:641a9672db08 794 {
AzureIoTClient 6:641a9672db08 795 /* Codes_SRS_SASLCLIENTIO_01_032: [The peer acting as the SASL server MUST announce supported authentication mechanisms using the sasl-mechanisms frame.] */
AzureIoTClient 6:641a9672db08 796 if ((sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_INIT_SENT) &&
AzureIoTClient 6:641a9672db08 797 (sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_RESPONSE_SENT))
AzureIoTClient 6:641a9672db08 798 {
AzureIoTClient 23:1111ee8bcba4 799 LogError("SASL challenge received in a bad state: %s", ENUM_TO_STRING(SASL_CLIENT_NEGOTIATION_STATE, sasl_client_io_instance->sasl_client_negotiation_state));
AzureIoTClient 6:641a9672db08 800 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 801 }
AzureIoTClient 6:641a9672db08 802 else
AzureIoTClient 6:641a9672db08 803 {
AzureIoTClient 6:641a9672db08 804 SASL_CHALLENGE_HANDLE sasl_challenge_handle;
Azure.IoT Build 0:6ae2f7bca550 805
AzureIoTClient 6:641a9672db08 806 if (amqpvalue_get_sasl_challenge(sasl_frame, &sasl_challenge_handle) != 0)
AzureIoTClient 6:641a9672db08 807 {
AzureIoTClient 30:0407b2db334c 808 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 809 LogError("Cannot get SASL challenge values");
AzureIoTClient 6:641a9672db08 810 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 811 }
AzureIoTClient 6:641a9672db08 812 else
AzureIoTClient 6:641a9672db08 813 {
AzureIoTClient 6:641a9672db08 814 amqp_binary challenge_binary_value;
AzureIoTClient 30:0407b2db334c 815
AzureIoTClient 30:0407b2db334c 816 challenge_binary_value.bytes = NULL;
AzureIoTClient 30:0407b2db334c 817 challenge_binary_value.length = 0;
Azure.IoT Build 0:6ae2f7bca550 818
AzureIoTClient 6:641a9672db08 819 /* Codes_SRS_SASLCLIENTIO_01_053: [Challenge information, a block of opaque binary data passed to the security mechanism.] */
AzureIoTClient 6:641a9672db08 820 if (sasl_challenge_get_challenge(sasl_challenge_handle, &challenge_binary_value) != 0)
AzureIoTClient 6:641a9672db08 821 {
AzureIoTClient 30:0407b2db334c 822 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 823 LogError("Cannot get SASL challenge binary value");
AzureIoTClient 6:641a9672db08 824 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 825 }
AzureIoTClient 6:641a9672db08 826 else
AzureIoTClient 6:641a9672db08 827 {
AzureIoTClient 6:641a9672db08 828 SASL_MECHANISM_BYTES challenge;
AzureIoTClient 30:0407b2db334c 829 SASL_MECHANISM_BYTES response_bytes;
AzureIoTClient 6:641a9672db08 830
AzureIoTClient 6:641a9672db08 831 challenge.bytes = challenge_binary_value.bytes;
AzureIoTClient 6:641a9672db08 832 challenge.length = challenge_binary_value.length;
AzureIoTClient 30:0407b2db334c 833 response_bytes.bytes = NULL;
AzureIoTClient 30:0407b2db334c 834 response_bytes.length = 0;
Azure.IoT Build 0:6ae2f7bca550 835
AzureIoTClient 6:641a9672db08 836 /* Codes_SRS_SASLCLIENTIO_01_057: [The contents of this data are defined by the SASL security mechanism.] */
AzureIoTClient 6:641a9672db08 837 /* Codes_SRS_SASLCLIENTIO_01_037: [SASL-RESPONSE -->] */
AzureIoTClient 23:1111ee8bcba4 838 if (saslmechanism_challenge(sasl_client_io_instance->sasl_mechanism, &challenge, &response_bytes) != 0)
AzureIoTClient 6:641a9672db08 839 {
AzureIoTClient 30:0407b2db334c 840 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 841 LogError("SASL Challenge failed");
AzureIoTClient 23:1111ee8bcba4 842 handle_error(sasl_client_io_instance);
AzureIoTClient 23:1111ee8bcba4 843 }
AzureIoTClient 23:1111ee8bcba4 844 else if (send_sasl_response(sasl_client_io_instance, response_bytes) != 0)
AzureIoTClient 23:1111ee8bcba4 845 {
AzureIoTClient 30:0407b2db334c 846 /* Codes_SRS_SASLCLIENTIO_01_119: [If any error is encountered when parsing the received frame, the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 23:1111ee8bcba4 847 LogError("Cannot send SASL reponse");
AzureIoTClient 6:641a9672db08 848 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 849 }
AzureIoTClient 6:641a9672db08 850 }
Azure.IoT Build 0:6ae2f7bca550 851
AzureIoTClient 6:641a9672db08 852 sasl_challenge_destroy(sasl_challenge_handle);
AzureIoTClient 6:641a9672db08 853 }
AzureIoTClient 6:641a9672db08 854 }
AzureIoTClient 6:641a9672db08 855 }
AzureIoTClient 6:641a9672db08 856 /* Codes_SRS_SASLCLIENTIO_01_058: [This frame indicates the outcome of the SASL dialog.] */
AzureIoTClient 6:641a9672db08 857 /* Codes_SRS_SASLCLIENTIO_01_038: [<-- SASL-OUTCOME] */
AzureIoTClient 6:641a9672db08 858 else if (is_sasl_outcome_type_by_descriptor(descriptor))
AzureIoTClient 6:641a9672db08 859 {
AzureIoTClient 6:641a9672db08 860 /* Codes_SRS_SASLCLIENTIO_01_032: [The peer acting as the SASL server MUST announce supported authentication mechanisms using the sasl-mechanisms frame.] */
AzureIoTClient 6:641a9672db08 861 if ((sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_INIT_SENT) &&
AzureIoTClient 6:641a9672db08 862 (sasl_client_io_instance->sasl_client_negotiation_state != SASL_CLIENT_NEGOTIATION_RESPONSE_SENT))
AzureIoTClient 6:641a9672db08 863 {
AzureIoTClient 23:1111ee8bcba4 864 LogError("SASL outcome received in a bad state: %s", ENUM_TO_STRING(SASL_CLIENT_NEGOTIATION_STATE, sasl_client_io_instance->sasl_client_negotiation_state));
AzureIoTClient 6:641a9672db08 865 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 866 }
AzureIoTClient 6:641a9672db08 867 else
AzureIoTClient 6:641a9672db08 868 {
AzureIoTClient 6:641a9672db08 869 SASL_OUTCOME_HANDLE sasl_outcome;
Azure.IoT Build 0:6ae2f7bca550 870
AzureIoTClient 6:641a9672db08 871 sasl_client_io_instance->sasl_client_negotiation_state = SASL_CLIENT_NEGOTIATION_OUTCOME_RCVD;
Azure.IoT Build 0:6ae2f7bca550 872
AzureIoTClient 6:641a9672db08 873 if (amqpvalue_get_sasl_outcome(sasl_frame, &sasl_outcome) != 0)
AzureIoTClient 6:641a9672db08 874 {
AzureIoTClient 23:1111ee8bcba4 875 LogError("Cannot get SASL outcome");
AzureIoTClient 6:641a9672db08 876 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 877 }
AzureIoTClient 6:641a9672db08 878 else
AzureIoTClient 6:641a9672db08 879 {
AzureIoTClient 6:641a9672db08 880 sasl_code sasl_code;
Azure.IoT Build 0:6ae2f7bca550 881
AzureIoTClient 6:641a9672db08 882 /* Codes_SRS_SASLCLIENTIO_01_060: [A reply-code indicating the outcome of the SASL dialog.] */
AzureIoTClient 6:641a9672db08 883 if (sasl_outcome_get_code(sasl_outcome, &sasl_code) != 0)
AzureIoTClient 6:641a9672db08 884 {
AzureIoTClient 23:1111ee8bcba4 885 LogError("Cannot get SASL outcome code");
AzureIoTClient 6:641a9672db08 886 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 887 }
AzureIoTClient 6:641a9672db08 888 else
AzureIoTClient 6:641a9672db08 889 {
AzureIoTClient 6:641a9672db08 890 switch (sasl_code)
AzureIoTClient 6:641a9672db08 891 {
AzureIoTClient 6:641a9672db08 892 default:
AzureIoTClient 6:641a9672db08 893 case sasl_code_auth:
AzureIoTClient 6:641a9672db08 894 /* Codes_SRS_SASLCLIENTIO_01_063: [1 Connection authentication failed due to an unspecified problem with the supplied credentials.] */
AzureIoTClient 6:641a9672db08 895 case sasl_code_sys:
AzureIoTClient 6:641a9672db08 896 /* Codes_SRS_SASLCLIENTIO_01_064: [2 Connection authentication failed due to a system error.] */
AzureIoTClient 6:641a9672db08 897 case sasl_code_sys_perm:
AzureIoTClient 6:641a9672db08 898 /* Codes_SRS_SASLCLIENTIO_01_065: [3 Connection authentication failed due to a system error that is unlikely to be corrected without intervention.] */
AzureIoTClient 6:641a9672db08 899 case sasl_code_sys_temp:
AzureIoTClient 6:641a9672db08 900 /* Codes_SRS_SASLCLIENTIO_01_066: [4 Connection authentication failed due to a transient system error.] */
AzureIoTClient 23:1111ee8bcba4 901 LogError("SASL handshake failed with code %02X", (unsigned char)sasl_code);
AzureIoTClient 6:641a9672db08 902 handle_error(sasl_client_io_instance);
AzureIoTClient 6:641a9672db08 903 break;
Azure.IoT Build 0:6ae2f7bca550 904
AzureIoTClient 6:641a9672db08 905 case sasl_code_ok:
AzureIoTClient 6:641a9672db08 906 /* Codes_SRS_SASLCLIENTIO_01_059: [Upon successful completion of the SASL dialog the security layer has been established] */
AzureIoTClient 6:641a9672db08 907 /* Codes_SRS_SASLCLIENTIO_01_062: [0 Connection authentication succeeded.] */
AzureIoTClient 6:641a9672db08 908 sasl_client_io_instance->io_state = IO_STATE_OPEN;
AzureIoTClient 30:0407b2db334c 909
AzureIoTClient 30:0407b2db334c 910 /* Codes_SRS_SASLCLIENTIO_01_072: [When the SASL handshake is complete, if the handshake is successful, the SASL client IO state shall be switched to `IO_STATE_OPEN` and the `on_io_open_complete` callback shall be called with `IO_OPEN_OK`.]*/
AzureIoTClient 6:641a9672db08 911 indicate_open_complete(sasl_client_io_instance, IO_OPEN_OK);
AzureIoTClient 6:641a9672db08 912 break;
AzureIoTClient 6:641a9672db08 913 }
AzureIoTClient 6:641a9672db08 914 }
Azure.IoT Build 0:6ae2f7bca550 915
AzureIoTClient 6:641a9672db08 916 sasl_outcome_destroy(sasl_outcome);
AzureIoTClient 6:641a9672db08 917 }
AzureIoTClient 6:641a9672db08 918 }
AzureIoTClient 6:641a9672db08 919 }
AzureIoTClient 6:641a9672db08 920 else
AzureIoTClient 6:641a9672db08 921 {
AzureIoTClient 6:641a9672db08 922 LogError("Bad SASL frame");
AzureIoTClient 6:641a9672db08 923 }
AzureIoTClient 6:641a9672db08 924 }
AzureIoTClient 6:641a9672db08 925 }
AzureIoTClient 6:641a9672db08 926 break;
AzureIoTClient 6:641a9672db08 927 }
Azure.IoT Build 0:6ae2f7bca550 928 }
Azure.IoT Build 0:6ae2f7bca550 929
Azure.IoT Build 0:6ae2f7bca550 930 static void on_frame_codec_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 931 {
AzureIoTClient 6:641a9672db08 932 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 933
AzureIoTClient 30:0407b2db334c 934 /* Codes_SRS_SASLCLIENTIO_01_122: [When `on_frame_codec_error` is called while in the OPENING state the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`.]*/
AzureIoTClient 30:0407b2db334c 935 /* Codes_SRS_SASLCLIENTIO_01_143: [ When `on_frame_codec_error` is called while in the OPEN state the `on_io_error` callback shall be triggered. ]*/
AzureIoTClient 30:0407b2db334c 936 /* Codes_SRS_SASLCLIENTIO_01_123: [When `on_frame_codec_error` is called in the ERROR state nothing shall be done.]*/
AzureIoTClient 23:1111ee8bcba4 937 LogError("Error encoding frame (on_frame_codec_error)");
AzureIoTClient 6:641a9672db08 938 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 939 }
Azure.IoT Build 0:6ae2f7bca550 940
Azure.IoT Build 0:6ae2f7bca550 941 static void on_sasl_frame_codec_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 942 {
AzureIoTClient 6:641a9672db08 943 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 944
AzureIoTClient 30:0407b2db334c 945 /* Codes_SRS_SASLCLIENTIO_01_141: [ When `on_sasl_frame_codec_error` is called while in the OPENING state the `on_io_open_complete` callback shall be triggered with `IO_OPEN_ERROR`. ]*/
AzureIoTClient 30:0407b2db334c 946 /* Codes_SRS_SASLCLIENTIO_01_144: [ When `on_sasl_frame_codec_error` is called while OPEN state the `on_io_error` callback shall be triggered. ]*/
AzureIoTClient 30:0407b2db334c 947 /* Codes_SRS_SASLCLIENTIO_01_142: [ When `on_sasl_frame_codec_error` is called in the ERROR state nothing shall be done. ]*/
AzureIoTClient 23:1111ee8bcba4 948 LogError("Error encoding SASL frame (on_sasl_frame_codec_error)");
AzureIoTClient 6:641a9672db08 949 handle_error(sasl_client_io_instance);
Azure.IoT Build 0:6ae2f7bca550 950 }
Azure.IoT Build 0:6ae2f7bca550 951
Azure.IoT Build 5:ae49385aff34 952 CONCRETE_IO_HANDLE saslclientio_create(void* io_create_parameters)
Azure.IoT Build 0:6ae2f7bca550 953 {
AzureIoTClient 23:1111ee8bcba4 954 SASLCLIENTIO_CONFIG* sasl_client_io_config = (SASLCLIENTIO_CONFIG*)io_create_parameters;
AzureIoTClient 6:641a9672db08 955 SASL_CLIENT_IO_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 956
AzureIoTClient 30:0407b2db334c 957 /* Codes_SRS_SASLCLIENTIO_01_005: [If `io_create_parameters` is NULL, `saslclientio_create` shall fail and return NULL.] */
AzureIoTClient 23:1111ee8bcba4 958 if (sasl_client_io_config == NULL)
AzureIoTClient 23:1111ee8bcba4 959 {
AzureIoTClient 23:1111ee8bcba4 960 LogError("NULL io_create_parameters");
AzureIoTClient 23:1111ee8bcba4 961 result = NULL;
AzureIoTClient 23:1111ee8bcba4 962 }
AzureIoTClient 30:0407b2db334c 963 /* Codes_SRS_SASLCLIENTIO_01_092: [If any of the `sasl_mechanism` or `underlying_io` members of the configuration structure are NULL, `saslclientio_create` shall fail and return NULL.] */
AzureIoTClient 23:1111ee8bcba4 964 else if ((sasl_client_io_config->underlying_io == NULL) ||
AzureIoTClient 6:641a9672db08 965 (sasl_client_io_config->sasl_mechanism == NULL))
AzureIoTClient 6:641a9672db08 966 {
AzureIoTClient 23:1111ee8bcba4 967 LogError("Bad parameters: underlying_io = %p, sasl_mechanism = %p",
AzureIoTClient 23:1111ee8bcba4 968 sasl_client_io_config->underlying_io, sasl_client_io_config->sasl_mechanism);
AzureIoTClient 6:641a9672db08 969 result = NULL;
AzureIoTClient 6:641a9672db08 970 }
AzureIoTClient 6:641a9672db08 971 else
AzureIoTClient 6:641a9672db08 972 {
AzureIoTClient 23:1111ee8bcba4 973 result = (SASL_CLIENT_IO_INSTANCE*)malloc(sizeof(SASL_CLIENT_IO_INSTANCE));
AzureIoTClient 23:1111ee8bcba4 974 if (result == NULL)
AzureIoTClient 23:1111ee8bcba4 975 {
AzureIoTClient 30:0407b2db334c 976 /* Codes_SRS_SASLCLIENTIO_01_006: [If memory cannot be allocated for the new instance, `saslclientio_create` shall fail and return NULL.] */
AzureIoTClient 23:1111ee8bcba4 977 LogError("Cannot allocate sasl client IO instance");
AzureIoTClient 23:1111ee8bcba4 978 }
AzureIoTClient 23:1111ee8bcba4 979 else
AzureIoTClient 6:641a9672db08 980 {
AzureIoTClient 6:641a9672db08 981 result->underlying_io = sasl_client_io_config->underlying_io;
AzureIoTClient 30:0407b2db334c 982 /* Codes_SRS_SASLCLIENTIO_01_089: [`saslclientio_create` shall create a frame codec to be used for encoding/decoding frames by calling `frame_codec_create` and passing `on_frame_codec_error` and a context as arguments.] */
AzureIoTClient 23:1111ee8bcba4 983 result->frame_codec = frame_codec_create(on_frame_codec_error, result);
AzureIoTClient 23:1111ee8bcba4 984 if (result->frame_codec == NULL)
AzureIoTClient 6:641a9672db08 985 {
AzureIoTClient 30:0407b2db334c 986 /* Codes_SRS_SASLCLIENTIO_01_090: [If `frame_codec_create` fails, then `saslclientio_create` shall fail and return NULL.] */
AzureIoTClient 23:1111ee8bcba4 987 LogError("frame_codec_create failed");
AzureIoTClient 21:f9c433d8e6ca 988 free(result);
AzureIoTClient 6:641a9672db08 989 result = NULL;
AzureIoTClient 6:641a9672db08 990 }
AzureIoTClient 6:641a9672db08 991 else
AzureIoTClient 6:641a9672db08 992 {
AzureIoTClient 30:0407b2db334c 993 /* Codes_SRS_SASLCLIENTIO_01_084: [`saslclientio_create` shall create a SASL frame codec to be used for SASL frame encoding/decoding by calling `sasl_frame_codec_create` and passing the just created frame codec as argument.] */
AzureIoTClient 30:0407b2db334c 994 result->sasl_frame_codec = sasl_frame_codec_create(result->frame_codec, on_sasl_frame_received_callback, on_sasl_frame_codec_error, result);
AzureIoTClient 23:1111ee8bcba4 995 if (result->sasl_frame_codec == NULL)
AzureIoTClient 6:641a9672db08 996 {
AzureIoTClient 30:0407b2db334c 997 /* Codes_SRS_SASLCLIENTIO_01_085: [If `sasl_frame_codec_create` fails, then `saslclientio_create` shall fail and return NULL.] */
AzureIoTClient 23:1111ee8bcba4 998 LogError("sasl_frame_codec_create failed");
AzureIoTClient 23:1111ee8bcba4 999 frame_codec_destroy(result->frame_codec);
AzureIoTClient 21:f9c433d8e6ca 1000 free(result);
AzureIoTClient 6:641a9672db08 1001 result = NULL;
AzureIoTClient 6:641a9672db08 1002 }
AzureIoTClient 6:641a9672db08 1003 else
AzureIoTClient 6:641a9672db08 1004 {
AzureIoTClient 30:0407b2db334c 1005 /* Codes_SRS_SASLCLIENTIO_01_004: [`saslclientio_create` shall return on success a non-NULL handle to a new SASL client IO instance.] */
AzureIoTClient 23:1111ee8bcba4 1006 result->on_bytes_received = NULL;
AzureIoTClient 23:1111ee8bcba4 1007 result->on_io_open_complete = NULL;
AzureIoTClient 23:1111ee8bcba4 1008 result->on_io_error = NULL;
AzureIoTClient 23:1111ee8bcba4 1009 result->on_io_close_complete = NULL;
AzureIoTClient 23:1111ee8bcba4 1010 result->on_bytes_received_context = NULL;
AzureIoTClient 23:1111ee8bcba4 1011 result->on_io_open_complete_context = NULL;
AzureIoTClient 23:1111ee8bcba4 1012 result->on_io_close_complete_context = NULL;
AzureIoTClient 23:1111ee8bcba4 1013 result->on_io_error_context = NULL;
AzureIoTClient 23:1111ee8bcba4 1014 result->sasl_mechanism = sasl_client_io_config->sasl_mechanism;
Azure.IoT Build 0:6ae2f7bca550 1015
AzureIoTClient 23:1111ee8bcba4 1016 result->io_state = IO_STATE_NOT_OPEN;
AzureIoTClient 6:641a9672db08 1017 }
AzureIoTClient 6:641a9672db08 1018 }
AzureIoTClient 6:641a9672db08 1019 }
AzureIoTClient 6:641a9672db08 1020 }
Azure.IoT Build 0:6ae2f7bca550 1021
AzureIoTClient 6:641a9672db08 1022 return result;
Azure.IoT Build 0:6ae2f7bca550 1023 }
Azure.IoT Build 0:6ae2f7bca550 1024
Azure.IoT Build 0:6ae2f7bca550 1025 void saslclientio_destroy(CONCRETE_IO_HANDLE sasl_client_io)
Azure.IoT Build 0:6ae2f7bca550 1026 {
AzureIoTClient 23:1111ee8bcba4 1027 if (sasl_client_io == NULL)
AzureIoTClient 23:1111ee8bcba4 1028 {
AzureIoTClient 30:0407b2db334c 1029 /* Codes_SRS_SASLCLIENTIO_01_008: [If the argument `sasl_client_io` is NULL, `saslclientio_destroy` shall do nothing.] */
AzureIoTClient 23:1111ee8bcba4 1030 LogError("NULL sasl_client_io");
AzureIoTClient 23:1111ee8bcba4 1031 }
AzureIoTClient 23:1111ee8bcba4 1032 else
AzureIoTClient 6:641a9672db08 1033 {
AzureIoTClient 6:641a9672db08 1034 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
Azure.IoT Build 0:6ae2f7bca550 1035
AzureIoTClient 30:0407b2db334c 1036 /* Codes_SRS_SASLCLIENTIO_01_007: [`saslclientio_destroy` shall free all resources associated with the SASL client IO handle.] */
AzureIoTClient 30:0407b2db334c 1037 /* Codes_SRS_SASLCLIENTIO_01_086: [`saslclientio_destroy` shall destroy the SASL frame codec created in `saslclientio_create` by calling `sasl_frame_codec_destroy`.] */
AzureIoTClient 6:641a9672db08 1038 sasl_frame_codec_destroy(sasl_client_io_instance->sasl_frame_codec);
Azure.IoT Build 0:6ae2f7bca550 1039
AzureIoTClient 30:0407b2db334c 1040 /* Codes_SRS_SASLCLIENTIO_01_091: [`saslclientio_destroy` shall destroy the frame codec created in `saslclientio_create` by calling `frame_codec_destroy`.] */
AzureIoTClient 6:641a9672db08 1041 frame_codec_destroy(sasl_client_io_instance->frame_codec);
AzureIoTClient 21:f9c433d8e6ca 1042 free(sasl_client_io);
AzureIoTClient 6:641a9672db08 1043 }
Azure.IoT Build 0:6ae2f7bca550 1044 }
Azure.IoT Build 0:6ae2f7bca550 1045
AzureIoTClient 30:0407b2db334c 1046 int saslclientio_open_async(CONCRETE_IO_HANDLE sasl_client_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
Azure.IoT Build 0:6ae2f7bca550 1047 {
AzureIoTClient 6:641a9672db08 1048 int result = 0;
Azure.IoT Build 0:6ae2f7bca550 1049
AzureIoTClient 6:641a9672db08 1050 if ((sasl_client_io == NULL) ||
AzureIoTClient 30:0407b2db334c 1051 (on_io_open_complete == NULL) ||
AzureIoTClient 30:0407b2db334c 1052 (on_bytes_received == NULL) ||
AzureIoTClient 30:0407b2db334c 1053 (on_io_error == NULL))
AzureIoTClient 6:641a9672db08 1054 {
AzureIoTClient 30:0407b2db334c 1055 /* Codes_SRS_SASLCLIENTIO_01_011: [If any of the `sasl_client_io`, `on_io_open_complete`, `on_bytes_received` or `on_io_error` arguments is NULL, `saslclientio_open` shall fail and return a non-zero value.] */
AzureIoTClient 30:0407b2db334c 1056 LogError("Bad arguments: sasl_client_io = %p, on_io_open_complete = %p, on_bytes_received = %p, on_io_error = %p",
AzureIoTClient 30:0407b2db334c 1057 sasl_client_io, on_io_open_complete, on_bytes_received, on_io_error);
AzureIoTClient 19:000ab4e6a2c1 1058 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1059 }
AzureIoTClient 6:641a9672db08 1060 else
AzureIoTClient 6:641a9672db08 1061 {
AzureIoTClient 6:641a9672db08 1062 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
Azure.IoT Build 0:6ae2f7bca550 1063
AzureIoTClient 6:641a9672db08 1064 if (sasl_client_io_instance->io_state != IO_STATE_NOT_OPEN)
AzureIoTClient 6:641a9672db08 1065 {
AzureIoTClient 23:1111ee8bcba4 1066 LogError("Open called while already OPEN");
AzureIoTClient 19:000ab4e6a2c1 1067 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1068 }
AzureIoTClient 6:641a9672db08 1069 else
AzureIoTClient 6:641a9672db08 1070 {
AzureIoTClient 6:641a9672db08 1071 sasl_client_io_instance->on_bytes_received = on_bytes_received;
AzureIoTClient 6:641a9672db08 1072 sasl_client_io_instance->on_io_open_complete = on_io_open_complete;
AzureIoTClient 6:641a9672db08 1073 sasl_client_io_instance->on_io_error = on_io_error;
AzureIoTClient 6:641a9672db08 1074 sasl_client_io_instance->on_bytes_received_context = on_bytes_received_context;
Azure.IoT Build 0:6ae2f7bca550 1075 sasl_client_io_instance->on_io_open_complete_context = on_io_open_complete_context;
Azure.IoT Build 0:6ae2f7bca550 1076 sasl_client_io_instance->on_io_error_context = on_io_error_context;
AzureIoTClient 6:641a9672db08 1077 sasl_client_io_instance->sasl_header_exchange_state = SASL_HEADER_EXCHANGE_IDLE;
AzureIoTClient 6:641a9672db08 1078 sasl_client_io_instance->sasl_client_negotiation_state = SASL_CLIENT_NEGOTIATION_NOT_STARTED;
AzureIoTClient 6:641a9672db08 1079 sasl_client_io_instance->header_bytes_received = 0;
AzureIoTClient 6:641a9672db08 1080 sasl_client_io_instance->io_state = IO_STATE_OPENING_UNDERLYING_IO;
AzureIoTClient 6:641a9672db08 1081 sasl_client_io_instance->is_trace_on = 0;
AzureIoTClient 30:0407b2db334c 1082 sasl_client_io_instance->is_trace_on_set = 0;
Azure.IoT Build 0:6ae2f7bca550 1083
AzureIoTClient 30:0407b2db334c 1084 /* Codes_SRS_SASLCLIENTIO_01_009: [`saslclientio_open` shall call `xio_open` on the `underlying_io` passed to `saslclientio_create`.] */
AzureIoTClient 30:0407b2db334c 1085 /* Codes_SRS_SASLCLIENTIO_01_013: [`saslclientio_open_async` shall pass to `xio_open` the `on_underlying_io_open_complete` as `on_io_open_complete` argument, `on_underlying_io_bytes_received` as `on_bytes_received` argument and `on_underlying_io_error` as `on_io_error` argument.] */
AzureIoTClient 6:641a9672db08 1086 if (xio_open(sasl_client_io_instance->underlying_io, on_underlying_io_open_complete, sasl_client_io_instance, on_underlying_io_bytes_received, sasl_client_io_instance, on_underlying_io_error, sasl_client_io_instance) != 0)
AzureIoTClient 6:641a9672db08 1087 {
AzureIoTClient 30:0407b2db334c 1088 /* Codes_SRS_SASLCLIENTIO_01_012: [If the open of the `underlying_io` fails, `saslclientio_open_async` shall fail and return non-zero value.] */
AzureIoTClient 23:1111ee8bcba4 1089 LogError("xio_open failed");
AzureIoTClient 19:000ab4e6a2c1 1090 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1091 }
AzureIoTClient 6:641a9672db08 1092 else
AzureIoTClient 6:641a9672db08 1093 {
AzureIoTClient 30:0407b2db334c 1094 /* Codes_SRS_SASLCLIENTIO_01_010: [On success, `saslclientio_open_async` shall return 0.]*/
AzureIoTClient 6:641a9672db08 1095 result = 0;
AzureIoTClient 6:641a9672db08 1096 }
AzureIoTClient 6:641a9672db08 1097 }
AzureIoTClient 6:641a9672db08 1098 }
AzureIoTClient 6:641a9672db08 1099
AzureIoTClient 6:641a9672db08 1100 return result;
Azure.IoT Build 0:6ae2f7bca550 1101 }
Azure.IoT Build 0:6ae2f7bca550 1102
AzureIoTClient 30:0407b2db334c 1103 int saslclientio_close_async(CONCRETE_IO_HANDLE sasl_client_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* on_io_close_complete_context)
Azure.IoT Build 0:6ae2f7bca550 1104 {
AzureIoTClient 6:641a9672db08 1105 int result = 0;
Azure.IoT Build 0:6ae2f7bca550 1106
AzureIoTClient 30:0407b2db334c 1107 /* Codes_SRS_SASLCLIENTIO_01_017: [If `sasl_client_io` is NULL, `saslclientio_close_async` shall fail and return a non-zero value.] */
AzureIoTClient 6:641a9672db08 1108 if (sasl_client_io == NULL)
AzureIoTClient 6:641a9672db08 1109 {
AzureIoTClient 23:1111ee8bcba4 1110 LogError("NULL saslclientio_close");
AzureIoTClient 19:000ab4e6a2c1 1111 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1112 }
AzureIoTClient 6:641a9672db08 1113 else
AzureIoTClient 6:641a9672db08 1114 {
AzureIoTClient 6:641a9672db08 1115 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
Azure.IoT Build 0:6ae2f7bca550 1116
AzureIoTClient 30:0407b2db334c 1117 /* Codes_SRS_SASLCLIENTIO_01_098: [`saslclientio_close_async` shall only perform the close if the state is OPEN, OPENING or ERROR.] */
AzureIoTClient 6:641a9672db08 1118 if ((sasl_client_io_instance->io_state == IO_STATE_NOT_OPEN) ||
AzureIoTClient 6:641a9672db08 1119 (sasl_client_io_instance->io_state == IO_STATE_CLOSING))
AzureIoTClient 6:641a9672db08 1120 {
AzureIoTClient 30:0407b2db334c 1121 /* Codes_SRS_SASLCLIENTIO_01_097: [If `saslclientio_close_async` is called when the IO is in the `IO_STATE_NOT_OPEN` state, `saslclientio_close_async` shall fail and return a non zero value.] */
AzureIoTClient 23:1111ee8bcba4 1122 LogError("saslclientio_close called while not open");
AzureIoTClient 19:000ab4e6a2c1 1123 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1124 }
AzureIoTClient 6:641a9672db08 1125 else
AzureIoTClient 6:641a9672db08 1126 {
AzureIoTClient 6:641a9672db08 1127 sasl_client_io_instance->io_state = IO_STATE_CLOSING;
Azure.IoT Build 0:6ae2f7bca550 1128
Azure.IoT Build 0:6ae2f7bca550 1129 sasl_client_io_instance->on_io_close_complete = on_io_close_complete;
Azure.IoT Build 0:6ae2f7bca550 1130 sasl_client_io_instance->on_io_close_complete_context = on_io_close_complete_context;
Azure.IoT Build 0:6ae2f7bca550 1131
AzureIoTClient 30:0407b2db334c 1132 /* Codes_SRS_SASLCLIENTIO_01_015: [`saslclientio_close_async` shall close the underlying io handle passed in `saslclientio_create` by calling `xio_close`.] */
AzureIoTClient 6:641a9672db08 1133 if (xio_close(sasl_client_io_instance->underlying_io, on_underlying_io_close_complete, sasl_client_io_instance) != 0)
AzureIoTClient 6:641a9672db08 1134 {
AzureIoTClient 30:0407b2db334c 1135 /* Codes_SRS_SASLCLIENTIO_01_018: [If `xio_close` fails, then `saslclientio_close_async` shall return a non-zero value.] */
AzureIoTClient 23:1111ee8bcba4 1136 LogError("xio_close failed");
AzureIoTClient 19:000ab4e6a2c1 1137 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1138 }
AzureIoTClient 6:641a9672db08 1139 else
AzureIoTClient 6:641a9672db08 1140 {
AzureIoTClient 30:0407b2db334c 1141 /* Codes_SRS_SASLCLIENTIO_01_016: [On success, `saslclientio_close_async` shall return 0.] */
AzureIoTClient 6:641a9672db08 1142 result = 0;
AzureIoTClient 6:641a9672db08 1143 }
AzureIoTClient 6:641a9672db08 1144 }
AzureIoTClient 6:641a9672db08 1145 }
Azure.IoT Build 0:6ae2f7bca550 1146
AzureIoTClient 6:641a9672db08 1147 return result;
Azure.IoT Build 0:6ae2f7bca550 1148 }
Azure.IoT Build 0:6ae2f7bca550 1149
AzureIoTClient 30:0407b2db334c 1150 int saslclientio_send_async(CONCRETE_IO_HANDLE sasl_client_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 1151 {
AzureIoTClient 6:641a9672db08 1152 int result;
Azure.IoT Build 0:6ae2f7bca550 1153
AzureIoTClient 30:0407b2db334c 1154 /* Codes_SRS_SASLCLIENTIO_01_022: [If the `sasl_client_io` or `buffer` argument is NULL, `saslclientio_send_async` shall fail and return a non-zero value.]*/
AzureIoTClient 30:0407b2db334c 1155 /* Codes_SRS_SASLCLIENTIO_01_127: [ `on_send_complete` shall be allowed to be NULL. ]*/
AzureIoTClient 6:641a9672db08 1156 if ((sasl_client_io == NULL) ||
AzureIoTClient 6:641a9672db08 1157 (buffer == NULL) ||
AzureIoTClient 30:0407b2db334c 1158 /* Codes_SRS_SASLCLIENTIO_01_023: [If `size` is 0, `saslclientio_send_async` shall fail and return a non-zero value.]*/
AzureIoTClient 6:641a9672db08 1159 (size == 0))
AzureIoTClient 6:641a9672db08 1160 {
AzureIoTClient 6:641a9672db08 1161 /* Invalid arguments */
AzureIoTClient 23:1111ee8bcba4 1162 LogError("Bad arguments: sasl_client_io = %p, buffer = %p, size = %u",
AzureIoTClient 23:1111ee8bcba4 1163 sasl_client_io, buffer, (unsigned int)size);
AzureIoTClient 19:000ab4e6a2c1 1164 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1165 }
AzureIoTClient 6:641a9672db08 1166 else
AzureIoTClient 6:641a9672db08 1167 {
AzureIoTClient 6:641a9672db08 1168 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
Azure.IoT Build 0:6ae2f7bca550 1169
AzureIoTClient 30:0407b2db334c 1170 /* Codes_SRS_SASLCLIENTIO_01_019: [If `saslclientio_send_async` is called while the SASL client IO state is not `IO_STATE_OPEN`, `saslclientio_send_async` shall fail and return a non-zero value.]*/
AzureIoTClient 6:641a9672db08 1171 if (sasl_client_io_instance->io_state != IO_STATE_OPEN)
AzureIoTClient 6:641a9672db08 1172 {
AzureIoTClient 23:1111ee8bcba4 1173 LogError("send called while not open");
AzureIoTClient 19:000ab4e6a2c1 1174 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1175 }
AzureIoTClient 6:641a9672db08 1176 else
AzureIoTClient 6:641a9672db08 1177 {
AzureIoTClient 30:0407b2db334c 1178 /* Codes_SRS_SASLCLIENTIO_01_020: [If the SASL client IO state is `IO_STATE_OPEN`, `saslclientio_send_async` shall call `xio_send` on the `underlying_io` passed to `saslclientio_create`, while passing as arguments the `buffer`,`size`, `on_send_complete` and `callback_context`.]*/
AzureIoTClient 6:641a9672db08 1179 if (xio_send(sasl_client_io_instance->underlying_io, buffer, size, on_send_complete, callback_context) != 0)
AzureIoTClient 6:641a9672db08 1180 {
AzureIoTClient 30:0407b2db334c 1181 /* Codes_SRS_SASLCLIENTIO_01_024: [If the call to `xio_send` fails, then `saslclientio_send_async` shall fail and return a non-zero value.]*/
AzureIoTClient 23:1111ee8bcba4 1182 LogError("xio_send failed");
AzureIoTClient 19:000ab4e6a2c1 1183 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 1184 }
AzureIoTClient 6:641a9672db08 1185 else
AzureIoTClient 6:641a9672db08 1186 {
AzureIoTClient 30:0407b2db334c 1187 /* Codes_SRS_SASLCLIENTIO_01_021: [On success, `saslclientio_send_async` shall return 0.]*/
AzureIoTClient 6:641a9672db08 1188 result = 0;
AzureIoTClient 6:641a9672db08 1189 }
AzureIoTClient 6:641a9672db08 1190 }
AzureIoTClient 6:641a9672db08 1191 }
Azure.IoT Build 0:6ae2f7bca550 1192
AzureIoTClient 6:641a9672db08 1193 return result;
Azure.IoT Build 0:6ae2f7bca550 1194 }
Azure.IoT Build 0:6ae2f7bca550 1195
Azure.IoT Build 0:6ae2f7bca550 1196 void saslclientio_dowork(CONCRETE_IO_HANDLE sasl_client_io)
Azure.IoT Build 0:6ae2f7bca550 1197 {
AzureIoTClient 30:0407b2db334c 1198 /* Codes_SRS_SASLCLIENTIO_01_026: [If the `sasl_client_io` argument is NULL, `saslclientio_dowork` shall do nothing.]*/
AzureIoTClient 23:1111ee8bcba4 1199 if (sasl_client_io == NULL)
AzureIoTClient 23:1111ee8bcba4 1200 {
AzureIoTClient 23:1111ee8bcba4 1201 LogError("NULL sasl_client_io");
AzureIoTClient 23:1111ee8bcba4 1202 }
AzureIoTClient 23:1111ee8bcba4 1203 else
AzureIoTClient 6:641a9672db08 1204 {
AzureIoTClient 6:641a9672db08 1205 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
Azure.IoT Build 0:6ae2f7bca550 1206
AzureIoTClient 30:0407b2db334c 1207 /* Codes_SRS_SASLCLIENTIO_01_099: [If the state of the IO is `IO_NOT_OPEN`, `saslclientio_dowork` shall make no calls to the underlying IO.]*/
AzureIoTClient 6:641a9672db08 1208 if (sasl_client_io_instance->io_state != IO_STATE_NOT_OPEN)
AzureIoTClient 6:641a9672db08 1209 {
AzureIoTClient 30:0407b2db334c 1210 /* Codes_SRS_SASLCLIENTIO_01_025: [`saslclientio_dowork` shall call the `xio_dowork` on the `underlying_io` passed in `saslclientio_create`.]*/
AzureIoTClient 6:641a9672db08 1211 xio_dowork(sasl_client_io_instance->underlying_io);
AzureIoTClient 6:641a9672db08 1212 }
AzureIoTClient 6:641a9672db08 1213 }
Azure.IoT Build 0:6ae2f7bca550 1214 }
Azure.IoT Build 0:6ae2f7bca550 1215
AzureIoTClient 30:0407b2db334c 1216 int saslclientio_setoption(CONCRETE_IO_HANDLE sasl_client_io, const char* option_name, const void* value)
Azure.IoT Build 0:6ae2f7bca550 1217 {
AzureIoTClient 1:eab586236bfe 1218 int result;
AzureIoTClient 1:eab586236bfe 1219
AzureIoTClient 30:0407b2db334c 1220 if ((sasl_client_io == NULL) ||
AzureIoTClient 30:0407b2db334c 1221 (option_name == NULL))
AzureIoTClient 1:eab586236bfe 1222 {
AzureIoTClient 30:0407b2db334c 1223 /* Codes_SRS_SASLCLIENTIO_01_130: [ If `sasl_client_io` or `option_name` is NULL, `saslclientio_setoption` shall fail and return a non-zero value. ]*/
AzureIoTClient 30:0407b2db334c 1224 LogError("Bad arguments: sasl_client_io = %p, option_name = %p",
AzureIoTClient 30:0407b2db334c 1225 sasl_client_io, option_name);
AzureIoTClient 19:000ab4e6a2c1 1226 result = __FAILURE__;
AzureIoTClient 1:eab586236bfe 1227 }
AzureIoTClient 1:eab586236bfe 1228 else
AzureIoTClient 1:eab586236bfe 1229 {
AzureIoTClient 1:eab586236bfe 1230 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
AzureIoTClient 1:eab586236bfe 1231
AzureIoTClient 1:eab586236bfe 1232 if (sasl_client_io_instance->underlying_io == NULL)
AzureIoTClient 1:eab586236bfe 1233 {
AzureIoTClient 23:1111ee8bcba4 1234 LogError("NULL underlying_io");
AzureIoTClient 19:000ab4e6a2c1 1235 result = __FAILURE__;
AzureIoTClient 1:eab586236bfe 1236 }
AzureIoTClient 30:0407b2db334c 1237 /* Codes_SRS_SASLCLIENTIO_01_131: [ SASL client IO shall handle the following options: ]*/
AzureIoTClient 30:0407b2db334c 1238 /* Codes_SRS_SASLCLIENTIO_01_132: [ - logtrace - bool. ]*/
AzureIoTClient 30:0407b2db334c 1239 else if (strcmp("logtrace", option_name) == 0)
AzureIoTClient 6:641a9672db08 1240 {
AzureIoTClient 6:641a9672db08 1241 sasl_client_io_instance->is_trace_on = *((bool*)value) == true ? 1 : 0;
AzureIoTClient 30:0407b2db334c 1242 sasl_client_io_instance->is_trace_on_set = 1;
AzureIoTClient 30:0407b2db334c 1243
AzureIoTClient 30:0407b2db334c 1244 /* Codes_SRS_SASLCLIENTIO_01_128: [ On success, `saslclientio_setoption` shall return 0. ]*/
AzureIoTClient 6:641a9672db08 1245 result = 0;
AzureIoTClient 6:641a9672db08 1246 }
AzureIoTClient 1:eab586236bfe 1247 else
AzureIoTClient 1:eab586236bfe 1248 {
AzureIoTClient 30:0407b2db334c 1249 /* Codes_SRS_SASLCLIENTIO_03_001: [`saslclientio_setoption` shall forward all unhandled options to underlying io by calling `xio_setoption`.]*/
AzureIoTClient 30:0407b2db334c 1250 if (xio_setoption(sasl_client_io_instance->underlying_io, option_name, value) != 0)
AzureIoTClient 30:0407b2db334c 1251 {
AzureIoTClient 30:0407b2db334c 1252 LogError("Error executing xio_setoption");
AzureIoTClient 30:0407b2db334c 1253 result = __FAILURE__;
AzureIoTClient 30:0407b2db334c 1254 }
AzureIoTClient 30:0407b2db334c 1255 else
AzureIoTClient 30:0407b2db334c 1256 {
AzureIoTClient 30:0407b2db334c 1257 /* Codes_SRS_SASLCLIENTIO_01_128: [ On success, `saslclientio_setoption` shall return 0. ]*/
AzureIoTClient 30:0407b2db334c 1258 result = 0;
AzureIoTClient 30:0407b2db334c 1259 }
AzureIoTClient 1:eab586236bfe 1260 }
AzureIoTClient 1:eab586236bfe 1261 }
AzureIoTClient 23:1111ee8bcba4 1262
AzureIoTClient 6:641a9672db08 1263 return result;
AzureIoTClient 6:641a9672db08 1264 }
AzureIoTClient 1:eab586236bfe 1265
AzureIoTClient 6:641a9672db08 1266 /*this function will clone an option given by name and value*/
AzureIoTClient 30:0407b2db334c 1267 static void* saslclientio_clone_option(const char* name, const void* value)
AzureIoTClient 6:641a9672db08 1268 {
AzureIoTClient 17:923575db8b2d 1269 (void)name;
AzureIoTClient 17:923575db8b2d 1270 (void)value;
AzureIoTClient 6:641a9672db08 1271 return NULL;
AzureIoTClient 6:641a9672db08 1272 }
AzureIoTClient 6:641a9672db08 1273
AzureIoTClient 6:641a9672db08 1274 /*this function destroys an option previously created*/
AzureIoTClient 30:0407b2db334c 1275 static void saslclientio_destroy_option(const char* name, const void* value)
AzureIoTClient 6:641a9672db08 1276 {
AzureIoTClient 17:923575db8b2d 1277 (void)name;
AzureIoTClient 17:923575db8b2d 1278 (void)value;
AzureIoTClient 6:641a9672db08 1279 }
AzureIoTClient 6:641a9672db08 1280
AzureIoTClient 30:0407b2db334c 1281 static OPTIONHANDLER_HANDLE saslclientio_retrieveoptions(CONCRETE_IO_HANDLE sasl_client_io)
AzureIoTClient 6:641a9672db08 1282 {
AzureIoTClient 6:641a9672db08 1283 OPTIONHANDLER_HANDLE result;
AzureIoTClient 30:0407b2db334c 1284
AzureIoTClient 30:0407b2db334c 1285 if (sasl_client_io == NULL)
AzureIoTClient 6:641a9672db08 1286 {
AzureIoTClient 30:0407b2db334c 1287 /* Codes_SRS_SASLCLIENTIO_01_139: [ When `saslclientio_retrieveoptions` is called with NULL `sasl_client_io` it shall fail and return NULL. ]*/
AzureIoTClient 30:0407b2db334c 1288 result = NULL;
AzureIoTClient 6:641a9672db08 1289 }
AzureIoTClient 6:641a9672db08 1290 else
AzureIoTClient 6:641a9672db08 1291 {
AzureIoTClient 30:0407b2db334c 1292 /* Codes_SRS_SASLCLIENTIO_01_133: [ `saslclientio_retrieveoptions` shall create an option handler by calling `OptionHandler_Create`. ]*/
AzureIoTClient 30:0407b2db334c 1293 result = OptionHandler_Create(saslclientio_clone_option, saslclientio_destroy_option, saslclientio_setoption);
AzureIoTClient 30:0407b2db334c 1294 if (result == NULL)
AzureIoTClient 30:0407b2db334c 1295 {
AzureIoTClient 30:0407b2db334c 1296 /* Codes_SRS_SASLCLIENTIO_01_138: [ If `OptionHandler_AddOption` or `OptionHandler_Create` fails then `saslclientio_retrieveoptions` shall fail and return NULL. ]*/
AzureIoTClient 30:0407b2db334c 1297 LogError("unable to OptionHandler_Create");
AzureIoTClient 30:0407b2db334c 1298 /*return as is*/
AzureIoTClient 30:0407b2db334c 1299 }
AzureIoTClient 30:0407b2db334c 1300 else
AzureIoTClient 30:0407b2db334c 1301 {
AzureIoTClient 30:0407b2db334c 1302 SASL_CLIENT_IO_INSTANCE* sasl_client_io_instance = (SASL_CLIENT_IO_INSTANCE*)sasl_client_io;
AzureIoTClient 30:0407b2db334c 1303
AzureIoTClient 30:0407b2db334c 1304 /*insert here work to add the options to "result" handle*/
AzureIoTClient 30:0407b2db334c 1305 if (sasl_client_io_instance->is_trace_on_set)
AzureIoTClient 30:0407b2db334c 1306 {
AzureIoTClient 30:0407b2db334c 1307 bool logtrace = sasl_client_io_instance->is_trace_on ? true : false;
AzureIoTClient 30:0407b2db334c 1308 /* Codes_SRS_SASLCLIENTIO_01_137: [ The options shall be added by calling `OptionHandler_AddOption`. ]*/
AzureIoTClient 30:0407b2db334c 1309 if (OptionHandler_AddOption(result, "logtrace", &logtrace) != 0)
AzureIoTClient 30:0407b2db334c 1310 {
AzureIoTClient 30:0407b2db334c 1311 /* Codes_SRS_SASLCLIENTIO_01_138: [ If `OptionHandler_AddOption` or `OptionHandler_Create` fails then `saslclientio_retrieveoptions` shall fail and return NULL. ]*/
AzureIoTClient 30:0407b2db334c 1312 LogError("unable to add logtrace option");
AzureIoTClient 30:0407b2db334c 1313 OptionHandler_Destroy(result);
AzureIoTClient 30:0407b2db334c 1314 result = NULL;
AzureIoTClient 30:0407b2db334c 1315 }
AzureIoTClient 30:0407b2db334c 1316 }
AzureIoTClient 30:0407b2db334c 1317 }
AzureIoTClient 6:641a9672db08 1318 }
AzureIoTClient 23:1111ee8bcba4 1319
AzureIoTClient 1:eab586236bfe 1320 return result;
Azure.IoT Build 0:6ae2f7bca550 1321 }
Azure.IoT Build 0:6ae2f7bca550 1322
Azure.IoT Build 0:6ae2f7bca550 1323 static const IO_INTERFACE_DESCRIPTION sasl_client_io_interface_description =
Azure.IoT Build 0:6ae2f7bca550 1324 {
AzureIoTClient 6:641a9672db08 1325 saslclientio_retrieveoptions,
AzureIoTClient 6:641a9672db08 1326 saslclientio_create,
AzureIoTClient 6:641a9672db08 1327 saslclientio_destroy,
AzureIoTClient 30:0407b2db334c 1328 saslclientio_open_async,
AzureIoTClient 30:0407b2db334c 1329 saslclientio_close_async,
AzureIoTClient 30:0407b2db334c 1330 saslclientio_send_async,
AzureIoTClient 6:641a9672db08 1331 saslclientio_dowork,
Azure.IoT Build 0:6ae2f7bca550 1332 saslclientio_setoption
Azure.IoT Build 0:6ae2f7bca550 1333 };
Azure.IoT Build 0:6ae2f7bca550 1334
AzureIoTClient 30:0407b2db334c 1335 /* Codes_SRS_SASLCLIENTIO_01_087: [`saslclientio_get_interface_description` shall return a pointer to an `IO_INTERFACE_DESCRIPTION` structure that contains pointers to the functions: `saslclientio_create`, `saslclientio_destroy`, `saslclientio_open_async`, `saslclientio_close_async`, `saslclientio_send_async`, `saslclientio_setoption`, `saslclientio_retrieveoptions` and `saslclientio_dowork`.]*/
Azure.IoT Build 0:6ae2f7bca550 1336 const IO_INTERFACE_DESCRIPTION* saslclientio_get_interface_description(void)
Azure.IoT Build 0:6ae2f7bca550 1337 {
AzureIoTClient 6:641a9672db08 1338 return &sasl_client_io_interface_description;
Azure.IoT Build 0:6ae2f7bca550 1339 }