Microsoft Azure IoTHub client libraries

Dependents:   sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp f767zi_mqtt ... more

This library implements the Microsoft Azure IoTHub client library. The code is replicated from https://github.com/Azure/azure-iot-sdks

Revision:
75:86205ca63a59
Parent:
73:c4d9077dd0a1
Child:
77:e4e36df9caee
--- a/iothub_client_ll.c	Fri Aug 25 11:22:43 2017 -0700
+++ b/iothub_client_ll.c	Mon Sep 11 09:22:55 2017 -0700
@@ -20,6 +20,10 @@
 #include "iothub_client_version.h"
 #include <stdint.h>
 
+#ifdef USE_DPS_MODULE
+#include "iothub_client_dps_ll.h"
+#endif
+
 #ifndef DONT_USE_UPLOADTOBLOB
 #include "iothub_client_ll_uploadtoblob.h"
 #endif
@@ -176,7 +180,7 @@
     return result;
 }
 
-static IOTHUB_CLIENT_LL_HANDLE_DATA* initialize_iothub_client(const IOTHUB_CLIENT_CONFIG* client_config, const IOTHUB_CLIENT_DEVICE_CONFIG* device_config)
+static IOTHUB_CLIENT_LL_HANDLE_DATA* initialize_iothub_client(const IOTHUB_CLIENT_CONFIG* client_config, const IOTHUB_CLIENT_DEVICE_CONFIG* device_config, bool use_dev_auth)
 {
     IOTHUB_CLIENT_LL_HANDLE_DATA* result;
     STRING_HANDLE product_info = make_product_info(NULL);
@@ -198,88 +202,65 @@
             IOTHUB_CLIENT_CONFIG actual_config;
             const IOTHUB_CLIENT_CONFIG* config = NULL;
             char* IoTHubName = NULL;
-            STRING_HANDLE transport_hostname = NULL;
+            char* IoTHubSuffix = NULL;
 
             memset(result, 0, sizeof(IOTHUB_CLIENT_LL_HANDLE_DATA));
-
-            const char* device_key;
-            const char* device_id;
-            const char* sas_token;
-
-            if (device_config == NULL)
-            {
-                device_key = client_config->deviceKey;
-                device_id = client_config->deviceId;
-                sas_token = client_config->deviceSasToken;
-            }
-            else
-            {
-                device_key = device_config->deviceKey;
-                device_id = device_config->deviceId;
-                sas_token = device_config->deviceSasToken;
-            }
-
-            /* Codes_SRS_IOTHUBCLIENT_LL_07_029: [ IoTHubClient_LL_Create shall create the Auth module with the device_key, device_id, and/or deviceSasToken values ] */
-            if ((result->authorization_module = IoTHubClient_Auth_Create(device_key, device_id, sas_token)) == NULL)
+            if (use_dev_auth)
             {
-                LogError("Failed create authorization module");
-                free(result);
-                STRING_delete(product_info);
-                result = NULL;
-            }
-            else if (client_config != NULL)
-            {
-                IOTHUBTRANSPORT_CONFIG lowerLayerConfig;
-                memset(&lowerLayerConfig, 0, sizeof(IOTHUBTRANSPORT_CONFIG));
-                /*Codes_SRS_IOTHUBCLIENT_LL_02_006: [IoTHubClient_LL_Create shall populate a structure of type IOTHUBTRANSPORT_CONFIG with the information from config parameter and the previous DLIST and shall pass that to the underlying layer _Create function.]*/
-                lowerLayerConfig.upperConfig = client_config;
-                lowerLayerConfig.waitingToSend = &(result->waitingToSend);
-                lowerLayerConfig.auth_module_handle = result->authorization_module;
-
-                setTransportProtocol(result, (TRANSPORT_PROVIDER*)client_config->protocol());
-                if ((result->transportHandle = result->IoTHubTransport_Create(&lowerLayerConfig)) == NULL)
+                if ((result->authorization_module = IoTHubClient_Auth_CreateFromDeviceAuth(client_config->deviceId)) == NULL)
                 {
-                    /*Codes_SRS_IOTHUBCLIENT_LL_02_007: [If the underlaying layer _Create function fails them IoTHubClient_LL_Create shall fail and return NULL.] */
-                    LogError("underlying transport failed");
-                    destroy_blob_upload_module(result);
-                    tickcounter_destroy(result->tickCounter);
-                    IoTHubClient_Auth_Destroy(result->authorization_module);
-                    STRING_delete(product_info);
+                    LogError("Failed create authorization module");
                     free(result);
+                    STRING_delete(product_info);
                     result = NULL;
                 }
-                else
-                {
-                    /*Codes_SRS_IOTHUBCLIENT_LL_02_008: [Otherwise, IoTHubClient_LL_Create shall succeed and return a non-NULL handle.] */
-                    result->isSharedTransport = false;
-                    config = client_config;
-                }
             }
             else
             {
-                result->transportHandle = device_config->transportHandle;
-                setTransportProtocol(result, (TRANSPORT_PROVIDER*)device_config->protocol());
-
-                transport_hostname = result->IoTHubTransport_GetHostname(result->transportHandle);
-                if (transport_hostname == NULL)
+                const char* device_key;
+                const char* device_id;
+                const char* sas_token;
+                if (device_config == NULL)
                 {
-                    /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/
-                    LogError("unable to determine the transport IoTHub name");
-                    IoTHubClient_Auth_Destroy(result->authorization_module);
-                    STRING_delete(product_info);
-                    free(result);
-                    result = NULL;
+                    device_key = client_config->deviceKey;
+                    device_id = client_config->deviceId;
+                    sas_token = client_config->deviceSasToken;
                 }
                 else
                 {
-                    const char* hostname = STRING_c_str(transport_hostname);
-                    /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClient_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/
-                    /*the first '.' says where the iothubname finishes*/
-                    const char* whereIsDot = strchr(hostname, '.');
-                    if (whereIsDot == NULL)
+                    device_key = device_config->deviceKey;
+                    device_id = device_config->deviceId;
+                    sas_token = device_config->deviceSasToken;
+                }
+
+                /* Codes_SRS_IOTHUBCLIENT_LL_07_029: [ IoTHubClient_LL_Create shall create the Auth module with the device_key, device_id, and/or deviceSasToken values ] */
+                if ((result->authorization_module = IoTHubClient_Auth_Create(device_key, device_id, sas_token)) == NULL)
+                {
+                    LogError("Failed create authorization module");
+                    free(result);
+                    STRING_delete(product_info);
+                    result = NULL;
+                }
+            }
+
+            if (result != NULL)
+            {
+                if (client_config != NULL)
+                {
+                    IOTHUBTRANSPORT_CONFIG lowerLayerConfig;
+                    memset(&lowerLayerConfig, 0, sizeof(IOTHUBTRANSPORT_CONFIG));
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_006: [IoTHubClient_LL_Create shall populate a structure of type IOTHUBTRANSPORT_CONFIG with the information from config parameter and the previous DLIST and shall pass that to the underlying layer _Create function.]*/
+                    lowerLayerConfig.upperConfig = client_config;
+                    lowerLayerConfig.waitingToSend = &(result->waitingToSend);
+                    lowerLayerConfig.auth_module_handle = result->authorization_module;
+
+                    setTransportProtocol(result, (TRANSPORT_PROVIDER*)client_config->protocol());
+                    if ((result->transportHandle = result->IoTHubTransport_Create(&lowerLayerConfig)) == NULL)
                     {
-                        /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/
-                        LogError("unable to determine the IoTHub name");
+                        /*Codes_SRS_IOTHUBCLIENT_LL_02_007: [If the underlaying layer _Create function fails them IoTHubClient_LL_Create shall fail and return NULL.] */
+                        LogError("underlying transport failed");
+                        destroy_blob_upload_module(result);
+                        tickcounter_destroy(result->tickCounter);
                         IoTHubClient_Auth_Destroy(result->authorization_module);
                         STRING_delete(product_info);
                         free(result);
@@ -287,12 +268,38 @@
                     }
                     else
                     {
+                        /*Codes_SRS_IOTHUBCLIENT_LL_02_008: [Otherwise, IoTHubClient_LL_Create shall succeed and return a non-NULL handle.] */
+                        result->isSharedTransport = false;
+                        config = client_config;
+                    }
+                }
+                else
+                {
+                    STRING_HANDLE transport_hostname = NULL;
+
+                    result->transportHandle = device_config->transportHandle;
+                    setTransportProtocol(result, (TRANSPORT_PROVIDER*)device_config->protocol());
+
+                    transport_hostname = result->IoTHubTransport_GetHostname(result->transportHandle);
+                    if (transport_hostname == NULL)
+                    {
+                        /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/
+                        LogError("unable to determine the transport IoTHub name");
+                        IoTHubClient_Auth_Destroy(result->authorization_module);
+                        STRING_delete(product_info);
+                        free(result);
+                        result = NULL;
+                    }
+                    else
+                    {
+                        const char* hostname = STRING_c_str(transport_hostname);
                         /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClient_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/
-                        IoTHubName = (char*)malloc(whereIsDot - hostname + 1);
-                        if (IoTHubName == NULL)
+                        /*the first '.' says where the iothubname finishes*/
+                        const char* whereIsDot = strchr(hostname, '.');
+                        if (whereIsDot == NULL)
                         {
                             /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/
-                            LogError("unable to malloc");
+                            LogError("unable to determine the IoTHub name");
                             IoTHubClient_Auth_Destroy(result->authorization_module);
                             STRING_delete(product_info);
                             free(result);
@@ -300,24 +307,49 @@
                         }
                         else
                         {
-                            const char* IotHubSuffix = whereIsDot + 1;
-                            (void)memcpy(IoTHubName, hostname, whereIsDot - hostname);
-                            IoTHubName[whereIsDot - hostname] = '\0';
+                            size_t suffix_len = strlen(whereIsDot);
+                            /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClient_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/
+                            IoTHubName = (char*)malloc(whereIsDot - hostname + 1);
+                            if (IoTHubName == NULL)
+                            {
+                                /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/
+                                LogError("unable to malloc");
+                                IoTHubClient_Auth_Destroy(result->authorization_module);
+                                STRING_delete(product_info);
+                                free(result);
+                                result = NULL;
+                            }
+                            else if ((IoTHubSuffix = (char*)malloc(suffix_len + 1)) == NULL)
+                            {
+                                /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/
+                                LogError("unable to malloc");
+                                IoTHubClient_Auth_Destroy(result->authorization_module);
+                                STRING_delete(product_info);
+                                free(result);
+                                result = NULL;
+                            }
+                            else
+                            {
+                                memset(IoTHubName, 0, whereIsDot - hostname + 1);
+                                (void)strncpy(IoTHubName, hostname, whereIsDot - hostname);
+                                (void)strcpy(IoTHubSuffix, whereIsDot+1);
 
-                            actual_config.deviceId = device_config->deviceId;
-                            actual_config.deviceKey = device_config->deviceKey;
-                            actual_config.deviceSasToken = device_config->deviceSasToken;
-                            actual_config.iotHubName = IoTHubName;
-                            actual_config.iotHubSuffix = IotHubSuffix;
-                            actual_config.protocol = NULL; /*irrelevant to IoTHubClient_LL_UploadToBlob*/
-                            actual_config.protocolGatewayHostName = NULL; /*irrelevant to IoTHubClient_LL_UploadToBlob*/
+                                actual_config.deviceId = device_config->deviceId;
+                                actual_config.deviceKey = device_config->deviceKey;
+                                actual_config.deviceSasToken = device_config->deviceSasToken;
+                                actual_config.iotHubName = IoTHubName;
+                                actual_config.iotHubSuffix = IoTHubSuffix;
+                                actual_config.protocol = NULL; /*irrelevant to IoTHubClient_LL_UploadToBlob*/
+                                actual_config.protocolGatewayHostName = NULL; /*irrelevant to IoTHubClient_LL_UploadToBlob*/
 
-                            config = &actual_config;
+                                config = &actual_config;
 
-                            /*Codes_SRS_IOTHUBCLIENT_LL_02_008: [Otherwise, IoTHubClient_LL_Create shall succeed and return a non-NULL handle.] */
-                            result->isSharedTransport = true;
+                                /*Codes_SRS_IOTHUBCLIENT_LL_02_008: [Otherwise, IoTHubClient_LL_Create shall succeed and return a non-NULL handle.] */
+                                result->isSharedTransport = true;
+                            }
                         }
                     }
+                    STRING_delete(transport_hostname);
                 }
             }
             if (result != NULL)
@@ -414,9 +446,9 @@
             {
                 free(IoTHubName);
             }
-            if (transport_hostname)
+            if (IoTHubSuffix)
             {
-                STRING_delete(transport_hostname);
+                free(IoTHubSuffix);
             }
         }
     }
@@ -461,8 +493,8 @@
             result->ms_timesOutAfter = 0;
             result->context = userContextCallback;
             result->reported_state_callback = reportedStateCallback;
-			result->client_handle = handleData;
-			result->device_handle = handleData->deviceHandle;
+            result->client_handle = handleData;
+            result->device_handle = handleData->deviceHandle;
         }
     }
     else
@@ -472,6 +504,106 @@
     return result;
 }
 
+IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateFromDeviceAuth(const char* iothub_uri, const char* device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
+{
+    IOTHUB_CLIENT_LL_HANDLE result;
+    if (iothub_uri == NULL || protocol == NULL || device_id == NULL)
+    {
+        LogError("Input parameter is NULL: iothub_uri: %p  protocol: %p device_id: %p", iothub_uri, protocol, device_id);
+        result = NULL;
+    }
+    else
+    {
+#ifdef USE_DPS_MODULE
+        IOTHUB_CLIENT_CONFIG* config = (IOTHUB_CLIENT_CONFIG*)malloc(sizeof(IOTHUB_CLIENT_CONFIG));
+        if (config == NULL)
+        {
+            /* Codes_SRS_IOTHUBCLIENT_LL_12_012: [If the allocation failed IoTHubClient_LL_CreateFromConnectionString  returns NULL]  */
+            LogError("Malloc failed");
+            result = NULL;
+        }
+        else
+        {
+            const char* iterator;
+            const char* initial;
+            char* iothub_name = NULL;
+            char* iothub_suffix = NULL;
+
+            memset(config, 0, sizeof(IOTHUB_CLIENT_CONFIG) );
+            config->protocol = protocol;
+            config->deviceId = device_id;
+            //config->useDeviceAuthKey = 1;
+            
+            // Find the iothub suffix
+            initial = iterator = iothub_uri;
+            while (iterator != NULL && *iterator != '\0')
+            {
+                if (*iterator == '.')
+                {
+                    size_t length = iterator-initial;
+                    iothub_name = (char*)malloc(length+1);
+                    if (iothub_name != NULL)
+                    {
+                        memset(iothub_name, 0, length + 1);
+                        memcpy(iothub_name, initial, length);
+                        config->iotHubName = iothub_name;
+
+                        length = strlen(initial)-length-1;
+                        iothub_suffix = (char*)malloc(length + 1);
+                        if (iothub_suffix != NULL)
+                        {
+                            memset(iothub_suffix, 0, length + 1);
+                            memcpy(iothub_suffix, iterator+1, length);
+                            config->iotHubSuffix = iothub_suffix;
+                            break;
+                        }
+                        else
+                        {
+                            LogError("Failed to allocate iothub suffix");
+                            free(iothub_name);
+                            result = NULL;
+                        }
+                    }
+                    else
+                    {
+                        LogError("Failed to allocate iothub name");
+                        result = NULL;
+                    }
+                }
+                iterator++;
+            }
+
+            if (config->iotHubName == NULL || config->iotHubSuffix == NULL)
+            {
+                LogError("initialize iothub client");
+                result = NULL;
+            }
+            else
+            {
+                IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = initialize_iothub_client(config, NULL, true);
+                if (handleData == NULL)
+                {
+                    LogError("initialize iothub client");
+                    result = NULL;
+                }
+                else
+                {
+                    result = handleData;
+                }
+            }
+
+            free(iothub_name);
+            free(iothub_suffix);
+            free(config);
+        }
+#else
+        LogError("DPS module is not included");
+        result = NULL;
+#endif
+    }
+    return result;
+}
+
 IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol)
 {
     IOTHUB_CLIENT_LL_HANDLE result;
@@ -703,7 +835,7 @@
                 else
                 {
                     /* Codes_SRS_IOTHUBCLIENT_LL_12_011: [IoTHubClient_LL_CreateFromConnectionString shall call into the IoTHubClient_LL_Create API with the current structure and returns with the return value of it] */
-                    result = initialize_iothub_client(config, NULL);
+                    result = initialize_iothub_client(config, NULL, false);
                     if (result == NULL)
                     {
                         LogError("IoTHubClient_LL_Create failed");
@@ -756,7 +888,7 @@
     }
     else
     {
-        IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = initialize_iothub_client(config, NULL);
+        IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = initialize_iothub_client(config, NULL, false);
         if (handleData == NULL)
         {
             LogError("initialize iothub client");
@@ -788,7 +920,7 @@
     }
     else
     {
-        result = initialize_iothub_client(NULL, config);
+        result = initialize_iothub_client(NULL, config, false);
     }
     return result;
 }