A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Jan 13 18:40:42 2017 -0800
Revision:
16:22a72cf8e416
Parent:
15:5db103709f20
Child:
17:923575db8b2d
1.1.4

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