Azure IoT common library

Fork of azure_c_shared_utility by Azure IoT

Revision:
15:956c6d205aa7
Parent:
14:b7e6599cacf5
Child:
18:6d8a413a4d9a
--- a/httpapi_compact.c	Fri Oct 21 22:11:02 2016 +0000
+++ b/httpapi_compact.c	Wed Nov 16 21:38:39 2016 -0800
@@ -16,10 +16,11 @@
 #include "azure_c_shared_utility/platform.h"
 #include "azure_c_shared_utility/tlsio.h"
 #include "azure_c_shared_utility/threadapi.h"
+#include "azure_c_shared_utility/shared_util_options.h"
 #include <string.h>
 #include <limits.h>
 
-/*Codes_SRS_HTTPAPI_COMPACT_21_001: [ The httpapi_compact shall implement the methods defined by the `httpapi.h`. ]*/ 
+/*Codes_SRS_HTTPAPI_COMPACT_21_001: [ The httpapi_compact shall implement the methods defined by the `httpapi.h`. ]*/
 /*Codes_SRS_HTTPAPI_COMPACT_21_002: [ The httpapi_compact shall support the http requests. ]*/
 /*Codes_SRS_HTTPAPI_COMPACT_21_003: [ The httpapi_compact shall return error codes defined by HTTPAPI_RESULT. ]*/
 #include "azure_c_shared_utility/httpapi.h"
@@ -27,41 +28,47 @@
 #define MAX_HOSTNAME     64
 #define TEMP_BUFFER_SIZE 1024
 
-/*Codes_SRS_HTTPAPI_COMPACT_21_076: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 times. ]*/
-/*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
-#define MAX_RECEIVE_RETRY   70
-/*Codes_SRS_HTTPAPI_COMPACT_21_078: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
-#define RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS  100
-#define OPEN_RETRY_INTERVAL_IN_MICROSECONDS  100
-
+/*Codes_SRS_HTTPAPI_COMPACT_21_077: [ The HTTPAPI_ExecuteRequest shall wait, at least, 10 seconds for the SSL open process. ]*/
+#define MAX_OPEN_RETRY   100
+/*Codes_SRS_HTTPAPI_COMPACT_21_084: [ The HTTPAPI_CloseConnection shall wait, at least, 10 seconds for the SSL close process. ]*/
+#define MAX_CLOSE_RETRY   100
+/*Codes_SRS_HTTPAPI_COMPACT_21_079: [ The HTTPAPI_ExecuteRequest shall wait, at least, 20 seconds to send a buffer using the SSL connection. ]*/
+#define MAX_SEND_RETRY   200
+/*Codes_SRS_HTTPAPI_COMPACT_21_081: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 seconds. ]*/
+#define MAX_RECEIVE_RETRY   200
+/*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+#define RETRY_INTERVAL_IN_MICROSECONDS  100
 
 DEFINE_ENUM_STRINGS(HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES)
 
 typedef struct HTTP_HANDLE_DATA_TAG
 {
     char*           certificate;
+    char*           x509ClientCertificate;
+    char*           x509ClientPrivateKey;
     XIO_HANDLE      xio_handle;
     size_t          received_bytes_count;
     unsigned char*  received_bytes;
     unsigned int    is_io_error : 1;
     unsigned int    is_connected : 1;
+    unsigned int    send_completed : 1;
 } HTTP_HANDLE_DATA;
 
 /*the following function does the same as sscanf(pos2, "%d", &sec)*/
 /*this function only exists because some of platforms do not have sscanf. */
 static int ParseStringToDecimal(const char *src, int* dst)
 {
-	int result;
+    int result;
     char* next;
     (*dst) = strtol(src, &next, 0);
     if ((src == next) || ((((*dst) == LONG_MAX) || ((*dst) == LONG_MIN)) && (errno != 0)))
     {
-		result = EOF;
+        result = EOF;
     }
-	else
-	{
-		result = 1;
-	}
+    else
+    {
+        result = 1;
+    }
     return result;
 }
 
@@ -70,27 +77,27 @@
 #define HEXA_DIGIT_VAL(c)         (((c>='0') && (c<='9')) ? (c-'0') : ((c>='a') && (c<='f')) ? (c-'a'+10) : ((c>='A') && (c<='F')) ? (c-'A'+10) : -1)
 static int ParseStringToHexadecimal(const char *src, size_t* dst)
 {
-	int result;
+    int result;
     int digitVal;
     if (src == NULL)
-	{
-		result = EOF;
-	}
-	else if (HEXA_DIGIT_VAL(*src) == -1)
-	{
-		result = EOF;
-	}
-	else
-	{
-		(*dst) = 0;
-		while ((digitVal = HEXA_DIGIT_VAL(*src)) != -1)
-		{
-			(*dst) *= 0x10;
-			(*dst) += (size_t)digitVal;
-			src++;
-		}
-		result = 1;
-	}
+    {
+        result = EOF;
+    }
+    else if (HEXA_DIGIT_VAL(*src) == -1)
+    {
+        result = EOF;
+    }
+    else
+    {
+        (*dst) = 0;
+        while ((digitVal = HEXA_DIGIT_VAL(*src)) != -1)
+        {
+            (*dst) *= 0x10;
+            (*dst) += (size_t)digitVal;
+            src++;
+        }
+        result = 1;
+    }
     return result;
 }
 
@@ -98,88 +105,88 @@
 /*this function only exists because some of platforms do not have sscanf. This is not a full implementation; it only works with well-defined HTTP response. */
 static int  ParseHttpResponse(const char* src, int* dst)
 {
-	int result;
-	static const char HTTPPrefix[] = "HTTP/";
+    int result;
+    static const char HTTPPrefix[] = "HTTP/";
     bool fail;
     const char* runPrefix;
 
-	if ((src == NULL) || (dst == NULL))
-	{
-		result = EOF;
-	}
-	else
-	{
-		fail = false;
-		runPrefix = HTTPPrefix;
+    if ((src == NULL) || (dst == NULL))
+    {
+        result = EOF;
+    }
+    else
+    {
+        fail = false;
+        runPrefix = HTTPPrefix;
 
-		while((*runPrefix) != '\0')
-		{
-			if ((*runPrefix) != (*src))
-			{
-				fail = true;
-				break;
-			}
-			src++;
-			runPrefix++;
-		}
+        while((*runPrefix) != '\0')
+        {
+            if ((*runPrefix) != (*src))
+            {
+                fail = true;
+                break;
+            }
+            src++;
+            runPrefix++;
+        }
 
-		if (!fail)
-		{
-			while ((*src) != '.')
-			{
-				if ((*src) == '\0')
-				{
-					fail = true;
+        if (!fail)
+        {
+            while ((*src) != '.')
+            {
+                if ((*src) == '\0')
+                {
+                    fail = true;
                     break;
-				}
-				src++;
-			}
-		}
+                }
+                src++;
+            }
+        }
 
-		if (!fail)
-		{
-			while ((*src) != ' ')
-			{
-				if ((*src) == '\0')
-				{
-					fail = true;
+        if (!fail)
+        {
+            while ((*src) != ' ')
+            {
+                if ((*src) == '\0')
+                {
+                    fail = true;
                     break;
-				}
-				src++;
-			}
-		}
+                }
+                src++;
+            }
+        }
 
-		if (fail)
-		{
-			result = EOF;
-		}
-		else
-		{
-			result = ParseStringToDecimal(src, dst);
-		}
-	}
+        if (fail)
+        {
+            result = EOF;
+        }
+        else
+        {
+            result = ParseStringToDecimal(src, dst);
+        }
+    }
 
     return result;
 }
 
 HTTPAPI_RESULT HTTPAPI_Init(void)
 {
-	/*Codes_SRS_HTTPAPI_COMPACT_21_004: [ The HTTPAPI_Init shall allocate all memory to control the http protocol. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_007: [ If there is not enough memory to control the http protocol, the HTTPAPI_Init shall return HTTPAPI_ALLOC_FAILED. ]*/
-	/**
-	 * No memory is necessary. 
-	 */
+/*Codes_SRS_HTTPAPI_COMPACT_21_004: [ The HTTPAPI_Init shall allocate all memory to control the http protocol. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_007: [ If there is not enough memory to control the http protocol, the HTTPAPI_Init shall return HTTPAPI_ALLOC_FAILED. ]*/
+/**
+ * No memory is necessary.
+ */
 
-	/*Codes_SRS_HTTPAPI_COMPACT_21_006: [ If HTTPAPI_Init succeed allocating all the needed memory, it shall return HTTPAPI_OK. ]*/
-    return HTTPAPI_OK;
+ /*Codes_SRS_HTTPAPI_COMPACT_21_006: [ If HTTPAPI_Init succeed allocating all the needed memory, it shall return HTTPAPI_OK. ]*/
+return HTTPAPI_OK;
 }
 
 void HTTPAPI_Deinit(void)
 {
-	/*Codes_SRS_HTTPAPI_COMPACT_21_009: [ The HTTPAPI_Init shall release all memory allocated by the httpapi_compact. ]*/
-	/**
-	* No memory was necessary.
-	*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_009: [ The HTTPAPI_Init shall release all memory allocated by the httpapi_compact. ]*/
+    /**
+    * No memory was necessary.
+    */
 }
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_011: [ The HTTPAPI_CreateConnection shall create an http connection to the host specified by the hostName parameter. ]*/
@@ -188,75 +195,132 @@
     HTTP_HANDLE_DATA* http_instance;
     TLSIO_CONFIG tlsio_config;
 
-	if (hostName == NULL)
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_014: [ If the hostName is NULL, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
-		LogError("Invalid host name. Null hostName parameter.");
-		http_instance = NULL;
-	}
-	else if (*hostName == '\0')
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_015: [ If the hostName is empty, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
-		LogError("Invalid host name. Empty string.");
-		http_instance = NULL;
-	}
-	else
-	{
-		http_instance = (HTTP_HANDLE_DATA*)malloc(sizeof(HTTP_HANDLE_DATA));
-		/*Codes_SRS_HTTPAPI_COMPACT_21_013: [ If there is not enough memory to control the http connection, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
-		if (http_instance == NULL)
-		{
-			LogError("There is no memory to control the http connection");
-		}
-		else
-		{
-			tlsio_config.hostname = hostName;
-			tlsio_config.port = 443;
+    if (hostName == NULL)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_014: [ If the hostName is NULL, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
+        LogError("Invalid host name. Null hostName parameter.");
+        http_instance = NULL;
+    }
+    else if (*hostName == '\0')
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_015: [ If the hostName is empty, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
+        LogError("Invalid host name. Empty string.");
+        http_instance = NULL;
+    }
+    else
+    {
+        http_instance = (HTTP_HANDLE_DATA*)malloc(sizeof(HTTP_HANDLE_DATA));
+        /*Codes_SRS_HTTPAPI_COMPACT_21_013: [ If there is not enough memory to control the http connection, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/
+        if (http_instance == NULL)
+        {
+            LogError("There is no memory to control the http connection");
+        }
+        else
+        {
+            tlsio_config.hostname = hostName;
+            tlsio_config.port = 443;
+
+            http_instance->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config);
 
-			http_instance->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config);
+            /*Codes_SRS_HTTPAPI_COMPACT_21_016: [ If the HTTPAPI_CreateConnection failed to create the connection, it shall return NULL as the handle. ]*/
+            if (http_instance->xio_handle == NULL)
+            {
+                LogError("Create connection failed");
+                free(http_instance);
+                http_instance = NULL;
+            }
+            else
+            {
+                http_instance->is_connected = 0;
+                http_instance->is_io_error = 0;
+                http_instance->received_bytes_count = 0;
+                http_instance->received_bytes = NULL;
+                http_instance->certificate = NULL;
+                http_instance->x509ClientCertificate = NULL;
+                http_instance->x509ClientPrivateKey = NULL;
+            }
+        }
+    }
 
-			/*Codes_SRS_HTTPAPI_COMPACT_21_016: [ If the HTTPAPI_CreateConnection failed to create the connection, it shall return NULL as the handle. ]*/
-			if (http_instance->xio_handle == NULL)
-			{
-				LogError("Create connection failed");
-				free(http_instance);
-				http_instance = NULL;
-			}
-			else
-			{
-				http_instance->is_connected = 0;
-				http_instance->is_io_error = 0;
-				http_instance->received_bytes_count = 0;
-				http_instance->received_bytes = NULL;
-				http_instance->certificate = NULL;
-			}
-		}
-	}
+    /*Codes_SRS_HTTPAPI_COMPACT_21_012: [ The HTTPAPI_CreateConnection shall return a non-NULL handle on success. ]*/
+    return (HTTP_HANDLE)http_instance;
+}
 
-	/*Codes_SRS_HTTPAPI_COMPACT_21_012: [ The HTTPAPI_CreateConnection shall return a non-NULL handle on success. ]*/
-	return (HTTP_HANDLE)http_instance;
+static void on_io_close_complete(void* context)
+{
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
+
+    if (http_instance != NULL)
+    {
+        http_instance->is_connected = 0;
+    }
 }
 
 void HTTPAPI_CloseConnection(HTTP_HANDLE handle)
 {
     HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
 
-	/*Codes_SRS_HTTPAPI_COMPACT_21_020: [ If the connection handle is NULL, the HTTPAPI_CloseConnection shall not do anything. ]*/
-	if (http_instance != NULL)
+    /*Codes_SRS_HTTPAPI_COMPACT_21_020: [ If the connection handle is NULL, the HTTPAPI_CloseConnection shall not do anything. ]*/
+    if (http_instance != NULL)
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_019: [ If there is no previous connection, the HTTPAPI_CloseConnection shall not do anything. ]*/
-		if (http_instance->xio_handle != NULL)
+        /*Codes_SRS_HTTPAPI_COMPACT_21_019: [ If there is no previous connection, the HTTPAPI_CloseConnection shall not do anything. ]*/
+        if (http_instance->xio_handle != NULL)
         {
-			/*Codes_SRS_HTTPAPI_COMPACT_21_017: [ The HTTPAPI_CloseConnection shall close the connection previously created in HTTPAPI_CreateConnection. ]*/
+            http_instance->is_io_error = 0;
+            /*Codes_SRS_HTTPAPI_COMPACT_21_017: [ The HTTPAPI_CloseConnection shall close the connection previously created in HTTPAPI_ExecuteRequest. ]*/
+            if (xio_close(http_instance->xio_handle, on_io_close_complete, http_instance) != 0)
+            {
+                LogError("The SSL got error closing the connection");
+                /*Codes_SRS_HTTPAPI_COMPACT_21_087: [ If the xio return anything different than 0, the HTTPAPI_CloseConnection shall destroy the connection anyway. ]*/
+                http_instance->is_connected = 0;
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_084: [ The HTTPAPI_CloseConnection shall wait, at least, 10 seconds for the SSL close process. ]*/
+                int countRetry = MAX_CLOSE_RETRY;
+                while (http_instance->is_connected == 1)
+                {
+                    xio_dowork(http_instance->xio_handle);
+                    if ((countRetry--) < 0)
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_085: [ If the HTTPAPI_CloseConnection retries 10 seconds to close the connection without success, it shall destroy the connection anyway. ]*/
+                        LogError("Close timeout. The SSL didn't close the connection");
+                        http_instance->is_connected = 0;
+                    }
+                    else if (http_instance->is_io_error == 1)
+                    {
+                        LogError("The SSL got error closing the connection");
+                        http_instance->is_connected = 0;
+                    }
+                    else if (http_instance->is_connected == 1)
+                    {
+                        LogInfo("Waiting for TLS close connection");
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_086: [ The HTTPAPI_CloseConnection shall wait, at least, 100 milliseconds between retries. ]*/
+                        ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+                    }
+                }
+            }
+            /*Codes_SRS_HTTPAPI_COMPACT_21_076: [ After close the connection, The HTTPAPI_CloseConnection shall destroy the connection previously created in HTTPAPI_CreateConnection. ]*/
             xio_destroy(http_instance->xio_handle);
         }
 
-		/*Codes_SRS_HTTPAPI_COMPACT_21_018: [ If there is a certificate associated to this connection, the HTTPAPI_CloseConnection shall free all allocated memory for the certificate. ]*/
-		if (http_instance->certificate)
+        /*Codes_SRS_HTTPAPI_COMPACT_21_018: [ If there is a certificate associated to this connection, the HTTPAPI_CloseConnection shall free all allocated memory for the certificate. ]*/
+        if (http_instance->certificate)
         {
             free(http_instance->certificate);
         }
 
+        /*Codes_SRS_HTTPAPI_COMPACT_06_001: [ If there is a x509 client certificate associated to this connection, the HTTAPI_CloseConnection shall free all allocated memory for the certificate. ]*/
+        if (http_instance->x509ClientCertificate)
+        {
+            free(http_instance->x509ClientCertificate);
+        }
+
+        /*Codes_SRS_HTTPAPI_COMPACT_06_002: [ If there is a x509 client private key associated to this connection, then HTTP_CloseConnection shall free all the allocated memory for the private key. ]*/
+        if (http_instance->x509ClientPrivateKey)
+        {
+            free(http_instance->x509ClientPrivateKey);
+        }
         free(http_instance);
     }
 }
@@ -264,19 +328,37 @@
 static void on_io_open_complete(void* context, IO_OPEN_RESULT open_result)
 {
     HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
-    
+
     if (http_instance != NULL)
-	{
-		if (open_result == IO_OPEN_OK)
-		{
-			http_instance->is_connected = 1;
-			http_instance->is_io_error = 0;
-		}
-		else
-		{
-			http_instance->is_io_error = 1;
-		}
-	}
+    {
+        if (open_result == IO_OPEN_OK)
+        {
+            http_instance->is_connected = 1;
+            http_instance->is_io_error = 0;
+        }
+        else
+        {
+            http_instance->is_io_error = 1;
+        }
+    }
+}
+
+static void on_send_complete(void* context, IO_SEND_RESULT send_result)
+{
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
+
+    if (http_instance != NULL)
+    {
+        if (send_result == IO_SEND_OK)
+        {
+            http_instance->send_completed = 1;
+            http_instance->is_io_error = 0;
+        }
+        else
+        {
+            http_instance->is_io_error = 1;
+        }
+    }
 }
 
 #define TOLOWER(c) (((c>='A') && (c<='Z'))?c-'A'+'a':c)
@@ -284,26 +366,26 @@
 {
     int result;
 
-	if ((s1 == NULL) || (s2 == NULL))
-	{
-		result = -1;
-	}
-	else
-	{
-		result = 0;
-		while (((n--) >= 0) && ((*s1) != '\0') && ((*s2) != '\0') && (result == 0))
-		{
-			/* compute the difference between the chars */
-			result = TOLOWER(*s1) - TOLOWER(*s2);
-			s1++;
-			s2++;
-		}
+    if ((s1 == NULL) || (s2 == NULL))
+    {
+        result = -1;
+    }
+    else
+    {
+        result = 0;
+        while (((n--) >= 0) && ((*s1) != '\0') && ((*s2) != '\0') && (result == 0))
+        {
+            /* compute the difference between the chars */
+            result = TOLOWER(*s1) - TOLOWER(*s2);
+            s1++;
+            s2++;
+        }
 
         if ((*s2) != '\0')
         {
             result = -1;
         }
-	}
+    }
 
     return result;
 }
@@ -344,7 +426,7 @@
                 }
             }
         }
-	}
+    }
 }
 
 static void on_io_error(void* context)
@@ -361,47 +443,48 @@
 {
     int result;
 
-	if ((http_instance == NULL) || (buffer == NULL) || (count < 0))
-	{
+    if ((http_instance == NULL) || (buffer == NULL) || (count < 0))
+    {
         LogError("conn_receive: %s", ((http_instance == NULL) ? "Invalid HTTP instance" : "Invalid HTTP buffer"));
         result = -1;
-	}
-	else
-	{
-		result = 0;
-		while (result < count)
-		{
-			xio_dowork(http_instance->xio_handle);
+    }
+    else
+    {
+        result = 0;
+        while (result < count)
+        {
+            xio_dowork(http_instance->xio_handle);
 
-			/* if any error was detected while receiving then simply break and report it */
-			if (http_instance->is_io_error != 0)
-			{
+            /* if any error was detected while receiving then simply break and report it */
+            if (http_instance->is_io_error != 0)
+            {
                 LogError("xio reported error on dowork");
                 result = -1;
-				break;
-			}
+                break;
+            }
 
-			if (http_instance->received_bytes_count >= (size_t)count)
-			{
-				/* Consuming bytes from the receive buffer */
-				(void)memcpy(buffer, http_instance->received_bytes, count);
-				(void)memmove(http_instance->received_bytes, http_instance->received_bytes + count, http_instance->received_bytes_count - count);
-				http_instance->received_bytes_count -= count;
+            if (http_instance->received_bytes_count >= (size_t)count)
+            {
+                /* Consuming bytes from the receive buffer */
+                (void)memcpy(buffer, http_instance->received_bytes, count);
+                (void)memmove(http_instance->received_bytes, http_instance->received_bytes + count, http_instance->received_bytes_count - count);
+                http_instance->received_bytes_count -= count;
 
-				/* we're not reallocating at each consumption so that we don't trash due to byte by byte consumption */
-				if (http_instance->received_bytes_count == 0)
-				{
-					free(http_instance->received_bytes);
-					http_instance->received_bytes = NULL;
-				}
+                /* we're not reallocating at each consumption so that we don't trash due to byte by byte consumption */
+                if (http_instance->received_bytes_count == 0)
+                {
+                    free(http_instance->received_bytes);
+                    http_instance->received_bytes = NULL;
+                }
 
-				result = count;
-				break;
-			}
+                result = count;
+                break;
+            }
 
-			ThreadAPI_Sleep(RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS);
-		}
-	}
+            /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+            ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+        }
+    }
 
     return result;
 }
@@ -431,7 +514,7 @@
     else
     {
         char* destByte = buf;
-        /*Codes_SRS_HTTPAPI_COMPACT_21_076: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 times. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_081: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 seconds. ]*/
         int countRetry = MAX_RECEIVE_RETRY;
         bool endOfSearch = false;
         resultLineSize = -1;
@@ -493,13 +576,13 @@
             {
                 if ((countRetry--) > 0)
                 {
-                    /*Codes_SRS_HTTPAPI_COMPACT_21_078: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
-                    ThreadAPI_Sleep(RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS);
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                    ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
                 }
                 else
                 {
-                    /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
-                    LogError("Timeout. The HTTP request is incomplete");
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                    LogError("Receive timeout. The HTTP request is incomplete");
                     endOfSearch = true;
                 }
             }
@@ -522,10 +605,10 @@
         cur = conn_receive(http_instance, buf + offset, (int)size);
 
         // end of stream reached
-		if (cur == 0)
-		{
-			break;
-		}
+        if (cur == 0)
+        {
+            break;
+        }
 
         // read cur bytes (might be less than requested)
         size -= (size_t)cur;
@@ -549,7 +632,7 @@
     }
     else
     {
-        /*Codes_SRS_HTTPAPI_COMPACT_21_076: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 times. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_081: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 seconds. ]*/
         int countRetry = MAX_RECEIVE_RETRY;
         result = (int)n;
         while (n > 0)
@@ -581,13 +664,13 @@
                 {
                     if ((countRetry--) > 0)
                     {
-                        /*Codes_SRS_HTTPAPI_COMPACT_21_078: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
-                        ThreadAPI_Sleep(RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS);
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                        ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
                     }
                     else
                     {
-                        /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
-                        LogError("Timeout. The HTTP request is incomplete");
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                        LogError("Receive timeout. The HTTP request is incomplete");
                         n = 0;
                         result = -1;
                     }
@@ -603,53 +686,127 @@
 /*Codes_SRS_HTTPAPI_COMPACT_21_021: [ The HTTPAPI_ExecuteRequest shall execute the http communtication with the provided host, sending a request and reciving the response. ]*/
 static HTTPAPI_RESULT OpenXIOConnection(HTTP_HANDLE_DATA* http_instance)
 {
-	HTTPAPI_RESULT result;
+    HTTPAPI_RESULT result;
+
+    if (http_instance->is_connected != 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+    }
+    else
+    {
+        http_instance->is_io_error = 0;
+
+        /*Codes_SRS_HTTPAPI_COMPACT_21_022: [ If a Certificate was provided, the HTTPAPI_ExecuteRequest shall set this option on the transport layer. ]*/
+        if ((http_instance->certificate != NULL) &&
+            (xio_setoption(http_instance->xio_handle, "TrustedCerts", http_instance->certificate) != 0))
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_023: [ If the transport failed setting the Certificate, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ]*/
+            result = HTTPAPI_SET_OPTION_FAILED;
+            LogInfo("Could not load certificate");
+        }
+        /*Codes_SRS_HTTPAPI_COMPACT_06_003: [ If the x509 client certificate is provided, the HTTPAPI_ExecuteRequest shall set this option on the transport layer. ]*/
+        else if ((http_instance->x509ClientCertificate != NULL) &&
+            (xio_setoption(http_instance->xio_handle, SU_OPTION_X509_CERT, http_instance->x509ClientCertificate) != 0))
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_06_005: [ If the transport failed setting the client certificate, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ]*/
+            result = HTTPAPI_SET_OPTION_FAILED;
+            LogInfo("Could not load the client certificate");
+        }
+        else if ((http_instance->x509ClientPrivateKey != NULL) &&
+            (xio_setoption(http_instance->xio_handle, SU_OPTION_X509_PRIVATE_KEY, http_instance->x509ClientPrivateKey) != 0))
+        {
 
-	if (http_instance->is_connected != 0)
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
-	}
-	else
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_022: [ If a Certificate was provided, the HTTPAPI_ExecuteRequest shall set this option on the transport layer. ]*/
-		if ((http_instance->certificate != NULL) &&
-			(xio_setoption(http_instance->xio_handle, "TrustedCerts", http_instance->certificate) != 0))
-		{
-			/*Codes_SRS_HTTPAPI_COMPACT_21_023: [ If the transport failed setting the Certificate, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ]*/
-			result = HTTPAPI_SET_OPTION_FAILED;
-			LogInfo("Could not load certificate");
-		}
-		else
-		{
-			/*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
-			if (xio_open(http_instance->xio_handle, on_io_open_complete, http_instance, on_bytes_received, http_instance, on_io_error, http_instance) != 0)
-			{
-				/*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
-				result = HTTPAPI_OPEN_REQUEST_FAILED;
-			}
-			else
-			{
-				/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-				result = HTTPAPI_OK;
-				while ((http_instance->is_connected == 0) &&
-					(http_instance->is_io_error == 0))
-				{
-					xio_dowork(http_instance->xio_handle);
-					LogInfo("Waiting for TLS connection");
-					ThreadAPI_Sleep(OPEN_RETRY_INTERVAL_IN_MICROSECONDS);
-				}
-			}
-		}
-	}
-	
-	if ((http_instance->is_io_error != 0) && (result == HTTPAPI_OK))
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
-		result = HTTPAPI_OPEN_REQUEST_FAILED;
-	}
+            /*Codes_SRS_HTTPAPI_COMPACT_06_006: [ If the transport failed setting the client certificate private key, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ] */
+            result = HTTPAPI_SET_OPTION_FAILED;
+            LogInfo("Could not load the client certificate private key");
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
+            if (xio_open(http_instance->xio_handle, on_io_open_complete, http_instance, on_bytes_received, http_instance, on_io_error, http_instance) != 0)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
+                result = HTTPAPI_OPEN_REQUEST_FAILED;
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+                result = HTTPAPI_OK;
+                /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ The HTTPAPI_ExecuteRequest shall wait, at least, 10 seconds for the SSL open process. ]*/
+                int countRetry = MAX_OPEN_RETRY;
+                while ((http_instance->is_connected == 0) &&
+                    (http_instance->is_io_error == 0))
+                {
+                    xio_dowork(http_instance->xio_handle);
+                    LogInfo("Waiting for TLS connection");
+                    if ((countRetry--) < 0)
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_078: [ If the HTTPAPI_ExecuteRequest cannot open the connection in 10 seconds, it shall fail and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
+                        LogError("Open timeout. The HTTP request is incomplete");
+                        result = HTTPAPI_OPEN_REQUEST_FAILED;
+                        break;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                        ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+                    }
+                }
+            }
+        }
+    }
 
-	return result;
+    if ((http_instance->is_io_error != 0) && (result == HTTPAPI_OK))
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/
+        result = HTTPAPI_OPEN_REQUEST_FAILED;
+    }
+
+    return result;
+}
+
+static HTTPAPI_RESULT conn_send_all(HTTP_HANDLE_DATA* http_instance, const unsigned char* buf, size_t bufLen)
+{
+    HTTPAPI_RESULT result;
+
+    http_instance->send_completed = 0;
+    http_instance->is_io_error = 0;
+    if (xio_send(http_instance->xio_handle, buf, bufLen, on_send_complete, http_instance) != 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+        result = HTTPAPI_SEND_REQUEST_FAILED;
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_079: [ The HTTPAPI_ExecuteRequest shall wait, at least, 20 seconds to send a buffer using the SSL connection. ]*/
+        int countRetry = MAX_SEND_RETRY;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+        while ((http_instance->send_completed == 0) && (result == HTTPAPI_OK))
+        {
+            xio_dowork(http_instance->xio_handle);
+            if (http_instance->is_io_error != 0)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+                result = HTTPAPI_SEND_REQUEST_FAILED;
+            }
+            else if ((countRetry--) <= 0)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_080: [ If the HTTPAPI_ExecuteRequest retries to send the message for 20 seconds without success, it shall fail and return HTTPAPI_SEND_REQUEST_FAILED. ]*/
+                LogError("Send timeout. The HTTP request is incomplete");
+                /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+                result = HTTPAPI_SEND_REQUEST_FAILED;
+            }
+            else
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
+                ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
+            }
+        }
+    }
+
+    return result;
 }
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_035: [ The HTTPAPI_ExecuteRequest shall execute resquest for types `GET`, `POST`, `PUT`, `DELETE`, `PATCH`. ]*/
@@ -662,249 +819,234 @@
 /*Codes_SRS_HTTPAPI_COMPACT_21_026: [ If the open process succeed, the HTTPAPI_ExecuteRequest shall send the request message to the host. ]*/
 static HTTPAPI_RESULT SendHeadsToXIO(HTTP_HANDLE_DATA* http_instance, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, HTTP_HEADERS_HANDLE httpHeadersHandle, size_t headersCount)
 {
-	HTTPAPI_RESULT result;
-	char    buf[TEMP_BUFFER_SIZE];
-	int     ret;
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
+    int     ret;
 
-	//Send request
-	/*Codes_SRS_HTTPAPI_COMPACT_21_038: [ The HTTPAPI_ExecuteRequest shall execute the resquest for the path in relativePath parameter. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_036: [ The request type shall be provided in the parameter requestType. ]*/
-	if (((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", get_request_type(requestType), relativePath)) < 0) ||
-		(ret >= sizeof(buf)))
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/
-		result = HTTPAPI_STRING_PROCESSING_ERROR;
-	}
-    else if (xio_send(http_instance->xio_handle, (const unsigned char*)buf, strlen(buf), NULL, NULL) != 0)
+    //Send request
+    /*Codes_SRS_HTTPAPI_COMPACT_21_038: [ The HTTPAPI_ExecuteRequest shall execute the resquest for the path in relativePath parameter. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_036: [ The request type shall be provided in the parameter requestType. ]*/
+    if (((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", get_request_type(requestType), relativePath)) < 0) ||
+        (ret >= sizeof(buf)))
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/
+        result = HTTPAPI_STRING_PROCESSING_ERROR;
+    }
+        /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
+    else if ((result = conn_send_all(http_instance, (const unsigned char*)buf, strlen(buf))) == HTTPAPI_OK)
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
-		result = HTTPAPI_SEND_REQUEST_FAILED;
-	}
-	else
-	{
-		//Send default headers
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
-		for (size_t i = 0; ((i < headersCount) && (result == HTTPAPI_OK)); i++)
-		{
-			char* header;
-			if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &header) != HTTP_HEADERS_OK)
-			{
-				/*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/
-				result = HTTPAPI_STRING_PROCESSING_ERROR;
-			}
-			else
-			{
-                if (xio_send(http_instance->xio_handle, (const unsigned char*)header, strlen(header), NULL, NULL) != 0)
+        //Send default headers
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        for (size_t i = 0; ((i < headersCount) && (result == HTTPAPI_OK)); i++)
+        {
+            char* header;
+            if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &header) != HTTP_HEADERS_OK)
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/
+                result = HTTPAPI_STRING_PROCESSING_ERROR;
+            }
+            else
+            {
+                if ((result = conn_send_all(http_instance, (const unsigned char*)header, strlen(header))) == HTTPAPI_OK)
                 {
-					/*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
-					result = HTTPAPI_SEND_REQUEST_FAILED;
-				}
-                if (xio_send(http_instance->xio_handle, (const unsigned char*)"\r\n", (size_t)2, NULL, NULL) != 0)
-                {
-					/*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
-					result = HTTPAPI_SEND_REQUEST_FAILED;
-				}
-				free(header);
-			}
-		}
+                    result = conn_send_all(http_instance, (const unsigned char*)"\r\n", (size_t)2);
+                }
+                free(header);
+            }
+        }
 
-		//Close headers
-        if (xio_send(http_instance->xio_handle, (const unsigned char*)"\r\n", (size_t)2, NULL, NULL) != 0)
+        //Close headers
+        if (result == HTTPAPI_OK)
         {
-			/*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/
-			result = HTTPAPI_SEND_REQUEST_FAILED;
-		}
-	}
-	return result;
+            result = conn_send_all(http_instance, (const unsigned char*)"\r\n", (size_t)2);
+        }
+    }
+    return result;
 }
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/
 static HTTPAPI_RESULT SendContentToXIO(HTTP_HANDLE_DATA* http_instance, const unsigned char* content, size_t contentLength)
 {
-	HTTPAPI_RESULT result;
+    HTTPAPI_RESULT result;
 
-	//Send data (if available)
-	/*Codes_SRS_HTTPAPI_COMPACT_21_045: [ If the contentLength is lower than one, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/
-	if (content && contentLength > 0)
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_044: [ If the content is not NULL, the number of bytes in the content shall be provided in contentLength parameter. ]*/
-        if (xio_send(http_instance->xio_handle, content, contentLength, NULL, NULL) != 0)
-        {
-			/*Codes_SRS_HTTPAPI_COMPACT_21_029: [ If the HTTPAPI_ExecuteRequest cannot send the buffer with the request, it shall return HTTPAPI_SEND_REQUEST_FAILED. ]*/
-			result = HTTPAPI_SEND_REQUEST_FAILED;
-		}
-		else
-		{
-			/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-			result = HTTPAPI_OK;
-		}
-	}
-	else
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_043: [ If the content is NULL, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
-	}
-	return result;
+    //Send data (if available)
+    /*Codes_SRS_HTTPAPI_COMPACT_21_045: [ If the contentLength is lower than one, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/
+    if (content && contentLength > 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_044: [ If the content is not NULL, the number of bytes in the content shall be provided in contentLength parameter. ]*/
+        result = conn_send_all(http_instance, content, contentLength);
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_043: [ If the content is NULL, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+    }
+    return result;
 }
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_030: [ At the end of the transmission, the HTTPAPI_ExecuteRequest shall receive the response from the host. ]*/
 static HTTPAPI_RESULT RecieveHeaderFromXIO(HTTP_HANDLE_DATA* http_instance, unsigned int* statusCode)
 {
-	HTTPAPI_RESULT result;
-	char    buf[TEMP_BUFFER_SIZE];
-	int     ret;
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
+    int     ret;
+
+    http_instance->is_io_error = 0;
 
-	//Receive response
-	if (readLine(http_instance, buf, TEMP_BUFFER_SIZE) < 0)
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-        /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+    //Receive response
+    if (readLine(http_instance, buf, TEMP_BUFFER_SIZE) < 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
         result = HTTPAPI_READ_DATA_FAILED;
-	}
-	//Parse HTTP response
-	else if (ParseHttpResponse(buf, &ret) != 1)
-	{
-		//Cannot match string, error
+    }
+    //Parse HTTP response
+    else if (ParseHttpResponse(buf, &ret) != 1)
+    {
+        //Cannot match string, error
         /*Codes_SRS_HTTPAPI_COMPACT_21_055: [ If the HTTPAPI_ExecuteRequest cannot parser the recived message, it shall return HTTPAPI_RECEIVE_RESPONSE_FAILED. ]*/
         LogInfo("Not a correct HTTP answer");
-		result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
-	}
-	else
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_046: [ The HTTPAPI_ExecuteRequest shall return the http status reported by the host in the received response. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_048: [ If the statusCode is NULL, the HTTPAPI_ExecuteRequest shall report not report any status. ]*/
-		if (statusCode)
-		{
-			/*Codes_SRS_HTTPAPI_COMPACT_21_047: [ The HTTPAPI_ExecuteRequest shall report the status in the statusCode parameter. ]*/
-			*statusCode = ret;
-		}
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
-	}
+        result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_046: [ The HTTPAPI_ExecuteRequest shall return the http status reported by the host in the received response. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_048: [ If the statusCode is NULL, the HTTPAPI_ExecuteRequest shall report not report any status. ]*/
+        if (statusCode)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_047: [ The HTTPAPI_ExecuteRequest shall report the status in the statusCode parameter. ]*/
+            *statusCode = ret;
+        }
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+    }
 
-	return result;
+    return result;
 }
 
 static HTTPAPI_RESULT RecieveContentInfoFromXIO(HTTP_HANDLE_DATA* http_instance, HTTP_HEADERS_HANDLE responseHeadersHandle, size_t* bodyLength, bool* chunked)
 {
-	HTTPAPI_RESULT result;
-	char    buf[TEMP_BUFFER_SIZE];
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
     const char* substr;
     char* whereIsColon;
     int lengthInMsg;
-	const char* ContentLength = "content-length:";
-	const int ContentLengthSize = 16;
-	const char* TransferEncoding = "transfer-encoding:";
-	const int TransferEncodingSize = 19;
-	const char* Chunked = "chunked";
-	const int ChunkedSize = 8;
+    const char* ContentLength = "content-length:";
+    const int ContentLengthSize = 16;
+    const char* TransferEncoding = "transfer-encoding:";
+    const int TransferEncodingSize = 19;
+    const char* Chunked = "chunked";
+    const int ChunkedSize = 8;
+
+    http_instance->is_io_error = 0;
 
-	//Read HTTP response headers
-	if (readLine(http_instance, buf, sizeof(buf)) < 0)
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-        /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+    //Read HTTP response headers
+    if (readLine(http_instance, buf, sizeof(buf)) < 0)
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
         result = HTTPAPI_READ_DATA_FAILED;
-	}
-	else
-	{
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
+    }
+    else
+    {
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
 
-		while (*buf && (result == HTTPAPI_OK))
-		{
-			if (InternStrnicmp(buf, ContentLength, ContentLengthSize) == 0)
-			{
-				substr = buf + ContentLengthSize - 1;
-				if (ParseStringToDecimal(substr, &lengthInMsg) != 1)
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-					result = HTTPAPI_READ_DATA_FAILED;
-				}
-				else
-				{
-					(*bodyLength) = (size_t)lengthInMsg;
-				}
-			}
-			else if (InternStrnicmp(buf, TransferEncoding, TransferEncodingSize) == 0)
-			{
-				substr = buf + TransferEncodingSize - 1;
+        while (*buf && (result == HTTPAPI_OK))
+        {
+            if (InternStrnicmp(buf, ContentLength, ContentLengthSize) == 0)
+            {
+                substr = buf + ContentLengthSize - 1;
+                if (ParseStringToDecimal(substr, &lengthInMsg) != 1)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                    result = HTTPAPI_READ_DATA_FAILED;
+                }
+                else
+                {
+                    (*bodyLength) = (size_t)lengthInMsg;
+                }
+            }
+            else if (InternStrnicmp(buf, TransferEncoding, TransferEncodingSize) == 0)
+            {
+                substr = buf + TransferEncodingSize - 1;
+
+                while (isspace(*substr)) substr++;
 
-				while (isspace(*substr)) substr++;
-				
-				if (InternStrnicmp(substr, Chunked, ChunkedSize) == 0)
-				{
-					(*chunked) = true;
-				}
-			}
+                if (InternStrnicmp(substr, Chunked, ChunkedSize) == 0)
+                {
+                    (*chunked) = true;
+                }
+            }
 
-			if (result == HTTPAPI_OK)
-			{
-				whereIsColon = strchr((char*)buf, ':');
-				/*Codes_SRS_HTTPAPI_COMPACT_21_049: [ If responseHeadersHandle is provide, the HTTPAPI_ExecuteRequest shall prepare a Response Header usign the HTTPHeaders_AddHeaderNameValuePair. ]*/
-				if (whereIsColon && (responseHeadersHandle != NULL))
-				{
-					*whereIsColon = '\0';
-					HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1);
-				}
+            if (result == HTTPAPI_OK)
+            {
+                whereIsColon = strchr((char*)buf, ':');
+                /*Codes_SRS_HTTPAPI_COMPACT_21_049: [ If responseHeadersHandle is provide, the HTTPAPI_ExecuteRequest shall prepare a Response Header usign the HTTPHeaders_AddHeaderNameValuePair. ]*/
+                if (whereIsColon && (responseHeadersHandle != NULL))
+                {
+                    *whereIsColon = '\0';
+                    HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1);
+                }
 
-				if (readLine(http_instance, buf, sizeof(buf)) < 0)
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-                    /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                if (readLine(http_instance, buf, sizeof(buf)) < 0)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
                     result = HTTPAPI_READ_DATA_FAILED;
-				}
-			}
-		}
-	}
+                }
+            }
+        }
+    }
 
-	return result;
+    return result;
 }
 
 static HTTPAPI_RESULT ReadHTTPResponseBodyFromXIO(HTTP_HANDLE_DATA* http_instance, size_t bodyLength, bool chunked, BUFFER_HANDLE responseContent)
 {
-	HTTPAPI_RESULT result;
-	char    buf[TEMP_BUFFER_SIZE];
-	const unsigned char* receivedContent;
+    HTTPAPI_RESULT result;
+    char    buf[TEMP_BUFFER_SIZE];
+    const unsigned char* receivedContent;
+
+    http_instance->is_io_error = 0;
 
-	//Read HTTP response body
-	if (!chunked)
-	{
-		if (bodyLength)
-		{
-			if (responseContent != NULL)
-			{
-				if (BUFFER_pre_build(responseContent, bodyLength) != 0)
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
-					result = HTTPAPI_ALLOC_FAILED;
-				}
-				else if (BUFFER_content(responseContent, &receivedContent) != 0)
-				{
-					(void)BUFFER_unbuild(responseContent);
+    //Read HTTP response body
+    if (!chunked)
+    {
+        if (bodyLength)
+        {
+            if (responseContent != NULL)
+            {
+                if (BUFFER_pre_build(responseContent, bodyLength) != 0)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                    result = HTTPAPI_ALLOC_FAILED;
+                }
+                else if (BUFFER_content(responseContent, &receivedContent) != 0)
+                {
+                    (void)BUFFER_unbuild(responseContent);
 
-					/*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
-					result = HTTPAPI_ALLOC_FAILED;
-				}
-				else if (readChunk(http_instance, (char*)receivedContent, bodyLength) < 0)
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-					result = HTTPAPI_READ_DATA_FAILED;
-				}
-				else
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-					result = HTTPAPI_OK;
-				}
-			}
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                    result = HTTPAPI_ALLOC_FAILED;
+                }
+                else if (readChunk(http_instance, (char*)receivedContent, bodyLength) < 0)
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                    result = HTTPAPI_READ_DATA_FAILED;
+                }
+                else
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+                    result = HTTPAPI_OK;
+                }
+            }
             else
             {
                 /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
                 if (skipN(http_instance, bodyLength) < 0)
                 {
-                    /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
                     result = HTTPAPI_READ_DATA_FAILED;
                 }
                 else
@@ -912,114 +1054,114 @@
                     result = HTTPAPI_OK;
                 }
             }
-		}
-		else
-		{
-			/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-			result = HTTPAPI_OK;
-		}
-	}
-	else
-	{
-		size_t size = 0;
-		/*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
-		result = HTTPAPI_OK;
-		while (result == HTTPAPI_OK)
-		{
-			size_t chunkSize;
-			if (readLine(http_instance, buf, sizeof(buf)) < 0)    // read [length in hex]/r/n
-			{
-				/*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
-                /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+            result = HTTPAPI_OK;
+        }
+    }
+    else
+    {
+        size_t size = 0;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
+        result = HTTPAPI_OK;
+        while (result == HTTPAPI_OK)
+        {
+            size_t chunkSize;
+            if (readLine(http_instance, buf, sizeof(buf)) < 0)    // read [length in hex]/r/n
+            {
+                /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
+                /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
                 result = HTTPAPI_READ_DATA_FAILED;
-			}
-			else if (ParseStringToHexadecimal(buf, &chunkSize) != 1)     // chunkSize is length of next line (/r/n is not counted)
-			{
-				//Cannot match string, error
-				/*Codes_SRS_HTTPAPI_COMPACT_21_055: [ If the HTTPAPI_ExecuteRequest cannot parser the recived message, it shall return HTTPAPI_RECEIVE_RESPONSE_FAILED. ]*/
-				result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
-			}
-			else if (chunkSize == 0)
-			{
-				// 0 length means next line is just '\r\n' and end of chunks
-				if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
-					|| buf[0] != '\r' || buf[1] != '\n') // skip /r/n
-				{
-					(void)BUFFER_unbuild(responseContent);
+            }
+            else if (ParseStringToHexadecimal(buf, &chunkSize) != 1)     // chunkSize is length of next line (/r/n is not counted)
+            {
+                //Cannot match string, error
+                /*Codes_SRS_HTTPAPI_COMPACT_21_055: [ If the HTTPAPI_ExecuteRequest cannot parser the recived message, it shall return HTTPAPI_RECEIVE_RESPONSE_FAILED. ]*/
+                result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
+            }
+            else if (chunkSize == 0)
+            {
+                // 0 length means next line is just '\r\n' and end of chunks
+                if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
+                    || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
+                {
+                    (void)BUFFER_unbuild(responseContent);
 
-					result = HTTPAPI_READ_DATA_FAILED;
-				}
-				break;
-			}
-			else
-			{
-				if (responseContent != NULL)
-				{
-					if (BUFFER_enlarge(responseContent, chunkSize) != 0)
-					{
-						(void)BUFFER_unbuild(responseContent);
+                    result = HTTPAPI_READ_DATA_FAILED;
+                }
+                break;
+            }
+            else
+            {
+                if (responseContent != NULL)
+                {
+                    if (BUFFER_enlarge(responseContent, chunkSize) != 0)
+                    {
+                        (void)BUFFER_unbuild(responseContent);
 
-						/*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
-						result = HTTPAPI_ALLOC_FAILED;
-					}
-					else if (BUFFER_content(responseContent, &receivedContent) != 0)
-					{
-						(void)BUFFER_unbuild(responseContent);
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                        result = HTTPAPI_ALLOC_FAILED;
+                    }
+                    else if (BUFFER_content(responseContent, &receivedContent) != 0)
+                    {
+                        (void)BUFFER_unbuild(responseContent);
 
-						/*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
-						result = HTTPAPI_ALLOC_FAILED;
-					}
-					else if (readChunk(http_instance, (char*)receivedContent + size, chunkSize) < 0)
-					{
-						result = HTTPAPI_READ_DATA_FAILED;
-					}
-				}
-				else
-				{
-					/*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
-					if (skipN(http_instance, chunkSize) < 0)
-					{
-                        /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
+                        result = HTTPAPI_ALLOC_FAILED;
+                    }
+                    else if (readChunk(http_instance, (char*)receivedContent + size, chunkSize) < 0)
+                    {
+                        result = HTTPAPI_READ_DATA_FAILED;
+                    }
+                }
+                else
+                {
+                    /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
+                    if (skipN(http_instance, chunkSize) < 0)
+                    {
+                        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
                         result = HTTPAPI_READ_DATA_FAILED;
-					}
-				}
+                    }
+                }
 
-				if (result == HTTPAPI_OK)
-				{
-					if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
-						|| buf[0] != '\r' || buf[1] != '\n') // skip /r/n
-					{
-						result = HTTPAPI_READ_DATA_FAILED;
-					}
-					size += chunkSize;
-				}
-			}
-		}
+                if (result == HTTPAPI_OK)
+                {
+                    if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
+                        || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
+                    {
+                        result = HTTPAPI_READ_DATA_FAILED;
+                    }
+                    size += chunkSize;
+                }
+            }
+        }
 
-	}
-	return result;
+    }
+    return result;
 }
 
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
 static bool validRequestType(HTTPAPI_REQUEST_TYPE requestType)
 {
-	bool result;
+    bool result;
 
-	if ((requestType == HTTPAPI_REQUEST_GET) ||
-		(requestType == HTTPAPI_REQUEST_POST) ||
-		(requestType == HTTPAPI_REQUEST_PUT) ||
-		(requestType == HTTPAPI_REQUEST_DELETE) ||
-		(requestType == HTTPAPI_REQUEST_PATCH))
-	{
-		result = true;
-	}
-	else
-	{
-		result = false;
-	}
+    if ((requestType == HTTPAPI_REQUEST_GET) ||
+        (requestType == HTTPAPI_REQUEST_POST) ||
+        (requestType == HTTPAPI_REQUEST_PUT) ||
+        (requestType == HTTPAPI_REQUEST_DELETE) ||
+        (requestType == HTTPAPI_REQUEST_PATCH))
+    {
+        result = true;
+    }
+    else
+    {
+        result = false;
+    }
 
-	return result;
+    return result;
 }
 
 /*Codes_SRS_HTTPAPI_COMPACT_21_021: [ The HTTPAPI_ExecuteRequest shall execute the http communtication with the provided host, sending a request and reciving the response. ]*/
@@ -1035,65 +1177,58 @@
     size_t  headersCount;
     size_t  bodyLength = 0;
     bool    chunked = false;
-	HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
+    HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
 
-	/*Codes_SRS_HTTPAPI_COMPACT_21_034: [ If there is no previous connection, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_039: [ If the relativePath is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_041: [ If the httpHeadersHandle is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_053: [ The HTTPAPI_ExecuteRequest shall produce a set of http header to send to the host. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_040: [ The request shall contain the http header provided in httpHeadersHandle parameter. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_054: [ If Http header maker cannot provide the number of headers, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
-	if (http_instance == NULL ||
+    /*Codes_SRS_HTTPAPI_COMPACT_21_034: [ If there is no previous connection, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_039: [ If the relativePath is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_041: [ If the httpHeadersHandle is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_053: [ The HTTPAPI_ExecuteRequest shall produce a set of http header to send to the host. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_040: [ The request shall contain the http header provided in httpHeadersHandle parameter. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_054: [ If Http header maker cannot provide the number of headers, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
+    if (http_instance == NULL ||
         relativePath == NULL ||
         httpHeadersHandle == NULL ||
-		!validRequestType(requestType) ||
+        !validRequestType(requestType) ||
         HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK)
     {
         result = HTTPAPI_INVALID_ARG;
         LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
     }
-	/*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
-	else if ((result = OpenXIOConnection(http_instance)) != HTTPAPI_OK)
-	{
-		LogError("Open HTTP connection failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
-	/*Codes_SRS_HTTPAPI_COMPACT_21_026: [ If the open process succeed, the HTTPAPI_ExecuteRequest shall send the request message to the host. ]*/
-	else if ((result = SendHeadsToXIO(http_instance, requestType, relativePath, httpHeadersHandle, headersCount)) != HTTPAPI_OK)
-	{
-		LogError("Send heads to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
-	/*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/
-	else if ((result = SendContentToXIO(http_instance, content, contentLength)) != HTTPAPI_OK)
-	{
-		LogError("Send content to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
-	/*Codes_SRS_HTTPAPI_COMPACT_21_030: [ At the end of the transmission, the HTTPAPI_ExecuteRequest shall receive the response from the host. ]*/
-	/*Codes_SRS_HTTPAPI_COMPACT_21_073: [ The message recived by the HTTPAPI_ExecuteRequest shall starts with a valid header. ]*/
-	else if ((result = RecieveHeaderFromXIO(http_instance, statusCode)) != HTTPAPI_OK)
-	{
-		LogError("Receive header from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
-	/*Codes_SRS_HTTPAPI_COMPACT_21_074: [ After the header, the message recieved by the HTTPAPI_ExecuteRequest can contain addition information about the content. ]*/
-	else if ((result = RecieveContentInfoFromXIO(http_instance, responseHeadersHandle, &bodyLength, &chunked)) != HTTPAPI_OK)
-	{
-		LogError("Receive content information from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
-	/*Codes_SRS_HTTPAPI_COMPACT_21_075: [ The message recieved by the HTTPAPI_ExecuteRequest can contain a body with the message content. ]*/
-	else if ((result = ReadHTTPResponseBodyFromXIO(http_instance, bodyLength, chunked, responseContent)) != HTTPAPI_OK)
-	{
-		LogError("Read HTTP response body from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-	}
+    /*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
+    else if ((result = OpenXIOConnection(http_instance)) != HTTPAPI_OK)
+    {
+        LogError("Open HTTP connection failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_026: [ If the open process succeed, the HTTPAPI_ExecuteRequest shall send the request message to the host. ]*/
+    else if ((result = SendHeadsToXIO(http_instance, requestType, relativePath, httpHeadersHandle, headersCount)) != HTTPAPI_OK)
+    {
+        LogError("Send heads to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/
+    else if ((result = SendContentToXIO(http_instance, content, contentLength)) != HTTPAPI_OK)
+    {
+        LogError("Send content to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_030: [ At the end of the transmission, the HTTPAPI_ExecuteRequest shall receive the response from the host. ]*/
+    /*Codes_SRS_HTTPAPI_COMPACT_21_073: [ The message recived by the HTTPAPI_ExecuteRequest shall starts with a valid header. ]*/
+    else if ((result = RecieveHeaderFromXIO(http_instance, statusCode)) != HTTPAPI_OK)
+    {
+        LogError("Receive header from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_074: [ After the header, the message recieved by the HTTPAPI_ExecuteRequest can contain addition information about the content. ]*/
+    else if ((result = RecieveContentInfoFromXIO(http_instance, responseHeadersHandle, &bodyLength, &chunked)) != HTTPAPI_OK)
+    {
+        LogError("Receive content information from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
+    /*Codes_SRS_HTTPAPI_COMPACT_21_075: [ The message recieved by the HTTPAPI_ExecuteRequest can contain a body with the message content. ]*/
+    else if ((result = ReadHTTPResponseBodyFromXIO(http_instance, bodyLength, chunked, responseContent)) != HTTPAPI_OK)
+    {
+        LogError("Read HTTP response body from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+    }
 
     conn_receive_discard_buffer(http_instance);
 
-    /*Codes_SRS_HTTPAPI_COMPACT_21_031: [ After receive the response, the HTTPAPI_ExecuteRequest shall close the transport connection with the host. ]*/
-	if ((http_instance != NULL) &&
-        (http_instance->is_connected != 0))
-    {
-        xio_close(http_instance->xio_handle, NULL, NULL);
-        http_instance->is_connected = 0;
-    }
 
     return result;
 }
@@ -1106,16 +1241,16 @@
     HTTPAPI_RESULT result;
     HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
 
-	if (
+    if (
         (http_instance == NULL) ||
         (optionName == NULL) ||
         (value == NULL)
         )
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_059: [ If the handle is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_060: [ If the optionName is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_061: [ If the value is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
-		result = HTTPAPI_INVALID_ARG;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_059: [ If the handle is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_060: [ If the optionName is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_061: [ If the value is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        result = HTTPAPI_INVALID_ARG;
     }
     else if (strcmp("TrustedCerts", optionName) == 0)
     {
@@ -1128,20 +1263,64 @@
         http_instance->certificate = (char*)malloc((len + 1) * sizeof(char));
         if (http_instance->certificate == NULL)
         {
-			/*SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
-			result = HTTPAPI_ALLOC_FAILED;
+            /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
             LogInfo("unable to allocate memory for the certificate in HTTPAPI_SetOption");
         }
         else
         {
-			/*SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
             (void)strcpy(http_instance->certificate, (const char*)value);
             result = HTTPAPI_OK;
         }
     }
+    else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
+    {
+        if (http_instance->x509ClientCertificate)
+        {
+            free(http_instance->x509ClientCertificate);
+        }
+
+        int len = (int)strlen((char*)value);
+        http_instance->x509ClientCertificate = (char*)malloc((len + 1) * sizeof(char));
+        if (http_instance->x509ClientCertificate == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+            LogInfo("unable to allocate memory for the client certificate in HTTPAPI_SetOption");
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(http_instance->x509ClientCertificate, (const char*)value);
+            result = HTTPAPI_OK;
+        }
+    }
+    else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
+    {
+        if (http_instance->x509ClientPrivateKey)
+        {
+            free(http_instance->x509ClientPrivateKey);
+        }
+
+        int len = (int)strlen((char*)value);
+        http_instance->x509ClientPrivateKey = (char*)malloc((len + 1) * sizeof(char));
+        if (http_instance->x509ClientPrivateKey == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+            LogInfo("unable to allocate memory for the client private key in HTTPAPI_SetOption");
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(http_instance->x509ClientPrivateKey, (const char*)value);
+            result = HTTPAPI_OK;
+        }
+    }
     else
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_063: [ If the HTTP do not support the optionName, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_063: [ If the HTTP do not support the optionName, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
         result = HTTPAPI_INVALID_ARG;
         LogInfo("unknown option %s", optionName);
     }
@@ -1156,16 +1335,16 @@
     size_t certLen;
     char* tempCert;
 
-	if (
+    if (
         (optionName == NULL) ||
         (value == NULL) ||
         (savedValue == NULL)
         )
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_067: [ If the optionName is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_068: [ If the value is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
-		/*Codes_SRS_HTTPAPI_COMPACT_21_069: [ If the savedValue is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
-		result = HTTPAPI_INVALID_ARG;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_067: [ If the optionName is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_068: [ If the value is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        /*Codes_SRS_HTTPAPI_COMPACT_21_069: [ If the savedValue is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        result = HTTPAPI_INVALID_ARG;
     }
     else if (strcmp("TrustedCerts", optionName) == 0)
     {
@@ -1173,21 +1352,55 @@
         tempCert = (char*)malloc((certLen + 1) * sizeof(char));
         if (tempCert == NULL)
         {
-			/*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
-			result = HTTPAPI_ALLOC_FAILED;
+            /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
         }
         else
         {
-			/*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
-			(void)strcpy(tempCert, (const char*)value);
+            /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(tempCert, (const char*)value);
+            *savedValue = tempCert;
+            result = HTTPAPI_OK;
+        }
+    }
+    else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
+    {
+        certLen = strlen((const char*)value);
+        tempCert = (char*)malloc((certLen + 1) * sizeof(char));
+        if (tempCert == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(tempCert, (const char*)value);
+            *savedValue = tempCert;
+            result = HTTPAPI_OK;
+        }
+    }
+    else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
+    {
+        certLen = strlen((const char*)value);
+        tempCert = (char*)malloc((certLen + 1) * sizeof(char));
+        if (tempCert == NULL)
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
+            result = HTTPAPI_ALLOC_FAILED;
+        }
+        else
+        {
+            /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
+            (void)strcpy(tempCert, (const char*)value);
             *savedValue = tempCert;
             result = HTTPAPI_OK;
         }
     }
     else
     {
-		/*Codes_SRS_HTTPAPI_COMPACT_21_071: [ If the HTTP do not support the optionName, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
-		result = HTTPAPI_INVALID_ARG;
+        /*Codes_SRS_HTTPAPI_COMPACT_21_071: [ If the HTTP do not support the optionName, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
+        result = HTTPAPI_INVALID_ARG;
         LogInfo("unknown option %s", optionName);
     }
     return result;