A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Feb 24 14:00:58 2017 -0800
Revision:
19:000ab4e6a2c1
Parent:
17:923575db8b2d
Child:
21:f9c433d8e6ca
1.1.8

Who changed what in which revision?

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