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 <stdbool.h>
XinZhangMS 0:f7f1f0d76dd6 7 #include "azure_c_shared_utility/optimize_size.h"
XinZhangMS 0:f7f1f0d76dd6 8 #include "azure_c_shared_utility/gballoc.h"
XinZhangMS 0:f7f1f0d76dd6 9 #include "azure_c_shared_utility/xlogging.h"
XinZhangMS 0:f7f1f0d76dd6 10 #include "azure_c_shared_utility/singlylinkedlist.h"
XinZhangMS 0:f7f1f0d76dd6 11 #include "azure_uamqp_c/header_detect_io.h"
XinZhangMS 0:f7f1f0d76dd6 12 #include "azure_uamqp_c/server_protocol_io.h"
XinZhangMS 0:f7f1f0d76dd6 13
XinZhangMS 0:f7f1f0d76dd6 14 static const unsigned char amqp_header_bytes[] = { 'A', 'M', 'Q', 'P', 0, 1, 0, 0 };
XinZhangMS 0:f7f1f0d76dd6 15 static const unsigned char sasl_amqp_header_bytes[] = { 'A', 'M', 'Q', 'P', 3, 1, 0, 0 };
XinZhangMS 0:f7f1f0d76dd6 16
XinZhangMS 0:f7f1f0d76dd6 17 typedef enum IO_STATE_TAG
XinZhangMS 0:f7f1f0d76dd6 18 {
XinZhangMS 0:f7f1f0d76dd6 19 IO_STATE_NOT_OPEN,
XinZhangMS 0:f7f1f0d76dd6 20 IO_STATE_OPENING_UNDERLYING_IO,
XinZhangMS 0:f7f1f0d76dd6 21 IO_STATE_WAIT_FOR_HEADER,
XinZhangMS 0:f7f1f0d76dd6 22 IO_STATE_OPENING_DETECTED_IO,
XinZhangMS 0:f7f1f0d76dd6 23 IO_STATE_OPEN,
XinZhangMS 0:f7f1f0d76dd6 24 IO_STATE_CLOSING,
XinZhangMS 0:f7f1f0d76dd6 25 IO_STATE_ERROR
XinZhangMS 0:f7f1f0d76dd6 26 } IO_STATE;
XinZhangMS 0:f7f1f0d76dd6 27
XinZhangMS 0:f7f1f0d76dd6 28 typedef struct INTERNAL_HEADER_DETECT_ENTRY_TAG
XinZhangMS 0:f7f1f0d76dd6 29 {
XinZhangMS 0:f7f1f0d76dd6 30 unsigned char* header_bytes;
XinZhangMS 0:f7f1f0d76dd6 31 size_t header_size;
XinZhangMS 0:f7f1f0d76dd6 32 const IO_INTERFACE_DESCRIPTION* io_interface_description;
XinZhangMS 0:f7f1f0d76dd6 33 } INTERNAL_HEADER_DETECT_ENTRY;
XinZhangMS 0:f7f1f0d76dd6 34
XinZhangMS 0:f7f1f0d76dd6 35 typedef struct CHAINED_IO_TAG
XinZhangMS 0:f7f1f0d76dd6 36 {
XinZhangMS 0:f7f1f0d76dd6 37 XIO_HANDLE detected_io;
XinZhangMS 0:f7f1f0d76dd6 38 ON_BYTES_RECEIVED on_bytes_received;
XinZhangMS 0:f7f1f0d76dd6 39 void* on_bytes_received_context;
XinZhangMS 0:f7f1f0d76dd6 40 } CHAINED_IO;
XinZhangMS 0:f7f1f0d76dd6 41
XinZhangMS 0:f7f1f0d76dd6 42 typedef struct HEADER_DETECT_IO_INSTANCE_TAG
XinZhangMS 0:f7f1f0d76dd6 43 {
XinZhangMS 0:f7f1f0d76dd6 44 XIO_HANDLE underlying_io;
XinZhangMS 0:f7f1f0d76dd6 45 IO_STATE io_state;
XinZhangMS 0:f7f1f0d76dd6 46 size_t header_pos;
XinZhangMS 0:f7f1f0d76dd6 47 ON_IO_OPEN_COMPLETE on_io_open_complete;
XinZhangMS 0:f7f1f0d76dd6 48 ON_IO_CLOSE_COMPLETE on_io_close_complete;
XinZhangMS 0:f7f1f0d76dd6 49 ON_IO_ERROR on_io_error;
XinZhangMS 0:f7f1f0d76dd6 50 ON_BYTES_RECEIVED on_bytes_received;
XinZhangMS 0:f7f1f0d76dd6 51 void* on_io_open_complete_context;
XinZhangMS 0:f7f1f0d76dd6 52 void* on_io_close_complete_context;
XinZhangMS 0:f7f1f0d76dd6 53 void* on_io_error_context;
XinZhangMS 0:f7f1f0d76dd6 54 void* on_bytes_received_context;
XinZhangMS 0:f7f1f0d76dd6 55 INTERNAL_HEADER_DETECT_ENTRY* header_detect_entries;
XinZhangMS 0:f7f1f0d76dd6 56 size_t header_detect_entry_count;
XinZhangMS 0:f7f1f0d76dd6 57 SINGLYLINKEDLIST_HANDLE chained_io_list;
XinZhangMS 0:f7f1f0d76dd6 58 XIO_HANDLE* last_io;
XinZhangMS 0:f7f1f0d76dd6 59 } HEADER_DETECT_IO_INSTANCE;
XinZhangMS 0:f7f1f0d76dd6 60
XinZhangMS 0:f7f1f0d76dd6 61 static void destroy_io_chain(HEADER_DETECT_IO_INSTANCE* header_detect_io)
XinZhangMS 0:f7f1f0d76dd6 62 {
XinZhangMS 0:f7f1f0d76dd6 63 LIST_ITEM_HANDLE list_item = singlylinkedlist_get_head_item(header_detect_io->chained_io_list);
XinZhangMS 0:f7f1f0d76dd6 64 while (list_item != NULL)
XinZhangMS 0:f7f1f0d76dd6 65 {
XinZhangMS 0:f7f1f0d76dd6 66 CHAINED_IO* chained_io = (CHAINED_IO*)singlylinkedlist_item_get_value(list_item);
XinZhangMS 0:f7f1f0d76dd6 67
XinZhangMS 0:f7f1f0d76dd6 68 if (singlylinkedlist_remove(header_detect_io->chained_io_list, list_item) != 0)
XinZhangMS 0:f7f1f0d76dd6 69 {
XinZhangMS 0:f7f1f0d76dd6 70 LogError("Cannot remove detected IO from list");
XinZhangMS 0:f7f1f0d76dd6 71 }
XinZhangMS 0:f7f1f0d76dd6 72
XinZhangMS 0:f7f1f0d76dd6 73 xio_destroy(chained_io->detected_io);
XinZhangMS 0:f7f1f0d76dd6 74 free(chained_io);
XinZhangMS 0:f7f1f0d76dd6 75
XinZhangMS 0:f7f1f0d76dd6 76 list_item = singlylinkedlist_get_head_item(header_detect_io->chained_io_list);
XinZhangMS 0:f7f1f0d76dd6 77 }
XinZhangMS 0:f7f1f0d76dd6 78
XinZhangMS 0:f7f1f0d76dd6 79 header_detect_io->last_io = &header_detect_io->underlying_io;
XinZhangMS 0:f7f1f0d76dd6 80 }
XinZhangMS 0:f7f1f0d76dd6 81
XinZhangMS 0:f7f1f0d76dd6 82 static void internal_close(HEADER_DETECT_IO_INSTANCE* header_detect_io)
XinZhangMS 0:f7f1f0d76dd6 83 {
XinZhangMS 0:f7f1f0d76dd6 84 // close the last underlying IO (the one that we're talking to)
XinZhangMS 0:f7f1f0d76dd6 85 if (xio_close(*header_detect_io->last_io, NULL, NULL) != 0)
XinZhangMS 0:f7f1f0d76dd6 86 {
XinZhangMS 0:f7f1f0d76dd6 87 LogError("Cannot close underlying IO");
XinZhangMS 0:f7f1f0d76dd6 88 }
XinZhangMS 0:f7f1f0d76dd6 89
XinZhangMS 0:f7f1f0d76dd6 90 destroy_io_chain(header_detect_io);
XinZhangMS 0:f7f1f0d76dd6 91
XinZhangMS 0:f7f1f0d76dd6 92 header_detect_io->io_state = IO_STATE_NOT_OPEN;
XinZhangMS 0:f7f1f0d76dd6 93 }
XinZhangMS 0:f7f1f0d76dd6 94
XinZhangMS 0:f7f1f0d76dd6 95 static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT open_result);
XinZhangMS 0:f7f1f0d76dd6 96 static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size);
XinZhangMS 0:f7f1f0d76dd6 97 static void on_underlying_io_error(void* context);
XinZhangMS 0:f7f1f0d76dd6 98
XinZhangMS 0:f7f1f0d76dd6 99 static void indicate_error(HEADER_DETECT_IO_INSTANCE* header_detect_io_instance)
XinZhangMS 0:f7f1f0d76dd6 100 {
XinZhangMS 0:f7f1f0d76dd6 101 if (header_detect_io_instance->on_io_error != NULL)
XinZhangMS 0:f7f1f0d76dd6 102 {
XinZhangMS 0:f7f1f0d76dd6 103 header_detect_io_instance->on_io_error(header_detect_io_instance->on_io_error_context);
XinZhangMS 0:f7f1f0d76dd6 104 }
XinZhangMS 0:f7f1f0d76dd6 105 }
XinZhangMS 0:f7f1f0d76dd6 106
XinZhangMS 0:f7f1f0d76dd6 107 static void indicate_open_complete(HEADER_DETECT_IO_INSTANCE* header_detect_io_instance, IO_OPEN_RESULT open_result)
XinZhangMS 0:f7f1f0d76dd6 108 {
XinZhangMS 0:f7f1f0d76dd6 109 if (header_detect_io_instance->on_io_open_complete != NULL)
XinZhangMS 0:f7f1f0d76dd6 110 {
XinZhangMS 0:f7f1f0d76dd6 111 header_detect_io_instance->on_io_open_complete(header_detect_io_instance->on_io_open_complete_context, open_result);
XinZhangMS 0:f7f1f0d76dd6 112 }
XinZhangMS 0:f7f1f0d76dd6 113 }
XinZhangMS 0:f7f1f0d76dd6 114
XinZhangMS 0:f7f1f0d76dd6 115 static void indicate_close_complete(HEADER_DETECT_IO_INSTANCE* header_detect_io_instance)
XinZhangMS 0:f7f1f0d76dd6 116 {
XinZhangMS 0:f7f1f0d76dd6 117 if (header_detect_io_instance->on_io_close_complete != NULL)
XinZhangMS 0:f7f1f0d76dd6 118 {
XinZhangMS 0:f7f1f0d76dd6 119 header_detect_io_instance->on_io_close_complete(header_detect_io_instance->on_io_close_complete_context);
XinZhangMS 0:f7f1f0d76dd6 120 }
XinZhangMS 0:f7f1f0d76dd6 121 }
XinZhangMS 0:f7f1f0d76dd6 122
XinZhangMS 0:f7f1f0d76dd6 123 static void on_send_complete(void* context, IO_SEND_RESULT send_result)
XinZhangMS 0:f7f1f0d76dd6 124 {
XinZhangMS 0:f7f1f0d76dd6 125 // able to send the header
XinZhangMS 0:f7f1f0d76dd6 126 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)context;
XinZhangMS 0:f7f1f0d76dd6 127
XinZhangMS 0:f7f1f0d76dd6 128 if (send_result != IO_SEND_OK)
XinZhangMS 0:f7f1f0d76dd6 129 {
XinZhangMS 0:f7f1f0d76dd6 130 // signal error
XinZhangMS 0:f7f1f0d76dd6 131 indicate_error(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 132 }
XinZhangMS 0:f7f1f0d76dd6 133 }
XinZhangMS 0:f7f1f0d76dd6 134
XinZhangMS 0:f7f1f0d76dd6 135 // This callback usage needs to be either verified and commented or integrated into
XinZhangMS 0:f7f1f0d76dd6 136 // the state machine.
XinZhangMS 0:f7f1f0d76dd6 137 static void unchecked_on_send_complete(void* context, IO_SEND_RESULT send_result)
XinZhangMS 0:f7f1f0d76dd6 138 {
XinZhangMS 0:f7f1f0d76dd6 139 (void)context;
XinZhangMS 0:f7f1f0d76dd6 140 (void)send_result;
XinZhangMS 0:f7f1f0d76dd6 141 }
XinZhangMS 0:f7f1f0d76dd6 142
XinZhangMS 0:f7f1f0d76dd6 143 static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
XinZhangMS 0:f7f1f0d76dd6 144 {
XinZhangMS 0:f7f1f0d76dd6 145 if (context == NULL)
XinZhangMS 0:f7f1f0d76dd6 146 {
XinZhangMS 0:f7f1f0d76dd6 147 /* Codes_SRS_HEADER_DETECT_IO_01_050: [ If `context` is NULL, `on_underlying_io_bytes_received` shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 148 LogError("NULL context");
XinZhangMS 0:f7f1f0d76dd6 149 }
XinZhangMS 0:f7f1f0d76dd6 150 else
XinZhangMS 0:f7f1f0d76dd6 151 {
XinZhangMS 0:f7f1f0d76dd6 152 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)context;
XinZhangMS 0:f7f1f0d76dd6 153
XinZhangMS 0:f7f1f0d76dd6 154 if ((buffer == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 155 (size == 0))
XinZhangMS 0:f7f1f0d76dd6 156 {
XinZhangMS 0:f7f1f0d76dd6 157 switch (header_detect_io_instance->io_state)
XinZhangMS 0:f7f1f0d76dd6 158 {
XinZhangMS 0:f7f1f0d76dd6 159 default:
XinZhangMS 0:f7f1f0d76dd6 160 break;
XinZhangMS 0:f7f1f0d76dd6 161
XinZhangMS 0:f7f1f0d76dd6 162 case IO_STATE_OPEN:
XinZhangMS 0:f7f1f0d76dd6 163 /* Codes_SRS_HEADER_DETECT_IO_01_051: [ If `buffer` is NULL or `size` is 0 while the IO is OPEN an error shall be indicated by calling `on_io_error`. ]*/
XinZhangMS 0:f7f1f0d76dd6 164 indicate_error(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 165 break;
XinZhangMS 0:f7f1f0d76dd6 166 }
XinZhangMS 0:f7f1f0d76dd6 167 }
XinZhangMS 0:f7f1f0d76dd6 168 else
XinZhangMS 0:f7f1f0d76dd6 169 {
XinZhangMS 0:f7f1f0d76dd6 170 while (size > 0)
XinZhangMS 0:f7f1f0d76dd6 171 {
XinZhangMS 0:f7f1f0d76dd6 172 switch (header_detect_io_instance->io_state)
XinZhangMS 0:f7f1f0d76dd6 173 {
XinZhangMS 0:f7f1f0d76dd6 174 default:
XinZhangMS 0:f7f1f0d76dd6 175 break;
XinZhangMS 0:f7f1f0d76dd6 176
XinZhangMS 0:f7f1f0d76dd6 177 case IO_STATE_OPENING_UNDERLYING_IO:
XinZhangMS 0:f7f1f0d76dd6 178 /* Codes_SRS_HEADER_DETECT_IO_01_049: [ When `on_underlying_io_bytes_received` is called while opening the underlying IO (before the underlying open complete is received), an error shall be indicated by calling `on_io_open_complete` with `IO_OPEN_ERROR`. ]*/
XinZhangMS 0:f7f1f0d76dd6 179 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
XinZhangMS 0:f7f1f0d76dd6 180 size = 0;
XinZhangMS 0:f7f1f0d76dd6 181 break;
XinZhangMS 0:f7f1f0d76dd6 182
XinZhangMS 0:f7f1f0d76dd6 183 case IO_STATE_OPENING_DETECTED_IO:
XinZhangMS 0:f7f1f0d76dd6 184 {
XinZhangMS 0:f7f1f0d76dd6 185 /* Codes_SRS_HEADER_DETECT_IO_01_087: [ If `on_underlying_io_bytes_received` is called while waiting for the detected IO to complete its open, the bytes shall be given to the last created IO by calling its `on_bytes_received` callback that was filled into the `on_bytes_received` member of `SERVER_PROTOCOL_IO_CONFIG`. ]*/
XinZhangMS 0:f7f1f0d76dd6 186 CHAINED_IO* chained_io = (CHAINED_IO*)(((unsigned char*)header_detect_io_instance->last_io) - offsetof(CHAINED_IO, detected_io));
XinZhangMS 0:f7f1f0d76dd6 187 (chained_io->on_bytes_received)(chained_io->on_bytes_received_context, buffer, size);
XinZhangMS 0:f7f1f0d76dd6 188 size = 0;
XinZhangMS 0:f7f1f0d76dd6 189 break;
XinZhangMS 0:f7f1f0d76dd6 190 }
XinZhangMS 0:f7f1f0d76dd6 191
XinZhangMS 0:f7f1f0d76dd6 192 case IO_STATE_WAIT_FOR_HEADER:
XinZhangMS 0:f7f1f0d76dd6 193 {
XinZhangMS 0:f7f1f0d76dd6 194 size_t i;
XinZhangMS 0:f7f1f0d76dd6 195 bool has_one_match = false;
XinZhangMS 0:f7f1f0d76dd6 196
XinZhangMS 0:f7f1f0d76dd6 197 /* check if any of the headers matches */
XinZhangMS 0:f7f1f0d76dd6 198 for (i = 0; i < header_detect_io_instance->header_detect_entry_count; i++)
XinZhangMS 0:f7f1f0d76dd6 199 {
XinZhangMS 0:f7f1f0d76dd6 200 /* Codes_SRS_HEADER_DETECT_IO_01_067: [ When `on_underlying_io_bytes_received` is called while waiting for header bytes (after the underlying IO was open), the bytes shall be matched against the entries provided in the configuration passed to `header_detect_io_create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 201 /* Codes_SRS_HEADER_DETECT_IO_01_068: [ Header bytes shall be accepted in multiple `on_underlying_io_bytes_received` calls. ]*/
XinZhangMS 0:f7f1f0d76dd6 202 if ((header_detect_io_instance->header_pos < header_detect_io_instance->header_detect_entries[i].header_size) &&
XinZhangMS 0:f7f1f0d76dd6 203 (header_detect_io_instance->header_detect_entries[i].header_bytes[header_detect_io_instance->header_pos] == buffer[0]))
XinZhangMS 0:f7f1f0d76dd6 204 {
XinZhangMS 0:f7f1f0d76dd6 205 has_one_match = true;
XinZhangMS 0:f7f1f0d76dd6 206
XinZhangMS 0:f7f1f0d76dd6 207 if (header_detect_io_instance->header_pos + 1 == header_detect_io_instance->header_detect_entries[i].header_size)
XinZhangMS 0:f7f1f0d76dd6 208 {
XinZhangMS 0:f7f1f0d76dd6 209 /* recognized one header */
XinZhangMS 0:f7f1f0d76dd6 210 if (xio_send(*header_detect_io_instance->last_io, header_detect_io_instance->header_detect_entries[i].header_bytes, header_detect_io_instance->header_detect_entries[i].header_size, on_send_complete, header_detect_io_instance) != 0)
XinZhangMS 0:f7f1f0d76dd6 211 {
XinZhangMS 0:f7f1f0d76dd6 212 LogError("Failed sending header");
XinZhangMS 0:f7f1f0d76dd6 213 header_detect_io_instance->io_state = IO_STATE_NOT_OPEN;
XinZhangMS 0:f7f1f0d76dd6 214 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
XinZhangMS 0:f7f1f0d76dd6 215 }
XinZhangMS 0:f7f1f0d76dd6 216 else
XinZhangMS 0:f7f1f0d76dd6 217 {
XinZhangMS 0:f7f1f0d76dd6 218 // wait for send complete and then start the detected IO open
XinZhangMS 0:f7f1f0d76dd6 219 if (header_detect_io_instance->header_detect_entries[i].io_interface_description == NULL)
XinZhangMS 0:f7f1f0d76dd6 220 {
XinZhangMS 0:f7f1f0d76dd6 221 header_detect_io_instance->io_state = IO_STATE_OPEN;
XinZhangMS 0:f7f1f0d76dd6 222 indicate_open_complete(header_detect_io_instance, IO_OPEN_OK);
XinZhangMS 0:f7f1f0d76dd6 223 }
XinZhangMS 0:f7f1f0d76dd6 224 else
XinZhangMS 0:f7f1f0d76dd6 225 {
XinZhangMS 0:f7f1f0d76dd6 226 SERVER_PROTOCOL_IO_CONFIG server_protocol_io_config;
XinZhangMS 0:f7f1f0d76dd6 227 CHAINED_IO* chained_io = (CHAINED_IO*)malloc(sizeof(CHAINED_IO));
XinZhangMS 0:f7f1f0d76dd6 228 if (chained_io == NULL)
XinZhangMS 0:f7f1f0d76dd6 229 {
XinZhangMS 0:f7f1f0d76dd6 230 LogError("Cannot allocate memory for chained IO");
XinZhangMS 0:f7f1f0d76dd6 231 internal_close(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 232 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
XinZhangMS 0:f7f1f0d76dd6 233 }
XinZhangMS 0:f7f1f0d76dd6 234 else
XinZhangMS 0:f7f1f0d76dd6 235 {
XinZhangMS 0:f7f1f0d76dd6 236 /* Codes_SRS_HEADER_DETECT_IO_01_076: [ If no detected IO was created then the underlying IO in the `SERVER_PROTOCOL_IO_CONFIG` structure shall be set to the `underlying_io` passed in the create arguments. ]*/
XinZhangMS 0:f7f1f0d76dd6 237 /* Codes_SRS_HEADER_DETECT_IO_01_075: [ The underlying IO in the `SERVER_PROTOCOL_IO_CONFIG` structure shall be set to the last detected IO that was created if any. ]*/
XinZhangMS 0:f7f1f0d76dd6 238 server_protocol_io_config.underlying_io = *header_detect_io_instance->last_io;
XinZhangMS 0:f7f1f0d76dd6 239 server_protocol_io_config.on_bytes_received = &chained_io->on_bytes_received;
XinZhangMS 0:f7f1f0d76dd6 240 server_protocol_io_config.on_bytes_received_context = &chained_io->on_bytes_received_context;
XinZhangMS 0:f7f1f0d76dd6 241
XinZhangMS 0:f7f1f0d76dd6 242 /* Codes_SRS_HEADER_DETECT_IO_01_069: [ If a header match was detected on an entry with a non-NULL io handle, a new IO associated shall be created by calling `xio_create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 243 /* Codes_SRS_HEADER_DETECT_IO_01_073: [ The interface description passed to `xio_create` shall be the interface description associated with the detected header. ]*/
XinZhangMS 0:f7f1f0d76dd6 244 /* Codes_SRS_HEADER_DETECT_IO_01_074: [ The IO create parameters shall be a `SERVER_PROTOCOL_IO_CONFIG` structure. ]*/
XinZhangMS 0:f7f1f0d76dd6 245 chained_io->detected_io = xio_create(header_detect_io_instance->header_detect_entries[i].io_interface_description, &server_protocol_io_config);
XinZhangMS 0:f7f1f0d76dd6 246 if (chained_io->detected_io == NULL)
XinZhangMS 0:f7f1f0d76dd6 247 {
XinZhangMS 0:f7f1f0d76dd6 248 /* Codes_SRS_HEADER_DETECT_IO_01_077: [ If `xio_create` fails the header detect IO shall be closed and an error shall be indicated by calling `on_io_open_complete` with `IO_OPEN_ERROR`. ]*/
XinZhangMS 0:f7f1f0d76dd6 249 LogError("Creating detected IO failed");
XinZhangMS 0:f7f1f0d76dd6 250 free(chained_io);
XinZhangMS 0:f7f1f0d76dd6 251 internal_close(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 252 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
XinZhangMS 0:f7f1f0d76dd6 253 }
XinZhangMS 0:f7f1f0d76dd6 254 else
XinZhangMS 0:f7f1f0d76dd6 255 {
XinZhangMS 0:f7f1f0d76dd6 256 /* Codes_SRS_HEADER_DETECT_IO_01_086: [ The newly created IO shall be added to the chain of IOs by calling `singlylinkedlist_add`. ]*/
XinZhangMS 0:f7f1f0d76dd6 257 LIST_ITEM_HANDLE new_list_item = singlylinkedlist_add(header_detect_io_instance->chained_io_list, chained_io);
XinZhangMS 0:f7f1f0d76dd6 258 if (new_list_item == NULL)
XinZhangMS 0:f7f1f0d76dd6 259 {
XinZhangMS 0:f7f1f0d76dd6 260 /* Codes_SRS_HEADER_DETECT_IO_01_084: [ If `singlylinkedlist_add` fails the newly created IO shall be destroyed and an error shall be indicated by calling `on_io_open_complete` with `IO_OPEN_ERROR`. ]*/
XinZhangMS 0:f7f1f0d76dd6 261 LogError("Cannot add detected IO to list");
XinZhangMS 0:f7f1f0d76dd6 262 xio_destroy(chained_io->detected_io);
XinZhangMS 0:f7f1f0d76dd6 263 free(chained_io);
XinZhangMS 0:f7f1f0d76dd6 264 internal_close(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 265 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
XinZhangMS 0:f7f1f0d76dd6 266 }
XinZhangMS 0:f7f1f0d76dd6 267 else
XinZhangMS 0:f7f1f0d76dd6 268 {
XinZhangMS 0:f7f1f0d76dd6 269 /* Codes_SRS_HEADER_DETECT_IO_01_063: [ `header_detect_io_close_async` shall close the last detected IO that was created as a result of matching a header. ]*/
XinZhangMS 0:f7f1f0d76dd6 270 XIO_HANDLE* previous_last_io = header_detect_io_instance->last_io;
XinZhangMS 0:f7f1f0d76dd6 271 header_detect_io_instance->last_io = &chained_io->detected_io;
XinZhangMS 0:f7f1f0d76dd6 272
XinZhangMS 0:f7f1f0d76dd6 273 /* Codes_SRS_HEADER_DETECT_IO_01_083: [ The header detect IO shall wait for opening of the detected IO (signaled by the `on_underlying_io_open_complete`). ]*/
XinZhangMS 0:f7f1f0d76dd6 274 header_detect_io_instance->io_state = IO_STATE_OPENING_DETECTED_IO;
XinZhangMS 0:f7f1f0d76dd6 275
XinZhangMS 0:f7f1f0d76dd6 276 /* Codes_SRS_HEADER_DETECT_IO_01_078: [ The newly create IO shall be open by calling `xio_open`. ]*/
XinZhangMS 0:f7f1f0d76dd6 277 /* Codes_SRS_HEADER_DETECT_IO_01_079: [ The `on_io_open_complete` callback passed to `xio_open` shall be `on_underlying_io_open_complete`. ]*/
XinZhangMS 0:f7f1f0d76dd6 278 /* Codes_SRS_HEADER_DETECT_IO_01_080: [ The `on_bytes_received` callback passed to `xio_open` shall be `on_underlying_io_bytes_received`. ]*/
XinZhangMS 0:f7f1f0d76dd6 279 /* Codes_SRS_HEADER_DETECT_IO_01_081: [ The `on_io_error` callback passed to `xio_open` shall be `on_underlying_io_error`. ]*/
XinZhangMS 0:f7f1f0d76dd6 280 if (xio_open(chained_io->detected_io, on_underlying_io_open_complete, header_detect_io_instance, on_underlying_io_bytes_received, header_detect_io_instance, on_underlying_io_error, header_detect_io_instance) != 0)
XinZhangMS 0:f7f1f0d76dd6 281 {
XinZhangMS 0:f7f1f0d76dd6 282 /* Codes_SRS_HEADER_DETECT_IO_01_082: [ If `xio_open` fails the header detect IO shall be closed and an error shall be indicated by calling `on_io_open_complete` with `IO_OPEN_ERROR`. ]*/
XinZhangMS 0:f7f1f0d76dd6 283 LogError("Opening detected IO failed");
XinZhangMS 0:f7f1f0d76dd6 284 if (singlylinkedlist_remove(header_detect_io_instance->chained_io_list, new_list_item) != 0)
XinZhangMS 0:f7f1f0d76dd6 285 {
XinZhangMS 0:f7f1f0d76dd6 286 LogError("Cannot remove chained IO from list");
XinZhangMS 0:f7f1f0d76dd6 287 }
XinZhangMS 0:f7f1f0d76dd6 288
XinZhangMS 0:f7f1f0d76dd6 289 xio_destroy(chained_io->detected_io);
XinZhangMS 0:f7f1f0d76dd6 290 free(chained_io);
XinZhangMS 0:f7f1f0d76dd6 291 header_detect_io_instance->last_io = previous_last_io;
XinZhangMS 0:f7f1f0d76dd6 292 internal_close(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 293 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
XinZhangMS 0:f7f1f0d76dd6 294 }
XinZhangMS 0:f7f1f0d76dd6 295 else
XinZhangMS 0:f7f1f0d76dd6 296 {
XinZhangMS 0:f7f1f0d76dd6 297 // all OK
XinZhangMS 0:f7f1f0d76dd6 298 }
XinZhangMS 0:f7f1f0d76dd6 299 }
XinZhangMS 0:f7f1f0d76dd6 300 }
XinZhangMS 0:f7f1f0d76dd6 301 }
XinZhangMS 0:f7f1f0d76dd6 302 }
XinZhangMS 0:f7f1f0d76dd6 303 }
XinZhangMS 0:f7f1f0d76dd6 304
XinZhangMS 0:f7f1f0d76dd6 305 break;
XinZhangMS 0:f7f1f0d76dd6 306 }
XinZhangMS 0:f7f1f0d76dd6 307 }
XinZhangMS 0:f7f1f0d76dd6 308 }
XinZhangMS 0:f7f1f0d76dd6 309
XinZhangMS 0:f7f1f0d76dd6 310 if (has_one_match)
XinZhangMS 0:f7f1f0d76dd6 311 {
XinZhangMS 0:f7f1f0d76dd6 312 if (header_detect_io_instance->io_state == IO_STATE_OPENING_DETECTED_IO)
XinZhangMS 0:f7f1f0d76dd6 313 {
XinZhangMS 0:f7f1f0d76dd6 314 header_detect_io_instance->header_pos = 0;
XinZhangMS 0:f7f1f0d76dd6 315 }
XinZhangMS 0:f7f1f0d76dd6 316 else
XinZhangMS 0:f7f1f0d76dd6 317 {
XinZhangMS 0:f7f1f0d76dd6 318 header_detect_io_instance->header_pos++;
XinZhangMS 0:f7f1f0d76dd6 319 }
XinZhangMS 0:f7f1f0d76dd6 320
XinZhangMS 0:f7f1f0d76dd6 321 size--;
XinZhangMS 0:f7f1f0d76dd6 322 buffer++;
XinZhangMS 0:f7f1f0d76dd6 323 }
XinZhangMS 0:f7f1f0d76dd6 324 else
XinZhangMS 0:f7f1f0d76dd6 325 {
XinZhangMS 0:f7f1f0d76dd6 326 /* all header matches failed, we can't proceed, send back to the peer the first header we know of, */
XinZhangMS 0:f7f1f0d76dd6 327 /* then close as per spec. We do not care if we fail sending */
XinZhangMS 0:f7f1f0d76dd6 328 if (xio_send(header_detect_io_instance->underlying_io, header_detect_io_instance->header_detect_entries[0].header_bytes, header_detect_io_instance->header_detect_entries[0].header_size, unchecked_on_send_complete, NULL) != 0)
XinZhangMS 0:f7f1f0d76dd6 329 {
XinZhangMS 0:f7f1f0d76dd6 330 LogError("Failed sending header");
XinZhangMS 0:f7f1f0d76dd6 331 }
XinZhangMS 0:f7f1f0d76dd6 332
XinZhangMS 0:f7f1f0d76dd6 333 internal_close(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 334 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
XinZhangMS 0:f7f1f0d76dd6 335 size = 0;
XinZhangMS 0:f7f1f0d76dd6 336 }
XinZhangMS 0:f7f1f0d76dd6 337
XinZhangMS 0:f7f1f0d76dd6 338 break;
XinZhangMS 0:f7f1f0d76dd6 339 }
XinZhangMS 0:f7f1f0d76dd6 340
XinZhangMS 0:f7f1f0d76dd6 341 case IO_STATE_OPEN:
XinZhangMS 0:f7f1f0d76dd6 342 /* Codes_SRS_HEADER_DETECT_IO_01_089: [ If `on_underlying_io_bytes_received` is called while header detect IO is OPEN the bytes shall be given to the user via the `on_bytes_received` callback that was the `on_bytes_received` callback passed to `header_detect_io_open_async`. ]*/
XinZhangMS 0:f7f1f0d76dd6 343 /* Codes_SRS_HEADER_DETECT_IO_01_090: [ If no detected IOs were created and `on_underlying_io_bytes_received` is called while header detect IO is OPEN, the `on_bytes_received` callback passed to `header_detect_io_open_async` shall be called to indicate the bytes as received. ]*/
XinZhangMS 0:f7f1f0d76dd6 344 header_detect_io_instance->on_bytes_received(header_detect_io_instance->on_bytes_received_context, buffer, size);
XinZhangMS 0:f7f1f0d76dd6 345 size = 0;
XinZhangMS 0:f7f1f0d76dd6 346 break;
XinZhangMS 0:f7f1f0d76dd6 347 }
XinZhangMS 0:f7f1f0d76dd6 348 }
XinZhangMS 0:f7f1f0d76dd6 349 }
XinZhangMS 0:f7f1f0d76dd6 350 }
XinZhangMS 0:f7f1f0d76dd6 351 }
XinZhangMS 0:f7f1f0d76dd6 352
XinZhangMS 0:f7f1f0d76dd6 353 static void on_underlying_io_close_complete(void* context)
XinZhangMS 0:f7f1f0d76dd6 354 {
XinZhangMS 0:f7f1f0d76dd6 355 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)context;
XinZhangMS 0:f7f1f0d76dd6 356
XinZhangMS 0:f7f1f0d76dd6 357 switch (header_detect_io_instance->io_state)
XinZhangMS 0:f7f1f0d76dd6 358 {
XinZhangMS 0:f7f1f0d76dd6 359 default:
XinZhangMS 0:f7f1f0d76dd6 360 break;
XinZhangMS 0:f7f1f0d76dd6 361
XinZhangMS 0:f7f1f0d76dd6 362 case IO_STATE_CLOSING:
XinZhangMS 0:f7f1f0d76dd6 363 /* Codes_SRS_HEADER_DETECT_IO_01_095: [ When `on_underlying_io_open_complete` is called when the IO is closing, it shall destroy all the detected IOs that were created. ]*/
XinZhangMS 0:f7f1f0d76dd6 364 destroy_io_chain(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 365
XinZhangMS 0:f7f1f0d76dd6 366 header_detect_io_instance->io_state = IO_STATE_NOT_OPEN;
XinZhangMS 0:f7f1f0d76dd6 367 indicate_close_complete(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 368 break;
XinZhangMS 0:f7f1f0d76dd6 369
XinZhangMS 0:f7f1f0d76dd6 370 case IO_STATE_WAIT_FOR_HEADER:
XinZhangMS 0:f7f1f0d76dd6 371 case IO_STATE_OPENING_DETECTED_IO:
XinZhangMS 0:f7f1f0d76dd6 372 case IO_STATE_OPENING_UNDERLYING_IO:
XinZhangMS 0:f7f1f0d76dd6 373 header_detect_io_instance->io_state = IO_STATE_NOT_OPEN;
XinZhangMS 0:f7f1f0d76dd6 374 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
XinZhangMS 0:f7f1f0d76dd6 375 break;
XinZhangMS 0:f7f1f0d76dd6 376 }
XinZhangMS 0:f7f1f0d76dd6 377 }
XinZhangMS 0:f7f1f0d76dd6 378
XinZhangMS 0:f7f1f0d76dd6 379 static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT open_result)
XinZhangMS 0:f7f1f0d76dd6 380 {
XinZhangMS 0:f7f1f0d76dd6 381 if (context == NULL)
XinZhangMS 0:f7f1f0d76dd6 382 {
XinZhangMS 0:f7f1f0d76dd6 383 /* Codes_SRS_HEADER_DETECT_IO_01_048: [ If `context` is NULL, `on_underlying_io_open_complete` shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 384 LogError("NULL context");
XinZhangMS 0:f7f1f0d76dd6 385 }
XinZhangMS 0:f7f1f0d76dd6 386 else
XinZhangMS 0:f7f1f0d76dd6 387 {
XinZhangMS 0:f7f1f0d76dd6 388 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)context;
XinZhangMS 0:f7f1f0d76dd6 389
XinZhangMS 0:f7f1f0d76dd6 390 if (open_result == IO_OPEN_OK)
XinZhangMS 0:f7f1f0d76dd6 391 {
XinZhangMS 0:f7f1f0d76dd6 392 switch (header_detect_io_instance->io_state)
XinZhangMS 0:f7f1f0d76dd6 393 {
XinZhangMS 0:f7f1f0d76dd6 394 default:
XinZhangMS 0:f7f1f0d76dd6 395 LogError("on_io_open_complete called in unexpected state: %d", (int)header_detect_io_instance->io_state);
XinZhangMS 0:f7f1f0d76dd6 396 break;
XinZhangMS 0:f7f1f0d76dd6 397
XinZhangMS 0:f7f1f0d76dd6 398 case IO_STATE_OPENING_DETECTED_IO:
XinZhangMS 0:f7f1f0d76dd6 399 case IO_STATE_OPENING_UNDERLYING_IO:
XinZhangMS 0:f7f1f0d76dd6 400 /* Codes_SRS_HEADER_DETECT_IO_01_046: [ When `on_underlying_io_open_complete` is called with `open_result` being `IO_OPEN_OK` while OPENING, the IO shall start monitoring received bytes in order to detect headers. ]*/
XinZhangMS 0:f7f1f0d76dd6 401 header_detect_io_instance->io_state = IO_STATE_WAIT_FOR_HEADER;
XinZhangMS 0:f7f1f0d76dd6 402 break;
XinZhangMS 0:f7f1f0d76dd6 403 }
XinZhangMS 0:f7f1f0d76dd6 404 }
XinZhangMS 0:f7f1f0d76dd6 405 else
XinZhangMS 0:f7f1f0d76dd6 406 {
XinZhangMS 0:f7f1f0d76dd6 407 switch (header_detect_io_instance->io_state)
XinZhangMS 0:f7f1f0d76dd6 408 {
XinZhangMS 0:f7f1f0d76dd6 409 default:
XinZhangMS 0:f7f1f0d76dd6 410 LogError("on_io_open_complete called in unexpected state: %d", (int)header_detect_io_instance->io_state);
XinZhangMS 0:f7f1f0d76dd6 411 break;
XinZhangMS 0:f7f1f0d76dd6 412
XinZhangMS 0:f7f1f0d76dd6 413 case IO_STATE_OPENING_DETECTED_IO:
XinZhangMS 0:f7f1f0d76dd6 414 case IO_STATE_OPENING_UNDERLYING_IO:
XinZhangMS 0:f7f1f0d76dd6 415 /* Codes_SRS_HEADER_DETECT_IO_01_047: [ When `on_underlying_io_open_complete` is called with `open_result` being `IO_OPEN_ERROR` while OPENING, the `on_io_open_complete` callback passed to `header_detect_io_open` shall be called with `IO_OPEN_ERROR`. ]*/
XinZhangMS 0:f7f1f0d76dd6 416 internal_close(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 417
XinZhangMS 0:f7f1f0d76dd6 418 header_detect_io_instance->io_state = IO_STATE_NOT_OPEN;
XinZhangMS 0:f7f1f0d76dd6 419 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
XinZhangMS 0:f7f1f0d76dd6 420 break;
XinZhangMS 0:f7f1f0d76dd6 421 }
XinZhangMS 0:f7f1f0d76dd6 422 }
XinZhangMS 0:f7f1f0d76dd6 423 }
XinZhangMS 0:f7f1f0d76dd6 424 }
XinZhangMS 0:f7f1f0d76dd6 425
XinZhangMS 0:f7f1f0d76dd6 426 static void on_underlying_io_error(void* context)
XinZhangMS 0:f7f1f0d76dd6 427 {
XinZhangMS 0:f7f1f0d76dd6 428 if (context == NULL)
XinZhangMS 0:f7f1f0d76dd6 429 {
XinZhangMS 0:f7f1f0d76dd6 430 /* Codes_SRS_HEADER_DETECT_IO_01_058: [ If `context` is NULL, `on_underlying_io_error` shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 431 LogError("NULL context");
XinZhangMS 0:f7f1f0d76dd6 432 }
XinZhangMS 0:f7f1f0d76dd6 433 else
XinZhangMS 0:f7f1f0d76dd6 434 {
XinZhangMS 0:f7f1f0d76dd6 435 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)context;
XinZhangMS 0:f7f1f0d76dd6 436
XinZhangMS 0:f7f1f0d76dd6 437 switch (header_detect_io_instance->io_state)
XinZhangMS 0:f7f1f0d76dd6 438 {
XinZhangMS 0:f7f1f0d76dd6 439 default:
XinZhangMS 0:f7f1f0d76dd6 440 break;
XinZhangMS 0:f7f1f0d76dd6 441
XinZhangMS 0:f7f1f0d76dd6 442 case IO_STATE_WAIT_FOR_HEADER:
XinZhangMS 0:f7f1f0d76dd6 443 case IO_STATE_OPENING_DETECTED_IO:
XinZhangMS 0:f7f1f0d76dd6 444 case IO_STATE_OPENING_UNDERLYING_IO:
XinZhangMS 0:f7f1f0d76dd6 445 /* Tests_SRS_HEADER_DETECT_IO_01_057: [ When `on_underlying_io_error` is called while OPENING, the IO shall indicate an error by calling `on_io_open_complete` with `IO_OPEN_ERROR` and it shall close the underlying IOs. ]*/
XinZhangMS 0:f7f1f0d76dd6 446 internal_close(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 447 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
XinZhangMS 0:f7f1f0d76dd6 448 break;
XinZhangMS 0:f7f1f0d76dd6 449
XinZhangMS 0:f7f1f0d76dd6 450 case IO_STATE_OPEN:
XinZhangMS 0:f7f1f0d76dd6 451 /* Codes_SRS_HEADER_DETECT_IO_01_059: [ When `on_underlying_io_error` is called while OPEN, the error should be indicated to the consumer by calling `on_io_error` and passing the `on_io_error_context` to it. ]*/
XinZhangMS 0:f7f1f0d76dd6 452 header_detect_io_instance->io_state = IO_STATE_ERROR;
XinZhangMS 0:f7f1f0d76dd6 453 indicate_error(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 454 break;
XinZhangMS 0:f7f1f0d76dd6 455 }
XinZhangMS 0:f7f1f0d76dd6 456 }
XinZhangMS 0:f7f1f0d76dd6 457 }
XinZhangMS 0:f7f1f0d76dd6 458
XinZhangMS 0:f7f1f0d76dd6 459 static CONCRETE_IO_HANDLE header_detect_io_create(void* io_create_parameters)
XinZhangMS 0:f7f1f0d76dd6 460 {
XinZhangMS 0:f7f1f0d76dd6 461 HEADER_DETECT_IO_INSTANCE* result;
XinZhangMS 0:f7f1f0d76dd6 462
XinZhangMS 0:f7f1f0d76dd6 463 if (io_create_parameters == NULL)
XinZhangMS 0:f7f1f0d76dd6 464 {
XinZhangMS 0:f7f1f0d76dd6 465 /* Codes_SRS_HEADER_DETECT_IO_01_003: [ If `io_create_parameters` is NULL, `header_detect_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 466 LogError("NULL io_create_parameters");
XinZhangMS 0:f7f1f0d76dd6 467 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 468 }
XinZhangMS 0:f7f1f0d76dd6 469 else
XinZhangMS 0:f7f1f0d76dd6 470 {
XinZhangMS 0:f7f1f0d76dd6 471 /* Codes_SRS_HEADER_DETECT_IO_01_004: [ `io_create_parameters` shall be used as `HEADER_DETECT_IO_CONFIG*`. ]*/
XinZhangMS 0:f7f1f0d76dd6 472 HEADER_DETECT_IO_CONFIG* header_detect_io_config = (HEADER_DETECT_IO_CONFIG*)io_create_parameters;
XinZhangMS 0:f7f1f0d76dd6 473
XinZhangMS 0:f7f1f0d76dd6 474 /* Codes_SRS_HEADER_DETECT_IO_01_005: [ If the member `header_detect_entry_count` of `HEADER_DETECT_IO_CONFIG` is 0 then `header_detect_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 475 if ((header_detect_io_config->header_detect_entry_count == 0) ||
XinZhangMS 0:f7f1f0d76dd6 476 /* Codes_SRS_HEADER_DETECT_IO_01_006: [ If the member `header_detect_entries` is NULL then `header_detect_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 477 (header_detect_io_config->header_detect_entries == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 478 /* Codes_SRS_HEADER_DETECT_IO_01_007: [ If the member `underlying_io` is NULL then `header_detect_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 479 (header_detect_io_config->underlying_io == NULL))
XinZhangMS 0:f7f1f0d76dd6 480 {
XinZhangMS 0:f7f1f0d76dd6 481 LogError("Bad create parameters: header_detect_entry_count = %u, header_detect_entries = %p, underlying_io = %p",
XinZhangMS 0:f7f1f0d76dd6 482 header_detect_io_config->header_detect_entry_count,
XinZhangMS 0:f7f1f0d76dd6 483 header_detect_io_config->header_detect_entries,
XinZhangMS 0:f7f1f0d76dd6 484 header_detect_io_config->underlying_io);
XinZhangMS 0:f7f1f0d76dd6 485 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 486 }
XinZhangMS 0:f7f1f0d76dd6 487 else
XinZhangMS 0:f7f1f0d76dd6 488 {
XinZhangMS 0:f7f1f0d76dd6 489 size_t i;
XinZhangMS 0:f7f1f0d76dd6 490 bool null_io_found = false;
XinZhangMS 0:f7f1f0d76dd6 491
XinZhangMS 0:f7f1f0d76dd6 492 for (i = 0; i < header_detect_io_config->header_detect_entry_count; i++)
XinZhangMS 0:f7f1f0d76dd6 493 {
XinZhangMS 0:f7f1f0d76dd6 494 /* Codes_SRS_HEADER_DETECT_IO_01_052: [ The `io` member in the in each of the `header_detect_entries` shall be allowed to be NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 495 if (header_detect_io_config->header_detect_entries[i].header.header_bytes == NULL)
XinZhangMS 0:f7f1f0d76dd6 496 {
XinZhangMS 0:f7f1f0d76dd6 497 LogError("header detect entry %u is invalid", (unsigned int)i);
XinZhangMS 0:f7f1f0d76dd6 498 break;
XinZhangMS 0:f7f1f0d76dd6 499 }
XinZhangMS 0:f7f1f0d76dd6 500
XinZhangMS 0:f7f1f0d76dd6 501 if (header_detect_io_config->header_detect_entries[i].io_interface_description == NULL)
XinZhangMS 0:f7f1f0d76dd6 502 {
XinZhangMS 0:f7f1f0d76dd6 503 null_io_found = true;
XinZhangMS 0:f7f1f0d76dd6 504 }
XinZhangMS 0:f7f1f0d76dd6 505 }
XinZhangMS 0:f7f1f0d76dd6 506
XinZhangMS 0:f7f1f0d76dd6 507 if (i < header_detect_io_config->header_detect_entry_count)
XinZhangMS 0:f7f1f0d76dd6 508 {
XinZhangMS 0:f7f1f0d76dd6 509 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 510 }
XinZhangMS 0:f7f1f0d76dd6 511 else if (!null_io_found)
XinZhangMS 0:f7f1f0d76dd6 512 {
XinZhangMS 0:f7f1f0d76dd6 513 /* Codes_SRS_HEADER_DETECT_IO_01_054: [ At least one entry in `header_detect_entries` shall have IO set to NULL, otherwise `header_detect_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 514 LogError("No default header found");
XinZhangMS 0:f7f1f0d76dd6 515 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 516 }
XinZhangMS 0:f7f1f0d76dd6 517 else
XinZhangMS 0:f7f1f0d76dd6 518 {
XinZhangMS 0:f7f1f0d76dd6 519 /* Codes_SRS_HEADER_DETECT_IO_01_001: [ `header_detect_io_create` shall create a new header detect IO instance and on success it shall return a non-NULL handle to the newly created instance. ] */
XinZhangMS 0:f7f1f0d76dd6 520 result = (HEADER_DETECT_IO_INSTANCE*)malloc(sizeof(HEADER_DETECT_IO_INSTANCE));
XinZhangMS 0:f7f1f0d76dd6 521 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 522 {
XinZhangMS 0:f7f1f0d76dd6 523 /* Codes_SRS_HEADER_DETECT_IO_01_002: [ If allocating memory for the header detect IO instance fails, `header_detect_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 524 LogError("Cannot allocate memory for header detect IO");
XinZhangMS 0:f7f1f0d76dd6 525 }
XinZhangMS 0:f7f1f0d76dd6 526 else
XinZhangMS 0:f7f1f0d76dd6 527 {
XinZhangMS 0:f7f1f0d76dd6 528 /* Codes_SRS_HEADER_DETECT_IO_01_009: [ The `header_detect_entries` array shall be copied so that it can be later used when detecting which header was received. ]*/
XinZhangMS 0:f7f1f0d76dd6 529 result->header_detect_entries = (INTERNAL_HEADER_DETECT_ENTRY*)malloc(header_detect_io_config->header_detect_entry_count * sizeof(INTERNAL_HEADER_DETECT_ENTRY));
XinZhangMS 0:f7f1f0d76dd6 530 if (result->header_detect_entries == NULL)
XinZhangMS 0:f7f1f0d76dd6 531 {
XinZhangMS 0:f7f1f0d76dd6 532 free(result);
XinZhangMS 0:f7f1f0d76dd6 533 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 534 }
XinZhangMS 0:f7f1f0d76dd6 535 else
XinZhangMS 0:f7f1f0d76dd6 536 {
XinZhangMS 0:f7f1f0d76dd6 537 result->header_detect_entry_count = header_detect_io_config->header_detect_entry_count;
XinZhangMS 0:f7f1f0d76dd6 538
XinZhangMS 0:f7f1f0d76dd6 539 /* Codes_SRS_HEADER_DETECT_IO_01_009: [ The `header_detect_entries` array shall be copied so that it can be later used when detecting which header was received. ]*/
XinZhangMS 0:f7f1f0d76dd6 540 for (i = 0; i < header_detect_io_config->header_detect_entry_count; i++)
XinZhangMS 0:f7f1f0d76dd6 541 {
XinZhangMS 0:f7f1f0d76dd6 542 result->header_detect_entries[i].header_size = header_detect_io_config->header_detect_entries[i].header.header_size;
XinZhangMS 0:f7f1f0d76dd6 543 result->header_detect_entries[i].header_bytes = (unsigned char*)malloc(result->header_detect_entries[i].header_size);
XinZhangMS 0:f7f1f0d76dd6 544 if (result->header_detect_entries[i].header_bytes == NULL)
XinZhangMS 0:f7f1f0d76dd6 545 {
XinZhangMS 0:f7f1f0d76dd6 546 /* Codes_SRS_HEADER_DETECT_IO_01_010: [ If allocating memory for the `header_detect_entries` or its constituents fails then `header_detect_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 547 break;
XinZhangMS 0:f7f1f0d76dd6 548 }
XinZhangMS 0:f7f1f0d76dd6 549 else
XinZhangMS 0:f7f1f0d76dd6 550 {
XinZhangMS 0:f7f1f0d76dd6 551 /* Codes_SRS_HEADER_DETECT_IO_01_014: [ For each entry in `header_detect_entries` the `header` field shall also be copied. ]*/
XinZhangMS 0:f7f1f0d76dd6 552 (void)memcpy(result->header_detect_entries[i].header_bytes, header_detect_io_config->header_detect_entries[i].header.header_bytes, result->header_detect_entries[i].header_size);
XinZhangMS 0:f7f1f0d76dd6 553 result->header_detect_entries[i].io_interface_description = header_detect_io_config->header_detect_entries[i].io_interface_description;
XinZhangMS 0:f7f1f0d76dd6 554 }
XinZhangMS 0:f7f1f0d76dd6 555 }
XinZhangMS 0:f7f1f0d76dd6 556
XinZhangMS 0:f7f1f0d76dd6 557 if (i < header_detect_io_config->header_detect_entry_count)
XinZhangMS 0:f7f1f0d76dd6 558 {
XinZhangMS 0:f7f1f0d76dd6 559 size_t j;
XinZhangMS 0:f7f1f0d76dd6 560
XinZhangMS 0:f7f1f0d76dd6 561 LogError("Failed copying header detect configuration");
XinZhangMS 0:f7f1f0d76dd6 562 for (j = 0; j < i; j++)
XinZhangMS 0:f7f1f0d76dd6 563 {
XinZhangMS 0:f7f1f0d76dd6 564 free(result->header_detect_entries[j].header_bytes);
XinZhangMS 0:f7f1f0d76dd6 565 }
XinZhangMS 0:f7f1f0d76dd6 566
XinZhangMS 0:f7f1f0d76dd6 567 free(result->header_detect_entries);
XinZhangMS 0:f7f1f0d76dd6 568 free(result);
XinZhangMS 0:f7f1f0d76dd6 569 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 570 }
XinZhangMS 0:f7f1f0d76dd6 571 else
XinZhangMS 0:f7f1f0d76dd6 572 {
XinZhangMS 0:f7f1f0d76dd6 573 /* Codes_SRS_HEADER_DETECT_IO_01_060: [ `header_detect_io_create` shall create a singly linked list by calling `singlylinkedlist_create` where the chained detected IOs shall be stored. ]*/
XinZhangMS 0:f7f1f0d76dd6 574 result->chained_io_list = singlylinkedlist_create();
XinZhangMS 0:f7f1f0d76dd6 575 if (result->chained_io_list == NULL)
XinZhangMS 0:f7f1f0d76dd6 576 {
XinZhangMS 0:f7f1f0d76dd6 577 /* Codes_SRS_HEADER_DETECT_IO_01_065: [ If `singlylinkedlist_create` fails then `header_detect_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 578 LogError("Failed copying header detect configuration");
XinZhangMS 0:f7f1f0d76dd6 579 for (i = 0; i < result->header_detect_entry_count; i++)
XinZhangMS 0:f7f1f0d76dd6 580 {
XinZhangMS 0:f7f1f0d76dd6 581 free(result->header_detect_entries[i].header_bytes);
XinZhangMS 0:f7f1f0d76dd6 582 }
XinZhangMS 0:f7f1f0d76dd6 583
XinZhangMS 0:f7f1f0d76dd6 584 free(result->header_detect_entries);
XinZhangMS 0:f7f1f0d76dd6 585 free(result);
XinZhangMS 0:f7f1f0d76dd6 586 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 587 }
XinZhangMS 0:f7f1f0d76dd6 588 else
XinZhangMS 0:f7f1f0d76dd6 589 {
XinZhangMS 0:f7f1f0d76dd6 590 result->underlying_io = header_detect_io_config->underlying_io;
XinZhangMS 0:f7f1f0d76dd6 591 result->on_io_open_complete = NULL;
XinZhangMS 0:f7f1f0d76dd6 592 result->on_io_close_complete = NULL;
XinZhangMS 0:f7f1f0d76dd6 593 result->on_io_error = NULL;
XinZhangMS 0:f7f1f0d76dd6 594 result->on_bytes_received = NULL;
XinZhangMS 0:f7f1f0d76dd6 595 result->on_io_open_complete_context = NULL;
XinZhangMS 0:f7f1f0d76dd6 596 result->on_io_close_complete_context = NULL;
XinZhangMS 0:f7f1f0d76dd6 597 result->on_io_error_context = NULL;
XinZhangMS 0:f7f1f0d76dd6 598 result->on_bytes_received_context = NULL;
XinZhangMS 0:f7f1f0d76dd6 599
XinZhangMS 0:f7f1f0d76dd6 600 /* Codes_SRS_HEADER_DETECT_IO_01_070: [ If no detected IO was created then `header_detect_io_close_async` shall close the `underlying_io` passed in `header_detect_io_create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 601 result->last_io = &result->underlying_io;
XinZhangMS 0:f7f1f0d76dd6 602
XinZhangMS 0:f7f1f0d76dd6 603 result->io_state = IO_STATE_NOT_OPEN;
XinZhangMS 0:f7f1f0d76dd6 604 }
XinZhangMS 0:f7f1f0d76dd6 605 }
XinZhangMS 0:f7f1f0d76dd6 606 }
XinZhangMS 0:f7f1f0d76dd6 607 }
XinZhangMS 0:f7f1f0d76dd6 608 }
XinZhangMS 0:f7f1f0d76dd6 609 }
XinZhangMS 0:f7f1f0d76dd6 610 }
XinZhangMS 0:f7f1f0d76dd6 611
XinZhangMS 0:f7f1f0d76dd6 612 return result;
XinZhangMS 0:f7f1f0d76dd6 613 }
XinZhangMS 0:f7f1f0d76dd6 614
XinZhangMS 0:f7f1f0d76dd6 615 static void header_detect_io_destroy(CONCRETE_IO_HANDLE header_detect_io)
XinZhangMS 0:f7f1f0d76dd6 616 {
XinZhangMS 0:f7f1f0d76dd6 617 if (header_detect_io == NULL)
XinZhangMS 0:f7f1f0d76dd6 618 {
XinZhangMS 0:f7f1f0d76dd6 619 /* Codes_SRS_HEADER_DETECT_IO_01_012: [ If `header_detect_io` is NULL, `header_detect_io_destroy` shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 620 LogError("NULL header_detect_io");
XinZhangMS 0:f7f1f0d76dd6 621 }
XinZhangMS 0:f7f1f0d76dd6 622 else
XinZhangMS 0:f7f1f0d76dd6 623 {
XinZhangMS 0:f7f1f0d76dd6 624 size_t i;
XinZhangMS 0:f7f1f0d76dd6 625 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
XinZhangMS 0:f7f1f0d76dd6 626
XinZhangMS 0:f7f1f0d76dd6 627 if (header_detect_io_instance->io_state != IO_STATE_NOT_OPEN)
XinZhangMS 0:f7f1f0d76dd6 628 {
XinZhangMS 0:f7f1f0d76dd6 629 /* Codes_SRS_HEADER_DETECT_IO_01_062: [ If the IO is still open when `header_detect_io_destroy` is called, all actions normally executed when closing the IO shall also be executed. ]*/
XinZhangMS 0:f7f1f0d76dd6 630 internal_close(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 631 }
XinZhangMS 0:f7f1f0d76dd6 632
XinZhangMS 0:f7f1f0d76dd6 633 /* Codes_SRS_HEADER_DETECT_IO_01_061: [ `header_detect_io_destroy` shall destroy the chained IO list by calling `singlylinkedlist_destroy`. ]*/
XinZhangMS 0:f7f1f0d76dd6 634 singlylinkedlist_destroy(header_detect_io_instance->chained_io_list);
XinZhangMS 0:f7f1f0d76dd6 635
XinZhangMS 0:f7f1f0d76dd6 636 /* Codes_SRS_HEADER_DETECT_IO_01_011: [ `header_detect_io_destroy` shall free all resources associated with the `header_detect_io` handle. ]*/
XinZhangMS 0:f7f1f0d76dd6 637 for (i = 0; i < header_detect_io_instance->header_detect_entry_count; i++)
XinZhangMS 0:f7f1f0d76dd6 638 {
XinZhangMS 0:f7f1f0d76dd6 639 /* Codes_SRS_HEADER_DETECT_IO_01_013: [ `header_detect_io_destroy` shall free the memory allocated for the `header_detect_entries`. ]*/
XinZhangMS 0:f7f1f0d76dd6 640 free(header_detect_io_instance->header_detect_entries[i].header_bytes);
XinZhangMS 0:f7f1f0d76dd6 641 }
XinZhangMS 0:f7f1f0d76dd6 642
XinZhangMS 0:f7f1f0d76dd6 643 free(header_detect_io_instance->header_detect_entries);
XinZhangMS 0:f7f1f0d76dd6 644
XinZhangMS 0:f7f1f0d76dd6 645 free(header_detect_io);
XinZhangMS 0:f7f1f0d76dd6 646 }
XinZhangMS 0:f7f1f0d76dd6 647 }
XinZhangMS 0:f7f1f0d76dd6 648
XinZhangMS 0:f7f1f0d76dd6 649 static int header_detect_io_open_async(CONCRETE_IO_HANDLE header_detect_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 650 {
XinZhangMS 0:f7f1f0d76dd6 651 int result;
XinZhangMS 0:f7f1f0d76dd6 652
XinZhangMS 0:f7f1f0d76dd6 653 if ((header_detect_io == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 654 (on_io_open_complete == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 655 (on_bytes_received == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 656 (on_io_error == NULL))
XinZhangMS 0:f7f1f0d76dd6 657 {
XinZhangMS 0:f7f1f0d76dd6 658 /* Codes_SRS_HEADER_DETECT_IO_01_021: [ If `header_detect_io`, `on_io_open_complete`, `on_bytes_received` or `on_io_error` is NULL, `header_detect_io_open_async` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 659 LogError("Bad arguments: header_detect_io = %p, on_io_open_complete = %p, on_bytes_received = %p, on_io_error = %p",
XinZhangMS 0:f7f1f0d76dd6 660 header_detect_io, on_io_open_complete, on_bytes_received, on_io_error);
XinZhangMS 0:f7f1f0d76dd6 661 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 662 }
XinZhangMS 0:f7f1f0d76dd6 663 else
XinZhangMS 0:f7f1f0d76dd6 664 {
XinZhangMS 0:f7f1f0d76dd6 665 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
XinZhangMS 0:f7f1f0d76dd6 666
XinZhangMS 0:f7f1f0d76dd6 667 if (header_detect_io_instance->io_state != IO_STATE_NOT_OPEN)
XinZhangMS 0:f7f1f0d76dd6 668 {
XinZhangMS 0:f7f1f0d76dd6 669 /* Codes_SRS_HEADER_DETECT_IO_01_020: [ If the IO is already OPEN or OPENING then `header_detect_io_open_async` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 670 LogError("Already OPEN");
XinZhangMS 0:f7f1f0d76dd6 671 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 672 }
XinZhangMS 0:f7f1f0d76dd6 673 else
XinZhangMS 0:f7f1f0d76dd6 674 {
XinZhangMS 0:f7f1f0d76dd6 675 header_detect_io_instance->on_bytes_received = on_bytes_received;
XinZhangMS 0:f7f1f0d76dd6 676 header_detect_io_instance->on_io_open_complete = on_io_open_complete;
XinZhangMS 0:f7f1f0d76dd6 677 header_detect_io_instance->on_io_error = on_io_error;
XinZhangMS 0:f7f1f0d76dd6 678 header_detect_io_instance->on_bytes_received_context = on_bytes_received_context;
XinZhangMS 0:f7f1f0d76dd6 679 header_detect_io_instance->on_io_open_complete_context = on_io_open_complete_context;
XinZhangMS 0:f7f1f0d76dd6 680 header_detect_io_instance->on_io_error_context = on_io_error_context;
XinZhangMS 0:f7f1f0d76dd6 681
XinZhangMS 0:f7f1f0d76dd6 682 header_detect_io_instance->io_state = IO_STATE_OPENING_UNDERLYING_IO;
XinZhangMS 0:f7f1f0d76dd6 683 header_detect_io_instance->header_pos = 0;
XinZhangMS 0:f7f1f0d76dd6 684
XinZhangMS 0:f7f1f0d76dd6 685 /* Codes_SRS_HEADER_DETECT_IO_01_015: [ `header_detect_io_open_async` shall open the underlying IO by calling `xio_open` and passing to it: ]*/
XinZhangMS 0:f7f1f0d76dd6 686 /* Codes_SRS_HEADER_DETECT_IO_01_016: [ - `xio` shall be the `underlying_io` member of the `io_create_parameters` passed to `header_detect_io_create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 687 /* Codes_SRS_HEADER_DETECT_IO_01_017: [ - `on_io_open_complete`, `on_io_open_complete_context`, `on_bytes_received`, `on_bytes_received_context`, `on_error` and `on_error_context` shall be set to implementation specific values of `header_detect_io`. ]*/
XinZhangMS 0:f7f1f0d76dd6 688 if (xio_open(header_detect_io_instance->underlying_io, on_underlying_io_open_complete, header_detect_io_instance, on_underlying_io_bytes_received, header_detect_io_instance, on_underlying_io_error, header_detect_io_instance) != 0)
XinZhangMS 0:f7f1f0d76dd6 689 {
XinZhangMS 0:f7f1f0d76dd6 690 /* Codes_SRS_HEADER_DETECT_IO_01_019: [ If `xio_open` fails, `header_detect_io_open_async` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 691 LogError("xio_open failed");
XinZhangMS 0:f7f1f0d76dd6 692 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 693 }
XinZhangMS 0:f7f1f0d76dd6 694 else
XinZhangMS 0:f7f1f0d76dd6 695 {
XinZhangMS 0:f7f1f0d76dd6 696 /* Codes_SRS_HEADER_DETECT_IO_01_018: [ On success `header_detect_io_open_async` shall return 0. ]*/
XinZhangMS 0:f7f1f0d76dd6 697 result = 0;
XinZhangMS 0:f7f1f0d76dd6 698 }
XinZhangMS 0:f7f1f0d76dd6 699 }
XinZhangMS 0:f7f1f0d76dd6 700 }
XinZhangMS 0:f7f1f0d76dd6 701
XinZhangMS 0:f7f1f0d76dd6 702 return result;
XinZhangMS 0:f7f1f0d76dd6 703 }
XinZhangMS 0:f7f1f0d76dd6 704
XinZhangMS 0:f7f1f0d76dd6 705 static int header_detect_io_close_async(CONCRETE_IO_HANDLE header_detect_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* callback_context)
XinZhangMS 0:f7f1f0d76dd6 706 {
XinZhangMS 0:f7f1f0d76dd6 707 int result;
XinZhangMS 0:f7f1f0d76dd6 708
XinZhangMS 0:f7f1f0d76dd6 709 if (header_detect_io == NULL)
XinZhangMS 0:f7f1f0d76dd6 710 {
XinZhangMS 0:f7f1f0d76dd6 711 /* Codes_SRS_HEADER_DETECT_IO_01_026: [ If `header_detect_io` is NULL, `header_detect_io_close_async` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 712 LogError("NULL header_detect_io");
XinZhangMS 0:f7f1f0d76dd6 713 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 714 }
XinZhangMS 0:f7f1f0d76dd6 715 else
XinZhangMS 0:f7f1f0d76dd6 716 {
XinZhangMS 0:f7f1f0d76dd6 717 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
XinZhangMS 0:f7f1f0d76dd6 718
XinZhangMS 0:f7f1f0d76dd6 719 /* Codes_SRS_HEADER_DETECT_IO_01_027: [ If the IO is not OPEN (open has not been called or close has been completely carried out) `header_detect_io_close_async` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 720 if ((header_detect_io_instance->io_state == IO_STATE_OPENING_UNDERLYING_IO) ||
XinZhangMS 0:f7f1f0d76dd6 721 (header_detect_io_instance->io_state == IO_STATE_OPENING_DETECTED_IO) ||
XinZhangMS 0:f7f1f0d76dd6 722 (header_detect_io_instance->io_state == IO_STATE_WAIT_FOR_HEADER))
XinZhangMS 0:f7f1f0d76dd6 723 {
XinZhangMS 0:f7f1f0d76dd6 724 /* Codes_SRS_HEADER_DETECT_IO_01_028: [ If the IO is OPENING (`header_detect_io_open_async` has been called, but no header has been detected yet), `header_detect_io_close_async` shall close the underlying IO and call `on_io_open_complete` with `IO_OPEN_CANCELLED`. ]*/
XinZhangMS 0:f7f1f0d76dd6 725 (void)internal_close(header_detect_io_instance);
XinZhangMS 0:f7f1f0d76dd6 726 header_detect_io_instance->on_io_open_complete(header_detect_io_instance->on_io_open_complete_context, IO_OPEN_CANCELLED);
XinZhangMS 0:f7f1f0d76dd6 727 result = 0;
XinZhangMS 0:f7f1f0d76dd6 728 }
XinZhangMS 0:f7f1f0d76dd6 729 else if ((header_detect_io_instance->io_state == IO_STATE_NOT_OPEN) ||
XinZhangMS 0:f7f1f0d76dd6 730 /* Codes_SRS_HEADER_DETECT_IO_01_053: [ If the IO is CLOSING then `header_detect_io_close_async` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 731 (header_detect_io_instance->io_state == IO_STATE_CLOSING))
XinZhangMS 0:f7f1f0d76dd6 732 {
XinZhangMS 0:f7f1f0d76dd6 733 LogError("Not open");
XinZhangMS 0:f7f1f0d76dd6 734 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 735 }
XinZhangMS 0:f7f1f0d76dd6 736 else
XinZhangMS 0:f7f1f0d76dd6 737 {
XinZhangMS 0:f7f1f0d76dd6 738 header_detect_io_instance->io_state = IO_STATE_CLOSING;
XinZhangMS 0:f7f1f0d76dd6 739 header_detect_io_instance->on_io_close_complete = on_io_close_complete;
XinZhangMS 0:f7f1f0d76dd6 740 header_detect_io_instance->on_io_close_complete_context = callback_context;
XinZhangMS 0:f7f1f0d76dd6 741
XinZhangMS 0:f7f1f0d76dd6 742 /* Codes_SRS_HEADER_DETECT_IO_01_022: [ `header_detect_io_close_async` shall close the underlying IO by calling `xio_close` and passing to it: ]*/
XinZhangMS 0:f7f1f0d76dd6 743 /* Codes_SRS_HEADER_DETECT_IO_01_023: [ - `xio` shall be the `underlying_io` member of the `io_create_parameters` passed to `header_detect_io_create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 744 /* Codes_SRS_HEADER_DETECT_IO_01_024: [ - `on_io_close_complete` shall be set to implementation specific values of `header_detect_io`. ]*/
XinZhangMS 0:f7f1f0d76dd6 745 if (xio_close(*header_detect_io_instance->last_io, on_underlying_io_close_complete, header_detect_io_instance) != 0)
XinZhangMS 0:f7f1f0d76dd6 746 {
XinZhangMS 0:f7f1f0d76dd6 747 /* Codes_SRS_HEADER_DETECT_IO_01_092: [ If `xio_close` fails `header_detect_io_close_async` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 748 LogError("xio_close failed");
XinZhangMS 0:f7f1f0d76dd6 749 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 750 }
XinZhangMS 0:f7f1f0d76dd6 751 else
XinZhangMS 0:f7f1f0d76dd6 752 {
XinZhangMS 0:f7f1f0d76dd6 753 /* Codes_SRS_HEADER_DETECT_IO_01_025: [ On success `header_detect_io_close_async` shall return 0. ]*/
XinZhangMS 0:f7f1f0d76dd6 754 result = 0;
XinZhangMS 0:f7f1f0d76dd6 755 }
XinZhangMS 0:f7f1f0d76dd6 756 }
XinZhangMS 0:f7f1f0d76dd6 757 }
XinZhangMS 0:f7f1f0d76dd6 758
XinZhangMS 0:f7f1f0d76dd6 759 return result;
XinZhangMS 0:f7f1f0d76dd6 760 }
XinZhangMS 0:f7f1f0d76dd6 761
XinZhangMS 0:f7f1f0d76dd6 762 static int header_detect_io_send_async(CONCRETE_IO_HANDLE header_detect_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* callback_context)
XinZhangMS 0:f7f1f0d76dd6 763 {
XinZhangMS 0:f7f1f0d76dd6 764 int result;
XinZhangMS 0:f7f1f0d76dd6 765
XinZhangMS 0:f7f1f0d76dd6 766 /* Codes_SRS_HEADER_DETECT_IO_01_055: [ `on_send_complete` and `callback_context` shall be allowed to be NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 767 if ((header_detect_io == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 768 (buffer == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 769 /* Codes_SRS_HEADER_DETECT_IO_01_034: [ If `size` is 0, `header_detect_io_send_async` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 770 (size == 0))
XinZhangMS 0:f7f1f0d76dd6 771 {
XinZhangMS 0:f7f1f0d76dd6 772 /* Codes_SRS_HEADER_DETECT_IO_01_033: [ If `header_detect_io` or `buffer` is NULL, `header_detect_io_send_async` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 773 LogError("Bad arguments: header_detect_io = %p, buffer = %p, size = %u",
XinZhangMS 0:f7f1f0d76dd6 774 header_detect_io, buffer, (unsigned int)size);
XinZhangMS 0:f7f1f0d76dd6 775 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 776 }
XinZhangMS 0:f7f1f0d76dd6 777 else
XinZhangMS 0:f7f1f0d76dd6 778 {
XinZhangMS 0:f7f1f0d76dd6 779 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
XinZhangMS 0:f7f1f0d76dd6 780
XinZhangMS 0:f7f1f0d76dd6 781 if (header_detect_io_instance->io_state != IO_STATE_OPEN)
XinZhangMS 0:f7f1f0d76dd6 782 {
XinZhangMS 0:f7f1f0d76dd6 783 /* Codes_SRS_HEADER_DETECT_IO_01_093: [ `header_detect_io_send_async` when the IO is not open shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 784 LogError("header_detect_io not OPEN");
XinZhangMS 0:f7f1f0d76dd6 785 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 786 }
XinZhangMS 0:f7f1f0d76dd6 787 else
XinZhangMS 0:f7f1f0d76dd6 788 {
XinZhangMS 0:f7f1f0d76dd6 789 /* Codes_SRS_HEADER_DETECT_IO_01_029: [ If no detected IO was created, `header_detect_io_send_async` shall send the bytes to the underlying IO passed via `header_detect_io_create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 790 /* Codes_SRS_HEADER_DETECT_IO_01_030: [ The `buffer`, `size`, `on_send_complete` and `callback_context` shall be passed as is to `xio_send`. ]*/
XinZhangMS 0:f7f1f0d76dd6 791 /* Codes_SRS_HEADER_DETECT_IO_01_071: [ If the header IO is open `header_detect_io_send_async` shall send the bytes to the last detected IO by calling `xio_send` that was created as result of matching a header. ]*/
XinZhangMS 0:f7f1f0d76dd6 792 if (xio_send(*header_detect_io_instance->last_io, buffer, size, on_send_complete, callback_context) != 0)
XinZhangMS 0:f7f1f0d76dd6 793 {
XinZhangMS 0:f7f1f0d76dd6 794 LogError("xio_send failed");
XinZhangMS 0:f7f1f0d76dd6 795 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 796 }
XinZhangMS 0:f7f1f0d76dd6 797 else
XinZhangMS 0:f7f1f0d76dd6 798 {
XinZhangMS 0:f7f1f0d76dd6 799 /* Codes_SRS_HEADER_DETECT_IO_01_031: [ On success `header_detect_io_send_async` shall return 0. ]*/
XinZhangMS 0:f7f1f0d76dd6 800 result = 0;
XinZhangMS 0:f7f1f0d76dd6 801 }
XinZhangMS 0:f7f1f0d76dd6 802 }
XinZhangMS 0:f7f1f0d76dd6 803 }
XinZhangMS 0:f7f1f0d76dd6 804
XinZhangMS 0:f7f1f0d76dd6 805 return result;
XinZhangMS 0:f7f1f0d76dd6 806 }
XinZhangMS 0:f7f1f0d76dd6 807
XinZhangMS 0:f7f1f0d76dd6 808 static void header_detect_io_dowork(CONCRETE_IO_HANDLE header_detect_io)
XinZhangMS 0:f7f1f0d76dd6 809 {
XinZhangMS 0:f7f1f0d76dd6 810 if (header_detect_io == NULL)
XinZhangMS 0:f7f1f0d76dd6 811 {
XinZhangMS 0:f7f1f0d76dd6 812 /* Codes_SRS_HEADER_DETECT_IO_01_036: [ If `header_detect_io` is NULL, `header_detect_io_dowork` shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 813 LogError("NULL header_detect_io");
XinZhangMS 0:f7f1f0d76dd6 814 }
XinZhangMS 0:f7f1f0d76dd6 815 else
XinZhangMS 0:f7f1f0d76dd6 816 {
XinZhangMS 0:f7f1f0d76dd6 817 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
XinZhangMS 0:f7f1f0d76dd6 818
XinZhangMS 0:f7f1f0d76dd6 819 /* Codes_SRS_HEADER_DETECT_IO_01_037: [ No work shall be scheduled if `header_detect_io` is not OPEN or in ERROR (an error has been indicated to the user). ]*/
XinZhangMS 0:f7f1f0d76dd6 820 if ((header_detect_io_instance->io_state != IO_STATE_NOT_OPEN) &&
XinZhangMS 0:f7f1f0d76dd6 821 (header_detect_io_instance->io_state != IO_STATE_ERROR))
XinZhangMS 0:f7f1f0d76dd6 822 {
XinZhangMS 0:f7f1f0d76dd6 823 /* Codes_SRS_HEADER_DETECT_IO_01_056: [ `header_detect_io_dowork` shall call `xio_dowork` for all detected IOs created as a result of matching headers. ]*/
XinZhangMS 0:f7f1f0d76dd6 824 LIST_ITEM_HANDLE list_item = singlylinkedlist_get_head_item(header_detect_io_instance->chained_io_list);
XinZhangMS 0:f7f1f0d76dd6 825 while (list_item != NULL)
XinZhangMS 0:f7f1f0d76dd6 826 {
XinZhangMS 0:f7f1f0d76dd6 827 CHAINED_IO* chained_io = (CHAINED_IO*)singlylinkedlist_item_get_value(list_item);
XinZhangMS 0:f7f1f0d76dd6 828 xio_dowork(chained_io->detected_io);
XinZhangMS 0:f7f1f0d76dd6 829
XinZhangMS 0:f7f1f0d76dd6 830 list_item = singlylinkedlist_get_next_item(list_item);
XinZhangMS 0:f7f1f0d76dd6 831 }
XinZhangMS 0:f7f1f0d76dd6 832
XinZhangMS 0:f7f1f0d76dd6 833 /* Codes_SRS_HEADER_DETECT_IO_01_035: [ `header_detect_io_dowork` shall schedule work for the underlying IO associated with `header_detect_io` by calling `xio_dowork` and passing as argument the `underlying_io` member of the `io_create_parameters` passed to `header_detect_io_create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 834 xio_dowork(header_detect_io_instance->underlying_io);
XinZhangMS 0:f7f1f0d76dd6 835 }
XinZhangMS 0:f7f1f0d76dd6 836 }
XinZhangMS 0:f7f1f0d76dd6 837 }
XinZhangMS 0:f7f1f0d76dd6 838
XinZhangMS 0:f7f1f0d76dd6 839 static int header_detect_io_set_option(CONCRETE_IO_HANDLE header_detect_io, const char* option_name, const void* value)
XinZhangMS 0:f7f1f0d76dd6 840 {
XinZhangMS 0:f7f1f0d76dd6 841 int result;
XinZhangMS 0:f7f1f0d76dd6 842
XinZhangMS 0:f7f1f0d76dd6 843 if ((header_detect_io == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 844 (option_name == NULL))
XinZhangMS 0:f7f1f0d76dd6 845 {
XinZhangMS 0:f7f1f0d76dd6 846 /* Codes_SRS_HEADER_DETECT_IO_01_044: [ If `header_detect_io` or `optionName` is NULL, `header_detect_io_set_option` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 847 LogError("NULL header_detect_io");
XinZhangMS 0:f7f1f0d76dd6 848 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 849 }
XinZhangMS 0:f7f1f0d76dd6 850 else
XinZhangMS 0:f7f1f0d76dd6 851 {
XinZhangMS 0:f7f1f0d76dd6 852 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
XinZhangMS 0:f7f1f0d76dd6 853
XinZhangMS 0:f7f1f0d76dd6 854 /* Codes_SRS_HEADER_DETECT_IO_01_042: [ If no detected IO was created `header_detect_io_set_option` shall pass any option to the underlying IO by calling `xio_setoption` and passing as IO handle the `underlying_io` member of the `io_create_parameters` passed to `header_detect_io_create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 855 /* Codes_SRS_HEADER_DETECT_IO_01_072: [ If any detected IO was created, `header_detect_io_set_option` shall pass any option to the last detected IO by calling `xio_setoption` and passing as IO handle the `underlying_io` member of the `io_create_parameters` passed to `header_detect_io_create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 856 if (xio_setoption(*header_detect_io_instance->last_io, option_name, value) != 0)
XinZhangMS 0:f7f1f0d76dd6 857 {
XinZhangMS 0:f7f1f0d76dd6 858 /* Codes_SRS_HEADER_DETECT_IO_01_045: [ If `xio_setoption` fails, `header_detect_io_set_option` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 859 LogError("Setting the option on the underlying IO failed");
XinZhangMS 0:f7f1f0d76dd6 860 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 861 }
XinZhangMS 0:f7f1f0d76dd6 862 else
XinZhangMS 0:f7f1f0d76dd6 863 {
XinZhangMS 0:f7f1f0d76dd6 864 /* Codes_SRS_HEADER_DETECT_IO_01_043: [ On success, `header_detect_io_set_option` shall return 0. ]*/
XinZhangMS 0:f7f1f0d76dd6 865 result = 0;
XinZhangMS 0:f7f1f0d76dd6 866 }
XinZhangMS 0:f7f1f0d76dd6 867 }
XinZhangMS 0:f7f1f0d76dd6 868
XinZhangMS 0:f7f1f0d76dd6 869 return result;
XinZhangMS 0:f7f1f0d76dd6 870 }
XinZhangMS 0:f7f1f0d76dd6 871
XinZhangMS 0:f7f1f0d76dd6 872 /*this function will clone an option given by name and value*/
XinZhangMS 0:f7f1f0d76dd6 873 static void* header_detect_io_clone_option(const char* name, const void* value)
XinZhangMS 0:f7f1f0d76dd6 874 {
XinZhangMS 0:f7f1f0d76dd6 875 (void)name;
XinZhangMS 0:f7f1f0d76dd6 876 (void)value;
XinZhangMS 0:f7f1f0d76dd6 877 return NULL;
XinZhangMS 0:f7f1f0d76dd6 878 }
XinZhangMS 0:f7f1f0d76dd6 879
XinZhangMS 0:f7f1f0d76dd6 880 /*this function destroys an option previously created*/
XinZhangMS 0:f7f1f0d76dd6 881 static void header_detect_io_destroy_option(const char* name, const void* value)
XinZhangMS 0:f7f1f0d76dd6 882 {
XinZhangMS 0:f7f1f0d76dd6 883 (void)name;
XinZhangMS 0:f7f1f0d76dd6 884 (void)value;
XinZhangMS 0:f7f1f0d76dd6 885 }
XinZhangMS 0:f7f1f0d76dd6 886
XinZhangMS 0:f7f1f0d76dd6 887 static OPTIONHANDLER_HANDLE header_detect_io_retrieve_options(CONCRETE_IO_HANDLE header_detect_io)
XinZhangMS 0:f7f1f0d76dd6 888 {
XinZhangMS 0:f7f1f0d76dd6 889 OPTIONHANDLER_HANDLE result;
XinZhangMS 0:f7f1f0d76dd6 890
XinZhangMS 0:f7f1f0d76dd6 891 if (header_detect_io == NULL)
XinZhangMS 0:f7f1f0d76dd6 892 {
XinZhangMS 0:f7f1f0d76dd6 893 /* Codes_SRS_HEADER_DETECT_IO_01_041: [ If `header_detect_io` is NULL, `header_detect_io_retrieve_options` shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 894 LogError("NULL header_detect_io");
XinZhangMS 0:f7f1f0d76dd6 895 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 896 }
XinZhangMS 0:f7f1f0d76dd6 897 else
XinZhangMS 0:f7f1f0d76dd6 898 {
XinZhangMS 0:f7f1f0d76dd6 899 /* Codes_SRS_HEADER_DETECT_IO_01_038: [ `header_detect_io_retrieve_options` shall create a new `OPTIONHANDLER_HANDLE` by calling `OptionHandler_Create` and on success it shall return a non-NULL handle to the newly created option handler. ]*/
XinZhangMS 0:f7f1f0d76dd6 900 result = OptionHandler_Create(header_detect_io_clone_option, header_detect_io_destroy_option, header_detect_io_set_option);
XinZhangMS 0:f7f1f0d76dd6 901 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 902 {
XinZhangMS 0:f7f1f0d76dd6 903 /* Codes_SRS_HEADER_DETECT_IO_01_040: [ If `OptionHandler_Create` fails, `header_detect_io_retrieve_options` shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 904 LogError("unable to OptionHandler_Create");
XinZhangMS 0:f7f1f0d76dd6 905 /*return as is*/
XinZhangMS 0:f7f1f0d76dd6 906 }
XinZhangMS 0:f7f1f0d76dd6 907 else
XinZhangMS 0:f7f1f0d76dd6 908 {
XinZhangMS 0:f7f1f0d76dd6 909 /*insert here work to add the options to "result" handle*/
XinZhangMS 0:f7f1f0d76dd6 910 /* Codes_SRS_HEADER_DETECT_IO_01_039: [ No options shall be added to the newly created option handler. ]*/
XinZhangMS 0:f7f1f0d76dd6 911 }
XinZhangMS 0:f7f1f0d76dd6 912 }
XinZhangMS 0:f7f1f0d76dd6 913 return result;
XinZhangMS 0:f7f1f0d76dd6 914 }
XinZhangMS 0:f7f1f0d76dd6 915
XinZhangMS 0:f7f1f0d76dd6 916 static const IO_INTERFACE_DESCRIPTION header_detect_io_interface_description =
XinZhangMS 0:f7f1f0d76dd6 917 {
XinZhangMS 0:f7f1f0d76dd6 918 header_detect_io_retrieve_options,
XinZhangMS 0:f7f1f0d76dd6 919 header_detect_io_create,
XinZhangMS 0:f7f1f0d76dd6 920 header_detect_io_destroy,
XinZhangMS 0:f7f1f0d76dd6 921 header_detect_io_open_async,
XinZhangMS 0:f7f1f0d76dd6 922 header_detect_io_close_async,
XinZhangMS 0:f7f1f0d76dd6 923 header_detect_io_send_async,
XinZhangMS 0:f7f1f0d76dd6 924 header_detect_io_dowork,
XinZhangMS 0:f7f1f0d76dd6 925 header_detect_io_set_option
XinZhangMS 0:f7f1f0d76dd6 926 };
XinZhangMS 0:f7f1f0d76dd6 927
XinZhangMS 0:f7f1f0d76dd6 928 const IO_INTERFACE_DESCRIPTION* header_detect_io_get_interface_description(void)
XinZhangMS 0:f7f1f0d76dd6 929 {
XinZhangMS 0:f7f1f0d76dd6 930 return &header_detect_io_interface_description;
XinZhangMS 0:f7f1f0d76dd6 931 }
XinZhangMS 0:f7f1f0d76dd6 932
XinZhangMS 0:f7f1f0d76dd6 933 static const AMQP_HEADER amqp_header =
XinZhangMS 0:f7f1f0d76dd6 934 {
XinZhangMS 0:f7f1f0d76dd6 935 amqp_header_bytes,
XinZhangMS 0:f7f1f0d76dd6 936 sizeof(amqp_header_bytes)
XinZhangMS 0:f7f1f0d76dd6 937 };
XinZhangMS 0:f7f1f0d76dd6 938
XinZhangMS 0:f7f1f0d76dd6 939 static const AMQP_HEADER sasl_amqp_header =
XinZhangMS 0:f7f1f0d76dd6 940 {
XinZhangMS 0:f7f1f0d76dd6 941 sasl_amqp_header_bytes,
XinZhangMS 0:f7f1f0d76dd6 942 sizeof(sasl_amqp_header_bytes)
XinZhangMS 0:f7f1f0d76dd6 943 };
XinZhangMS 0:f7f1f0d76dd6 944
XinZhangMS 0:f7f1f0d76dd6 945 AMQP_HEADER header_detect_io_get_amqp_header(void)
XinZhangMS 0:f7f1f0d76dd6 946 {
XinZhangMS 0:f7f1f0d76dd6 947 /* Codes_SRS_HEADER_DETECT_IO_01_091: [ `header_detect_io_get_amqp_header` shall return a structure that should point to a buffer that contains the bytes { 'A', 'M', 'Q', 'P', 0, 1, 0, 0 }. ]*/
XinZhangMS 0:f7f1f0d76dd6 948 return amqp_header;
XinZhangMS 0:f7f1f0d76dd6 949 }
XinZhangMS 0:f7f1f0d76dd6 950
XinZhangMS 0:f7f1f0d76dd6 951 AMQP_HEADER header_detect_io_get_sasl_amqp_header(void)
XinZhangMS 0:f7f1f0d76dd6 952 {
XinZhangMS 0:f7f1f0d76dd6 953 /* Codes_SRS_HEADER_DETECT_IO_01_091: [ `header_detect_io_get_sasl_amqp_header` shall return a structure that should point to a buffer that contains the bytes { 'A', 'M', 'Q', 'P', 3, 1, 0, 0 }. ]*/
XinZhangMS 0:f7f1f0d76dd6 954 return sasl_amqp_header;
XinZhangMS 0:f7f1f0d76dd6 955 }