Microsoft Azure IoTHub client HTTP transport

Dependents:   iothub_client_sample_http simplesample_http temp_sensor_anomaly

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

Revision:
3:4e9296134ffb
Parent:
2:ff9104b866b8
Child:
4:ce756a949fbd
--- a/iothubtransporthttp.c	Wed Sep 16 22:42:49 2015 -0700
+++ b/iothubtransporthttp.c	Tue Sep 22 20:36:43 2015 -0700
@@ -28,11 +28,13 @@
 #define APPLICATION_OCTET_STREAM "application/octet-stream"
 #define APPLICATION_VND_MICROSOFT_IOTHUB_JSON "application/vnd.microsoft.iothub.json"
 
-/*DEFAULT_GETMINIMUMPOLLINGTIME is the minimum time in seconds allowed between 2 consecutive GET issues to the service (GET=fetch notifications)*/
+/*DEFAULT_GETMINIMUMPOLLINGTIME is the minimum time in seconds allowed between 2 consecutive GET issues to the service (GET=fetch messages)*/
 /*the default is 25 minutes*/
 #define DEFAULT_GETMINIMUMPOLLINGTIME ((unsigned int)25*60) 
 
 #define MAXIMUM_MESSAGE_SIZE (255*1024-1)
+#define MAXIMUM_PAYLOAD_OVERHEAD 384
+#define MAXIMUM_PROPERTY_OVERHEAD 16
 
 /*forward declaration*/
 static int appendMapToJSON(STRING_HANDLE existing, const char* const* keys, const char* const* values, size_t count);
@@ -49,7 +51,7 @@
     IoTHubTransportHttp_GetSendStatus /* pfIoTHubTransport_GetSendStatus IoTHubTransport_GetSendStatus */
 };
 
-const void* IoTHubTransportHttp_ProvideTransportInterface(void)
+const void* HTTP_Protocol(void)
 {
     return &thisTransportProvider;
 }
@@ -57,14 +59,14 @@
 typedef struct HTTPTRANSPORT_HANDLE_DATA_TAG
 {
     STRING_HANDLE eventHTTPrelativePath;
-    STRING_HANDLE notificationHTTPrelativePath;
+    STRING_HANDLE messageHTTPrelativePath;
     HTTP_HEADERS_HANDLE eventHTTPrequestHeaders;
     STRING_HANDLE hostName;
     HTTPAPIEX_HANDLE httpApiExHandle;
-    HTTP_HEADERS_HANDLE notificationHTTPrequestHeaders;
+    HTTP_HEADERS_HANDLE messageHTTPrequestHeaders;
     STRING_HANDLE abandonHTTPrelativePathBegin;
     HTTPAPIEX_SAS_HANDLE sasObject;
-    bool DoWork_PullNotification;
+    bool DoWork_PullMessage;
     bool doBatchedTransfers;
     bool isFirstPoll;
     unsigned int getMinimumPollingTime;
@@ -108,19 +110,19 @@
     return result;
 }
 
-/*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_034: [Otherwise, IoTHubTransportHttp_Create shall create an immutable string (further called "notification HTTP relative path") from the following pieces: "/devices/" + URL_ENCODED(config->upperConfig->deviceId) + "/messages/devicebound?api-version=2015-08-15-preview".]*/
-static void destroy_notificationHTTPrelativePath(HTTPTRANSPORT_HANDLE_DATA* handleData)
+/*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_034: [Otherwise, IoTHubTransportHttp_Create shall create an immutable string (further called "message HTTP relative path") from the following pieces: "/devices/" + URL_ENCODED(config->upperConfig->deviceId) + "/messages/devicebound?api-version=2015-08-15-preview".]*/
+static void destroy_messageHTTPrelativePath(HTTPTRANSPORT_HANDLE_DATA* handleData)
 {
-    STRING_delete(handleData->notificationHTTPrelativePath);
-    handleData->notificationHTTPrelativePath = NULL;
+    STRING_delete(handleData->messageHTTPrelativePath);
+    handleData->messageHTTPrelativePath = NULL;
 }
 
-/*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_034: [Otherwise, IoTHubTransportHttp_Create shall create an immutable string (further called "notification HTTP relative path") from the following pieces: "/devices/" + URL_ENCODED(config->upperConfig->deviceId) + "/messages/devicebound?api-version=2015-08-15-preview".]*/
-static bool create_notificationHTTPrelativePath(HTTPTRANSPORT_HANDLE_DATA* handleData, const IOTHUBTRANSPORT_CONFIG* config)
+/*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_034: [Otherwise, IoTHubTransportHttp_Create shall create an immutable string (further called "message HTTP relative path") from the following pieces: "/devices/" + URL_ENCODED(config->upperConfig->deviceId) + "/messages/devicebound?api-version=2015-08-15-preview".]*/
+static bool create_messageHTTPrelativePath(HTTPTRANSPORT_HANDLE_DATA* handleData, const IOTHUBTRANSPORT_CONFIG* config)
 {
     bool result;
-    handleData->notificationHTTPrelativePath = STRING_construct("/devices/");
-    if (handleData->notificationHTTPrelativePath == NULL)
+    handleData->messageHTTPrelativePath = STRING_construct("/devices/");
+    if (handleData->messageHTTPrelativePath == NULL)
     {
         result = false;
     }
@@ -129,12 +131,12 @@
         STRING_HANDLE urlEncodedDeviceId = NULL;
         if (!(
             ((urlEncodedDeviceId = URL_EncodeString(config->upperConfig->deviceId)) != NULL) &&
-            (STRING_concat_with_STRING(handleData->notificationHTTPrelativePath, urlEncodedDeviceId) == 0) &&
-            (STRING_concat(handleData->notificationHTTPrelativePath, NOTIFICATION_ENDPOINT_HTTP API_VERSION) == 0)
+            (STRING_concat_with_STRING(handleData->messageHTTPrelativePath, urlEncodedDeviceId) == 0) &&
+            (STRING_concat(handleData->messageHTTPrelativePath, MESSAGE_ENDPOINT_HTTP API_VERSION) == 0)
             ))
         {
             result = false;
-            destroy_notificationHTTPrelativePath(handleData);
+            destroy_messageHTTPrelativePath(handleData);
         }
         else
         {
@@ -272,30 +274,30 @@
     return result;
 }
 
-/*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_059: [Otherwise, IoTHubTransportHttp_Create shall create a set of HTTP headers (further on called "notification HTTP request headers") consisting of the following fixed field names and values:
+/*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_059: [Otherwise, IoTHubTransportHttp_Create shall create a set of HTTP headers (further on called "message HTTP request headers") consisting of the following fixed field names and values:
 "Authorization": " "]*/
-static void destroy_notificationHTTPrequestHeaders(HTTPTRANSPORT_HANDLE_DATA* handleData)
+static void destroy_messageHTTPrequestHeaders(HTTPTRANSPORT_HANDLE_DATA* handleData)
 {
-    HTTPHeaders_Free(handleData->notificationHTTPrequestHeaders);
-    handleData->notificationHTTPrequestHeaders = NULL;
+    HTTPHeaders_Free(handleData->messageHTTPrequestHeaders);
+    handleData->messageHTTPrequestHeaders = NULL;
 }
 
-/*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_059: [Otherwise, IoTHubTransportHttp_Create shall create a set of HTTP headers (further on called "notification HTTP request headers") consisting of the following fixed field names and values:
+/*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_059: [Otherwise, IoTHubTransportHttp_Create shall create a set of HTTP headers (further on called "message HTTP request headers") consisting of the following fixed field names and values:
 "Authorization": " "]*/
-static bool create_notificationHTTPrequestHeaders(HTTPTRANSPORT_HANDLE_DATA* handleData, const IOTHUBTRANSPORT_CONFIG* config)
+static bool create_messageHTTPrequestHeaders(HTTPTRANSPORT_HANDLE_DATA* handleData, const IOTHUBTRANSPORT_CONFIG* config)
 {
     bool result;
     (void)config;
-    handleData->notificationHTTPrequestHeaders = HTTPHeaders_Alloc();
-    if (handleData->notificationHTTPrequestHeaders == NULL)
+    handleData->messageHTTPrequestHeaders = HTTPHeaders_Alloc();
+    if (handleData->messageHTTPrequestHeaders == NULL)
     {
         result = false;
     }
     else
     {
-        if (HTTPHeaders_AddHeaderNameValuePair(handleData->notificationHTTPrequestHeaders, "Authorization", " ") != HTTP_HEADERS_OK)
+        if (HTTPHeaders_AddHeaderNameValuePair(handleData->messageHTTPrequestHeaders, "Authorization", " ") != HTTP_HEADERS_OK)
         {
-            destroy_notificationHTTPrequestHeaders(handleData);
+            destroy_messageHTTPrequestHeaders(handleData);
             result = false;
         }
         else
@@ -328,7 +330,7 @@
         if (!(
             ((urlEncodedDeviceId = URL_EncodeString(config->upperConfig->deviceId)) != NULL) &&
             (STRING_concat_with_STRING(handleData->abandonHTTPrelativePathBegin, urlEncodedDeviceId) == 0) &&
-            (STRING_concat(handleData->abandonHTTPrelativePathBegin, NOTIFICATION_ENDPOINT_HTTP_ETAG) == 0)
+            (STRING_concat(handleData->abandonHTTPrelativePathBegin, MESSAGE_ENDPOINT_HTTP_ETAG) == 0)
             ))
         {
             LogError("unable to STRING_concat\r\n");
@@ -472,18 +474,18 @@
         else
         {
             bool was_eventHTTPrelativePath_ok = create_eventHTTPrelativePath(result, config);
-            bool was_notificationHTTPrelativePath_ok = was_eventHTTPrelativePath_ok && create_notificationHTTPrelativePath(result, config);
-            bool was_eventHTTPrequestHeaders_ok = was_notificationHTTPrelativePath_ok && create_eventHTTPrequestHeaders(result, config);
+            bool was_messageHTTPrelativePath_ok = was_eventHTTPrelativePath_ok && create_messageHTTPrelativePath(result, config);
+            bool was_eventHTTPrequestHeaders_ok = was_messageHTTPrelativePath_ok && create_eventHTTPrequestHeaders(result, config);
             bool was_hostName_ok = was_eventHTTPrequestHeaders_ok && create_hostName(result, config);
             bool was_httpApiExHandle_ok = was_hostName_ok && create_httpApiExHandle(result, config);
-            bool was_notificationHTTPrequestHeaders_ok = was_httpApiExHandle_ok && create_notificationHTTPrequestHeaders(result, config);
-            bool was_abandonHTTPrelativePathBegin_ok = was_notificationHTTPrequestHeaders_ok && create_abandonHTTPrelativePathBegin(result, config);
+            bool was_messageHTTPrequestHeaders_ok = was_httpApiExHandle_ok && create_messageHTTPrequestHeaders(result, config);
+            bool was_abandonHTTPrelativePathBegin_ok = was_messageHTTPrequestHeaders_ok && create_abandonHTTPrelativePathBegin(result, config);
             bool was_sasObject_ok = was_abandonHTTPrelativePathBegin_ok && create_deviceSASObject(result, config);
 
-            /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_011: [Otherwise, IoTHubTransportHttp_Create shall set a flag called "DoWork_PullNotification" to false, succeed and return a non-NULL value.]*/
+            /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_011: [Otherwise, IoTHubTransportHttp_Create shall set a flag called "DoWork_PullMessage" to false, succeed and return a non-NULL value.]*/
             if (was_sasObject_ok)
             {
-                result->DoWork_PullNotification = false;
+                result->DoWork_PullMessage = false;
                 result->doBatchedTransfers = false;
                 result->isFirstPoll = true;
                 result->getMinimumPollingTime = DEFAULT_GETMINIMUMPOLLINGTIME;
@@ -494,16 +496,16 @@
             {
                 /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_004: [If creating the string fail for any reason then IoTHubTransportHttp_Create shall fail and return NULL.] */
                 if (was_eventHTTPrelativePath_ok) destroy_eventHTTPrelativePath(result);
-                /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_035: [If creating the notification HTTP relative path fails, then IoTHubTransportHttp_Create shall fail and return NULL.] */
-                if (was_notificationHTTPrelativePath_ok) destroy_notificationHTTPrelativePath(result);
+                /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_035: [If creating the message HTTP relative path fails, then IoTHubTransportHttp_Create shall fail and return NULL.] */
+                if (was_messageHTTPrelativePath_ok) destroy_messageHTTPrelativePath(result);
                 /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_006: [If creating the event HTTP request headers fails, then IoTHubTransportHttp_Create shall fail and return NULL.] */
                 if (was_eventHTTPrequestHeaders_ok) destroy_eventHTTPrequestHeaders(result);
                 /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_008: [If creating the hostname fails then IoTHubTransportHttp_Create shall fail and return NULL.] */
                 if (was_hostName_ok) destroy_hostName(result);
                 /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_010: [If creating the HTTPAPIEX_HANDLE fails then IoTHubTransportHttp_Create shall fail and return NULL.] */
                 if (was_httpApiExHandle_ok) destroy_httpApiExHandle(result);
-                /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_060: [If creating notification HTTP request headers then IoTHubTransportHttp_Create shall fail and return NULL.]*/
-                if (was_notificationHTTPrequestHeaders_ok) destroy_notificationHTTPrequestHeaders(result);
+                /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_060: [If creating message HTTP request headers then IoTHubTransportHttp_Create shall fail and return NULL.]*/
+                if (was_messageHTTPrequestHeaders_ok) destroy_messageHTTPrequestHeaders(result);
                 /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_062: [If creating the abandonHTTPrelativePathBegin fails then IoTHubTransportHttp_Create shall fail and return NULL] */
                 if (was_abandonHTTPrelativePathBegin_ok) destroy_abandonHTTPrelativePathBegin(result);
 
@@ -522,11 +524,11 @@
     {
         /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_013: [Otherwise IoTHubTransportHttp_Destroy shall free all the resources currently in use.] */
         destroy_eventHTTPrelativePath(handle);
-        destroy_notificationHTTPrelativePath(handle);
+        destroy_messageHTTPrelativePath(handle);
         destroy_eventHTTPrequestHeaders(handle);
         destroy_hostName(handle);
         destroy_httpApiExHandle(handle);
-        destroy_notificationHTTPrequestHeaders(handle);
+        destroy_messageHTTPrequestHeaders(handle);
         destroy_abandonHTTPrelativePathBegin(handle);
         destroy_SASObject(handle);
         free(handle);
@@ -544,9 +546,9 @@
     }
     else
     {
-        /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_056: [Otherwise, IoTHubTransportHttp_Subscribe shall set the flag called DoWork_PullNotifications to true and succeed.] */
+        /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_056: [Otherwise, IoTHubTransportHttp_Subscribe shall set the flag called DoWork_PullMessages to true and succeed.] */
         HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
-        handleData->DoWork_PullNotification = true;
+        handleData->DoWork_PullMessage = true;
         result = 0;
     }
     return result;
@@ -558,14 +560,14 @@
     if (handle != NULL)
     {
         HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
-        /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_058: [Otherwise it shall set the flag DoWork_PullNotification to false.] */
-        handleData->DoWork_PullNotification = false;
+        /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_058: [Otherwise it shall set the flag DoWork_PullMessage to false.] */
+        handleData->DoWork_PullMessage = false;
     }
 }
 
 /*produces a representation of the properties, if they exist*/
 /*if they do not exist, produces ""*/
-static int concat_Properties(STRING_HANDLE existing, MAP_HANDLE map)
+static int concat_Properties(STRING_HANDLE existing, MAP_HANDLE map, size_t* propertiesMessageSizeContribution)
 {
     int result;
     const char*const* keys;
@@ -584,6 +586,7 @@
             /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_076: [If IoTHubMessage does not have properties, then "properties":{...} shall be missing from the payload*/
             /*no properties - do nothing with existing*/
             result = 0;
+            *propertiesMessageSizeContribution = 0;
         }
         else
         {
@@ -602,6 +605,13 @@
             else
             {
                 /*all is fine*/
+                size_t i;
+                *propertiesMessageSizeContribution = 0;
+                for (i = 0;i < count;i++)
+                {
+                    /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_120: [Every property name shall add to the message size the length of the property name + the length of the property value + 16 bytes.] */
+                    *propertiesMessageSizeContribution += (strlen(keys[i]) + strlen(values[i]) + MAXIMUM_PROPERTY_OVERHEAD);
+                }
                 result = 0;
             }
         }
@@ -658,11 +668,12 @@
 
 /*makes the following string:{"body":"base64 encoding of the message content"[,"properties":{"a":"valueOfA"}]}*/
 /*return NULL if there was a failure, or a non-NULL STRING_HANDLE that contains the intended data*/
-static STRING_HANDLE make1EventJSONitem(PDLIST_ENTRY item)
+static STRING_HANDLE make1EventJSONitem(PDLIST_ENTRY item, size_t *messageSizeContribution)
 {
     STRING_HANDLE result; /*temp wants to contain :{"body":"base64 encoding of the message content"[,"properties":{"a":"valueOfA"}]}*/
     IOTHUB_MESSAGE_LIST* message = containingRecord(item, IOTHUB_MESSAGE_LIST, entry);
     IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(message->messageHandle);
+    
     switch (contentType)
     {
     case IOTHUBMESSAGE_BYTEARRAY:
@@ -694,10 +705,11 @@
                 }
                 else
                 {
+                    size_t propertiesSize;
                     if (!(
                         (STRING_concat_with_STRING(result, encoded) == 0) &&
                         (STRING_concat(result, "\"") == 0) && /*\" because closing value*/
-                        (concat_Properties(result, IoTHubMessage_Properties(message->messageHandle)) == 0) &&
+                        (concat_Properties(result, IoTHubMessage_Properties(message->messageHandle), &propertiesSize) == 0) &&
                         (STRING_concat(result, "},") == 0) /*the last comma shall be replaced by a ']' by DaCr's suggestion (which is awesome enough to receive credits in the source code)*/
                         ))
                     {
@@ -708,6 +720,8 @@
                     else
                     {
                         /*all is fine... */
+                        /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_119: [The message size is computed from the length of the payload + 384.] */
+                        *messageSizeContribution = size + MAXIMUM_PAYLOAD_OVERHEAD + propertiesSize;
                     }
                     STRING_delete(encoded);
                 }
@@ -743,10 +757,11 @@
                 }
                 else
                 {
+                    size_t propertiesSize;
                     if (!(
                         (STRING_concat_with_STRING(result, asJson) == 0) &&
                         (STRING_concat(result, ",\"base64Encoded\":false") == 0) &&
-                        (concat_Properties(result, IoTHubMessage_Properties(message->messageHandle)) == 0) &&
+                        (concat_Properties(result, IoTHubMessage_Properties(message->messageHandle), &propertiesSize) == 0) &&
                         (STRING_concat(result, "},") == 0) /*the last comma shall be replaced by a ']' by DaCr's suggestion (which is awesome enough to receive credits in the source code)*/
                         ))
                     {
@@ -757,6 +772,8 @@
                     else
                     {
                         /*result has the intended content*/
+                        /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_119: [The message size is computed from the length of the payload + 384.] */
+                        *messageSizeContribution = strlen(source) + MAXIMUM_PAYLOAD_OVERHEAD + propertiesSize;
                     }
                     STRING_delete(asJson);
                 }
@@ -787,7 +804,7 @@
 static MAKE_PAYLOAD_RESULT makePayload(HTTPTRANSPORT_HANDLE_DATA* handleData, STRING_HANDLE* payload)
 {
     MAKE_PAYLOAD_RESULT result;
-    
+    size_t allMessagesSize = 0;
     *payload = STRING_construct("[");
     if (*payload == NULL)
     {
@@ -803,7 +820,8 @@
         bool keepGoing = true; /*keepGoing gets sometimes to false from within the loop*/
         while (keepGoing && ((actual = handleData->waitingToSend->Flink) != handleData->waitingToSend))
         {
-            STRING_HANDLE temp = make1EventJSONitem(actual);
+            size_t messageSize;
+            STRING_HANDLE temp = make1EventJSONitem(actual, &messageSize);
             if (isFirst)
             {
                 isFirst = false;
@@ -818,7 +836,8 @@
                 else
                 {
                     /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_071: [If the oldest message in waitingToSend causes the message size to exceed the message size limit then it shall be removed from waitingToSend, and IoTHubClient_LL_SendComplete shall be called. Parameter PDLIST_ENTRY completed shall point to a list containing only the oldest item, and parameter IOTHUB_BATCHSTATE result shall be set to IOTHUB_BATCHSTATE_FAILED.]*/
-                    if (STRING_length(temp) >= MAXIMUM_MESSAGE_SIZE)
+                    /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_118: [The message size shall be limited to 255KB - 1 byte.]*/
+                    if (messageSize > MAXIMUM_MESSAGE_SIZE)
                     {
                         PDLIST_ENTRY head = DList_RemoveHeadList(handleData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
                         DList_InsertTailList(&(handleData->eventConfirmations), head);
@@ -842,6 +861,7 @@
                             /*first item was put nicely in the payload*/
                             PDLIST_ENTRY head = DList_RemoveHeadList(handleData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
                             DList_InsertTailList(&(handleData->eventConfirmations), head);
+                            allMessagesSize += messageSize;
                         }
                     }
                     STRING_delete(temp);
@@ -859,7 +879,7 @@
                 }
                 else
                 {
-                    if (STRING_length(*payload) + STRING_length(temp) > MAXIMUM_MESSAGE_SIZE)
+                    if (allMessagesSize + messageSize > MAXIMUM_MESSAGE_SIZE)
                     {
                         /*this item doesn't make it to the payload, but the payload is valid so far*/
                         /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_072: [If at any point during construction of the string there are errors, IoTHubTransportHttp_DoWork shall use the so far constructed string as payload.]*/
@@ -878,6 +898,7 @@
                         /*cool, the payload made it there, let's continue... */
                         PDLIST_ENTRY head = DList_RemoveHeadList(handleData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
                         DList_InsertTailList(&(handleData->eventConfirmations), head);
+                        allMessagesSize += messageSize;
                     }
                     STRING_delete(temp);
                 }
@@ -1017,16 +1038,22 @@
         }
         else
         {
-            const unsigned char* messageContent;
-            size_t messageSize;
+            const unsigned char* messageContent=NULL;
+            size_t messageSize=0;
+            size_t originalMessageSize=0;
             IOTHUB_MESSAGE_LIST* message = containingRecord(handleData->waitingToSend->Flink, IOTHUB_MESSAGE_LIST, entry);
             IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(message->messageHandle);
 
+            /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_122: [The message size is computed from the length of the payload + 384.]*/
             if (!(
-                ((contentType == IOTHUBMESSAGE_BYTEARRAY) && (IoTHubMessage_GetByteArray(message->messageHandle, &messageContent, &messageSize)==IOTHUB_MESSAGE_OK)) ||
+                (((contentType == IOTHUBMESSAGE_BYTEARRAY) && 
+                    (IoTHubMessage_GetByteArray(message->messageHandle, &messageContent, &originalMessageSize)==IOTHUB_MESSAGE_OK)) ? (messageSize= originalMessageSize + MAXIMUM_PAYLOAD_OVERHEAD, 1): 0)
+                
+                ||
+
                 ((contentType == IOTHUBMESSAGE_STRING) && (
                     messageContent = (const unsigned char*)IoTHubMessage_GetString(message->messageHandle), 
-                    (messageSize = (messageContent == NULL)?0:strlen((const char*)messageContent)), 
+                    (messageSize = MAXIMUM_PAYLOAD_OVERHEAD + (originalMessageSize = ((messageContent == NULL)?0:strlen((const char*)messageContent)))), 
                     messageContent!=NULL)
                     )
                 ))
@@ -1037,7 +1064,8 @@
             else
             {
                 /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_109: [If the oldest message in waitingToSend causes the message to exceed the message size limit then it shall be removed from waitingToSend, and IoTHubClient_LL_SendComplete shall be called. Parameter PDLIST_ENTRY completed shall point to a list containing only the oldest item, and parameter IOTHUB_BATCHSTATE result shall be set to IOTHUB_BATCHSTATE_FAILED.]*/
-                if (messageSize >= MAXIMUM_MESSAGE_SIZE)
+                /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_121: [The message size shall be limited to 255KB -1 bytes.] */
+                if (messageSize > MAXIMUM_MESSAGE_SIZE)
                 {
                     PDLIST_ENTRY head = DList_RemoveHeadList(handleData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
                     DList_InsertTailList(&(handleData->eventConfirmations), head);
@@ -1079,32 +1107,44 @@
                                 bool goOn = true;
                                 for (i = 0; (i < count) && goOn; i++)
                                 {
-                                    
-                                    STRING_HANDLE temp = STRING_construct(IOTHUB_APP_PREFIX);
-                                    if (temp == NULL)
+                                    /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_123: [Every property name shall add  to the message size the length of the property name + the length of the property value + 16 bytes.] */
+                                    messageSize += (strlen(values[i]) + strlen(keys[i]) + MAXIMUM_PROPERTY_OVERHEAD);
+                                    if (messageSize > MAXIMUM_MESSAGE_SIZE)
                                     {
-                                        /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_108: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
-                                        LogError("unable to STRING_construct\r\n");
+                                        /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_121: [The message size shall be limited to 255KB -1 bytes.] */
+                                        PDLIST_ENTRY head = DList_RemoveHeadList(handleData->waitingToSend); /*actually this is the same as "actual", but now it is removed*/
+                                        DList_InsertTailList(&(handleData->eventConfirmations), head);
+                                        IoTHubClient_LL_SendComplete(iotHubClientHandle, &(handleData->eventConfirmations), IOTHUB_BATCHSTATE_FAILED); /*takes care of emptying the list too*/
                                         goOn = false;
                                     }
                                     else
                                     {
-                                        if (STRING_concat(temp, keys[i]) != 0)
+                                        STRING_HANDLE temp = STRING_construct(IOTHUB_APP_PREFIX);
+                                        if (temp == NULL)
                                         {
                                             /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_108: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
-                                            LogError("unable to STRING_concat\r\n");
+                                            LogError("unable to STRING_construct\r\n");
                                             goOn = false;
                                         }
                                         else
                                         {
-                                            if (HTTPHeaders_ReplaceHeaderNameValuePair(clonedEventHTTPrequestHeaders, STRING_c_str(temp), values[i]) != HTTP_HEADERS_OK)
+                                            if (STRING_concat(temp, keys[i]) != 0)
                                             {
                                                 /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_108: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
-                                                LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair\r\n");
+                                                LogError("unable to STRING_concat\r\n");
                                                 goOn = false;
                                             }
+                                            else
+                                            {
+                                                if (HTTPHeaders_ReplaceHeaderNameValuePair(clonedEventHTTPrequestHeaders, STRING_c_str(temp), values[i]) != HTTP_HEADERS_OK)
+                                                {
+                                                    /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_108: [If any HTTP header operation fails, _DoWork shall advance to the next action.] */
+                                                    LogError("unable to HTTPHeaders_ReplaceHeaderNameValuePair\r\n");
+                                                    goOn = false;
+                                                }
+                                            }
+                                            STRING_delete(temp);
                                         }
-                                        STRING_delete(temp); 
                                     }
                                 }
 
@@ -1122,7 +1162,7 @@
                                     }
                                     else
                                     {
-                                        if (BUFFER_build(toBeSend, messageContent, messageSize) != 0)
+                                        if (BUFFER_build(toBeSend, messageContent, originalMessageSize) != 0)
                                         {
                                             LogError("unable to BUFFER_build\r\n");
                                         }
@@ -1311,11 +1351,11 @@
     }
 }
 
-static void DoNotifications(TRANSPORT_HANDLE handle, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle)
+static void DoMessages(TRANSPORT_HANDLE handle, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle)
 {
     HTTPTRANSPORT_HANDLE_DATA* handleData = (HTTPTRANSPORT_HANDLE_DATA*)handle;
-    /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_057: [If flag DoWork_PullNotification is set to false then _DoWork shall advance to the next action.] */
-    if (handleData->DoWork_PullNotification)
+    /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_057: [If flag DoWork_PullMessage is set to false then _DoWork shall advance to the next action.] */
+    if (handleData->DoWork_PullMessage)
     {
         /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_116: [After client creation, the first GET shall be allowed no matter what the value of GetMinimumPollingTime.] */
         /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_117: [If time is not available then all calls shall be treated as if they are the first one.] */
@@ -1343,8 +1383,8 @@
                 unsigned int statusCode;
                 /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_036: [Otherwise, IoTHubTransportHttp_DoWork shall call HTTPAPIEX_SAS_ExecuteRequest passing the following parameters
 requestType: GET
-relativePath: the notification HTTP relative path
-requestHttpHeadersHandle: notification HTTP request headers created by _Create
+relativePath: the message HTTP relative path
+requestHttpHeadersHandle: message HTTP request headers created by _Create
 requestContent: NULL
 statusCode: a pointer to unsigned int which shall be later examined
 responseHeadearsHandle: a new instance of HTTP headers
@@ -1354,8 +1394,8 @@
                     handleData->sasObject,
                     handleData->httpApiExHandle,     
                     HTTPAPI_REQUEST_GET,                                            /*requestType: GET*/
-                    STRING_c_str(handleData->notificationHTTPrelativePath),         /*relativePath: the notification HTTP relative path*/
-                    handleData->notificationHTTPrequestHeaders,                     /*requestHttpHeadersHandle: notification HTTP request headers created by _Create*/
+                    STRING_c_str(handleData->messageHTTPrelativePath),         /*relativePath: the message HTTP relative path*/
+                    handleData->messageHTTPrequestHeaders,                     /*requestHttpHeadersHandle: message HTTP request headers created by _Create*/
                     NULL,                                                           /*requestContent: NULL*/
                     &statusCode,                                                    /*statusCode: a pointer to unsigned int which shall be later examined*/
                     responseHTTPHeaders,                                            /*responseHeadearsHandle: a new instance of HTTP headers*/
@@ -1464,21 +1504,21 @@
                                         }
                                         else
                                         {
-                                            /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_043: [Otherwise, _DoWork shall call IoTHubClient_LL_NotificationCallback with parameters handle = iotHubClientHandle and notificationMessage = newly created message.]*/
-                                            IOTHUBMESSAGE_DISPOSITION_RESULT notificationResult = IoTHubClient_LL_NotificationCallback(iotHubClientHandle, receivedMessage);
-                                            if (notificationResult == IOTHUBMESSAGE_ACCEPTED)
+                                            /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_043: [Otherwise, _DoWork shall call IoTHubClient_LL_MessageCallback with parameters handle = iotHubClientHandle and message = newly created message.]*/
+                                            IOTHUBMESSAGE_DISPOSITION_RESULT messageResult = IoTHubClient_LL_MessageCallback(iotHubClientHandle, receivedMessage);
+                                            if (messageResult == IOTHUBMESSAGE_ACCEPTED)
                                             {
-                                                /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_044: [If IoTHubClient_LL_NotificationCallback returns IOTHUBMESSAGE_ACCEPTED then _DoWork shall "accept" the message.]*/
+                                                /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_044: [If IoTHubClient_LL_MessageCallback returns IOTHUBMESSAGE_ACCEPTED then _DoWork shall "accept" the message.]*/
                                                 abandonOrAcceptMessage(handle, etagValue, ACCEPT);
                                             }
-                                            else if (notificationResult == IOTHUBMESSAGE_REJECTED)
+                                            else if (messageResult == IOTHUBMESSAGE_REJECTED)
                                             {
-                                                /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_074: [If IoTHubClient_LL_NotificationCallback returns IOTHUBMESSAGE_REJECTED then _DoWork shall "reject" the message.]*/
+                                                /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_074: [If IoTHubClient_LL_MessageCallback returns IOTHUBMESSAGE_REJECTED then _DoWork shall "reject" the message.]*/
                                                 abandonOrAcceptMessage(handle, etagValue, REJECT);
                                             }
                                             else
                                             {
-                                                /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_079: [If IoTHubClient_LL_NotificationCallback returns IOTHUBMESSAGE_ABANDONED then _DoWork shall "abandon" the message.] */
+                                                /*Codes_SRS_IOTHUBTRANSPORTTHTTP_02_079: [If IoTHubClient_LL_MessageCallback returns IOTHUBMESSAGE_ABANDONED then _DoWork shall "abandon" the message.] */
                                                 abandonOrAcceptMessage(handle, etagValue, ABANDON);
                                             }
                                         }
@@ -1509,7 +1549,7 @@
     if ((handle != NULL) && (iotHubClientHandle != NULL))
     {
         DoEvent(handle, iotHubClientHandle);
-        DoNotifications(handle, iotHubClientHandle);
+        DoMessages(handle, iotHubClientHandle);
     }
 }