A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Tue Jan 24 15:23:52 2017 -0800
Revision:
17:923575db8b2d
Parent:
16:22a72cf8e416
Child:
19:000ab4e6a2c1
1.1.5

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