A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

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