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:
61:8b85a4e797cf
Parent:
60:41648c4e7036
Child:
62:5a4cdacf5090
--- a/iothub_client_ll.c	Fri Feb 24 14:00:43 2017 -0800
+++ b/iothub_client_ll.c	Fri Mar 10 11:47:36 2017 -0800
@@ -12,9 +12,9 @@
 #include "azure_c_shared_utility/constbuffer.h"
 
 #include "iothub_client_ll.h"
+#include "iothub_transport_ll.h"
 #include "iothub_client_private.h"
 #include "iothub_client_version.h"
-#include "iothub_transport_ll.h"
 #include <stdint.h>
 
 #ifndef DONT_USE_UPLOADTOBLOB
@@ -27,6 +27,22 @@
 DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUES);
 DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_CONFIRMATION_RESULT, IOTHUB_CLIENT_CONFIRMATION_RESULT_VALUES);
 
+#define MESSAGE_CALLBACK_TYPE_VALUES \
+    MESSAGE_CALLBACK_TYPE_NONE,      \
+    MESSAGE_CALLBACK_TYPE_SYNC,    \
+    MESSAGE_CALLBACK_TYPE_ASYNC
+
+DEFINE_ENUM(MESSAGE_CALLBACK_TYPE, MESSAGE_CALLBACK_TYPE_VALUES)
+DEFINE_ENUM_STRINGS(MESSAGE_CALLBACK_TYPE, MESSAGE_CALLBACK_TYPE_VALUES)
+
+typedef struct IOTHUB_MESSAGE_CALLBACK_DATA_TAG
+{
+    MESSAGE_CALLBACK_TYPE messageCallbackType;
+    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC callbackSync;
+    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX callbackAsync;
+    void* messageUserContextCallback;
+}IOTHUB_MESSAGE_CALLBACK_DATA;
+
 typedef struct IOTHUB_CLIENT_LL_HANDLE_DATA_TAG
 {
     DLIST_ENTRY waitingToSend;
@@ -36,8 +52,7 @@
     bool isSharedTransport;
     IOTHUB_DEVICE_HANDLE deviceHandle;
     TRANSPORT_PROVIDER_FIELDS;
-    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback;
-    void* messageUserContextCallback;
+    IOTHUB_MESSAGE_CALLBACK_DATA messageCallback;
     IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK conStatusCallback;
     void* conStatusUserContextCallback;
     time_t lastMessageReceiveTime;
@@ -392,6 +407,7 @@
 
 static void setTransportProtocol(IOTHUB_CLIENT_LL_HANDLE_DATA* handleData, TRANSPORT_PROVIDER* protocol)
 {
+    handleData->IoTHubTransport_SendMessageDisposition = protocol->IoTHubTransport_SendMessageDisposition;
     handleData->IoTHubTransport_GetHostname = protocol->IoTHubTransport_GetHostname;
     handleData->IoTHubTransport_SetOption = protocol->IoTHubTransport_SetOption;
     handleData->IoTHubTransport_Create = protocol->IoTHubTransport_Create;
@@ -467,8 +483,10 @@
                     DList_InitializeListHead(&(handleData->iot_msg_queue));
                     DList_InitializeListHead(&(handleData->iot_ack_queue));
                     setTransportProtocol(handleData, (TRANSPORT_PROVIDER*)config->protocol());
-                    handleData->messageCallback = NULL;
-                    handleData->messageUserContextCallback = NULL;
+                    handleData->messageCallback.messageCallbackType = MESSAGE_CALLBACK_TYPE_NONE;
+                    handleData->messageCallback.callbackSync = NULL;
+                    handleData->messageCallback.callbackAsync = NULL;
+                    handleData->messageCallback.messageUserContextCallback = NULL;
                     handleData->deviceTwinCallback = NULL;
                     handleData->deviceTwinContextCallback = NULL;
                     handleData->deviceMethodCallback = NULL;
@@ -638,8 +656,10 @@
                             DList_InitializeListHead(&(handleData->waitingToSend));
                             DList_InitializeListHead(&(handleData->iot_msg_queue));
                             DList_InitializeListHead(&(handleData->iot_ack_queue));
-                            handleData->messageCallback = NULL;
-                            handleData->messageUserContextCallback = NULL;
+                            handleData->messageCallback.messageCallbackType = MESSAGE_CALLBACK_TYPE_NONE;
+                            handleData->messageCallback.callbackSync = NULL;
+                            handleData->messageCallback.callbackAsync = NULL;
+                            handleData->messageCallback.messageUserContextCallback = NULL;
                             handleData->deviceTwinCallback = NULL;
                             handleData->deviceTwinContextCallback = NULL;
                             handleData->deviceMethodCallback = NULL;
@@ -832,42 +852,158 @@
 IOTHUB_CLIENT_RESULT IoTHubClient_LL_SetMessageCallback(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback)
 {
     IOTHUB_CLIENT_RESULT result;
-    /*Codes_SRS_IOTHUBCLIENT_LL_02_016: [IoTHubClient_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.] */
     if (iotHubClientHandle == NULL)
     {
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_016: [IoTHubClient_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.] */
+        LogError("Invalid argument - iotHubClientHandle is NULL");
         result = IOTHUB_CLIENT_INVALID_ARG;
-        LOG_ERROR_RESULT;
     }
     else
     {
         IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle;
         if (messageCallback == NULL)
         {
-            /*Codes_SRS_IOTHUBCLIENT_LL_02_019: [If parameter messageCallback is NULL then IoTHubClient_LL_SetMessageCallback shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */
-            handleData->IoTHubTransport_Unsubscribe(handleData->deviceHandle);
-            handleData->messageCallback = NULL;
-            handleData->messageUserContextCallback = NULL;
-            result = IOTHUB_CLIENT_OK;
+            if (handleData->messageCallback.messageCallbackType == MESSAGE_CALLBACK_TYPE_NONE)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_010: [If parameter messageCallback is NULL and the _SetMessageCallback had not been called to subscribe for messages, then IoTHubClient_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("not currently set to accept or process incoming messages.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else if (handleData->messageCallback.messageCallbackType == MESSAGE_CALLBACK_TYPE_ASYNC)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_010: [If parameter messageCallback is NULL and the _SetMessageCallback had not been called to subscribe for messages, then IoTHubClient_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClient_LL_SetMessageCallbackEx function.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_019: [If parameter messageCallback is NULL then IoTHubClient_LL_SetMessageCallback shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */
+                handleData->IoTHubTransport_Unsubscribe(handleData->deviceHandle);
+                handleData->messageCallback.messageCallbackType = MESSAGE_CALLBACK_TYPE_NONE;
+                handleData->messageCallback.callbackSync = NULL;
+                handleData->messageCallback.callbackAsync = NULL;
+                handleData->messageCallback.messageUserContextCallback = NULL;
+                result = IOTHUB_CLIENT_OK;
+            }
         }
         else
         {
-            /*Codes_SRS_IOTHUBCLIENT_LL_02_017: [If parameter messageCallback is non-NULL then IoTHubClient_LL_SetMessageCallback shall call the underlying layer's _Subscribe function.]*/
-            if (handleData->IoTHubTransport_Subscribe(handleData->deviceHandle) == 0)
+            if (handleData->messageCallback.messageCallbackType == MESSAGE_CALLBACK_TYPE_ASYNC)
             {
-                handleData->messageCallback = messageCallback;
-                handleData->messageUserContextCallback = userContextCallback;
-                result = IOTHUB_CLIENT_OK;
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_011: [If parameter messageCallback is non-NULL and the _SetMessageCallbackEx had been used to susbscribe for messages, then IoTHubClient_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClient_LL_SetMessageCallbackEx function before subscribing with MessageCallback.");
+                result = IOTHUB_CLIENT_ERROR;
             }
             else
             {
-                handleData->messageCallback = NULL;
-                handleData->messageUserContextCallback = NULL;
-                /*Codes_SRS_IOTHUBCLIENT_LL_02_018: [If the underlying layer's _Subscribe function fails, then IoTHubClient_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR. Otherwise IoTHubClient_LL_SetMessageCallback shall succeed and return IOTHUB_CLIENT_OK.]*/
-                result = IOTHUB_CLIENT_ERROR;
+                if (handleData->IoTHubTransport_Subscribe(handleData->deviceHandle) == 0)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_017: [If parameter messageCallback is non-NULL then IoTHubClient_LL_SetMessageCallback shall call the underlying layer's _Subscribe function.]*/
+                    handleData->messageCallback.messageCallbackType = MESSAGE_CALLBACK_TYPE_SYNC;
+                    handleData->messageCallback.callbackSync = messageCallback;
+                    handleData->messageCallback.messageUserContextCallback = userContextCallback;
+                    result = IOTHUB_CLIENT_OK;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_02_018: [If the underlying layer's _Subscribe function fails, then IoTHubClient_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR. Otherwise IoTHubClient_LL_SetMessageCallback shall succeed and return IOTHUB_CLIENT_OK.]*/
+                    handleData->messageCallback.messageCallbackType = MESSAGE_CALLBACK_TYPE_NONE;
+                    handleData->messageCallback.callbackSync = NULL;
+                    handleData->messageCallback.callbackAsync = NULL;
+                    handleData->messageCallback.messageUserContextCallback = NULL;
+                    result = IOTHUB_CLIENT_ERROR;
+                }
             }
         }
     }
+    return result;
+}
 
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_SetMessageCallbackEx(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC_EX messageCallback, void* userContextCallback)
+{
+    IOTHUB_CLIENT_RESULT result;
+    if (iotHubClientHandle == NULL)
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_10_021: [IoTHubClient_LL_SetMessageCallbackEx shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.]*/
+        LogError("Invalid argument - iotHubClientHandle is NULL");
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle;
+        if (messageCallback == NULL)
+        {
+            if (handleData->messageCallback.messageCallbackType == MESSAGE_CALLBACK_TYPE_NONE)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_018: [If parameter messageCallback is NULL and IoTHubClient_LL_SetMessageCallbackEx had not been used to subscribe for messages, then IoTHubClient_LL_SetMessageCallbackEx shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("not currently set to accept or process incoming messages.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else if (handleData->messageCallback.messageCallbackType == MESSAGE_CALLBACK_TYPE_SYNC)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_019: [If parameter messageCallback is NULL and IoTHubClient_LL_SetMessageCallback had been used to subscribe for messages, then IoTHubClient_LL_SetMessageCallbackEx shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClient_LL_SetMessageCallback function.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_023: [If parameter messageCallback is NULL then IoTHubClient_LL_SetMessageCallbackEx shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */ 
+                handleData->IoTHubTransport_Unsubscribe(handleData->deviceHandle);
+                handleData->messageCallback.messageCallbackType = MESSAGE_CALLBACK_TYPE_NONE;
+                handleData->messageCallback.callbackSync = NULL;
+                handleData->messageCallback.callbackAsync = NULL;
+                handleData->messageCallback.messageUserContextCallback = NULL;
+                result = IOTHUB_CLIENT_OK;
+            }
+        }
+        else
+        {
+            if (handleData->messageCallback.messageCallbackType == MESSAGE_CALLBACK_TYPE_SYNC)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_020: [If parameter messageCallback is non-NULL, and IoTHubClient_LL_SetMessageCallback had been used to subscribe for messages, then IoTHubClient_LL_SetMessageCallbackEx shall fail and return IOTHUB_CLIENT_ERROR.] */
+                LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClient_LL_MessageCallbackEx function before subscribing with MessageCallback.");
+                result = IOTHUB_CLIENT_ERROR;
+            }
+            else
+            {
+                if (handleData->IoTHubTransport_Subscribe(handleData->deviceHandle) == 0)
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_10_024: [If parameter messageCallback is non-NULL then IoTHubClient_LL_SetMessageCallbackEx shall call the underlying layer's _Subscribe function.]*/
+                    handleData->messageCallback.messageCallbackType = MESSAGE_CALLBACK_TYPE_ASYNC;
+                    handleData->messageCallback.callbackAsync = messageCallback;
+                    handleData->messageCallback.messageUserContextCallback = userContextCallback;
+                    result = IOTHUB_CLIENT_OK;
+                }
+                else
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_10_025: [If the underlying layer's _Subscribe function fails, then IoTHubClient_LL_SetMessageCallbackEx shall fail and return IOTHUB_CLIENT_ERROR. Otherwise IoTHubClient_LL_SetMessageCallbackEx shall succeed and return IOTHUB_CLIENT_OK.] */
+                    handleData->messageCallback.messageCallbackType = MESSAGE_CALLBACK_TYPE_NONE;
+                    handleData->messageCallback.callbackSync = NULL;
+                    handleData->messageCallback.callbackAsync = NULL;
+                    handleData->messageCallback.messageUserContextCallback = NULL;
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+            }
+        }
+    }
+    return result;
+}
+
+IOTHUB_CLIENT_RESULT IoTHubClient_LL_SendMessageDisposition(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, MESSAGE_CALLBACK_INFO* message_data, IOTHUBMESSAGE_DISPOSITION_RESULT disposition)
+{
+    IOTHUB_CLIENT_RESULT result;
+    if ((iotHubClientHandle == NULL) || (message_data == NULL))
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_10_026: [IoTHubClient_LL_SendMessageDisposition shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.]*/
+        LogError("Invalid argument handle=%p, message=%p", iotHubClientHandle, message_data);
+        result = IOTHUB_CLIENT_INVALID_ARG;
+    }
+    else
+    {
+        IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle;
+        /*Codes_SRS_IOTHUBCLIENT_LL_10_027: [IoTHubClient_LL_SendMessageDisposition shall return the result from calling the underlying layer's _Send_Message_Disposition.]*/
+        result = handleData->IoTHubTransport_SendMessageDisposition(message_data, disposition);
+    }
     return result;
 }
 
@@ -1110,14 +1246,20 @@
     }
 }
 
-IOTHUBMESSAGE_DISPOSITION_RESULT IoTHubClient_LL_MessageCallback(IOTHUB_CLIENT_LL_HANDLE handle, IOTHUB_MESSAGE_HANDLE message)
+bool IoTHubClient_LL_MessageCallback(IOTHUB_CLIENT_LL_HANDLE handle, MESSAGE_CALLBACK_INFO* messageData)
 {
-    int result;
-    /*Codes_SRS_IOTHUBCLIENT_LL_02_029: [If parameter handle is NULL then IoTHubClient_LL_MessageCallback shall return IOTHUBMESSAGE_ABANDONED.] */
-    if (handle == NULL)
+    bool result;
+    if ((handle == NULL) || messageData == NULL)
     {
-        LogError("invalid argument");
-        result = IOTHUBMESSAGE_ABANDONED;
+        /*Codes_SRS_IOTHUBCLIENT_LL_02_029: [If parameter handle is NULL then IoTHubClient_LL_MessageCallback shall return IOTHUBMESSAGE_ABANDONED.] */
+        LogError("invalid argument: handle(%p), messageData(%p)", handle, messageData);
+        result = false;
+    }
+    else if (messageData->messageHandle == NULL)
+    {
+        /*Codes_SRS_IOTHUBCLIENT_LL_10_004: [If messageHandle field of paramger messageData is NULL then IoTHubClient_LL_MessageCallback shall return IOTHUBMESSAGE_ABANDONED.] */
+        LogError("invalid argument messageData->messageHandle(NULL)");
+        result = false;
     }
     else
     {
@@ -1125,26 +1267,52 @@
 
         /* Codes_SRS_IOTHUBCLIENT_LL_09_004: [IoTHubClient_LL_GetLastMessageReceiveTime shall return lastMessageReceiveTime in localtime] */
         handleData->lastMessageReceiveTime = get_time(NULL);
-
-        /*Codes_SRS_IOTHUBCLIENT_LL_02_030: [IoTHubClient_LL_MessageCallback shall invoke the last callback function (the parameter messageCallback to IoTHubClient_LL_SetMessageCallback) passing the message and the passed userContextCallback.]*/
-        if (handleData->messageCallback != NULL)
+        switch (handleData->messageCallback.messageCallbackType)
         {
-            result = handleData->messageCallback(message, handleData->messageUserContextCallback);
-        }
-        else
-        {
-            /*Codes_SRS_IOTHUBCLIENT_LL_02_032: [If the last callback function was NULL, then IoTHubClient_LL_MessageCallback  shall return IOTHUBMESSAGE_ABANDONED.] */
-            LogError("user callback was NULL");
-            result = IOTHUBMESSAGE_ABANDONED;
+            case MESSAGE_CALLBACK_TYPE_NONE:
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_032: [If the client is not subscribed to receive messages then IoTHubClient_LL_MessageCallback shall return false.] */
+                LogError("Invalid workflow - not currently set up to accept messages");
+                result = false;
+                break;
+            }
+            case MESSAGE_CALLBACK_TYPE_SYNC:
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_02_030: [If messageCallbackType is LEGACY then IoTHubClient_LL_MessageCallback shall invoke the last callback function (the parameter messageCallback to IoTHubClient_LL_SetMessageCallback) passing the message and the passed userContextCallback.]*/
+                IOTHUBMESSAGE_DISPOSITION_RESULT cb_result = handleData->messageCallback.callbackSync(messageData->messageHandle, handleData->messageCallback.messageUserContextCallback);
+
+                /*Codes_SRS_IOTHUBCLIENT_LL_10_007: [If messageCallbackType is LEGACY then IoTHubClient_LL_MessageCallback shall send the message disposition as returned by the client to the underlying layer.] */
+                if (handleData->IoTHubTransport_SendMessageDisposition(messageData, cb_result) != IOTHUB_CLIENT_OK)
+                {
+                    LogError("IoTHubTransport_SendMessageDisposition failed");
+                }
+                result = true;
+                break;
+            }
+            case MESSAGE_CALLBACK_TYPE_ASYNC:
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_10_009: [If messageCallbackType is ASYNC then IoTHubClient_LL_MessageCallback shall return what messageCallbacEx returns.] */
+                result = handleData->messageCallback.callbackAsync(messageData, handleData->messageCallback.messageUserContextCallback);
+                if (!result)
+                {
+                    LogError("messageCallbackEx failed");
+                }
+                break;
+            }
+            default:
+            {
+                LogError("Invalid state");
+                result = false;
+                break;
+            }
         }
     }
-    /*Codes_SRS_IOTHUBCLIENT_LL_02_031: [Then IoTHubClient_LL_MessageCallback shall return what the user function returns.]*/
-    return (IOTHUBMESSAGE_DISPOSITION_RESULT) result;
+    return result;
 }
 
-void IotHubClient_LL_ConnectionStatusCallBack(IOTHUB_CLIENT_LL_HANDLE handle, IOTHUB_CLIENT_CONNECTION_STATUS status, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason)
+void IoTHubClient_LL_ConnectionStatusCallBack(IOTHUB_CLIENT_LL_HANDLE handle, IOTHUB_CLIENT_CONNECTION_STATUS status, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason)
 {
-    /*Codes_SRS_IOTHUBCLIENT_LL_25_113: [If parameter connectionStatus is NULL or parameter handle is NULL then IotHubClient_LL_ConnectionStatusCallBack shall return.]*/
+    /*Codes_SRS_IOTHUBCLIENT_LL_25_113: [If parameter connectionStatus is NULL or parameter handle is NULL then IoTHubClient_LL_ConnectionStatusCallBack shall return.]*/
     if (handle == NULL)
     {
         /*"shall return"*/
@@ -1154,7 +1322,7 @@
     {
         IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)handle;
 
-        /*Codes_SRS_IOTHUBCLIENT_LL_25_114: [IotHubClient_LL_ConnectionStatusCallBack shall call non-callback set by the user from IoTHubClient_LL_SetConnectionStatusCallback passing the status, reason and the passed userContextCallback.]*/
+        /*Codes_SRS_IOTHUBCLIENT_LL_25_114: [IoTHubClient_LL_ConnectionStatusCallBack shall call non-callback set by the user from IoTHubClient_LL_SetConnectionStatusCallback passing the status, reason and the passed userContextCallback.]*/
         if (handleData->conStatusCallback != NULL)
         {
             handleData->conStatusCallback(status, reason, handleData->conStatusUserContextCallback);