A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

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

Who changed what in which revision?

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