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
Diff: iothub_client_ll_uploadtoblob.c
- Revision:
- 80:db5f5237bc95
- Parent:
- 79:bb88037c05e6
- Child:
- 82:f94e6bed4495
--- a/iothub_client_ll_uploadtoblob.c Fri Nov 17 13:57:39 2017 -0800 +++ b/iothub_client_ll_uploadtoblob.c Fri Dec 15 14:09:20 2017 -0800 @@ -71,6 +71,13 @@ HTTP_PROXY_OPTIONS http_proxy_options; }IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA; +typedef struct BLOB_UPLOAD_CONTEXT_TAG +{ + const unsigned char* blobSource; /* source to upload */ + size_t blobSourceSize; /* size of the source */ + size_t remainingSizeToUpload; /* size not yet uploaded */ +}BLOB_UPLOAD_CONTEXT; + IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE IoTHubClient_LL_UploadToBlob_Create(const IOTHUB_CLIENT_CONFIG* config) { IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* handleData = malloc(sizeof(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA)); @@ -168,11 +175,11 @@ { int result; - /*Codes_SRS_IOTHUBCLIENT_LL_02_066: [ IoTHubClient_LL_UploadToBlob shall create an HTTP relative path formed from "/devices/" + deviceId + "/files/" + "?api-version=API_VERSION". ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_066: [ IoTHubClient_LL_UploadMultipleBlocksToBlob shall create an HTTP relative path formed from "/devices/" + deviceId + "/files/" + "?api-version=API_VERSION". ]*/ STRING_HANDLE relativePath = STRING_construct("/devices/"); if (relativePath == NULL) { - /*Codes_SRS_IOTHUBCLIENT_LL_02_067: [ If creating the relativePath fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_067: [ If creating the relativePath fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to STRING_construct"); result = __FAILURE__; } @@ -184,17 +191,17 @@ (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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_067: [ If creating the relativePath fails then IoTHubClient_LL_UploadMultipleBlocksToBlob 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 + "\" }" */ + /*Codes_SRS_IOTHUBCLIENT_LL_32_001: [ IoTHubClient_LL_UploadMultipleBlocksToBlob 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to STRING_construct"); result = __FAILURE__; } @@ -205,7 +212,7 @@ (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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to concatenate STRING"); result = __FAILURE__; } @@ -216,23 +223,23 @@ 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadMultipleBlocksToBlob 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_068: [ IoTHubClient_LL_UploadMultipleBlocksToBlob 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_069: [ If creating the HTTP response buffer handle fails then IoTHubClient_LL_UploadMultipleBlocksToBlob 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_072: [ IoTHubClient_LL_UploadMultipleBlocksToBlob 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) && @@ -241,7 +248,7 @@ (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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_071: [ If creating the HTTP headers fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to HTTPHeaders_AddHeaderNameValuePair"); result = __FAILURE__; } @@ -262,9 +269,9 @@ case(X509): { unsigned int statusCode; - /*Codes_SRS_IOTHUBCLIENT_LL_32_003: [ IoTHubClient_LL_UploadToBlob shall execute HTTPAPIEX_ExecuteRequest passing the following information for arguments: ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_32_003: [ IoTHubClient_LL_UploadMultipleBlocksToBlob 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`*/ + iotHubHttpApiExHandle, /*HTTPAPIEX_HANDLE handle - the handle created at the beginning of `IoTHubClient_LL_UploadMultipleBlocksToBlob`*/ 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*/ @@ -274,13 +281,13 @@ 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_077: [ If HTTP statusCode is greater than or equal to 300 then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ if (statusCode >= 300) { result = __FAILURE__; @@ -296,19 +303,19 @@ 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: ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_073: [ If the credentials used to create handle have "sasToken" then IoTHubClient_LL_UploadMultipleBlocksToBlob 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 ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_074: [ If adding "Authorization" fails then IoTHubClient_LL_UploadMultipleBlocksToBlob 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: ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_32_004: [ IoTHubClient_LL_UploadMultipleBlocksToBlob 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`*/ + iotHubHttpApiExHandle, /*HTTPAPIEX_HANDLE handle - the handle created at the beginning of `IoTHubClient_LL_UploadMultipleBlocksToBlob`*/ 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*/ @@ -318,13 +325,13 @@ 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_077: [ If HTTP statusCode is greater than or equal to 300 then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ if (statusCode >= 300) { result = __FAILURE__; @@ -340,11 +347,11 @@ } 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: ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_078: [ If the credentials used to create handle have "deviceKey" then IoTHubClient_LL_UploadMultipleBlocksToBlob 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ result = __FAILURE__; LogError("unable to STRING_construct"); } @@ -355,7 +362,7 @@ (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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to STRING_concat_with_STRING"); result = __FAILURE__; } @@ -369,7 +376,7 @@ } 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ HTTPAPIEX_SAS_HANDLE sasHandle = HTTPAPIEX_SAS_Create(handleData->credentials.deviceKey, uriResource, empty); if (sasHandle == NULL) { @@ -379,7 +386,7 @@ else { unsigned int statusCode; - /*Codes_SRS_IOTHUBCLIENT_LL_32_005: [ IoTHubClient_LL_UploadToBlob shall call HTTPAPIEX_SAS_ExecuteRequest passing as arguments: ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_32_005: [ IoTHubClient_LL_UploadMultipleBlocksToBlob 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*/ @@ -392,7 +399,7 @@ 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_079: [ If HTTPAPIEX_SAS_ExecuteRequest fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to HTTPAPIEX_SAS_ExecuteRequest"); result = __FAILURE__; } @@ -400,7 +407,7 @@ { 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_080: [ If status code is greater than or equal to 300 then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ result = __FAILURE__; LogError("HTTP code was %u", statusCode); } @@ -435,11 +442,11 @@ } 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_081: [ Otherwise, IoTHubClient_LL_UploadMultipleBlocksToBlob 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to json_parse_string"); result = __FAILURE__; } @@ -448,7 +455,7 @@ 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to json_value_get_object"); result = __FAILURE__; } @@ -458,7 +465,7 @@ 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to json_object_get_string(jsonObject, \"correlationId\")"); result = __FAILURE__; } @@ -466,7 +473,7 @@ { 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to copy json_correlationId"); result = __FAILURE__; } @@ -475,7 +482,7 @@ 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to json_object_get_string(jsonObject, \"hostName\")"); result = __FAILURE__; } @@ -484,7 +491,7 @@ 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to json_object_get_string(jsonObject, \"containerName\")"); result = __FAILURE__; } @@ -493,7 +500,7 @@ 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to json_object_get_string(jsonObject, \"blobName\")"); result = __FAILURE__; } @@ -502,7 +509,7 @@ 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to json_object_get_string(jsonObject, \"sasToken\")"); result = __FAILURE__; } @@ -512,7 +519,7 @@ 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to STRING_copy"); result = __FAILURE__; } @@ -523,7 +530,7 @@ if (fileName == NULL) { - /*Codes_SRS_IOTHUBCLIENT_LL_32_009: [ If URL_EncodeString fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_32_009: [ If URL_EncodeString fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to URL_EncodeString of filename"); result = __FAILURE__; } @@ -539,7 +546,7 @@ (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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to STRING_concat"); result = __FAILURE__; } @@ -585,7 +592,7 @@ /*if step 1 failed, there's nothing that step 3 needs to report.*/ /*this POST "tries" to happen*/ - /*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: ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_085: [ IoTHubClient_LL_UploadMultipleBlocksToBlob shall use the same authorization as step 1. to prepare and perform a HTTP request with the following parameters: ]*/ STRING_HANDLE uriResource = STRING_construct(handleData->hostname); if (uriResource == NULL) { @@ -625,7 +632,7 @@ } else { - /*Codes_SRS_IOTHUBCLIENT_LL_02_086: [ If performing the HTTP request fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_086: [ If performing the HTTP request fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ switch (handleData->authorizationScheme) { default: @@ -654,7 +661,7 @@ { if (notificationStatusCode >= 300) { - /*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]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_087: [If the statusCode of the HTTP request is greater than or equal to 300 then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR]*/ LogError("server didn't like the notification request"); result = __FAILURE__; } @@ -696,7 +703,7 @@ NULL ) != HTTPAPIEX_OK) { - /*Codes_SRS_IOTHUBCLIENT_LL_02_079: [ If HTTPAPIEX_SAS_ExecuteRequest fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_079: [ If HTTPAPIEX_SAS_ExecuteRequest fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to HTTPAPIEX_SAS_ExecuteRequest"); result = __FAILURE__; ; @@ -705,7 +712,7 @@ { if (statusCode >= 300) { - /*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]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_087: [If the statusCode of the HTTP request is greater than or equal to 300 then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR]*/ result = __FAILURE__; LogError("HTTP code was %u", statusCode); } @@ -740,7 +747,7 @@ { if (notificationStatusCode >= 300) { - /*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]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_087: [If the statusCode of the HTTP request is greater than or equal to 300 then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR]*/ LogError("server didn't like the notification request"); result = __FAILURE__; } @@ -761,33 +768,61 @@ return result; } -IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_Impl(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName, const unsigned char* source, size_t size) +// this callback splits the source data into blocks to be fed to IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl +static void FileUpload_GetData_Callback(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* context) +{ + BLOB_UPLOAD_CONTEXT* uploadContext = (BLOB_UPLOAD_CONTEXT*) context; + + if (data == NULL || size == NULL) + { + // This is the last call, nothing to do + } + else if (result != FILE_UPLOAD_OK) + { + // Last call failed + *data = NULL; + *size = 0; + } + else if (uploadContext->remainingSizeToUpload == 0) + { + // Everything has been uploaded + *data = NULL; + *size = 0; + } + else + { + // Upload next block + size_t thisBlockSize = (uploadContext->remainingSizeToUpload > BLOCK_SIZE) ? BLOCK_SIZE : uploadContext->remainingSizeToUpload; + *data = (unsigned char*)uploadContext->blobSource + (uploadContext->blobSourceSize - uploadContext->remainingSizeToUpload); + *size = thisBlockSize; + uploadContext->remainingSizeToUpload -= thisBlockSize; + } +} + +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK getDataCallback, void* context) { IOTHUB_CLIENT_RESULT result; - BUFFER_HANDLE toBeTransmitted; - int requiredStringLength; - char* requiredString; - /*Codes_SRS_IOTHUBCLIENT_LL_02_061: [ If handle is NULL then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/ - /*Codes_SRS_IOTHUBCLIENT_LL_02_062: [ If destinationFileName is NULL then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/ - /*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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_061: [ If handle is NULL then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_062: [ If destinationFileName is NULL then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/ + if ( (handle == NULL) || (destinationFileName == NULL) || - ((source == NULL) && (size > 0)) + (getDataCallback == NULL) ) { - LogError("invalid argument detected handle=%p destinationFileName=%p source=%p size=%zu", handle, destinationFileName, source, size); + LogError("invalid argument detected handle=%p destinationFileName=%p getDataCallback=%p", handle, destinationFileName, getDataCallback); result = IOTHUB_CLIENT_INVALID_ARG; } else { IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle; - /*Codes_SRS_IOTHUBCLIENT_LL_02_064: [ IoTHubClient_LL_UploadToBlob shall create an HTTPAPIEX_HANDLE to the IoTHub hostname. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_064: [ IoTHubClient_LL_UploadMultipleBlocksToBlob shall create an HTTPAPIEX_HANDLE to the IoTHub hostname. ]*/ HTTPAPIEX_HANDLE iotHubHttpApiExHandle = HTTPAPIEX_Create(handleData->hostname); - /*Codes_SRS_IOTHUBCLIENT_LL_02_065: [ If creating the HTTPAPIEX_HANDLE fails then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_065: [ If creating the HTTPAPIEX_HANDLE fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ if (iotHubHttpApiExHandle == NULL) { LogError("unable to HTTPAPIEX_Create"); @@ -839,7 +874,7 @@ { result = IOTHUB_CLIENT_OK; } - + if (result != IOTHUB_CLIENT_ERROR) { STRING_HANDLE correlationId = STRING_new(); @@ -858,7 +893,7 @@ } else { - /*Codes_SRS_IOTHUBCLIENT_LL_02_070: [ IoTHubClient_LL_UploadToBlob shall create request HTTP headers. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_070: [ IoTHubClient_LL_UploadMultipleBlocksToBlob 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) { @@ -887,11 +922,11 @@ 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, &(handleData->http_proxy_options)) == BLOB_OK); + /*Codes_SRS_IOTHUBCLIENT_LL_02_083: [ IoTHubClient_LL_UploadMultipleBlocksToBlob shall call Blob_UploadFromSasUri and capture the HTTP return code and HTTP body. ]*/ + step2success = (Blob_UploadMultipleBlocksFromSasUri(STRING_c_str(sasUri), getDataCallback, context, &httpResponse, responseToIoTHub, handleData->certificates, &(handleData->http_proxy_options)) == 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. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_02_084: [ If Blob_UploadFromSasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob shall fail and return IOTHUB_CLIENT_ERROR. ]*/ LogError("unable to Blob_UploadFromSasUri"); /*do step 3*/ /*try*/ @@ -909,9 +944,9 @@ { /*must make a json*/ - requiredStringLength = snprintf(NULL, 0, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub)); + int requiredStringLength = snprintf(NULL, 0, "{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, BUFFER_u_char(responseToIoTHub)); - requiredString = malloc(requiredStringLength + 1); + char * requiredString = malloc(requiredStringLength + 1); if (requiredString == 0) { LogError("unable to malloc"); @@ -920,6 +955,7 @@ else { /*do again snprintf*/ + BUFFER_HANDLE toBeTransmitted = NULL; (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) @@ -958,6 +994,35 @@ HTTPAPIEX_Destroy(iotHubHttpApiExHandle); } } + + /*Codes_SRS_IOTHUBCLIENT_LL_99_003: [ If `IoTHubClient_LL_UploadMultipleBlocksToBlob` return `IOTHUB_CLIENT_OK`, it shall call `getDataCallback` with `result` set to `FILE_UPLOAD_OK`, and `data` and `size` set to NULL. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_99_004: [ If `IoTHubClient_LL_UploadMultipleBlocksToBlob` does not return `IOTHUB_CLIENT_OK`, it shall call `getDataCallback` with `result` set to `FILE_UPLOAD_ERROR`, and `data` and `size` set to NULL. ]*/ + getDataCallback(result == IOTHUB_CLIENT_OK ? FILE_UPLOAD_OK : FILE_UPLOAD_ERROR, NULL, NULL, context); + + return result; +} + +IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_Impl(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName, const unsigned char* source, size_t size) +{ + IOTHUB_CLIENT_RESULT result; + + /*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. ]*/ + if (source == NULL && size > 0) + { + LogError("invalid source and size combination: source=%p size=%zu", source, size); + result = IOTHUB_CLIENT_INVALID_ARG; + } + else + { + /*Codes_SRS_IOTHUBCLIENT_LL_99_001: [ `IoTHubClient_LL_UploadToBlob` shall create a struct containing the `source`, the `size`, and the remaining size to upload.]*/ + BLOB_UPLOAD_CONTEXT context; + context.blobSource = source; + context.blobSourceSize = size; + context.remainingSizeToUpload = size; + + /*Codes_SRS_IOTHUBCLIENT_LL_99_002: [ `IoTHubClient_LL_UploadToBlob` shall call `IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl` with `FileUpload_GetData_Callback` as `getDataCallback` and pass the struct created at step SRS_IOTHUBCLIENT_LL_99_001 as `context` ]*/ + result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(handle, destinationFileName, FileUpload_GetData_Callback, &context); + } return result; } @@ -1193,7 +1258,6 @@ return result; } - #endif /*DONT_USE_UPLOADTOBLOB*/