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:
45:54c11b1b1407
Parent:
44:33dd78697616
Child:
46:6a69294b6119
--- a/iothub_client_ll.c	Tue Jun 21 09:57:27 2016 -0700
+++ b/iothub_client_ll.c	Fri Jul 01 10:42:36 2016 -0700
@@ -9,7 +9,7 @@
 #include "azure_c_shared_utility/gballoc.h"
 #include "azure_c_shared_utility/string_tokenizer.h"
 #include "azure_c_shared_utility/doublylinkedlist.h"
-#include "azure_c_shared_utility/iot_logging.h"
+#include "azure_c_shared_utility/xlogging.h"
 #include "azure_c_shared_utility/tickcounter.h"
 
 #include "iothub_client_ll.h"
@@ -21,10 +21,11 @@
 #include "iothub_client_ll_uploadtoblob.h"
 #endif
 
-#define LOG_ERROR LogError("result = %s", ENUM_TO_STRING(IOTHUB_CLIENT_RESULT, result));
+#define LOG_ERROR_RESULT LogError("result = %s", ENUM_TO_STRING(IOTHUB_CLIENT_RESULT, result));
 #define INDEFINITE_TIME ((time_t)(-1))
 
 DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUES);
+DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_CONFIRMATION_RESULT, IOTHUB_CLIENT_CONFIRMATION_RESULT_VALUES);
 
 typedef struct IOTHUB_CLIENT_LL_HANDLE_DATA_TAG
 {
@@ -46,6 +47,8 @@
 
 static const char HOSTNAME_TOKEN[] = "HostName";
 static const char DEVICEID_TOKEN[] = "DeviceId";
+static const char X509_TOKEN[] = "x509";
+static const char X509_TOKEN_ONLY_ACCEPTABLE_VALUE[] = "true";
 static const char DEVICEKEY_TOKEN[] = "SharedAccessKey";
 static const char DEVICESAS_TOKEN[] = "SharedAccessSignature";
 static const char PROTOCOL_GATEWAY_HOST[] = "GatewayHostName";
@@ -126,9 +129,10 @@
                 LogError("Error creating HostSuffix String");
             }
             /* Codes_SRS_IOTHUBCLIENT_LL_12_005: [IoTHubClient_LL_CreateFromConnectionString shall try to parse the connectionString input parameter for the following structure: "Key1=value1;key2=value2;key3=value3..."] */
-            /* Codes_SRS_IOTHUBCLIENT_LL_12_006: [IoTHubClient_LL_CreateFromConnectionString shall verify the existence of the following Key/Value pairs in the connection string: HostName, DeviceId, SharedAccessKey or SharedAccessSignature.]  */
+            /* Codes_SRS_IOTHUBCLIENT_LL_12_006: [IoTHubClient_LL_CreateFromConnectionString shall verify the existence of the following Key/Value pairs in the connection string: HostName, DeviceId, SharedAccessKey, SharedAccessSignature or x509]  */
             else
             {
+                int isx509found = 0;
                 while ((STRING_TOKENIZER_get_next_token(tokenizer1, tokenString, "=") == 0))
                 {
                     if (STRING_TOKENIZER_get_next_token(tokenizer1, valueString, ";") != 0)
@@ -201,6 +205,17 @@
                                     config->deviceSasToken = STRING_c_str(deviceSasTokenString);
                                 }
                             }
+                            else if (strcmp(s_token, X509_TOKEN) == 0)
+                            {
+                                if (strcmp(STRING_c_str(valueString), X509_TOKEN_ONLY_ACCEPTABLE_VALUE) != 0)
+                                {
+                                    LogError("x509 option has wrong value, the only acceptable one is \"true\"");
+                                }
+                                else
+                                {
+                                    isx509found = 1;
+                                }
+                            }
                             /* Codes_SRS_IOTHUBCLIENT_LL_04_001: [IoTHubClient_LL_CreateFromConnectionString shall verify the existence of key/value pair GatewayHostName. If it does exist it shall pass the value to IoTHubClient_LL_Create API.] */
                             else if (strcmp(s_token, PROTOCOL_GATEWAY_HOST) == 0)
                             {
@@ -226,13 +241,12 @@
                 {
                     LogError("deviceId is not found");
                 }
-                else if (config->deviceKey == NULL && config->deviceSasToken == NULL)
+                else if (!(
+                    ((!isx509found) && (config->deviceSasToken == NULL) ^ (config->deviceKey == NULL)) ||
+                    ((isx509found) && (config->deviceSasToken == NULL) && (config->deviceKey == NULL))
+                    ))
                 {
-                    LogError("deviceKey/deviceSasToken not found");
-                }
-                else if (config->deviceKey != NULL && config->deviceSasToken != NULL)
-                {
-                    LogError("Both device Key & SAS token are defined. Only one should be provided.");
+                    LogError("invalid combination of x509, deviceSasToken and deviceKey");
                 }
                 else
                 {
@@ -408,7 +422,9 @@
     if (
         (config == NULL) ||
         (config->protocol == NULL) ||
-        (config->transportHandle == NULL)
+        (config->transportHandle == NULL) ||
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_098: [ IoTHubClient_LL_CreateWithTransport shall fail and return NULL if both config->deviceKey AND config->deviceSasToken are NULL. ]*/
+        ((config->deviceKey == NULL) && (config->deviceSasToken == NULL))
         )
     {
         result = NULL;
@@ -614,7 +630,7 @@
         )
     {
         result = IOTHUB_CLIENT_INVALID_ARG;
-        LOG_ERROR;
+        LOG_ERROR_RESULT;
     }
     else
     {
@@ -622,7 +638,7 @@
         if (newEntry == NULL)
         {
             result = IOTHUB_CLIENT_ERROR;
-            LOG_ERROR;
+            LOG_ERROR_RESULT;
         }
         else
         {
@@ -631,7 +647,7 @@
             if (attach_ms_timesOutAfter(handleData, newEntry) != 0)
             {
                 result = IOTHUB_CLIENT_ERROR;
-                LOG_ERROR;
+                LOG_ERROR_RESULT;
                 free(newEntry);
             }
             else
@@ -642,7 +658,7 @@
                     /*Codes_SRS_IOTHUBCLIENT_LL_02_014: [If cloning and/or adding the information fails for any reason, IoTHubClient_LL_SendEventAsync shall fail and return IOTHUB_CLIENT_ERROR.] */
                     result = IOTHUB_CLIENT_ERROR;
                     free(newEntry);
-                    LOG_ERROR;
+                    LOG_ERROR_RESULT;
                 }
                 else
                 {
@@ -667,7 +683,7 @@
     if (iotHubClientHandle == NULL)
     {
         result = IOTHUB_CLIENT_INVALID_ARG;
-        LOG_ERROR;
+        LOG_ERROR_RESULT;
     }
     else
     {
@@ -757,7 +773,7 @@
     if (iotHubClientHandle == NULL || iotHubClientStatus == NULL)
     {
         result = IOTHUB_CLIENT_INVALID_ARG;
-        LOG_ERROR;
+        LOG_ERROR_RESULT;
     }
     else
     {
@@ -771,7 +787,7 @@
     return result;
 }
 
-void IoTHubClient_LL_SendComplete(IOTHUB_CLIENT_LL_HANDLE handle, PDLIST_ENTRY completed, IOTHUB_BATCHSTATE_RESULT result)
+void IoTHubClient_LL_SendComplete(IOTHUB_CLIENT_LL_HANDLE handle, PDLIST_ENTRY completed, IOTHUB_CLIENT_CONFIRMATION_RESULT result)
 {
     /*Codes_SRS_IOTHUBCLIENT_LL_02_022: [If parameter completed is NULL, or parameter handle is NULL then IoTHubClient_LL_SendBatch shall return.]*/
     if (
@@ -784,9 +800,8 @@
     }
     else
     {
-        /*Codes_SRS_IOTHUBCLIENT_LL_02_027: [If parameter result is IOTHUB_BACTHSTATE_FAILED then IoTHubClient_LL_SendComplete shall call all the non-NULL callbacks with the result parameter set to IOTHUB_CLIENT_CONFIRMATION_ERROR and the context set to the context passed originally in the SendEventAsync call.] */
-        /*Codes_SRS_IOTHUBCLIENT_LL_02_025: [If parameter result is IOTHUB_BATCHSTATE_SUCCESS then IoTHubClient_LL_SendComplete shall call all the non-NULL callbacks with the result parameter set to IOTHUB_CLIENT_CONFIRMATION_OK and the context set to the context passed originally in the SendEventAsync call.]*/
-        IOTHUB_CLIENT_CONFIRMATION_RESULT resultToBeCalled = (result == IOTHUB_BATCHSTATE_SUCCESS) ? IOTHUB_CLIENT_CONFIRMATION_OK : IOTHUB_CLIENT_CONFIRMATION_ERROR;
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_027: [If parameter result is IOTHUB_CLIENT_CONFIRMATION_ERROR then IoTHubClient_LL_SendComplete shall call all the non-NULL callbacks with the result parameter set to IOTHUB_CLIENT_CONFIRMATION_ERROR and the context set to the context passed originally in the SendEventAsync call.] */
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_025: [If parameter result is IOTHUB_CLIENT_CONFIRMATION_OK then IoTHubClient_LL_SendComplete shall call all the non-NULL callbacks with the result parameter set to IOTHUB_CLIENT_CONFIRMATION_OK and the context set to the context passed originally in the SendEventAsync call.]*/
         PDLIST_ENTRY oldest;
         while ((oldest = DList_RemoveHeadList(completed)) != completed)
         {
@@ -794,7 +809,7 @@
             /*Codes_SRS_IOTHUBCLIENT_LL_02_026: [If any callback is NULL then there shall not be a callback call.]*/
             if (messageList->callback != NULL)
             {
-                messageList->callback(resultToBeCalled, messageList->context);
+                messageList->callback(result, messageList->context);
             }
             IoTHubMessage_Destroy(messageList->messageHandle);
             free(messageList);
@@ -843,7 +858,7 @@
     if (handleData == NULL || lastMessageReceiveTime == NULL)
     {
         result = IOTHUB_CLIENT_INVALID_ARG;
-        LOG_ERROR;
+        LOG_ERROR_RESULT;
     }
     else
     {
@@ -851,7 +866,7 @@
         if (handleData->lastMessageReceiveTime == INDEFINITE_TIME)
         {
             result = IOTHUB_CLIENT_INDEFINITE_TIME;
-            LOG_ERROR;
+            LOG_ERROR_RESULT;
         }
         else
         {