A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Thu Oct 04 09:16:13 2018 -0700
Revision:
47:365a93fdb5bb
Parent:
43:4c1e4e94cdd3
1.2.10

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
AzureIoTClient 43:4c1e4e94cdd3 135 // This callback usage needs to be either verified and commented or integrated into
AzureIoTClient 38:7631b92cc772 136 // the state machine.
AzureIoTClient 38:7631b92cc772 137 static void unchecked_on_send_complete(void* context, IO_SEND_RESULT send_result)
AzureIoTClient 38:7631b92cc772 138 {
AzureIoTClient 38:7631b92cc772 139 (void)context;
AzureIoTClient 38:7631b92cc772 140 (void)send_result;
AzureIoTClient 38:7631b92cc772 141 }
AzureIoTClient 38:7631b92cc772 142
Azure.IoT Build 0:6ae2f7bca550 143 static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
Azure.IoT Build 0:6ae2f7bca550 144 {
AzureIoTClient 29:4a11413cf217 145 if (context == NULL)
AzureIoTClient 29:4a11413cf217 146 {
AzureIoTClient 29:4a11413cf217 147 /* Codes_SRS_HEADER_DETECT_IO_01_050: [ If `context` is NULL, `on_underlying_io_bytes_received` shall do nothing. ]*/
AzureIoTClient 29:4a11413cf217 148 LogError("NULL context");
AzureIoTClient 29:4a11413cf217 149 }
AzureIoTClient 29:4a11413cf217 150 else
AzureIoTClient 29:4a11413cf217 151 {
AzureIoTClient 29:4a11413cf217 152 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 153
AzureIoTClient 29:4a11413cf217 154 if ((buffer == NULL) ||
AzureIoTClient 29:4a11413cf217 155 (size == 0))
AzureIoTClient 29:4a11413cf217 156 {
AzureIoTClient 29:4a11413cf217 157 switch (header_detect_io_instance->io_state)
AzureIoTClient 29:4a11413cf217 158 {
AzureIoTClient 29:4a11413cf217 159 default:
AzureIoTClient 29:4a11413cf217 160 break;
AzureIoTClient 29:4a11413cf217 161
AzureIoTClient 29:4a11413cf217 162 case IO_STATE_OPEN:
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 164 indicate_error(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 165 break;
AzureIoTClient 29:4a11413cf217 166 }
AzureIoTClient 29:4a11413cf217 167 }
AzureIoTClient 29:4a11413cf217 168 else
AzureIoTClient 28:add19eb7defa 169 {
AzureIoTClient 29:4a11413cf217 170 while (size > 0)
AzureIoTClient 29:4a11413cf217 171 {
AzureIoTClient 29:4a11413cf217 172 switch (header_detect_io_instance->io_state)
AzureIoTClient 29:4a11413cf217 173 {
AzureIoTClient 29:4a11413cf217 174 default:
AzureIoTClient 29:4a11413cf217 175 break;
AzureIoTClient 29:4a11413cf217 176
AzureIoTClient 29:4a11413cf217 177 case IO_STATE_OPENING_UNDERLYING_IO:
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 179 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
AzureIoTClient 29:4a11413cf217 180 size = 0;
AzureIoTClient 29:4a11413cf217 181 break;
Azure.IoT Build 0:6ae2f7bca550 182
AzureIoTClient 29:4a11413cf217 183 case IO_STATE_OPENING_DETECTED_IO:
AzureIoTClient 29:4a11413cf217 184 {
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 186 CHAINED_IO* chained_io = (CHAINED_IO*)(((unsigned char*)header_detect_io_instance->last_io) - offsetof(CHAINED_IO, detected_io));
AzureIoTClient 29:4a11413cf217 187 (chained_io->on_bytes_received)(chained_io->on_bytes_received_context, buffer, size);
AzureIoTClient 29:4a11413cf217 188 size = 0;
AzureIoTClient 29:4a11413cf217 189 break;
AzureIoTClient 29:4a11413cf217 190 }
AzureIoTClient 29:4a11413cf217 191
AzureIoTClient 29:4a11413cf217 192 case IO_STATE_WAIT_FOR_HEADER:
AzureIoTClient 29:4a11413cf217 193 {
AzureIoTClient 29:4a11413cf217 194 size_t i;
AzureIoTClient 29:4a11413cf217 195 bool has_one_match = false;
AzureIoTClient 29:4a11413cf217 196
AzureIoTClient 29:4a11413cf217 197 /* check if any of the headers matches */
AzureIoTClient 29:4a11413cf217 198 for (i = 0; i < header_detect_io_instance->header_detect_entry_count; i++)
AzureIoTClient 29:4a11413cf217 199 {
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 201 /* Codes_SRS_HEADER_DETECT_IO_01_068: [ Header bytes shall be accepted in multiple `on_underlying_io_bytes_received` calls. ]*/
AzureIoTClient 29:4a11413cf217 202 if ((header_detect_io_instance->header_pos < header_detect_io_instance->header_detect_entries[i].header_size) &&
AzureIoTClient 29:4a11413cf217 203 (header_detect_io_instance->header_detect_entries[i].header_bytes[header_detect_io_instance->header_pos] == buffer[0]))
AzureIoTClient 29:4a11413cf217 204 {
AzureIoTClient 29:4a11413cf217 205 has_one_match = true;
Azure.IoT Build 0:6ae2f7bca550 206
AzureIoTClient 29:4a11413cf217 207 if (header_detect_io_instance->header_pos + 1 == header_detect_io_instance->header_detect_entries[i].header_size)
AzureIoTClient 29:4a11413cf217 208 {
AzureIoTClient 29:4a11413cf217 209 /* recognized one header */
AzureIoTClient 29:4a11413cf217 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)
AzureIoTClient 29:4a11413cf217 211 {
AzureIoTClient 29:4a11413cf217 212 LogError("Failed sending header");
AzureIoTClient 29:4a11413cf217 213 header_detect_io_instance->io_state = IO_STATE_NOT_OPEN;
AzureIoTClient 29:4a11413cf217 214 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
AzureIoTClient 29:4a11413cf217 215 }
AzureIoTClient 29:4a11413cf217 216 else
AzureIoTClient 29:4a11413cf217 217 {
AzureIoTClient 29:4a11413cf217 218 // wait for send complete and then start the detected IO open
AzureIoTClient 29:4a11413cf217 219 if (header_detect_io_instance->header_detect_entries[i].io_interface_description == NULL)
AzureIoTClient 29:4a11413cf217 220 {
AzureIoTClient 29:4a11413cf217 221 header_detect_io_instance->io_state = IO_STATE_OPEN;
AzureIoTClient 29:4a11413cf217 222 indicate_open_complete(header_detect_io_instance, IO_OPEN_OK);
AzureIoTClient 29:4a11413cf217 223 }
AzureIoTClient 29:4a11413cf217 224 else
AzureIoTClient 29:4a11413cf217 225 {
AzureIoTClient 29:4a11413cf217 226 SERVER_PROTOCOL_IO_CONFIG server_protocol_io_config;
AzureIoTClient 29:4a11413cf217 227 CHAINED_IO* chained_io = (CHAINED_IO*)malloc(sizeof(CHAINED_IO));
AzureIoTClient 29:4a11413cf217 228 if (chained_io == NULL)
AzureIoTClient 29:4a11413cf217 229 {
AzureIoTClient 29:4a11413cf217 230 LogError("Cannot allocate memory for chained IO");
AzureIoTClient 29:4a11413cf217 231 internal_close(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 232 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
AzureIoTClient 29:4a11413cf217 233 }
AzureIoTClient 29:4a11413cf217 234 else
AzureIoTClient 29:4a11413cf217 235 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 238 server_protocol_io_config.underlying_io = *header_detect_io_instance->last_io;
AzureIoTClient 29:4a11413cf217 239 server_protocol_io_config.on_bytes_received = &chained_io->on_bytes_received;
AzureIoTClient 29:4a11413cf217 240 server_protocol_io_config.on_bytes_received_context = &chained_io->on_bytes_received_context;
AzureIoTClient 29:4a11413cf217 241
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 244 /* Codes_SRS_HEADER_DETECT_IO_01_074: [ The IO create parameters shall be a `SERVER_PROTOCOL_IO_CONFIG` structure. ]*/
AzureIoTClient 29:4a11413cf217 245 chained_io->detected_io = xio_create(header_detect_io_instance->header_detect_entries[i].io_interface_description, &server_protocol_io_config);
AzureIoTClient 29:4a11413cf217 246 if (chained_io->detected_io == NULL)
AzureIoTClient 29:4a11413cf217 247 {
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 249 LogError("Creating detected IO failed");
AzureIoTClient 29:4a11413cf217 250 free(chained_io);
AzureIoTClient 29:4a11413cf217 251 internal_close(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 252 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
AzureIoTClient 29:4a11413cf217 253 }
AzureIoTClient 29:4a11413cf217 254 else
AzureIoTClient 29:4a11413cf217 255 {
AzureIoTClient 29:4a11413cf217 256 /* 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 257 LIST_ITEM_HANDLE new_list_item = singlylinkedlist_add(header_detect_io_instance->chained_io_list, chained_io);
AzureIoTClient 29:4a11413cf217 258 if (new_list_item == NULL)
AzureIoTClient 29:4a11413cf217 259 {
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 261 LogError("Cannot add detected IO to list");
AzureIoTClient 29:4a11413cf217 262 xio_destroy(chained_io->detected_io);
AzureIoTClient 29:4a11413cf217 263 free(chained_io);
AzureIoTClient 29:4a11413cf217 264 internal_close(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 265 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
AzureIoTClient 29:4a11413cf217 266 }
AzureIoTClient 29:4a11413cf217 267 else
AzureIoTClient 29:4a11413cf217 268 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 270 XIO_HANDLE* previous_last_io = header_detect_io_instance->last_io;
AzureIoTClient 29:4a11413cf217 271 header_detect_io_instance->last_io = &chained_io->detected_io;
AzureIoTClient 29:4a11413cf217 272
AzureIoTClient 29:4a11413cf217 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`). ]*/
AzureIoTClient 29:4a11413cf217 274 header_detect_io_instance->io_state = IO_STATE_OPENING_DETECTED_IO;
AzureIoTClient 29:4a11413cf217 275
AzureIoTClient 29:4a11413cf217 276 /* Codes_SRS_HEADER_DETECT_IO_01_078: [ The newly create IO shall be open by calling `xio_open`. ]*/
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 278 /* 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 279 /* 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 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)
AzureIoTClient 29:4a11413cf217 281 {
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 283 LogError("Opening detected IO failed");
AzureIoTClient 29:4a11413cf217 284 if (singlylinkedlist_remove(header_detect_io_instance->chained_io_list, new_list_item) != 0)
AzureIoTClient 29:4a11413cf217 285 {
AzureIoTClient 29:4a11413cf217 286 LogError("Cannot remove chained IO from list");
AzureIoTClient 29:4a11413cf217 287 }
AzureIoTClient 29:4a11413cf217 288
AzureIoTClient 29:4a11413cf217 289 xio_destroy(chained_io->detected_io);
AzureIoTClient 29:4a11413cf217 290 free(chained_io);
AzureIoTClient 29:4a11413cf217 291 header_detect_io_instance->last_io = previous_last_io;
AzureIoTClient 29:4a11413cf217 292 internal_close(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 293 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
AzureIoTClient 29:4a11413cf217 294 }
AzureIoTClient 29:4a11413cf217 295 else
AzureIoTClient 29:4a11413cf217 296 {
AzureIoTClient 29:4a11413cf217 297 // all OK
AzureIoTClient 29:4a11413cf217 298 }
AzureIoTClient 29:4a11413cf217 299 }
AzureIoTClient 29:4a11413cf217 300 }
AzureIoTClient 29:4a11413cf217 301 }
AzureIoTClient 29:4a11413cf217 302 }
AzureIoTClient 29:4a11413cf217 303 }
AzureIoTClient 29:4a11413cf217 304
AzureIoTClient 29:4a11413cf217 305 break;
AzureIoTClient 29:4a11413cf217 306 }
AzureIoTClient 29:4a11413cf217 307 }
AzureIoTClient 29:4a11413cf217 308 }
AzureIoTClient 29:4a11413cf217 309
AzureIoTClient 29:4a11413cf217 310 if (has_one_match)
AzureIoTClient 28:add19eb7defa 311 {
AzureIoTClient 29:4a11413cf217 312 if (header_detect_io_instance->io_state == IO_STATE_OPENING_DETECTED_IO)
AzureIoTClient 29:4a11413cf217 313 {
AzureIoTClient 29:4a11413cf217 314 header_detect_io_instance->header_pos = 0;
AzureIoTClient 29:4a11413cf217 315 }
AzureIoTClient 29:4a11413cf217 316 else
AzureIoTClient 29:4a11413cf217 317 {
AzureIoTClient 29:4a11413cf217 318 header_detect_io_instance->header_pos++;
AzureIoTClient 29:4a11413cf217 319 }
AzureIoTClient 29:4a11413cf217 320
AzureIoTClient 29:4a11413cf217 321 size--;
AzureIoTClient 29:4a11413cf217 322 buffer++;
AzureIoTClient 28:add19eb7defa 323 }
AzureIoTClient 28:add19eb7defa 324 else
AzureIoTClient 28:add19eb7defa 325 {
AzureIoTClient 29:4a11413cf217 326 /* all header matches failed, we can't proceed, send back to the peer the first header we know of, */
AzureIoTClient 29:4a11413cf217 327 /* then close as per spec. We do not care if we fail sending */
AzureIoTClient 38:7631b92cc772 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)
AzureIoTClient 29:4a11413cf217 329 {
AzureIoTClient 29:4a11413cf217 330 LogError("Failed sending header");
AzureIoTClient 29:4a11413cf217 331 }
AzureIoTClient 29:4a11413cf217 332
AzureIoTClient 29:4a11413cf217 333 internal_close(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 334 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
AzureIoTClient 29:4a11413cf217 335 size = 0;
AzureIoTClient 28:add19eb7defa 336 }
AzureIoTClient 29:4a11413cf217 337
AzureIoTClient 29:4a11413cf217 338 break;
AzureIoTClient 29:4a11413cf217 339 }
AzureIoTClient 29:4a11413cf217 340
AzureIoTClient 29:4a11413cf217 341 case IO_STATE_OPEN:
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 344 header_detect_io_instance->on_bytes_received(header_detect_io_instance->on_bytes_received_context, buffer, size);
AzureIoTClient 29:4a11413cf217 345 size = 0;
AzureIoTClient 29:4a11413cf217 346 break;
AzureIoTClient 28:add19eb7defa 347 }
AzureIoTClient 28:add19eb7defa 348 }
AzureIoTClient 28:add19eb7defa 349 }
AzureIoTClient 28:add19eb7defa 350 }
Azure.IoT Build 0:6ae2f7bca550 351 }
Azure.IoT Build 0:6ae2f7bca550 352
Azure.IoT Build 0:6ae2f7bca550 353 static void on_underlying_io_close_complete(void* context)
Azure.IoT Build 0:6ae2f7bca550 354 {
AzureIoTClient 28:add19eb7defa 355 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 356
AzureIoTClient 28:add19eb7defa 357 switch (header_detect_io_instance->io_state)
AzureIoTClient 28:add19eb7defa 358 {
AzureIoTClient 28:add19eb7defa 359 default:
AzureIoTClient 28:add19eb7defa 360 break;
Azure.IoT Build 0:6ae2f7bca550 361
Azure.IoT Build 0:6ae2f7bca550 362 case IO_STATE_CLOSING:
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 364 destroy_io_chain(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 365
Azure.IoT Build 0:6ae2f7bca550 366 header_detect_io_instance->io_state = IO_STATE_NOT_OPEN;
Azure.IoT Build 0:6ae2f7bca550 367 indicate_close_complete(header_detect_io_instance);
Azure.IoT Build 0:6ae2f7bca550 368 break;
Azure.IoT Build 0:6ae2f7bca550 369
AzureIoTClient 28:add19eb7defa 370 case IO_STATE_WAIT_FOR_HEADER:
AzureIoTClient 29:4a11413cf217 371 case IO_STATE_OPENING_DETECTED_IO:
AzureIoTClient 28:add19eb7defa 372 case IO_STATE_OPENING_UNDERLYING_IO:
AzureIoTClient 28:add19eb7defa 373 header_detect_io_instance->io_state = IO_STATE_NOT_OPEN;
AzureIoTClient 28:add19eb7defa 374 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
AzureIoTClient 28:add19eb7defa 375 break;
AzureIoTClient 28:add19eb7defa 376 }
Azure.IoT Build 0:6ae2f7bca550 377 }
Azure.IoT Build 0:6ae2f7bca550 378
Azure.IoT Build 0:6ae2f7bca550 379 static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT open_result)
Azure.IoT Build 0:6ae2f7bca550 380 {
AzureIoTClient 29:4a11413cf217 381 if (context == NULL)
AzureIoTClient 28:add19eb7defa 382 {
AzureIoTClient 29:4a11413cf217 383 /* Codes_SRS_HEADER_DETECT_IO_01_048: [ If `context` is NULL, `on_underlying_io_open_complete` shall do nothing. ]*/
AzureIoTClient 29:4a11413cf217 384 LogError("NULL context");
AzureIoTClient 29:4a11413cf217 385 }
AzureIoTClient 29:4a11413cf217 386 else
AzureIoTClient 29:4a11413cf217 387 {
AzureIoTClient 29:4a11413cf217 388 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 389
AzureIoTClient 28:add19eb7defa 390 if (open_result == IO_OPEN_OK)
AzureIoTClient 28:add19eb7defa 391 {
AzureIoTClient 29:4a11413cf217 392 switch (header_detect_io_instance->io_state)
AzureIoTClient 29:4a11413cf217 393 {
AzureIoTClient 29:4a11413cf217 394 default:
AzureIoTClient 29:4a11413cf217 395 LogError("on_io_open_complete called in unexpected state: %d", (int)header_detect_io_instance->io_state);
AzureIoTClient 29:4a11413cf217 396 break;
AzureIoTClient 29:4a11413cf217 397
AzureIoTClient 29:4a11413cf217 398 case IO_STATE_OPENING_DETECTED_IO:
AzureIoTClient 29:4a11413cf217 399 case IO_STATE_OPENING_UNDERLYING_IO:
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 401 header_detect_io_instance->io_state = IO_STATE_WAIT_FOR_HEADER;
AzureIoTClient 29:4a11413cf217 402 break;
AzureIoTClient 29:4a11413cf217 403 }
AzureIoTClient 28:add19eb7defa 404 }
AzureIoTClient 28:add19eb7defa 405 else
AzureIoTClient 28:add19eb7defa 406 {
AzureIoTClient 29:4a11413cf217 407 switch (header_detect_io_instance->io_state)
AzureIoTClient 28:add19eb7defa 408 {
AzureIoTClient 29:4a11413cf217 409 default:
AzureIoTClient 29:4a11413cf217 410 LogError("on_io_open_complete called in unexpected state: %d", (int)header_detect_io_instance->io_state);
AzureIoTClient 29:4a11413cf217 411 break;
AzureIoTClient 29:4a11413cf217 412
AzureIoTClient 29:4a11413cf217 413 case IO_STATE_OPENING_DETECTED_IO:
AzureIoTClient 29:4a11413cf217 414 case IO_STATE_OPENING_UNDERLYING_IO:
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 416 internal_close(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 417
AzureIoTClient 28:add19eb7defa 418 header_detect_io_instance->io_state = IO_STATE_NOT_OPEN;
AzureIoTClient 28:add19eb7defa 419 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
AzureIoTClient 29:4a11413cf217 420 break;
AzureIoTClient 28:add19eb7defa 421 }
AzureIoTClient 28:add19eb7defa 422 }
AzureIoTClient 28:add19eb7defa 423 }
Azure.IoT Build 0:6ae2f7bca550 424 }
Azure.IoT Build 0:6ae2f7bca550 425
Azure.IoT Build 0:6ae2f7bca550 426 static void on_underlying_io_error(void* context)
Azure.IoT Build 0:6ae2f7bca550 427 {
AzureIoTClient 29:4a11413cf217 428 if (context == NULL)
AzureIoTClient 29:4a11413cf217 429 {
AzureIoTClient 29:4a11413cf217 430 /* Codes_SRS_HEADER_DETECT_IO_01_058: [ If `context` is NULL, `on_underlying_io_error` shall do nothing. ]*/
AzureIoTClient 29:4a11413cf217 431 LogError("NULL context");
AzureIoTClient 29:4a11413cf217 432 }
AzureIoTClient 29:4a11413cf217 433 else
AzureIoTClient 29:4a11413cf217 434 {
AzureIoTClient 29:4a11413cf217 435 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 436
AzureIoTClient 29:4a11413cf217 437 switch (header_detect_io_instance->io_state)
AzureIoTClient 29:4a11413cf217 438 {
AzureIoTClient 29:4a11413cf217 439 default:
AzureIoTClient 29:4a11413cf217 440 break;
Azure.IoT Build 0:6ae2f7bca550 441
AzureIoTClient 29:4a11413cf217 442 case IO_STATE_WAIT_FOR_HEADER:
AzureIoTClient 29:4a11413cf217 443 case IO_STATE_OPENING_DETECTED_IO:
AzureIoTClient 29:4a11413cf217 444 case IO_STATE_OPENING_UNDERLYING_IO:
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 446 internal_close(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 447 indicate_open_complete(header_detect_io_instance, IO_OPEN_ERROR);
AzureIoTClient 29:4a11413cf217 448 break;
Azure.IoT Build 0:6ae2f7bca550 449
AzureIoTClient 29:4a11413cf217 450 case IO_STATE_OPEN:
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 452 header_detect_io_instance->io_state = IO_STATE_ERROR;
AzureIoTClient 29:4a11413cf217 453 indicate_error(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 454 break;
AzureIoTClient 29:4a11413cf217 455 }
AzureIoTClient 28:add19eb7defa 456 }
Azure.IoT Build 0:6ae2f7bca550 457 }
Azure.IoT Build 0:6ae2f7bca550 458
AzureIoTClient 29:4a11413cf217 459 static CONCRETE_IO_HANDLE header_detect_io_create(void* io_create_parameters)
Azure.IoT Build 0:6ae2f7bca550 460 {
AzureIoTClient 28:add19eb7defa 461 HEADER_DETECT_IO_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 462
AzureIoTClient 28:add19eb7defa 463 if (io_create_parameters == NULL)
AzureIoTClient 28:add19eb7defa 464 {
AzureIoTClient 29:4a11413cf217 465 /* 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 466 LogError("NULL io_create_parameters");
AzureIoTClient 28:add19eb7defa 467 result = NULL;
AzureIoTClient 28:add19eb7defa 468 }
AzureIoTClient 28:add19eb7defa 469 else
AzureIoTClient 28:add19eb7defa 470 {
AzureIoTClient 29:4a11413cf217 471 /* Codes_SRS_HEADER_DETECT_IO_01_004: [ `io_create_parameters` shall be used as `HEADER_DETECT_IO_CONFIG*`. ]*/
AzureIoTClient 29:4a11413cf217 472 HEADER_DETECT_IO_CONFIG* header_detect_io_config = (HEADER_DETECT_IO_CONFIG*)io_create_parameters;
AzureIoTClient 29:4a11413cf217 473
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 475 if ((header_detect_io_config->header_detect_entry_count == 0) ||
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 477 (header_detect_io_config->header_detect_entries == NULL) ||
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 479 (header_detect_io_config->underlying_io == NULL))
AzureIoTClient 29:4a11413cf217 480 {
AzureIoTClient 29:4a11413cf217 481 LogError("Bad create parameters: header_detect_entry_count = %u, header_detect_entries = %p, underlying_io = %p",
AzureIoTClient 29:4a11413cf217 482 header_detect_io_config->header_detect_entry_count,
AzureIoTClient 29:4a11413cf217 483 header_detect_io_config->header_detect_entries,
AzureIoTClient 29:4a11413cf217 484 header_detect_io_config->underlying_io);
AzureIoTClient 29:4a11413cf217 485 result = NULL;
AzureIoTClient 29:4a11413cf217 486 }
AzureIoTClient 29:4a11413cf217 487 else
AzureIoTClient 28:add19eb7defa 488 {
AzureIoTClient 29:4a11413cf217 489 size_t i;
AzureIoTClient 29:4a11413cf217 490 bool null_io_found = false;
AzureIoTClient 29:4a11413cf217 491
AzureIoTClient 29:4a11413cf217 492 for (i = 0; i < header_detect_io_config->header_detect_entry_count; i++)
AzureIoTClient 29:4a11413cf217 493 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 495 if (header_detect_io_config->header_detect_entries[i].header.header_bytes == NULL)
AzureIoTClient 29:4a11413cf217 496 {
AzureIoTClient 29:4a11413cf217 497 LogError("header detect entry %u is invalid", (unsigned int)i);
AzureIoTClient 29:4a11413cf217 498 break;
AzureIoTClient 29:4a11413cf217 499 }
AzureIoTClient 29:4a11413cf217 500
AzureIoTClient 29:4a11413cf217 501 if (header_detect_io_config->header_detect_entries[i].io_interface_description == NULL)
AzureIoTClient 29:4a11413cf217 502 {
AzureIoTClient 29:4a11413cf217 503 null_io_found = true;
AzureIoTClient 29:4a11413cf217 504 }
AzureIoTClient 29:4a11413cf217 505 }
AzureIoTClient 29:4a11413cf217 506
AzureIoTClient 29:4a11413cf217 507 if (i < header_detect_io_config->header_detect_entry_count)
AzureIoTClient 29:4a11413cf217 508 {
AzureIoTClient 29:4a11413cf217 509 result = NULL;
AzureIoTClient 29:4a11413cf217 510 }
AzureIoTClient 29:4a11413cf217 511 else if (!null_io_found)
AzureIoTClient 29:4a11413cf217 512 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 514 LogError("No default header found");
AzureIoTClient 29:4a11413cf217 515 result = NULL;
AzureIoTClient 29:4a11413cf217 516 }
AzureIoTClient 29:4a11413cf217 517 else
AzureIoTClient 29:4a11413cf217 518 {
AzureIoTClient 29:4a11413cf217 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. ] */
AzureIoTClient 29:4a11413cf217 520 result = (HEADER_DETECT_IO_INSTANCE*)malloc(sizeof(HEADER_DETECT_IO_INSTANCE));
AzureIoTClient 29:4a11413cf217 521 if (result == NULL)
AzureIoTClient 29:4a11413cf217 522 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 524 LogError("Cannot allocate memory for header detect IO");
AzureIoTClient 29:4a11413cf217 525 }
AzureIoTClient 29:4a11413cf217 526 else
AzureIoTClient 29:4a11413cf217 527 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 529 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 530 if (result->header_detect_entries == NULL)
AzureIoTClient 29:4a11413cf217 531 {
AzureIoTClient 29:4a11413cf217 532 free(result);
AzureIoTClient 29:4a11413cf217 533 result = NULL;
AzureIoTClient 29:4a11413cf217 534 }
AzureIoTClient 29:4a11413cf217 535 else
AzureIoTClient 29:4a11413cf217 536 {
AzureIoTClient 29:4a11413cf217 537 result->header_detect_entry_count = header_detect_io_config->header_detect_entry_count;
Azure.IoT Build 0:6ae2f7bca550 538
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 540 for (i = 0; i < header_detect_io_config->header_detect_entry_count; i++)
AzureIoTClient 29:4a11413cf217 541 {
AzureIoTClient 29:4a11413cf217 542 result->header_detect_entries[i].header_size = header_detect_io_config->header_detect_entries[i].header.header_size;
AzureIoTClient 29:4a11413cf217 543 result->header_detect_entries[i].header_bytes = (unsigned char*)malloc(result->header_detect_entries[i].header_size);
AzureIoTClient 29:4a11413cf217 544 if (result->header_detect_entries[i].header_bytes == NULL)
AzureIoTClient 29:4a11413cf217 545 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 547 break;
AzureIoTClient 29:4a11413cf217 548 }
AzureIoTClient 29:4a11413cf217 549 else
AzureIoTClient 29:4a11413cf217 550 {
AzureIoTClient 29:4a11413cf217 551 /* Codes_SRS_HEADER_DETECT_IO_01_014: [ For each entry in `header_detect_entries` the `header` field shall also be copied. ]*/
AzureIoTClient 29:4a11413cf217 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);
AzureIoTClient 29:4a11413cf217 553 result->header_detect_entries[i].io_interface_description = header_detect_io_config->header_detect_entries[i].io_interface_description;
AzureIoTClient 29:4a11413cf217 554 }
AzureIoTClient 29:4a11413cf217 555 }
AzureIoTClient 29:4a11413cf217 556
AzureIoTClient 29:4a11413cf217 557 if (i < header_detect_io_config->header_detect_entry_count)
AzureIoTClient 29:4a11413cf217 558 {
AzureIoTClient 29:4a11413cf217 559 size_t j;
AzureIoTClient 29:4a11413cf217 560
AzureIoTClient 29:4a11413cf217 561 LogError("Failed copying header detect configuration");
AzureIoTClient 29:4a11413cf217 562 for (j = 0; j < i; j++)
AzureIoTClient 29:4a11413cf217 563 {
AzureIoTClient 29:4a11413cf217 564 free(result->header_detect_entries[j].header_bytes);
AzureIoTClient 29:4a11413cf217 565 }
AzureIoTClient 29:4a11413cf217 566
AzureIoTClient 29:4a11413cf217 567 free(result->header_detect_entries);
AzureIoTClient 29:4a11413cf217 568 free(result);
AzureIoTClient 29:4a11413cf217 569 result = NULL;
AzureIoTClient 29:4a11413cf217 570 }
AzureIoTClient 29:4a11413cf217 571 else
AzureIoTClient 29:4a11413cf217 572 {
AzureIoTClient 30:0407b2db334c 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. ]*/
AzureIoTClient 29:4a11413cf217 574 result->chained_io_list = singlylinkedlist_create();
AzureIoTClient 29:4a11413cf217 575 if (result->chained_io_list == NULL)
AzureIoTClient 29:4a11413cf217 576 {
AzureIoTClient 29:4a11413cf217 577 /* Codes_SRS_HEADER_DETECT_IO_01_065: [ If `singlylinkedlist_create` fails then `header_detect_io_create` shall fail and return NULL. ]*/
AzureIoTClient 29:4a11413cf217 578 LogError("Failed copying header detect configuration");
AzureIoTClient 29:4a11413cf217 579 for (i = 0; i < result->header_detect_entry_count; i++)
AzureIoTClient 29:4a11413cf217 580 {
AzureIoTClient 29:4a11413cf217 581 free(result->header_detect_entries[i].header_bytes);
AzureIoTClient 29:4a11413cf217 582 }
AzureIoTClient 29:4a11413cf217 583
AzureIoTClient 29:4a11413cf217 584 free(result->header_detect_entries);
AzureIoTClient 29:4a11413cf217 585 free(result);
AzureIoTClient 29:4a11413cf217 586 result = NULL;
AzureIoTClient 29:4a11413cf217 587 }
AzureIoTClient 29:4a11413cf217 588 else
AzureIoTClient 29:4a11413cf217 589 {
AzureIoTClient 29:4a11413cf217 590 result->underlying_io = header_detect_io_config->underlying_io;
AzureIoTClient 29:4a11413cf217 591 result->on_io_open_complete = NULL;
AzureIoTClient 29:4a11413cf217 592 result->on_io_close_complete = NULL;
AzureIoTClient 29:4a11413cf217 593 result->on_io_error = NULL;
AzureIoTClient 29:4a11413cf217 594 result->on_bytes_received = NULL;
AzureIoTClient 29:4a11413cf217 595 result->on_io_open_complete_context = NULL;
AzureIoTClient 29:4a11413cf217 596 result->on_io_close_complete_context = NULL;
AzureIoTClient 29:4a11413cf217 597 result->on_io_error_context = NULL;
AzureIoTClient 29:4a11413cf217 598 result->on_bytes_received_context = NULL;
AzureIoTClient 29:4a11413cf217 599
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 601 result->last_io = &result->underlying_io;
AzureIoTClient 29:4a11413cf217 602
AzureIoTClient 29:4a11413cf217 603 result->io_state = IO_STATE_NOT_OPEN;
AzureIoTClient 29:4a11413cf217 604 }
AzureIoTClient 29:4a11413cf217 605 }
AzureIoTClient 29:4a11413cf217 606 }
AzureIoTClient 29:4a11413cf217 607 }
AzureIoTClient 29:4a11413cf217 608 }
AzureIoTClient 28:add19eb7defa 609 }
AzureIoTClient 28:add19eb7defa 610 }
Azure.IoT Build 0:6ae2f7bca550 611
AzureIoTClient 28:add19eb7defa 612 return result;
Azure.IoT Build 0:6ae2f7bca550 613 }
Azure.IoT Build 0:6ae2f7bca550 614
AzureIoTClient 29:4a11413cf217 615 static void header_detect_io_destroy(CONCRETE_IO_HANDLE header_detect_io)
Azure.IoT Build 0:6ae2f7bca550 616 {
AzureIoTClient 29:4a11413cf217 617 if (header_detect_io == NULL)
AzureIoTClient 29:4a11413cf217 618 {
AzureIoTClient 29:4a11413cf217 619 /* Codes_SRS_HEADER_DETECT_IO_01_012: [ If `header_detect_io` is NULL, `header_detect_io_destroy` shall do nothing. ]*/
AzureIoTClient 29:4a11413cf217 620 LogError("NULL header_detect_io");
AzureIoTClient 29:4a11413cf217 621 }
AzureIoTClient 29:4a11413cf217 622 else
AzureIoTClient 28:add19eb7defa 623 {
AzureIoTClient 29:4a11413cf217 624 size_t i;
AzureIoTClient 28:add19eb7defa 625 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
AzureIoTClient 29:4a11413cf217 626
AzureIoTClient 29:4a11413cf217 627 if (header_detect_io_instance->io_state != IO_STATE_NOT_OPEN)
AzureIoTClient 29:4a11413cf217 628 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 630 internal_close(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 631 }
AzureIoTClient 29:4a11413cf217 632
AzureIoTClient 29:4a11413cf217 633 /* Codes_SRS_HEADER_DETECT_IO_01_061: [ `header_detect_io_destroy` shall destroy the chained IO list by calling `singlylinkedlist_destroy`. ]*/
AzureIoTClient 29:4a11413cf217 634 singlylinkedlist_destroy(header_detect_io_instance->chained_io_list);
AzureIoTClient 29:4a11413cf217 635
AzureIoTClient 29:4a11413cf217 636 /* 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 637 for (i = 0; i < header_detect_io_instance->header_detect_entry_count; i++)
AzureIoTClient 29:4a11413cf217 638 {
AzureIoTClient 29:4a11413cf217 639 /* Codes_SRS_HEADER_DETECT_IO_01_013: [ `header_detect_io_destroy` shall free the memory allocated for the `header_detect_entries`. ]*/
AzureIoTClient 29:4a11413cf217 640 free(header_detect_io_instance->header_detect_entries[i].header_bytes);
AzureIoTClient 29:4a11413cf217 641 }
AzureIoTClient 29:4a11413cf217 642
AzureIoTClient 29:4a11413cf217 643 free(header_detect_io_instance->header_detect_entries);
AzureIoTClient 29:4a11413cf217 644
AzureIoTClient 28:add19eb7defa 645 free(header_detect_io);
AzureIoTClient 28:add19eb7defa 646 }
Azure.IoT Build 0:6ae2f7bca550 647 }
Azure.IoT Build 0:6ae2f7bca550 648
AzureIoTClient 29:4a11413cf217 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)
Azure.IoT Build 0:6ae2f7bca550 650 {
AzureIoTClient 28:add19eb7defa 651 int result;
Azure.IoT Build 0:6ae2f7bca550 652
AzureIoTClient 29:4a11413cf217 653 if ((header_detect_io == NULL) ||
AzureIoTClient 29:4a11413cf217 654 (on_io_open_complete == NULL) ||
AzureIoTClient 29:4a11413cf217 655 (on_bytes_received == NULL) ||
AzureIoTClient 29:4a11413cf217 656 (on_io_error == NULL))
AzureIoTClient 28:add19eb7defa 657 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 659 LogError("Bad arguments: header_detect_io = %p, on_io_open_complete = %p, on_bytes_received = %p, on_io_error = %p",
AzureIoTClient 29:4a11413cf217 660 header_detect_io, on_io_open_complete, on_bytes_received, on_io_error);
AzureIoTClient 28:add19eb7defa 661 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 662 }
AzureIoTClient 28:add19eb7defa 663 else
AzureIoTClient 28:add19eb7defa 664 {
AzureIoTClient 28:add19eb7defa 665 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
Azure.IoT Build 0:6ae2f7bca550 666
AzureIoTClient 29:4a11413cf217 667 if (header_detect_io_instance->io_state != IO_STATE_NOT_OPEN)
Azure.IoT Build 0:6ae2f7bca550 668 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 670 LogError("Already OPEN");
AzureIoTClient 19:000ab4e6a2c1 671 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 672 }
AzureIoTClient 28:add19eb7defa 673 else
AzureIoTClient 28:add19eb7defa 674 {
AzureIoTClient 28:add19eb7defa 675 header_detect_io_instance->on_bytes_received = on_bytes_received;
AzureIoTClient 28:add19eb7defa 676 header_detect_io_instance->on_io_open_complete = on_io_open_complete;
AzureIoTClient 28:add19eb7defa 677 header_detect_io_instance->on_io_error = on_io_error;
Azure.IoT Build 0:6ae2f7bca550 678 header_detect_io_instance->on_bytes_received_context = on_bytes_received_context;
Azure.IoT Build 0:6ae2f7bca550 679 header_detect_io_instance->on_io_open_complete_context = on_io_open_complete_context;
Azure.IoT Build 0:6ae2f7bca550 680 header_detect_io_instance->on_io_error_context = on_io_error_context;
Azure.IoT Build 0:6ae2f7bca550 681
AzureIoTClient 29:4a11413cf217 682 header_detect_io_instance->io_state = IO_STATE_OPENING_UNDERLYING_IO;
AzureIoTClient 29:4a11413cf217 683 header_detect_io_instance->header_pos = 0;
AzureIoTClient 29:4a11413cf217 684
AzureIoTClient 29:4a11413cf217 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: ]*/
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 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)
Azure.IoT Build 0:6ae2f7bca550 689 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 691 LogError("xio_open failed");
AzureIoTClient 29:4a11413cf217 692 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 693 }
Azure.IoT Build 0:6ae2f7bca550 694 else
Azure.IoT Build 0:6ae2f7bca550 695 {
AzureIoTClient 29:4a11413cf217 696 /* Codes_SRS_HEADER_DETECT_IO_01_018: [ On success `header_detect_io_open_async` shall return 0. ]*/
AzureIoTClient 29:4a11413cf217 697 result = 0;
Azure.IoT Build 0:6ae2f7bca550 698 }
AzureIoTClient 28:add19eb7defa 699 }
AzureIoTClient 28:add19eb7defa 700 }
Azure.IoT Build 0:6ae2f7bca550 701
AzureIoTClient 28:add19eb7defa 702 return result;
Azure.IoT Build 0:6ae2f7bca550 703 }
Azure.IoT Build 0:6ae2f7bca550 704
AzureIoTClient 29:4a11413cf217 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)
Azure.IoT Build 0:6ae2f7bca550 706 {
AzureIoTClient 28:add19eb7defa 707 int result;
Azure.IoT Build 0:6ae2f7bca550 708
AzureIoTClient 28:add19eb7defa 709 if (header_detect_io == NULL)
AzureIoTClient 28:add19eb7defa 710 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 712 LogError("NULL header_detect_io");
AzureIoTClient 28:add19eb7defa 713 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 714 }
AzureIoTClient 28:add19eb7defa 715 else
AzureIoTClient 28:add19eb7defa 716 {
AzureIoTClient 28:add19eb7defa 717 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
Azure.IoT Build 0:6ae2f7bca550 718
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 720 if ((header_detect_io_instance->io_state == IO_STATE_OPENING_UNDERLYING_IO) ||
AzureIoTClient 29:4a11413cf217 721 (header_detect_io_instance->io_state == IO_STATE_OPENING_DETECTED_IO) ||
AzureIoTClient 29:4a11413cf217 722 (header_detect_io_instance->io_state == IO_STATE_WAIT_FOR_HEADER))
AzureIoTClient 29:4a11413cf217 723 {
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 725 (void)internal_close(header_detect_io_instance);
AzureIoTClient 29:4a11413cf217 726 header_detect_io_instance->on_io_open_complete(header_detect_io_instance->on_io_open_complete_context, IO_OPEN_CANCELLED);
AzureIoTClient 29:4a11413cf217 727 result = 0;
AzureIoTClient 29:4a11413cf217 728 }
AzureIoTClient 29:4a11413cf217 729 else if ((header_detect_io_instance->io_state == IO_STATE_NOT_OPEN) ||
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 28:add19eb7defa 731 (header_detect_io_instance->io_state == IO_STATE_CLOSING))
AzureIoTClient 28:add19eb7defa 732 {
AzureIoTClient 29:4a11413cf217 733 LogError("Not open");
AzureIoTClient 28:add19eb7defa 734 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 735 }
AzureIoTClient 28:add19eb7defa 736 else
AzureIoTClient 28:add19eb7defa 737 {
AzureIoTClient 28:add19eb7defa 738 header_detect_io_instance->io_state = IO_STATE_CLOSING;
Azure.IoT Build 0:6ae2f7bca550 739 header_detect_io_instance->on_io_close_complete = on_io_close_complete;
Azure.IoT Build 0:6ae2f7bca550 740 header_detect_io_instance->on_io_close_complete_context = callback_context;
Azure.IoT Build 0:6ae2f7bca550 741
AzureIoTClient 29:4a11413cf217 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: ]*/
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 744 /* 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 745 if (xio_close(*header_detect_io_instance->last_io, on_underlying_io_close_complete, header_detect_io_instance) != 0)
AzureIoTClient 28:add19eb7defa 746 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 748 LogError("xio_close failed");
AzureIoTClient 28:add19eb7defa 749 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 750 }
AzureIoTClient 28:add19eb7defa 751 else
AzureIoTClient 28:add19eb7defa 752 {
AzureIoTClient 29:4a11413cf217 753 /* Codes_SRS_HEADER_DETECT_IO_01_025: [ On success `header_detect_io_close_async` shall return 0. ]*/
AzureIoTClient 28:add19eb7defa 754 result = 0;
AzureIoTClient 28:add19eb7defa 755 }
AzureIoTClient 28:add19eb7defa 756 }
AzureIoTClient 28:add19eb7defa 757 }
Azure.IoT Build 0:6ae2f7bca550 758
AzureIoTClient 28:add19eb7defa 759 return result;
Azure.IoT Build 0:6ae2f7bca550 760 }
Azure.IoT Build 0:6ae2f7bca550 761
AzureIoTClient 29:4a11413cf217 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)
Azure.IoT Build 0:6ae2f7bca550 763 {
AzureIoTClient 28:add19eb7defa 764 int result;
Azure.IoT Build 0:6ae2f7bca550 765
AzureIoTClient 29:4a11413cf217 766 /* Codes_SRS_HEADER_DETECT_IO_01_055: [ `on_send_complete` and `callback_context` shall be allowed to be NULL. ]*/
AzureIoTClient 29:4a11413cf217 767 if ((header_detect_io == NULL) ||
AzureIoTClient 29:4a11413cf217 768 (buffer == NULL) ||
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 770 (size == 0))
AzureIoTClient 28:add19eb7defa 771 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 773 LogError("Bad arguments: header_detect_io = %p, buffer = %p, size = %u",
AzureIoTClient 29:4a11413cf217 774 header_detect_io, buffer, (unsigned int)size);
AzureIoTClient 28:add19eb7defa 775 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 776 }
AzureIoTClient 28:add19eb7defa 777 else
AzureIoTClient 28:add19eb7defa 778 {
AzureIoTClient 28:add19eb7defa 779 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
Azure.IoT Build 0:6ae2f7bca550 780
AzureIoTClient 28:add19eb7defa 781 if (header_detect_io_instance->io_state != IO_STATE_OPEN)
AzureIoTClient 28:add19eb7defa 782 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 784 LogError("header_detect_io not OPEN");
AzureIoTClient 28:add19eb7defa 785 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 786 }
AzureIoTClient 28:add19eb7defa 787 else
AzureIoTClient 28:add19eb7defa 788 {
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 792 if (xio_send(*header_detect_io_instance->last_io, buffer, size, on_send_complete, callback_context) != 0)
AzureIoTClient 28:add19eb7defa 793 {
AzureIoTClient 29:4a11413cf217 794 LogError("xio_send failed");
AzureIoTClient 28:add19eb7defa 795 result = __FAILURE__;
AzureIoTClient 28:add19eb7defa 796 }
AzureIoTClient 28:add19eb7defa 797 else
AzureIoTClient 28:add19eb7defa 798 {
AzureIoTClient 29:4a11413cf217 799 /* Codes_SRS_HEADER_DETECT_IO_01_031: [ On success `header_detect_io_send_async` shall return 0. ]*/
AzureIoTClient 28:add19eb7defa 800 result = 0;
AzureIoTClient 28:add19eb7defa 801 }
AzureIoTClient 28:add19eb7defa 802 }
AzureIoTClient 28:add19eb7defa 803 }
Azure.IoT Build 0:6ae2f7bca550 804
AzureIoTClient 28:add19eb7defa 805 return result;
Azure.IoT Build 0:6ae2f7bca550 806 }
Azure.IoT Build 0:6ae2f7bca550 807
AzureIoTClient 29:4a11413cf217 808 static void header_detect_io_dowork(CONCRETE_IO_HANDLE header_detect_io)
Azure.IoT Build 0:6ae2f7bca550 809 {
AzureIoTClient 29:4a11413cf217 810 if (header_detect_io == NULL)
AzureIoTClient 29:4a11413cf217 811 {
AzureIoTClient 29:4a11413cf217 812 /* Codes_SRS_HEADER_DETECT_IO_01_036: [ If `header_detect_io` is NULL, `header_detect_io_dowork` shall do nothing. ]*/
AzureIoTClient 29:4a11413cf217 813 LogError("NULL header_detect_io");
AzureIoTClient 29:4a11413cf217 814 }
AzureIoTClient 29:4a11413cf217 815 else
AzureIoTClient 28:add19eb7defa 816 {
AzureIoTClient 28:add19eb7defa 817 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
Azure.IoT Build 0:6ae2f7bca550 818
AzureIoTClient 29:4a11413cf217 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). ]*/
AzureIoTClient 28:add19eb7defa 820 if ((header_detect_io_instance->io_state != IO_STATE_NOT_OPEN) &&
AzureIoTClient 28:add19eb7defa 821 (header_detect_io_instance->io_state != IO_STATE_ERROR))
AzureIoTClient 28:add19eb7defa 822 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 824 LIST_ITEM_HANDLE list_item = singlylinkedlist_get_head_item(header_detect_io_instance->chained_io_list);
AzureIoTClient 29:4a11413cf217 825 while (list_item != NULL)
AzureIoTClient 29:4a11413cf217 826 {
AzureIoTClient 29:4a11413cf217 827 CHAINED_IO* chained_io = (CHAINED_IO*)singlylinkedlist_item_get_value(list_item);
AzureIoTClient 29:4a11413cf217 828 xio_dowork(chained_io->detected_io);
AzureIoTClient 29:4a11413cf217 829
AzureIoTClient 29:4a11413cf217 830 list_item = singlylinkedlist_get_next_item(list_item);
AzureIoTClient 29:4a11413cf217 831 }
AzureIoTClient 29:4a11413cf217 832
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 28:add19eb7defa 834 xio_dowork(header_detect_io_instance->underlying_io);
AzureIoTClient 28:add19eb7defa 835 }
AzureIoTClient 28:add19eb7defa 836 }
Azure.IoT Build 0:6ae2f7bca550 837 }
Azure.IoT Build 0:6ae2f7bca550 838
AzureIoTClient 29:4a11413cf217 839 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 840 {
AzureIoTClient 1:eab586236bfe 841 int result;
AzureIoTClient 1:eab586236bfe 842
AzureIoTClient 29:4a11413cf217 843 if ((header_detect_io == NULL) ||
AzureIoTClient 29:4a11413cf217 844 (option_name == NULL))
AzureIoTClient 1:eab586236bfe 845 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 847 LogError("NULL header_detect_io");
AzureIoTClient 19:000ab4e6a2c1 848 result = __FAILURE__;
AzureIoTClient 1:eab586236bfe 849 }
AzureIoTClient 1:eab586236bfe 850 else
AzureIoTClient 1:eab586236bfe 851 {
AzureIoTClient 1:eab586236bfe 852 HEADER_DETECT_IO_INSTANCE* header_detect_io_instance = (HEADER_DETECT_IO_INSTANCE*)header_detect_io;
AzureIoTClient 1:eab586236bfe 853
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 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`. ]*/
AzureIoTClient 29:4a11413cf217 856 if (xio_setoption(*header_detect_io_instance->last_io, option_name, value) != 0)
AzureIoTClient 1:eab586236bfe 857 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 859 LogError("Setting the option on the underlying IO failed");
AzureIoTClient 19:000ab4e6a2c1 860 result = __FAILURE__;
AzureIoTClient 1:eab586236bfe 861 }
AzureIoTClient 1:eab586236bfe 862 else
AzureIoTClient 1:eab586236bfe 863 {
AzureIoTClient 29:4a11413cf217 864 /* Codes_SRS_HEADER_DETECT_IO_01_043: [ On success, `header_detect_io_set_option` shall return 0. ]*/
AzureIoTClient 29:4a11413cf217 865 result = 0;
AzureIoTClient 1:eab586236bfe 866 }
AzureIoTClient 1:eab586236bfe 867 }
AzureIoTClient 1:eab586236bfe 868
AzureIoTClient 1:eab586236bfe 869 return result;
Azure.IoT Build 0:6ae2f7bca550 870 }
Azure.IoT Build 0:6ae2f7bca550 871
AzureIoTClient 6:641a9672db08 872 /*this function will clone an option given by name and value*/
AzureIoTClient 29:4a11413cf217 873 static void* header_detect_io_clone_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 return NULL;
AzureIoTClient 6:641a9672db08 878 }
AzureIoTClient 6:641a9672db08 879
AzureIoTClient 6:641a9672db08 880 /*this function destroys an option previously created*/
AzureIoTClient 29:4a11413cf217 881 static void header_detect_io_destroy_option(const char* name, const void* value)
AzureIoTClient 6:641a9672db08 882 {
AzureIoTClient 17:923575db8b2d 883 (void)name;
AzureIoTClient 17:923575db8b2d 884 (void)value;
AzureIoTClient 6:641a9672db08 885 }
AzureIoTClient 6:641a9672db08 886
AzureIoTClient 29:4a11413cf217 887 static OPTIONHANDLER_HANDLE header_detect_io_retrieve_options(CONCRETE_IO_HANDLE header_detect_io)
AzureIoTClient 6:641a9672db08 888 {
AzureIoTClient 6:641a9672db08 889 OPTIONHANDLER_HANDLE result;
AzureIoTClient 29:4a11413cf217 890
AzureIoTClient 29:4a11413cf217 891 if (header_detect_io == NULL)
AzureIoTClient 6:641a9672db08 892 {
AzureIoTClient 29:4a11413cf217 893 /* Codes_SRS_HEADER_DETECT_IO_01_041: [ If `header_detect_io` is NULL, `header_detect_io_retrieve_options` shall return NULL. ]*/
AzureIoTClient 29:4a11413cf217 894 LogError("NULL header_detect_io");
AzureIoTClient 29:4a11413cf217 895 result = NULL;
AzureIoTClient 6:641a9672db08 896 }
AzureIoTClient 6:641a9672db08 897 else
AzureIoTClient 6:641a9672db08 898 {
AzureIoTClient 29:4a11413cf217 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. ]*/
AzureIoTClient 29:4a11413cf217 900 result = OptionHandler_Create(header_detect_io_clone_option, header_detect_io_destroy_option, header_detect_io_set_option);
AzureIoTClient 29:4a11413cf217 901 if (result == NULL)
AzureIoTClient 29:4a11413cf217 902 {
AzureIoTClient 29:4a11413cf217 903 /* Codes_SRS_HEADER_DETECT_IO_01_040: [ If `OptionHandler_Create` fails, `header_detect_io_retrieve_options` shall return NULL. ]*/
AzureIoTClient 29:4a11413cf217 904 LogError("unable to OptionHandler_Create");
AzureIoTClient 29:4a11413cf217 905 /*return as is*/
AzureIoTClient 29:4a11413cf217 906 }
AzureIoTClient 29:4a11413cf217 907 else
AzureIoTClient 29:4a11413cf217 908 {
AzureIoTClient 29:4a11413cf217 909 /*insert here work to add the options to "result" handle*/
AzureIoTClient 29:4a11413cf217 910 /* Codes_SRS_HEADER_DETECT_IO_01_039: [ No options shall be added to the newly created option handler. ]*/
AzureIoTClient 29:4a11413cf217 911 }
AzureIoTClient 6:641a9672db08 912 }
AzureIoTClient 6:641a9672db08 913 return result;
AzureIoTClient 6:641a9672db08 914 }
AzureIoTClient 6:641a9672db08 915
Azure.IoT Build 0:6ae2f7bca550 916 static const IO_INTERFACE_DESCRIPTION header_detect_io_interface_description =
Azure.IoT Build 0:6ae2f7bca550 917 {
AzureIoTClient 29:4a11413cf217 918 header_detect_io_retrieve_options,
AzureIoTClient 29:4a11413cf217 919 header_detect_io_create,
AzureIoTClient 29:4a11413cf217 920 header_detect_io_destroy,
AzureIoTClient 29:4a11413cf217 921 header_detect_io_open_async,
AzureIoTClient 29:4a11413cf217 922 header_detect_io_close_async,
AzureIoTClient 29:4a11413cf217 923 header_detect_io_send_async,
AzureIoTClient 29:4a11413cf217 924 header_detect_io_dowork,
AzureIoTClient 29:4a11413cf217 925 header_detect_io_set_option
Azure.IoT Build 0:6ae2f7bca550 926 };
Azure.IoT Build 0:6ae2f7bca550 927
AzureIoTClient 29:4a11413cf217 928 const IO_INTERFACE_DESCRIPTION* header_detect_io_get_interface_description(void)
Azure.IoT Build 0:6ae2f7bca550 929 {
AzureIoTClient 28:add19eb7defa 930 return &header_detect_io_interface_description;
Azure.IoT Build 0:6ae2f7bca550 931 }
AzureIoTClient 29:4a11413cf217 932
AzureIoTClient 29:4a11413cf217 933 static const AMQP_HEADER amqp_header =
AzureIoTClient 29:4a11413cf217 934 {
AzureIoTClient 29:4a11413cf217 935 amqp_header_bytes,
AzureIoTClient 29:4a11413cf217 936 sizeof(amqp_header_bytes)
AzureIoTClient 29:4a11413cf217 937 };
AzureIoTClient 29:4a11413cf217 938
AzureIoTClient 29:4a11413cf217 939 static const AMQP_HEADER sasl_amqp_header =
AzureIoTClient 29:4a11413cf217 940 {
AzureIoTClient 29:4a11413cf217 941 sasl_amqp_header_bytes,
AzureIoTClient 29:4a11413cf217 942 sizeof(sasl_amqp_header_bytes)
AzureIoTClient 29:4a11413cf217 943 };
AzureIoTClient 29:4a11413cf217 944
AzureIoTClient 43:4c1e4e94cdd3 945 AMQP_HEADER header_detect_io_get_amqp_header(void)
AzureIoTClient 29:4a11413cf217 946 {
AzureIoTClient 29:4a11413cf217 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 }. ]*/
AzureIoTClient 29:4a11413cf217 948 return amqp_header;
AzureIoTClient 29:4a11413cf217 949 }
AzureIoTClient 29:4a11413cf217 950
AzureIoTClient 43:4c1e4e94cdd3 951 AMQP_HEADER header_detect_io_get_sasl_amqp_header(void)
AzureIoTClient 29:4a11413cf217 952 {
AzureIoTClient 29:4a11413cf217 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 }. ]*/
AzureIoTClient 29:4a11413cf217 954 return sasl_amqp_header;
AzureIoTClient 29:4a11413cf217 955 }