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:
43:038d8511e817
Parent:
42:448eecc3676e
Child:
44:33dd78697616
--- a/iothub_client_ll.c	Tue Jun 07 10:49:08 2016 -0700
+++ b/iothub_client_ll.c	Fri Jun 17 17:02:44 2016 -0700
@@ -16,7 +16,10 @@
 #include "iothub_client_private.h"
 #include "iothub_client_version.h"
 #include "iothub_transport_ll.h"
+
+#ifdef USE_UPLOADTOBLOB
 #include "iothub_client_ll_uploadtoblob.h"
+#endif
 
 #define LOG_ERROR LogError("result = %s", ENUM_TO_STRING(IOTHUB_CLIENT_RESULT, result));
 #define INDEFINITE_TIME ((time_t)(-1))
@@ -35,7 +38,9 @@
     time_t lastMessageReceiveTime;
     TICK_COUNTER_HANDLE tickCounter; /*shared tickcounter used to track message timeouts in waitingToSend list*/
     uint64_t currentMessageTimeout;
+#ifdef USE_UPLOADTOBLOB
     IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE uploadToBlobHandle;
+#endif
 
 }IOTHUB_CLIENT_LL_HANDLE_DATA;
 
@@ -274,6 +279,7 @@
 
 static void setTransportProtocol(IOTHUB_CLIENT_LL_HANDLE_DATA* handleData, TRANSPORT_PROVIDER* protocol)
 {
+    handleData->IoTHubTransport_GetHostname = protocol->IoTHubTransport_GetHostname;
     handleData->IoTHubTransport_SetOption = protocol->IoTHubTransport_SetOption;
     handleData->IoTHubTransport_Create = protocol->IoTHubTransport_Create;
     handleData->IoTHubTransport_Destroy = protocol->IoTHubTransport_Destroy;
@@ -308,6 +314,7 @@
         }
         else
         {
+#ifdef USE_UPLOADTOBLOB
             /*Codes_SRS_IOTHUBCLIENT_LL_02_094: [ IoTHubClient_LL_Create shall create a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE from IOTHUB_CLIENT_CONFIG. ]*/
             /*Codes_SRS_IOTHUBCLIENT_LL_02_092: [ IoTHubClient_LL_CreateFromConnectionString shall create a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE from IOTHUB_CLIENT_CONFIG. ]*/
             handleData->uploadToBlobHandle = IoTHubClient_LL_UploadToBlob_Create(config);
@@ -320,12 +327,15 @@
                 result = NULL;
             }
             else
+#endif
             {
                 /*Codes_SRS_IOTHUBCLIENT_LL_02_045: [ Otherwise IoTHubClient_LL_Create shall create a new TICK_COUNTER_HANDLE ]*/
                 if ((handleData->tickCounter = tickcounter_create()) == NULL)
                 {
+#ifdef USE_UPLOADTOBLOB
                     /*Codes_SRS_IOTHUBCLIENT_LL_02_046: [ If creating the TICK_COUNTER_HANDLE fails then IoTHubClient_LL_Create shall fail and return NULL. ]*/
                     IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle);
+#endif
                     LogError("unable to get a tickcounter");
                     free(handleData);
                     result = NULL;
@@ -346,7 +356,9 @@
                     if ((handleData->transportHandle = handleData->IoTHubTransport_Create(&lowerLayerConfig)) == NULL)
                     {
                         LogError("underlying transport failed");
+#ifdef USE_UPLOADTOBLOB
                         IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle);
+#endif
                         tickcounter_destroy(handleData->tickCounter);
                         free(handleData);
                         result = NULL;
@@ -365,7 +377,9 @@
                             /*Codes_SRS_IOTHUBCLIENT_LL_17_009: [If the _Register function fails, this function shall fail and return NULL.]*/
                             LogError("Registering device in transport failed");
                             handleData->IoTHubTransport_Destroy(handleData->transportHandle);
+#ifdef USE_UPLOADTOBLOB
                             IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle);
+#endif
                             tickcounter_destroy(handleData->tickCounter);
                             free(handleData);
                             result = NULL;
@@ -412,51 +426,113 @@
         }
         else
         {
-            handleData->uploadToBlobHandle = NULL;
-            /*Codes_SRS_IOTHUBCLIENT_LL_02_047: [ IoTHubClient_LL_CreateWithTransport shall create a TICK_COUNTER_HANDLE. ]*/
-            if ((handleData->tickCounter = tickcounter_create()) == NULL)
+            handleData->transportHandle = config->transportHandle;
+            setTransportProtocol(handleData, (TRANSPORT_PROVIDER*)config->protocol());
+
+#ifdef USE_UPLOADTOBLOB
+            const char* hostname = STRING_c_str(handleData->IoTHubTransport_GetHostname(handleData->transportHandle));
+            /*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)
             {
-                /*Codes_SRS_IOTHUBCLIENT_LL_02_048: [ If creating the handle fails, then IoTHubClient_LL_CreateWithTransport shall fail and return NULL ]*/
-                LogError("unable to get a tickcounter");
+                /*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");
                 free(handleData);
                 result = NULL;
             }
             else
             {
-                /*Codes_SRS_IOTHUBCLIENT_LL_17_004: [IoTHubClient_LL_CreateWithTransport shall initialize a new DLIST (further called "waitingToSend") containing records with fields of the following types: IOTHUB_MESSAGE_HANDLE, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, void*.]*/
-                DList_InitializeListHead(&(handleData->waitingToSend));
-                setTransportProtocol(handleData, (TRANSPORT_PROVIDER*)config->protocol());
-                handleData->messageCallback = NULL;
-                handleData->messageUserContextCallback = NULL;
-                handleData->lastMessageReceiveTime = INDEFINITE_TIME;
-                handleData->transportHandle = config->transportHandle;
-
-
-                IOTHUB_DEVICE_CONFIG deviceConfig;
-
-                deviceConfig.deviceId = config->deviceId;
-                deviceConfig.deviceKey = config->deviceKey;
-                deviceConfig.deviceSasToken = config->deviceSasToken;
-
-                /*Codes_SRS_IOTHUBCLIENT_LL_17_006: [IoTHubClient_LL_CreateWithTransport shall call the transport _Register function with the IOTHUB_DEVICE_CONFIG populated structure and waitingToSend list.]*/
-                if ((handleData->deviceHandle = handleData->IoTHubTransport_Register(config->transportHandle, &deviceConfig, handleData, &(handleData->waitingToSend))) == NULL)
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClient_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/
+                char* IoTHubName = malloc(whereIsDot - hostname + 1);
+                if (IoTHubName == NULL)
                 {
-                    /*Codes_SRS_IOTHUBCLIENT_LL_17_007: [If the _Register function fails, this function shall fail and return NULL.]*/
-                    LogError("Registering device in transport failed");
-
-                    tickcounter_destroy(handleData->tickCounter);
+                    /*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");
                     free(handleData);
                     result = NULL;
                 }
                 else
                 {
-                    /*Codes_SRS_IOTHUBCLIENT_LL_17_005: [IoTHubClient_LL_CreateWithTransport shall save the transport handle and mark this transport as shared.]*/
-                    handleData->isSharedTransport = true;
-                    /*Codes_SRS_IOTHUBCLIENT_LL_02_042: [ By default, messages shall not timeout. ]*/
-                    handleData->currentMessageTimeout = 0;
-                    result = handleData;
+                    const char* IotHubSuffix = whereIsDot + 1;
+                    memcpy(IoTHubName, hostname, whereIsDot - hostname);
+                    IoTHubName[whereIsDot - hostname ] = '\0';
+                    
+                    IOTHUB_CLIENT_CONFIG temp;
+                    temp.deviceId = config->deviceId;
+                    temp.deviceKey = config->deviceKey;
+                    temp.deviceSasToken = config->deviceSasToken;
+                    temp.iotHubName = IoTHubName;
+                    temp.iotHubSuffix = IotHubSuffix;
+                    temp.protocol = NULL; /*irrelevant to IoTHubClient_LL_UploadToBlob*/
+                    temp.protocolGatewayHostName = NULL; /*irrelevant to IoTHubClient_LL_UploadToBlob*/
+
+                    /*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. ]*/
+                    handleData->uploadToBlobHandle = IoTHubClient_LL_UploadToBlob_Create(&temp);
+                    if (handleData->uploadToBlobHandle == NULL)
+                    {
+                        /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClient_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/
+                        LogError("unable to IoTHubClient_LL_UploadToBlob_Create");
+                        free(handleData);
+                        result = NULL;
+                    }
+                    else
+#endif
+                    {
+                        /*Codes_SRS_IOTHUBCLIENT_LL_02_047: [ IoTHubClient_LL_CreateWithTransport shall create a TICK_COUNTER_HANDLE. ]*/
+                        if ((handleData->tickCounter = tickcounter_create()) == NULL)
+                        {
+                            /*Codes_SRS_IOTHUBCLIENT_LL_02_048: [ If creating the handle fails, then IoTHubClient_LL_CreateWithTransport shall fail and return NULL ]*/
+                            LogError("unable to get a tickcounter");
+#ifdef USE_UPLOADTOBLOB
+                            IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle);
+#endif
+                            free(handleData);
+                            result = NULL;
+                        }
+                        else
+                        {
+                            /*Codes_SRS_IOTHUBCLIENT_LL_17_004: [IoTHubClient_LL_CreateWithTransport shall initialize a new DLIST (further called "waitingToSend") containing records with fields of the following types: IOTHUB_MESSAGE_HANDLE, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, void*.]*/
+                            DList_InitializeListHead(&(handleData->waitingToSend));
+                            
+                            handleData->messageCallback = NULL;
+                            handleData->messageUserContextCallback = NULL;
+                            handleData->lastMessageReceiveTime = INDEFINITE_TIME;
+                            
+
+                            IOTHUB_DEVICE_CONFIG deviceConfig;
+
+                            deviceConfig.deviceId = config->deviceId;
+                            deviceConfig.deviceKey = config->deviceKey;
+                            deviceConfig.deviceSasToken = config->deviceSasToken;
+
+                            /*Codes_SRS_IOTHUBCLIENT_LL_17_006: [IoTHubClient_LL_CreateWithTransport shall call the transport _Register function with the IOTHUB_DEVICE_CONFIG populated structure and waitingToSend list.]*/
+                            if ((handleData->deviceHandle = handleData->IoTHubTransport_Register(config->transportHandle, &deviceConfig, handleData, &(handleData->waitingToSend))) == NULL)
+                            {
+                                /*Codes_SRS_IOTHUBCLIENT_LL_17_007: [If the _Register function fails, this function shall fail and return NULL.]*/
+                                LogError("Registering device in transport failed");
+#ifdef USE_UPLOADTOBLOB
+                                IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle);
+#endif
+                                tickcounter_destroy(handleData->tickCounter);
+                                free(handleData);
+                                result = NULL;
+                            }
+                            else
+                            {
+                                /*Codes_SRS_IOTHUBCLIENT_LL_17_005: [IoTHubClient_LL_CreateWithTransport shall save the transport handle and mark this transport as shared.]*/
+                                handleData->isSharedTransport = true;
+                                /*Codes_SRS_IOTHUBCLIENT_LL_02_042: [ By default, messages shall not timeout. ]*/
+                                handleData->currentMessageTimeout = 0;
+                                result = handleData;
+                            }
+                        }
+                    }
+#ifdef USE_UPLOADTOBLOB
+                    free(IoTHubName);
                 }
             }
+#endif
         }
     }
 
@@ -491,7 +567,9 @@
         }
         /*Codes_SRS_IOTHUBCLIENT_LL_17_011: [IoTHubClient_LL_Destroy  shall free the resources allocated by IoTHubClient (if any).] */
         tickcounter_destroy(handleData->tickCounter);
+#ifdef USE_UPLOADTOBLOB
         IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle);
+#endif
         free(handleData);
     }
 }
@@ -829,6 +907,7 @@
     return result;
 }
 
+#ifdef USE_UPLOADTOBLOB
 IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName, const unsigned char* source, size_t size)
 {
     IOTHUB_CLIENT_RESULT result;
@@ -850,3 +929,4 @@
     }
     return result;
 }
+#endif