Microsoft Azure IoTHub client AMQP transport
Dependents: sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp iothub_client_sample_amqp ... more
This library implements the AMQP transport for Microsoft Azure IoTHub client. The code is replicated from https://github.com/Azure/azure-iot-sdks
Diff: uamqp_messaging.c
- Revision:
- 42:c2eaa912a28c
- Parent:
- 41:71c01aa3df1a
- Child:
- 43:3da2d93bb955
--- a/uamqp_messaging.c Mon Sep 11 09:22:16 2017 -0700 +++ b/uamqp_messaging.c Mon Sep 25 13:37:09 2017 -0700 @@ -1,9 +1,20 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +#ifdef __cplusplus +#include <cstdlib> +#include <cstdint> +#include <cinttypes> +#else #include <stdlib.h> +#include <stdint.h> +#include <inttypes.h> +#endif + #include "uamqp_messaging.h" +#include "azure_c_shared_utility/gballoc.h" #include "azure_c_shared_utility/optimize_size.h" #include "azure_c_shared_utility/xlogging.h" +#include "azure_c_shared_utility/uuid.h" #include "azure_uamqp_c/message.h" #include "azure_uamqp_c/amqpvalue.h" #include "iothub_message.h" @@ -11,6 +22,8 @@ #define RESULT_OK 0 #endif +#define MESSAGE_ID_MAX_SIZE 128 + static int encode_callback(void* context, const unsigned char* bytes, size_t length) { BINARY_DATA* message_body_binary = (BINARY_DATA*)context; @@ -430,79 +443,223 @@ static int readPropertiesFromuAMQPMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, MESSAGE_HANDLE uamqp_message) { - int return_value; + int result; PROPERTIES_HANDLE uamqp_message_properties; AMQP_VALUE uamqp_message_property; - const char* uamqp_message_property_value; - int api_call_result; // Codes_SRS_UAMQP_MESSAGING_09_008: [The uAMQP message properties shall be retrieved using message_get_properties().] - if ((api_call_result = message_get_properties(uamqp_message, &uamqp_message_properties)) != 0) + if (message_get_properties(uamqp_message, &uamqp_message_properties) != 0) { // Codes_SRS_UAMQP_MESSAGING_09_009: [If message_get_properties() fails, message_create_IoTHubMessage_from_uamqp_message shall fail and return immediately.] - LogError("Failed to get property properties map from uAMQP message (error code %d).", api_call_result); - return_value = __FAILURE__; + LogError("Failed to get property properties map from uAMQP message."); + result = __FAILURE__; } else { - return_value = 0; // Properties 'message-id' and 'correlation-id' are optional according to the AMQP 1.0 spec. + result = RESULT_OK; // Properties 'message-id' and 'correlation-id' are optional according to the AMQP 1.0 spec. // Codes_SRS_UAMQP_MESSAGING_09_010: [The message-id property shall be read from the uAMQP message by calling properties_get_message_id.] - if ((api_call_result = properties_get_message_id(uamqp_message_properties, &uamqp_message_property)) != 0) + if (properties_get_message_id(uamqp_message_properties, &uamqp_message_property) != 0 || uamqp_message_property == NULL) { // Codes_SRS_UAMQP_MESSAGING_09_011: [If properties_get_message_id fails, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] - LogInfo("Failed to get value of uAMQP message 'message-id' property (%d). No failure, since it is optional.", api_call_result); } - // Codes_SRS_UAMQP_MESSAGING_09_012: [The type of the message-id property value shall be obtained using amqpvalue_get_type().] - // Codes_SRS_UAMQP_MESSAGING_09_013: [If the type of the message-id property value is AMQP_TYPE_NULL, message_create_IoTHubMessage_from_uamqp_message() shall skip processing the message-id (as it is optional) and continue normally.] - else if (amqpvalue_get_type(uamqp_message_property) != AMQP_TYPE_NULL) + else { - // Codes_SRS_UAMQP_MESSAGING_09_014: [The message-id value shall be retrieved from the AMQP_VALUE as char* by calling amqpvalue_get_string().] - if ((api_call_result = amqpvalue_get_string(uamqp_message_property, &uamqp_message_property_value)) != 0) + // Codes_SRS_UAMQP_MESSAGING_09_012: [The type of the message-id property value shall be obtained using amqpvalue_get_type().] + AMQP_TYPE value_type = amqpvalue_get_type(uamqp_message_property); + + // Codes_SRS_UAMQP_MESSAGING_09_013: [If the type of the message-id property value is AMQP_TYPE_NULL, message_create_IoTHubMessage_from_uamqp_message() shall skip processing the message-id (as it is optional) and continue normally.] + if (value_type != AMQP_TYPE_NULL) { - // Codes_SRS_UAMQP_MESSAGING_09_015: [If amqpvalue_get_string fails, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] - LogError("Failed to get value of uAMQP message 'message-id' property (%d).", api_call_result); - return_value = __FAILURE__; - } - // Codes_SRS_UAMQP_MESSAGING_09_016: [The message-id property shall be set on the IOTHUB_MESSAGE_HANDLE instance by calling IoTHubMessage_SetMessageId(), passing the value read from the uAMQP message.] - else if (IoTHubMessage_SetMessageId(iothub_message_handle, uamqp_message_property_value) != IOTHUB_MESSAGE_OK) - { - // Codes_SRS_UAMQP_MESSAGING_09_017: [If IoTHubMessage_SetMessageId fails, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] - LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'message-id' property."); - return_value = __FAILURE__; + + char* string_value; + char string_buffer[MESSAGE_ID_MAX_SIZE]; + + memset(string_buffer, 0, MESSAGE_ID_MAX_SIZE); + + if (value_type == AMQP_TYPE_STRING) + { + // Codes_SRS_UAMQP_MESSAGING_09_014: [The message-id value shall be retrieved from the AMQP_VALUE as char sequence] + if (amqpvalue_get_string(uamqp_message_property, (const char**)(&string_value)) != 0) + { + // Codes_SRS_UAMQP_MESSAGING_09_015: [If message-id fails to be obtained, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] + LogError("Failed to get value of uAMQP message 'message-id' property (string)"); + string_value = NULL; + result = __FAILURE__; + } + } + else if (value_type == AMQP_TYPE_ULONG) + { + uint64_t ulong_value; + + // Codes_SRS_UAMQP_MESSAGING_09_014: [The message-id value shall be retrieved from the AMQP_VALUE as char sequence] + if (amqpvalue_get_ulong(uamqp_message_property, &ulong_value) != 0) + { + // Codes_SRS_UAMQP_MESSAGING_09_015: [If message-id fails to be obtained, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] + LogError("Failed to get value of uAMQP message 'message-id' property (ulong)"); + string_value = NULL; + result = __FAILURE__; + } + else if (sprintf(string_buffer, "%" PRIu64, ulong_value) < 0) + { + LogError("Failed converting 'message-id' (ulong) to string"); + string_value = NULL; + result = __FAILURE__; + } + else + { + string_value = string_buffer; + } + } + else if (value_type == AMQP_TYPE_UUID) + { + uuid uuid_value; + + // Codes_SRS_UAMQP_MESSAGING_09_014: [The message-id value shall be retrieved from the AMQP_VALUE as char sequence] + if (amqpvalue_get_uuid(uamqp_message_property, &uuid_value) != 0) + { + // Codes_SRS_UAMQP_MESSAGING_09_015: [If message-id fails to be obtained, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] + LogError("Failed to get value of uAMQP message 'message-id' property (UUID)"); + string_value = NULL; + result = __FAILURE__; + } + else if ((string_value = UUID_to_string((UUID*)uuid_value)) == NULL) + { + // Codes_SRS_UAMQP_MESSAGING_09_015: [If message-id fails to be obtained, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] + LogError("Failed to get the string representation of 'message-id' UUID"); + string_value = NULL; + result = __FAILURE__; + } + else + { + (void)memcpy(string_buffer, string_value, sizeof(char) * strlen(string_value)); + free(string_value); + string_value = string_buffer; + } + } + else + { + LogError("Unrecognized type for message-id (%d)", value_type); + string_value = NULL; + result = __FAILURE__; + } + + if (string_value != NULL) + { + // Codes_SRS_UAMQP_MESSAGING_09_016: [The message-id property shall be set on the IOTHUB_MESSAGE_HANDLE instance by calling IoTHubMessage_SetMessageId(), passing the value read from the uAMQP message.] + if (IoTHubMessage_SetMessageId(iothub_message_handle, string_value) != IOTHUB_MESSAGE_OK) + { + // Codes_SRS_UAMQP_MESSAGING_09_017: [If IoTHubMessage_SetMessageId fails, IoTHubMessage_CreateFromuAMQPMessage() shall fail and return immediately.] + LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'message-id' property."); + result = __FAILURE__; + } + } } } // Codes_SRS_UAMQP_MESSAGING_09_018: [The correlation-id property shall be read from the uAMQP message by calling properties_get_correlation_id.] - if ((api_call_result = properties_get_correlation_id(uamqp_message_properties, &uamqp_message_property)) != 0) + if (properties_get_correlation_id(uamqp_message_properties, &uamqp_message_property) != 0 || uamqp_message_property == NULL) { // Codes_SRS_UAMQP_MESSAGING_09_019: [If properties_get_correlation_id() fails, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] - LogError("Failed to get value of uAMQP message 'correlation-id' property (%d). No failure, since it is optional.", api_call_result); } - // Codes_SRS_UAMQP_MESSAGING_09_020: [The type of the correlation-id property value shall be obtained using amqpvalue_get_type().] - // Codes_SRS_UAMQP_MESSAGING_09_021: [If the type of the correlation-id property value is AMQP_TYPE_NULL, message_create_IoTHubMessage_from_uamqp_message() shall skip processing the correlation-id (as it is optional) and continue normally.] - else if (amqpvalue_get_type(uamqp_message_property) != AMQP_TYPE_NULL) + else { - // Codes_SRS_UAMQP_MESSAGING_09_022: [The correlation-id value shall be retrieved from the AMQP_VALUE as char* by calling amqpvalue_get_string.] - if ((api_call_result = amqpvalue_get_string(uamqp_message_property, &uamqp_message_property_value)) != 0) + // Codes_SRS_UAMQP_MESSAGING_09_020: [The type of the correlation-id property value shall be obtained using amqpvalue_get_type().] + AMQP_TYPE value_type = amqpvalue_get_type(uamqp_message_property); + + // Codes_SRS_UAMQP_MESSAGING_09_021: [If the type of the correlation-id property value is AMQP_TYPE_NULL, IoTHubMessage_CreateFromuAMQPMessage() shall skip processing the correlation-id (as it is optional) and continue normally.] + if (value_type != AMQP_TYPE_NULL) { - // Codes_SRS_UAMQP_MESSAGING_09_023: [If amqpvalue_get_string fails, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] - LogError("Failed to get value of uAMQP message 'correlation-id' property (%d).", api_call_result); - return_value = __FAILURE__; - } - // Codes_SRS_UAMQP_MESSAGING_09_024: [The correlation-id property shall be set on the IOTHUB_MESSAGE_HANDLE by calling IoTHubMessage_SetCorrelationId, passing the value read from the uAMQP message.] - else if (IoTHubMessage_SetCorrelationId(iothub_message_handle, uamqp_message_property_value) != IOTHUB_MESSAGE_OK) - { - // Codes_SRS_UAMQP_MESSAGING_09_025: [If IoTHubMessage_SetCorrelationId fails, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] - LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'correlation-id' property."); - return_value = __FAILURE__; + char* string_value; + char string_buffer[MESSAGE_ID_MAX_SIZE]; + + memset(string_buffer, 0, MESSAGE_ID_MAX_SIZE); + + if (value_type == AMQP_TYPE_STRING) + { + // Codes_SRS_UAMQP_MESSAGING_09_022: [The correlation-id value shall be retrieved from the AMQP_VALUE as char sequence] + if (amqpvalue_get_string(uamqp_message_property, (const char**)(&string_value)) != 0) + { + // Codes_SRS_UAMQP_MESSAGING_09_023: [If correlation-id fails to be obtained, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] + LogError("Failed to get value of uAMQP message 'correlation-id' property (string)"); + string_value = NULL; + result = __FAILURE__; + } + } + else if (value_type == AMQP_TYPE_ULONG) + { + uint64_t ulong_value; + + // Codes_SRS_UAMQP_MESSAGING_09_022: [The correlation-id value shall be retrieved from the AMQP_VALUE as char sequence] + if (amqpvalue_get_ulong(uamqp_message_property, &ulong_value) != 0) + { + // Codes_SRS_UAMQP_MESSAGING_09_023: [If correlation-id fails to be obtained, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] + LogError("Failed to get value of uAMQP message 'correlation-id' property (ulong)"); + string_value = NULL; + result = __FAILURE__; + } + else if (sprintf(string_buffer, "%" PRIu64, ulong_value) < 0) + { + LogError("Failed converting 'correlation-id' (ulong) to string"); + string_value = NULL; + result = __FAILURE__; + } + else + { + string_value = string_buffer; + } + } + else if (value_type == AMQP_TYPE_UUID) + { + uuid uuid_value; + + // Codes_SRS_UAMQP_MESSAGING_09_022: [The correlation-id value shall be retrieved from the AMQP_VALUE as char sequence] + if (amqpvalue_get_uuid(uamqp_message_property, &uuid_value) != 0) + { + // Codes_SRS_UAMQP_MESSAGING_09_023: [If correlation-id fails to be obtained, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] + LogError("Failed to get value of uAMQP message 'correlation-id' property (UUID)"); + string_value = NULL; + result = __FAILURE__; + } + else if ((string_value = UUID_to_string((UUID*)uuid_value)) == NULL) + { + // Codes_SRS_UAMQP_MESSAGING_09_023: [If correlation-id fails to be obtained, message_create_IoTHubMessage_from_uamqp_message() shall fail and return immediately.] + LogError("Failed to get the string representation of 'correlation-id' UUID"); + string_value = NULL; + result = __FAILURE__; + } + else + { + (void)memcpy(string_buffer, string_value, sizeof(char) * strlen(string_value)); + free(string_value); + string_value = string_buffer; + } + } + else + { + LogError("Unrecognized type for correlation-id (%d)", value_type); + string_value = NULL; + result = __FAILURE__; + } + + if (string_value != NULL) + { + // Codes_SRS_UAMQP_MESSAGING_09_024: [The correlation-id property shall be set on the IOTHUB_MESSAGE_HANDLE by calling IoTHubMessage_SetCorrelationId, passing the value read from the uAMQP message.] + if (IoTHubMessage_SetCorrelationId(iothub_message_handle, string_value) != IOTHUB_MESSAGE_OK) + { + // Codes_SRS_UAMQP_MESSAGING_09_025: [If IoTHubMessage_SetCorrelationId fails, IoTHubMessage_CreateFromuAMQPMessage() shall fail and return immediately.] + LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'correlation-id' property."); + result = __FAILURE__; + } + } } } + // Codes_SRS_UAMQP_MESSAGING_09_026: [message_create_IoTHubMessage_from_uamqp_message() shall destroy the uAMQP message properties (obtained with message_get_properties()) by calling properties_destroy().] properties_destroy(uamqp_message_properties); } - return return_value; + return result; } static int readApplicationPropertiesFromuAMQPMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, MESSAGE_HANDLE uamqp_message)