corrected version (with typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE;) included in the sources

Dependents:   STM32F746_iothub_client_sample_mqtt

Fork of iothub_client by Azure IoT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers iothub_client_ll_uploadtoblob.c Source File

iothub_client_ll_uploadtoblob.c

00001 // Copyright (c) Microsoft. All rights reserved.
00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
00003 
00004 #include <stdlib.h>
00005 #ifdef _CRTDBG_MAP_ALLOC
00006 #include <crtdbg.h>
00007 #endif
00008 #include <string.h>
00009 #include "azure_c_shared_utility/gballoc.h"
00010 #include "azure_c_shared_utility/string_tokenizer.h"
00011 #include "azure_c_shared_utility/doublylinkedlist.h"
00012 #include "azure_c_shared_utility/iot_logging.h"
00013 #include "azure_c_shared_utility/tickcounter.h"
00014 #include "azure_c_shared_utility/httpapiexsas.h"
00015 
00016 #include "iothub_client_ll.h"
00017 #include "iothub_client_private.h"
00018 #include "iothub_client_version.h"
00019 #include "iothub_transport_ll.h"
00020 #include "parson.h"
00021 #include "iothub_client_ll_uploadtoblob.h"
00022 #include "blob.h"
00023 
00024 
00025 
00026 /*Codes_SRS_IOTHUBCLIENT_LL_02_085: [ IoTHubClient_LL_UploadToBlob shall use the same authorization as step 1. to prepare and perform a HTTP request with the following parameters: ]*/
00027 #define FILE_UPLOAD_FAILED_BODY "{ \"isSuccess\":false, \"statusCode\":-1,\"statusDescription\" : \"client not able to connect with the server\" }"
00028 
00029 #define AUTHORIZATION_SCHEME_VALUES \
00030     DEVICE_KEY, \
00031     SAS_TOKEN
00032 
00033 DEFINE_ENUM(AUTHORIZATION_SCHEME, AUTHORIZATION_SCHEME_VALUES);
00034 
00035 typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA_TAG
00036 {
00037     STRING_HANDLE deviceId;                     /*needed for file upload*/
00038     const char* hostname;                       /*needed for file upload*/
00039     AUTHORIZATION_SCHEME authorizationScheme;   /*needed for file upload*/
00040     union {
00041         STRING_HANDLE deviceKey;    /*used when authorizationScheme is DEVICE_KEY*/
00042         STRING_HANDLE sas;          /*used when authorizationScheme is SAS_TOKEN*/
00043     } credentials;                              /*needed for file upload*/
00044 }IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA;
00045 
00046 IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE IoTHubClient_LL_UploadToBlob_Create(const IOTHUB_CLIENT_CONFIG* config)
00047 {
00048     IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* handleData = malloc(sizeof(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA));
00049     if (handleData == NULL)
00050     {
00051         LogError("oom - malloc");
00052         /*return as is*/
00053     }
00054     else
00055     {
00056         size_t iotHubNameLength = strlen(config->iotHubName);
00057         size_t iotHubSuffixLength = strlen(config->iotHubSuffix);
00058         handleData->deviceId = STRING_construct(config->deviceId);
00059         if (handleData->deviceId == NULL)
00060         {
00061             LogError("unable to STRING_construct");
00062             free(handleData);
00063             handleData = NULL;
00064         }
00065         else
00066         {
00067             handleData->hostname = malloc(iotHubNameLength + 1 + iotHubSuffixLength + 1); /*first +1 is because "." the second +1 is because \0*/
00068             if (handleData->hostname == NULL)
00069             {
00070                 LogError("malloc failed");
00071                 STRING_delete(handleData->deviceId);
00072                 free(handleData);
00073                 handleData = NULL;
00074             }
00075             else
00076             {
00077                 memcpy((char*)handleData->hostname, config->iotHubName, iotHubNameLength);
00078                 ((char*)handleData->hostname)[iotHubNameLength] = '.';
00079                 memcpy((char*)handleData->hostname + iotHubNameLength + 1, config->iotHubSuffix, iotHubSuffixLength + 1); /*+1 will copy the \0 too*/
00080                 if (config->deviceSasToken != NULL)
00081                 {
00082                     handleData->authorizationScheme = SAS_TOKEN;
00083                     handleData->credentials.sas = STRING_construct(config->deviceSasToken);
00084                     if (handleData->credentials.sas == NULL)
00085                     {
00086                         LogError("unable to STRING_construct");
00087                         free((void*)handleData->hostname);
00088                         STRING_delete(handleData->deviceId);
00089                         free(handleData);
00090                         handleData = NULL;
00091                     }
00092                     else
00093                     {
00094                         /*return as is*/
00095                     }
00096                 }
00097                 else
00098                 {
00099                     handleData->authorizationScheme = DEVICE_KEY;
00100                     handleData->credentials.deviceKey = STRING_construct(config->deviceKey);
00101                     if (handleData->credentials.deviceKey == NULL)
00102                     {
00103                         LogError("unable to STRING_construct");
00104                         free((void*)handleData->hostname);
00105                         STRING_delete(handleData->deviceId);
00106                         free(handleData);
00107                         handleData = NULL;
00108                     }
00109                     else
00110                     {
00111                         /*return as is*/
00112                     }
00113                 }
00114             }
00115         }
00116     }
00117     return (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)handleData;
00118 
00119 }
00120 
00121 /*returns 0 when correlationId, sasUri contain data*/
00122 static int IoTHubClient_LL_UploadToBlob_step1and2(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* handleData, HTTPAPIEX_HANDLE iotHubHttpApiExHandle, HTTP_HEADERS_HANDLE requestHttpHeaders, const char* destinationFileName,
00123     STRING_HANDLE correlationId, STRING_HANDLE sasUri)
00124 {
00125     int result;
00126 
00127     /*Codes_SRS_IOTHUBCLIENT_LL_02_066: [ IoTHubClient_LL_UploadToBlob shall create an HTTP relative path formed from "/devices/" + deviceId + "/files/" + destinationFileName + "?api-version=API_VERSION". ]*/
00128     STRING_HANDLE relativePath = STRING_construct("/devices/");
00129     if (relativePath == NULL)
00130     {
00131         /*Codes_SRS_IOTHUBCLIENT_LL_02_067: [ If creating the relativePath fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00132         LogError("unable to STRING_construct");
00133         result = __LINE__;
00134     }
00135     else
00136     {
00137         if (!(
00138             (STRING_concat_with_STRING(relativePath, handleData->deviceId) == 0) &&
00139             (STRING_concat(relativePath, "/files/") == 0) &&
00140             (STRING_concat(relativePath, destinationFileName) == 0) &&
00141             (STRING_concat(relativePath, API_VERSION) == 0)
00142             ))
00143         {
00144             /*Codes_SRS_IOTHUBCLIENT_LL_02_067: [ If creating the relativePath fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00145             LogError("unable to concatenate STRING");
00146             result = __LINE__;
00147         }
00148         else
00149         {
00150             /*Codes_SRS_IOTHUBCLIENT_LL_02_068: [ IoTHubClient_LL_UploadToBlob shall create an HTTP responseContent BUFFER_HANDLE. ]*/
00151             BUFFER_HANDLE responseContent = BUFFER_new();
00152             if (responseContent == NULL)
00153             {
00154                 /*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. ]*/
00155                 result = __LINE__;
00156                 LogError("unable to BUFFER_new");
00157             }
00158             else
00159             {
00160                 /*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*/
00161                 if (!(
00162                     (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Content-Type", "application/json") == HTTP_HEADERS_OK) &&
00163                     (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Accept", "application/json") == HTTP_HEADERS_OK) &&
00164                     (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "User-Agent", "iothubclient/" IOTHUB_SDK_VERSION) == HTTP_HEADERS_OK) &&
00165                     (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Authorization", "") == HTTP_HEADERS_OK)
00166                     ))
00167                 {
00168                     /*Codes_SRS_IOTHUBCLIENT_LL_02_071: [ If creating the HTTP headers fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00169                     LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
00170                     result = __LINE__;
00171                 }
00172                 else
00173                 {
00174                     int wasIoTHubRequestSuccess = 0; /*!=0 means responseContent has a buffer that should be parsed by parson after executing the below switch*/
00175                     switch (handleData->authorizationScheme)
00176                     {
00177                     default:
00178                     {
00179                         /*wasIoTHubRequestSuccess takes care of the return value*/
00180                         LogError("Internal Error: unexpected value in handleData->authorizationScheme = %d", handleData->authorizationScheme);
00181                         break;
00182                     }
00183                     case (SAS_TOKEN):
00184                     {
00185                         const char* sasToken = STRING_c_str(handleData->credentials.sas);
00186                         /*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: ]*/
00187                         if (HTTPHeaders_ReplaceHeaderNameValuePair(requestHttpHeaders, "Authorization", sasToken) != HTTP_HEADERS_OK)
00188                         {
00189                             /*Codes_SRS_IOTHUBCLIENT_LL_02_074: [ If adding "Authorization" fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR ]*/
00190                             result = __LINE__;
00191                             LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
00192                         }
00193                         else
00194                         {
00195                             unsigned int statusCode;
00196                             /*Codes_SRS_IOTHUBCLIENT_LL_02_075: [ IoTHubClient_LL_UploadToBlob shall execute HTTPAPIEX_ExecuteRequest passing the following information for arguments: ]*/
00197                             if (HTTPAPIEX_ExecuteRequest(
00198                                 iotHubHttpApiExHandle,          /*HTTPAPIEX_HANDLE handle - the handle created at the beginning of `IoTHubClient_LL_UploadToBlob`*/
00199                                 HTTPAPI_REQUEST_GET,            /*HTTPAPI_REQUEST_TYPE requestType - HTTPAPI_REQUEST_GET*/
00200                                 STRING_c_str(relativePath),     /*const char* relativePath - the HTTP relative path*/
00201                                 requestHttpHeaders,             /*HTTP_HEADERS_HANDLE requestHttpHeadersHandle - request HTTP headers*/
00202                                 NULL,                           /*BUFFER_HANDLE requestContent - NULL*/
00203                                 &statusCode,                    /*unsigned int* statusCode - the address of an unsigned int that will contain the HTTP status code*/
00204                                 NULL,                           /*HTTP_HEADERS_HANDLE responseHttpHeadersHandl - NULL*/
00205                                 responseContent                 /*BUFFER_HANDLE responseContent - the HTTP response BUFFER_HANDLE - responseContent*/
00206                             ) != HTTPAPIEX_OK)
00207                             {
00208                                 /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00209                                 result = __LINE__;
00210                                 LogError("unable to HTTPAPIEX_ExecuteRequest");
00211                             }
00212                             else
00213                             {
00214                                 /*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. ]*/
00215                                 if (statusCode >= 300)
00216                                 {
00217                                     result = __LINE__;
00218                                     wasIoTHubRequestSuccess = 0;
00219                                     LogError("HTTP code was %u", statusCode);
00220                                 }
00221                                 else
00222                                 {
00223                                     wasIoTHubRequestSuccess = 1;
00224                                 }
00225                             }
00226                         }
00227                         break;
00228                     }
00229                     case(DEVICE_KEY):
00230                     {
00231                         /*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: ]*/
00232                         STRING_HANDLE uriResource = STRING_construct(handleData->hostname);
00233                         if (uriResource == NULL)
00234                         {
00235                             /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00236                             result = __LINE__;
00237                             LogError("unable to STRING_construct");
00238                         }
00239                         else
00240                         {
00241                             if (!(
00242                                 (STRING_concat(uriResource, "/devices/") == 0) &&
00243                                 (STRING_concat_with_STRING(uriResource, handleData->deviceId) == 0)
00244                                 ))
00245                             {
00246                                 /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00247                                 LogError("unable to STRING_concat_with_STRING");
00248                                 result = __LINE__;
00249                             }
00250                             else
00251                             {
00252                                 STRING_HANDLE empty = STRING_new();
00253                                 if (empty == NULL)
00254                                 {
00255                                     LogError("unable to STRING_new");
00256                                     result = __LINE__;
00257                                 }
00258                                 else
00259                                 {
00260                                     /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00261                                     HTTPAPIEX_SAS_HANDLE sasHandle = HTTPAPIEX_SAS_Create(handleData->credentials.deviceKey, uriResource, empty);
00262                                     if (sasHandle == NULL)
00263                                     {
00264                                         LogError("unable to HTTPAPIEX_SAS_Create");
00265                                         result = __LINE__;
00266                                     }
00267                                     else
00268                                     {
00269                                         unsigned int statusCode;
00270                                         /*Codes_SRS_IOTHUBCLIENT_LL_02_090: [ IoTHubClient_LL_UploadToBlob shall call HTTPAPIEX_SAS_ExecuteRequest passing as arguments: ]*/
00271                                         if (HTTPAPIEX_SAS_ExecuteRequest(
00272                                             sasHandle,                      /*HTTPAPIEX_SAS_HANDLE sasHandle - the created HTTPAPIEX_SAS_HANDLE*/
00273                                             iotHubHttpApiExHandle,          /*HTTPAPIEX_HANDLE handle - the created HTTPAPIEX_HANDLE*/
00274                                             HTTPAPI_REQUEST_GET,            /*HTTPAPI_REQUEST_TYPE requestType - HTTPAPI_REQUEST_GET*/
00275                                             STRING_c_str(relativePath),     /*const char* relativePath - the HTTP relative path*/
00276                                             requestHttpHeaders,             /*HTTP_HEADERS_HANDLE requestHttpHeadersHandle - request HTTP headers*/
00277                                             NULL,                           /*BUFFER_HANDLE requestContent - NULL*/
00278                                             &statusCode,                    /*unsigned int* statusCode - the address of an unsigned int that will contain the HTTP status code*/
00279                                             NULL,                           /*HTTP_HEADERS_HANDLE responseHeadersHandle - NULL*/
00280                                             responseContent
00281                                         ) != HTTPAPIEX_OK)
00282                                         {
00283                                             /*Codes_SRS_IOTHUBCLIENT_LL_02_079: [ If HTTPAPIEX_SAS_ExecuteRequest fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00284                                             LogError("unable to HTTPAPIEX_SAS_ExecuteRequest");
00285                                             result = __LINE__;
00286                                         }
00287                                         else
00288                                         {
00289                                             if (statusCode >= 300)
00290                                             {
00291                                                 /*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. ]*/
00292                                                 result = __LINE__;
00293                                                 LogError("HTTP code was %u", statusCode);
00294                                             }
00295                                             else
00296                                             {
00297                                                 wasIoTHubRequestSuccess = 1;
00298                                             }
00299                                         }
00300                                         HTTPAPIEX_SAS_Destroy(sasHandle);
00301                                     }
00302                                     STRING_delete(empty);
00303                                 }
00304                             }
00305                             STRING_delete(uriResource);
00306                         }
00307                     }
00308                     } /*switch*/
00309 
00310                     if (wasIoTHubRequestSuccess == 0)
00311                     {
00312                         /*do nothing, shall be reported as an error*/
00313                     }
00314                     else
00315                     {
00316                         const unsigned char*responseContent_u_char = BUFFER_u_char(responseContent);
00317                         size_t responseContent_length = BUFFER_length(responseContent);
00318                         STRING_HANDLE responseAsString = STRING_from_byte_array(responseContent_u_char, responseContent_length);
00319                         if (responseAsString == NULL)
00320                         {
00321                             result = __LINE__;
00322                             LogError("unable to get the response as string");
00323                         }
00324                         else
00325                         {
00326                             /*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. ]*/
00327                             JSON_Value* allJson = json_parse_string(STRING_c_str(responseAsString));
00328                             if (allJson == NULL)
00329                             {
00330                                 /*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. ]*/
00331                                 LogError("unable to json_parse_string");
00332                                 result = __LINE__;
00333                             }
00334                             else
00335                             {
00336                                 JSON_Object* jsonObject = json_value_get_object(allJson);
00337                                 if (jsonObject == NULL)
00338                                 {
00339                                     /*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. ]*/
00340                                     LogError("unable to json_value_get_object");
00341                                     result = __LINE__;
00342                                 }
00343                                 else
00344                                 {
00345                                     const char* json_correlationId;
00346                                     json_correlationId = json_object_get_string(jsonObject, "correlationId");
00347                                     if (json_correlationId == NULL)
00348                                     {
00349                                         /*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. ]*/
00350                                         LogError("unable to json_object_get_string(jsonObject, \"correlationId\")");
00351                                         result = __LINE__;
00352                                     }
00353                                     else
00354                                     {
00355                                         if (STRING_copy(correlationId, json_correlationId) != 0)
00356                                         {
00357                                             /*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. ]*/
00358                                             LogError("unable to copy json_correlationId");
00359                                             result = __LINE__;
00360                                         }
00361                                         else
00362                                         {
00363                                             const char* json_hostName = json_object_get_string(jsonObject, "hostName");
00364                                             if (json_hostName == NULL)
00365                                             {
00366                                                 /*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. ]*/
00367                                                 LogError("unable to json_object_get_string(jsonObject, \"hostName\")");
00368                                                 result = __LINE__;
00369                                             }
00370                                             else
00371                                             {
00372                                                 const char* json_containerName = json_object_get_string(jsonObject, "containerName");
00373                                                 if (json_containerName == NULL)
00374                                                 {
00375                                                     /*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. ]*/
00376                                                     LogError("unable to json_object_get_string(jsonObject, \"containerName\")");
00377                                                     result = __LINE__;
00378                                                 }
00379                                                 else
00380                                                 {
00381                                                     const char* json_blobName = json_object_get_string(jsonObject, "blobName");
00382                                                     if (json_blobName == NULL)
00383                                                     {
00384                                                         /*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. ]*/
00385                                                         LogError("unable to json_object_get_string(jsonObject, \"blobName\")");
00386                                                         result = __LINE__;
00387                                                     }
00388                                                     else
00389                                                     {
00390                                                         const char* json_sasToken = json_object_get_string(jsonObject, "sasToken");
00391                                                         if (json_sasToken == NULL)
00392                                                         {
00393                                                             /*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. ]*/
00394                                                             LogError("unable to json_object_get_string(jsonObject, \"sasToken\")");
00395                                                             result = __LINE__;
00396                                                         }
00397                                                         else
00398                                                         {
00399                                                             /*good JSON received from the service*/
00400 
00401                                                             if (STRING_copy(sasUri, "https://") != 0)
00402                                                             {
00403                                                                 /*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. ]*/
00404                                                                 LogError("unable to STRING_copy");
00405                                                                 result = __LINE__;
00406                                                             }
00407                                                             else
00408                                                             {
00409                                                                 if (!(
00410                                                                     (STRING_concat(sasUri, json_hostName) == 0) &&
00411                                                                     (STRING_concat(sasUri, "/") == 0) &&
00412                                                                     (STRING_concat(sasUri, json_containerName) == 0) &&
00413                                                                     (STRING_concat(sasUri, "/") == 0) &&
00414                                                                     (STRING_concat(sasUri, json_blobName) == 0) &&
00415                                                                     (STRING_concat(sasUri, json_sasToken) == 0)
00416                                                                     ))
00417                                                                 {
00418                                                                     /*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. ]*/
00419                                                                     LogError("unable to STRING_concat");
00420                                                                     result = __LINE__;
00421                                                                 }
00422                                                                 else
00423                                                                 {
00424                                                                     result = 0; /*success in step 1*/
00425                                                                 }
00426                                                             }
00427                                                         }
00428                                                     }
00429                                                 }
00430                                             }
00431                                         }
00432                                     }
00433                                 }
00434                                 json_value_free(allJson);
00435                             }
00436                             STRING_delete(responseAsString);
00437                         }
00438                     }
00439                 }
00440                 BUFFER_delete(responseContent);
00441             }
00442         }
00443         STRING_delete(relativePath);
00444     }
00445 
00446     return result;
00447 }
00448 
00449 /*returns 0 when the IoTHub has been informed about the file upload status*/
00450 static int IoTHubClient_LL_UploadToBlob_step3(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* handleData, STRING_HANDLE correlationId, HTTPAPIEX_HANDLE iotHubHttpApiExHandle, HTTP_HEADERS_HANDLE requestHttpHeaders, BUFFER_HANDLE messageBody)
00451 {
00452     int result;
00453     /*here is step 3. depending on the outcome of step 2 it needs to inform IoTHub about the file upload status*/
00454     /*if step 1 failed, there's nothing that step 3 needs to report.*/
00455     /*this POST "tries" to happen*/
00456 
00457     /*Codes_SRS_IOTHUBCLIENT_LL_02_085: [ IoTHubClient_LL_UploadToBlob shall use the same authorization as step 1. to prepare and perform a HTTP request with the following parameters: ]*/
00458     STRING_HANDLE uriResource = STRING_construct(handleData->hostname);
00459     if (uriResource == NULL)
00460     {
00461         LogError("unable to construct URI");
00462         result = __LINE__;
00463     }
00464     else
00465     {
00466         if (!(
00467             (STRING_concat(uriResource, "/devices/") == 0) &&
00468             (STRING_concat_with_STRING(uriResource, handleData->deviceId) == 0) &&
00469             (STRING_concat(uriResource, "/files/notifications") == 0)
00470             ))
00471         {
00472             LogError("unable to STRING_concat");
00473             result = __LINE__;
00474         }
00475         else
00476         {
00477             STRING_HANDLE relativePathNotification = STRING_construct("/devices/");
00478             if (relativePathNotification == NULL)
00479             {
00480                 result = __LINE__;
00481                 LogError("unable to STRING_construct");
00482             }
00483             else
00484             {
00485                 if (!(
00486                     (STRING_concat_with_STRING(relativePathNotification, handleData->deviceId) == 0) &&
00487                     (STRING_concat(relativePathNotification, "/files/notifications/") == 0) &&
00488                     (STRING_concat(relativePathNotification, STRING_c_str(correlationId)) == 0) &&
00489                     (STRING_concat(relativePathNotification, API_VERSION) == 0)
00490                     ))
00491                 {
00492                     LogError("unable to STRING_concat_with_STRING");
00493                     result = __LINE__;
00494                 }
00495                 else
00496                 {
00497                     /*Codes_SRS_IOTHUBCLIENT_LL_02_086: [ If performing the HTTP request fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00498                     switch (handleData->authorizationScheme)
00499                     {
00500                     default:
00501                     {
00502                         LogError("internal error: unknown authorization Scheme");
00503                         result = __LINE__;
00504                         break;
00505                     }
00506                     case (DEVICE_KEY):
00507                     {
00508                         STRING_HANDLE empty = STRING_new();
00509                         if (empty == NULL)
00510                         {
00511                             LogError("unable to STRING_new");
00512                             result = __LINE__;
00513                         }
00514                         else
00515                         {
00516                             HTTPAPIEX_SAS_HANDLE sasHandle = HTTPAPIEX_SAS_Create(handleData->credentials.deviceKey, uriResource, empty);
00517                             if (sasHandle == NULL)
00518                             {
00519                                 LogError("unable to HTTPAPIEX_SAS_Create");
00520                                 result = __LINE__;
00521                             }
00522                             else
00523                             {
00524                                 unsigned int statusCode;
00525                                 if (HTTPAPIEX_SAS_ExecuteRequest(
00526                                     sasHandle,                      /*HTTPAPIEX_SAS_HANDLE sasHandle - the created HTTPAPIEX_SAS_HANDLE*/
00527                                     iotHubHttpApiExHandle,          /*HTTPAPIEX_HANDLE handle - the created HTTPAPIEX_HANDLE*/
00528                                     HTTPAPI_REQUEST_POST,            /*HTTPAPI_REQUEST_TYPE requestType - HTTPAPI_REQUEST_GET*/
00529                                     STRING_c_str(relativePathNotification),     /*const char* relativePath - the HTTP relative path*/
00530                                     requestHttpHeaders,             /*HTTP_HEADERS_HANDLE requestHttpHeadersHandle - request HTTP headers*/
00531                                     messageBody,                    /*BUFFER_HANDLE requestContent*/
00532                                     &statusCode,                    /*unsigned int* statusCode - the address of an unsigned int that will contain the HTTP status code*/
00533                                     NULL,                           /*HTTP_HEADERS_HANDLE responseHeadersHandle - NULL*/
00534                                     NULL
00535                                 ) != HTTPAPIEX_OK)
00536                                 {
00537                                     /*Codes_SRS_IOTHUBCLIENT_LL_02_079: [ If HTTPAPIEX_SAS_ExecuteRequest fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00538                                     LogError("unable to HTTPAPIEX_SAS_ExecuteRequest");
00539                                     result = __LINE__;
00540                                     ;
00541                                 }
00542                                 else
00543                                 {
00544                                     if (statusCode >= 300)
00545                                     {
00546                                         /*Codes_SRS_IOTHUBCLIENT_LL_02_087: [If the statusCode of the HTTP request is greater than or equal to 300 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR]*/
00547                                         result = __LINE__;
00548                                         LogError("HTTP code was %u", statusCode);
00549                                     }
00550                                     else
00551                                     {
00552                                         result = 0;
00553                                     }
00554                                 }
00555                                 HTTPAPIEX_SAS_Destroy(sasHandle);
00556                             }
00557                             STRING_delete(empty);
00558                         }
00559                         break;
00560                     }
00561                     case(SAS_TOKEN):
00562                     {
00563                         unsigned int notificationStatusCode;
00564                         if (HTTPAPIEX_ExecuteRequest(
00565                             iotHubHttpApiExHandle,
00566                             HTTPAPI_REQUEST_POST,
00567                             STRING_c_str(relativePathNotification),
00568                             requestHttpHeaders,
00569                             messageBody,
00570                             &notificationStatusCode,
00571                             NULL,
00572                             NULL) != HTTPAPIEX_OK)
00573                         {
00574                             LogError("unable to do HTTPAPIEX_ExecuteRequest");
00575                             result = __LINE__;
00576                         }
00577                         else
00578                         {
00579                             if (notificationStatusCode >= 300)
00580                             {
00581                                 /*Codes_SRS_IOTHUBCLIENT_LL_02_087: [If the statusCode of the HTTP request is greater than or equal to 300 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR]*/
00582                                 LogError("server didn't like the notification request");
00583                                 result = __LINE__;
00584                             }
00585                             else
00586                             {
00587                                 result = 0;
00588                             }
00589                         }
00590                         break;
00591                     }
00592                     } /*switch authorizationScheme*/
00593                 }
00594                 STRING_delete(relativePathNotification);
00595             }
00596         }
00597         STRING_delete(uriResource);
00598     }
00599     return result;
00600 }
00601 
00602 IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_Impl(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName, const unsigned char* source, size_t size)
00603 {
00604     IOTHUB_CLIENT_RESULT result;
00605 
00606     /*Codes_SRS_IOTHUBCLIENT_LL_02_061: [ If handle is NULL then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
00607     /*Codes_SRS_IOTHUBCLIENT_LL_02_062: [ If destinationFileName is NULL then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
00608     /*Codes_SRS_IOTHUBCLIENT_LL_02_063: [ If source is NULL and size is greater than 0 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
00609     if (
00610         (handle == NULL) ||
00611         (destinationFileName == NULL) ||
00612         ((source == NULL) && (size > 0)) ||
00613         (size >= 64*1024*1024)
00614         )
00615     {
00616         LogError("invalid argument detected handle=%p destinationFileName=%p source=%p size=%zu", handle, destinationFileName, source, size);
00617         result = IOTHUB_CLIENT_INVALID_ARG;
00618     }
00619     else
00620     {
00621         IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle;
00622 
00623         /*Codes_SRS_IOTHUBCLIENT_LL_02_064: [ IoTHubClient_LL_UploadToBlob shall create an HTTPAPIEX_HANDLE to the IoTHub hostname. ]*/
00624         HTTPAPIEX_HANDLE iotHubHttpApiExHandle = HTTPAPIEX_Create(handleData->hostname);
00625 
00626         /*Codes_SRS_IOTHUBCLIENT_LL_02_065: [ If creating the HTTPAPIEX_HANDLE fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00627         if (iotHubHttpApiExHandle == NULL)
00628         {
00629             LogError("unable to HTTPAPIEX_Create");
00630             result = IOTHUB_CLIENT_ERROR;
00631         }
00632         else
00633         {
00634             STRING_HANDLE correlationId = STRING_new();
00635             if (correlationId == NULL)
00636             {
00637                 LogError("unable to STRING_new");
00638                 result = IOTHUB_CLIENT_ERROR;
00639             }
00640             else
00641             {
00642                 STRING_HANDLE sasUri = STRING_new();
00643                 if (sasUri == NULL)
00644                 {
00645                     LogError("unable to STRING_new");
00646                     result = IOTHUB_CLIENT_ERROR;
00647                 }
00648                 else
00649                 {
00650                     /*Codes_SRS_IOTHUBCLIENT_LL_02_070: [ IoTHubClient_LL_UploadToBlob shall create request HTTP headers. ]*/
00651                     HTTP_HEADERS_HANDLE requestHttpHeaders = HTTPHeaders_Alloc(); /*these are build by step 1 and used by step 3 too*/
00652                     if (requestHttpHeaders == NULL)
00653                     {
00654                         LogError("unable to HTTPHeaders_Alloc");
00655                         result = IOTHUB_CLIENT_ERROR;
00656                     }
00657                     else
00658                     {
00659                         /*do step 1*/
00660                         if (IoTHubClient_LL_UploadToBlob_step1and2(handleData, iotHubHttpApiExHandle, requestHttpHeaders, destinationFileName, correlationId, sasUri) != 0)
00661                         {
00662                             LogError("error in IoTHubClient_LL_UploadToBlob_step1");
00663                             result = IOTHUB_CLIENT_ERROR;
00664                         }
00665                         else
00666                         {
00667                             /*do step 2.*/
00668 
00669                             unsigned int httpResponse;
00670                             BUFFER_HANDLE responseToIoTHub = BUFFER_new();
00671                             if (responseToIoTHub == NULL)
00672                             {
00673                                 result = IOTHUB_CLIENT_ERROR;
00674                                 LogError("unable to BUFFER_new");
00675                             }
00676                             else
00677                             {
00678                                 int step2success;
00679                                 /*Codes_SRS_IOTHUBCLIENT_LL_02_083: [ IoTHubClient_LL_UploadToBlob shall call Blob_UploadFromSasUri and capture the HTTP return code and HTTP body. ]*/
00680                                 step2success = (Blob_UploadFromSasUri(STRING_c_str(sasUri), source, size, &httpResponse, responseToIoTHub) == BLOB_OK);
00681                                 if (!step2success)
00682                                 {
00683                                     /*Codes_SRS_IOTHUBCLIENT_LL_02_084: [ If Blob_UploadFromSasUri fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/
00684                                     LogError("unable to Blob_UploadFromSasUri");
00685 
00686                                     /*do step 3*/ /*try*/
00687                                     /*Codes_SRS_IOTHUBCLIENT_LL_02_091: [ If step 2 fails without establishing an HTTP dialogue, then the HTTP message body shall look like: ]*/
00688                                     if (BUFFER_build(responseToIoTHub, (const unsigned char*)FILE_UPLOAD_FAILED_BODY, sizeof(FILE_UPLOAD_FAILED_BODY) / sizeof(FILE_UPLOAD_FAILED_BODY[0])) == 0)
00689                                     {
00690                                         if (IoTHubClient_LL_UploadToBlob_step3(handleData, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, responseToIoTHub) != 0)
00691                                         {
00692                                             LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
00693                                         }
00694                                     }
00695                                     result = IOTHUB_CLIENT_ERROR;
00696                                 }
00697                                 else
00698                                 {
00699                                     /*must make a json*/
00700 
00701                                     int requiredStringLength = snprintf(NULL, 0, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub));
00702 
00703                                     char* requiredString = malloc(requiredStringLength + 1);
00704                                     if (requiredString == 0)
00705                                     {
00706                                         LogError("unable to malloc");
00707                                         result = IOTHUB_CLIENT_ERROR;
00708                                     }
00709                                     else
00710                                     {
00711                                         /*do again snprintf*/
00712                                         (void)snprintf(requiredString, requiredStringLength + 1, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub));
00713                                         BUFFER_HANDLE toBeTransmitted = BUFFER_create(requiredString, requiredStringLength);
00714                                         if (toBeTransmitted == NULL)
00715                                         {
00716                                             LogError("unable to BUFFER_create");
00717                                             result = IOTHUB_CLIENT_ERROR;
00718                                         }
00719                                         else
00720                                         {
00721                                             if (IoTHubClient_LL_UploadToBlob_step3(handleData, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, toBeTransmitted) != 0)
00722                                             {
00723                                                 LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
00724                                                 result = IOTHUB_CLIENT_ERROR;
00725                                             }
00726                                             else
00727                                             {
00728                                                 result = (httpResponse < 300) ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR;
00729                                             }
00730                                             BUFFER_delete(toBeTransmitted);
00731                                         }
00732                                         free(requiredString);
00733                                     }
00734                                 }
00735                                 BUFFER_delete(responseToIoTHub);
00736                             }
00737                         }
00738                         HTTPHeaders_Free(requestHttpHeaders);
00739                     }
00740                     STRING_delete(sasUri);
00741                 }
00742                 STRING_delete(correlationId);
00743             }
00744             HTTPAPIEX_Destroy(iotHubHttpApiExHandle);
00745         }
00746     }
00747     return result;
00748 }
00749 
00750 void IoTHubClient_LL_UploadToBlob_Destroy(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle)
00751 {
00752     if (handle == NULL)
00753     {
00754         LogError("unexepected NULL argument");
00755     }
00756     else
00757     {
00758         IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle;
00759         switch (handleData->authorizationScheme)
00760         {
00761             case(SAS_TOKEN):
00762             {
00763                 STRING_delete(handleData->credentials.sas);
00764                 break;
00765             }
00766             case(DEVICE_KEY):
00767             {
00768                 STRING_delete(handleData->credentials.deviceKey);
00769                 break;
00770             }
00771             default:
00772             {
00773                 LogError("INTERNAL ERROR");
00774                 break;
00775             }
00776         }
00777         free((void*)handleData->hostname);
00778         STRING_delete(handleData->deviceId);
00779         free(handleData);
00780     }
00781 }