A small memory footprint AMQP implimentation

Dependents:   iothub_client_sample_amqp remote_monitoring simplesample_amqp

Committer:
AzureIoTClient
Date:
Fri Jul 29 15:58:39 2016 -0700
Revision:
6:641a9672db08
Parent:
0:6ae2f7bca550
Child:
17:923575db8b2d
1.0.10

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 <stddef.h>
Azure.IoT Build 0:6ae2f7bca550 10 #include <string.h>
Azure.IoT Build 0:6ae2f7bca550 11 #include "azure_uamqp_c/amqp_frame_codec.h"
Azure.IoT Build 0:6ae2f7bca550 12 #include "azure_uamqp_c/frame_codec.h"
Azure.IoT Build 0:6ae2f7bca550 13 #include "azure_uamqp_c/amqpalloc.h"
Azure.IoT Build 0:6ae2f7bca550 14 #include "azure_uamqp_c/amqpvalue.h"
Azure.IoT Build 0:6ae2f7bca550 15
Azure.IoT Build 0:6ae2f7bca550 16 typedef enum AMQP_FRAME_DECODE_STATE_TAG
Azure.IoT Build 0:6ae2f7bca550 17 {
Azure.IoT Build 0:6ae2f7bca550 18 AMQP_FRAME_DECODE_FRAME,
Azure.IoT Build 0:6ae2f7bca550 19 AMQP_FRAME_DECODE_ERROR
Azure.IoT Build 0:6ae2f7bca550 20 } AMQP_FRAME_DECODE_STATE;
Azure.IoT Build 0:6ae2f7bca550 21
Azure.IoT Build 0:6ae2f7bca550 22 typedef struct AMQP_FRAME_CODEC_INSTANCE_TAG
Azure.IoT Build 0:6ae2f7bca550 23 {
Azure.IoT Build 0:6ae2f7bca550 24 FRAME_CODEC_HANDLE frame_codec;
Azure.IoT Build 0:6ae2f7bca550 25
Azure.IoT Build 0:6ae2f7bca550 26 /* decode */
Azure.IoT Build 0:6ae2f7bca550 27 AMQP_FRAME_RECEIVED_CALLBACK frame_received_callback;
Azure.IoT Build 0:6ae2f7bca550 28 AMQP_EMPTY_FRAME_RECEIVED_CALLBACK empty_frame_received_callback;
Azure.IoT Build 0:6ae2f7bca550 29 AMQP_FRAME_CODEC_ERROR_CALLBACK error_callback;
Azure.IoT Build 0:6ae2f7bca550 30 void* callback_context;
Azure.IoT Build 0:6ae2f7bca550 31 AMQPVALUE_DECODER_HANDLE decoder;
Azure.IoT Build 0:6ae2f7bca550 32 AMQP_FRAME_DECODE_STATE decode_state;
Azure.IoT Build 0:6ae2f7bca550 33 AMQP_VALUE decoded_performative;
Azure.IoT Build 0:6ae2f7bca550 34 } AMQP_FRAME_CODEC_INSTANCE;
Azure.IoT Build 0:6ae2f7bca550 35
Azure.IoT Build 0:6ae2f7bca550 36 static void amqp_value_decoded(void* context, AMQP_VALUE decoded_value)
Azure.IoT Build 0:6ae2f7bca550 37 {
Azure.IoT Build 0:6ae2f7bca550 38 AMQP_FRAME_CODEC_INSTANCE* amqp_frame_codec_instance = (AMQP_FRAME_CODEC_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 39 uint64_t performative_descriptor_ulong;
Azure.IoT Build 0:6ae2f7bca550 40 AMQP_VALUE descriptor = amqpvalue_get_inplace_descriptor(decoded_value);
Azure.IoT Build 0:6ae2f7bca550 41
Azure.IoT Build 0:6ae2f7bca550 42 /* Codes_SRS_AMQP_FRAME_CODEC_01_060: [If any error occurs while decoding a frame, the decoder shall switch to an error state where decoding shall not be possible anymore.] */
Azure.IoT Build 0:6ae2f7bca550 43 if ((descriptor == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 44 (amqpvalue_get_ulong(descriptor, &performative_descriptor_ulong) != 0) ||
Azure.IoT Build 0:6ae2f7bca550 45 /* Codes_SRS_AMQP_FRAME_CODEC_01_003: [The performative MUST be one of those defined in section 2.7 and is encoded as a described type in the AMQP type system.] */
Azure.IoT Build 0:6ae2f7bca550 46 (performative_descriptor_ulong < AMQP_OPEN) ||
Azure.IoT Build 0:6ae2f7bca550 47 (performative_descriptor_ulong > AMQP_CLOSE))
Azure.IoT Build 0:6ae2f7bca550 48 {
Azure.IoT Build 0:6ae2f7bca550 49 /* Codes_SRS_AMQP_FRAME_CODEC_01_060: [If any error occurs while decoding a frame, the decoder shall switch to an error state where decoding shall not be possible anymore.] */
Azure.IoT Build 0:6ae2f7bca550 50 amqp_frame_codec_instance->decode_state = AMQP_FRAME_DECODE_ERROR;
Azure.IoT Build 0:6ae2f7bca550 51 }
Azure.IoT Build 0:6ae2f7bca550 52 else
Azure.IoT Build 0:6ae2f7bca550 53 {
Azure.IoT Build 0:6ae2f7bca550 54 amqp_frame_codec_instance->decoded_performative = decoded_value;
Azure.IoT Build 0:6ae2f7bca550 55 }
Azure.IoT Build 0:6ae2f7bca550 56 }
Azure.IoT Build 0:6ae2f7bca550 57
Azure.IoT Build 0:6ae2f7bca550 58 static void frame_received(void* context, const unsigned char* type_specific, uint32_t type_specific_size, const unsigned char* frame_body, uint32_t frame_body_size)
Azure.IoT Build 0:6ae2f7bca550 59 {
Azure.IoT Build 0:6ae2f7bca550 60 AMQP_FRAME_CODEC_INSTANCE* amqp_frame_codec_instance = (AMQP_FRAME_CODEC_INSTANCE*)context;
Azure.IoT Build 0:6ae2f7bca550 61 uint16_t channel;
Azure.IoT Build 0:6ae2f7bca550 62
Azure.IoT Build 0:6ae2f7bca550 63 switch (amqp_frame_codec_instance->decode_state)
Azure.IoT Build 0:6ae2f7bca550 64 {
Azure.IoT Build 0:6ae2f7bca550 65 default:
Azure.IoT Build 0:6ae2f7bca550 66 /* Codes_SRS_AMQP_FRAME_CODEC_01_050: [All subsequent decoding shall fail and no AMQP frames shall be indicated from that point on to the consumers of amqp_frame_codec.] */
Azure.IoT Build 0:6ae2f7bca550 67 case AMQP_FRAME_DECODE_ERROR:
Azure.IoT Build 0:6ae2f7bca550 68 break;
Azure.IoT Build 0:6ae2f7bca550 69
Azure.IoT Build 0:6ae2f7bca550 70 case AMQP_FRAME_DECODE_FRAME:
Azure.IoT Build 0:6ae2f7bca550 71 /* Codes_SRS_AMQP_FRAME_CODEC_01_049: [If not enough type specific bytes are received to decode the channel number, the decoding shall stop with an error.] */
Azure.IoT Build 0:6ae2f7bca550 72 if (type_specific_size < 2)
Azure.IoT Build 0:6ae2f7bca550 73 {
Azure.IoT Build 0:6ae2f7bca550 74 amqp_frame_codec_instance->decode_state = AMQP_FRAME_DECODE_ERROR;
Azure.IoT Build 0:6ae2f7bca550 75
Azure.IoT Build 0:6ae2f7bca550 76 /* Codes_SRS_AMQP_FRAME_CODEC_01_069: [If any error occurs while decoding a frame, the decoder shall indicate the error by calling the amqp_frame_codec_error_callback and passing to it the callback context argument that was given in amqp_frame_codec_create.] */
Azure.IoT Build 0:6ae2f7bca550 77 amqp_frame_codec_instance->error_callback(amqp_frame_codec_instance->callback_context);
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 /* Codes_SRS_AMQP_FRAME_CODEC_01_001: [Bytes 6 and 7 of an AMQP frame contain the channel number ] */
Azure.IoT Build 0:6ae2f7bca550 82 channel = ((uint16_t)type_specific[0]) << 8;
Azure.IoT Build 0:6ae2f7bca550 83 channel += type_specific[1];
Azure.IoT Build 0:6ae2f7bca550 84
Azure.IoT Build 0:6ae2f7bca550 85 if (frame_body_size == 0)
Azure.IoT Build 0:6ae2f7bca550 86 {
Azure.IoT Build 0:6ae2f7bca550 87 /* Codes_SRS_AMQP_FRAME_CODEC_01_048: [When a frame header is received from frame_codec and the frame payload size is 0, empty_frame_received_callback shall be invoked, while passing the channel number as argument.] */
Azure.IoT Build 0:6ae2f7bca550 88 /* Codes_SRS_AMQP_FRAME_CODEC_01_007: [An AMQP frame with no body MAY be used to generate artificial traffic as needed to satisfy any negotiated idle timeout interval ] */
Azure.IoT Build 0:6ae2f7bca550 89 amqp_frame_codec_instance->empty_frame_received_callback(amqp_frame_codec_instance->callback_context, channel);
Azure.IoT Build 0:6ae2f7bca550 90 }
Azure.IoT Build 0:6ae2f7bca550 91 else
Azure.IoT Build 0:6ae2f7bca550 92 {
Azure.IoT Build 0:6ae2f7bca550 93 /* Codes_SRS_AMQP_FRAME_CODEC_01_051: [If the frame payload is greater than 0, amqp_frame_codec shall decode the performative as a described AMQP type.] */
Azure.IoT Build 0:6ae2f7bca550 94 /* Codes_SRS_AMQP_FRAME_CODEC_01_002: [The frame body is defined as a performative followed by an opaque payload.] */
Azure.IoT Build 0:6ae2f7bca550 95 amqp_frame_codec_instance->decoded_performative = NULL;
Azure.IoT Build 0:6ae2f7bca550 96
Azure.IoT Build 0:6ae2f7bca550 97 while ((frame_body_size > 0) &&
Azure.IoT Build 0:6ae2f7bca550 98 (amqp_frame_codec_instance->decoded_performative == NULL) &&
Azure.IoT Build 0:6ae2f7bca550 99 (amqp_frame_codec_instance->decode_state != AMQP_FRAME_DECODE_ERROR))
Azure.IoT Build 0:6ae2f7bca550 100 {
Azure.IoT Build 0:6ae2f7bca550 101 /* Codes_SRS_AMQP_FRAME_CODEC_01_052: [Decoding the performative shall be done by feeding the bytes to the decoder create in amqp_frame_codec_create.] */
Azure.IoT Build 0:6ae2f7bca550 102 if (amqpvalue_decode_bytes(amqp_frame_codec_instance->decoder, frame_body, 1) != 0)
Azure.IoT Build 0:6ae2f7bca550 103 {
Azure.IoT Build 0:6ae2f7bca550 104 /* Codes_SRS_AMQP_FRAME_CODEC_01_060: [If any error occurs while decoding a frame, the decoder shall switch to an error state where decoding shall not be possible anymore.] */
Azure.IoT Build 0:6ae2f7bca550 105 amqp_frame_codec_instance->decode_state = AMQP_FRAME_DECODE_ERROR;
Azure.IoT Build 0:6ae2f7bca550 106 }
Azure.IoT Build 0:6ae2f7bca550 107 else
Azure.IoT Build 0:6ae2f7bca550 108 {
Azure.IoT Build 0:6ae2f7bca550 109 frame_body_size--;
Azure.IoT Build 0:6ae2f7bca550 110 frame_body++;
Azure.IoT Build 0:6ae2f7bca550 111 }
Azure.IoT Build 0:6ae2f7bca550 112 }
Azure.IoT Build 0:6ae2f7bca550 113
Azure.IoT Build 0:6ae2f7bca550 114 if (amqp_frame_codec_instance->decode_state == AMQP_FRAME_DECODE_ERROR)
Azure.IoT Build 0:6ae2f7bca550 115 {
Azure.IoT Build 0:6ae2f7bca550 116 /* Codes_SRS_AMQP_FRAME_CODEC_01_069: [If any error occurs while decoding a frame, the decoder shall indicate the error by calling the amqp_frame_codec_error_callback and passing to it the callback context argument that was given in amqp_frame_codec_create.] */
Azure.IoT Build 0:6ae2f7bca550 117 amqp_frame_codec_instance->error_callback(amqp_frame_codec_instance->callback_context);
Azure.IoT Build 0:6ae2f7bca550 118 }
Azure.IoT Build 0:6ae2f7bca550 119 else
Azure.IoT Build 0:6ae2f7bca550 120 {
Azure.IoT Build 0:6ae2f7bca550 121 /* Codes_SRS_AMQP_FRAME_CODEC_01_004: [The remaining bytes in the frame body form the payload for that frame.] */
Azure.IoT Build 0:6ae2f7bca550 122 /* Codes_SRS_AMQP_FRAME_CODEC_01_067: [When the performative is decoded, the rest of the frame_bytes shall not be given to the AMQP decoder, but they shall be buffered so that later they are given to the frame_received callback.] */
Azure.IoT Build 0:6ae2f7bca550 123 /* Codes_SRS_AMQP_FRAME_CODEC_01_054: [Once the performative is decoded and all frame payload bytes are received, the callback frame_received_callback shall be called.] */
Azure.IoT Build 0:6ae2f7bca550 124 /* Codes_SRS_AMQP_FRAME_CODEC_01_068: [A pointer to all the payload bytes shall also be passed to frame_received_callback.] */
Azure.IoT Build 0:6ae2f7bca550 125 amqp_frame_codec_instance->frame_received_callback(amqp_frame_codec_instance->callback_context, channel, amqp_frame_codec_instance->decoded_performative, frame_body, frame_body_size);
Azure.IoT Build 0:6ae2f7bca550 126 }
Azure.IoT Build 0:6ae2f7bca550 127 }
Azure.IoT Build 0:6ae2f7bca550 128 }
Azure.IoT Build 0:6ae2f7bca550 129 break;
Azure.IoT Build 0:6ae2f7bca550 130 }
Azure.IoT Build 0:6ae2f7bca550 131 }
Azure.IoT Build 0:6ae2f7bca550 132
Azure.IoT Build 0:6ae2f7bca550 133 static int encode_bytes(void* context, const unsigned char* bytes, size_t length)
Azure.IoT Build 0:6ae2f7bca550 134 {
Azure.IoT Build 0:6ae2f7bca550 135 PAYLOAD* payload = (PAYLOAD*)context;
Azure.IoT Build 0:6ae2f7bca550 136 (void)memcpy((unsigned char*)payload->bytes + payload->length, bytes, length);
Azure.IoT Build 0:6ae2f7bca550 137 payload->length += length;
Azure.IoT Build 0:6ae2f7bca550 138 return 0;
Azure.IoT Build 0:6ae2f7bca550 139 }
Azure.IoT Build 0:6ae2f7bca550 140
Azure.IoT Build 0:6ae2f7bca550 141 /* Codes_SRS_AMQP_FRAME_CODEC_01_011: [amqp_frame_codec_create shall create an instance of an amqp_frame_codec and return a non-NULL handle to it.] */
Azure.IoT Build 0:6ae2f7bca550 142 AMQP_FRAME_CODEC_HANDLE amqp_frame_codec_create(FRAME_CODEC_HANDLE frame_codec, AMQP_FRAME_RECEIVED_CALLBACK frame_received_callback,
Azure.IoT Build 0:6ae2f7bca550 143 AMQP_EMPTY_FRAME_RECEIVED_CALLBACK empty_frame_received_callback, AMQP_FRAME_CODEC_ERROR_CALLBACK amqp_frame_codec_error_callback, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 144 {
Azure.IoT Build 0:6ae2f7bca550 145 AMQP_FRAME_CODEC_INSTANCE* result;
Azure.IoT Build 0:6ae2f7bca550 146
Azure.IoT Build 0:6ae2f7bca550 147 /* Codes_SRS_AMQP_FRAME_CODEC_01_012: [If any of the arguments frame_codec, frame_received_callback, amqp_frame_codec_error_callback or empty_frame_received_callback is NULL, amqp_frame_codec_create shall return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 148 if ((frame_codec == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 149 (frame_received_callback == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 150 (empty_frame_received_callback == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 151 (amqp_frame_codec_error_callback == NULL))
Azure.IoT Build 0:6ae2f7bca550 152 {
Azure.IoT Build 0:6ae2f7bca550 153 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 154 }
Azure.IoT Build 0:6ae2f7bca550 155 else
Azure.IoT Build 0:6ae2f7bca550 156 {
Azure.IoT Build 0:6ae2f7bca550 157 result = (AMQP_FRAME_CODEC_INSTANCE*)amqpalloc_malloc(sizeof(AMQP_FRAME_CODEC_INSTANCE));
Azure.IoT Build 0:6ae2f7bca550 158 /* Codes_SRS_AMQP_FRAME_CODEC_01_020: [If allocating memory for the new amqp_frame_codec fails, then amqp_frame_codec_create shall fail and return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 159 if (result != NULL)
Azure.IoT Build 0:6ae2f7bca550 160 {
Azure.IoT Build 0:6ae2f7bca550 161 result->frame_codec = frame_codec;
Azure.IoT Build 0:6ae2f7bca550 162 result->frame_received_callback = frame_received_callback;
Azure.IoT Build 0:6ae2f7bca550 163 result->empty_frame_received_callback = empty_frame_received_callback;
Azure.IoT Build 0:6ae2f7bca550 164 result->error_callback = amqp_frame_codec_error_callback;
Azure.IoT Build 0:6ae2f7bca550 165 result->callback_context = callback_context;
Azure.IoT Build 0:6ae2f7bca550 166 result->decode_state = AMQP_FRAME_DECODE_FRAME;
Azure.IoT Build 0:6ae2f7bca550 167
Azure.IoT Build 0:6ae2f7bca550 168 /* Codes_SRS_AMQP_FRAME_CODEC_01_018: [amqp_frame_codec_create shall create a decoder to be used for decoding AMQP values.] */
Azure.IoT Build 0:6ae2f7bca550 169 result->decoder = amqpvalue_decoder_create(amqp_value_decoded, result);
Azure.IoT Build 0:6ae2f7bca550 170 if (result->decoder == NULL)
Azure.IoT Build 0:6ae2f7bca550 171 {
Azure.IoT Build 0:6ae2f7bca550 172 /* Codes_SRS_AMQP_FRAME_CODEC_01_019: [If creating the decoder fails, amqp_frame_codec_create shall fail and return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 173 amqpalloc_free(result);
Azure.IoT Build 0:6ae2f7bca550 174 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 175 }
Azure.IoT Build 0:6ae2f7bca550 176 else
Azure.IoT Build 0:6ae2f7bca550 177 {
Azure.IoT Build 0:6ae2f7bca550 178 /* Codes_SRS_AMQP_FRAME_CODEC_01_013: [amqp_frame_codec_create shall subscribe for AMQP frames with the given frame_codec.] */
Azure.IoT Build 0:6ae2f7bca550 179 if (frame_codec_subscribe(frame_codec, FRAME_TYPE_AMQP, frame_received, result) != 0)
Azure.IoT Build 0:6ae2f7bca550 180 {
Azure.IoT Build 0:6ae2f7bca550 181 /* Codes_SRS_AMQP_FRAME_CODEC_01_014: [If subscribing for AMQP frames fails, amqp_frame_codec_create shall fail and return NULL.] */
Azure.IoT Build 0:6ae2f7bca550 182 amqpvalue_decoder_destroy(result->decoder);
Azure.IoT Build 0:6ae2f7bca550 183 amqpalloc_free(result);
Azure.IoT Build 0:6ae2f7bca550 184 result = NULL;
Azure.IoT Build 0:6ae2f7bca550 185 }
Azure.IoT Build 0:6ae2f7bca550 186 }
Azure.IoT Build 0:6ae2f7bca550 187 }
Azure.IoT Build 0:6ae2f7bca550 188 }
Azure.IoT Build 0:6ae2f7bca550 189
Azure.IoT Build 0:6ae2f7bca550 190 return result;
Azure.IoT Build 0:6ae2f7bca550 191 }
Azure.IoT Build 0:6ae2f7bca550 192
Azure.IoT Build 0:6ae2f7bca550 193 void amqp_frame_codec_destroy(AMQP_FRAME_CODEC_HANDLE amqp_frame_codec)
Azure.IoT Build 0:6ae2f7bca550 194 {
Azure.IoT Build 0:6ae2f7bca550 195 if (amqp_frame_codec != NULL)
Azure.IoT Build 0:6ae2f7bca550 196 {
Azure.IoT Build 0:6ae2f7bca550 197 /* Codes_SRS_AMQP_FRAME_CODEC_01_017: [amqp_frame_codec_destroy shall unsubscribe from receiving AMQP frames from the frame_codec that was passed to amqp_frame_codec_create.] */
Azure.IoT Build 0:6ae2f7bca550 198 (void)frame_codec_unsubscribe(amqp_frame_codec->frame_codec, FRAME_TYPE_AMQP);
Azure.IoT Build 0:6ae2f7bca550 199
Azure.IoT Build 0:6ae2f7bca550 200 /* Codes_SRS_AMQP_FRAME_CODEC_01_021: [The decoder created in amqp_frame_codec_create shall be destroyed by amqp_frame_codec_destroy.] */
Azure.IoT Build 0:6ae2f7bca550 201 amqpvalue_decoder_destroy(amqp_frame_codec->decoder);
Azure.IoT Build 0:6ae2f7bca550 202
Azure.IoT Build 0:6ae2f7bca550 203 /* Codes_SRS_AMQP_FRAME_CODEC_01_015: [amqp_frame_codec_destroy shall free all resources associated with the amqp_frame_codec instance.] */
Azure.IoT Build 0:6ae2f7bca550 204 amqpalloc_free(amqp_frame_codec);
Azure.IoT Build 0:6ae2f7bca550 205 }
Azure.IoT Build 0:6ae2f7bca550 206 }
Azure.IoT Build 0:6ae2f7bca550 207
Azure.IoT Build 0:6ae2f7bca550 208 int amqp_frame_codec_encode_frame(AMQP_FRAME_CODEC_HANDLE amqp_frame_codec, uint16_t channel, const AMQP_VALUE performative, const PAYLOAD* payloads, size_t payload_count, ON_BYTES_ENCODED on_bytes_encoded, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 209 {
Azure.IoT Build 0:6ae2f7bca550 210 int result;
Azure.IoT Build 0:6ae2f7bca550 211
Azure.IoT Build 0:6ae2f7bca550 212 /* Codes_SRS_AMQP_FRAME_CODEC_01_024: [If frame_codec, performative or on_bytes_encoded is NULL, amqp_frame_codec_encode_frame shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 213 if ((amqp_frame_codec == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 214 (performative == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 215 (on_bytes_encoded == NULL))
Azure.IoT Build 0:6ae2f7bca550 216 {
Azure.IoT Build 0:6ae2f7bca550 217 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 218 }
Azure.IoT Build 0:6ae2f7bca550 219 else
Azure.IoT Build 0:6ae2f7bca550 220 {
Azure.IoT Build 0:6ae2f7bca550 221 AMQP_VALUE descriptor;
Azure.IoT Build 0:6ae2f7bca550 222 uint64_t performative_ulong;
Azure.IoT Build 0:6ae2f7bca550 223 size_t encoded_size;
Azure.IoT Build 0:6ae2f7bca550 224
Azure.IoT Build 0:6ae2f7bca550 225 if (((descriptor = amqpvalue_get_inplace_descriptor(performative)) == NULL) ||
Azure.IoT Build 0:6ae2f7bca550 226 (amqpvalue_get_ulong(descriptor, &performative_ulong) != 0) ||
Azure.IoT Build 0:6ae2f7bca550 227 /* Codes_SRS_AMQP_FRAME_CODEC_01_008: [The performative MUST be one of those defined in section 2.7 and is encoded as a described type in the AMQP type system.] */
Azure.IoT Build 0:6ae2f7bca550 228 (performative_ulong < AMQP_OPEN) ||
Azure.IoT Build 0:6ae2f7bca550 229 (performative_ulong > AMQP_CLOSE))
Azure.IoT Build 0:6ae2f7bca550 230 {
Azure.IoT Build 0:6ae2f7bca550 231 /* Codes_SRS_AMQP_FRAME_CODEC_01_029: [If any error occurs during encoding, amqp_frame_codec_encode_frame shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 232 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 233 }
Azure.IoT Build 0:6ae2f7bca550 234 /* Codes_SRS_AMQP_FRAME_CODEC_01_027: [The encoded size of the performative and its fields shall be obtained by calling amqpvalue_get_encoded_size.] */
Azure.IoT Build 0:6ae2f7bca550 235 else if (amqpvalue_get_encoded_size(performative, &encoded_size) != 0)
Azure.IoT Build 0:6ae2f7bca550 236 {
Azure.IoT Build 0:6ae2f7bca550 237 /* Codes_SRS_AMQP_FRAME_CODEC_01_029: [If any error occurs during encoding, amqp_frame_codec_encode_frame shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 238 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 239 }
Azure.IoT Build 0:6ae2f7bca550 240 else
Azure.IoT Build 0:6ae2f7bca550 241 {
Azure.IoT Build 0:6ae2f7bca550 242 unsigned char* amqp_performative_bytes = (unsigned char*)amqpalloc_malloc(encoded_size);
Azure.IoT Build 0:6ae2f7bca550 243 if (amqp_performative_bytes == NULL)
Azure.IoT Build 0:6ae2f7bca550 244 {
Azure.IoT Build 0:6ae2f7bca550 245 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 246 }
Azure.IoT Build 0:6ae2f7bca550 247 else
Azure.IoT Build 0:6ae2f7bca550 248 {
Azure.IoT Build 0:6ae2f7bca550 249 PAYLOAD* new_payloads = (PAYLOAD*)amqpalloc_malloc(sizeof(PAYLOAD) * (payload_count + 1));
Azure.IoT Build 0:6ae2f7bca550 250 if (new_payloads == NULL)
Azure.IoT Build 0:6ae2f7bca550 251 {
Azure.IoT Build 0:6ae2f7bca550 252 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 253 }
Azure.IoT Build 0:6ae2f7bca550 254 else
Azure.IoT Build 0:6ae2f7bca550 255 {
Azure.IoT Build 0:6ae2f7bca550 256 /* Codes_SRS_AMQP_FRAME_CODEC_01_070: [The payloads argument for frame_codec_encode_frame shall be made of the payload for the encoded performative and the payloads passed to amqp_frame_codec_encode_frame.] */
Azure.IoT Build 0:6ae2f7bca550 257 /* Codes_SRS_AMQP_FRAME_CODEC_01_028: [The encode result for the performative shall be placed in a PAYLOAD structure.] */
Azure.IoT Build 0:6ae2f7bca550 258 new_payloads[0].bytes = amqp_performative_bytes;
Azure.IoT Build 0:6ae2f7bca550 259 new_payloads[0].length = 0;
Azure.IoT Build 0:6ae2f7bca550 260
Azure.IoT Build 0:6ae2f7bca550 261 if (payload_count > 0)
Azure.IoT Build 0:6ae2f7bca550 262 {
Azure.IoT Build 0:6ae2f7bca550 263 (void)memcpy(new_payloads + 1, payloads, sizeof(PAYLOAD) * payload_count);
Azure.IoT Build 0:6ae2f7bca550 264 }
Azure.IoT Build 0:6ae2f7bca550 265
Azure.IoT Build 0:6ae2f7bca550 266 if (amqpvalue_encode(performative, encode_bytes, &new_payloads[0]) != 0)
Azure.IoT Build 0:6ae2f7bca550 267 {
Azure.IoT Build 0:6ae2f7bca550 268 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 269 }
Azure.IoT Build 0:6ae2f7bca550 270 else
Azure.IoT Build 0:6ae2f7bca550 271 {
AzureIoTClient 6:641a9672db08 272 unsigned char channel_bytes[2];
AzureIoTClient 6:641a9672db08 273
AzureIoTClient 6:641a9672db08 274 channel_bytes[0] = channel >> 8;
AzureIoTClient 6:641a9672db08 275 channel_bytes[1] = channel & 0xFF;
Azure.IoT Build 0:6ae2f7bca550 276
Azure.IoT Build 0:6ae2f7bca550 277 /* Codes_SRS_AMQP_FRAME_CODEC_01_005: [Bytes 6 and 7 of an AMQP frame contain the channel number ] */
Azure.IoT Build 0:6ae2f7bca550 278 /* Codes_SRS_AMQP_FRAME_CODEC_01_025: [amqp_frame_codec_encode_frame shall encode the frame header by using frame_codec_encode_frame.] */
Azure.IoT Build 0:6ae2f7bca550 279 /* Codes_SRS_AMQP_FRAME_CODEC_01_006: [The frame body is defined as a performative followed by an opaque payload.] */
Azure.IoT Build 0:6ae2f7bca550 280 if (frame_codec_encode_frame(amqp_frame_codec->frame_codec, FRAME_TYPE_AMQP, new_payloads, payload_count + 1, channel_bytes, sizeof(channel_bytes), on_bytes_encoded, callback_context) != 0)
Azure.IoT Build 0:6ae2f7bca550 281 {
Azure.IoT Build 0:6ae2f7bca550 282 /* Codes_SRS_AMQP_FRAME_CODEC_01_029: [If any error occurs during encoding, amqp_frame_codec_encode_frame shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 283 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 284 }
Azure.IoT Build 0:6ae2f7bca550 285 else
Azure.IoT Build 0:6ae2f7bca550 286 {
Azure.IoT Build 0:6ae2f7bca550 287 /* Codes_SRS_AMQP_FRAME_CODEC_01_022: [amqp_frame_codec_begin_encode_frame shall encode the frame header and AMQP performative in an AMQP frame and on success it shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 288 result = 0;
Azure.IoT Build 0:6ae2f7bca550 289 }
Azure.IoT Build 0:6ae2f7bca550 290 }
Azure.IoT Build 0:6ae2f7bca550 291
Azure.IoT Build 0:6ae2f7bca550 292 amqpalloc_free(new_payloads);
Azure.IoT Build 0:6ae2f7bca550 293 }
Azure.IoT Build 0:6ae2f7bca550 294
Azure.IoT Build 0:6ae2f7bca550 295 amqpalloc_free(amqp_performative_bytes);
Azure.IoT Build 0:6ae2f7bca550 296 }
Azure.IoT Build 0:6ae2f7bca550 297 }
Azure.IoT Build 0:6ae2f7bca550 298 }
Azure.IoT Build 0:6ae2f7bca550 299
Azure.IoT Build 0:6ae2f7bca550 300 return result;
Azure.IoT Build 0:6ae2f7bca550 301 }
Azure.IoT Build 0:6ae2f7bca550 302
Azure.IoT Build 0:6ae2f7bca550 303 /* Codes_SRS_AMQP_FRAME_CODEC_01_042: [amqp_frame_codec_encode_empty_frame shall encode a frame with no payload.] */
Azure.IoT Build 0:6ae2f7bca550 304 /* Codes_SRS_AMQP_FRAME_CODEC_01_010: [An AMQP frame with no body MAY be used to generate artificial traffic as needed to satisfy any negotiated idle timeout interval ] */
Azure.IoT Build 0:6ae2f7bca550 305 int amqp_frame_codec_encode_empty_frame(AMQP_FRAME_CODEC_HANDLE amqp_frame_codec, uint16_t channel, ON_BYTES_ENCODED on_bytes_encoded, void* callback_context)
Azure.IoT Build 0:6ae2f7bca550 306 {
Azure.IoT Build 0:6ae2f7bca550 307 int result;
Azure.IoT Build 0:6ae2f7bca550 308
Azure.IoT Build 0:6ae2f7bca550 309 /* Codes_SRS_AMQP_FRAME_CODEC_01_045: [If amqp_frame_codec is NULL, amqp_frame_codec_encode_empty_frame shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 310 if (amqp_frame_codec == NULL)
Azure.IoT Build 0:6ae2f7bca550 311 {
Azure.IoT Build 0:6ae2f7bca550 312 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 313 }
Azure.IoT Build 0:6ae2f7bca550 314 else
Azure.IoT Build 0:6ae2f7bca550 315 {
AzureIoTClient 6:641a9672db08 316 unsigned char channel_bytes[2];
AzureIoTClient 6:641a9672db08 317
AzureIoTClient 6:641a9672db08 318 channel_bytes[0] = channel >> 8;
AzureIoTClient 6:641a9672db08 319 channel_bytes[1] = channel & 0xFF;
Azure.IoT Build 0:6ae2f7bca550 320
Azure.IoT Build 0:6ae2f7bca550 321 /* Codes_SRS_AMQP_FRAME_CODEC_01_044: [amqp_frame_codec_encode_empty_frame shall use frame_codec_encode_frame to encode the frame.] */
Azure.IoT Build 0:6ae2f7bca550 322 if (frame_codec_encode_frame(amqp_frame_codec->frame_codec, FRAME_TYPE_AMQP, NULL, 0, channel_bytes, sizeof(channel_bytes), on_bytes_encoded, callback_context) != 0)
Azure.IoT Build 0:6ae2f7bca550 323 {
Azure.IoT Build 0:6ae2f7bca550 324 /* Codes_SRS_AMQP_FRAME_CODEC_01_046: [If encoding fails in any way, amqp_frame_codec_encode_empty_frame shall fail and return a non-zero value.] */
Azure.IoT Build 0:6ae2f7bca550 325 result = __LINE__;
Azure.IoT Build 0:6ae2f7bca550 326 }
Azure.IoT Build 0:6ae2f7bca550 327 else
Azure.IoT Build 0:6ae2f7bca550 328 {
Azure.IoT Build 0:6ae2f7bca550 329 /* Codes_SRS_AMQP_FRAME_CODEC_01_043: [On success, amqp_frame_codec_encode_empty_frame shall return 0.] */
Azure.IoT Build 0:6ae2f7bca550 330 result = 0;
Azure.IoT Build 0:6ae2f7bca550 331 }
Azure.IoT Build 0:6ae2f7bca550 332 }
Azure.IoT Build 0:6ae2f7bca550 333
Azure.IoT Build 0:6ae2f7bca550 334 return result;
Azure.IoT Build 0:6ae2f7bca550 335 }