Nigel Rantor / azure_c_shared_utility

Fork of azure_c_shared_utility by Azure IoT

Files at this revision

API Documentation at this revision

Comitter:
AzureIoTClient
Date:
Fri Sep 09 13:38:26 2016 -0700
Parent:
10:1be0bc9a9deb
Child:
12:72001533b0e3
Commit message:
1.0.10

Changed in this revision

azure_c_shared_utility/base64.h Show annotated file Show diff for this revision Revisions of this file
azure_c_shared_utility/crt_abstractions.h Show annotated file Show diff for this revision Revisions of this file
azure_c_shared_utility/doublylinkedlist.h Show annotated file Show diff for this revision Revisions of this file
azure_c_shared_utility/map.h Show annotated file Show diff for this revision Revisions of this file
azure_c_shared_utility/refcount.h Show annotated file Show diff for this revision Revisions of this file
base64.c Show annotated file Show diff for this revision Revisions of this file
consolelogger.c Show annotated file Show diff for this revision Revisions of this file
constbuffer.c Show annotated file Show diff for this revision Revisions of this file
crt_abstractions.c Show annotated file Show diff for this revision Revisions of this file
httpapi_compact.c Show annotated file Show diff for this revision Revisions of this file
httpapiex.c Show annotated file Show diff for this revision Revisions of this file
httpheaders.c Show annotated file Show diff for this revision Revisions of this file
sastoken.c Show annotated file Show diff for this revision Revisions of this file
urlencode.c Show annotated file Show diff for this revision Revisions of this file
vector.c Show annotated file Show diff for this revision Revisions of this file
--- a/azure_c_shared_utility/base64.h	Fri Aug 26 12:59:40 2016 -0700
+++ b/azure_c_shared_utility/base64.h	Fri Sep 09 13:38:26 2016 -0700
@@ -21,6 +21,10 @@
 
 #include "azure_c_shared_utility/umock_c_prod.h"
 
+extern const char base64char[64];
+extern const char base64b16[16];
+extern const char base64b8[4];
+
 /**
  * @brief	Base64 encodes a buffer and returns the resulting string.
  *
--- a/azure_c_shared_utility/crt_abstractions.h	Fri Aug 26 12:59:40 2016 -0700
+++ b/azure_c_shared_utility/crt_abstractions.h	Fri Sep 09 13:38:26 2016 -0700
@@ -10,6 +10,7 @@
 #include <cstdio>
 #include <cstring>
 #include <cerrno>
+#include <cmath>
 extern "C" {
 #else
 #include <stdio.h>
@@ -124,7 +125,9 @@
 #else
 #ifdef __cplusplus
 /*C++ defines isnan... in C11*/
+extern "C++" {
 #define ISNAN std::isnan
+}
 #else
 #error unknown (or C89) compiler, provide ISNAN with the same meaning as isnan in C99 standard  
 #endif
--- a/azure_c_shared_utility/doublylinkedlist.h	Fri Aug 26 12:59:40 2016 -0700
+++ b/azure_c_shared_utility/doublylinkedlist.h	Fri Sep 09 13:38:26 2016 -0700
@@ -12,6 +12,7 @@
 #include <stddef.h>
 #endif
 
+#include <stdint.h>
 #include "azure_c_shared_utility/umock_c_prod.h"
 
 typedef struct DLIST_ENTRY_TAG
--- a/azure_c_shared_utility/map.h	Fri Aug 26 12:59:40 2016 -0700
+++ b/azure_c_shared_utility/map.h	Fri Sep 09 13:38:26 2016 -0700
@@ -9,6 +9,11 @@
 #ifndef MAP_H
 #define MAP_H
 
+#include "azure_c_shared_utility/macro_utils.h"
+#include "azure_c_shared_utility/strings.h"
+#include "azure_c_shared_utility/crt_abstractions.h"
+#include "azure_c_shared_utility/umock_c_prod.h"
+
 #ifdef __cplusplus
 #include <cstddef>
 extern "C"
@@ -17,12 +22,6 @@
 #include <stddef.h>
 #endif
 
-
-#include "azure_c_shared_utility/macro_utils.h"
-#include "azure_c_shared_utility/strings.h"
-#include "azure_c_shared_utility/crt_abstractions.h"
-#include "azure_c_shared_utility/umock_c_prod.h"
-
 #define MAP_RESULT_VALUES \
     MAP_OK, \
     MAP_ERROR, \
--- a/azure_c_shared_utility/refcount.h	Fri Aug 26 12:59:40 2016 -0700
+++ b/azure_c_shared_utility/refcount.h	Fri Sep 09 13:38:26 2016 -0700
@@ -27,6 +27,10 @@
 
 #include "azure_c_shared_utility/macro_utils.h"
 
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ == 201112) && (__STDC_NO_ATOMICS__!=1)
+#define REFCOUNT_USE_STD_ATOMIC 1
+#endif
+
 #define REFCOUNT_TYPE(type) \
 struct C2(C2(REFCOUNT_, type), _TAG)
 
@@ -41,7 +45,9 @@
 /*the newly allocated memory shall be free'd by free()*/
 /*and the ref counting is handled internally by the type in the _Create/ _Clone /_Destroy functions */
 
-#if defined(WIN32)
+#if defined(REFCOUNT_USE_STD_ATOMIC)
+#define COUNT_TYPE _Atomic uint32_t
+#elif defined(WIN32)
 #define COUNT_TYPE LONG
 #else
 #define COUNT_TYPE uint32_t
@@ -87,7 +93,7 @@
 */
 
 /*if macro DEC_REF returns DEC_RETURN_ZERO that means the ref count has reached zero.*/
-#if defined(__STDC_VERSION__) && (__STDC_VERSION__ == 201112) && (__STDC_NO_ATOMICS__!=1)
+#if defined(REFCOUNT_USE_STD_ATOMIC)
 #include <stdatomic.h>
 #define DEC_RETURN_ZERO (1)
 #define INC_REF(type, var) atomic_fetch_add((&((REFCOUNT_TYPE(type)*)var)->count), 1)
@@ -107,8 +113,8 @@
 #else
 #if defined(REFCOUNT_ATOMIC_DONTCARE)
 #define DEC_RETURN_ZERO (0)
-#define INC_REF(type, var) ++(&(((REFCOUNT_TYPE(type)*)var)->count))
-#define DEC_REF(type, var) --(&(((REFCOUNT_TYPE(type)*)var)->count))
+#define INC_REF(type, var) ++((((REFCOUNT_TYPE(type)*)var)->count))
+#define DEC_REF(type, var) --((((REFCOUNT_TYPE(type)*)var)->count))
 #else
 #error do not know how to atomically increment and decrement a uint32_t :(. Platform support needs to be extended to your platform.
 #endif /*defined(REFCOUNT_ATOMIC_DONTCARE)*/
--- a/base64.c	Fri Aug 26 12:59:40 2016 -0700
+++ b/base64.c	Fri Sep 09 13:38:26 2016 -0700
@@ -18,7 +18,7 @@
 #include "azure_c_shared_utility/base64.h"
 #include "azure_c_shared_utility/xlogging.h"
 
-static const char base64char[64] = {
+const char base64char[64] = {
     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
     'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
     'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
@@ -28,12 +28,12 @@
     '8', '9', '+', '/'
 };
 
-static const char base64b16[16] = {
+const char base64b16[16] = {
     'A', 'E', 'I', 'M', 'Q', 'U', 'Y', 'c', 'g', 'k',
     'o', 's', 'w', '0', '4', '8'
 };
 
-static const char base64b8[4] = {
+const char base64b8[4] = {
     'A', 'Q', 'g', 'w'
 };
 
--- a/consolelogger.c	Fri Aug 26 12:59:40 2016 -0700
+++ b/consolelogger.c	Fri Sep 09 13:38:26 2016 -0700
@@ -9,12 +9,6 @@
 #include <stdio.h>
 #include "azure_c_shared_utility/xlogging.h"
 
-#if defined _MSC_VER
-#define FUNC_NAME __FUNCDNAME__
-#else
-#define FUNC_NAME __func__
-#endif
-
 void consolelogger_log(LOG_CATEGORY log_category, const char* file, const char* func, const int line, unsigned int options, const char* format, ...)
 {
     va_list args;
--- a/constbuffer.c	Fri Aug 26 12:59:40 2016 -0700
+++ b/constbuffer.c	Fri Sep 09 13:38:26 2016 -0700
@@ -98,7 +98,9 @@
     }
     else
     {
-        result = (CONSTBUFFER_HANDLE_DATA*)CONSTBUFFER_Create_Internal(BUFFER_u_char(buffer), BUFFER_length(buffer));
+        size_t length = BUFFER_length(buffer);
+        unsigned char* rawBuffer = BUFFER_u_char(buffer);
+        result = (CONSTBUFFER_HANDLE_DATA*)CONSTBUFFER_Create_Internal(rawBuffer, length);
     }
     return (CONSTBUFFER_HANDLE)result;
 }
--- a/crt_abstractions.c	Fri Aug 26 12:59:40 2016 -0700
+++ b/crt_abstractions.c	Fri Sep 09 13:38:26 2016 -0700
@@ -443,14 +443,14 @@
     return result;
 }
 
-typedef enum
-{
-    FST_INFINITY,
-    FST_NAN,
-    FST_NUMBER,
-    FST_OVERFLOW,
-    FST_ERROR
-} FLOAT_STRING_TYPE;
+#define FLOAT_STRING_TYPE_VALUES    \
+            FST_INFINITY,           \
+            FST_NAN,                \
+            FST_NUMBER,             \
+            FST_OVERFLOW,           \
+            FST_ERROR
+
+DEFINE_ENUM(FLOAT_STRING_TYPE, FLOAT_STRING_TYPE_VALUES);
 
 static FLOAT_STRING_TYPE splitFloatString(const char* nptr, char** endptr, int *signal, double *fraction, int *exponential)
 {
--- a/httpapi_compact.c	Fri Aug 26 12:59:40 2016 -0700
+++ b/httpapi_compact.c	Fri Sep 09 13:38:26 2016 -0700
@@ -7,9 +7,8 @@
 #endif
 
 #include <stdio.h>
-#include <stdlib.h>
 #include <ctype.h>
-#include "azure_c_shared_utility/httpapi.h"
+#include "azure_c_shared_utility/gballoc.h"
 #include "azure_c_shared_utility/httpheaders.h"
 #include "azure_c_shared_utility/crt_abstractions.h"
 #include "azure_c_shared_utility/xlogging.h"
@@ -20,10 +19,14 @@
 #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_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"
+
 #define MAX_HOSTNAME     64
-#define TEMP_BUFFER_SIZE 4096
+#define TEMP_BUFFER_SIZE 1024
 
-#define CHAR_COUNT(A)   (sizeof(A) - 1)
 
 DEFINE_ENUM_STRINGS(HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES)
 
@@ -37,7 +40,6 @@
 
 typedef struct HTTP_HANDLE_DATA_TAG
 {
-    char            host[MAX_HOSTNAME];
     char*           certificate;
     XIO_HANDLE      xio_handle;
     size_t          received_bytes_count;
@@ -51,288 +53,399 @@
 /*this function only exists because some of platforms do not have sscanf. */
 static int ParseStringToDecimal(const char *src, int* dst)
 {
+	int result;
     char* next;
     (*dst) = strtol(src, &next, 0);
     if ((src == next) || ((((*dst) == LONG_MAX) || ((*dst) == LONG_MIN)) && (errno != 0)))
     {
-        return EOF;
+		result = EOF;
     }
-    return 1;
+	else
+	{
+		result = 1;
+	}
+    return result;
 }
 
 /*the following function does the same as sscanf(pos2, "%x", &sec)*/
 /*this function only exists because some of platforms do not have sscanf. This is not a full implementation; it only works with well-defined x numbers. */
 #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, int* dst)
+static int ParseStringToHexadecimal(const char *src, size_t* dst)
 {
-    if (src == NULL)
-        return EOF;
-    if (HEXA_DIGIT_VAL(*src) == -1)
-        return EOF;
-
+	int result;
     int digitVal;
-    (*dst) = 0;
-    while ((digitVal = HEXA_DIGIT_VAL(*src)) != -1)
-    {
-        (*dst) *= 0x10;
-        (*dst) += digitVal;
-        src++;
-    }
-    return 1;
+    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;
+	}
+    return result;
 }
 
 /*the following function does the same as sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &ret) */
 /*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)
+static int  ParseHttpResponse(const char* src, int* dst)
 {
-    const char* prefix = "HTTP/";
-    while ((*prefix) != '\0')
-    {
-        if ((*prefix) != (*src))
-            return EOF;
-        prefix++;
-        src++;
-    }
+	int result;
+	static const char HTTPPrefix[] = "HTTP/";
+    bool fail;
+    const char* runPrefix;
+
+	if ((src == NULL) || (dst == NULL))
+	{
+		result = EOF;
+	}
+	else
+	{
+		fail = false;
+		runPrefix = HTTPPrefix;
+
+		while((*runPrefix) != '\0')
+		{
+			if ((*runPrefix) != (*src))
+			{
+				fail = true;
+				break;
+			}
+			src++;
+			runPrefix++;
+		}
 
-    while ((*src) != '.')
-    {
-        if ((*src) == '\0')
-            return EOF;
-    }
+		if (!fail)
+		{
+			while ((*src) != '.')
+			{
+				if ((*src) == '\0')
+				{
+					fail = true;
+                    break;
+				}
+				src++;
+			}
+		}
 
-    while ((*src) != ' ')
-    {
-        if ((*src) == '\0')
-            return EOF;
-    }
+		if (!fail)
+		{
+			while ((*src) != ' ')
+			{
+				if ((*src) == '\0')
+				{
+					fail = true;
+                    break;
+				}
+				src++;
+			}
+		}
 
-    return 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_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_011: [ The HTTPAPI_CreateConnection shall create an http connection to the host specified by the hostName parameter. ]*/
 HTTP_HANDLE HTTPAPI_CreateConnection(const char* hostName)
 {
-    HTTP_HANDLE_DATA* handle = NULL;
+    HTTP_HANDLE_DATA* httpHandle;
+    TLSIO_CONFIG tlsio_config;
 
-    if (hostName)
-    {
-        handle = (HTTP_HANDLE_DATA*)malloc(sizeof(HTTP_HANDLE_DATA));
-        if (handle != NULL)
-        {
-            if (strcpy_s(handle->host, MAX_HOSTNAME, hostName) != 0)
-            {
-                LogError("HTTPAPI_CreateConnection::Could not strcpy_s");
-                free(handle);
-                handle = NULL;
-            }
-            else
-            {
-                TLSIO_CONFIG tlsio_config = { hostName, 443 };
-                handle->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config);
-                if (handle->xio_handle == NULL)
-                {
-                    LogError("HTTPAPI_CreateConnection::xio_create failed");
-                    free(handle->host);
-                    free(handle);
-                    handle = NULL;
-                }
-                else
-                {
-                    handle->is_connected = 0;
-                    handle->is_io_error = 0;
-                    handle->received_bytes_count = 0;
-                    handle->received_bytes = NULL;
-                    handle->send_all_result = SEND_ALL_RESULT_NOT_STARTED;
-                    handle->certificate = NULL;
-                }
-            }
-        }
-    }
-    else
-    {
-        LogInfo("HTTPAPI_CreateConnection:: null hostName parameter");
-    }
+	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.");
+		httpHandle = 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.");
+		httpHandle = NULL;
+	}
+	else
+	{
+		httpHandle = (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 (httpHandle == NULL)
+		{
+			LogError("There is no memory to control the http connection");
+		}
+		else
+		{
+			tlsio_config.hostname = hostName;
+			tlsio_config.port = 443;
 
-    return (HTTP_HANDLE)handle;
+			httpHandle->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 (httpHandle->xio_handle == NULL)
+			{
+				LogError("Create connection failed");
+				free(httpHandle);
+				httpHandle = NULL;
+			}
+			else
+			{
+				httpHandle->is_connected = 0;
+				httpHandle->is_io_error = 0;
+				httpHandle->received_bytes_count = 0;
+				httpHandle->received_bytes = NULL;
+				httpHandle->send_all_result = SEND_ALL_RESULT_NOT_STARTED;
+				httpHandle->certificate = NULL;
+			}
+		}
+	}
+
+	/*Codes_SRS_HTTPAPI_COMPACT_21_012: [ The HTTPAPI_CreateConnection shall return a non-NULL handle on success. ]*/
+	return (HTTP_HANDLE)httpHandle;
 }
 
 void HTTPAPI_CloseConnection(HTTP_HANDLE handle)
 {
-    HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)handle;
+    HTTP_HANDLE_DATA* httpHandle = (HTTP_HANDLE_DATA*)handle;
 
-    if (h)
+	/*Codes_SRS_HTTPAPI_COMPACT_21_020: [ If the connection handle is NULL, the HTTPAPI_CloseConnection shall not do anything. ]*/
+	if (httpHandle != NULL)
     {
-        if (h->xio_handle != NULL)
+		/*Codes_SRS_HTTPAPI_COMPACT_21_019: [ If there is no previous connection, the HTTPAPI_CloseConnection shall not do anything. ]*/
+		if (httpHandle->xio_handle != NULL)
         {
-            LogInfo("HTTPAPI_CloseConnection xio_destroy(); to %s", h->host);
-            xio_destroy(h->xio_handle);
+			/*Codes_SRS_HTTPAPI_COMPACT_21_017: [ The HTTPAPI_CloseConnection shall close the connection previously created in HTTPAPI_CreateConnection. ]*/
+			LogInfo("Close http connection.");
+            xio_destroy(httpHandle->xio_handle);
         }
 
-        if (h->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 (httpHandle->certificate)
         {
-            free(h->certificate);
+            free(httpHandle->certificate);
         }
 
-        free(h);
+        free(httpHandle);
     }
 }
 
 static void on_io_open_complete(void* context, IO_OPEN_RESULT open_result)
 {
-    HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)context;
-    if (open_result == IO_OPEN_OK)
-    {
-        h->is_connected = 1;
-        h->is_io_error = 0;
-    }
-    else
-    {
-        h->is_io_error = 1;
-    }
+    HTTP_HANDLE_DATA* httpHandle = (HTTP_HANDLE_DATA*)context;
+    
+    if (httpHandle != NULL)
+	{
+		if (open_result == IO_OPEN_OK)
+		{
+			httpHandle->is_connected = 1;
+			httpHandle->is_io_error = 0;
+		}
+		else
+		{
+			httpHandle->is_io_error = 1;
+		}
+	}
 }
 
-static int my_strnicmp(const char* s1, const char* s2, size_t n)
+#define TOLOWER(c) (((c>='A') && (c<='Z'))?c-'A'+'a':c)
+static int InternStrnicmp(const char* s1, const char* s2, size_t n)
 {
-    size_t i;
-    int result = 0;
+    int result;
 
-    for (i = 0; i < n; i++)
-    {
-        /* compute the difference between the chars */
-        result = tolower(s1[i]) - tolower(s2[i]);
+	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++;
+		}
 
-        /* break if we have a difference ... */
-        if ((result != 0) ||
-            /* ... or if we got to the end of one the strings */
-            (s1[i] == '\0') || (s2[i] == '\0'))
+        if ((*s2) != '\0')
         {
-            break;
+            result = -1;
         }
-    }
+	}
 
     return result;
 }
 
-static int my_stricmp(const char* s1, const char* s2)
-{
-    size_t i = 0;
-
-    while ((s1[i] != '\0') && (s2[i] != '\0'))
-    {
-        /* break if we have a difference ... */
-        if (tolower(s1[i]) != tolower(s2[i]))
-        {
-            break;
-        }
-
-        i++;
-    }
-
-    /* if we broke because we are at end of string this will yield 0 */
-    /* if we broke because there was a difference this will yield non-zero  */
-    return tolower(s1[i]) - tolower(s2[i]);
-}
-
 static void on_bytes_received(void* context, const unsigned char* buffer, size_t size)
 {
-    HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)context;
+    unsigned char* new_received_bytes;
+    HTTP_HANDLE_DATA* httpHandle = (HTTP_HANDLE_DATA*)context;
+
+    if (httpHandle != NULL)
+	{
 
-    /* Here we got some bytes so we'll buffer them so the receive functions can consumer it */
-    unsigned char* new_received_bytes = (unsigned char*)realloc(h->received_bytes, h->received_bytes_count + size);
-    if (new_received_bytes == NULL)
-    {
-        h->is_io_error = 1;
-        LogError("on_bytes_received: Error allocating memory for received data");
-    }
-    else
-    {
-        h->received_bytes = new_received_bytes;
-        (void)memcpy(h->received_bytes + h->received_bytes_count, buffer, size);
-        h->received_bytes_count += size;
-    }
+        if (buffer == NULL)
+        {
+            httpHandle->is_io_error = 1;
+            LogError("on_bytes_received: NULL pointer error");
+        }
+        else
+        {
+            /* Here we got some bytes so we'll buffer them so the receive functions can consumer it */
+            new_received_bytes = (unsigned char*)realloc(httpHandle->received_bytes, httpHandle->received_bytes_count + size);
+            if (new_received_bytes == NULL)
+            {
+                httpHandle->is_io_error = 1;
+                LogError("on_bytes_received: Error allocating memory for received data");
+            }
+            else
+            {
+                httpHandle->received_bytes = new_received_bytes;
+                if (memcpy(httpHandle->received_bytes + httpHandle->received_bytes_count, buffer, size) == NULL)
+                {
+                    httpHandle->is_io_error = 1;
+                    LogError("on_bytes_received: Error copping received data to the HTTP bufffer");
+                }
+                else
+                {
+                    httpHandle->received_bytes_count += size;
+                }
+            }
+        }
+	}
 }
 
 static void on_io_error(void* context)
 {
-    HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)context;
-    h->is_io_error = 1;
-    LogError("on_io_error: Error signalled by underlying IO");
+    HTTP_HANDLE_DATA* httpHandle = (HTTP_HANDLE_DATA*)context;
+    if (httpHandle != NULL)
+	{
+		httpHandle->is_io_error = 1;
+		LogError("on_io_error: Error signalled by underlying IO");
+	}
 }
 
 static int conn_receive(HTTP_HANDLE_DATA* http_instance, char* buffer, int count)
 {
-    int result = 0;
+    int result;
 
-    if (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
-    {
-        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("conn_receive: 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(1);
-        }
-    }
+			ThreadAPI_Sleep(1);
+		}
+	}
 
     return result;
 }
 
+static void conn_receive_discard_buffer(HTTP_HANDLE_DATA* http_instance)
+{
+    if (http_instance->received_bytes != NULL)
+    {
+        free(http_instance->received_bytes);
+        http_instance->received_bytes = NULL;
+    }
+    http_instance->received_bytes_count = 0;
+}
+
+
 static void on_send_complete(void* context, IO_SEND_RESULT send_result)
 {
-    /* If a send is complete we'll simply signal this by changing the send all state */
     HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
-    if (send_result == IO_SEND_OK)
-    {
-        http_instance->send_all_result = SEND_ALL_RESULT_OK;
-    }
-    else
-    {
-        http_instance->send_all_result = SEND_ALL_RESULT_ERROR;
-    }
+    
+    if (http_instance != NULL)
+	{
+		/* If a send is complete we'll simply signal this by changing the send all state */
+		if (send_result == IO_SEND_OK)
+		{
+			http_instance->send_all_result = SEND_ALL_RESULT_OK;
+		}
+		else
+		{
+			http_instance->send_all_result = SEND_ALL_RESULT_ERROR;
+		}
+	}
 }
 
-static int conn_send_all(HTTP_HANDLE_DATA* http_instance, char* buffer, int count)
+static int conn_send_all(HTTP_HANDLE_DATA* http_instance, const unsigned char* buffer, size_t count)
 {
     int result;
 
-    if (count < 0)
-    {
+	if ((http_instance == NULL) || (buffer == 0) || (count < (size_t)0))
+	{
+        LogError("conn_send_all: %s", ((http_instance == NULL) ? "Invalid HTTP instance" : "Invalid HTTP buffer"));
         result = -1;
     }
     else
@@ -340,6 +453,7 @@
         http_instance->send_all_result = SEND_ALL_RESULT_PENDING;
         if (xio_send(http_instance->xio_handle, buffer, count, on_send_complete, http_instance) != 0)
         {
+            LogError("conn_send_all: xio failed sending data");
             result = -1;
         }
         else
@@ -347,8 +461,6 @@
             /* We have to loop in here until all bytes are sent or we encounter an error. */
             while (1)
             {
-                xio_dowork(http_instance->xio_handle);
-
                 /* If we got an error signalled from the underlying IO we simply report it up */
                 if (http_instance->is_io_error)
                 {
@@ -361,6 +473,8 @@
                     break;
                 }
 
+                xio_dowork(http_instance->xio_handle);
+
                 /* We yield the CPU for a bit so others can do their work */
                 ThreadAPI_Sleep(1);
             }
@@ -378,7 +492,7 @@
                     break;
 
                 case SEND_ALL_RESULT_OK:
-                    result = count;
+                    result = (int)count;
                     break;
 
                 case SEND_ALL_RESULT_ERROR:
@@ -394,41 +508,75 @@
 static int readLine(HTTP_HANDLE_DATA* http_instance, char* buf, const size_t size)
 {
     // reads until \r\n is encountered. writes in buf all the characters
-    char* p = buf;
+	int result;
+    char* substr = buf;
     char  c;
-    if (conn_receive(http_instance, &c, 1) < 0)
-        return -1;
-    while (c != '\r') {
-        if ((p - buf + 1) >= (int)size)
-            return -1;
-        *p++ = c;
-        if (conn_receive(http_instance, &c, 1) < 0)
-            return -1;
+
+	if (conn_receive(http_instance, &c, 1) < 0)
+	{
+        result = -1;
+	}
+	else
+	{
+		result = 0;
+		while (c != '\r') 
+		{
+			if ((substr - buf + 1) >= (int)size)
+			{
+                result = -1;
+                conn_receive_discard_buffer(http_instance);
+                break;
+			}
+            else
+            {
+                *substr++ = c;
+            }
+			
+			if (conn_receive(http_instance, &c, 1) < 0)
+			{
+				result = -1;
+				break;
+			}
+		}
+
+		if (result != -1)
+		{
+			*substr = 0;
+			if (conn_receive(http_instance, &c, 1) < 0 || c != '\n') // skip \n
+			{
+				result = -1;
+			}
+		}
+
+        if (result != -1)
+        {
+            result = (int)(substr - buf);
+        }
     }
-    *p = 0;
-    if (conn_receive(http_instance, &c, 1) < 0 || c != '\n') // skip \n
-        return -1;
-    return p - buf;
+
+	return result;
 }
 
 static int readChunk(HTTP_HANDLE_DATA* http_instance, char* buf, size_t size)
 {
-    size_t cur, offset;
+    int cur, offset;
 
     // read content with specified length, even if it is received
     // only in chunks due to fragmentation in the networking layer.
     // returns -1 in case of error.
     offset = 0;
-    while (size > 0)
+    while (size > (size_t)0)
     {
-        cur = conn_receive(http_instance, buf + offset, size);
+        cur = conn_receive(http_instance, buf + offset, (int)size);
 
         // end of stream reached
-        if (cur == 0)
-            return offset;
+		if (cur == 0)
+		{
+			break;
+		}
 
         // read cur bytes (might be less than requested)
-        size -= cur;
+        size -= (size_t)cur;
         offset += cur;
     }
 
@@ -437,23 +585,444 @@
 
 static int skipN(HTTP_HANDLE_DATA* http_instance, size_t n, char* buf, size_t size)
 {
-    size_t org = n;
+    int org = (int)n;
     // read and abandon response content with specified length
     // returns -1 in case of error.
     while (n > size)
     {
-        if (readChunk(http_instance, (char*)buf, size) < 0)
-            return -1;
+		if (readChunk(http_instance, (char*)buf, size) < 0)
+		{
+			org = -1;
+			break;
+		}
 
         n -= size;
     }
 
-    if (readChunk(http_instance, (char*)buf, n) < 0)
-        return -1;
+	if (org >= 0)
+	{
+		if (readChunk(http_instance, (char*)buf, n) < 0)
+		{
+			org = -1;
+		}
+	}
 
     return org;
 }
 
+
+/*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* httpHandle)
+{
+	HTTPAPI_RESULT result;
+
+	if (httpHandle->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 ((httpHandle->certificate != NULL) &&
+			(xio_setoption(httpHandle->xio_handle, "TrustedCerts", httpHandle->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(httpHandle->xio_handle, on_io_open_complete, httpHandle, on_bytes_received, httpHandle, on_io_error, httpHandle) != 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 ((httpHandle->is_connected == 0) &&
+					(httpHandle->is_io_error == 0))
+				{
+					xio_dowork(httpHandle->xio_handle);
+					LogInfo("Waiting for TLS connection");
+					ThreadAPI_Sleep(1);
+				}
+			}
+		}
+	}
+	
+	if ((httpHandle->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;
+}
+
+/*Codes_SRS_HTTPAPI_COMPACT_21_035: [ The HTTPAPI_ExecuteRequest shall execute resquest for types `GET`, `POST`, `PUT`, `DELETE`, `PATCH`. ]*/
+const char httpapiRequestString[5][7] = { "GET", "POST", "PUT", "DELETE", "PATCH" };
+const char* get_request_type(HTTPAPI_REQUEST_TYPE requestType)
+{
+    return (const char*)httpapiRequestString[requestType];
+}
+
+/*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* httpHandle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, HTTP_HEADERS_HANDLE httpHeadersHandle, size_t headersCount)
+{
+	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 (conn_send_all(httpHandle, (const unsigned char*)buf, strlen(buf)) < 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
+	{
+		//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 (conn_send_all(httpHandle, (const unsigned char*)header, strlen(header)) < 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;
+				}
+				if (conn_send_all(httpHandle, (const unsigned char*)"\r\n", (size_t)2) < 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);
+			}
+		}
+
+		//Close headers
+		if (conn_send_all(httpHandle, (const unsigned char*)"\r\n", (size_t)2) < 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;
+		}
+	}
+	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* httpHandle, const unsigned char* content, size_t contentLength)
+{
+	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 (conn_send_all(httpHandle, content, contentLength) < 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;
+}
+
+/*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* httpHandle, unsigned int* statusCode)
+{
+	HTTPAPI_RESULT result;
+	char    buf[TEMP_BUFFER_SIZE];
+	int     ret;
+
+	//Receive response
+	if (readLine(httpHandle, 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. ]*/
+		result = HTTPAPI_READ_DATA_FAILED;
+	}
+	//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("HTTPAPI_ExecuteRequest::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;
+	}
+
+	return result;
+}
+
+static HTTPAPI_RESULT RecieveContentInfoFromXIO(HTTP_HANDLE_DATA* httpHandle, HTTP_HEADERS_HANDLE responseHeadersHandle, size_t* bodyLength, bool* chunked)
+{
+	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;
+
+	//Read HTTP response headers
+	if (readLine(httpHandle, 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. ]*/
+		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;
+
+		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++;
+				
+				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 (readLine(httpHandle, 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. ]*/
+					result = HTTPAPI_READ_DATA_FAILED;
+				}
+			}
+		}
+	}
+
+	return result;
+}
+
+static HTTPAPI_RESULT ReadHTTPResponseBodyFromXIO(HTTP_HANDLE_DATA* httpHandle, size_t bodyLength, bool chunked, BUFFER_HANDLE responseContent)
+{
+	HTTPAPI_RESULT result;
+	char    buf[TEMP_BUFFER_SIZE];
+	const unsigned char* receivedContent;
+
+	//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(httpHandle, (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. ]*/
+				(void)skipN(httpHandle, bodyLength, buf, sizeof(buf));
+				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(httpHandle, 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. ]*/
+				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(httpHandle, (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);
+
+						/*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(httpHandle, (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(httpHandle, chunkSize, buf, sizeof(buf)) < 0)
+					{
+						result = HTTPAPI_READ_DATA_FAILED;
+					}
+				}
+
+				if (result == HTTPAPI_OK)
+				{
+					if (readChunk(httpHandle, (char*)buf, (size_t)2) < 0
+						|| buf[0] != '\r' || buf[1] != '\n') // skip /r/n
+					{
+						result = HTTPAPI_READ_DATA_FAILED;
+					}
+					size += chunkSize;
+				}
+			}
+		}
+
+	}
+	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;
+
+	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;
+}
+
+/*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. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_050: [ If there is a content in the response, the HTTPAPI_ExecuteRequest shall copy it in the responseContent buffer. ]*/
 //Note: This function assumes that "Host:" and "Content-Length:" headers are setup
 //      by the caller of HTTPAPI_ExecuteRequest() (which is true for httptransport.c).
 HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
@@ -461,403 +1030,163 @@
     size_t contentLength, unsigned int* statusCode,
     HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
 {
-
-    HTTPAPI_RESULT result;
+    HTTPAPI_RESULT result = HTTPAPI_ERROR;
     size_t  headersCount;
-    char    buf[TEMP_BUFFER_SIZE];
-    int     ret;
     size_t  bodyLength = 0;
     bool    chunked = false;
-    const unsigned char* receivedContent;
+	HTTP_HANDLE_DATA* httpHandle = (HTTP_HANDLE_DATA*)handle;
 
-    const char* method = (requestType == HTTPAPI_REQUEST_GET) ? "GET"
-        : (requestType == HTTPAPI_REQUEST_POST) ? "POST"
-        : (requestType == HTTPAPI_REQUEST_PUT) ? "PUT"
-        : (requestType == HTTPAPI_REQUEST_DELETE) ? "DELETE"
-        : (requestType == HTTPAPI_REQUEST_PATCH) ? "PATCH"
-        : NULL;
-
-    if (handle == 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 (httpHandle == NULL ||
         relativePath == NULL ||
         httpHeadersHandle == NULL ||
-        method == NULL ||
+		!validRequestType(requestType) ||
         HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK)
     {
         result = HTTPAPI_INVALID_ARG;
         LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-        goto exit;
     }
-
-    HTTP_HANDLE_DATA* httpHandle = (HTTP_HANDLE_DATA*)handle;
-
-    if (handle->is_connected == 0)
-    {
-        // Load the certificate
-        if ((httpHandle->certificate != NULL) &&
-			(xio_setoption(httpHandle->xio_handle, "TrustedCerts", httpHandle->certificate) != 0))
-        {
-            result = HTTPAPI_ERROR;
-            LogError("Could not load certificate (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-            goto exit;
-        }
+	/*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(httpHandle)) != 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(httpHandle, 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(httpHandle, 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(httpHandle, 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(httpHandle, 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(httpHandle, bodyLength, chunked, responseContent)) != HTTPAPI_OK)
+	{
+		LogError("Read HTTP response body from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
+	}
 
-        // Make the connection
-        if (xio_open(httpHandle->xio_handle, on_io_open_complete, httpHandle, on_bytes_received, httpHandle, on_io_error, httpHandle) != 0)
-        {
-            result = HTTPAPI_ERROR;
-            LogError("Could not connect (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-            goto exit;
-        }
-
-        while (1)
-        {
-            xio_dowork(httpHandle->xio_handle);
-            if ((handle->is_connected == 1) ||
-                (handle->is_io_error == 1))
-            {
-                break;
-            }
-
-            ThreadAPI_Sleep(1);
-        }
-    }
-
-    //Send request
-    if ((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", method, relativePath)) < 0
-        || ret >= sizeof(buf))
-    {
-        result = HTTPAPI_STRING_PROCESSING_ERROR;
-        LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-        goto exit;
-    }
-    if (conn_send_all(httpHandle, buf, strlen(buf)) < 0)
+	/*Codes_SRS_HTTPAPI_COMPACT_21_031: [ After receive the response, the HTTPAPI_ExecuteRequest shall close the transport connection with the host. ]*/
+	if ((httpHandle != NULL) &&
+        (httpHandle->is_connected != 0))
     {
-        result = HTTPAPI_SEND_REQUEST_FAILED;
-        LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-        goto exit;
-    }
-
-    //Send default headers
-    for (size_t i = 0; i < headersCount; i++)
-    {
-        char* header;
-        if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &header) != HTTP_HEADERS_OK)
-        {
-            result = HTTPAPI_HTTP_HEADERS_FAILED;
-            LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-            goto exit;
-        }
-        if (conn_send_all(httpHandle, header, strlen(header)) < 0)
-        {
-            result = HTTPAPI_SEND_REQUEST_FAILED;
-            LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-            free(header);
-            goto exit;
-        }
-        if (conn_send_all(httpHandle, "\r\n", 2) < 0)
-        {
-            result = HTTPAPI_SEND_REQUEST_FAILED;
-            LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-            free(header);
-            goto exit;
-        }
-        free(header);
-    }
-
-    //Close headers
-    if (conn_send_all(httpHandle, "\r\n", 2) < 0)
-    {
-        result = HTTPAPI_SEND_REQUEST_FAILED;
-        LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-        goto exit;
-    }
-
-    //Send data (if available)
-    if (content && contentLength > 0)
-    {
-        if (conn_send_all(httpHandle, (char*)content, contentLength) < 0)
-        {
-            result = HTTPAPI_SEND_REQUEST_FAILED;
-            LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-            goto exit;
-        }
+        conn_receive_discard_buffer(httpHandle);
+        xio_close(httpHandle->xio_handle, NULL, NULL);
+        httpHandle->is_connected = 0;
     }
 
-    //Receive response
-    if (readLine(httpHandle, buf, sizeof(buf)) < 0)
-    {
-        result = HTTPAPI_READ_DATA_FAILED;
-        LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-        goto exit;
-    }
+    return result;
+}
 
-    //Parse HTTP response
-    if (ParseHttpResponse(buf, &ret) != 1)
-    {
-        //Cannot match string, error
-        LogInfo("HTTPAPI_ExecuteRequest::Not a correct HTTP answer=%s", buf);
-        result = HTTPAPI_READ_DATA_FAILED;
-        LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-        goto exit;
-    }
-    if (statusCode)
-        *statusCode = ret;
+/*Codes_SRS_HTTPAPI_COMPACT_21_056: [ The HTTPAPI_SetOption shall change the HTTP options. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_057: [ The HTTPAPI_SetOption shall recieve a handle that identiry the HTTP connection. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_058: [ The HTTPAPI_SetOption shall recieve the option as a pair optionName/value. ]*/
+HTTPAPI_RESULT HTTPAPI_SetOption(HTTP_HANDLE handle, const char* optionName, const void* value)
+{
+    HTTPAPI_RESULT result;
+    HTTP_HANDLE_DATA* httpHandle = (HTTP_HANDLE_DATA*)handle;
 
-    //Read HTTP response headers
-    if (readLine(httpHandle, buf, sizeof(buf)) < 0)
+	if (
+        (httpHandle == NULL) ||
+        (optionName == NULL) ||
+        (value == NULL)
+        )
     {
-        result = HTTPAPI_READ_DATA_FAILED;
-        LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-        goto exit;
+		/*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;
     }
-
-    while (buf[0])
+    else if (strcmp("TrustedCerts", optionName) == 0)
     {
-        const char ContentLength[] = "content-length:";
-        const char TransferEncoding[] = "transfer-encoding:";
-
-        if (my_strnicmp(buf, ContentLength, CHAR_COUNT(ContentLength)) == 0)
+        if (httpHandle->certificate)
         {
-            if (ParseStringToDecimal(buf + CHAR_COUNT(ContentLength), &bodyLength) != 1)
-            {
-                result = HTTPAPI_READ_DATA_FAILED;
-                LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                goto exit;
-            }
-        }
-        else if (my_strnicmp(buf, TransferEncoding, CHAR_COUNT(TransferEncoding)) == 0)
-        {
-            const char* p = buf + CHAR_COUNT(TransferEncoding);
-            while (isspace(*p)) p++;
-            if (my_stricmp(p, "chunked") == 0)
-                chunked = true;
+            free(httpHandle->certificate);
         }
 
-        char* whereIsColon = strchr((char*)buf, ':');
-        if (whereIsColon && responseHeadersHandle != NULL)
-        {
-            *whereIsColon = '\0';
-            HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1);
-        }
-
-        if (readLine(httpHandle, buf, sizeof(buf)) < 0)
-        {
-            result = HTTPAPI_READ_DATA_FAILED;
-            LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-            goto exit;
-        }
-    }
-
-    //Read HTTP response body
-    if (!chunked)
-    {
-        if (bodyLength)
+        int len = (int)strlen((char*)value);
+        httpHandle->certificate = (char*)malloc((len + 1) * sizeof(char));
+        if (httpHandle->certificate == NULL)
         {
-            if (responseContent != NULL)
-            {
-                if (BUFFER_pre_build(responseContent, bodyLength) != 0)
-                {
-                    result = HTTPAPI_ALLOC_FAILED;
-                    LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                }
-                else if (BUFFER_content(responseContent, &receivedContent) != 0)
-                {
-                    (void)BUFFER_unbuild(responseContent);
-
-                    result = HTTPAPI_ALLOC_FAILED;
-                    LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                }
-
-                if (readChunk(httpHandle, (char*)receivedContent, bodyLength) < 0)
-                {
-                    result = HTTPAPI_READ_DATA_FAILED;
-                    LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                    goto exit;
-                }
-                else
-                {
-                    result = HTTPAPI_OK;
-                }
-            }
-            else
-            {
-                (void)skipN(httpHandle, bodyLength, buf, sizeof(buf));
-                result = HTTPAPI_OK;
-            }
+			/*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. ]*/
+            (void)strcpy(httpHandle->certificate, (const char*)value);
             result = HTTPAPI_OK;
         }
     }
     else
     {
-        size_t size = 0;
-        result = HTTPAPI_OK;
-        for (;;)
-        {
-            int chunkSize;
-            if (readLine(httpHandle, buf, sizeof(buf)) < 0)    // read [length in hex]/r/n
-            {
-                result = HTTPAPI_READ_DATA_FAILED;
-                LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                goto exit;
-            }
-            if (ParseStringToHexadecimal(buf, &chunkSize) != 1)     // chunkSize is length of next line (/r/n is not counted)
-            {
-                //Cannot match string, error
-                result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
-                LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                goto exit;
-            }
-
-            if (chunkSize == 0)
-            {
-                // 0 length means next line is just '\r\n' and end of chunks
-                if (readChunk(httpHandle, (char*)buf, 2) < 0
-                    || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
-                {
-                    (void)BUFFER_unbuild(responseContent);
-
-                    result = HTTPAPI_READ_DATA_FAILED;
-                    LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                    goto exit;
-                }
-                break;
-            }
-            else
-            {
-                if (responseContent != NULL)
-                {
-                    if (BUFFER_enlarge(responseContent, chunkSize) != 0)
-                    {
-                        (void)BUFFER_unbuild(responseContent);
-
-                        result = HTTPAPI_ALLOC_FAILED;
-                        LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                    }
-                    else if (BUFFER_content(responseContent, &receivedContent) != 0)
-                    {
-                        (void)BUFFER_unbuild(responseContent);
-
-                        result = HTTPAPI_ALLOC_FAILED;
-                        LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                    }
-
-                    if (readChunk(httpHandle, (char*)receivedContent + size, chunkSize) < 0)
-                    {
-                        result = HTTPAPI_READ_DATA_FAILED;
-                        LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                        goto exit;
-                    }
-                }
-                else
-                {
-                    if (skipN(httpHandle, chunkSize, buf, sizeof(buf)) < 0)
-                    {
-                        result = HTTPAPI_READ_DATA_FAILED;
-                        LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                        goto exit;
-                    }
-                }
-
-                if (readChunk(httpHandle, (char*)buf, 2) < 0
-                    || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
-                {
-                    result = HTTPAPI_READ_DATA_FAILED;
-                    LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
-                    goto exit;
-                }
-                size += chunkSize;
-            }
-        }
-
-    }
-
-exit:
-    if ((handle != NULL) &&
-        (handle->is_io_error != 0))
-    {
-        xio_close(handle->xio_handle, NULL, NULL);
-        handle->is_connected = 0;
-    }
-
-    return result;
-}
-
-HTTPAPI_RESULT HTTPAPI_SetOption(HTTP_HANDLE handle, const char* optionName, const void* value)
-{
-    HTTPAPI_RESULT result;
-    if (
-        (handle == NULL) ||
-        (optionName == NULL) ||
-        (value == NULL)
-        )
-    {
+		/*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;
-        LogError("invalid parameter (NULL) passed to HTTPAPI_SetOption");
-    }
-    else if (strcmp("TrustedCerts", optionName) == 0)
-    {
-        HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)handle;
-        if (h->certificate)
-        {
-            free(h->certificate);
-        }
-
-        int len = strlen((char*)value);
-        h->certificate = (char*)malloc(len + 1);
-        if (h->certificate == NULL)
-        {
-            result = HTTPAPI_ERROR;
-            LogError("unable to allocate certificate memory in HTTPAPI_SetOption");
-        }
-        else
-        {
-            (void)strcpy(h->certificate, (const char*)value);
-            result = HTTPAPI_OK;
-        }
-    }
-    else
-    {
-        result = HTTPAPI_INVALID_ARG;
-        LogError("unknown option %s", optionName);
+        LogInfo("unknown option %s", optionName);
     }
     return result;
 }
 
+/*Codes_SRS_HTTPAPI_COMPACT_21_065: [ The HTTPAPI_CloneOption shall provide the means to clone the HTTP option. ]*/
+/*Codes_SRS_HTTPAPI_COMPACT_21_066: [ The HTTPAPI_CloneOption shall return a clone of the value identified by the optionName. ]*/
 HTTPAPI_RESULT HTTPAPI_CloneOption(const char* optionName, const void* value, const void** savedValue)
 {
     HTTPAPI_RESULT result;
-    if (
+    size_t certLen;
+    char* tempCert;
+
+	if (
         (optionName == NULL) ||
         (value == NULL) ||
         (savedValue == NULL)
         )
     {
-        result = HTTPAPI_INVALID_ARG;
-        LogError("invalid argument(NULL) passed to HTTPAPI_CloneOption");
+		/*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)
     {
-        size_t certLen = strlen((const char*)value);
-        char* tempCert = (char*)malloc(certLen+1);
+        certLen = strlen((const char*)value);
+        tempCert = (char*)malloc((certLen + 1) * sizeof(char));
         if (tempCert == NULL)
         {
-            result = HTTPAPI_INVALID_ARG;
-            LogError("unable to allocate certificate memory in HTTPAPI_CloneOption");
+			/*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
         {
-            (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
     {
-        result = HTTPAPI_INVALID_ARG;
-        LogError("unknown option %s", optionName);
+		/*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;
 }
--- a/httpapiex.c	Fri Aug 26 12:59:40 2016 -0700
+++ b/httpapiex.c	Fri Sep 09 13:38:26 2016 -0700
@@ -409,7 +409,9 @@
                         }
                         case 2:
                         {
-                            if (HTTPAPI_ExecuteRequest(handleData->httpHandle, requestType, toBeUsedRelativePath, toBeUsedRequestHttpHeadersHandle, BUFFER_u_char(toBeUsedRequestContent), BUFFER_length(toBeUsedRequestContent), toBeUsedStatusCode, toBeUsedResponseHttpHeadersHandle, toBeUsedResponseContent) != HTTPAPI_OK)
+                            size_t length = BUFFER_length(toBeUsedRequestContent);
+                            unsigned char* buffer = BUFFER_u_char(toBeUsedRequestContent);
+                            if (HTTPAPI_ExecuteRequest(handleData->httpHandle, requestType, toBeUsedRelativePath, toBeUsedRequestHttpHeadersHandle, buffer, length, toBeUsedStatusCode, toBeUsedResponseHttpHeadersHandle, toBeUsedResponseContent) != HTTPAPI_OK)
                             {
                                 goOn = false;
                             }
--- a/httpheaders.c	Fri Aug 26 12:59:40 2016 -0700
+++ b/httpheaders.c	Fri Sep 09 13:38:26 2016 -0700
@@ -13,12 +13,6 @@
 #include "azure_c_shared_utility/crt_abstractions.h"
 #include "azure_c_shared_utility/xlogging.h"
 
-static const char COLON_AND_SPACE[] = { ':', ' ', '\0' };
-#define COLON_AND_SPACE_LENGTH  ((sizeof(COLON_AND_SPACE)/sizeof(COLON_AND_SPACE[0]))-1)
-
-static const char COMMA_AND_SPACE[] = { ',', ' ', '\0' };
-#define COMMA_AND_SPACE_LENGTH  ((sizeof(COMMA_AND_SPACE)/sizeof(COMMA_AND_SPACE[0]))-1)
-
 DEFINE_ENUM_STRINGS(HTTP_HEADERS_RESULT, HTTP_HEADERS_RESULT_VALUES);
 
 typedef struct HTTP_HEADERS_HANDLE_DATA_TAG
@@ -120,7 +114,9 @@
 
             if (!replace && (existingValue != NULL))
             {
-                char* newValue = (char*)malloc(strlen(existingValue) + COMMA_AND_SPACE_LENGTH + strlen(value) + 1);
+                size_t existingValueLen = strlen(existingValue);
+                size_t valueLen = strlen(value);
+                char* newValue = (char*)malloc(sizeof(char) * (existingValueLen + /*COMMA_AND_SPACE_LENGTH*/ 2 + valueLen + /*EOL*/ 1));
                 if (newValue == NULL)
                 {
                     /*Codes_SRS_HTTP_HEADERS_99_015:[ The function shall return HTTP_HEADERS_ALLOC_FAILED when an internal request to allocate memory fails.]*/
@@ -129,10 +125,13 @@
                 }
                 else
                 {
+                    char* runNewValue;
                     /*Codes_SRS_HTTP_HEADERS_99_017:[ If the name already exists in the collection of headers, the function shall concatenate the new value after the existing value, separated by a comma and a space as in: old-value+", "+new-value.]*/
-                    (void)strcpy(newValue, existingValue);
-                    (void)strcat(newValue, COMMA_AND_SPACE);
-                    (void)strcat(newValue, value);
+                    (void)memcpy(newValue, existingValue, existingValueLen);
+                    runNewValue = newValue + existingValueLen;
+                    (*runNewValue++) = ',';
+                    (*runNewValue++) = ' ';
+                    (void)memcpy(runNewValue, value, valueLen + /*EOL*/ 1);
 
                     /*Codes_SRS_HTTP_HEADERS_99_016:[ The function shall store the name:value pair in such a way that when later retrieved by a call to GetHeader it will return a string that shall strcmp equal to the name+": "+value.]*/
                     if (Map_AddOrUpdate(handleData->headers, name, newValue) != MAP_OK)
@@ -275,7 +274,9 @@
             }
             else
             {
-                *destination = (char*)malloc(strlen(keys[index]) + COLON_AND_SPACE_LENGTH + strlen(values[index]) + 1);
+                size_t keyLen = strlen(keys[index]);
+                size_t valueLen = strlen(values[index]);
+                *destination = (char*)malloc(sizeof(char) * (keyLen + /*COLON_AND_SPACE_LENGTH*/ 2 + valueLen + /*EOL*/ 1));
                 if (*destination == NULL)
                 {
                     /*Codes_SRS_HTTP_HEADERS_99_034:[ The function shall return HTTP_HEADERS_ERROR when an internal error occurs]*/
@@ -286,9 +287,12 @@
                 {
                     /*Codes_SRS_HTTP_HEADERS_99_016:[ The function shall store the name:value pair in such a way that when later retrieved by a call to GetHeader it will return a string that shall strcmp equal to the name+": "+value.]*/
                     /*Codes_SRS_HTTP_HEADERS_99_027:[ Calling this API shall produce the string value+": "+pair) for the index header in the *destination parameter.]*/
-                    strcpy(*destination, keys[index]);
-                    strcat(*destination, COLON_AND_SPACE);
-                    strcat(*destination, values[index]);
+                    char* runDestination = (*destination);
+                    (void)memcpy(runDestination, keys[index], keyLen);
+                    runDestination += keyLen;
+                    (*runDestination++) = ':';
+                    (*runDestination++) = ' ';
+                    (void)memcpy(runDestination, values[index], valueLen + /*EOL*/ 1);
                     /*Codes_SRS_HTTP_HEADERS_99_035:[ The function shall return HTTP_HEADERS_OK when the function executed without error.]*/
                     result = HTTP_HEADERS_OK;
                 }
--- a/sastoken.c	Fri Aug 26 12:59:40 2016 -0700
+++ b/sastoken.c	Fri Sep 09 13:38:26 2016 -0700
@@ -77,6 +77,10 @@
                     {
                         STRING_HANDLE base64Signature = NULL;
                         STRING_HANDLE urlEncodedSignature = NULL;
+                        size_t inLen = STRING_length(toBeHashed);
+                        const unsigned char* inBuf = (const unsigned char*)STRING_c_str(toBeHashed);
+                        size_t outLen = BUFFER_length(decodedKey);
+                        unsigned char* outBuf = BUFFER_u_char(decodedKey);
                         /*Codes_SRS_SASTOKEN_06_013: [If an error is returned from the HMAC256 function then NULL is returned from SASToken_Create.]*/
                         /*Codes_SRS_SASTOKEN_06_012: [An HMAC256 hash is calculated using the decodedKey, over toBeHashed.]*/
                         /*Codes_SRS_SASTOKEN_06_014: [If there are any errors from the following operations then NULL shall be returned.]*/
@@ -90,7 +94,7 @@
                         /*Codes_SRS_SASTOKEN_06_021: [tokenExpirationTime is appended to result.]*/
                         /*Codes_SRS_SASTOKEN_06_022: [The string "&skn=" is appended to result.]*/
                         /*Codes_SRS_SASTOKEN_06_023: [The argument keyName is appended to result.]*/
-                        if ((HMACSHA256_ComputeHash(BUFFER_u_char(decodedKey), BUFFER_length(decodedKey), (const unsigned char*)STRING_c_str(toBeHashed), STRING_length(toBeHashed), hash) != HMACSHA256_OK) ||
+                        if ((HMACSHA256_ComputeHash(outBuf, outLen, inBuf, inLen, hash) != HMACSHA256_OK) ||
                             ((base64Signature = Base64_Encode(hash)) == NULL) ||
                             ((urlEncodedSignature = URL_Encode(base64Signature)) == NULL) ||
                             (STRING_copy(result, "SharedAccessSignature sr=") != 0) ||
--- a/urlencode.c	Fri Aug 26 12:59:40 2016 -0700
+++ b/urlencode.c	Fri Sep 09 13:38:26 2016 -0700
@@ -19,267 +19,90 @@
 #include "azure_c_shared_utility/xlogging.h"
 #include "azure_c_shared_utility/strings.h"
 
-static const struct {
-    size_t numberOfChars;
-    const char* encoding;
-} urlEncoding[] = {
-    { 1, "\0"  },
-    { 3, "%01" },
-    { 3, "%02" },
-    { 3, "%03" },
-    { 3, "%04" },
-    { 3, "%05" },
-    { 3, "%06" },
-    { 3, "%07" },
-    { 3, "%08" },
-    { 3, "%09" },
-    { 3, "%0a" },
-    { 3, "%0b" },
-    { 3, "%0c" },
-    { 3, "%0d" },
-    { 3, "%0e" },
-    { 3, "%0f" },
-    { 3, "%10" },
-    { 3, "%11" },
-    { 3, "%12" },
-    { 3, "%13" },
-    { 3, "%14" },
-    { 3, "%15" },
-    { 3, "%16" },
-    { 3, "%17" },
-    { 3, "%18" },
-    { 3, "%19" },
-    { 3, "%1a" },
-    { 3, "%1b" },
-    { 3, "%1c" },
-    { 3, "%1d" },
-    { 3, "%1e" },
-    { 3, "%1f" },
-    { 3, "%20" },
-    { 1, "!" },
-    { 3, "%22" },
-    { 3, "%23" },
-    { 3, "%24" },
-    { 3, "%25" },
-    { 3, "%26" },
-    { 3, "%27" },
-    { 1, "(" },
-    { 1, ")" },
-    { 1, "*" },
-    { 3, "%2b" },
-    { 3, "%2c" },
-    { 1, "-" },
-    { 1, "." },
-    { 3, "%2f" },
-    { 1, "0" },
-    { 1, "1" },
-    { 1, "2" },
-    { 1, "3" },
-    { 1, "4" },
-    { 1, "5" },
-    { 1, "6" },
-    { 1, "7" },
-    { 1, "8" },
-    { 1, "9" },
-    { 3, "%3a" },
-    { 3, "%3b" },
-    { 3, "%3c" },
-    { 3, "%3d" },
-    { 3, "%3e" },
-    { 3, "%3f" },
-    { 3, "%40" },
-    { 1, "A" },
-    { 1, "B" },
-    { 1, "C" },
-    { 1, "D" },
-    { 1, "E" },
-    { 1, "F" },
-    { 1, "G" },
-    { 1, "H" },
-    { 1, "I" },
-    { 1, "J" },
-    { 1, "K" },
-    { 1, "L" },
-    { 1, "M" },
-    { 1, "N" },
-    { 1, "O" },
-    { 1, "P" },
-    { 1, "Q" },
-    { 1, "R" },
-    { 1, "S" },
-    { 1, "T" },
-    { 1, "U" },
-    { 1, "V" },
-    { 1, "W" },
-    { 1, "X" },
-    { 1, "Y" },
-    { 1, "Z" },
-    { 3, "%5b" },
-    { 3, "%5c" },
-    { 3, "%5d" },
-    { 3, "%5e" },
-    { 1, "_" },
-    { 3, "%60" },
-    { 1, "a" },
-    { 1, "b" },
-    { 1, "c" },
-    { 1, "d" },
-    { 1, "e" },
-    { 1, "f" },
-    { 1, "g" },
-    { 1, "h" },
-    { 1, "i" },
-    { 1, "j" },
-    { 1, "k" },
-    { 1, "l" },
-    { 1, "m" },
-    { 1, "n" },
-    { 1, "o" },
-    { 1, "p" },
-    { 1, "q" },
-    { 1, "r" },
-    { 1, "s" },
-    { 1, "t" },
-    { 1, "u" },
-    { 1, "v" },
-    { 1, "w" },
-    { 1, "x" },
-    { 1, "y" },
-    { 1, "z" },
-    { 3, "%7b" },
-    { 3, "%7c" },
-    { 3, "%7d" },
-    { 3, "%7e" },
-    { 3, "%7f" },
-    { 6, "%c2%80" },
-    { 6, "%c2%81" },
-    { 6, "%c2%82" },
-    { 6, "%c2%83" },
-    { 6, "%c2%84" },
-    { 6, "%c2%85" },
-    { 6, "%c2%86" },
-    { 6, "%c2%87" },
-    { 6, "%c2%88" },
-    { 6, "%c2%89" },
-    { 6, "%c2%8a" },
-    { 6, "%c2%8b" },
-    { 6, "%c2%8c" },
-    { 6, "%c2%8d" },
-    { 6, "%c2%8e" },
-    { 6, "%c2%8f" },
-    { 6, "%c2%90" },
-    { 6, "%c2%91" },
-    { 6, "%c2%92" },
-    { 6, "%c2%93" },
-    { 6, "%c2%94" },
-    { 6, "%c2%95" },
-    { 6, "%c2%96" },
-    { 6, "%c2%97" },
-    { 6, "%c2%98" },
-    { 6, "%c2%99" },
-    { 6, "%c2%9a" },
-    { 6, "%c2%9b" },
-    { 6, "%c2%9c" },
-    { 6, "%c2%9d" },
-    { 6, "%c2%9e" },
-    { 6, "%c2%9f" },
-    { 6, "%c2%a0" },
-    { 6, "%c2%a1" },
-    { 6, "%c2%a2" },
-    { 6, "%c2%a3" },
-    { 6, "%c2%a4" },
-    { 6, "%c2%a5" },
-    { 6, "%c2%a6" },
-    { 6, "%c2%a7" },
-    { 6, "%c2%a8" },
-    { 6, "%c2%a9" },
-    { 6, "%c2%aa" },
-    { 6, "%c2%ab" },
-    { 6, "%c2%ac" },
-    { 6, "%c2%ad" },
-    { 6, "%c2%ae" },
-    { 6, "%c2%af" },
-    { 6, "%c2%b0" },
-    { 6, "%c2%b1" },
-    { 6, "%c2%b2" },
-    { 6, "%c2%b3" },
-    { 6, "%c2%b4" },
-    { 6, "%c2%b5" },
-    { 6, "%c2%b6" },
-    { 6, "%c2%b7" },
-    { 6, "%c2%b8" },
-    { 6, "%c2%b9" },
-    { 6, "%c2%ba" },
-    { 6, "%c2%bb" },
-    { 6, "%c2%bc" },
-    { 6, "%c2%bd" },
-    { 6, "%c2%be" },
-    { 6, "%c2%bf" },
-    { 6, "%c3%80" },
-    { 6, "%c3%81" },
-    { 6, "%c3%82" },
-    { 6, "%c3%83" },
-    { 6, "%c3%84" },
-    { 6, "%c3%85" },
-    { 6, "%c3%86" },
-    { 6, "%c3%87" },
-    { 6, "%c3%88" },
-    { 6, "%c3%89" },
-    { 6, "%c3%8a" },
-    { 6, "%c3%8b" },
-    { 6, "%c3%8c" },
-    { 6, "%c3%8d" },
-    { 6, "%c3%8e" },
-    { 6, "%c3%8f" },
-    { 6, "%c3%90" },
-    { 6, "%c3%91" },
-    { 6, "%c3%92" },
-    { 6, "%c3%93" },
-    { 6, "%c3%94" },
-    { 6, "%c3%95" },
-    { 6, "%c3%96" },
-    { 6, "%c3%97" },
-    { 6, "%c3%98" },
-    { 6, "%c3%99" },
-    { 6, "%c3%9a" },
-    { 6, "%c3%9b" },
-    { 6, "%c3%9c" },
-    { 6, "%c3%9d" },
-    { 6, "%c3%9e" },
-    { 6, "%c3%9f" },
-    { 6, "%c3%a0" },
-    { 6, "%c3%a1" },
-    { 6, "%c3%a2" },
-    { 6, "%c3%a3" },
-    { 6, "%c3%a4" },
-    { 6, "%c3%a5" },
-    { 6, "%c3%a6" },
-    { 6, "%c3%a7" },
-    { 6, "%c3%a8" },
-    { 6, "%c3%a9" },
-    { 6, "%c3%aa" },
-    { 6, "%c3%ab" },
-    { 6, "%c3%ac" },
-    { 6, "%c3%ad" },
-    { 6, "%c3%ae" },
-    { 6, "%c3%af" },
-    { 6, "%c3%b0" },
-    { 6, "%c3%b1" },
-    { 6, "%c3%b2" },
-    { 6, "%c3%b3" },
-    { 6, "%c3%b4" },
-    { 6, "%c3%b5" },
-    { 6, "%c3%b6" },
-    { 6, "%c3%b7" },
-    { 6, "%c3%b8" },
-    { 6, "%c3%b9" },
-    { 6, "%c3%ba" },
-    { 6, "%c3%bb" },
-    { 6, "%c3%bc" },
-    { 6, "%c3%bd" },
-    { 6, "%c3%be" },
-    { 6, "%c3%bf" }
-};
+#define NIBBLE_STR(c) (char)(c < 10 ? c + '0' : c - 10 + 'a')
+#define IS_PRINTABLE(c) (                           \
+    (c == 0) ||                                     \
+    (c == '!') ||                                   \
+    (c == '(') || (c == ')') || (c == '*') ||       \
+    (c == '-') || (c == '.') ||                     \
+    ((c >= '0') && (c <= '9')) ||                   \
+    ((c >= 'A') && (c <= 'Z')) ||                   \
+    (c == '_') ||                                   \
+    ((c >= 'a') && (c <= 'z'))                      \
+)
+
+static size_t URL_PrintableChar(unsigned char charVal, char* buffer)
+{
+    size_t size;
+    if (IS_PRINTABLE(charVal))
+    {
+        buffer[0] = (char)charVal;
+        size = 1;
+    }
+    else
+    {
+        char bigNibbleStr;
+        char littleNibbleStr;
+        unsigned char bigNibbleVal = charVal >> 4;
+        unsigned char littleNibbleVal = charVal & 0x0F;
+
+        if (bigNibbleVal >= 0x0C)
+        {
+            bigNibbleVal -= 0x04;
+        }
+
+        bigNibbleStr = NIBBLE_STR(bigNibbleVal);
+        littleNibbleStr = NIBBLE_STR(littleNibbleVal);
+
+        buffer[0] = '%';
+
+        if (charVal < 0x80)
+        {
+            buffer[1] = bigNibbleStr;
+            buffer[2] = littleNibbleStr;
+            size = 3;
+        }
+        else
+        {
+            buffer[1] = 'c';
+            buffer[3] = '%';
+            buffer[4] = bigNibbleStr;
+            buffer[5] = littleNibbleStr;
+            if (charVal < 0xC0)
+            {
+                buffer[2] = '2';
+            }
+            else
+            {
+                buffer[2] = '3';
+            }
+            size = 6;
+        }
+    }
+
+    return size;
+}
+
+static size_t URL_PrintableCharSize(unsigned char charVal)
+{
+    size_t size;
+    if (IS_PRINTABLE(charVal))
+    {
+        size = 1;
+    }
+    else
+    {
+        if (charVal < 0x80)
+        {
+            size = 3;
+        }
+        else
+        {
+            size = 6;
+        }
+    }
+    return size;
+}
 
 STRING_HANDLE URL_EncodeString(const char* textEncode)
 {
@@ -324,7 +147,7 @@
         do
         {
             currentUnsignedChar = (unsigned char)(*currentInput++);
-            lengthOfResult += urlEncoding[currentUnsignedChar].numberOfChars;
+            lengthOfResult += URL_PrintableCharSize(currentUnsignedChar);
         } while (currentUnsignedChar != 0);
         if ((encodedURL = malloc(lengthOfResult)) == NULL)
         {
@@ -339,17 +162,15 @@
             do
             {
                 currentUnsignedChar = (unsigned char)(*currentInput++);
-                if (urlEncoding[currentUnsignedChar].numberOfChars == 1)
-                {
-                    encodedURL[currentEncodePosition++] = *(urlEncoding[currentUnsignedChar].encoding);
-                }
-                else
-                {
-                    memcpy(encodedURL + currentEncodePosition, urlEncoding[currentUnsignedChar].encoding, urlEncoding[currentUnsignedChar].numberOfChars);
-                    currentEncodePosition += urlEncoding[currentUnsignedChar].numberOfChars;
-                }
+                currentEncodePosition += URL_PrintableChar(currentUnsignedChar, &encodedURL[currentEncodePosition]);
             } while (currentUnsignedChar != 0);
+
             result = STRING_new_with_memory(encodedURL);
+            if (result == NULL)
+            {
+                LogError("URL_Encode:: MALLOC failure on encode.");
+                free(encodedURL);
+            }
         }
     }
     return result;
--- a/vector.c	Fri Aug 26 12:59:40 2016 -0700
+++ b/vector.c	Fri Sep 09 13:38:26 2016 -0700
@@ -125,7 +125,7 @@
     if (handle != NULL)
     {
         const VECTOR* vec = (const VECTOR*)handle;
-        if (index <= vec->count)
+        if (index < vec->count)
         {
             result = (unsigned char*)vec->storage + (vec->elementSize * index);
         }