Xin Zhang / azure-iot-c-sdk-f767zi

Dependents:   samplemqtt

Committer:
XinZhangMS
Date:
Thu Aug 23 06:52:14 2018 +0000
Revision:
0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI

Who changed what in which revision?

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