Microsoft Azure IoTHub client libraries

Dependents:   sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp f767zi_mqtt ... more

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

Revision:
74:ea0021abecf7
Parent:
69:b6f532f8c608
Child:
75:86205ca63a59
--- a/iothub_client_ll_uploadtoblob.c	Fri Aug 11 14:02:31 2017 -0700
+++ b/iothub_client_ll_uploadtoblob.c	Fri Aug 25 11:22:43 2017 -0700
@@ -14,6 +14,7 @@
 #include "azure_c_shared_utility/xlogging.h"
 #include "azure_c_shared_utility/tickcounter.h"
 #include "azure_c_shared_utility/httpapiexsas.h"
+#include "azure_c_shared_utility/shared_util_options.h"
 
 #include "iothub_client_ll.h"
 #include "iothub_client_options.h"
@@ -66,6 +67,7 @@
         UPLOADTOBLOB_X509_CREDENTIALS x509credentials; /*assumed to be used when both deviceKey and deviceSasToken are NULL*/
     } credentials;                              /*needed for file upload*/
     char* certificates; /*if there are any certificates used*/
+    HTTP_PROXY_OPTIONS http_proxy_options;
 }IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA;
 
 IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE IoTHubClient_LL_UploadToBlob_Create(const IOTHUB_CLIENT_CONFIG* config)
@@ -103,6 +105,8 @@
                 ((char*)handleData->hostname)[iotHubNameLength] = '.';
                 (void)memcpy((char*)handleData->hostname + iotHubNameLength + 1, config->iotHubSuffix, iotHubSuffixLength + 1); /*+1 will copy the \0 too*/
                 handleData->certificates = NULL;
+                memset(&(handleData->http_proxy_options), 0, sizeof(HTTP_PROXY_OPTIONS));
+
                 if ((config->deviceSasToken != NULL) && (config->deviceKey == NULL))
                 {
                     handleData->authorizationScheme = SAS_TOKEN;
@@ -165,389 +169,389 @@
         LogError("unable to STRING_construct");
         result = __FAILURE__;
     }
-	else
-	{
-		if (!(
-			(STRING_concat_with_STRING(relativePath, handleData->deviceId) == 0) &&
-			(STRING_concat(relativePath, "/files") == 0) &&
-			(STRING_concat(relativePath, API_VERSION) == 0)
-			))
-		{
-			/*Codes_SRS_IOTHUBCLIENT_LL_02_067: [ If creating the relativePath fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-			LogError("unable to concatenate STRING");
-			result = __FAILURE__;
-		}
-		else
-		{
-			/*Codes_SRS_IOTHUBCLIENT_LL_32_001: [ IoTHubClient_LL_UploadToBlob shall create a JSON string formed from "{ \"blobName\": \" + destinationFileName + "\" }" */
-			STRING_HANDLE blobName = STRING_construct("{ \"blobName\": \"");
-			if (blobName == NULL)
-			{
-				/*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-				LogError("unable to STRING_construct");
-				result = __FAILURE__;
-			}
-			else
-			{
-				if (!(
-					(STRING_concat(blobName, destinationFileName) == 0) &&
-					(STRING_concat(blobName, "\" }") == 0)
-					))
-				{
-					/*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-					LogError("unable to concatenate STRING");
-					result = __FAILURE__;
-				}
-				else
-				{
+    else
+    {
+        if (!(
+            (STRING_concat_with_STRING(relativePath, handleData->deviceId) == 0) &&
+            (STRING_concat(relativePath, "/files") == 0) &&
+            (STRING_concat(relativePath, API_VERSION) == 0)
+            ))
+        {
+            /*Codes_SRS_IOTHUBCLIENT_LL_02_067: [ If creating the relativePath fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+            LogError("unable to concatenate STRING");
+            result = __FAILURE__;
+        }
+        else
+        {
+            /*Codes_SRS_IOTHUBCLIENT_LL_32_001: [ IoTHubClient_LL_UploadToBlob shall create a JSON string formed from "{ \"blobName\": \" + destinationFileName + "\" }" */
+            STRING_HANDLE blobName = STRING_construct("{ \"blobName\": \"");
+            if (blobName == NULL)
+            {
+                /*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                LogError("unable to STRING_construct");
+                result = __FAILURE__;
+            }
+            else
+            {
+                if (!(
+                    (STRING_concat(blobName, destinationFileName) == 0) &&
+                    (STRING_concat(blobName, "\" }") == 0)
+                    ))
+                {
+                    /*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                    LogError("unable to concatenate STRING");
+                    result = __FAILURE__;
+                }
+                else
+                {
                     size_t len = STRING_length(blobName);
-					BUFFER_HANDLE blobBuffer = BUFFER_create((const unsigned char *)STRING_c_str(blobName), len);
+                    BUFFER_HANDLE blobBuffer = BUFFER_create((const unsigned char *)STRING_c_str(blobName), len);
 
-					if (blobBuffer == NULL)
-					{
-						/*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                    if (blobBuffer == NULL)
+                    {
+                        /*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
                         LogError("unable to create BUFFER");
-						result = __FAILURE__;
-					}
-					else
-					{
-						/*Codes_SRS_IOTHUBCLIENT_LL_02_068: [ IoTHubClient_LL_UploadToBlob shall create an HTTP responseContent BUFFER_HANDLE. ]*/
-						BUFFER_HANDLE responseContent = BUFFER_new();
-						if (responseContent == NULL)
-						{
-							/*Codes_SRS_IOTHUBCLIENT_LL_02_069: [ If creating the HTTP response buffer handle fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-							result = __FAILURE__;
-							LogError("unable to BUFFER_new");
-						}
-						else
-						{
-							/*Codes_SRS_IOTHUBCLIENT_LL_02_072: [ IoTHubClient_LL_UploadToBlob shall add the following name:value to request HTTP headers: ] "Content-Type": "application/json" "Accept": "application/json" "User-Agent": "iothubclient/" IOTHUB_SDK_VERSION*/
-							/*Codes_SRS_IOTHUBCLIENT_LL_02_107: [ - "Authorization" header shall not be build. ]*/
-							if (!(
-								(HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Content-Type", "application/json") == HTTP_HEADERS_OK) &&
-								(HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Accept", "application/json") == HTTP_HEADERS_OK) &&
-								(HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "User-Agent", "iothubclient/" IOTHUB_SDK_VERSION) == HTTP_HEADERS_OK) &&
-								(handleData->authorizationScheme == X509 || (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Authorization", "") == HTTP_HEADERS_OK))
-								))
-							{
-								/*Codes_SRS_IOTHUBCLIENT_LL_02_071: [ If creating the HTTP headers fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-								LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
-								result = __FAILURE__;
-							}
-							else
-							{
-								int wasIoTHubRequestSuccess = 0; /*!=0 means responseContent has a buffer that should be parsed by parson after executing the below switch*/
-								/* set the result to error by default */
-								result = __FAILURE__;
-								switch (handleData->authorizationScheme)
-								{
-								default:
-								{
-									/*wasIoTHubRequestSuccess takes care of the return value*/
-									LogError("Internal Error: unexpected value in handleData->authorizationScheme = %d", handleData->authorizationScheme);
-									result = __FAILURE__;
-									break;
-								}
-								case(X509):
-								{
-									unsigned int statusCode;
-									/*Codes_SRS_IOTHUBCLIENT_LL_32_003: [ IoTHubClient_LL_UploadToBlob shall execute HTTPAPIEX_ExecuteRequest passing the following information for arguments: ]*/
-									if (HTTPAPIEX_ExecuteRequest(
-										iotHubHttpApiExHandle,          /*HTTPAPIEX_HANDLE handle - the handle created at the beginning of `IoTHubClient_LL_UploadToBlob`*/
-										HTTPAPI_REQUEST_POST,           /*HTTPAPI_REQUEST_TYPE requestType - HTTPAPI_REQUEST_POST*/
-										STRING_c_str(relativePath),     /*const char* relativePath - the HTTP relative path*/
-										requestHttpHeaders,             /*HTTP_HEADERS_HANDLE requestHttpHeadersHandle - request HTTP headers*/
-										blobBuffer,                     /*BUFFER_HANDLE requestContent - address of JSON with optional/directory/tree/filename*/
-										&statusCode,                    /*unsigned int* statusCode - the address of an unsigned int that will contain the HTTP status code*/
-										NULL,                           /*HTTP_HEADERS_HANDLE responseHttpHeadersHandle - NULL*/
-										responseContent                 /*BUFFER_HANDLE responseContent - the HTTP response BUFFER_HANDLE - responseContent*/
-									) != HTTPAPIEX_OK)
-									{
-										/*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-										result = __FAILURE__;
-										LogError("unable to HTTPAPIEX_ExecuteRequest");
-									}
-									else
-									{
-										/*Codes_SRS_IOTHUBCLIENT_LL_02_077: [ If HTTP statusCode is greater than or equal to 300 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-										if (statusCode >= 300)
-										{
-											result = __FAILURE__;
-											LogError("HTTP code was %u", statusCode);
-										}
-										else
-										{
-											wasIoTHubRequestSuccess = 1;
-										}
-									}
-									break;
-								}
-								case (SAS_TOKEN):
-								{
-									const char* sasToken = STRING_c_str(handleData->credentials.sas);
-									/*Codes_SRS_IOTHUBCLIENT_LL_02_073: [ If the credentials used to create handle have "sasToken" then IoTHubClient_LL_UploadToBlob shall add the following HTTP request headers: ]*/
-									if (HTTPHeaders_ReplaceHeaderNameValuePair(requestHttpHeaders, "Authorization", sasToken) != HTTP_HEADERS_OK)
-									{
-										/*Codes_SRS_IOTHUBCLIENT_LL_02_074: [ If adding "Authorization" fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR ]*/
-										result = __FAILURE__;
-										LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
-									}
-									else
-									{
-										unsigned int statusCode;
-										/*Codes_SRS_IOTHUBCLIENT_LL_32_004: [ IoTHubClient_LL_UploadToBlob shall execute HTTPAPIEX_ExecuteRequest passing the following information for arguments: ]*/
-										if (HTTPAPIEX_ExecuteRequest(
-											iotHubHttpApiExHandle,          /*HTTPAPIEX_HANDLE handle - the handle created at the beginning of `IoTHubClient_LL_UploadToBlob`*/
-											HTTPAPI_REQUEST_POST,           /*HTTPAPI_REQUEST_TYPE requestType - HTTPAPI_REQUEST_POST*/
-											STRING_c_str(relativePath),     /*const char* relativePath - the HTTP relative path*/
-											requestHttpHeaders,             /*HTTP_HEADERS_HANDLE requestHttpHeadersHandle - request HTTP headers*/
-											blobBuffer,                     /*BUFFER_HANDLE requestContent - address of JSON with optional/directory/tree/filename*/
-											&statusCode,                    /*unsigned int* statusCode - the address of an unsigned int that will contain the HTTP status code*/
-											NULL,                           /*HTTP_HEADERS_HANDLE responseHttpHeadersHandle - NULL*/
-											responseContent                 /*BUFFER_HANDLE responseContent - the HTTP response BUFFER_HANDLE - responseContent*/
-										) != HTTPAPIEX_OK)
-										{
-											/*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-											result = __FAILURE__;
-											LogError("unable to HTTPAPIEX_ExecuteRequest");
-										}
-										else
-										{
-											/*Codes_SRS_IOTHUBCLIENT_LL_02_077: [ If HTTP statusCode is greater than or equal to 300 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-											if (statusCode >= 300)
-											{
-												result = __FAILURE__;
-												LogError("HTTP code was %u", statusCode);
-											}
-											else
-											{
-												wasIoTHubRequestSuccess = 1;
-											}
-										}
-									}
-									break;
-								}
-								case(DEVICE_KEY):
-								{
-									/*Codes_SRS_IOTHUBCLIENT_LL_02_078: [ If the credentials used to create handle have "deviceKey" then IoTHubClient_LL_UploadToBlob shall create an HTTPAPIEX_SAS_HANDLE passing as arguments: ]*/
-									STRING_HANDLE uriResource = STRING_construct(handleData->hostname);
-									if (uriResource == NULL)
-									{
-										/*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-										result = __FAILURE__;
-										LogError("unable to STRING_construct");
-									}
-									else
-									{
-										if (!(
-											(STRING_concat(uriResource, "/devices/") == 0) &&
-											(STRING_concat_with_STRING(uriResource, handleData->deviceId) == 0)
-											))
-										{
-											/*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-											LogError("unable to STRING_concat_with_STRING");
-											result = __FAILURE__;
-										}
-										else
-										{
-											STRING_HANDLE empty = STRING_new();
-											if (empty == NULL)
-											{
-												LogError("unable to STRING_new");
-												result = __FAILURE__;
-											}
-											else	
-											{
-												/*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-												HTTPAPIEX_SAS_HANDLE sasHandle = HTTPAPIEX_SAS_Create(handleData->credentials.deviceKey, uriResource, empty);
-												if (sasHandle == NULL)
-												{
-													LogError("unable to HTTPAPIEX_SAS_Create");
-													result = __FAILURE__;
-												}
-												else
-												{
-													unsigned int statusCode;
-													/*Codes_SRS_IOTHUBCLIENT_LL_32_005: [ IoTHubClient_LL_UploadToBlob shall call HTTPAPIEX_SAS_ExecuteRequest passing as arguments: ]*/
-													if (HTTPAPIEX_SAS_ExecuteRequest(
-														sasHandle,                      /*HTTPAPIEX_SAS_HANDLE sasHandle - the created HTTPAPIEX_SAS_HANDLE*/
-														iotHubHttpApiExHandle,          /*HTTPAPIEX_HANDLE handle - the created HTTPAPIEX_HANDLE*/
-														HTTPAPI_REQUEST_POST,           /*HTTPAPI_REQUEST_TYPE requestType - HTTPAPI_REQUEST_POST*/
-														STRING_c_str(relativePath),     /*const char* relativePath - the HTTP relative path*/
-														requestHttpHeaders,             /*HTTP_HEADERS_HANDLE requestHttpHeadersHandle - request HTTP headers*/
-														blobBuffer,                     /*BUFFER_HANDLE requestContent - address of JSON with optional/directory/tree/filename*/
-														&statusCode,                    /*unsigned int* statusCode - the address of an unsigned int that will contain the HTTP status code*/
-														NULL,                           /*HTTP_HEADERS_HANDLE responseHeadersHandle - NULL*/
-														responseContent
-													) != HTTPAPIEX_OK)
-													{
-														/*Codes_SRS_IOTHUBCLIENT_LL_02_079: [ If HTTPAPIEX_SAS_ExecuteRequest fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-														LogError("unable to HTTPAPIEX_SAS_ExecuteRequest");
-														result = __FAILURE__;
-													}
-													else
-													{
-														if (statusCode >= 300)
-														{
-															/*Codes_SRS_IOTHUBCLIENT_LL_02_080: [ If status code is greater than or equal to 300 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-															result = __FAILURE__;
-															LogError("HTTP code was %u", statusCode);
-														}
-														else
-														{
-															wasIoTHubRequestSuccess = 1;
-														}
-													}
-													HTTPAPIEX_SAS_Destroy(sasHandle);
-												}
-												STRING_delete(empty);
-											}
-										}
-										STRING_delete(uriResource);
-									}
-								}
-								} /*switch*/
+                        result = __FAILURE__;
+                    }
+                    else
+                    {
+                        /*Codes_SRS_IOTHUBCLIENT_LL_02_068: [ IoTHubClient_LL_UploadToBlob shall create an HTTP responseContent BUFFER_HANDLE. ]*/
+                        BUFFER_HANDLE responseContent = BUFFER_new();
+                        if (responseContent == NULL)
+                        {
+                            /*Codes_SRS_IOTHUBCLIENT_LL_02_069: [ If creating the HTTP response buffer handle fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                            result = __FAILURE__;
+                            LogError("unable to BUFFER_new");
+                        }
+                        else
+                        {
+                            /*Codes_SRS_IOTHUBCLIENT_LL_02_072: [ IoTHubClient_LL_UploadToBlob shall add the following name:value to request HTTP headers: ] "Content-Type": "application/json" "Accept": "application/json" "User-Agent": "iothubclient/" IOTHUB_SDK_VERSION*/
+                            /*Codes_SRS_IOTHUBCLIENT_LL_02_107: [ - "Authorization" header shall not be build. ]*/
+                            if (!(
+                                (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Content-Type", "application/json") == HTTP_HEADERS_OK) &&
+                                (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Accept", "application/json") == HTTP_HEADERS_OK) &&
+                                (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "User-Agent", "iothubclient/" IOTHUB_SDK_VERSION) == HTTP_HEADERS_OK) &&
+                                (handleData->authorizationScheme == X509 || (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Authorization", "") == HTTP_HEADERS_OK))
+                                ))
+                            {
+                                /*Codes_SRS_IOTHUBCLIENT_LL_02_071: [ If creating the HTTP headers fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
+                                result = __FAILURE__;
+                            }
+                            else
+                            {
+                                int wasIoTHubRequestSuccess = 0; /*!=0 means responseContent has a buffer that should be parsed by parson after executing the below switch*/
+                                /* set the result to error by default */
+                                result = __FAILURE__;
+                                switch (handleData->authorizationScheme)
+                                {
+                                default:
+                                {
+                                    /*wasIoTHubRequestSuccess takes care of the return value*/
+                                    LogError("Internal Error: unexpected value in handleData->authorizationScheme = %d", handleData->authorizationScheme);
+                                    result = __FAILURE__;
+                                    break;
+                                }
+                                case(X509):
+                                {
+                                    unsigned int statusCode;
+                                    /*Codes_SRS_IOTHUBCLIENT_LL_32_003: [ IoTHubClient_LL_UploadToBlob shall execute HTTPAPIEX_ExecuteRequest passing the following information for arguments: ]*/
+                                    if (HTTPAPIEX_ExecuteRequest(
+                                        iotHubHttpApiExHandle,          /*HTTPAPIEX_HANDLE handle - the handle created at the beginning of `IoTHubClient_LL_UploadToBlob`*/
+                                        HTTPAPI_REQUEST_POST,           /*HTTPAPI_REQUEST_TYPE requestType - HTTPAPI_REQUEST_POST*/
+                                        STRING_c_str(relativePath),     /*const char* relativePath - the HTTP relative path*/
+                                        requestHttpHeaders,             /*HTTP_HEADERS_HANDLE requestHttpHeadersHandle - request HTTP headers*/
+                                        blobBuffer,                     /*BUFFER_HANDLE requestContent - address of JSON with optional/directory/tree/filename*/
+                                        &statusCode,                    /*unsigned int* statusCode - the address of an unsigned int that will contain the HTTP status code*/
+                                        NULL,                           /*HTTP_HEADERS_HANDLE responseHttpHeadersHandle - NULL*/
+                                        responseContent                 /*BUFFER_HANDLE responseContent - the HTTP response BUFFER_HANDLE - responseContent*/
+                                    ) != HTTPAPIEX_OK)
+                                    {
+                                        /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                        result = __FAILURE__;
+                                        LogError("unable to HTTPAPIEX_ExecuteRequest");
+                                    }
+                                    else
+                                    {
+                                        /*Codes_SRS_IOTHUBCLIENT_LL_02_077: [ If HTTP statusCode is greater than or equal to 300 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                        if (statusCode >= 300)
+                                        {
+                                            result = __FAILURE__;
+                                            LogError("HTTP code was %u", statusCode);
+                                        }
+                                        else
+                                        {
+                                            wasIoTHubRequestSuccess = 1;
+                                        }
+                                    }
+                                    break;
+                                }
+                                case (SAS_TOKEN):
+                                {
+                                    const char* sasToken = STRING_c_str(handleData->credentials.sas);
+                                    /*Codes_SRS_IOTHUBCLIENT_LL_02_073: [ If the credentials used to create handle have "sasToken" then IoTHubClient_LL_UploadToBlob shall add the following HTTP request headers: ]*/
+                                    if (HTTPHeaders_ReplaceHeaderNameValuePair(requestHttpHeaders, "Authorization", sasToken) != HTTP_HEADERS_OK)
+                                    {
+                                        /*Codes_SRS_IOTHUBCLIENT_LL_02_074: [ If adding "Authorization" fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR ]*/
+                                        result = __FAILURE__;
+                                        LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
+                                    }
+                                    else
+                                    {
+                                        unsigned int statusCode;
+                                        /*Codes_SRS_IOTHUBCLIENT_LL_32_004: [ IoTHubClient_LL_UploadToBlob shall execute HTTPAPIEX_ExecuteRequest passing the following information for arguments: ]*/
+                                        if (HTTPAPIEX_ExecuteRequest(
+                                            iotHubHttpApiExHandle,          /*HTTPAPIEX_HANDLE handle - the handle created at the beginning of `IoTHubClient_LL_UploadToBlob`*/
+                                            HTTPAPI_REQUEST_POST,           /*HTTPAPI_REQUEST_TYPE requestType - HTTPAPI_REQUEST_POST*/
+                                            STRING_c_str(relativePath),     /*const char* relativePath - the HTTP relative path*/
+                                            requestHttpHeaders,             /*HTTP_HEADERS_HANDLE requestHttpHeadersHandle - request HTTP headers*/
+                                            blobBuffer,                     /*BUFFER_HANDLE requestContent - address of JSON with optional/directory/tree/filename*/
+                                            &statusCode,                    /*unsigned int* statusCode - the address of an unsigned int that will contain the HTTP status code*/
+                                            NULL,                           /*HTTP_HEADERS_HANDLE responseHttpHeadersHandle - NULL*/
+                                            responseContent                 /*BUFFER_HANDLE responseContent - the HTTP response BUFFER_HANDLE - responseContent*/
+                                        ) != HTTPAPIEX_OK)
+                                        {
+                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                            result = __FAILURE__;
+                                            LogError("unable to HTTPAPIEX_ExecuteRequest");
+                                        }
+                                        else
+                                        {
+                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_077: [ If HTTP statusCode is greater than or equal to 300 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                            if (statusCode >= 300)
+                                            {
+                                                result = __FAILURE__;
+                                                LogError("HTTP code was %u", statusCode);
+                                            }
+                                            else
+                                            {
+                                                wasIoTHubRequestSuccess = 1;
+                                            }
+                                        }
+                                    }
+                                    break;
+                                }
+                                case(DEVICE_KEY):
+                                {
+                                    /*Codes_SRS_IOTHUBCLIENT_LL_02_078: [ If the credentials used to create handle have "deviceKey" then IoTHubClient_LL_UploadToBlob shall create an HTTPAPIEX_SAS_HANDLE passing as arguments: ]*/
+                                    STRING_HANDLE uriResource = STRING_construct(handleData->hostname);
+                                    if (uriResource == NULL)
+                                    {
+                                        /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                        result = __FAILURE__;
+                                        LogError("unable to STRING_construct");
+                                    }
+                                    else
+                                    {
+                                        if (!(
+                                            (STRING_concat(uriResource, "/devices/") == 0) &&
+                                            (STRING_concat_with_STRING(uriResource, handleData->deviceId) == 0)
+                                            ))
+                                        {
+                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                            LogError("unable to STRING_concat_with_STRING");
+                                            result = __FAILURE__;
+                                        }
+                                        else
+                                        {
+                                            STRING_HANDLE empty = STRING_new();
+                                            if (empty == NULL)
+                                            {
+                                                LogError("unable to STRING_new");
+                                                result = __FAILURE__;
+                                            }
+                                            else
+                                            {
+                                                /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                HTTPAPIEX_SAS_HANDLE sasHandle = HTTPAPIEX_SAS_Create(handleData->credentials.deviceKey, uriResource, empty);
+                                                if (sasHandle == NULL)
+                                                {
+                                                    LogError("unable to HTTPAPIEX_SAS_Create");
+                                                    result = __FAILURE__;
+                                                }
+                                                else
+                                                {
+                                                    unsigned int statusCode;
+                                                    /*Codes_SRS_IOTHUBCLIENT_LL_32_005: [ IoTHubClient_LL_UploadToBlob shall call HTTPAPIEX_SAS_ExecuteRequest passing as arguments: ]*/
+                                                    if (HTTPAPIEX_SAS_ExecuteRequest(
+                                                        sasHandle,                      /*HTTPAPIEX_SAS_HANDLE sasHandle - the created HTTPAPIEX_SAS_HANDLE*/
+                                                        iotHubHttpApiExHandle,          /*HTTPAPIEX_HANDLE handle - the created HTTPAPIEX_HANDLE*/
+                                                        HTTPAPI_REQUEST_POST,           /*HTTPAPI_REQUEST_TYPE requestType - HTTPAPI_REQUEST_POST*/
+                                                        STRING_c_str(relativePath),     /*const char* relativePath - the HTTP relative path*/
+                                                        requestHttpHeaders,             /*HTTP_HEADERS_HANDLE requestHttpHeadersHandle - request HTTP headers*/
+                                                        blobBuffer,                     /*BUFFER_HANDLE requestContent - address of JSON with optional/directory/tree/filename*/
+                                                        &statusCode,                    /*unsigned int* statusCode - the address of an unsigned int that will contain the HTTP status code*/
+                                                        NULL,                           /*HTTP_HEADERS_HANDLE responseHeadersHandle - NULL*/
+                                                        responseContent
+                                                    ) != HTTPAPIEX_OK)
+                                                    {
+                                                        /*Codes_SRS_IOTHUBCLIENT_LL_02_079: [ If HTTPAPIEX_SAS_ExecuteRequest fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                        LogError("unable to HTTPAPIEX_SAS_ExecuteRequest");
+                                                        result = __FAILURE__;
+                                                    }
+                                                    else
+                                                    {
+                                                        if (statusCode >= 300)
+                                                        {
+                                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_080: [ If status code is greater than or equal to 300 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                            result = __FAILURE__;
+                                                            LogError("HTTP code was %u", statusCode);
+                                                        }
+                                                        else
+                                                        {
+                                                            wasIoTHubRequestSuccess = 1;
+                                                        }
+                                                    }
+                                                    HTTPAPIEX_SAS_Destroy(sasHandle);
+                                                }
+                                                STRING_delete(empty);
+                                            }
+                                        }
+                                        STRING_delete(uriResource);
+                                    }
+                                }
+                                } /*switch*/
 
-								if (wasIoTHubRequestSuccess == 0)
-								{
-									/*do nothing, shall be reported as an error*/
-								}
-								else
-								{
-									const unsigned char*responseContent_u_char = BUFFER_u_char(responseContent);
-									size_t responseContent_length = BUFFER_length(responseContent);
-									STRING_HANDLE responseAsString = STRING_from_byte_array(responseContent_u_char, responseContent_length);
-									if (responseAsString == NULL)
-									{
-										result = __FAILURE__;
-										LogError("unable to get the response as string");
-									}
-									else
-									{
-										/*Codes_SRS_IOTHUBCLIENT_LL_02_081: [ Otherwise, IoTHubClient_LL_UploadToBlob shall use parson to extract and save the following information from the response buffer: correlationID and SasUri. ]*/
-										JSON_Value* allJson = json_parse_string(STRING_c_str(responseAsString));
-										if (allJson == NULL)
-										{
-											/*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-											LogError("unable to json_parse_string");
-											result = __FAILURE__;
-										}
-										else
-										{
-											JSON_Object* jsonObject = json_value_get_object(allJson);
-											if (jsonObject == NULL)
-											{
-												/*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-												LogError("unable to json_value_get_object");
-												result = __FAILURE__;
-											}
-											else
-											{
-												const char* json_correlationId;
-												json_correlationId = json_object_get_string(jsonObject, "correlationId");
-												if (json_correlationId == NULL)
-												{
-													/*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-													LogError("unable to json_object_get_string(jsonObject, \"correlationId\")");
-													result = __FAILURE__;
-												}
-												else
-												{
-													if (STRING_copy(correlationId, json_correlationId) != 0)
-													{
-														/*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-														LogError("unable to copy json_correlationId");
-														result = __FAILURE__;
-													}
-													else
-													{
-														const char* json_hostName = json_object_get_string(jsonObject, "hostName");
-														if (json_hostName == NULL)
-														{
-															/*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-															LogError("unable to json_object_get_string(jsonObject, \"hostName\")");
-															result = __FAILURE__;
-														}
-														else
-														{
-															const char* json_containerName = json_object_get_string(jsonObject, "containerName");
-															if (json_containerName == NULL)
-															{
-																/*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-																LogError("unable to json_object_get_string(jsonObject, \"containerName\")");
-																result = __FAILURE__;
-															}
-															else
-															{
-																const char* json_blobName = json_object_get_string(jsonObject, "blobName");
-																if (json_blobName == NULL)
-																{
-																	/*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-																	LogError("unable to json_object_get_string(jsonObject, \"blobName\")");
-																	result = __FAILURE__;
-																}
-																else
-																{
-																	const char* json_sasToken = json_object_get_string(jsonObject, "sasToken");
-																	if (json_sasToken == NULL)
-																	{
-																		/*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-																		LogError("unable to json_object_get_string(jsonObject, \"sasToken\")");
-																		result = __FAILURE__;
-																	}
-																	else
-																	{
-																		/*good JSON received from the service*/
+                                if (wasIoTHubRequestSuccess == 0)
+                                {
+                                    /*do nothing, shall be reported as an error*/
+                                }
+                                else
+                                {
+                                    const unsigned char*responseContent_u_char = BUFFER_u_char(responseContent);
+                                    size_t responseContent_length = BUFFER_length(responseContent);
+                                    STRING_HANDLE responseAsString = STRING_from_byte_array(responseContent_u_char, responseContent_length);
+                                    if (responseAsString == NULL)
+                                    {
+                                        result = __FAILURE__;
+                                        LogError("unable to get the response as string");
+                                    }
+                                    else
+                                    {
+                                        /*Codes_SRS_IOTHUBCLIENT_LL_02_081: [ Otherwise, IoTHubClient_LL_UploadToBlob shall use parson to extract and save the following information from the response buffer: correlationID and SasUri. ]*/
+                                        JSON_Value* allJson = json_parse_string(STRING_c_str(responseAsString));
+                                        if (allJson == NULL)
+                                        {
+                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                            LogError("unable to json_parse_string");
+                                            result = __FAILURE__;
+                                        }
+                                        else
+                                        {
+                                            JSON_Object* jsonObject = json_value_get_object(allJson);
+                                            if (jsonObject == NULL)
+                                            {
+                                                /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                LogError("unable to json_value_get_object");
+                                                result = __FAILURE__;
+                                            }
+                                            else
+                                            {
+                                                const char* json_correlationId;
+                                                json_correlationId = json_object_get_string(jsonObject, "correlationId");
+                                                if (json_correlationId == NULL)
+                                                {
+                                                    /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                    LogError("unable to json_object_get_string(jsonObject, \"correlationId\")");
+                                                    result = __FAILURE__;
+                                                }
+                                                else
+                                                {
+                                                    if (STRING_copy(correlationId, json_correlationId) != 0)
+                                                    {
+                                                        /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                        LogError("unable to copy json_correlationId");
+                                                        result = __FAILURE__;
+                                                    }
+                                                    else
+                                                    {
+                                                        const char* json_hostName = json_object_get_string(jsonObject, "hostName");
+                                                        if (json_hostName == NULL)
+                                                        {
+                                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                            LogError("unable to json_object_get_string(jsonObject, \"hostName\")");
+                                                            result = __FAILURE__;
+                                                        }
+                                                        else
+                                                        {
+                                                            const char* json_containerName = json_object_get_string(jsonObject, "containerName");
+                                                            if (json_containerName == NULL)
+                                                            {
+                                                                /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                                LogError("unable to json_object_get_string(jsonObject, \"containerName\")");
+                                                                result = __FAILURE__;
+                                                            }
+                                                            else
+                                                            {
+                                                                const char* json_blobName = json_object_get_string(jsonObject, "blobName");
+                                                                if (json_blobName == NULL)
+                                                                {
+                                                                    /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                                    LogError("unable to json_object_get_string(jsonObject, \"blobName\")");
+                                                                    result = __FAILURE__;
+                                                                }
+                                                                else
+                                                                {
+                                                                    const char* json_sasToken = json_object_get_string(jsonObject, "sasToken");
+                                                                    if (json_sasToken == NULL)
+                                                                    {
+                                                                        /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                                        LogError("unable to json_object_get_string(jsonObject, \"sasToken\")");
+                                                                        result = __FAILURE__;
+                                                                    }
+                                                                    else
+                                                                    {
+                                                                        /*good JSON received from the service*/
 
-																		if (STRING_copy(sasUri, "https://") != 0)
-																		{
-																			/*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-																			LogError("unable to STRING_copy");
-																			result = __FAILURE__;
-																		}
-																		else
-																		{
-																			if (!(
-																				(STRING_concat(sasUri, json_hostName) == 0) &&
-																				(STRING_concat(sasUri, "/") == 0) &&
-																				(STRING_concat(sasUri, json_containerName) == 0) &&
-																				(STRING_concat(sasUri, "/") == 0) &&
-																				(STRING_concat(sasUri, json_blobName) == 0) &&
-																				(STRING_concat(sasUri, json_sasToken) == 0)
-																				))
-																			{
-																				/*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-																				LogError("unable to STRING_concat");
-																				result = __FAILURE__;
-																			}
-																			else
-																			{
-																				result = 0; /*success in step 1*/
-																			}
-																		}
-																	}
-																}
-															}
-														}
-													}
-												}
-											}
-											json_value_free(allJson);
-										}
-										STRING_delete(responseAsString);
-									}
-								}
-							}
-							BUFFER_delete(responseContent);
-						}
+                                                                        if (STRING_copy(sasUri, "https://") != 0)
+                                                                        {
+                                                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                                            LogError("unable to STRING_copy");
+                                                                            result = __FAILURE__;
+                                                                        }
+                                                                        else
+                                                                        {
+                                                                            if (!(
+                                                                                (STRING_concat(sasUri, json_hostName) == 0) &&
+                                                                                (STRING_concat(sasUri, "/") == 0) &&
+                                                                                (STRING_concat(sasUri, json_containerName) == 0) &&
+                                                                                (STRING_concat(sasUri, "/") == 0) &&
+                                                                                (STRING_concat(sasUri, json_blobName) == 0) &&
+                                                                                (STRING_concat(sasUri, json_sasToken) == 0)
+                                                                                ))
+                                                                            {
+                                                                                /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                                                LogError("unable to STRING_concat");
+                                                                                result = __FAILURE__;
+                                                                            }
+                                                                            else
+                                                                            {
+                                                                                result = 0; /*success in step 1*/
+                                                                            }
+                                                                        }
+                                                                    }
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                            json_value_free(allJson);
+                                        }
+                                        STRING_delete(responseAsString);
+                                    }
+                                }
+                            }
+                            BUFFER_delete(responseContent);
+                        }
                         BUFFER_delete(blobBuffer);
-					}
-				}
-				STRING_delete(blobName);
-			}
-		}
-		STRING_delete(relativePath);
-	}
+                    }
+                }
+                STRING_delete(blobName);
+            }
+        }
+        STRING_delete(relativePath);
+    }
     return result;
 }
 
@@ -794,115 +798,138 @@
                 else
                 {
 
-                    STRING_HANDLE correlationId = STRING_new();
-                    if (correlationId == NULL)
+                    if (handleData->http_proxy_options.host_address != NULL)
                     {
-                        LogError("unable to STRING_new");
-                        result = IOTHUB_CLIENT_ERROR;
+                        HTTP_PROXY_OPTIONS proxy_options;
+                        proxy_options = handleData->http_proxy_options;
+
+                        if (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_HTTP_PROXY, &proxy_options) != HTTPAPIEX_OK)
+                        {
+                            LogError("unable to set http proxy!");
+                            result = IOTHUB_CLIENT_ERROR;
+                        }
+                        else
+                        {
+                            result = IOTHUB_CLIENT_OK;
+                        }
                     }
                     else
                     {
-                        STRING_HANDLE sasUri = STRING_new();
-                        if (sasUri == NULL)
+                        result = IOTHUB_CLIENT_OK;
+                    }
+                        
+                    if (result != IOTHUB_CLIENT_ERROR)
+                    {
+                        STRING_HANDLE correlationId = STRING_new();
+                        if (correlationId == NULL)
                         {
                             LogError("unable to STRING_new");
                             result = IOTHUB_CLIENT_ERROR;
                         }
                         else
                         {
-                            /*Codes_SRS_IOTHUBCLIENT_LL_02_070: [ IoTHubClient_LL_UploadToBlob shall create request HTTP headers. ]*/
-                            HTTP_HEADERS_HANDLE requestHttpHeaders = HTTPHeaders_Alloc(); /*these are build by step 1 and used by step 3 too*/
-                            if (requestHttpHeaders == NULL)
+                            STRING_HANDLE sasUri = STRING_new();
+                            if (sasUri == NULL)
                             {
-                                LogError("unable to HTTPHeaders_Alloc");
+                                LogError("unable to STRING_new");
                                 result = IOTHUB_CLIENT_ERROR;
                             }
                             else
                             {
-                                /*do step 1*/
-                                if (IoTHubClient_LL_UploadToBlob_step1and2(handleData, iotHubHttpApiExHandle, requestHttpHeaders, destinationFileName, correlationId, sasUri) != 0)
+                                /*Codes_SRS_IOTHUBCLIENT_LL_02_070: [ IoTHubClient_LL_UploadToBlob shall create request HTTP headers. ]*/
+                                HTTP_HEADERS_HANDLE requestHttpHeaders = HTTPHeaders_Alloc(); /*these are build by step 1 and used by step 3 too*/
+                                if (requestHttpHeaders == NULL)
                                 {
-                                    LogError("error in IoTHubClient_LL_UploadToBlob_step1");
+                                    LogError("unable to HTTPHeaders_Alloc");
                                     result = IOTHUB_CLIENT_ERROR;
                                 }
                                 else
                                 {
-                                    /*do step 2.*/
-
-                                    unsigned int httpResponse;
-                                    BUFFER_HANDLE responseToIoTHub = BUFFER_new();
-                                    if (responseToIoTHub == NULL)
+                                    /*do step 1*/
+                                    if (IoTHubClient_LL_UploadToBlob_step1and2(handleData, iotHubHttpApiExHandle, requestHttpHeaders, destinationFileName, correlationId, sasUri) != 0)
                                     {
+                                        LogError("error in IoTHubClient_LL_UploadToBlob_step1");
                                         result = IOTHUB_CLIENT_ERROR;
-                                        LogError("unable to BUFFER_new");
                                     }
                                     else
                                     {
-                                        int step2success;
-                                        /*Codes_SRS_IOTHUBCLIENT_LL_02_083: [ IoTHubClient_LL_UploadToBlob shall call Blob_UploadFromSasUri and capture the HTTP return code and HTTP body. ]*/
-                                        step2success = (Blob_UploadFromSasUri(STRING_c_str(sasUri), source, size, &httpResponse, responseToIoTHub, handleData->certificates) == BLOB_OK);
-                                        if (!step2success)
-                                        {
-                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_084: [ If Blob_UploadFromSasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
-                                            LogError("unable to Blob_UploadFromSasUri");
+                                        /*do step 2.*/
 
-                                            /*do step 3*/ /*try*/
-                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_091: [ If step 2 fails without establishing an HTTP dialogue, then the HTTP message body shall look like: ]*/
-                                            if (BUFFER_build(responseToIoTHub, (const unsigned char*)FILE_UPLOAD_FAILED_BODY, sizeof(FILE_UPLOAD_FAILED_BODY) / sizeof(FILE_UPLOAD_FAILED_BODY[0])) == 0)
-                                            {
-                                                if (IoTHubClient_LL_UploadToBlob_step3(handleData, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, responseToIoTHub) != 0)
-                                                {
-                                                    LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
-                                                }
-                                            }
+                                        unsigned int httpResponse;
+                                        BUFFER_HANDLE responseToIoTHub = BUFFER_new();
+                                        if (responseToIoTHub == NULL)
+                                        {
                                             result = IOTHUB_CLIENT_ERROR;
+                                            LogError("unable to BUFFER_new");
                                         }
                                         else
                                         {
-                                            /*must make a json*/
-
-                                            requiredStringLength = snprintf(NULL, 0, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub));
+                                            int step2success;
+                                            /*Codes_SRS_IOTHUBCLIENT_LL_02_083: [ IoTHubClient_LL_UploadToBlob shall call Blob_UploadFromSasUri and capture the HTTP return code and HTTP body. ]*/
+                                            step2success = (Blob_UploadFromSasUri(STRING_c_str(sasUri), source, size, &httpResponse, responseToIoTHub, handleData->certificates) == BLOB_OK);
+                                            if (!step2success)
+                                            {
+                                                /*Codes_SRS_IOTHUBCLIENT_LL_02_084: [ If Blob_UploadFromSasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
+                                                LogError("unable to Blob_UploadFromSasUri");
 
-                                            requiredString = malloc(requiredStringLength + 1);
-                                            if (requiredString == 0)
-                                            {
-                                                LogError("unable to malloc");
+                                                /*do step 3*/ /*try*/
+                                                /*Codes_SRS_IOTHUBCLIENT_LL_02_091: [ If step 2 fails without establishing an HTTP dialogue, then the HTTP message body shall look like: ]*/
+                                                if (BUFFER_build(responseToIoTHub, (const unsigned char*)FILE_UPLOAD_FAILED_BODY, sizeof(FILE_UPLOAD_FAILED_BODY) / sizeof(FILE_UPLOAD_FAILED_BODY[0])) == 0)
+                                                {
+                                                    if (IoTHubClient_LL_UploadToBlob_step3(handleData, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, responseToIoTHub) != 0)
+                                                    {
+                                                        LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
+                                                    }
+                                                }
                                                 result = IOTHUB_CLIENT_ERROR;
                                             }
                                             else
                                             {
-                                                /*do again snprintf*/
-                                                (void)snprintf(requiredString, requiredStringLength + 1, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub));
-                                                toBeTransmitted = BUFFER_create((const unsigned char*)requiredString, requiredStringLength);
-                                                if (toBeTransmitted == NULL)
+                                                /*must make a json*/
+
+                                                requiredStringLength = snprintf(NULL, 0, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub));
+
+                                                requiredString = malloc(requiredStringLength + 1);
+                                                if (requiredString == 0)
                                                 {
-                                                    LogError("unable to BUFFER_create");
+                                                    LogError("unable to malloc");
                                                     result = IOTHUB_CLIENT_ERROR;
                                                 }
                                                 else
                                                 {
-                                                    if (IoTHubClient_LL_UploadToBlob_step3(handleData, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, toBeTransmitted) != 0)
+                                                    /*do again snprintf*/
+                                                    (void)snprintf(requiredString, requiredStringLength + 1, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub));
+                                                    toBeTransmitted = BUFFER_create((const unsigned char*)requiredString, requiredStringLength);
+                                                    if (toBeTransmitted == NULL)
                                                     {
-                                                        LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
+                                                        LogError("unable to BUFFER_create");
                                                         result = IOTHUB_CLIENT_ERROR;
                                                     }
                                                     else
                                                     {
-                                                        result = (httpResponse < 300) ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR;
+                                                        if (IoTHubClient_LL_UploadToBlob_step3(handleData, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, toBeTransmitted) != 0)
+                                                        {
+                                                            LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
+                                                            result = IOTHUB_CLIENT_ERROR;
+                                                        }
+                                                        else
+                                                        {
+                                                            result = (httpResponse < 300) ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR;
+                                                        }
+                                                        BUFFER_delete(toBeTransmitted);
                                                     }
-                                                    BUFFER_delete(toBeTransmitted);
+                                                    free(requiredString);
                                                 }
-                                                free(requiredString);
                                             }
+                                            BUFFER_delete(responseToIoTHub);
                                         }
-                                        BUFFER_delete(responseToIoTHub);
                                     }
+                                    HTTPHeaders_Free(requestHttpHeaders);
                                 }
-                                HTTPHeaders_Free(requestHttpHeaders);
+                                STRING_delete(sasUri);
                             }
-                            STRING_delete(sasUri);
+                            STRING_delete(correlationId);
                         }
-                        STRING_delete(correlationId);
                     }
                 }
             }
@@ -957,6 +984,18 @@
         {
             free(handleData->certificates);
         }
+        if (handleData->http_proxy_options.host_address != NULL)
+        {
+            free((char *)handleData->http_proxy_options.host_address);
+        }
+        if (handleData->http_proxy_options.username != NULL)
+        {
+            free((char *)handleData->http_proxy_options.username);
+        }
+        if (handleData->http_proxy_options.password != NULL)
+        {
+            free((char *)handleData->http_proxy_options.password);
+        }
         free(handleData);
     }
 }
@@ -1064,6 +1103,65 @@
                 }
             }
         }
+        /*Codes_SRS_IOTHUBCLIENT_LL_32_008: [ OPTION_HTTP_PROXY - then the value will be a pointer to HTTP_PROXY_OPTIONS structure. ]*/
+        else if (strcmp(optionName, OPTION_HTTP_PROXY) == 0)
+        {
+            HTTP_PROXY_OPTIONS* proxy_options = (HTTP_PROXY_OPTIONS *)value;
+            
+            if (proxy_options->host_address == NULL)
+            {
+                /* Codes_SRS_IOTHUBCLIENT_LL_32_006: [ If `host_address` is NULL, `IoTHubClient_LL_UploadToBlob_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+                LogError("NULL host_address in proxy options");
+                result = IOTHUB_CLIENT_INVALID_ARG;
+            }
+            /* Codes_SRS_IOTHUBCLIENT_LL_32_007: [ If only one of `username` and `password` is NULL, `IoTHubClient_LL_UploadToBlob_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
+            else if (((proxy_options->username == NULL) || (proxy_options->password == NULL)) &&
+                (proxy_options->username != proxy_options->password))
+            {
+                LogError("Only one of username and password for proxy settings was NULL");
+                result = IOTHUB_CLIENT_INVALID_ARG;
+            }
+            else
+            {
+                if (handleData->http_proxy_options.host_address != NULL)
+                {
+                    free((char *)handleData->http_proxy_options.host_address);
+                    handleData->http_proxy_options.host_address = NULL;
+                }
+                if (handleData->http_proxy_options.username != NULL)
+                {
+                    free((char *)handleData->http_proxy_options.username);
+                    handleData->http_proxy_options.username = NULL;
+                }
+                if (handleData->http_proxy_options.password != NULL)
+                {
+                    free((char *)handleData->http_proxy_options.password);
+                    handleData->http_proxy_options.password = NULL;
+                }
+                
+                handleData->http_proxy_options.port = proxy_options->port;
+
+                if (mallocAndStrcpy_s((char **)(&handleData->http_proxy_options.host_address), proxy_options->host_address) != 0)
+                {
+                    LogError("failure in mallocAndStrcpy_s - handleData->http_proxy_options.host_address");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else if (proxy_options->username != NULL && mallocAndStrcpy_s((char **)(&handleData->http_proxy_options.username), proxy_options->username) != 0)
+                {
+                    LogError("failure in mallocAndStrcpy_s - handleData->http_proxy_options.username");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else if (proxy_options->password != NULL && mallocAndStrcpy_s((char **)(&handleData->http_proxy_options.password), proxy_options->password) != 0)
+                {
+                    LogError("failure in mallocAndStrcpy_s - handleData->http_proxy_options.password");
+                    result = IOTHUB_CLIENT_ERROR;
+                }
+                else
+                {
+                    result = IOTHUB_CLIENT_OK;
+                }
+            }
+        }
         else
         {
             /*Codes_SRS_IOTHUBCLIENT_LL_02_102: [ If an unknown option is presented then IoTHubClient_LL_UploadToBlob_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/