A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Jul 28 09:52:29 2017 -0700
Revision:
30:0407b2db334c
Parent:
28:add19eb7defa
Child:
38:7631b92cc772
1.1.20

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