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:
54:830550fef7ea
Parent:
53:e21e1e88460f
Child:
56:8704100b3b54
--- a/iothubtransportamqp_methods.c	Mon Jun 11 15:38:09 2018 -0700
+++ b/iothubtransportamqp_methods.c	Tue Jun 26 19:13:11 2018 -0700
@@ -25,6 +25,7 @@
 typedef struct IOTHUBTRANSPORT_AMQP_METHODS_TAG
 {
     char* device_id;
+    char* module_id;
     char* hostname;
     LINK_HANDLE receiver_link;
     LINK_HANDLE sender_link;
@@ -90,7 +91,7 @@
     }
 }
 
-IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransportamqp_methods_create(const char* hostname, const char* device_id)
+IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransportamqp_methods_create(const char* hostname, const char* device_id, const char* module_id)
 {
     IOTHUBTRANSPORT_AMQP_METHODS* result;
 
@@ -113,6 +114,8 @@
         }
         else
         {
+            memset(result, 0, sizeof(IOTHUBTRANSPORT_AMQP_METHODS));
+            
             /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_115: [ `iothubtransportamqp_methods_create` shall save the device id for later use by using `mallocAndStrcpy_s`. ]*/
             if (mallocAndStrcpy_s(&result->device_id, device_id) != 0)
             {
@@ -121,6 +124,14 @@
                 free(result);
                 result = NULL;
             }
+            else if ((module_id != NULL) && (mallocAndStrcpy_s(&result->module_id, module_id) != 0))
+            {
+                /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_116: [ If `mallocAndStrcpy_s` fails, `iothubtransportamqp_methods_create` shall return NULL. ]*/
+                LogError("Cannot copy device_id");
+                free(result->device_id);
+                free(result);
+                result = NULL;
+            }
             else
             {
                 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_139: [ `iothubtransportamqp_methods_create` shall save the `hostname` for later use by using `mallocAndStrcpy_s`. ]*/
@@ -129,6 +140,7 @@
                     /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_116: [ If `mallocAndStrcpy_s` fails, `iothubtransportamqp_methods_create` shall return NULL. ]*/
                     LogError("Cannot copy hostname");
                     free(result->device_id);
+                    free(result->module_id);
                     free(result);
                     result = NULL;
                 }
@@ -177,6 +189,7 @@
         /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_005: [ `iothubtransportamqp_methods_destroy` shall free all resources allocated by `iothubtransportamqp_methods_create` for the handle `iothubtransport_amqp_methods_handle`. ]*/
         free(iothubtransport_amqp_methods_handle->hostname);
         free(iothubtransport_amqp_methods_handle->device_id);
+        free(iothubtransport_amqp_methods_handle->module_id);
         free(iothubtransport_amqp_methods_handle);
     }
 }
@@ -476,6 +489,56 @@
     return result;
 }
 
+STRING_HANDLE create_correlation_id(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransport_amqp_methods_handle)
+{
+    if (iothubtransport_amqp_methods_handle->module_id != NULL)
+    {
+        return STRING_construct_sprintf("%s/%s", iothubtransport_amqp_methods_handle->device_id, iothubtransport_amqp_methods_handle->module_id);  
+    }
+    else
+    {
+        return STRING_construct(iothubtransport_amqp_methods_handle->device_id);
+    }
+}
+
+STRING_HANDLE create_peer_endpoint_name(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransport_amqp_methods_handle)
+{
+    if (iothubtransport_amqp_methods_handle->module_id != NULL)
+    {
+        return STRING_construct_sprintf("amqps://%s/devices/%s/modules/%s/methods/devicebound", iothubtransport_amqp_methods_handle->hostname, iothubtransport_amqp_methods_handle->device_id, iothubtransport_amqp_methods_handle->module_id);
+    }
+    else
+    {
+        return STRING_construct_sprintf("amqps://%s/devices/%s/methods/devicebound", iothubtransport_amqp_methods_handle->hostname, iothubtransport_amqp_methods_handle->device_id);
+    }
+}
+
+STRING_HANDLE create_requests_link_name(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransport_amqp_methods_handle)
+{
+    if (iothubtransport_amqp_methods_handle->module_id != NULL)
+    {
+        return STRING_construct_sprintf("methods_requests_link-%s/%s", iothubtransport_amqp_methods_handle->device_id, iothubtransport_amqp_methods_handle->module_id);
+    }
+    else
+    {
+        return STRING_construct_sprintf("methods_requests_link-%s", iothubtransport_amqp_methods_handle->device_id);
+    }
+}
+
+STRING_HANDLE create_responses_link_name(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransport_amqp_methods_handle)
+{
+    if (iothubtransport_amqp_methods_handle->module_id != NULL)
+    {
+        return STRING_construct_sprintf("methods_responses_link-%s/%s", iothubtransport_amqp_methods_handle->device_id, iothubtransport_amqp_methods_handle->module_id);
+    }
+    else
+    {
+        return STRING_construct_sprintf("methods_responses_link-%s", iothubtransport_amqp_methods_handle->device_id);
+    }
+}
+
+
+
 static int set_link_attach_properties(IOTHUBTRANSPORT_AMQP_METHODS_HANDLE iothubtransport_amqp_methods_handle)
 {
     int result = 0;
@@ -486,7 +549,7 @@
     if (link_attach_properties == NULL)
     {
         /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
-        LogError("Cannot create the map for link ttach properties");
+        LogError("Cannot create the map for link attach properties");
         result = __FAILURE__;
     }
     else
@@ -501,9 +564,17 @@
         }
         else
         {
-            /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_142: [ A property value of type string that shall contain the device id shall be created by calling `amqpvalue_create_string`. ]*/
-            AMQP_VALUE channel_correlation_id_property_value = amqpvalue_create_string(iothubtransport_amqp_methods_handle->device_id);
-            if (channel_correlation_id_property_value == NULL)
+            /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_142: [ A property value of type string that shall contain the device id (and "/" + module id if module is present) shall be created by calling `amqpvalue_create_string`. ]*/
+            STRING_HANDLE correlation_id = NULL;
+            AMQP_VALUE channel_correlation_id_property_value = NULL;
+
+            if ((correlation_id = create_correlation_id(iothubtransport_amqp_methods_handle)) == NULL)
+            {
+                /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
+                LogError("Cannot create the channel correlation id string for the link attach properties");
+                result = __FAILURE__;
+            }
+            else if ((channel_correlation_id_property_value = amqpvalue_create_string(STRING_c_str(correlation_id))) == NULL)
             {
                 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_145: [ If any call for creating or setting the link attach properties fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
                 LogError("Cannot create the channel correlation id property key for the link attach properties");
@@ -577,6 +648,7 @@
                 /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_146: [ The link attach properties and all associated values shall be freed by calling `amqpvalue_destroy` after setting the link attach properties. ]*/
                 amqpvalue_destroy(channel_correlation_id_property_value);
             }
+            STRING_delete(correlation_id);
 
             /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_146: [ The link attach properties and all associated values shall be freed by calling `amqpvalue_destroy` after setting the link attach properties. ]*/
             amqpvalue_destroy(channel_correlation_id_property_key);
@@ -615,9 +687,9 @@
     }
     else
     {
-        /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_015: [ The address string used to create the source shall be of the form `/devices/{device id}/methods/devicebound`. ]*/
+        /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_015: [ The address string used to create the source shall be of the form `/devices/{device id}` + (`/modules/{module  id}` if modules are present) + `/methods/devicebound`. ]*/
         /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_016: [ The string shall be created by using `STRING_construct_sprintf`. ]*/
-        STRING_HANDLE peer_endpoint_string = STRING_construct_sprintf("amqps://%s/devices/%s/methods/devicebound", iothubtransport_amqp_methods_handle->hostname, iothubtransport_amqp_methods_handle->device_id);
+        STRING_HANDLE peer_endpoint_string = create_peer_endpoint_name(iothubtransport_amqp_methods_handle);
         if (peer_endpoint_string == NULL)
         {
             /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_018: [ If `STRING_construct_sprintf` fails `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
@@ -653,8 +725,8 @@
                 }
                 else
                 {
-                    /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_012: [ - `name` shall be in the format `methods_requests_link-{device_id}`, where device_id is the `device_id` argument passed to `iothubtransportamqp_methods_create`. ]*/
-                    STRING_HANDLE requests_link_name = STRING_construct_sprintf("methods_requests_link-%s", iothubtransport_amqp_methods_handle->device_id);
+                    /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_012: [ - `name` shall be in the format `methods_requests_link-{device_id}` (+ `/{module-id}` if module id is present). ]*/
+                    STRING_HANDLE requests_link_name = create_requests_link_name(iothubtransport_amqp_methods_handle); 
                     if (requests_link_name == NULL)
                     {
                         /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_153: [ If constructing the requests link name fails, `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
@@ -696,11 +768,11 @@
                                 }
                                 else
                                 {
-                                    /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_023: [ - `name` shall be format `methods_responses_link-{device_id}`, where device_id is the `device_id` argument passed to `iothubtransportamqp_methods_create`. ]*/
-                                    STRING_HANDLE responses_link_name = STRING_construct_sprintf("methods_responses_link-%s", iothubtransport_amqp_methods_handle->device_id);
+                                    /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_023: [ - `name` shall be format `methods_responses_link-{device_id}` (+ `/{module-id}` if module id is present). ]*/
+                                    STRING_HANDLE responses_link_name = create_responses_link_name(iothubtransport_amqp_methods_handle);
                                     if (responses_link_name == NULL)
                                     {
-                                        /* CodeS_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_154: [ If constructing the responses link name fails, `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
+                                        /* Codes_SRS_IOTHUBTRANSPORT_AMQP_METHODS_01_154: [ If constructing the responses link name fails, `iothubtransportamqp_methods_subscribe` shall fail and return a non-zero value. ]*/
                                         LogError("Cannot create methods responses link name.");
                                         result = __FAILURE__;
                                     }