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

Committer:
AzureIoTClient
Date:
Thu Oct 04 09:15:49 2018 -0700
Revision:
93:7c0bbb86b167
Parent:
88:248736be106e
1.2.10

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AzureIoTClient 42:448eecc3676e 1 // Copyright (c) Microsoft. All rights reserved.
AzureIoTClient 42:448eecc3676e 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
AzureIoTClient 42:448eecc3676e 3
AzureIoTClient 42:448eecc3676e 4 #include <stdlib.h>
AzureIoTClient 62:5a4cdacf5090 5 #include <stdint.h>
AzureIoTClient 42:448eecc3676e 6 #include "azure_c_shared_utility/gballoc.h"
AzureIoTClient 88:248736be106e 7 #include "internal/blob.h"
AzureIoTClient 88:248736be106e 8 #include "internal/iothub_client_ll_uploadtoblob.h"
AzureIoTClient 42:448eecc3676e 9
AzureIoTClient 42:448eecc3676e 10 #include "azure_c_shared_utility/httpapiex.h"
Azure.IoT Build 45:54c11b1b1407 11 #include "azure_c_shared_utility/xlogging.h"
AzureIoTClient 43:038d8511e817 12 #include "azure_c_shared_utility/base64.h"
AzureIoTClient 79:bb88037c05e6 13 #include "azure_c_shared_utility/shared_util_options.h"
AzureIoTClient 43:038d8511e817 14
AzureIoTClient 80:db5f5237bc95 15 BLOB_RESULT Blob_UploadBlock(
AzureIoTClient 80:db5f5237bc95 16 HTTPAPIEX_HANDLE httpApiExHandle,
AzureIoTClient 80:db5f5237bc95 17 const char* relativePath,
AzureIoTClient 80:db5f5237bc95 18 BUFFER_HANDLE requestContent,
AzureIoTClient 80:db5f5237bc95 19 unsigned int blockID,
AzureIoTClient 80:db5f5237bc95 20 STRING_HANDLE blockIDList,
AzureIoTClient 80:db5f5237bc95 21 unsigned int* httpStatus,
AzureIoTClient 80:db5f5237bc95 22 BUFFER_HANDLE httpResponse)
AzureIoTClient 42:448eecc3676e 23 {
AzureIoTClient 42:448eecc3676e 24 BLOB_RESULT result;
AzureIoTClient 80:db5f5237bc95 25
AzureIoTClient 80:db5f5237bc95 26 if (requestContent == NULL ||
AzureIoTClient 80:db5f5237bc95 27 blockIDList == NULL ||
AzureIoTClient 80:db5f5237bc95 28 relativePath == NULL ||
AzureIoTClient 80:db5f5237bc95 29 httpApiExHandle == NULL ||
AzureIoTClient 80:db5f5237bc95 30 httpStatus == NULL ||
AzureIoTClient 80:db5f5237bc95 31 httpResponse == NULL)
AzureIoTClient 80:db5f5237bc95 32 {
AzureIoTClient 80:db5f5237bc95 33 LogError("invalid argument detected requestContent=%p blockIDList=%p relativePath=%p httpApiExHandle=%p httpStatus=%p httpResponse=%p", requestContent, blockIDList, relativePath, httpApiExHandle, httpStatus, httpResponse);
AzureIoTClient 80:db5f5237bc95 34 result = BLOB_ERROR;
AzureIoTClient 80:db5f5237bc95 35 }
AzureIoTClient 80:db5f5237bc95 36 else
AzureIoTClient 80:db5f5237bc95 37 {
AzureIoTClient 80:db5f5237bc95 38 char temp[7]; /*this will contain 000000... 049999*/
AzureIoTClient 80:db5f5237bc95 39 if (sprintf(temp, "%6u", (unsigned int)blockID) != 6) /*produces 000000... 049999*/
AzureIoTClient 80:db5f5237bc95 40 {
AzureIoTClient 80:db5f5237bc95 41 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 80:db5f5237bc95 42 LogError("failed to sprintf");
AzureIoTClient 80:db5f5237bc95 43 result = BLOB_ERROR;
AzureIoTClient 80:db5f5237bc95 44 }
AzureIoTClient 80:db5f5237bc95 45 else
AzureIoTClient 80:db5f5237bc95 46 {
AzureIoTClient 80:db5f5237bc95 47 STRING_HANDLE blockIdString = Base64_Encode_Bytes((const unsigned char*)temp, 6);
AzureIoTClient 80:db5f5237bc95 48 if (blockIdString == NULL)
AzureIoTClient 80:db5f5237bc95 49 {
AzureIoTClient 80:db5f5237bc95 50 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 80:db5f5237bc95 51 LogError("unable to Base64_Encode_Bytes");
AzureIoTClient 80:db5f5237bc95 52 result = BLOB_ERROR;
AzureIoTClient 80:db5f5237bc95 53 }
AzureIoTClient 80:db5f5237bc95 54 else
AzureIoTClient 80:db5f5237bc95 55 {
AzureIoTClient 80:db5f5237bc95 56 /*add the blockId base64 encoded to the XML*/
AzureIoTClient 80:db5f5237bc95 57 if (!(
AzureIoTClient 80:db5f5237bc95 58 (STRING_concat(blockIDList, "<Latest>") == 0) &&
AzureIoTClient 80:db5f5237bc95 59 (STRING_concat_with_STRING(blockIDList, blockIdString) == 0) &&
AzureIoTClient 80:db5f5237bc95 60 (STRING_concat(blockIDList, "</Latest>") == 0)
AzureIoTClient 80:db5f5237bc95 61 ))
AzureIoTClient 80:db5f5237bc95 62 {
AzureIoTClient 80:db5f5237bc95 63 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 80:db5f5237bc95 64 LogError("unable to STRING_concat");
AzureIoTClient 80:db5f5237bc95 65 result = BLOB_ERROR;
AzureIoTClient 80:db5f5237bc95 66 }
AzureIoTClient 80:db5f5237bc95 67 else
AzureIoTClient 80:db5f5237bc95 68 {
AzureIoTClient 80:db5f5237bc95 69 /*Codes_SRS_BLOB_02_022: [ Blob_UploadMultipleBlocksFromSasUri shall construct a new relativePath from following string: base relativePath + "&comp=block&blockid=BASE64 encoded string of blockId" ]*/
AzureIoTClient 80:db5f5237bc95 70 STRING_HANDLE newRelativePath = STRING_construct(relativePath);
AzureIoTClient 80:db5f5237bc95 71 if (newRelativePath == NULL)
AzureIoTClient 80:db5f5237bc95 72 {
AzureIoTClient 80:db5f5237bc95 73 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 80:db5f5237bc95 74 LogError("unable to STRING_construct");
AzureIoTClient 80:db5f5237bc95 75 result = BLOB_ERROR;
AzureIoTClient 80:db5f5237bc95 76 }
AzureIoTClient 80:db5f5237bc95 77 else
AzureIoTClient 80:db5f5237bc95 78 {
AzureIoTClient 80:db5f5237bc95 79 if (!(
AzureIoTClient 80:db5f5237bc95 80 (STRING_concat(newRelativePath, "&comp=block&blockid=") == 0) &&
AzureIoTClient 80:db5f5237bc95 81 (STRING_concat_with_STRING(newRelativePath, blockIdString) == 0)
AzureIoTClient 80:db5f5237bc95 82 ))
AzureIoTClient 80:db5f5237bc95 83 {
AzureIoTClient 80:db5f5237bc95 84 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 80:db5f5237bc95 85 LogError("unable to STRING concatenate");
AzureIoTClient 80:db5f5237bc95 86 result = BLOB_ERROR;
AzureIoTClient 80:db5f5237bc95 87 }
AzureIoTClient 80:db5f5237bc95 88 else
AzureIoTClient 80:db5f5237bc95 89 {
AzureIoTClient 80:db5f5237bc95 90 /*Codes_SRS_BLOB_02_024: [ Blob_UploadMultipleBlocksFromSasUri shall call HTTPAPIEX_ExecuteRequest with a PUT operation, passing httpStatus and httpResponse. ]*/
AzureIoTClient 80:db5f5237bc95 91 if (HTTPAPIEX_ExecuteRequest(
AzureIoTClient 80:db5f5237bc95 92 httpApiExHandle,
AzureIoTClient 80:db5f5237bc95 93 HTTPAPI_REQUEST_PUT,
AzureIoTClient 80:db5f5237bc95 94 STRING_c_str(newRelativePath),
AzureIoTClient 80:db5f5237bc95 95 NULL,
AzureIoTClient 80:db5f5237bc95 96 requestContent,
AzureIoTClient 80:db5f5237bc95 97 httpStatus,
AzureIoTClient 80:db5f5237bc95 98 NULL,
AzureIoTClient 80:db5f5237bc95 99 httpResponse) != HTTPAPIEX_OK
AzureIoTClient 80:db5f5237bc95 100 )
AzureIoTClient 80:db5f5237bc95 101 {
AzureIoTClient 80:db5f5237bc95 102 /*Codes_SRS_BLOB_02_025: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/
AzureIoTClient 80:db5f5237bc95 103 LogError("unable to HTTPAPIEX_ExecuteRequest");
AzureIoTClient 80:db5f5237bc95 104 result = BLOB_HTTP_ERROR;
AzureIoTClient 80:db5f5237bc95 105 }
AzureIoTClient 80:db5f5237bc95 106 else if (*httpStatus >= 300)
AzureIoTClient 80:db5f5237bc95 107 {
AzureIoTClient 80:db5f5237bc95 108 /*Codes_SRS_BLOB_02_026: [ Otherwise, if HTTP response code is >=300 then Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
AzureIoTClient 80:db5f5237bc95 109 LogError("HTTP status from storage does not indicate success (%d)", (int)*httpStatus);
AzureIoTClient 80:db5f5237bc95 110 result = BLOB_OK;
AzureIoTClient 80:db5f5237bc95 111 }
AzureIoTClient 80:db5f5237bc95 112 else
AzureIoTClient 80:db5f5237bc95 113 {
AzureIoTClient 80:db5f5237bc95 114 /*Codes_SRS_BLOB_02_027: [ Otherwise Blob_UploadMultipleBlocksFromSasUri shall continue execution. ]*/
AzureIoTClient 80:db5f5237bc95 115 result = BLOB_OK;
AzureIoTClient 80:db5f5237bc95 116 }
AzureIoTClient 80:db5f5237bc95 117 }
AzureIoTClient 80:db5f5237bc95 118 STRING_delete(newRelativePath);
AzureIoTClient 80:db5f5237bc95 119 }
AzureIoTClient 80:db5f5237bc95 120 }
AzureIoTClient 80:db5f5237bc95 121 STRING_delete(blockIdString);
AzureIoTClient 80:db5f5237bc95 122 }
AzureIoTClient 80:db5f5237bc95 123 }
AzureIoTClient 80:db5f5237bc95 124 }
AzureIoTClient 80:db5f5237bc95 125 return result;
AzureIoTClient 80:db5f5237bc95 126 }
AzureIoTClient 80:db5f5237bc95 127
AzureIoTClient 82:f94e6bed4495 128 BLOB_RESULT Blob_UploadMultipleBlocksFromSasUri(const char* SASURI, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context, unsigned int* httpStatus, BUFFER_HANDLE httpResponse, const char* certificates, HTTP_PROXY_OPTIONS *proxyOptions)
AzureIoTClient 80:db5f5237bc95 129 {
AzureIoTClient 80:db5f5237bc95 130 BLOB_RESULT result;
AzureIoTClient 80:db5f5237bc95 131 /*Codes_SRS_BLOB_02_001: [ If SASURI is NULL then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
AzureIoTClient 42:448eecc3676e 132 if (SASURI == NULL)
AzureIoTClient 42:448eecc3676e 133 {
AzureIoTClient 42:448eecc3676e 134 LogError("parameter SASURI is NULL");
AzureIoTClient 42:448eecc3676e 135 result = BLOB_INVALID_ARG;
AzureIoTClient 42:448eecc3676e 136 }
AzureIoTClient 42:448eecc3676e 137 else
AzureIoTClient 42:448eecc3676e 138 {
AzureIoTClient 82:f94e6bed4495 139 /*Codes_SRS_BLOB_02_002: [ If getDataCallbackEx is NULL then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
AzureIoTClient 82:f94e6bed4495 140 if (getDataCallbackEx == NULL)
AzureIoTClient 42:448eecc3676e 141 {
AzureIoTClient 82:f94e6bed4495 142 LogError("IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx is NULL");
AzureIoTClient 42:448eecc3676e 143 result = BLOB_INVALID_ARG;
AzureIoTClient 42:448eecc3676e 144 }
AzureIoTClient 62:5a4cdacf5090 145 /*the below define avoid a "condition always false" on some compilers*/
AzureIoTClient 42:448eecc3676e 146 else
AzureIoTClient 42:448eecc3676e 147 {
AzureIoTClient 80:db5f5237bc95 148 /*Codes_SRS_BLOB_02_017: [ Blob_UploadMultipleBlocksFromSasUri shall copy from SASURI the hostname to a new const char* ]*/
AzureIoTClient 42:448eecc3676e 149 /*to find the hostname, the following logic is applied:*/
AzureIoTClient 42:448eecc3676e 150 /*the hostname starts at the first character after "://"*/
AzureIoTClient 42:448eecc3676e 151 /*the hostname ends at the first character before the next "/" after "://"*/
AzureIoTClient 42:448eecc3676e 152 const char* hostnameBegin = strstr(SASURI, "://");
AzureIoTClient 42:448eecc3676e 153 if (hostnameBegin == NULL)
AzureIoTClient 42:448eecc3676e 154 {
AzureIoTClient 80:db5f5237bc95 155 /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
AzureIoTClient 42:448eecc3676e 156 LogError("hostname cannot be determined");
AzureIoTClient 42:448eecc3676e 157 result = BLOB_INVALID_ARG;
AzureIoTClient 42:448eecc3676e 158 }
AzureIoTClient 42:448eecc3676e 159 else
AzureIoTClient 42:448eecc3676e 160 {
AzureIoTClient 42:448eecc3676e 161 hostnameBegin += 3; /*have to skip 3 characters which are "://"*/
AzureIoTClient 42:448eecc3676e 162 const char* hostnameEnd = strchr(hostnameBegin, '/');
AzureIoTClient 42:448eecc3676e 163 if (hostnameEnd == NULL)
AzureIoTClient 42:448eecc3676e 164 {
AzureIoTClient 80:db5f5237bc95 165 /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
AzureIoTClient 42:448eecc3676e 166 LogError("hostname cannot be determined");
AzureIoTClient 42:448eecc3676e 167 result = BLOB_INVALID_ARG;
AzureIoTClient 42:448eecc3676e 168 }
AzureIoTClient 42:448eecc3676e 169 else
AzureIoTClient 42:448eecc3676e 170 {
AzureIoTClient 42:448eecc3676e 171 size_t hostnameSize = hostnameEnd - hostnameBegin;
AzureIoTClient 42:448eecc3676e 172 char* hostname = (char*)malloc(hostnameSize + 1); /*+1 because of '\0' at the end*/
AzureIoTClient 42:448eecc3676e 173 if (hostname == NULL)
AzureIoTClient 42:448eecc3676e 174 {
AzureIoTClient 80:db5f5237bc95 175 /*Codes_SRS_BLOB_02_016: [ If the hostname copy cannot be made then then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 42:448eecc3676e 176 LogError("oom - out of memory");
AzureIoTClient 42:448eecc3676e 177 result = BLOB_ERROR;
AzureIoTClient 42:448eecc3676e 178 }
AzureIoTClient 42:448eecc3676e 179 else
AzureIoTClient 42:448eecc3676e 180 {
AzureIoTClient 42:448eecc3676e 181 HTTPAPIEX_HANDLE httpApiExHandle;
AzureIoTClient 58:15b0d29b2667 182 (void)memcpy(hostname, hostnameBegin, hostnameSize);
AzureIoTClient 42:448eecc3676e 183 hostname[hostnameSize] = '\0';
AzureIoTClient 42:448eecc3676e 184
AzureIoTClient 80:db5f5237bc95 185 /*Codes_SRS_BLOB_02_018: [ Blob_UploadMultipleBlocksFromSasUri shall create a new HTTPAPI_EX_HANDLE by calling HTTPAPIEX_Create passing the hostname. ]*/
AzureIoTClient 42:448eecc3676e 186 httpApiExHandle = HTTPAPIEX_Create(hostname);
AzureIoTClient 42:448eecc3676e 187 if (httpApiExHandle == NULL)
AzureIoTClient 42:448eecc3676e 188 {
AzureIoTClient 80:db5f5237bc95 189 /*Codes_SRS_BLOB_02_007: [ If HTTPAPIEX_Create fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR. ]*/
AzureIoTClient 42:448eecc3676e 190 LogError("unable to create a HTTPAPIEX_HANDLE");
AzureIoTClient 42:448eecc3676e 191 result = BLOB_ERROR;
AzureIoTClient 42:448eecc3676e 192 }
AzureIoTClient 42:448eecc3676e 193 else
AzureIoTClient 42:448eecc3676e 194 {
AzureIoTClient 62:5a4cdacf5090 195 if ((certificates != NULL)&& (HTTPAPIEX_SetOption(httpApiExHandle, "TrustedCerts", certificates) == HTTPAPIEX_ERROR))
AzureIoTClient 62:5a4cdacf5090 196 {
AzureIoTClient 62:5a4cdacf5090 197 LogError("failure in setting trusted certificates");
AzureIoTClient 62:5a4cdacf5090 198 result = BLOB_ERROR;
AzureIoTClient 62:5a4cdacf5090 199 }
AzureIoTClient 80:db5f5237bc95 200 else if ((proxyOptions != NULL && proxyOptions->host_address != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_PROXY, proxyOptions) == HTTPAPIEX_ERROR)
AzureIoTClient 80:db5f5237bc95 201 {
AzureIoTClient 80:db5f5237bc95 202 LogError("failure in setting proxy options");
AzureIoTClient 80:db5f5237bc95 203 result = BLOB_ERROR;
AzureIoTClient 80:db5f5237bc95 204 }
AzureIoTClient 62:5a4cdacf5090 205 else
AzureIoTClient 62:5a4cdacf5090 206 {
AzureIoTClient 80:db5f5237bc95 207 /*Codes_SRS_BLOB_02_019: [ Blob_UploadMultipleBlocksFromSasUri shall compute the base relative path of the request from the SASURI parameter. ]*/
AzureIoTClient 80:db5f5237bc95 208 const char* relativePath = hostnameEnd; /*this is where the relative path begins in the SasUri*/
AzureIoTClient 80:db5f5237bc95 209
AzureIoTClient 80:db5f5237bc95 210 /*Codes_SRS_BLOB_02_028: [ Blob_UploadMultipleBlocksFromSasUri shall construct an XML string with the following content: ]*/
AzureIoTClient 80:db5f5237bc95 211 STRING_HANDLE blockIDList = STRING_construct("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<BlockList>"); /*the XML "build as we go"*/
AzureIoTClient 80:db5f5237bc95 212 if (blockIDList == NULL)
AzureIoTClient 79:bb88037c05e6 213 {
AzureIoTClient 80:db5f5237bc95 214 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 80:db5f5237bc95 215 LogError("failed to STRING_construct");
AzureIoTClient 80:db5f5237bc95 216 result = BLOB_HTTP_ERROR;
AzureIoTClient 79:bb88037c05e6 217 }
AzureIoTClient 79:bb88037c05e6 218 else
AzureIoTClient 42:448eecc3676e 219 {
AzureIoTClient 82:f94e6bed4495 220 /*Codes_SRS_BLOB_02_021: [ For every block returned by `getDataCallbackEx` the following operations shall happen: ]*/
AzureIoTClient 80:db5f5237bc95 221 unsigned int blockID = 0; /* incremented for each new block */
AzureIoTClient 82:f94e6bed4495 222 unsigned int isError = 0; /* set to 1 if a block upload fails or if getDataCallbackEx returns incorrect blocks to upload */
AzureIoTClient 82:f94e6bed4495 223 unsigned int uploadOneMoreBlock = 1; /* set to 1 while getDataCallbackEx returns correct blocks to upload */
AzureIoTClient 82:f94e6bed4495 224 unsigned char const * source; /* data set by getDataCallbackEx */
AzureIoTClient 82:f94e6bed4495 225 size_t size; /* source size set by getDataCallbackEx */
AzureIoTClient 82:f94e6bed4495 226 IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataReturnValue;
AzureIoTClient 80:db5f5237bc95 227
AzureIoTClient 82:f94e6bed4495 228 do
AzureIoTClient 80:db5f5237bc95 229 {
AzureIoTClient 82:f94e6bed4495 230 getDataReturnValue = getDataCallbackEx(FILE_UPLOAD_OK, &source, &size, context);
AzureIoTClient 82:f94e6bed4495 231 if (getDataReturnValue == IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT)
AzureIoTClient 80:db5f5237bc95 232 {
AzureIoTClient 82:f94e6bed4495 233 /*Codes_SRS_BLOB_99_004: [ If `getDataCallbackEx` returns `IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT_ABORT`, then `Blob_UploadMultipleBlocksFromSasUri` shall exit the loop and return `BLOB_ABORTED`. ]*/
AzureIoTClient 82:f94e6bed4495 234 LogInfo("Upload to blob has been aborted by the user");
AzureIoTClient 82:f94e6bed4495 235 uploadOneMoreBlock = 0;
AzureIoTClient 82:f94e6bed4495 236 result = BLOB_ABORTED;
AzureIoTClient 82:f94e6bed4495 237 }
AzureIoTClient 82:f94e6bed4495 238 else if (source == NULL || size == 0)
AzureIoTClient 82:f94e6bed4495 239 {
AzureIoTClient 82:f94e6bed4495 240 /*Codes_SRS_BLOB_99_002: [ If the size of the block returned by `getDataCallbackEx` is 0 or if the data is NULL, then `Blob_UploadMultipleBlocksFromSasUri` shall exit the loop. ]*/
AzureIoTClient 82:f94e6bed4495 241 uploadOneMoreBlock = 0;
AzureIoTClient 82:f94e6bed4495 242 result = BLOB_OK;
AzureIoTClient 80:db5f5237bc95 243 }
AzureIoTClient 80:db5f5237bc95 244 else
AzureIoTClient 80:db5f5237bc95 245 {
AzureIoTClient 82:f94e6bed4495 246 if (size > BLOCK_SIZE)
AzureIoTClient 80:db5f5237bc95 247 {
AzureIoTClient 82:f94e6bed4495 248 /*Codes_SRS_BLOB_99_001: [ If the size of the block returned by `getDataCallbackEx` is bigger than 4MB, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/
AzureIoTClient 82:f94e6bed4495 249 LogError("tried to upload block of size %zu, max allowed size is %d", size, BLOCK_SIZE);
AzureIoTClient 82:f94e6bed4495 250 result = BLOB_INVALID_ARG;
AzureIoTClient 82:f94e6bed4495 251 isError = 1;
AzureIoTClient 82:f94e6bed4495 252 }
AzureIoTClient 82:f94e6bed4495 253 else if (blockID >= MAX_BLOCK_COUNT)
AzureIoTClient 82:f94e6bed4495 254 {
AzureIoTClient 82:f94e6bed4495 255 /*Codes_SRS_BLOB_99_003: [ If `getDataCallbackEx` returns more than 50000 blocks, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/
AzureIoTClient 82:f94e6bed4495 256 LogError("unable to upload more than %zu blocks in one blob", MAX_BLOCK_COUNT);
AzureIoTClient 82:f94e6bed4495 257 result = BLOB_INVALID_ARG;
AzureIoTClient 82:f94e6bed4495 258 isError = 1;
AzureIoTClient 80:db5f5237bc95 259 }
AzureIoTClient 80:db5f5237bc95 260 else
AzureIoTClient 80:db5f5237bc95 261 {
AzureIoTClient 82:f94e6bed4495 262 /*Codes_SRS_BLOB_02_023: [ Blob_UploadMultipleBlocksFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/
AzureIoTClient 82:f94e6bed4495 263 BUFFER_HANDLE requestContent = BUFFER_create(source, size);
AzureIoTClient 82:f94e6bed4495 264 if (requestContent == NULL)
AzureIoTClient 80:db5f5237bc95 265 {
AzureIoTClient 82:f94e6bed4495 266 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 82:f94e6bed4495 267 LogError("unable to BUFFER_create");
AzureIoTClient 82:f94e6bed4495 268 result = BLOB_ERROR;
AzureIoTClient 80:db5f5237bc95 269 isError = 1;
AzureIoTClient 80:db5f5237bc95 270 }
AzureIoTClient 82:f94e6bed4495 271 else
AzureIoTClient 80:db5f5237bc95 272 {
AzureIoTClient 82:f94e6bed4495 273 result = Blob_UploadBlock(
AzureIoTClient 82:f94e6bed4495 274 httpApiExHandle,
AzureIoTClient 82:f94e6bed4495 275 relativePath,
AzureIoTClient 82:f94e6bed4495 276 requestContent,
AzureIoTClient 82:f94e6bed4495 277 blockID,
AzureIoTClient 82:f94e6bed4495 278 blockIDList,
AzureIoTClient 82:f94e6bed4495 279 httpStatus,
AzureIoTClient 82:f94e6bed4495 280 httpResponse);
AzureIoTClient 82:f94e6bed4495 281
AzureIoTClient 82:f94e6bed4495 282 BUFFER_delete(requestContent);
AzureIoTClient 82:f94e6bed4495 283 }
AzureIoTClient 82:f94e6bed4495 284
AzureIoTClient 82:f94e6bed4495 285 /*Codes_SRS_BLOB_02_026: [ Otherwise, if HTTP response code is >=300 then Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
AzureIoTClient 82:f94e6bed4495 286 if (result != BLOB_OK || *httpStatus >= 300)
AzureIoTClient 82:f94e6bed4495 287 {
AzureIoTClient 93:7c0bbb86b167 288 LogError("unable to Blob_UploadBlock. Returned value=%d, httpStatus=%u", result, (unsigned int)*httpStatus);
AzureIoTClient 80:db5f5237bc95 289 isError = 1;
AzureIoTClient 80:db5f5237bc95 290 }
AzureIoTClient 80:db5f5237bc95 291 }
AzureIoTClient 82:f94e6bed4495 292 blockID++;
AzureIoTClient 80:db5f5237bc95 293 }
AzureIoTClient 80:db5f5237bc95 294 }
AzureIoTClient 82:f94e6bed4495 295 while(uploadOneMoreBlock && !isError);
AzureIoTClient 80:db5f5237bc95 296
AzureIoTClient 82:f94e6bed4495 297 if (isError || result != BLOB_OK)
AzureIoTClient 80:db5f5237bc95 298 {
AzureIoTClient 80:db5f5237bc95 299 /*do nothing, it will be reported "as is"*/
AzureIoTClient 80:db5f5237bc95 300 }
AzureIoTClient 80:db5f5237bc95 301 else
AzureIoTClient 80:db5f5237bc95 302 {
AzureIoTClient 80:db5f5237bc95 303 /*complete the XML*/
AzureIoTClient 80:db5f5237bc95 304 if (STRING_concat(blockIDList, "</BlockList>") != 0)
AzureIoTClient 80:db5f5237bc95 305 {
AzureIoTClient 80:db5f5237bc95 306 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 80:db5f5237bc95 307 LogError("failed to STRING_concat");
AzureIoTClient 43:038d8511e817 308 result = BLOB_ERROR;
AzureIoTClient 43:038d8511e817 309 }
AzureIoTClient 43:038d8511e817 310 else
AzureIoTClient 42:448eecc3676e 311 {
AzureIoTClient 80:db5f5237bc95 312 /*Codes_SRS_BLOB_02_029: [Blob_UploadMultipleBlocksFromSasUri shall construct a new relativePath from following string : base relativePath + "&comp=blocklist"]*/
AzureIoTClient 80:db5f5237bc95 313 STRING_HANDLE newRelativePath = STRING_construct(relativePath);
AzureIoTClient 80:db5f5237bc95 314 if (newRelativePath == NULL)
AzureIoTClient 43:038d8511e817 315 {
AzureIoTClient 80:db5f5237bc95 316 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 80:db5f5237bc95 317 LogError("failed to STRING_construct");
AzureIoTClient 62:5a4cdacf5090 318 result = BLOB_ERROR;
AzureIoTClient 43:038d8511e817 319 }
AzureIoTClient 43:038d8511e817 320 else
AzureIoTClient 43:038d8511e817 321 {
AzureIoTClient 80:db5f5237bc95 322 if (STRING_concat(newRelativePath, "&comp=blocklist") != 0)
AzureIoTClient 43:038d8511e817 323 {
AzureIoTClient 80:db5f5237bc95 324 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 79:bb88037c05e6 325 LogError("failed to STRING_concat");
AzureIoTClient 43:038d8511e817 326 result = BLOB_ERROR;
AzureIoTClient 43:038d8511e817 327 }
AzureIoTClient 43:038d8511e817 328 else
AzureIoTClient 43:038d8511e817 329 {
AzureIoTClient 80:db5f5237bc95 330 /*Codes_SRS_BLOB_02_030: [ Blob_UploadMultipleBlocksFromSasUri shall call HTTPAPIEX_ExecuteRequest with a PUT operation, passing the new relativePath, httpStatus and httpResponse and the XML string as content. ]*/
AzureIoTClient 80:db5f5237bc95 331 const char* s = STRING_c_str(blockIDList);
AzureIoTClient 80:db5f5237bc95 332 BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s));
AzureIoTClient 80:db5f5237bc95 333 if (blockIDListAsBuffer == NULL)
AzureIoTClient 43:038d8511e817 334 {
AzureIoTClient 80:db5f5237bc95 335 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
AzureIoTClient 80:db5f5237bc95 336 LogError("failed to BUFFER_create");
AzureIoTClient 43:038d8511e817 337 result = BLOB_ERROR;
AzureIoTClient 43:038d8511e817 338 }
AzureIoTClient 43:038d8511e817 339 else
AzureIoTClient 43:038d8511e817 340 {
AzureIoTClient 80:db5f5237bc95 341 if (HTTPAPIEX_ExecuteRequest(
AzureIoTClient 80:db5f5237bc95 342 httpApiExHandle,
AzureIoTClient 80:db5f5237bc95 343 HTTPAPI_REQUEST_PUT,
AzureIoTClient 80:db5f5237bc95 344 STRING_c_str(newRelativePath),
AzureIoTClient 80:db5f5237bc95 345 NULL,
AzureIoTClient 80:db5f5237bc95 346 blockIDListAsBuffer,
AzureIoTClient 80:db5f5237bc95 347 httpStatus,
AzureIoTClient 80:db5f5237bc95 348 NULL,
AzureIoTClient 80:db5f5237bc95 349 httpResponse
AzureIoTClient 80:db5f5237bc95 350 ) != HTTPAPIEX_OK)
AzureIoTClient 43:038d8511e817 351 {
AzureIoTClient 80:db5f5237bc95 352 /*Codes_SRS_BLOB_02_031: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/
AzureIoTClient 80:db5f5237bc95 353 LogError("unable to HTTPAPIEX_ExecuteRequest");
AzureIoTClient 80:db5f5237bc95 354 result = BLOB_HTTP_ERROR;
AzureIoTClient 43:038d8511e817 355 }
AzureIoTClient 43:038d8511e817 356 else
AzureIoTClient 43:038d8511e817 357 {
AzureIoTClient 80:db5f5237bc95 358 /*Codes_SRS_BLOB_02_032: [ Otherwise, Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
AzureIoTClient 80:db5f5237bc95 359 result = BLOB_OK;
AzureIoTClient 43:038d8511e817 360 }
AzureIoTClient 80:db5f5237bc95 361 BUFFER_delete(blockIDListAsBuffer);
AzureIoTClient 43:038d8511e817 362 }
AzureIoTClient 43:038d8511e817 363 }
AzureIoTClient 80:db5f5237bc95 364 STRING_delete(newRelativePath);
AzureIoTClient 43:038d8511e817 365 }
AzureIoTClient 42:448eecc3676e 366 }
AzureIoTClient 42:448eecc3676e 367 }
AzureIoTClient 80:db5f5237bc95 368 STRING_delete(blockIDList);
AzureIoTClient 42:448eecc3676e 369 }
AzureIoTClient 80:db5f5237bc95 370
AzureIoTClient 42:448eecc3676e 371 }
AzureIoTClient 42:448eecc3676e 372 HTTPAPIEX_Destroy(httpApiExHandle);
AzureIoTClient 42:448eecc3676e 373 }
AzureIoTClient 42:448eecc3676e 374 free(hostname);
AzureIoTClient 42:448eecc3676e 375 }
AzureIoTClient 42:448eecc3676e 376 }
AzureIoTClient 42:448eecc3676e 377 }
AzureIoTClient 42:448eecc3676e 378 }
AzureIoTClient 42:448eecc3676e 379 }
AzureIoTClient 42:448eecc3676e 380 return result;
AzureIoTClient 42:448eecc3676e 381 }