A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Mar 24 16:35:45 2017 -0700
Revision:
21:f9c433d8e6ca
Parent:
19:000ab4e6a2c1
Child:
22:524bded3f7a8
1.1.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
Azure.IoT Build 0:6ae2f7bca550 4 #include <stdlib.h>
Azure.IoT Build 0:6ae2f7bca550 5 #include <stdint.h>
Azure.IoT Build 0:6ae2f7bca550 6 #include <stdbool.h>
Azure.IoT Build 0:6ae2f7bca550 7 #include <string.h>
AzureIoTClient 19:000ab4e6a2c1 8 #include "azure_c_shared_utility/optimize_size.h"
AzureIoTClient 21:f9c433d8e6ca 9 #include "azure_c_shared_utility/gballoc.h"
Azure.IoT Build 0:6ae2f7bca550 10 #include "azure_c_shared_utility/xlogging.h"
AzureIoTClient 12:b30dacf113f2 11 #include "azure_c_shared_utility/singlylinkedlist.h"
Azure.IoT Build 0:6ae2f7bca550 12 #include "azure_uamqp_c/frame_codec.h"
Azure.IoT Build 0:6ae2f7bca550 13 #include "azure_uamqp_c/amqpvalue.h"
Azure.IoT Build 0:6ae2f7bca550 14
Azure.IoT Build 0:6ae2f7bca550 15 #define FRAME_HEADER_SIZE 8
Azure.IoT Build 0:6ae2f7bca550 16 #define MAX_TYPE_SPECIFIC_SIZE ((255 * 4) - 6)
Azure.IoT Build 0:6ae2f7bca550 17
Azure.IoT Build 0:6ae2f7bca550 18 typedef enum RECEIVE_FRAME_STATE_TAG
Azure.IoT Build 0:6ae2f7bca550 19 {
Azure.IoT Build 0:6ae2f7bca550 20 RECEIVE_FRAME_STATE_FRAME_SIZE,
Azure.IoT Build 0:6ae2f7bca550 21 RECEIVE_FRAME_STATE_DOFF,
Azure.IoT Build 0:6ae2f7bca550 22 RECEIVE_FRAME_STATE_FRAME_TYPE,
Azure.IoT Build 0:6ae2f7bca550 23 RECEIVE_FRAME_STATE_TYPE_SPECIFIC,
Azure.IoT Build 0:6ae2f7bca550 24 RECEIVE_FRAME_STATE_FRAME_BODY,
Azure.IoT Build 0:6ae2f7bca550 25 RECEIVE_FRAME_STATE_ERROR
Azure.IoT Build 0:6ae2f7bca550 26 } RECEIVE_FRAME_STATE;
Azure.IoT Build 0:6ae2f7bca550 27
Azure.IoT Build 0:6ae2f7bca550 28 typedef struct SUBSCRIPTION_TAG
Azure.IoT Build 0:6ae2f7bca550 29 {
Azure.IoT Build 0:6ae2f7bca550 30 uint8_t frame_type;
Azure.IoT Build 0:6ae2f7bca550 31 ON_FRAME_RECEIVED on_frame_received;
Azure.IoT Build 0:6ae2f7bca550 32 void* callback_context;
Azure.IoT Build 0:6ae2f7bca550 33 } SUBSCRIPTION;
Azure.IoT Build 0:6ae2f7bca550 34
Azure.IoT Build 0:6ae2f7bca550 35 typedef struct FRAME_CODEC_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 36 {
Azure.IoT Build 0:6ae2f7bca550 37 /* subscriptions */
AzureIoTClient 12:b30dacf113f2 38 SINGLYLINKEDLIST_HANDLE subscription_list;
Azure.IoT Build 0:6ae2f7bca550 39
Azure.IoT Build 0:6ae2f7bca550 40 /* decode frame */
Azure.IoT Build 0:6ae2f7bca550 41 RECEIVE_FRAME_STATE receive_frame_state;
Azure.IoT Build 0:6ae2f7bca550 42 size_t receive_frame_pos;
Azure.IoT Build 0:6ae2f7bca550 43 uint32_t receive_frame_size;
Azure.IoT Build 0:6ae2f7bca550 44 uint32_t type_specific_size;
Azure.IoT Build 0:6ae2f7bca550 45 uint8_t receive_frame_doff;
Azure.IoT Build 0:6ae2f7bca550 46 uint8_t receive_frame_type;
Azure.IoT Build 0:6ae2f7bca550 47 SUBSCRIPTION* receive_frame_subscription;
Azure.IoT Build 0:6ae2f7bca550 48 unsigned char* receive_frame_bytes;
Azure.IoT Build 0:6ae2f7bca550 49 ON_FRAME_CODEC_ERROR on_frame_codec_error;
Azure.IoT Build 0:6ae2f7bca550 50 void* on_frame_codec_error_callback_context;
Azure.IoT Build 0:6ae2f7bca550 51
Azure.IoT Build 0:6ae2f7bca550 52 /* configuration */
Azure.IoT Build 0:6ae2f7bca550 53 uint32_t max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 54 } FRAME_CODEC_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 55
Azure.IoT Build 0:6ae2f7bca550 56 static bool find_subscription_by_frame_type(LIST_ITEM_HANDLE list_item, const void* match_context)
Azure.IoT Build 0:6ae2f7bca550 57 {
Azure.IoT Build 0:6ae2f7bca550 58 bool result;
AzureIoTClient 12:b30dacf113f2 59 SUBSCRIPTION* subscription = (SUBSCRIPTION*)singlylinkedlist_item_get_value(list_item);
Azure.IoT Build 0:6ae2f7bca550 60
Azure.IoT Build 0:6ae2f7bca550 61 if (subscription == NULL)
Azure.IoT Build 0:6ae2f7bca550 62 {
Azure.IoT Build 0:6ae2f7bca550 63 result = false;
Azure.IoT Build 0:6ae2f7bca550 64 }
Azure.IoT Build 0:6ae2f7bca550 65 else
Azure.IoT Build 0:6ae2f7bca550 66 {
Azure.IoT Build 0:6ae2f7bca550 67 result = subscription->frame_type == *((uint8_t*)match_context) ? true : false;
Azure.IoT Build 0:6ae2f7bca550 68 }
Azure.IoT Build 0:6ae2f7bca550 69
Azure.IoT Build 0:6ae2f7bca550 70 return result;
Azure.IoT Build 0:6ae2f7bca550 71 }
Azure.IoT Build 0:6ae2f7bca550 72
Azure.IoT Build 5:ae49385aff34 73 FRAME_CODEC_HANDLE frame_codec_create(ON_FRAME_CODEC_ERROR on_frame_codec_error, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 74 {
Azure.IoT Build 0:6ae2f7bca550 75 FRAME_CODEC_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 76
Azure.IoT Build 0:6ae2f7bca550 77 /* Codes_SRS_FRAME_CODEC_01_020: [If the on_frame_codec_error argument is NULL, frame_codec_create shall return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 78 /* Codes_SRS_FRAME_CODEC_01_104: [The callback_context shall be allowed to be NULL.] */
Azure.IoT Build 0:6ae2f7bca550 79 if (on_frame_codec_error == NULL)
Azure.IoT Build 0:6ae2f7bca550 80 {
Azure.IoT Build 0:6ae2f7bca550 81 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 82 }
Azure.IoT Build 0:6ae2f7bca550 83 else
Azure.IoT Build 0:6ae2f7bca550 84 {
AzureIoTClient 21:f9c433d8e6ca 85 result = malloc(sizeof(FRAME_CODEC_INSTANCE));
Azure.IoT Build 0:6ae2f7bca550 86 /* Codes_SRS_FRAME_CODEC_01_022: [If allocating memory for the frame_codec instance fails, frame_codec_create shall return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 87 if (result != NULL)
Azure.IoT Build 0:6ae2f7bca550 88 {
Azure.IoT Build 0:6ae2f7bca550 89 /* Codes_SRS_FRAME_CODEC_01_021: [frame_codec_create shall create a new instance of frame_codec and return a non-NULL handle to it on success.] */
Azure.IoT Build 0:6ae2f7bca550 90 result->receive_frame_state = RECEIVE_FRAME_STATE_FRAME_SIZE;
Azure.IoT Build 0:6ae2f7bca550 91 result->on_frame_codec_error = on_frame_codec_error;
Azure.IoT Build 0:6ae2f7bca550 92 result->on_frame_codec_error_callback_context = callback_context;
Azure.IoT Build 0:6ae2f7bca550 93 result->receive_frame_pos = 0;
Azure.IoT Build 0:6ae2f7bca550 94 result->receive_frame_size = 0;
Azure.IoT Build 0:6ae2f7bca550 95 result->receive_frame_bytes = NULL;
AzureIoTClient 12:b30dacf113f2 96 result->subscription_list = singlylinkedlist_create();
Azure.IoT Build 0:6ae2f7bca550 97
Azure.IoT Build 0:6ae2f7bca550 98 /* Codes_SRS_FRAME_CODEC_01_082: [The initial max_frame_size_shall be 512.] */
Azure.IoT Build 0:6ae2f7bca550 99 result->max_frame_size = 512;
Azure.IoT Build 0:6ae2f7bca550 100 }
Azure.IoT Build 0:6ae2f7bca550 101 }
Azure.IoT Build 0:6ae2f7bca550 102
Azure.IoT Build 0:6ae2f7bca550 103 return result;
Azure.IoT Build 0:6ae2f7bca550 104 }
Azure.IoT Build 0:6ae2f7bca550 105
Azure.IoT Build 0:6ae2f7bca550 106 void frame_codec_destroy(FRAME_CODEC_HANDLE frame_codec)
Azure.IoT Build 0:6ae2f7bca550 107 {
Azure.IoT Build 0:6ae2f7bca550 108 /* Codes_SRS_FRAME_CODEC_01_024: [If frame_codec is NULL, frame_codec_destroy shall do nothing.] */
Azure.IoT Build 0:6ae2f7bca550 109 if (frame_codec != NULL)
Azure.IoT Build 0:6ae2f7bca550 110 {
Azure.IoT Build 0:6ae2f7bca550 111 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
Azure.IoT Build 0:6ae2f7bca550 112
AzureIoTClient 12:b30dacf113f2 113 singlylinkedlist_destroy(frame_codec_data->subscription_list);
Azure.IoT Build 0:6ae2f7bca550 114 if (frame_codec_data->receive_frame_bytes != NULL)
Azure.IoT Build 0:6ae2f7bca550 115 {
AzureIoTClient 21:f9c433d8e6ca 116 free(frame_codec_data->receive_frame_bytes);
Azure.IoT Build 0:6ae2f7bca550 117 }
Azure.IoT Build 0:6ae2f7bca550 118
Azure.IoT Build 0:6ae2f7bca550 119 /* Codes_SRS_FRAME_CODEC_01_023: [frame_codec_destroy shall free all resources associated with a frame_codec instance.] */
AzureIoTClient 21:f9c433d8e6ca 120 free(frame_codec);
Azure.IoT Build 0:6ae2f7bca550 121 }
Azure.IoT Build 0:6ae2f7bca550 122 }
Azure.IoT Build 0:6ae2f7bca550 123
Azure.IoT Build 0:6ae2f7bca550 124 int frame_codec_set_max_frame_size(FRAME_CODEC_HANDLE frame_codec, uint32_t max_frame_size)
Azure.IoT Build 0:6ae2f7bca550 125 {
Azure.IoT Build 0:6ae2f7bca550 126 int result;
Azure.IoT Build 0:6ae2f7bca550 127 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
Azure.IoT Build 0:6ae2f7bca550 128
Azure.IoT Build 0:6ae2f7bca550 129 /* Codes_SRS_FRAME_CODEC_01_077: [If frame_codec is NULL, frame_codec_set_max_frame_size shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 130 if ((frame_codec == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 131 /* Codes_SRS_FRAME_CODEC_01_078: [If max_frame_size is invalid according to the AMQP standard, frame_codec_set_max_frame_size shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 132 (max_frame_size < FRAME_HEADER_SIZE) ||
Azure.IoT Build 0:6ae2f7bca550 133 /* Codes_SRS_FRAME_CODEC_01_081: [If a frame being decoded already has a size bigger than the max_frame_size argument then frame_codec_set_max_frame_size shall return a non-zero value and the previous frame size shall be kept.] */
Azure.IoT Build 0:6ae2f7bca550 134 ((max_frame_size < frame_codec_data->receive_frame_size) && (frame_codec_data->receive_frame_state != RECEIVE_FRAME_STATE_FRAME_SIZE)) ||
Azure.IoT Build 0:6ae2f7bca550 135 /* Codes_SRS_FRAME_CODEC_01_097: [Setting a frame size on a frame_codec that had a decode error shall fail.] */
AzureIoTClient 21:f9c433d8e6ca 136 (frame_codec_data->receive_frame_state == RECEIVE_FRAME_STATE_ERROR))
Azure.IoT Build 0:6ae2f7bca550 137 {
AzureIoTClient 19:000ab4e6a2c1 138 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 139 }
Azure.IoT Build 0:6ae2f7bca550 140 else
Azure.IoT Build 0:6ae2f7bca550 141 {
Azure.IoT Build 0:6ae2f7bca550 142 /* Codes_SRS_FRAME_CODEC_01_075: [frame_codec_set_max_frame_size shall set the maximum frame size for a frame_codec.] */
Azure.IoT Build 0:6ae2f7bca550 143 /* Codes_SRS_FRAME_CODEC_01_079: [The new frame size shall take effect immediately, even for a frame that is being decoded at the time of the call.] */
Azure.IoT Build 0:6ae2f7bca550 144 frame_codec_data->max_frame_size = max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 145
Azure.IoT Build 0:6ae2f7bca550 146 /* Codes_SRS_FRAME_CODEC_01_076: [On success, frame_codec_set_max_frame_size shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 147 result = 0;
Azure.IoT Build 0:6ae2f7bca550 148 }
Azure.IoT Build 0:6ae2f7bca550 149 return result;
Azure.IoT Build 0:6ae2f7bca550 150 }
Azure.IoT Build 0:6ae2f7bca550 151
Azure.IoT Build 0:6ae2f7bca550 152 /* Codes_SRS_FRAME_CODEC_01_001: [Frames are divided into three distinct areas: a fixed width frame header, a variable width extended header, and a variable width frame body.] */
Azure.IoT Build 0:6ae2f7bca550 153 /* Codes_SRS_FRAME_CODEC_01_002: [frame header The frame header is a fixed size (8 byte) structure that precedes each frame.] */
Azure.IoT Build 0:6ae2f7bca550 154 /* Codes_SRS_FRAME_CODEC_01_003: [The frame header includes mandatory information necessary to parse the rest of the frame including size and type information.] */
Azure.IoT Build 0:6ae2f7bca550 155 /* Codes_SRS_FRAME_CODEC_01_004: [extended header The extended header is a variable width area preceding the frame body.] */
Azure.IoT Build 0:6ae2f7bca550 156 /* Codes_SRS_FRAME_CODEC_01_007: [frame body The frame body is a variable width sequence of bytes the format of which depends on the frame type.] */
Azure.IoT Build 0:6ae2f7bca550 157 /* Codes_SRS_FRAME_CODEC_01_028: [The sequence of bytes shall be decoded according to the AMQP ISO.] */
Azure.IoT Build 0:6ae2f7bca550 158 /* Codes_SRS_FRAME_CODEC_01_029: [The sequence of bytes does not have to be a complete frame, frame_codec shall be responsible for maintaining decoding state between frame_codec_receive_bytes calls.] */
Azure.IoT Build 0:6ae2f7bca550 159 int frame_codec_receive_bytes(FRAME_CODEC_HANDLE frame_codec, const unsigned char* buffer, size_t size)
Azure.IoT Build 0:6ae2f7bca550 160 {
AzureIoTClient 19:000ab4e6a2c1 161 int result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 162 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
Azure.IoT Build 0:6ae2f7bca550 163
Azure.IoT Build 0:6ae2f7bca550 164 /* Codes_SRS_FRAME_CODEC_01_026: [If frame_codec or buffer are NULL, frame_codec_receive_bytes shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 165 if ((frame_codec == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 166 (buffer == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 167 /* Codes_SRS_FRAME_CODEC_01_027: [If size is zero, frame_codec_receive_bytes shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 168 (size == 0))
Azure.IoT Build 0:6ae2f7bca550 169 {
AzureIoTClient 19:000ab4e6a2c1 170 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 171 }
Azure.IoT Build 0:6ae2f7bca550 172 else
Azure.IoT Build 0:6ae2f7bca550 173 {
Azure.IoT Build 0:6ae2f7bca550 174 while (size > 0)
Azure.IoT Build 0:6ae2f7bca550 175 {
Azure.IoT Build 0:6ae2f7bca550 176 switch (frame_codec_data->receive_frame_state)
Azure.IoT Build 0:6ae2f7bca550 177 {
Azure.IoT Build 0:6ae2f7bca550 178 default:
Azure.IoT Build 0:6ae2f7bca550 179 case RECEIVE_FRAME_STATE_ERROR:
Azure.IoT Build 0:6ae2f7bca550 180 /* Codes_SRS_FRAME_CODEC_01_074: [If a decoding error is detected, any subsequent calls on frame_codec_data_receive_bytes shall fail.] */
AzureIoTClient 19:000ab4e6a2c1 181 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 182 size = 0;
Azure.IoT Build 0:6ae2f7bca550 183 break;
Azure.IoT Build 0:6ae2f7bca550 184
Azure.IoT Build 0:6ae2f7bca550 185 /* Codes_SRS_FRAME_CODEC_01_008: [SIZE Bytes 0-3 of the frame header contain the frame size.] */
Azure.IoT Build 0:6ae2f7bca550 186 case RECEIVE_FRAME_STATE_FRAME_SIZE:
Azure.IoT Build 0:6ae2f7bca550 187 /* Codes_SRS_FRAME_CODEC_01_009: [This is an unsigned 32-bit integer that MUST contain the total frame size of the frame header, extended header, and frame body.] */
Azure.IoT Build 0:6ae2f7bca550 188 frame_codec_data->receive_frame_size += buffer[0] << (24 - frame_codec_data->receive_frame_pos * 8);
Azure.IoT Build 0:6ae2f7bca550 189 buffer++;
Azure.IoT Build 0:6ae2f7bca550 190 size--;
Azure.IoT Build 0:6ae2f7bca550 191 frame_codec_data->receive_frame_pos++;
Azure.IoT Build 0:6ae2f7bca550 192
Azure.IoT Build 0:6ae2f7bca550 193 if (frame_codec_data->receive_frame_pos == 4)
Azure.IoT Build 0:6ae2f7bca550 194 {
Azure.IoT Build 0:6ae2f7bca550 195 /* Codes_SRS_FRAME_CODEC_01_010: [The frame is malformed if the size is less than the size of the frame header (8 bytes).] */
Azure.IoT Build 0:6ae2f7bca550 196 if ((frame_codec_data->receive_frame_size < FRAME_HEADER_SIZE) ||
Azure.IoT Build 0:6ae2f7bca550 197 /* Codes_SRS_FRAME_CODEC_01_096: [If a frame bigger than the current max frame size is received, frame_codec_receive_bytes shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 198 (frame_codec_data->receive_frame_size > frame_codec_data->max_frame_size))
Azure.IoT Build 0:6ae2f7bca550 199 {
Azure.IoT Build 0:6ae2f7bca550 200 /* Codes_SRS_FRAME_CODEC_01_074: [If a decoding error is detected, any subsequent calls on frame_codec_data_receive_bytes shall fail.] */
Azure.IoT Build 0:6ae2f7bca550 201 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_ERROR;
Azure.IoT Build 0:6ae2f7bca550 202 /* Codes_SRS_FRAME_CODEC_01_103: [Upon any decode error, if an error callback has been passed to frame_codec_create, then the error callback shall be called with the context argument being the on_frame_codec_error_callback_context argument passed to frame_codec_create.] */
Azure.IoT Build 0:6ae2f7bca550 203 frame_codec_data->on_frame_codec_error(frame_codec_data->on_frame_codec_error_callback_context);
Azure.IoT Build 0:6ae2f7bca550 204
AzureIoTClient 19:000ab4e6a2c1 205 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 206 }
Azure.IoT Build 0:6ae2f7bca550 207 else
Azure.IoT Build 0:6ae2f7bca550 208 {
Azure.IoT Build 0:6ae2f7bca550 209 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_DOFF;
Azure.IoT Build 0:6ae2f7bca550 210 result = 0;
Azure.IoT Build 0:6ae2f7bca550 211 }
Azure.IoT Build 0:6ae2f7bca550 212 }
Azure.IoT Build 0:6ae2f7bca550 213 else
Azure.IoT Build 0:6ae2f7bca550 214 {
Azure.IoT Build 0:6ae2f7bca550 215 result = 0;
Azure.IoT Build 0:6ae2f7bca550 216 }
Azure.IoT Build 0:6ae2f7bca550 217
Azure.IoT Build 0:6ae2f7bca550 218 break;
Azure.IoT Build 0:6ae2f7bca550 219
Azure.IoT Build 0:6ae2f7bca550 220 case RECEIVE_FRAME_STATE_DOFF:
Azure.IoT Build 0:6ae2f7bca550 221 /* Codes_SRS_FRAME_CODEC_01_011: [DOFF Byte 4 of the frame header is the data offset.] */
Azure.IoT Build 0:6ae2f7bca550 222 /* Codes_SRS_FRAME_CODEC_01_013: [The value of the data offset is an unsigned, 8-bit integer specifying a count of 4-byte words.] */
Azure.IoT Build 0:6ae2f7bca550 223 /* Codes_SRS_FRAME_CODEC_01_012: [This gives the position of the body within the frame.] */
Azure.IoT Build 0:6ae2f7bca550 224 frame_codec_data->receive_frame_doff = buffer[0];
Azure.IoT Build 0:6ae2f7bca550 225 buffer++;
Azure.IoT Build 0:6ae2f7bca550 226 size--;
Azure.IoT Build 0:6ae2f7bca550 227
Azure.IoT Build 0:6ae2f7bca550 228 /* Codes_SRS_FRAME_CODEC_01_014: [Due to the mandatory 8-byte frame header, the frame is malformed if the value is less than 2.] */
Azure.IoT Build 0:6ae2f7bca550 229 if (frame_codec_data->receive_frame_doff < 2)
Azure.IoT Build 0:6ae2f7bca550 230 {
Azure.IoT Build 0:6ae2f7bca550 231 /* Codes_SRS_FRAME_CODEC_01_074: [If a decoding error is detected, any subsequent calls on frame_codec_data_receive_bytes shall fail.] */
Azure.IoT Build 0:6ae2f7bca550 232 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_ERROR;
Azure.IoT Build 0:6ae2f7bca550 233
Azure.IoT Build 0:6ae2f7bca550 234 /* Codes_SRS_FRAME_CODEC_01_103: [Upon any decode error, if an error callback has been passed to frame_codec_create, then the error callback shall be called with the context argument being the on_frame_codec_error_callback_context argument passed to frame_codec_create.] */
Azure.IoT Build 0:6ae2f7bca550 235 frame_codec_data->on_frame_codec_error(frame_codec_data->on_frame_codec_error_callback_context);
Azure.IoT Build 0:6ae2f7bca550 236
AzureIoTClient 19:000ab4e6a2c1 237 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 238 }
Azure.IoT Build 0:6ae2f7bca550 239 else
Azure.IoT Build 0:6ae2f7bca550 240 {
Azure.IoT Build 0:6ae2f7bca550 241 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_FRAME_TYPE;
Azure.IoT Build 0:6ae2f7bca550 242 result = 0;
Azure.IoT Build 0:6ae2f7bca550 243 }
Azure.IoT Build 0:6ae2f7bca550 244
Azure.IoT Build 0:6ae2f7bca550 245 break;
Azure.IoT Build 0:6ae2f7bca550 246
Azure.IoT Build 0:6ae2f7bca550 247 case RECEIVE_FRAME_STATE_FRAME_TYPE:
Azure.IoT Build 0:6ae2f7bca550 248 {
Azure.IoT Build 0:6ae2f7bca550 249 LIST_ITEM_HANDLE item_handle;
Azure.IoT Build 0:6ae2f7bca550 250 frame_codec_data->type_specific_size = (frame_codec_data->receive_frame_doff * 4) - 6;
Azure.IoT Build 0:6ae2f7bca550 251
Azure.IoT Build 0:6ae2f7bca550 252 /* Codes_SRS_FRAME_CODEC_01_015: [TYPE Byte 5 of the frame header is a type code.] */
Azure.IoT Build 0:6ae2f7bca550 253 frame_codec_data->receive_frame_type = buffer[0];
Azure.IoT Build 0:6ae2f7bca550 254 buffer++;
Azure.IoT Build 0:6ae2f7bca550 255 size--;
Azure.IoT Build 0:6ae2f7bca550 256
Azure.IoT Build 0:6ae2f7bca550 257 /* Codes_SRS_FRAME_CODEC_01_035: [After successfully registering a callback for a certain frame type, when subsequently that frame type is received the callbacks shall be invoked, passing to it the received frame and the callback_context value.] */
AzureIoTClient 12:b30dacf113f2 258 item_handle = singlylinkedlist_find(frame_codec_data->subscription_list, find_subscription_by_frame_type, &frame_codec_data->receive_frame_type);
Azure.IoT Build 0:6ae2f7bca550 259 if (item_handle == NULL)
Azure.IoT Build 0:6ae2f7bca550 260 {
Azure.IoT Build 0:6ae2f7bca550 261 frame_codec_data->receive_frame_subscription = NULL;
Azure.IoT Build 0:6ae2f7bca550 262 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_TYPE_SPECIFIC;
Azure.IoT Build 0:6ae2f7bca550 263 result = 0;
Azure.IoT Build 0:6ae2f7bca550 264 break;
Azure.IoT Build 0:6ae2f7bca550 265 }
Azure.IoT Build 0:6ae2f7bca550 266 else
Azure.IoT Build 0:6ae2f7bca550 267 {
AzureIoTClient 12:b30dacf113f2 268 frame_codec_data->receive_frame_subscription = (SUBSCRIPTION*)singlylinkedlist_item_get_value(item_handle);
Azure.IoT Build 0:6ae2f7bca550 269 if (frame_codec_data->receive_frame_subscription == NULL)
Azure.IoT Build 0:6ae2f7bca550 270 {
Azure.IoT Build 0:6ae2f7bca550 271 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_TYPE_SPECIFIC;
Azure.IoT Build 0:6ae2f7bca550 272 result = 0;
Azure.IoT Build 0:6ae2f7bca550 273 break;
Azure.IoT Build 0:6ae2f7bca550 274 }
Azure.IoT Build 0:6ae2f7bca550 275 else
Azure.IoT Build 0:6ae2f7bca550 276 {
Azure.IoT Build 0:6ae2f7bca550 277 frame_codec_data->receive_frame_pos = 0;
Azure.IoT Build 0:6ae2f7bca550 278
Azure.IoT Build 0:6ae2f7bca550 279 /* Codes_SRS_FRAME_CODEC_01_102: [frame_codec_receive_bytes shall allocate memory to hold the frame_body bytes.] */
AzureIoTClient 21:f9c433d8e6ca 280 frame_codec_data->receive_frame_bytes = (unsigned char*)malloc(frame_codec_data->receive_frame_size - 6);
Azure.IoT Build 0:6ae2f7bca550 281 if (frame_codec_data->receive_frame_bytes == NULL)
Azure.IoT Build 0:6ae2f7bca550 282 {
Azure.IoT Build 0:6ae2f7bca550 283 /* Codes_SRS_FRAME_CODEC_01_101: [If the memory for the frame_body bytes cannot be allocated, frame_codec_receive_bytes shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 284 /* Codes_SRS_FRAME_CODEC_01_030: [If a decoding error occurs, frame_codec_data_receive_bytes shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 285 /* Codes_SRS_FRAME_CODEC_01_074: [If a decoding error is detected, any subsequent calls on frame_codec_data_receive_bytes shall fail.] */
Azure.IoT Build 0:6ae2f7bca550 286 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_ERROR;
Azure.IoT Build 0:6ae2f7bca550 287
Azure.IoT Build 0:6ae2f7bca550 288 /* Codes_SRS_FRAME_CODEC_01_103: [Upon any decode error, if an error callback has been passed to frame_codec_create, then the error callback shall be called with the context argument being the on_frame_codec_error_callback_context argument passed to frame_codec_create.] */
Azure.IoT Build 0:6ae2f7bca550 289 frame_codec_data->on_frame_codec_error(frame_codec_data->on_frame_codec_error_callback_context);
Azure.IoT Build 0:6ae2f7bca550 290
AzureIoTClient 19:000ab4e6a2c1 291 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 292 break;
Azure.IoT Build 0:6ae2f7bca550 293 }
Azure.IoT Build 0:6ae2f7bca550 294 else
Azure.IoT Build 0:6ae2f7bca550 295 {
Azure.IoT Build 0:6ae2f7bca550 296 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_TYPE_SPECIFIC;
Azure.IoT Build 0:6ae2f7bca550 297 result = 0;
Azure.IoT Build 0:6ae2f7bca550 298 break;
Azure.IoT Build 0:6ae2f7bca550 299 }
Azure.IoT Build 0:6ae2f7bca550 300 }
Azure.IoT Build 0:6ae2f7bca550 301 }
Azure.IoT Build 0:6ae2f7bca550 302 }
Azure.IoT Build 0:6ae2f7bca550 303
Azure.IoT Build 0:6ae2f7bca550 304 case RECEIVE_FRAME_STATE_TYPE_SPECIFIC:
Azure.IoT Build 0:6ae2f7bca550 305 {
AzureIoTClient 6:641a9672db08 306 size_t to_copy = frame_codec_data->type_specific_size - frame_codec_data->receive_frame_pos;
Azure.IoT Build 0:6ae2f7bca550 307 if (to_copy > size)
Azure.IoT Build 0:6ae2f7bca550 308 {
Azure.IoT Build 0:6ae2f7bca550 309 to_copy = size;
Azure.IoT Build 0:6ae2f7bca550 310 }
Azure.IoT Build 0:6ae2f7bca550 311
Azure.IoT Build 0:6ae2f7bca550 312 if (frame_codec_data->receive_frame_subscription != NULL)
Azure.IoT Build 0:6ae2f7bca550 313 {
Azure.IoT Build 0:6ae2f7bca550 314 (void)memcpy(&frame_codec_data->receive_frame_bytes[frame_codec_data->receive_frame_pos], buffer, to_copy);
Azure.IoT Build 0:6ae2f7bca550 315 frame_codec_data->receive_frame_pos += to_copy;
Azure.IoT Build 0:6ae2f7bca550 316 buffer += to_copy;
Azure.IoT Build 0:6ae2f7bca550 317 size -= to_copy;
Azure.IoT Build 0:6ae2f7bca550 318 }
Azure.IoT Build 0:6ae2f7bca550 319 else
Azure.IoT Build 0:6ae2f7bca550 320 {
Azure.IoT Build 0:6ae2f7bca550 321 frame_codec_data->receive_frame_pos += to_copy;
Azure.IoT Build 0:6ae2f7bca550 322 buffer += to_copy;
Azure.IoT Build 0:6ae2f7bca550 323 size -= to_copy;
Azure.IoT Build 0:6ae2f7bca550 324 }
Azure.IoT Build 0:6ae2f7bca550 325
Azure.IoT Build 0:6ae2f7bca550 326 if (frame_codec_data->receive_frame_pos == frame_codec_data->type_specific_size)
Azure.IoT Build 0:6ae2f7bca550 327 {
Azure.IoT Build 0:6ae2f7bca550 328 if (frame_codec_data->receive_frame_size == FRAME_HEADER_SIZE)
Azure.IoT Build 0:6ae2f7bca550 329 {
Azure.IoT Build 0:6ae2f7bca550 330 if (frame_codec_data->receive_frame_subscription != NULL)
Azure.IoT Build 0:6ae2f7bca550 331 {
Azure.IoT Build 0:6ae2f7bca550 332 /* Codes_SRS_FRAME_CODEC_01_031: [When a complete frame is successfully decoded it shall be indicated to the upper layer by invoking the on_frame_received passed to frame_codec_subscribe.] */
Azure.IoT Build 0:6ae2f7bca550 333 /* Codes_SRS_FRAME_CODEC_01_032: [Besides passing the frame information, the callback_context value passed to frame_codec_data_subscribe shall be passed to the on_frame_received function.] */
Azure.IoT Build 0:6ae2f7bca550 334 /* Codes_SRS_FRAME_CODEC_01_005: [This is an extension point defined for future expansion.] */
Azure.IoT Build 0:6ae2f7bca550 335 /* Codes_SRS_FRAME_CODEC_01_006: [The treatment of this area depends on the frame type.] */
Azure.IoT Build 0:6ae2f7bca550 336 /* Codes_SRS_FRAME_CODEC_01_100: [If the frame body size is 0, the frame_body pointer passed to on_frame_received shall be NULL.] */
Azure.IoT Build 0:6ae2f7bca550 337 frame_codec_data->receive_frame_subscription->on_frame_received(frame_codec_data->receive_frame_subscription->callback_context, frame_codec_data->receive_frame_bytes, frame_codec_data->type_specific_size, NULL, 0);
AzureIoTClient 21:f9c433d8e6ca 338 free(frame_codec_data->receive_frame_bytes);
Azure.IoT Build 0:6ae2f7bca550 339 frame_codec_data->receive_frame_bytes = NULL;
Azure.IoT Build 0:6ae2f7bca550 340 }
Azure.IoT Build 0:6ae2f7bca550 341
Azure.IoT Build 0:6ae2f7bca550 342 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_FRAME_SIZE;
Azure.IoT Build 0:6ae2f7bca550 343 frame_codec_data->receive_frame_size = 0;
Azure.IoT Build 0:6ae2f7bca550 344 }
Azure.IoT Build 0:6ae2f7bca550 345 else
Azure.IoT Build 0:6ae2f7bca550 346 {
Azure.IoT Build 0:6ae2f7bca550 347 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_FRAME_BODY;
Azure.IoT Build 0:6ae2f7bca550 348 }
Azure.IoT Build 0:6ae2f7bca550 349
Azure.IoT Build 0:6ae2f7bca550 350 frame_codec_data->receive_frame_pos = 0;
Azure.IoT Build 0:6ae2f7bca550 351 }
Azure.IoT Build 0:6ae2f7bca550 352
Azure.IoT Build 0:6ae2f7bca550 353 result = 0;
Azure.IoT Build 0:6ae2f7bca550 354 break;
Azure.IoT Build 0:6ae2f7bca550 355 }
Azure.IoT Build 0:6ae2f7bca550 356
Azure.IoT Build 0:6ae2f7bca550 357 case RECEIVE_FRAME_STATE_FRAME_BODY:
Azure.IoT Build 0:6ae2f7bca550 358 {
Azure.IoT Build 0:6ae2f7bca550 359 uint32_t frame_body_size = frame_codec_data->receive_frame_size - (frame_codec_data->receive_frame_doff * 4);
AzureIoTClient 6:641a9672db08 360 size_t to_copy = frame_body_size - frame_codec_data->receive_frame_pos;
Azure.IoT Build 0:6ae2f7bca550 361
Azure.IoT Build 0:6ae2f7bca550 362 if (to_copy > size)
Azure.IoT Build 0:6ae2f7bca550 363 {
Azure.IoT Build 0:6ae2f7bca550 364 to_copy = size;
Azure.IoT Build 0:6ae2f7bca550 365 }
Azure.IoT Build 0:6ae2f7bca550 366
Azure.IoT Build 0:6ae2f7bca550 367 (void)memcpy(frame_codec_data->receive_frame_bytes + frame_codec_data->receive_frame_pos + frame_codec_data->type_specific_size, buffer, to_copy);
Azure.IoT Build 0:6ae2f7bca550 368
Azure.IoT Build 0:6ae2f7bca550 369 buffer += to_copy;
Azure.IoT Build 0:6ae2f7bca550 370 size -= to_copy;
Azure.IoT Build 0:6ae2f7bca550 371 frame_codec_data->receive_frame_pos += to_copy;
Azure.IoT Build 0:6ae2f7bca550 372
Azure.IoT Build 0:6ae2f7bca550 373 if (frame_codec_data->receive_frame_pos == frame_body_size)
Azure.IoT Build 0:6ae2f7bca550 374 {
Azure.IoT Build 0:6ae2f7bca550 375 if (frame_codec_data->receive_frame_subscription != NULL)
Azure.IoT Build 0:6ae2f7bca550 376 {
Azure.IoT Build 0:6ae2f7bca550 377 /* Codes_SRS_FRAME_CODEC_01_031: [When a complete frame is successfully decoded it shall be indicated to the upper layer by invoking the on_frame_received passed to frame_codec_subscribe.] */
Azure.IoT Build 0:6ae2f7bca550 378 /* Codes_SRS_FRAME_CODEC_01_032: [Besides passing the frame information, the callback_context value passed to frame_codec_data_subscribe shall be passed to the on_frame_received function.] */
Azure.IoT Build 0:6ae2f7bca550 379 /* Codes_SRS_FRAME_CODEC_01_005: [This is an extension point defined for future expansion.] */
Azure.IoT Build 0:6ae2f7bca550 380 /* Codes_SRS_FRAME_CODEC_01_006: [The treatment of this area depends on the frame type.] */
Azure.IoT Build 0:6ae2f7bca550 381 /* Codes_SRS_FRAME_CODEC_01_099: [A pointer to the frame_body bytes shall also be passed to the on_frame_received.] */
Azure.IoT Build 0:6ae2f7bca550 382 frame_codec_data->receive_frame_subscription->on_frame_received(frame_codec_data->receive_frame_subscription->callback_context, frame_codec_data->receive_frame_bytes, frame_codec_data->type_specific_size, frame_codec_data->receive_frame_bytes + frame_codec_data->type_specific_size, frame_body_size);
AzureIoTClient 21:f9c433d8e6ca 383 free(frame_codec_data->receive_frame_bytes);
Azure.IoT Build 0:6ae2f7bca550 384 frame_codec_data->receive_frame_bytes = NULL;
Azure.IoT Build 0:6ae2f7bca550 385 }
Azure.IoT Build 0:6ae2f7bca550 386
Azure.IoT Build 0:6ae2f7bca550 387 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_FRAME_SIZE;
Azure.IoT Build 0:6ae2f7bca550 388 frame_codec_data->receive_frame_pos = 0;
Azure.IoT Build 0:6ae2f7bca550 389 frame_codec_data->receive_frame_size = 0;
Azure.IoT Build 0:6ae2f7bca550 390 }
Azure.IoT Build 0:6ae2f7bca550 391 result = 0;
Azure.IoT Build 0:6ae2f7bca550 392
Azure.IoT Build 0:6ae2f7bca550 393 break;
Azure.IoT Build 0:6ae2f7bca550 394 }
Azure.IoT Build 0:6ae2f7bca550 395 }
Azure.IoT Build 0:6ae2f7bca550 396 }
Azure.IoT Build 0:6ae2f7bca550 397 }
Azure.IoT Build 0:6ae2f7bca550 398
Azure.IoT Build 0:6ae2f7bca550 399 return result;
Azure.IoT Build 0:6ae2f7bca550 400 }
Azure.IoT Build 0:6ae2f7bca550 401
Azure.IoT Build 0:6ae2f7bca550 402 /* Codes_SRS_FRAME_CODEC_01_033: [frame_codec_subscribe subscribes for a certain type of frame received by the frame_codec instance identified by frame_codec.] */
Azure.IoT Build 0:6ae2f7bca550 403 int frame_codec_subscribe(FRAME_CODEC_HANDLE frame_codec, uint8_t type, ON_FRAME_RECEIVED on_frame_received, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 404 {
Azure.IoT Build 0:6ae2f7bca550 405 int result;
Azure.IoT Build 0:6ae2f7bca550 406
Azure.IoT Build 0:6ae2f7bca550 407 /* Codes_SRS_FRAME_CODEC_01_034: [If any of the frame_codec or on_frame_received arguments is NULL, frame_codec_subscribe shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 408 if ((frame_codec == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 409 (on_frame_received == NULL))
Azure.IoT Build 0:6ae2f7bca550 410 {
AzureIoTClient 19:000ab4e6a2c1 411 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 412 }
Azure.IoT Build 0:6ae2f7bca550 413 else
Azure.IoT Build 0:6ae2f7bca550 414 {
Azure.IoT Build 0:6ae2f7bca550 415 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
Azure.IoT Build 0:6ae2f7bca550 416 SUBSCRIPTION* subscription;
Azure.IoT Build 0:6ae2f7bca550 417
Azure.IoT Build 0:6ae2f7bca550 418 /* Codes_SRS_FRAME_CODEC_01_036: [Only one callback pair shall be allowed to be registered for a given frame type.] */
Azure.IoT Build 0:6ae2f7bca550 419 /* find the subscription for this frame type */
AzureIoTClient 12:b30dacf113f2 420 LIST_ITEM_HANDLE list_item = singlylinkedlist_find(frame_codec_data->subscription_list, find_subscription_by_frame_type, &type);
Azure.IoT Build 0:6ae2f7bca550 421 if (list_item != NULL)
Azure.IoT Build 0:6ae2f7bca550 422 {
AzureIoTClient 12:b30dacf113f2 423 subscription = (SUBSCRIPTION*)singlylinkedlist_item_get_value(list_item);
Azure.IoT Build 0:6ae2f7bca550 424 if (subscription == NULL)
Azure.IoT Build 0:6ae2f7bca550 425 {
Azure.IoT Build 0:6ae2f7bca550 426 /* Codes_SRS_FRAME_CODEC_01_037: [If any failure occurs while performing the subscribe operation, frame_codec_subscribe shall return a non-zero value.] */
AzureIoTClient 19:000ab4e6a2c1 427 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 428 }
Azure.IoT Build 0:6ae2f7bca550 429 else
Azure.IoT Build 0:6ae2f7bca550 430 {
Azure.IoT Build 0:6ae2f7bca550 431 /* a subscription was found */
Azure.IoT Build 0:6ae2f7bca550 432 subscription->on_frame_received = on_frame_received;
Azure.IoT Build 0:6ae2f7bca550 433 subscription->callback_context = callback_context;
Azure.IoT Build 0:6ae2f7bca550 434
Azure.IoT Build 0:6ae2f7bca550 435 /* Codes_SRS_FRAME_CODEC_01_087: [On success, frame_codec_subscribe shall return zero.] */
Azure.IoT Build 0:6ae2f7bca550 436 result = 0;
Azure.IoT Build 0:6ae2f7bca550 437 }
Azure.IoT Build 0:6ae2f7bca550 438 }
Azure.IoT Build 0:6ae2f7bca550 439 else
Azure.IoT Build 0:6ae2f7bca550 440 {
Azure.IoT Build 0:6ae2f7bca550 441 /* add a new subscription */
AzureIoTClient 21:f9c433d8e6ca 442 subscription = (SUBSCRIPTION*)malloc(sizeof(SUBSCRIPTION));
Azure.IoT Build 0:6ae2f7bca550 443 /* Codes_SRS_FRAME_CODEC_01_037: [If any failure occurs while performing the subscribe operation, frame_codec_subscribe shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 444 if (subscription == NULL)
Azure.IoT Build 0:6ae2f7bca550 445 {
AzureIoTClient 19:000ab4e6a2c1 446 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 447 }
Azure.IoT Build 0:6ae2f7bca550 448 else
Azure.IoT Build 0:6ae2f7bca550 449 {
Azure.IoT Build 0:6ae2f7bca550 450 subscription->on_frame_received = on_frame_received;
Azure.IoT Build 0:6ae2f7bca550 451 subscription->callback_context = callback_context;
Azure.IoT Build 0:6ae2f7bca550 452 subscription->frame_type = type;
Azure.IoT Build 0:6ae2f7bca550 453
Azure.IoT Build 0:6ae2f7bca550 454 /* Codes_SRS_FRAME_CODEC_01_037: [If any failure occurs while performing the subscribe operation, frame_codec_subscribe shall return a non-zero value.] */
AzureIoTClient 12:b30dacf113f2 455 if (singlylinkedlist_add(frame_codec_data->subscription_list, subscription) == NULL)
Azure.IoT Build 0:6ae2f7bca550 456 {
AzureIoTClient 21:f9c433d8e6ca 457 free(subscription);
AzureIoTClient 19:000ab4e6a2c1 458 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 459 }
Azure.IoT Build 0:6ae2f7bca550 460 else
Azure.IoT Build 0:6ae2f7bca550 461 {
Azure.IoT Build 0:6ae2f7bca550 462 /* Codes_SRS_FRAME_CODEC_01_087: [On success, frame_codec_subscribe shall return zero.] */
Azure.IoT Build 0:6ae2f7bca550 463 result = 0;
Azure.IoT Build 0:6ae2f7bca550 464 }
Azure.IoT Build 0:6ae2f7bca550 465 }
Azure.IoT Build 0:6ae2f7bca550 466 }
Azure.IoT Build 0:6ae2f7bca550 467 }
Azure.IoT Build 0:6ae2f7bca550 468
Azure.IoT Build 0:6ae2f7bca550 469 return result;
Azure.IoT Build 0:6ae2f7bca550 470 }
Azure.IoT Build 0:6ae2f7bca550 471
Azure.IoT Build 0:6ae2f7bca550 472 int frame_codec_unsubscribe(FRAME_CODEC_HANDLE frame_codec, uint8_t type)
Azure.IoT Build 0:6ae2f7bca550 473 {
Azure.IoT Build 0:6ae2f7bca550 474 int result;
Azure.IoT Build 0:6ae2f7bca550 475
Azure.IoT Build 0:6ae2f7bca550 476 /* Codes_SRS_FRAME_CODEC_01_039: [If frame_codec is NULL, frame_codec_unsubscribe shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 477 if (frame_codec == NULL)
Azure.IoT Build 0:6ae2f7bca550 478 {
AzureIoTClient 19:000ab4e6a2c1 479 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 480 }
Azure.IoT Build 0:6ae2f7bca550 481 else
Azure.IoT Build 0:6ae2f7bca550 482 {
Azure.IoT Build 0:6ae2f7bca550 483 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
AzureIoTClient 12:b30dacf113f2 484 LIST_ITEM_HANDLE list_item = singlylinkedlist_find(frame_codec_data->subscription_list, find_subscription_by_frame_type, &type);
Azure.IoT Build 0:6ae2f7bca550 485
Azure.IoT Build 0:6ae2f7bca550 486 if (list_item == NULL)
Azure.IoT Build 0:6ae2f7bca550 487 {
Azure.IoT Build 0:6ae2f7bca550 488 /* Codes_SRS_FRAME_CODEC_01_040: [If no subscription for the type frame type exists, frame_codec_unsubscribe shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 489 /* Codes_SRS_FRAME_CODEC_01_041: [If any failure occurs while performing the unsubscribe operation, frame_codec_unsubscribe shall return a non-zero value.] */
AzureIoTClient 19:000ab4e6a2c1 490 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 491 }
Azure.IoT Build 0:6ae2f7bca550 492 else
Azure.IoT Build 0:6ae2f7bca550 493 {
AzureIoTClient 12:b30dacf113f2 494 SUBSCRIPTION* subscription = (SUBSCRIPTION*)singlylinkedlist_item_get_value(list_item);
Azure.IoT Build 0:6ae2f7bca550 495 if (subscription == NULL)
Azure.IoT Build 0:6ae2f7bca550 496 {
Azure.IoT Build 0:6ae2f7bca550 497 /* Codes_SRS_FRAME_CODEC_01_041: [If any failure occurs while performing the unsubscribe operation, frame_codec_unsubscribe shall return a non-zero value.] */
AzureIoTClient 19:000ab4e6a2c1 498 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 499 }
Azure.IoT Build 0:6ae2f7bca550 500 else
Azure.IoT Build 0:6ae2f7bca550 501 {
AzureIoTClient 21:f9c433d8e6ca 502 free(subscription);
AzureIoTClient 12:b30dacf113f2 503 if (singlylinkedlist_remove(frame_codec_data->subscription_list, list_item) != 0)
Azure.IoT Build 0:6ae2f7bca550 504 {
Azure.IoT Build 0:6ae2f7bca550 505 /* Codes_SRS_FRAME_CODEC_01_041: [If any failure occurs while performing the unsubscribe operation, frame_codec_unsubscribe shall return a non-zero value.] */
AzureIoTClient 19:000ab4e6a2c1 506 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 507 }
Azure.IoT Build 0:6ae2f7bca550 508 else
Azure.IoT Build 0:6ae2f7bca550 509 {
Azure.IoT Build 0:6ae2f7bca550 510 /* Codes_SRS_FRAME_CODEC_01_038: [frame_codec_unsubscribe removes a previous subscription for frames of type type and on success it shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 511 result = 0;
Azure.IoT Build 0:6ae2f7bca550 512 }
Azure.IoT Build 0:6ae2f7bca550 513 }
Azure.IoT Build 0:6ae2f7bca550 514 }
Azure.IoT Build 0:6ae2f7bca550 515 }
Azure.IoT Build 0:6ae2f7bca550 516
Azure.IoT Build 0:6ae2f7bca550 517 return result;
Azure.IoT Build 0:6ae2f7bca550 518 }
Azure.IoT Build 0:6ae2f7bca550 519
Azure.IoT Build 0:6ae2f7bca550 520 int frame_codec_encode_frame(FRAME_CODEC_HANDLE frame_codec, uint8_t type, const PAYLOAD* payloads, size_t payload_count, const unsigned char* type_specific_bytes, uint32_t type_specific_size, ON_BYTES_ENCODED on_bytes_encoded, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 521 {
Azure.IoT Build 0:6ae2f7bca550 522 int result;
Azure.IoT Build 0:6ae2f7bca550 523
Azure.IoT Build 0:6ae2f7bca550 524 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
Azure.IoT Build 0:6ae2f7bca550 525
AzureIoTClient 21:f9c433d8e6ca 526 /* Codes_SRS_FRAME_CODEC_01_044: [If any of arguments `frame_codec` or `on_bytes_encoded` is NULL, `frame_codec_encode_frame` shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 527 if ((frame_codec == NULL) ||
AzureIoTClient 21:f9c433d8e6ca 528 (on_bytes_encoded == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 529 /* Codes_SRS_FRAME_CODEC_01_091: [If the argument type_specific_size is greater than 0 and type_specific_bytes is NULL, frame_codec_encode_frame shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 530 ((type_specific_size > 0) && (type_specific_bytes == NULL)) ||
Azure.IoT Build 0:6ae2f7bca550 531 /* Codes_SRS_FRAME_CODEC_01_092: [If type_specific_size is too big to allow encoding the frame according to the AMQP ISO then frame_codec_encode_frame shall return a non-zero value.] */
AzureIoTClient 21:f9c433d8e6ca 532 (type_specific_size > MAX_TYPE_SPECIFIC_SIZE))
Azure.IoT Build 0:6ae2f7bca550 533 {
AzureIoTClient 21:f9c433d8e6ca 534 LogError("Bad arguments: frame_codec = %p, on_bytes_encoded = %p, type_specific_size = %u, type_specific_bytes = %p",
AzureIoTClient 21:f9c433d8e6ca 535 frame_codec, on_bytes_encoded, (unsigned int)type_specific_size, type_specific_bytes);
AzureIoTClient 19:000ab4e6a2c1 536 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 537 }
AzureIoTClient 21:f9c433d8e6ca 538 else if ((payloads == NULL) && (payload_count > 0))
AzureIoTClient 21:f9c433d8e6ca 539 {
AzureIoTClient 21:f9c433d8e6ca 540 /* Codes_SRS_FRAME_CODEC_01_107: [If the argument `payloads` is NULL and `payload_count` is non-zero, `frame_codec_encode_frame` shall return a non-zero value.]*/
AzureIoTClient 21:f9c433d8e6ca 541 LogError("NULL payloads argument with non-zero payload count");
AzureIoTClient 21:f9c433d8e6ca 542 result = __FAILURE__;
AzureIoTClient 21:f9c433d8e6ca 543 }
AzureIoTClient 21:f9c433d8e6ca 544 else
Azure.IoT Build 0:6ae2f7bca550 545 {
AzureIoTClient 6:641a9672db08 546 /* round up to the 4 bytes for doff */
AzureIoTClient 6:641a9672db08 547 /* Codes_SRS_FRAME_CODEC_01_067: [The value of the data offset is an unsigned, 8-bit integer specifying a count of 4-byte words.] */
AzureIoTClient 6:641a9672db08 548 /* Codes_SRS_FRAME_CODEC_01_068: [Due to the mandatory 8-byte frame header, the frame is malformed if the value is less than 2.] */
AzureIoTClient 6:641a9672db08 549 uint8_t padding_byte_count;
AzureIoTClient 6:641a9672db08 550 uint32_t frame_body_offset = type_specific_size + 6;
AzureIoTClient 6:641a9672db08 551 uint8_t doff = (uint8_t)((frame_body_offset + 3) / 4);
AzureIoTClient 6:641a9672db08 552 size_t i;
AzureIoTClient 6:641a9672db08 553 size_t frame_size;
AzureIoTClient 6:641a9672db08 554 size_t frame_body_size = 0;
AzureIoTClient 6:641a9672db08 555 frame_body_offset = doff * 4;
AzureIoTClient 6:641a9672db08 556 padding_byte_count = (uint8_t)(frame_body_offset - type_specific_size - 6);
Azure.IoT Build 0:6ae2f7bca550 557
AzureIoTClient 6:641a9672db08 558 for (i = 0; i < payload_count; i++)
AzureIoTClient 6:641a9672db08 559 {
AzureIoTClient 21:f9c433d8e6ca 560 /* Codes_SRS_FRAME_CODEC_01_110: [ If the `bytes` member of a payload entry is NULL, `frame_codec_encode_frame` shall fail and return a non-zero value. ] */
AzureIoTClient 21:f9c433d8e6ca 561 if ((payloads[i].bytes == NULL) ||
AzureIoTClient 21:f9c433d8e6ca 562 /* Codes_SRS_FRAME_CODEC_01_111: [ If the `length` member of a payload entry is 0, `frame_codec_encode_frame` shall fail and return a non-zero value. ] */
AzureIoTClient 21:f9c433d8e6ca 563 (payloads[i].length == 0))
AzureIoTClient 21:f9c433d8e6ca 564 {
AzureIoTClient 21:f9c433d8e6ca 565 break;
AzureIoTClient 21:f9c433d8e6ca 566 }
AzureIoTClient 21:f9c433d8e6ca 567
AzureIoTClient 6:641a9672db08 568 frame_body_size += payloads[i].length;
AzureIoTClient 6:641a9672db08 569 }
AzureIoTClient 6:641a9672db08 570
AzureIoTClient 21:f9c433d8e6ca 571 if (i < payload_count)
AzureIoTClient 6:641a9672db08 572 {
AzureIoTClient 21:f9c433d8e6ca 573 LogError("Bad payload entry");
AzureIoTClient 19:000ab4e6a2c1 574 result = __FAILURE__;
AzureIoTClient 6:641a9672db08 575 }
AzureIoTClient 6:641a9672db08 576 else
AzureIoTClient 6:641a9672db08 577 {
AzureIoTClient 6:641a9672db08 578 /* Codes_SRS_FRAME_CODEC_01_063: [This is an unsigned 32-bit integer that MUST contain the total frame size of the frame header, extended header, and frame body.] */
AzureIoTClient 21:f9c433d8e6ca 579 frame_size = frame_body_size + frame_body_offset;
Azure.IoT Build 0:6ae2f7bca550 580
AzureIoTClient 21:f9c433d8e6ca 581 if (frame_size > frame_codec_data->max_frame_size)
AzureIoTClient 21:f9c433d8e6ca 582 {
AzureIoTClient 21:f9c433d8e6ca 583 /* Codes_SRS_FRAME_CODEC_01_095: [If the frame_size needed for the frame is bigger than the maximum frame size, frame_codec_encode_frame shall fail and return a non-zero value.] */
AzureIoTClient 21:f9c433d8e6ca 584 LogError("Encoded frame size exceeds the maximum allowed frame size");
AzureIoTClient 21:f9c433d8e6ca 585 result = __FAILURE__;
AzureIoTClient 21:f9c433d8e6ca 586 }
AzureIoTClient 21:f9c433d8e6ca 587 else
AzureIoTClient 21:f9c433d8e6ca 588 {
AzureIoTClient 21:f9c433d8e6ca 589 /* Codes_SRS_FRAME_CODEC_01_108: [ Memory shall be allocated to hold the entire frame. ]*/
AzureIoTClient 21:f9c433d8e6ca 590 unsigned char* encoded_frame = (unsigned char*)malloc(frame_size);
AzureIoTClient 21:f9c433d8e6ca 591 if (encoded_frame == NULL)
AzureIoTClient 21:f9c433d8e6ca 592 {
AzureIoTClient 21:f9c433d8e6ca 593 /* Codes_SRS_FRAME_CODEC_01_109: [ If allocating memory fails, `frame_codec_encode_frame` shall fail and return a non-zero value. ]*/
AzureIoTClient 21:f9c433d8e6ca 594 LogError("Cannot allocate memory for frame");
AzureIoTClient 21:f9c433d8e6ca 595 result = __FAILURE__;
AzureIoTClient 21:f9c433d8e6ca 596 }
AzureIoTClient 21:f9c433d8e6ca 597 else
AzureIoTClient 21:f9c433d8e6ca 598 {
AzureIoTClient 21:f9c433d8e6ca 599 /* Codes_SRS_FRAME_CODEC_01_042: [frame_codec_encode_frame encodes the header, type specific bytes and frame payload of a frame that has frame_payload_size bytes.]*/
AzureIoTClient 21:f9c433d8e6ca 600 /* Codes_SRS_FRAME_CODEC_01_055: [Frames are divided into three distinct areas: a fixed width frame header, a variable width extended header, and a variable width frame body.] */
AzureIoTClient 21:f9c433d8e6ca 601 /* Codes_SRS_FRAME_CODEC_01_056: [frame header The frame header is a fixed size (8 byte) structure that precedes each frame.] */
AzureIoTClient 21:f9c433d8e6ca 602 /* Codes_SRS_FRAME_CODEC_01_057: [The frame header includes mandatory information necessary to parse the rest of the frame including size and type information.] */
AzureIoTClient 21:f9c433d8e6ca 603 /* Codes_SRS_FRAME_CODEC_01_058: [extended header The extended header is a variable width area preceding the frame body.] */
AzureIoTClient 21:f9c433d8e6ca 604 /* Codes_SRS_FRAME_CODEC_01_059: [This is an extension point defined for future expansion.] */
AzureIoTClient 21:f9c433d8e6ca 605 /* Codes_SRS_FRAME_CODEC_01_060: [The treatment of this area depends on the frame type.]*/
AzureIoTClient 21:f9c433d8e6ca 606 /* Codes_SRS_FRAME_CODEC_01_062: [SIZE Bytes 0-3 of the frame header contain the frame size.] */
AzureIoTClient 21:f9c433d8e6ca 607 /* Codes_SRS_FRAME_CODEC_01_063: [This is an unsigned 32-bit integer that MUST contain the total frame size of the frame header, extended header, and frame body.] */
AzureIoTClient 21:f9c433d8e6ca 608 /* Codes_SRS_FRAME_CODEC_01_064: [The frame is malformed if the size is less than the size of the frame header (8 bytes).] */
AzureIoTClient 21:f9c433d8e6ca 609 unsigned char frame_header[6];
AzureIoTClient 21:f9c433d8e6ca 610 size_t current_pos = 0;
AzureIoTClient 6:641a9672db08 611
AzureIoTClient 21:f9c433d8e6ca 612 frame_header[0] = (frame_size >> 24) & 0xFF;
AzureIoTClient 21:f9c433d8e6ca 613 frame_header[1] = (frame_size >> 16) & 0xFF;
AzureIoTClient 21:f9c433d8e6ca 614 frame_header[2] = (frame_size >> 8) & 0xFF;
AzureIoTClient 21:f9c433d8e6ca 615 frame_header[3] = frame_size & 0xFF;
AzureIoTClient 21:f9c433d8e6ca 616 /* Codes_SRS_FRAME_CODEC_01_065: [DOFF Byte 4 of the frame header is the data offset.] */
AzureIoTClient 21:f9c433d8e6ca 617 frame_header[4] = doff;
AzureIoTClient 21:f9c433d8e6ca 618 /* Codes_SRS_FRAME_CODEC_01_069: [TYPE Byte 5 of the frame header is a type code.] */
AzureIoTClient 21:f9c433d8e6ca 619 frame_header[5] = type;
AzureIoTClient 6:641a9672db08 620
AzureIoTClient 21:f9c433d8e6ca 621 (void)memcpy(encoded_frame, frame_header, sizeof(frame_header));
AzureIoTClient 21:f9c433d8e6ca 622 current_pos += sizeof(frame_header);
AzureIoTClient 21:f9c433d8e6ca 623
AzureIoTClient 21:f9c433d8e6ca 624 if (type_specific_size > 0)
AzureIoTClient 21:f9c433d8e6ca 625 {
AzureIoTClient 21:f9c433d8e6ca 626 (void)memcpy(encoded_frame + current_pos, type_specific_bytes, type_specific_size);
AzureIoTClient 21:f9c433d8e6ca 627 current_pos += type_specific_size;
AzureIoTClient 21:f9c433d8e6ca 628 }
AzureIoTClient 21:f9c433d8e6ca 629
AzureIoTClient 21:f9c433d8e6ca 630 /* send padding bytes */
AzureIoTClient 21:f9c433d8e6ca 631 /* Codes_SRS_FRAME_CODEC_01_090: [If the type_specific_size - 2 does not divide by 4, frame_codec_encode_frame shall pad the type_specific bytes with zeroes so that type specific data is according to the AMQP ISO.] */
AzureIoTClient 21:f9c433d8e6ca 632 unsigned char padding_bytes[] = { 0x00, 0x00, 0x00 };
Azure.IoT Build 0:6ae2f7bca550 633
AzureIoTClient 21:f9c433d8e6ca 634 if (padding_byte_count > 0)
AzureIoTClient 21:f9c433d8e6ca 635 {
AzureIoTClient 21:f9c433d8e6ca 636 (void)memcpy(encoded_frame + current_pos, padding_bytes, padding_byte_count);
AzureIoTClient 21:f9c433d8e6ca 637 current_pos += padding_byte_count;
AzureIoTClient 21:f9c433d8e6ca 638 }
Azure.IoT Build 0:6ae2f7bca550 639
AzureIoTClient 21:f9c433d8e6ca 640 /* Codes_SRS_FRAME_CODEC_01_106: [All payloads shall be encoded in order as part of the frame.] */
AzureIoTClient 21:f9c433d8e6ca 641 for (i = 0; i < payload_count; i++)
AzureIoTClient 21:f9c433d8e6ca 642 {
AzureIoTClient 21:f9c433d8e6ca 643 (void)memcpy(encoded_frame + current_pos, payloads[i].bytes, payloads[i].length);
AzureIoTClient 21:f9c433d8e6ca 644 current_pos += payloads[i].length;
AzureIoTClient 21:f9c433d8e6ca 645 }
AzureIoTClient 21:f9c433d8e6ca 646
AzureIoTClient 21:f9c433d8e6ca 647 /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the `on_bytes_encoded` callback in a single call, while setting the `encode complete` argument to true.] */
AzureIoTClient 21:f9c433d8e6ca 648 on_bytes_encoded(callback_context, encoded_frame, frame_size, true);
AzureIoTClient 21:f9c433d8e6ca 649
AzureIoTClient 21:f9c433d8e6ca 650 free(encoded_frame);
AzureIoTClient 21:f9c433d8e6ca 651
AzureIoTClient 21:f9c433d8e6ca 652 /* Codes_SRS_FRAME_CODEC_01_043: [On success it shall return 0.] */
AzureIoTClient 21:f9c433d8e6ca 653 result = 0;
AzureIoTClient 21:f9c433d8e6ca 654 }
AzureIoTClient 6:641a9672db08 655 }
AzureIoTClient 6:641a9672db08 656 }
Azure.IoT Build 0:6ae2f7bca550 657 }
Azure.IoT Build 0:6ae2f7bca550 658
Azure.IoT Build 0:6ae2f7bca550 659 return result;
Azure.IoT Build 0:6ae2f7bca550 660 }