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:
Fri Dec 15 14:09:20 2017 -0800
Revision:
80:db5f5237bc95
Parent:
79:bb88037c05e6
Child:
82:f94e6bed4495
1.1.29

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