Xin Zhang / azure-iot-c-sdk-f767zi

Dependents:   samplemqtt

Committer:
XinZhangMS
Date:
Thu Aug 23 06:52:14 2018 +0000
Revision:
0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI

Who changed what in which revision?

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