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

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)