A small memory footprint AMQP implimentation
Dependents: iothub_client_sample_amqp remote_monitoring simplesample_amqp
Diff: frame_codec.c
- Revision:
- 6:641a9672db08
- Parent:
- 5:ae49385aff34
- Child:
- 12:b30dacf113f2
--- a/frame_codec.c Fri Jul 01 10:42:48 2016 -0700 +++ b/frame_codec.c Fri Jul 29 15:58:39 2016 -0700 @@ -173,7 +173,7 @@ /* 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.] */ int frame_codec_receive_bytes(FRAME_CODEC_HANDLE frame_codec, const unsigned char* buffer, size_t size) { - int result; + int result = __LINE__; FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec; /* Codes_SRS_FRAME_CODEC_01_026: [If frame_codec or buffer are NULL, frame_codec_receive_bytes shall return a non-zero value.] */ @@ -318,7 +318,7 @@ case RECEIVE_FRAME_STATE_TYPE_SPECIFIC: { - uint32_t to_copy = frame_codec_data->type_specific_size - frame_codec_data->receive_frame_pos; + size_t to_copy = frame_codec_data->type_specific_size - frame_codec_data->receive_frame_pos; if (to_copy > size) { to_copy = size; @@ -372,7 +372,7 @@ case RECEIVE_FRAME_STATE_FRAME_BODY: { uint32_t frame_body_size = frame_codec_data->receive_frame_size - (frame_codec_data->receive_frame_doff * 4); - uint32_t to_copy = frame_body_size - frame_codec_data->receive_frame_pos; + size_t to_copy = frame_body_size - frame_codec_data->receive_frame_pos; if (to_copy > size) { @@ -535,26 +535,8 @@ 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) { int result; - uint32_t frame_body_offset = type_specific_size + 6; - /* round up to the 4 bytes for doff */ - /* 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.] */ - /* 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.] */ - uint8_t doff = (frame_body_offset + 3) / 4; - size_t frame_size; FRAME_CODEC_INSTANCE* frame_codec_data = (FRAME_CODEC_INSTANCE*)frame_codec; - uint32_t frame_body_size = 0; - size_t i; - - for (i = 0; i < payload_count; i++) - { - frame_body_size += payloads[i].length; - } - - frame_body_offset = doff * 4; - - /* 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.] */ - frame_size = frame_body_size + frame_body_offset; /* Codes_SRS_FRAME_CODEC_01_044: [If the argument frame_codec is NULL, frame_codec_encode_frame shall return a non-zero value.] */ if ((frame_codec == NULL) || @@ -562,65 +544,88 @@ ((type_specific_size > 0) && (type_specific_bytes == NULL)) || /* 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.] */ (type_specific_size > MAX_TYPE_SPECIFIC_SIZE) || - (frame_codec_data->encode_frame_state == ENCODE_FRAME_STATE_ERROR) || - /* 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.] */ - (frame_size > frame_codec_data->max_frame_size)) + (frame_codec_data->encode_frame_state == ENCODE_FRAME_STATE_ERROR)) { result = __LINE__; } else { - uint8_t padding_byte_count = frame_body_offset - type_specific_size - 6; + /* round up to the 4 bytes for doff */ + /* 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.] */ + /* 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.] */ + uint8_t padding_byte_count; + uint32_t frame_body_offset = type_specific_size + 6; + uint8_t doff = (uint8_t)((frame_body_offset + 3) / 4); + size_t i; + size_t frame_size; + size_t frame_body_size = 0; + frame_body_offset = doff * 4; + padding_byte_count = (uint8_t)(frame_body_offset - type_specific_size - 6); - /* 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.] */ - /* 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.] */ - /* Codes_SRS_FRAME_CODEC_01_056: [frame header The frame header is a fixed size (8 byte) structure that precedes each frame.] */ - /* 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.] */ - /* Codes_SRS_FRAME_CODEC_01_058: [extended header The extended header is a variable width area preceding the frame body.] */ - /* Codes_SRS_FRAME_CODEC_01_059: [This is an extension point defined for future expansion.] */ - /* Codes_SRS_FRAME_CODEC_01_060: [The treatment of this area depends on the frame type.]*/ - /* Codes_SRS_FRAME_CODEC_01_062: [SIZE Bytes 0-3 of the frame header contain the frame size.] */ - /* 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.] */ - /* Codes_SRS_FRAME_CODEC_01_064: [The frame is malformed if the size is less than the size of the frame header (8 bytes).] */ - unsigned char frame_header[] = - { - (frame_size >> 24) & 0xFF, - (frame_size >> 16) & 0xFF, - (frame_size >> 8) & 0xFF, - frame_size & 0xFF, - /* Codes_SRS_FRAME_CODEC_01_065: [DOFF Byte 4 of the frame header is the data offset.] */ - doff, - /* Codes_SRS_FRAME_CODEC_01_069: [TYPE Byte 5 of the frame header is a type code.] */ - type - }; + for (i = 0; i < payload_count; i++) + { + frame_body_size += payloads[i].length; + } + + /* 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.] */ + frame_size = frame_body_size + frame_body_offset; - /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */ - on_bytes_encoded(callback_context, frame_header, sizeof(frame_header), ((frame_body_size + type_specific_bytes + padding_byte_count) == 0) ? true : false); + if (frame_size > frame_codec_data->max_frame_size) + { + /* 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.] */ + result = __LINE__; + } + else + { + /* 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.] */ + /* 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.] */ + /* Codes_SRS_FRAME_CODEC_01_056: [frame header The frame header is a fixed size (8 byte) structure that precedes each frame.] */ + /* 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.] */ + /* Codes_SRS_FRAME_CODEC_01_058: [extended header The extended header is a variable width area preceding the frame body.] */ + /* Codes_SRS_FRAME_CODEC_01_059: [This is an extension point defined for future expansion.] */ + /* Codes_SRS_FRAME_CODEC_01_060: [The treatment of this area depends on the frame type.]*/ + /* Codes_SRS_FRAME_CODEC_01_062: [SIZE Bytes 0-3 of the frame header contain the frame size.] */ + /* 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.] */ + /* Codes_SRS_FRAME_CODEC_01_064: [The frame is malformed if the size is less than the size of the frame header (8 bytes).] */ + unsigned char frame_header[6]; - /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */ - if (type_specific_size > 0) - { - on_bytes_encoded(callback_context, type_specific_bytes, type_specific_size, ((frame_body_size + padding_byte_count) == 0) ? true : false); - } - - /* send padding bytes */ - /* 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.] */ - unsigned char padding_bytes[] = { 0x00, 0x00, 0x00 }; + frame_header[0] = (frame_size >> 24) & 0xFF; + frame_header[1] = (frame_size >> 16) & 0xFF; + frame_header[2] = (frame_size >> 8) & 0xFF; + frame_header[3] = frame_size & 0xFF; + /* Codes_SRS_FRAME_CODEC_01_065: [DOFF Byte 4 of the frame header is the data offset.] */ + frame_header[4] = doff; + /* Codes_SRS_FRAME_CODEC_01_069: [TYPE Byte 5 of the frame header is a type code.] */ + frame_header[5] = type; - /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */ - if (padding_byte_count > 0) - { - on_bytes_encoded(callback_context, padding_bytes, padding_byte_count, (payload_count == 0) ? true : false); - } + /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */ + on_bytes_encoded(callback_context, frame_header, sizeof(frame_header), ((frame_body_size + type_specific_bytes + padding_byte_count) == 0) ? true : false); + + /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */ + if (type_specific_size > 0) + { + on_bytes_encoded(callback_context, type_specific_bytes, type_specific_size, ((frame_body_size + padding_byte_count) == 0) ? true : false); + } + + /* send padding bytes */ + /* 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.] */ + unsigned char padding_bytes[] = { 0x00, 0x00, 0x00 }; - for (i = 0; i < payload_count; i++) - { - /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */ - on_bytes_encoded(callback_context, payloads[i].bytes, payloads[i].length, (i == payload_count - 1) ? true : false); - } + /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */ + if (padding_byte_count > 0) + { + on_bytes_encoded(callback_context, padding_bytes, padding_byte_count, (payload_count == 0) ? true : false); + } - /* Codes_SRS_FRAME_CODEC_01_043: [On success it shall return 0.] */ - result = 0; + for (i = 0; i < payload_count; i++) + { + /* Codes_SRS_FRAME_CODEC_01_088: [Encoded bytes shall be passed to the on_bytes_encoded callback.] */ + on_bytes_encoded(callback_context, payloads[i].bytes, payloads[i].length, (i == payload_count - 1) ? true : false); + } + + /* Codes_SRS_FRAME_CODEC_01_043: [On success it shall return 0.] */ + result = 0; + } } return result;