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
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 ¬ificationStatusCode, 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 }
Generated on Tue Jul 12 2022 19:44:54 by 1.7.2