A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Feb 24 14:00:58 2017 -0800
Revision:
19:000ab4e6a2c1
Parent:
17:923575db8b2d
Child:
21:f9c433d8e6ca
1.1.8

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"
Azure.IoT Build 0:6ae2f7bca550 9 #include "azure_c_shared_utility/xlogging.h"
Azure.IoT Build 0:6ae2f7bca550 10 #include "azure_c_shared_utility/xio.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 #include "azure_uamqp_c/amqpalloc.h"
Azure.IoT Build 0:6ae2f7bca550 15
Azure.IoT Build 0:6ae2f7bca550 16 #define FRAME_HEADER_SIZE 8
Azure.IoT Build 0:6ae2f7bca550 17 #define MAX_TYPE_SPECIFIC_SIZE ((255 * 4) - 6)
Azure.IoT Build 0:6ae2f7bca550 18
Azure.IoT Build 0:6ae2f7bca550 19 typedef enum RECEIVE_FRAME_STATE_TAG
Azure.IoT Build 0:6ae2f7bca550 20 {
Azure.IoT Build 0:6ae2f7bca550 21 RECEIVE_FRAME_STATE_FRAME_SIZE,
Azure.IoT Build 0:6ae2f7bca550 22 RECEIVE_FRAME_STATE_DOFF,
Azure.IoT Build 0:6ae2f7bca550 23 RECEIVE_FRAME_STATE_FRAME_TYPE,
Azure.IoT Build 0:6ae2f7bca550 24 RECEIVE_FRAME_STATE_TYPE_SPECIFIC,
Azure.IoT Build 0:6ae2f7bca550 25 RECEIVE_FRAME_STATE_FRAME_BODY,
Azure.IoT Build 0:6ae2f7bca550 26 RECEIVE_FRAME_STATE_ERROR
Azure.IoT Build 0:6ae2f7bca550 27 } RECEIVE_FRAME_STATE;
Azure.IoT Build 0:6ae2f7bca550 28
Azure.IoT Build 0:6ae2f7bca550 29 typedef enum ENCODE_FRAME_STATE_TAG
Azure.IoT Build 0:6ae2f7bca550 30 {
Azure.IoT Build 0:6ae2f7bca550 31 ENCODE_FRAME_STATE_IDLE,
Azure.IoT Build 0:6ae2f7bca550 32 ENCODE_FRAME_STATE_ERROR
Azure.IoT Build 0:6ae2f7bca550 33 } ENCODE_FRAME_STATE;
Azure.IoT Build 0:6ae2f7bca550 34
Azure.IoT Build 0:6ae2f7bca550 35 typedef struct SUBSCRIPTION_TAG
Azure.IoT Build 0:6ae2f7bca550 36 {
Azure.IoT Build 0:6ae2f7bca550 37 uint8_t frame_type;
Azure.IoT Build 0:6ae2f7bca550 38 ON_FRAME_RECEIVED on_frame_received;
Azure.IoT Build 0:6ae2f7bca550 39 void* callback_context;
Azure.IoT Build 0:6ae2f7bca550 40 } SUBSCRIPTION;
Azure.IoT Build 0:6ae2f7bca550 41
Azure.IoT Build 0:6ae2f7bca550 42 typedef struct FRAME_CODEC_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 43 {
Azure.IoT Build 0:6ae2f7bca550 44 /* subscriptions */
AzureIoTClient 12:b30dacf113f2 45 SINGLYLINKEDLIST_HANDLE subscription_list;
Azure.IoT Build 0:6ae2f7bca550 46
Azure.IoT Build 0:6ae2f7bca550 47 /* decode frame */
Azure.IoT Build 0:6ae2f7bca550 48 RECEIVE_FRAME_STATE receive_frame_state;
Azure.IoT Build 0:6ae2f7bca550 49 size_t receive_frame_pos;
Azure.IoT Build 0:6ae2f7bca550 50 uint32_t receive_frame_size;
Azure.IoT Build 0:6ae2f7bca550 51 uint32_t type_specific_size;
Azure.IoT Build 0:6ae2f7bca550 52 uint8_t receive_frame_doff;
Azure.IoT Build 0:6ae2f7bca550 53 uint8_t receive_frame_type;
Azure.IoT Build 0:6ae2f7bca550 54 SUBSCRIPTION* receive_frame_subscription;
Azure.IoT Build 0:6ae2f7bca550 55 unsigned char* receive_frame_bytes;
Azure.IoT Build 0:6ae2f7bca550 56 ON_FRAME_CODEC_ERROR on_frame_codec_error;
Azure.IoT Build 0:6ae2f7bca550 57 void* on_frame_codec_error_callback_context;
Azure.IoT Build 0:6ae2f7bca550 58
Azure.IoT Build 0:6ae2f7bca550 59 /* encode frame */
Azure.IoT Build 0:6ae2f7bca550 60 ENCODE_FRAME_STATE encode_frame_state;
Azure.IoT Build 0:6ae2f7bca550 61
Azure.IoT Build 0:6ae2f7bca550 62 /* configuration */
Azure.IoT Build 0:6ae2f7bca550 63 uint32_t max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 64 } FRAME_CODEC_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 65
Azure.IoT Build 0:6ae2f7bca550 66 static bool find_subscription_by_frame_type(LIST_ITEM_HANDLE list_item, const void* match_context)
Azure.IoT Build 0:6ae2f7bca550 67 {
Azure.IoT Build 0:6ae2f7bca550 68 bool result;
AzureIoTClient 12:b30dacf113f2 69 SUBSCRIPTION* subscription = (SUBSCRIPTION*)singlylinkedlist_item_get_value(list_item);
Azure.IoT Build 0:6ae2f7bca550 70
Azure.IoT Build 0:6ae2f7bca550 71 if (subscription == NULL)
Azure.IoT Build 0:6ae2f7bca550 72 {
Azure.IoT Build 0:6ae2f7bca550 73 result = false;
Azure.IoT Build 0:6ae2f7bca550 74 }
Azure.IoT Build 0:6ae2f7bca550 75 else
Azure.IoT Build 0:6ae2f7bca550 76 {
Azure.IoT Build 0:6ae2f7bca550 77 result = subscription->frame_type == *((uint8_t*)match_context) ? true : false;
Azure.IoT Build 0:6ae2f7bca550 78 }
Azure.IoT Build 0:6ae2f7bca550 79
Azure.IoT Build 0:6ae2f7bca550 80 return result;
Azure.IoT Build 0:6ae2f7bca550 81 }
Azure.IoT Build 0:6ae2f7bca550 82
Azure.IoT Build 5:ae49385aff34 83 FRAME_CODEC_HANDLE frame_codec_create(ON_FRAME_CODEC_ERROR on_frame_codec_error, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 84 {
Azure.IoT Build 0:6ae2f7bca550 85 FRAME_CODEC_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 86
Azure.IoT Build 0:6ae2f7bca550 87 /* 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 88 /* Codes_SRS_FRAME_CODEC_01_104: [The callback_context shall be allowed to be NULL.] */
Azure.IoT Build 0:6ae2f7bca550 89 if (on_frame_codec_error == NULL)
Azure.IoT Build 0:6ae2f7bca550 90 {
Azure.IoT Build 0:6ae2f7bca550 91 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 92 }
Azure.IoT Build 0:6ae2f7bca550 93 else
Azure.IoT Build 0:6ae2f7bca550 94 {
Azure.IoT Build 0:6ae2f7bca550 95 result = amqpalloc_malloc(sizeof(FRAME_CODEC_INSTANCE));
Azure.IoT Build 0:6ae2f7bca550 96 /* 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 97 if (result != NULL)
Azure.IoT Build 0:6ae2f7bca550 98 {
Azure.IoT Build 0:6ae2f7bca550 99 /* 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 100 result->encode_frame_state = ENCODE_FRAME_STATE_IDLE;
Azure.IoT Build 0:6ae2f7bca550 101 result->receive_frame_state = RECEIVE_FRAME_STATE_FRAME_SIZE;
Azure.IoT Build 0:6ae2f7bca550 102 result->on_frame_codec_error = on_frame_codec_error;
Azure.IoT Build 0:6ae2f7bca550 103 result->on_frame_codec_error_callback_context = callback_context;
Azure.IoT Build 0:6ae2f7bca550 104 result->receive_frame_pos = 0;
Azure.IoT Build 0:6ae2f7bca550 105 result->receive_frame_size = 0;
Azure.IoT Build 0:6ae2f7bca550 106 result->receive_frame_bytes = NULL;
AzureIoTClient 12:b30dacf113f2 107 result->subscription_list = singlylinkedlist_create();
Azure.IoT Build 0:6ae2f7bca550 108
Azure.IoT Build 0:6ae2f7bca550 109 /* Codes_SRS_FRAME_CODEC_01_082: [The initial max_frame_size_shall be 512.] */
Azure.IoT Build 0:6ae2f7bca550 110 result->max_frame_size = 512;
Azure.IoT Build 0:6ae2f7bca550 111 }
Azure.IoT Build 0:6ae2f7bca550 112 }
Azure.IoT Build 0:6ae2f7bca550 113
Azure.IoT Build 0:6ae2f7bca550 114 return result;
Azure.IoT Build 0:6ae2f7bca550 115 }
Azure.IoT Build 0:6ae2f7bca550 116
Azure.IoT Build 0:6ae2f7bca550 117 void frame_codec_destroy(FRAME_CODEC_HANDLE frame_codec)
Azure.IoT Build 0:6ae2f7bca550 118 {
Azure.IoT Build 0:6ae2f7bca550 119 /* Codes_SRS_FRAME_CODEC_01_024: [If frame_codec is NULL, frame_codec_destroy shall do nothing.] */
Azure.IoT Build 0:6ae2f7bca550 120 if (frame_codec != NULL)
Azure.IoT Build 0:6ae2f7bca550 121 {
Azure.IoT Build 0:6ae2f7bca550 122 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
Azure.IoT Build 0:6ae2f7bca550 123
AzureIoTClient 12:b30dacf113f2 124 singlylinkedlist_destroy(frame_codec_data->subscription_list);
Azure.IoT Build 0:6ae2f7bca550 125 if (frame_codec_data->receive_frame_bytes != NULL)
Azure.IoT Build 0:6ae2f7bca550 126 {
Azure.IoT Build 0:6ae2f7bca550 127 amqpalloc_free(frame_codec_data->receive_frame_bytes);
Azure.IoT Build 0:6ae2f7bca550 128 }
Azure.IoT Build 0:6ae2f7bca550 129
Azure.IoT Build 0:6ae2f7bca550 130 /* Codes_SRS_FRAME_CODEC_01_023: [frame_codec_destroy shall free all resources associated with a frame_codec instance.] */
Azure.IoT Build 0:6ae2f7bca550 131 amqpalloc_free(frame_codec);
Azure.IoT Build 0:6ae2f7bca550 132 }
Azure.IoT Build 0:6ae2f7bca550 133 }
Azure.IoT Build 0:6ae2f7bca550 134
Azure.IoT Build 0:6ae2f7bca550 135 int frame_codec_set_max_frame_size(FRAME_CODEC_HANDLE frame_codec, uint32_t max_frame_size)
Azure.IoT Build 0:6ae2f7bca550 136 {
Azure.IoT Build 0:6ae2f7bca550 137 int result;
Azure.IoT Build 0:6ae2f7bca550 138 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
Azure.IoT Build 0:6ae2f7bca550 139
Azure.IoT Build 0:6ae2f7bca550 140 /* 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 141 if ((frame_codec == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 142 /* 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 143 (max_frame_size < FRAME_HEADER_SIZE) ||
Azure.IoT Build 0:6ae2f7bca550 144 /* 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 145 ((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 146 /* Codes_SRS_FRAME_CODEC_01_097: [Setting a frame size on a frame_codec that had a decode error shall fail.] */
Azure.IoT Build 0:6ae2f7bca550 147 (frame_codec_data->receive_frame_state == RECEIVE_FRAME_STATE_ERROR) ||
Azure.IoT Build 0:6ae2f7bca550 148 /* Codes_SRS_FRAME_CODEC_01_098: [Setting a frame size on a frame_codec that had an encode error shall fail.] */
Azure.IoT Build 0:6ae2f7bca550 149 (frame_codec_data->encode_frame_state == ENCODE_FRAME_STATE_ERROR))
Azure.IoT Build 0:6ae2f7bca550 150 {
AzureIoTClient 19:000ab4e6a2c1 151 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 152 }
Azure.IoT Build 0:6ae2f7bca550 153 else
Azure.IoT Build 0:6ae2f7bca550 154 {
Azure.IoT Build 0:6ae2f7bca550 155 /* 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 156 /* 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 157 frame_codec_data->max_frame_size = max_frame_size;
Azure.IoT Build 0:6ae2f7bca550 158
Azure.IoT Build 0:6ae2f7bca550 159 /* Codes_SRS_FRAME_CODEC_01_076: [On success, frame_codec_set_max_frame_size shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 160 result = 0;
Azure.IoT Build 0:6ae2f7bca550 161 }
Azure.IoT Build 0:6ae2f7bca550 162 return result;
Azure.IoT Build 0:6ae2f7bca550 163 }
Azure.IoT Build 0:6ae2f7bca550 164
Azure.IoT Build 0:6ae2f7bca550 165 /* 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 166 /* 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 167 /* 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 168 /* 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 169 /* 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 170 /* Codes_SRS_FRAME_CODEC_01_028: [The sequence of bytes shall be decoded according to the AMQP ISO.] */
Azure.IoT Build 0:6ae2f7bca550 171 /* 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 172 int frame_codec_receive_bytes(FRAME_CODEC_HANDLE frame_codec, const unsigned char* buffer, size_t size)
Azure.IoT Build 0:6ae2f7bca550 173 {
AzureIoTClient 19:000ab4e6a2c1 174 int result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 175 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
Azure.IoT Build 0:6ae2f7bca550 176
Azure.IoT Build 0:6ae2f7bca550 177 /* 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 178 if ((frame_codec == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 179 (buffer == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 180 /* 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 181 (size == 0))
Azure.IoT Build 0:6ae2f7bca550 182 {
AzureIoTClient 19:000ab4e6a2c1 183 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 184 }
Azure.IoT Build 0:6ae2f7bca550 185 else
Azure.IoT Build 0:6ae2f7bca550 186 {
Azure.IoT Build 0:6ae2f7bca550 187 while (size > 0)
Azure.IoT Build 0:6ae2f7bca550 188 {
Azure.IoT Build 0:6ae2f7bca550 189 switch (frame_codec_data->receive_frame_state)
Azure.IoT Build 0:6ae2f7bca550 190 {
Azure.IoT Build 0:6ae2f7bca550 191 default:
Azure.IoT Build 0:6ae2f7bca550 192 case RECEIVE_FRAME_STATE_ERROR:
Azure.IoT Build 0:6ae2f7bca550 193 /* 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 194 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 195 size = 0;
Azure.IoT Build 0:6ae2f7bca550 196 break;
Azure.IoT Build 0:6ae2f7bca550 197
Azure.IoT Build 0:6ae2f7bca550 198 /* Codes_SRS_FRAME_CODEC_01_008: [SIZE Bytes 0-3 of the frame header contain the frame size.] */
Azure.IoT Build 0:6ae2f7bca550 199 case RECEIVE_FRAME_STATE_FRAME_SIZE:
Azure.IoT Build 0:6ae2f7bca550 200 /* 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 201 frame_codec_data->receive_frame_size += buffer[0] << (24 - frame_codec_data->receive_frame_pos * 8);
Azure.IoT Build 0:6ae2f7bca550 202 buffer++;
Azure.IoT Build 0:6ae2f7bca550 203 size--;
Azure.IoT Build 0:6ae2f7bca550 204 frame_codec_data->receive_frame_pos++;
Azure.IoT Build 0:6ae2f7bca550 205
Azure.IoT Build 0:6ae2f7bca550 206 if (frame_codec_data->receive_frame_pos == 4)
Azure.IoT Build 0:6ae2f7bca550 207 {
Azure.IoT Build 0:6ae2f7bca550 208 /* 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 209 if ((frame_codec_data->receive_frame_size < FRAME_HEADER_SIZE) ||
Azure.IoT Build 0:6ae2f7bca550 210 /* 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 211 (frame_codec_data->receive_frame_size > frame_codec_data->max_frame_size))
Azure.IoT Build 0:6ae2f7bca550 212 {
Azure.IoT Build 0:6ae2f7bca550 213 /* 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 214 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_ERROR;
Azure.IoT Build 0:6ae2f7bca550 215 /* 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 216 frame_codec_data->on_frame_codec_error(frame_codec_data->on_frame_codec_error_callback_context);
Azure.IoT Build 0:6ae2f7bca550 217
AzureIoTClient 19:000ab4e6a2c1 218 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 219 }
Azure.IoT Build 0:6ae2f7bca550 220 else
Azure.IoT Build 0:6ae2f7bca550 221 {
Azure.IoT Build 0:6ae2f7bca550 222 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_DOFF;
Azure.IoT Build 0:6ae2f7bca550 223 result = 0;
Azure.IoT Build 0:6ae2f7bca550 224 }
Azure.IoT Build 0:6ae2f7bca550 225 }
Azure.IoT Build 0:6ae2f7bca550 226 else
Azure.IoT Build 0:6ae2f7bca550 227 {
Azure.IoT Build 0:6ae2f7bca550 228 result = 0;
Azure.IoT Build 0:6ae2f7bca550 229 }
Azure.IoT Build 0:6ae2f7bca550 230
Azure.IoT Build 0:6ae2f7bca550 231 break;
Azure.IoT Build 0:6ae2f7bca550 232
Azure.IoT Build 0:6ae2f7bca550 233 case RECEIVE_FRAME_STATE_DOFF:
Azure.IoT Build 0:6ae2f7bca550 234 /* Codes_SRS_FRAME_CODEC_01_011: [DOFF Byte 4 of the frame header is the data offset.] */
Azure.IoT Build 0:6ae2f7bca550 235 /* 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 236 /* Codes_SRS_FRAME_CODEC_01_012: [This gives the position of the body within the frame.] */
Azure.IoT Build 0:6ae2f7bca550 237 frame_codec_data->receive_frame_doff = buffer[0];
Azure.IoT Build 0:6ae2f7bca550 238 buffer++;
Azure.IoT Build 0:6ae2f7bca550 239 size--;
Azure.IoT Build 0:6ae2f7bca550 240
Azure.IoT Build 0:6ae2f7bca550 241 /* 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 242 if (frame_codec_data->receive_frame_doff < 2)
Azure.IoT Build 0:6ae2f7bca550 243 {
Azure.IoT Build 0:6ae2f7bca550 244 /* 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 245 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_ERROR;
Azure.IoT Build 0:6ae2f7bca550 246
Azure.IoT Build 0:6ae2f7bca550 247 /* 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 248 frame_codec_data->on_frame_codec_error(frame_codec_data->on_frame_codec_error_callback_context);
Azure.IoT Build 0:6ae2f7bca550 249
AzureIoTClient 19:000ab4e6a2c1 250 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 251 }
Azure.IoT Build 0:6ae2f7bca550 252 else
Azure.IoT Build 0:6ae2f7bca550 253 {
Azure.IoT Build 0:6ae2f7bca550 254 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_FRAME_TYPE;
Azure.IoT Build 0:6ae2f7bca550 255 result = 0;
Azure.IoT Build 0:6ae2f7bca550 256 }
Azure.IoT Build 0:6ae2f7bca550 257
Azure.IoT Build 0:6ae2f7bca550 258 break;
Azure.IoT Build 0:6ae2f7bca550 259
Azure.IoT Build 0:6ae2f7bca550 260 case RECEIVE_FRAME_STATE_FRAME_TYPE:
Azure.IoT Build 0:6ae2f7bca550 261 {
Azure.IoT Build 0:6ae2f7bca550 262 LIST_ITEM_HANDLE item_handle;
Azure.IoT Build 0:6ae2f7bca550 263 frame_codec_data->type_specific_size = (frame_codec_data->receive_frame_doff * 4) - 6;
Azure.IoT Build 0:6ae2f7bca550 264
Azure.IoT Build 0:6ae2f7bca550 265 /* Codes_SRS_FRAME_CODEC_01_015: [TYPE Byte 5 of the frame header is a type code.] */
Azure.IoT Build 0:6ae2f7bca550 266 frame_codec_data->receive_frame_type = buffer[0];
Azure.IoT Build 0:6ae2f7bca550 267 buffer++;
Azure.IoT Build 0:6ae2f7bca550 268 size--;
Azure.IoT Build 0:6ae2f7bca550 269
Azure.IoT Build 0:6ae2f7bca550 270 /* 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 271 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 272 if (item_handle == NULL)
Azure.IoT Build 0:6ae2f7bca550 273 {
Azure.IoT Build 0:6ae2f7bca550 274 frame_codec_data->receive_frame_subscription = NULL;
Azure.IoT Build 0:6ae2f7bca550 275 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_TYPE_SPECIFIC;
Azure.IoT Build 0:6ae2f7bca550 276 result = 0;
Azure.IoT Build 0:6ae2f7bca550 277 break;
Azure.IoT Build 0:6ae2f7bca550 278 }
Azure.IoT Build 0:6ae2f7bca550 279 else
Azure.IoT Build 0:6ae2f7bca550 280 {
AzureIoTClient 12:b30dacf113f2 281 frame_codec_data->receive_frame_subscription = (SUBSCRIPTION*)singlylinkedlist_item_get_value(item_handle);
Azure.IoT Build 0:6ae2f7bca550 282 if (frame_codec_data->receive_frame_subscription == NULL)
Azure.IoT Build 0:6ae2f7bca550 283 {
Azure.IoT Build 0:6ae2f7bca550 284 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_TYPE_SPECIFIC;
Azure.IoT Build 0:6ae2f7bca550 285 result = 0;
Azure.IoT Build 0:6ae2f7bca550 286 break;
Azure.IoT Build 0:6ae2f7bca550 287 }
Azure.IoT Build 0:6ae2f7bca550 288 else
Azure.IoT Build 0:6ae2f7bca550 289 {
Azure.IoT Build 0:6ae2f7bca550 290 frame_codec_data->receive_frame_pos = 0;
Azure.IoT Build 0:6ae2f7bca550 291
Azure.IoT Build 0:6ae2f7bca550 292 /* Codes_SRS_FRAME_CODEC_01_102: [frame_codec_receive_bytes shall allocate memory to hold the frame_body bytes.] */
Azure.IoT Build 0:6ae2f7bca550 293 frame_codec_data->receive_frame_bytes = (unsigned char*)amqpalloc_malloc(frame_codec_data->receive_frame_size - 6);
Azure.IoT Build 0:6ae2f7bca550 294 if (frame_codec_data->receive_frame_bytes == NULL)
Azure.IoT Build 0:6ae2f7bca550 295 {
Azure.IoT Build 0:6ae2f7bca550 296 /* 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 297 /* 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 298 /* 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 299 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_ERROR;
Azure.IoT Build 0:6ae2f7bca550 300
Azure.IoT Build 0:6ae2f7bca550 301 /* 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 302 frame_codec_data->on_frame_codec_error(frame_codec_data->on_frame_codec_error_callback_context);
Azure.IoT Build 0:6ae2f7bca550 303
AzureIoTClient 19:000ab4e6a2c1 304 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 305 break;
Azure.IoT Build 0:6ae2f7bca550 306 }
Azure.IoT Build 0:6ae2f7bca550 307 else
Azure.IoT Build 0:6ae2f7bca550 308 {
Azure.IoT Build 0:6ae2f7bca550 309 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_TYPE_SPECIFIC;
Azure.IoT Build 0:6ae2f7bca550 310 result = 0;
Azure.IoT Build 0:6ae2f7bca550 311 break;
Azure.IoT Build 0:6ae2f7bca550 312 }
Azure.IoT Build 0:6ae2f7bca550 313 }
Azure.IoT Build 0:6ae2f7bca550 314 }
Azure.IoT Build 0:6ae2f7bca550 315 }
Azure.IoT Build 0:6ae2f7bca550 316
Azure.IoT Build 0:6ae2f7bca550 317 case RECEIVE_FRAME_STATE_TYPE_SPECIFIC:
Azure.IoT Build 0:6ae2f7bca550 318 {
AzureIoTClient 6:641a9672db08 319 size_t to_copy = frame_codec_data->type_specific_size - frame_codec_data->receive_frame_pos;
Azure.IoT Build 0:6ae2f7bca550 320 if (to_copy > size)
Azure.IoT Build 0:6ae2f7bca550 321 {
Azure.IoT Build 0:6ae2f7bca550 322 to_copy = size;
Azure.IoT Build 0:6ae2f7bca550 323 }
Azure.IoT Build 0:6ae2f7bca550 324
Azure.IoT Build 0:6ae2f7bca550 325 if (frame_codec_data->receive_frame_subscription != NULL)
Azure.IoT Build 0:6ae2f7bca550 326 {
Azure.IoT Build 0:6ae2f7bca550 327 (void)memcpy(&frame_codec_data->receive_frame_bytes[frame_codec_data->receive_frame_pos], buffer, to_copy);
Azure.IoT Build 0:6ae2f7bca550 328 frame_codec_data->receive_frame_pos += to_copy;
Azure.IoT Build 0:6ae2f7bca550 329 buffer += to_copy;
Azure.IoT Build 0:6ae2f7bca550 330 size -= to_copy;
Azure.IoT Build 0:6ae2f7bca550 331 }
Azure.IoT Build 0:6ae2f7bca550 332 else
Azure.IoT Build 0:6ae2f7bca550 333 {
Azure.IoT Build 0:6ae2f7bca550 334 frame_codec_data->receive_frame_pos += to_copy;
Azure.IoT Build 0:6ae2f7bca550 335 buffer += to_copy;
Azure.IoT Build 0:6ae2f7bca550 336 size -= to_copy;
Azure.IoT Build 0:6ae2f7bca550 337 }
Azure.IoT Build 0:6ae2f7bca550 338
Azure.IoT Build 0:6ae2f7bca550 339 if (frame_codec_data->receive_frame_pos == frame_codec_data->type_specific_size)
Azure.IoT Build 0:6ae2f7bca550 340 {
Azure.IoT Build 0:6ae2f7bca550 341 if (frame_codec_data->receive_frame_size == FRAME_HEADER_SIZE)
Azure.IoT Build 0:6ae2f7bca550 342 {
Azure.IoT Build 0:6ae2f7bca550 343 if (frame_codec_data->receive_frame_subscription != NULL)
Azure.IoT Build 0:6ae2f7bca550 344 {
Azure.IoT Build 0:6ae2f7bca550 345 /* 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 346 /* 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 347 /* Codes_SRS_FRAME_CODEC_01_005: [This is an extension point defined for future expansion.] */
Azure.IoT Build 0:6ae2f7bca550 348 /* Codes_SRS_FRAME_CODEC_01_006: [The treatment of this area depends on the frame type.] */
Azure.IoT Build 0:6ae2f7bca550 349 /* 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 350 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);
Azure.IoT Build 0:6ae2f7bca550 351 amqpalloc_free(frame_codec_data->receive_frame_bytes);
Azure.IoT Build 0:6ae2f7bca550 352 frame_codec_data->receive_frame_bytes = NULL;
Azure.IoT Build 0:6ae2f7bca550 353 }
Azure.IoT Build 0:6ae2f7bca550 354
Azure.IoT Build 0:6ae2f7bca550 355 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_FRAME_SIZE;
Azure.IoT Build 0:6ae2f7bca550 356 frame_codec_data->receive_frame_size = 0;
Azure.IoT Build 0:6ae2f7bca550 357 }
Azure.IoT Build 0:6ae2f7bca550 358 else
Azure.IoT Build 0:6ae2f7bca550 359 {
Azure.IoT Build 0:6ae2f7bca550 360 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_FRAME_BODY;
Azure.IoT Build 0:6ae2f7bca550 361 }
Azure.IoT Build 0:6ae2f7bca550 362
Azure.IoT Build 0:6ae2f7bca550 363 frame_codec_data->receive_frame_pos = 0;
Azure.IoT Build 0:6ae2f7bca550 364 }
Azure.IoT Build 0:6ae2f7bca550 365
Azure.IoT Build 0:6ae2f7bca550 366 result = 0;
Azure.IoT Build 0:6ae2f7bca550 367 break;
Azure.IoT Build 0:6ae2f7bca550 368 }
Azure.IoT Build 0:6ae2f7bca550 369
Azure.IoT Build 0:6ae2f7bca550 370 case RECEIVE_FRAME_STATE_FRAME_BODY:
Azure.IoT Build 0:6ae2f7bca550 371 {
Azure.IoT Build 0:6ae2f7bca550 372 uint32_t frame_body_size = frame_codec_data->receive_frame_size - (frame_codec_data->receive_frame_doff * 4);
AzureIoTClient 6:641a9672db08 373 size_t to_copy = frame_body_size - frame_codec_data->receive_frame_pos;
Azure.IoT Build 0:6ae2f7bca550 374
Azure.IoT Build 0:6ae2f7bca550 375 if (to_copy > size)
Azure.IoT Build 0:6ae2f7bca550 376 {
Azure.IoT Build 0:6ae2f7bca550 377 to_copy = size;
Azure.IoT Build 0:6ae2f7bca550 378 }
Azure.IoT Build 0:6ae2f7bca550 379
Azure.IoT Build 0:6ae2f7bca550 380 (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 381
Azure.IoT Build 0:6ae2f7bca550 382 buffer += to_copy;
Azure.IoT Build 0:6ae2f7bca550 383 size -= to_copy;
Azure.IoT Build 0:6ae2f7bca550 384 frame_codec_data->receive_frame_pos += to_copy;
Azure.IoT Build 0:6ae2f7bca550 385
Azure.IoT Build 0:6ae2f7bca550 386 if (frame_codec_data->receive_frame_pos == frame_body_size)
Azure.IoT Build 0:6ae2f7bca550 387 {
Azure.IoT Build 0:6ae2f7bca550 388 if (frame_codec_data->receive_frame_subscription != NULL)
Azure.IoT Build 0:6ae2f7bca550 389 {
Azure.IoT Build 0:6ae2f7bca550 390 /* 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 391 /* 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 392 /* Codes_SRS_FRAME_CODEC_01_005: [This is an extension point defined for future expansion.] */
Azure.IoT Build 0:6ae2f7bca550 393 /* Codes_SRS_FRAME_CODEC_01_006: [The treatment of this area depends on the frame type.] */
Azure.IoT Build 0:6ae2f7bca550 394 /* 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 395 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);
Azure.IoT Build 0:6ae2f7bca550 396 amqpalloc_free(frame_codec_data->receive_frame_bytes);
Azure.IoT Build 0:6ae2f7bca550 397 frame_codec_data->receive_frame_bytes = NULL;
Azure.IoT Build 0:6ae2f7bca550 398 }
Azure.IoT Build 0:6ae2f7bca550 399
Azure.IoT Build 0:6ae2f7bca550 400 frame_codec_data->receive_frame_state = RECEIVE_FRAME_STATE_FRAME_SIZE;
Azure.IoT Build 0:6ae2f7bca550 401 frame_codec_data->receive_frame_pos = 0;
Azure.IoT Build 0:6ae2f7bca550 402 frame_codec_data->receive_frame_size = 0;
Azure.IoT Build 0:6ae2f7bca550 403 }
Azure.IoT Build 0:6ae2f7bca550 404 result = 0;
Azure.IoT Build 0:6ae2f7bca550 405
Azure.IoT Build 0:6ae2f7bca550 406 break;
Azure.IoT Build 0:6ae2f7bca550 407 }
Azure.IoT Build 0:6ae2f7bca550 408 }
Azure.IoT Build 0:6ae2f7bca550 409 }
Azure.IoT Build 0:6ae2f7bca550 410 }
Azure.IoT Build 0:6ae2f7bca550 411
Azure.IoT Build 0:6ae2f7bca550 412 return result;
Azure.IoT Build 0:6ae2f7bca550 413 }
Azure.IoT Build 0:6ae2f7bca550 414
Azure.IoT Build 0:6ae2f7bca550 415 /* 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 416 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 417 {
Azure.IoT Build 0:6ae2f7bca550 418 int result;
Azure.IoT Build 0:6ae2f7bca550 419
Azure.IoT Build 0:6ae2f7bca550 420 /* 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 421 if ((frame_codec == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 422 (on_frame_received == NULL))
Azure.IoT Build 0:6ae2f7bca550 423 {
AzureIoTClient 19:000ab4e6a2c1 424 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 425 }
Azure.IoT Build 0:6ae2f7bca550 426 else
Azure.IoT Build 0:6ae2f7bca550 427 {
Azure.IoT Build 0:6ae2f7bca550 428 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
Azure.IoT Build 0:6ae2f7bca550 429 SUBSCRIPTION* subscription;
Azure.IoT Build 0:6ae2f7bca550 430
Azure.IoT Build 0:6ae2f7bca550 431 /* 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 432 /* find the subscription for this frame type */
AzureIoTClient 12:b30dacf113f2 433 LIST_ITEM_HANDLE list_item = singlylinkedlist_find(frame_codec_data->subscription_list, find_subscription_by_frame_type, &type);
Azure.IoT Build 0:6ae2f7bca550 434 if (list_item != NULL)
Azure.IoT Build 0:6ae2f7bca550 435 {
AzureIoTClient 12:b30dacf113f2 436 subscription = (SUBSCRIPTION*)singlylinkedlist_item_get_value(list_item);
Azure.IoT Build 0:6ae2f7bca550 437 if (subscription == NULL)
Azure.IoT Build 0:6ae2f7bca550 438 {
Azure.IoT Build 0:6ae2f7bca550 439 /* 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 440 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 441 }
Azure.IoT Build 0:6ae2f7bca550 442 else
Azure.IoT Build 0:6ae2f7bca550 443 {
Azure.IoT Build 0:6ae2f7bca550 444 /* a subscription was found */
Azure.IoT Build 0:6ae2f7bca550 445 subscription->on_frame_received = on_frame_received;
Azure.IoT Build 0:6ae2f7bca550 446 subscription->callback_context = callback_context;
Azure.IoT Build 0:6ae2f7bca550 447
Azure.IoT Build 0:6ae2f7bca550 448 /* Codes_SRS_FRAME_CODEC_01_087: [On success, frame_codec_subscribe shall return zero.] */
Azure.IoT Build 0:6ae2f7bca550 449 result = 0;
Azure.IoT Build 0:6ae2f7bca550 450 }
Azure.IoT Build 0:6ae2f7bca550 451 }
Azure.IoT Build 0:6ae2f7bca550 452 else
Azure.IoT Build 0:6ae2f7bca550 453 {
Azure.IoT Build 0:6ae2f7bca550 454 /* add a new subscription */
Azure.IoT Build 0:6ae2f7bca550 455 subscription = (SUBSCRIPTION*)amqpalloc_malloc(sizeof(SUBSCRIPTION));
Azure.IoT Build 0:6ae2f7bca550 456 /* 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 457 if (subscription == NULL)
Azure.IoT Build 0:6ae2f7bca550 458 {
AzureIoTClient 19:000ab4e6a2c1 459 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 460 }
Azure.IoT Build 0:6ae2f7bca550 461 else
Azure.IoT Build 0:6ae2f7bca550 462 {
Azure.IoT Build 0:6ae2f7bca550 463 subscription->on_frame_received = on_frame_received;
Azure.IoT Build 0:6ae2f7bca550 464 subscription->callback_context = callback_context;
Azure.IoT Build 0:6ae2f7bca550 465 subscription->frame_type = type;
Azure.IoT Build 0:6ae2f7bca550 466
Azure.IoT Build 0:6ae2f7bca550 467 /* 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 468 if (singlylinkedlist_add(frame_codec_data->subscription_list, subscription) == NULL)
Azure.IoT Build 0:6ae2f7bca550 469 {
Azure.IoT Build 0:6ae2f7bca550 470 amqpalloc_free(subscription);
AzureIoTClient 19:000ab4e6a2c1 471 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 472 }
Azure.IoT Build 0:6ae2f7bca550 473 else
Azure.IoT Build 0:6ae2f7bca550 474 {
Azure.IoT Build 0:6ae2f7bca550 475 /* Codes_SRS_FRAME_CODEC_01_087: [On success, frame_codec_subscribe shall return zero.] */
Azure.IoT Build 0:6ae2f7bca550 476 result = 0;
Azure.IoT Build 0:6ae2f7bca550 477 }
Azure.IoT Build 0:6ae2f7bca550 478 }
Azure.IoT Build 0:6ae2f7bca550 479 }
Azure.IoT Build 0:6ae2f7bca550 480 }
Azure.IoT Build 0:6ae2f7bca550 481
Azure.IoT Build 0:6ae2f7bca550 482 return result;
Azure.IoT Build 0:6ae2f7bca550 483 }
Azure.IoT Build 0:6ae2f7bca550 484
Azure.IoT Build 0:6ae2f7bca550 485 int frame_codec_unsubscribe(FRAME_CODEC_HANDLE frame_codec, uint8_t type)
Azure.IoT Build 0:6ae2f7bca550 486 {
Azure.IoT Build 0:6ae2f7bca550 487 int result;
Azure.IoT Build 0:6ae2f7bca550 488
Azure.IoT Build 0:6ae2f7bca550 489 /* 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 490 if (frame_codec == NULL)
Azure.IoT Build 0:6ae2f7bca550 491 {
AzureIoTClient 19:000ab4e6a2c1 492 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 493 }
Azure.IoT Build 0:6ae2f7bca550 494 else
Azure.IoT Build 0:6ae2f7bca550 495 {
Azure.IoT Build 0:6ae2f7bca550 496 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
AzureIoTClient 12:b30dacf113f2 497 LIST_ITEM_HANDLE list_item = singlylinkedlist_find(frame_codec_data->subscription_list, find_subscription_by_frame_type, &type);
Azure.IoT Build 0:6ae2f7bca550 498
Azure.IoT Build 0:6ae2f7bca550 499 if (list_item == NULL)
Azure.IoT Build 0:6ae2f7bca550 500 {
Azure.IoT Build 0:6ae2f7bca550 501 /* 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 502 /* 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 503 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 504 }
Azure.IoT Build 0:6ae2f7bca550 505 else
Azure.IoT Build 0:6ae2f7bca550 506 {
AzureIoTClient 12:b30dacf113f2 507 SUBSCRIPTION* subscription = (SUBSCRIPTION*)singlylinkedlist_item_get_value(list_item);
Azure.IoT Build 0:6ae2f7bca550 508 if (subscription == NULL)
Azure.IoT Build 0:6ae2f7bca550 509 {
Azure.IoT Build 0:6ae2f7bca550 510 /* 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 511 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 512 }
Azure.IoT Build 0:6ae2f7bca550 513 else
Azure.IoT Build 0:6ae2f7bca550 514 {
Azure.IoT Build 0:6ae2f7bca550 515 amqpalloc_free(subscription);
AzureIoTClient 12:b30dacf113f2 516 if (singlylinkedlist_remove(frame_codec_data->subscription_list, list_item) != 0)
Azure.IoT Build 0:6ae2f7bca550 517 {
Azure.IoT Build 0:6ae2f7bca550 518 /* 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 519 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 520 }
Azure.IoT Build 0:6ae2f7bca550 521 else
Azure.IoT Build 0:6ae2f7bca550 522 {
Azure.IoT Build 0:6ae2f7bca550 523 /* 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 524 result = 0;
Azure.IoT Build 0:6ae2f7bca550 525 }
Azure.IoT Build 0:6ae2f7bca550 526 }
Azure.IoT Build 0:6ae2f7bca550 527 }
Azure.IoT Build 0:6ae2f7bca550 528 }
Azure.IoT Build 0:6ae2f7bca550 529
Azure.IoT Build 0:6ae2f7bca550 530 return result;
Azure.IoT Build 0:6ae2f7bca550 531 }
Azure.IoT Build 0:6ae2f7bca550 532
Azure.IoT Build 0:6ae2f7bca550 533 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 534 {
Azure.IoT Build 0:6ae2f7bca550 535 int result;
Azure.IoT Build 0:6ae2f7bca550 536
Azure.IoT Build 0:6ae2f7bca550 537 FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec;
Azure.IoT Build 0:6ae2f7bca550 538
Azure.IoT Build 0:6ae2f7bca550 539 /* Codes_SRS_FRAME_CODEC_01_044: [If the argument frame_codec is NULL, frame_codec_encode_frame shall return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 540 if ((frame_codec == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 541 /* 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 542 ((type_specific_size > 0) && (type_specific_bytes == NULL)) ||
Azure.IoT Build 0:6ae2f7bca550 543 /* 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.] */
Azure.IoT Build 0:6ae2f7bca550 544 (type_specific_size > MAX_TYPE_SPECIFIC_SIZE) ||
AzureIoTClient 6:641a9672db08 545 (frame_codec_data->encode_frame_state == ENCODE_FRAME_STATE_ERROR))
Azure.IoT Build 0:6ae2f7bca550 546 {
AzureIoTClient 19:000ab4e6a2c1 547 result = __FAILURE__;
Azure.IoT Build 0:6ae2f7bca550 548 }
Azure.IoT Build 0:6ae2f7bca550 549 else
Azure.IoT Build 0:6ae2f7bca550 550 {
AzureIoTClient 6:641a9672db08 551 /* round up to the 4 bytes for doff */
AzureIoTClient 6:641a9672db08 552 /* 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 553 /* 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 554 uint8_t padding_byte_count;
AzureIoTClient 6:641a9672db08 555 uint32_t frame_body_offset = type_specific_size + 6;
AzureIoTClient 6:641a9672db08 556 uint8_t doff = (uint8_t)((frame_body_offset + 3) / 4);
AzureIoTClient 6:641a9672db08 557 size_t i;
AzureIoTClient 6:641a9672db08 558 size_t frame_size;
AzureIoTClient 6:641a9672db08 559 size_t frame_body_size = 0;
AzureIoTClient 6:641a9672db08 560 frame_body_offset = doff * 4;
AzureIoTClient 6:641a9672db08 561 padding_byte_count = (uint8_t)(frame_body_offset - type_specific_size - 6);
Azure.IoT Build 0:6ae2f7bca550 562
AzureIoTClient 6:641a9672db08 563 for (i = 0; i < payload_count; i++)
AzureIoTClient 6:641a9672db08 564 {
AzureIoTClient 6:641a9672db08 565 frame_body_size += payloads[i].length;
AzureIoTClient 6:641a9672db08 566 }
AzureIoTClient 6:641a9672db08 567
AzureIoTClient 6:641a9672db08 568 /* 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 6:641a9672db08 569 frame_size = frame_body_size + frame_body_offset;
Azure.IoT Build 0:6ae2f7bca550 570
AzureIoTClient 6:641a9672db08 571 if (frame_size > frame_codec_data->max_frame_size)
AzureIoTClient 6:641a9672db08 572 {
AzureIoTClient 6:641a9672db08 573 /* 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 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_042: [frame_codec_encode_frame encodes the header and type specific bytes of a frame that has frame_payload_size bytes.] */
AzureIoTClient 6:641a9672db08 579 /* 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 6:641a9672db08 580 /* Codes_SRS_FRAME_CODEC_01_056: [frame header The frame header is a fixed size (8 byte) structure that precedes each frame.] */
AzureIoTClient 6:641a9672db08 581 /* 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 6:641a9672db08 582 /* Codes_SRS_FRAME_CODEC_01_058: [extended header The extended header is a variable width area preceding the frame body.] */
AzureIoTClient 6:641a9672db08 583 /* Codes_SRS_FRAME_CODEC_01_059: [This is an extension point defined for future expansion.] */
AzureIoTClient 6:641a9672db08 584 /* Codes_SRS_FRAME_CODEC_01_060: [The treatment of this area depends on the frame type.]*/
AzureIoTClient 6:641a9672db08 585 /* Codes_SRS_FRAME_CODEC_01_062: [SIZE Bytes 0-3 of the frame header contain the frame size.] */
AzureIoTClient 6:641a9672db08 586 /* 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 6:641a9672db08 587 /* 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 6:641a9672db08 588 unsigned char frame_header[6];
Azure.IoT Build 0:6ae2f7bca550 589
AzureIoTClient 6:641a9672db08 590 frame_header[0] = (frame_size >> 24) & 0xFF;
AzureIoTClient 6:641a9672db08 591 frame_header[1] = (frame_size >> 16) & 0xFF;
AzureIoTClient 6:641a9672db08 592 frame_header[2] = (frame_size >> 8) & 0xFF;
AzureIoTClient 6:641a9672db08 593 frame_header[3] = frame_size & 0xFF;
AzureIoTClient 6:641a9672db08 594 /* Codes_SRS_FRAME_CODEC_01_065: [DOFF Byte 4 of the frame header is the data offset.] */
AzureIoTClient 6:641a9672db08 595 frame_header[4] = doff;
AzureIoTClient 6:641a9672db08 596 /* Codes_SRS_FRAME_CODEC_01_069: [TYPE Byte 5 of the frame header is a type code.] */
AzureIoTClient 6:641a9672db08 597 frame_header[5] = type;
Azure.IoT Build 0:6ae2f7bca550 598
AzureIoTClient 6:641a9672db08 599 /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */
AzureIoTClient 6:641a9672db08 600 on_bytes_encoded(callback_context, frame_header, sizeof(frame_header), ((frame_body_size + type_specific_bytes + padding_byte_count) == 0) ? true : false);
AzureIoTClient 6:641a9672db08 601
AzureIoTClient 6:641a9672db08 602 /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */
AzureIoTClient 6:641a9672db08 603 if (type_specific_size > 0)
AzureIoTClient 6:641a9672db08 604 {
AzureIoTClient 6:641a9672db08 605 on_bytes_encoded(callback_context, type_specific_bytes, type_specific_size, ((frame_body_size + padding_byte_count) == 0) ? true : false);
AzureIoTClient 6:641a9672db08 606 }
AzureIoTClient 6:641a9672db08 607
AzureIoTClient 6:641a9672db08 608 /* send padding bytes */
AzureIoTClient 16:22a72cf8e416 609 /* 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 6:641a9672db08 610 unsigned char padding_bytes[] = { 0x00, 0x00, 0x00 };
Azure.IoT Build 0:6ae2f7bca550 611
AzureIoTClient 6:641a9672db08 612 /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */
AzureIoTClient 6:641a9672db08 613 if (padding_byte_count > 0)
AzureIoTClient 6:641a9672db08 614 {
AzureIoTClient 6:641a9672db08 615 on_bytes_encoded(callback_context, padding_bytes, padding_byte_count, (payload_count == 0) ? true : false);
AzureIoTClient 6:641a9672db08 616 }
Azure.IoT Build 0:6ae2f7bca550 617
AzureIoTClient 6:641a9672db08 618 for (i = 0; i < payload_count; i++)
AzureIoTClient 6:641a9672db08 619 {
AzureIoTClient 6:641a9672db08 620 /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */
AzureIoTClient 6:641a9672db08 621 on_bytes_encoded(callback_context, payloads[i].bytes, payloads[i].length, (i == payload_count - 1) ? true : false);
AzureIoTClient 6:641a9672db08 622 }
AzureIoTClient 6:641a9672db08 623
AzureIoTClient 6:641a9672db08 624 /* Codes_SRS_FRAME_CODEC_01_043: [On success it shall return 0.] */
AzureIoTClient 6:641a9672db08 625 result = 0;
AzureIoTClient 6:641a9672db08 626 }
Azure.IoT Build 0:6ae2f7bca550 627 }
Azure.IoT Build 0:6ae2f7bca550 628
Azure.IoT Build 0:6ae2f7bca550 629 return result;
Azure.IoT Build 0:6ae2f7bca550 630 }