Xin Zhang / azure-iot-c-sdk-f767zi

Dependents:   samplemqtt

Committer:
XinZhangMS
Date:
Thu Aug 23 06:52:14 2018 +0000
Revision:
0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI

Who changed what in which revision?

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