- Timestamp:
- Jun 22, 2021, 9:00:19 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/src/blob.c
r457 r464 13 13 #include "azure_c_shared_utility/azure_base64.h" 14 14 #include "azure_c_shared_utility/shared_util_options.h" 15 16 static const char blockListXmlBegin[] = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<BlockList>"; 17 static const char blockListXmlEnd[] = "</BlockList>"; 18 static const char blockListUriMarker[] = "&comp=blocklist"; 15 19 16 20 BLOB_RESULT Blob_UploadBlock( … … 132 136 } 133 137 138 139 // InvokeUserCallbackAndSendBlobs invokes the application's getDataCallbackEx as many time as callback requests and, for each call, 140 // sends the blob contents to the server. 141 static BLOB_RESULT InvokeUserCallbackAndSendBlobs(HTTPAPIEX_HANDLE httpApiExHandle, const char* relativePath, STRING_HANDLE blockIDList, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context, unsigned int* httpStatus, BUFFER_HANDLE httpResponse) 142 { 143 BLOB_RESULT result; 144 145 /*Codes_SRS_BLOB_02_021: [ For every block returned by `getDataCallbackEx` the following operations shall happen: ]*/ 146 unsigned int blockID = 0; /* incremented for each new block */ 147 unsigned int isError = 0; /* set to 1 if a block upload fails or if getDataCallbackEx returns incorrect blocks to upload */ 148 unsigned int uploadOneMoreBlock = 1; /* set to 1 while getDataCallbackEx returns correct blocks to upload */ 149 unsigned char const * source = NULL; /* data set by getDataCallbackEx */ 150 size_t size = 0; /* source size set by getDataCallbackEx */ 151 IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataReturnValue; 152 153 do 154 { 155 getDataReturnValue = getDataCallbackEx(FILE_UPLOAD_OK, &source, &size, context); 156 if (getDataReturnValue == IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT) 157 { 158 /*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`. ]*/ 159 LogInfo("Upload to blob has been aborted by the user"); 160 uploadOneMoreBlock = 0; 161 result = BLOB_ABORTED; 162 } 163 else if (source == NULL || size == 0) 164 { 165 /*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. ]*/ 166 uploadOneMoreBlock = 0; 167 result = BLOB_OK; 168 } 169 else 170 { 171 if (size > BLOCK_SIZE) 172 { 173 /*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`. ]*/ 174 LogError("tried to upload block of size %lu, max allowed size is %d", (unsigned long)size, BLOCK_SIZE); 175 result = BLOB_INVALID_ARG; 176 isError = 1; 177 } 178 else if (blockID >= MAX_BLOCK_COUNT) 179 { 180 /*Codes_SRS_BLOB_99_003: [ If `getDataCallbackEx` returns more than 50000 blocks, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/ 181 LogError("unable to upload more than %lu blocks in one blob", (unsigned long)MAX_BLOCK_COUNT); 182 result = BLOB_INVALID_ARG; 183 isError = 1; 184 } 185 else 186 { 187 /*Codes_SRS_BLOB_02_023: [ Blob_UploadMultipleBlocksFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/ 188 BUFFER_HANDLE requestContent = BUFFER_create(source, size); 189 if (requestContent == NULL) 190 { 191 /*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 ]*/ 192 LogError("unable to BUFFER_create"); 193 result = BLOB_ERROR; 194 isError = 1; 195 } 196 else 197 { 198 result = Blob_UploadBlock( 199 httpApiExHandle, 200 relativePath, 201 requestContent, 202 blockID, 203 blockIDList, 204 httpStatus, 205 httpResponse); 206 207 BUFFER_delete(requestContent); 208 } 209 210 /*Codes_SRS_BLOB_02_026: [ Otherwise, if HTTP response code is >=300 then Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/ 211 if (result != BLOB_OK) 212 { 213 LogError("unable to Blob_UploadBlock. Returned value=%d", result); 214 isError = 1; 215 } 216 else if (*httpStatus >= 300) 217 { 218 LogError("unable to Blob_UploadBlock. Returned httpStatus=%u", (unsigned int)*httpStatus); 219 isError = 1; 220 } 221 } 222 blockID++; 223 } 224 } 225 while(uploadOneMoreBlock && !isError); 226 227 return result; 228 } 229 230 // SendBlockIdList to send an XML of uploaded blockIds to the server after the application's payload block(s) have been transfered. 231 static BLOB_RESULT SendBlockIdList(HTTPAPIEX_HANDLE httpApiExHandle, const char* relativePath, STRING_HANDLE blockIDList, unsigned int* httpStatus, BUFFER_HANDLE httpResponse) 232 { 233 BLOB_RESULT result; 234 235 /*complete the XML*/ 236 if (STRING_concat(blockIDList, blockListXmlEnd) != 0) 237 { 238 /*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 ]*/ 239 LogError("failed to STRING_concat"); 240 result = BLOB_ERROR; 241 } 242 else 243 { 244 /*Codes_SRS_BLOB_02_029: [Blob_UploadMultipleBlocksFromSasUri shall construct a new relativePath from following string : base relativePath + "&comp=blocklist"]*/ 245 STRING_HANDLE newRelativePath = STRING_construct(relativePath); 246 if (newRelativePath == NULL) 247 { 248 /*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 ]*/ 249 LogError("failed to STRING_construct"); 250 result = BLOB_ERROR; 251 } 252 else 253 { 254 if (STRING_concat(newRelativePath, blockListUriMarker) != 0) 255 { 256 /*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 ]*/ 257 LogError("failed to STRING_concat"); 258 result = BLOB_ERROR; 259 } 260 else 261 { 262 /*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. ]*/ 263 const char* s = STRING_c_str(blockIDList); 264 BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s)); 265 if (blockIDListAsBuffer == NULL) 266 { 267 /*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 ]*/ 268 LogError("failed to BUFFER_create"); 269 result = BLOB_ERROR; 270 } 271 else 272 { 273 if (HTTPAPIEX_ExecuteRequest( 274 httpApiExHandle, 275 HTTPAPI_REQUEST_PUT, 276 STRING_c_str(newRelativePath), 277 NULL, 278 blockIDListAsBuffer, 279 httpStatus, 280 NULL, 281 httpResponse 282 ) != HTTPAPIEX_OK) 283 { 284 /*Codes_SRS_BLOB_02_031: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/ 285 LogError("unable to HTTPAPIEX_ExecuteRequest"); 286 result = BLOB_HTTP_ERROR; 287 } 288 else 289 { 290 /*Codes_SRS_BLOB_02_032: [ Otherwise, Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/ 291 result = BLOB_OK; 292 } 293 BUFFER_delete(blockIDListAsBuffer); 294 } 295 } 296 STRING_delete(newRelativePath); 297 } 298 } 299 300 return result; 301 } 302 303 134 304 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) 135 305 { 136 306 BLOB_RESULT result; 307 const char* hostnameBegin; 308 STRING_HANDLE blockIDList = NULL; 309 HTTPAPIEX_HANDLE httpApiExHandle = NULL; 310 char* hostname = NULL; 311 137 312 /*Codes_SRS_BLOB_02_001: [ If SASURI is NULL then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ 138 if (SASURI == NULL) 139 { 140 LogError("parameter SASURI is NULL"); 313 /*Codes_SRS_BLOB_02_002: [ If getDataCallbackEx is NULL then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ 314 if ((SASURI == NULL) || (getDataCallbackEx == NULL)) 315 { 316 LogError("One or more required values is NULL, SASURI=%p, getDataCallbackEx=%p", SASURI, getDataCallbackEx); 141 317 result = BLOB_INVALID_ARG; 142 318 } 319 /*Codes_SRS_BLOB_02_017: [ Blob_UploadMultipleBlocksFromSasUri shall copy from SASURI the hostname to a new const char* ]*/ 320 /*to find the hostname, the following logic is applied:*/ 321 /*the hostname starts at the first character after "://"*/ 322 /*the hostname ends at the first character before the next "/" after "://"*/ 323 else if ((hostnameBegin = strstr(SASURI, "://")) == NULL) 324 { 325 /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ 326 LogError("hostname cannot be determined"); 327 result = BLOB_INVALID_ARG; 328 } 143 329 else 144 330 { 145 /*Codes_SRS_BLOB_02_002: [ If getDataCallbackEx is NULL then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ 146 if (getDataCallbackEx == NULL) 147 { 148 LogError("IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx is NULL"); 331 hostnameBegin += 3; /*have to skip 3 characters which are "://"*/ 332 const char* relativePath = strchr(hostnameBegin, '/'); 333 if (relativePath == NULL) 334 { 335 /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ 336 LogError("hostname cannot be determined"); 149 337 result = BLOB_INVALID_ARG; 150 338 } 151 /*the below define avoid a "condition always false" on some compilers*/152 339 else 153 340 { 154 /*Codes_SRS_BLOB_02_017: [ Blob_UploadMultipleBlocksFromSasUri shall copy from SASURI the hostname to a new const char* ]*/ 155 /*to find the hostname, the following logic is applied:*/ 156 /*the hostname starts at the first character after "://"*/ 157 /*the hostname ends at the first character before the next "/" after "://"*/ 158 const char* hostnameBegin = strstr(SASURI, "://"); 159 if (hostnameBegin == NULL) 160 { 161 /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ 162 LogError("hostname cannot be determined"); 163 result = BLOB_INVALID_ARG; 341 size_t hostnameSize = relativePath - hostnameBegin; 342 if ((hostname = (char*)malloc(hostnameSize + 1)) == NULL) 343 { 344 /*Codes_SRS_BLOB_02_016: [ If the hostname copy cannot be made then then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/ 345 LogError("oom - out of memory"); 346 result = BLOB_ERROR; 164 347 } 165 348 else 166 349 { 167 hostnameBegin += 3; /*have to skip 3 characters which are "://"*/ 168 const char* hostnameEnd = strchr(hostnameBegin, '/'); 169 if (hostnameEnd == NULL) 170 { 171 /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ 172 LogError("hostname cannot be determined"); 173 result = BLOB_INVALID_ARG; 174 } 175 else 176 { 177 size_t hostnameSize = hostnameEnd - hostnameBegin; 178 char* hostname = (char*)malloc(hostnameSize + 1); /*+1 because of '\0' at the end*/ 179 if (hostname == NULL) 180 { 181 /*Codes_SRS_BLOB_02_016: [ If the hostname copy cannot be made then then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/ 182 LogError("oom - out of memory"); 183 result = BLOB_ERROR; 184 } 185 else 186 { 187 HTTPAPIEX_HANDLE httpApiExHandle; 188 (void)memcpy(hostname, hostnameBegin, hostnameSize); 189 hostname[hostnameSize] = '\0'; 190 191 /*Codes_SRS_BLOB_02_018: [ Blob_UploadMultipleBlocksFromSasUri shall create a new HTTPAPI_EX_HANDLE by calling HTTPAPIEX_Create passing the hostname. ]*/ 192 httpApiExHandle = HTTPAPIEX_Create(hostname); 193 if (httpApiExHandle == NULL) 194 { 195 /*Codes_SRS_BLOB_02_007: [ If HTTPAPIEX_Create fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR. ]*/ 196 LogError("unable to create a HTTPAPIEX_HANDLE"); 197 result = BLOB_ERROR; 198 } 199 else 200 { 201 if ((certificates != NULL)&& (HTTPAPIEX_SetOption(httpApiExHandle, "TrustedCerts", certificates) == HTTPAPIEX_ERROR)) 202 { 203 LogError("failure in setting trusted certificates"); 204 result = BLOB_ERROR; 205 } 206 else if ((proxyOptions != NULL && proxyOptions->host_address != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_PROXY, proxyOptions) == HTTPAPIEX_ERROR) 207 { 208 LogError("failure in setting proxy options"); 209 result = BLOB_ERROR; 210 } 211 else 212 { 213 /*Codes_SRS_BLOB_02_019: [ Blob_UploadMultipleBlocksFromSasUri shall compute the base relative path of the request from the SASURI parameter. ]*/ 214 const char* relativePath = hostnameEnd; /*this is where the relative path begins in the SasUri*/ 215 216 /*Codes_SRS_BLOB_02_028: [ Blob_UploadMultipleBlocksFromSasUri shall construct an XML string with the following content: ]*/ 217 STRING_HANDLE blockIDList = STRING_construct("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<BlockList>"); /*the XML "build as we go"*/ 218 if (blockIDList == NULL) 219 { 220 /*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 ]*/ 221 LogError("failed to STRING_construct"); 222 result = BLOB_HTTP_ERROR; 223 } 224 else 225 { 226 /*Codes_SRS_BLOB_02_021: [ For every block returned by `getDataCallbackEx` the following operations shall happen: ]*/ 227 unsigned int blockID = 0; /* incremented for each new block */ 228 unsigned int isError = 0; /* set to 1 if a block upload fails or if getDataCallbackEx returns incorrect blocks to upload */ 229 unsigned int uploadOneMoreBlock = 1; /* set to 1 while getDataCallbackEx returns correct blocks to upload */ 230 unsigned char const * source; /* data set by getDataCallbackEx */ 231 size_t size; /* source size set by getDataCallbackEx */ 232 IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataReturnValue; 233 234 do 235 { 236 getDataReturnValue = getDataCallbackEx(FILE_UPLOAD_OK, &source, &size, context); 237 if (getDataReturnValue == IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT) 238 { 239 /*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`. ]*/ 240 LogInfo("Upload to blob has been aborted by the user"); 241 uploadOneMoreBlock = 0; 242 result = BLOB_ABORTED; 243 } 244 else if (source == NULL || size == 0) 245 { 246 /*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. ]*/ 247 uploadOneMoreBlock = 0; 248 result = BLOB_OK; 249 } 250 else 251 { 252 if (size > BLOCK_SIZE) 253 { 254 /*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`. ]*/ 255 LogError("tried to upload block of size %lu, max allowed size is %d", (unsigned long)size, BLOCK_SIZE); 256 result = BLOB_INVALID_ARG; 257 isError = 1; 258 } 259 else if (blockID >= MAX_BLOCK_COUNT) 260 { 261 /*Codes_SRS_BLOB_99_003: [ If `getDataCallbackEx` returns more than 50000 blocks, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/ 262 LogError("unable to upload more than %lu blocks in one blob", (unsigned long)MAX_BLOCK_COUNT); 263 result = BLOB_INVALID_ARG; 264 isError = 1; 265 } 266 else 267 { 268 /*Codes_SRS_BLOB_02_023: [ Blob_UploadMultipleBlocksFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/ 269 BUFFER_HANDLE requestContent = BUFFER_create(source, size); 270 if (requestContent == NULL) 271 { 272 /*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 ]*/ 273 LogError("unable to BUFFER_create"); 274 result = BLOB_ERROR; 275 isError = 1; 276 } 277 else 278 { 279 result = Blob_UploadBlock( 280 httpApiExHandle, 281 relativePath, 282 requestContent, 283 blockID, 284 blockIDList, 285 httpStatus, 286 httpResponse); 287 288 BUFFER_delete(requestContent); 289 } 290 291 /*Codes_SRS_BLOB_02_026: [ Otherwise, if HTTP response code is >=300 then Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/ 292 if (result != BLOB_OK || *httpStatus >= 300) 293 { 294 LogError("unable to Blob_UploadBlock. Returned value=%d, httpStatus=%u", result, (unsigned int)*httpStatus); 295 isError = 1; 296 } 297 } 298 blockID++; 299 } 300 } 301 while(uploadOneMoreBlock && !isError); 302 303 if (isError || result != BLOB_OK) 304 { 305 /*do nothing, it will be reported "as is"*/ 306 } 307 else 308 { 309 /*complete the XML*/ 310 if (STRING_concat(blockIDList, "</BlockList>") != 0) 311 { 312 /*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 ]*/ 313 LogError("failed to STRING_concat"); 314 result = BLOB_ERROR; 315 } 316 else 317 { 318 /*Codes_SRS_BLOB_02_029: [Blob_UploadMultipleBlocksFromSasUri shall construct a new relativePath from following string : base relativePath + "&comp=blocklist"]*/ 319 STRING_HANDLE newRelativePath = STRING_construct(relativePath); 320 if (newRelativePath == NULL) 321 { 322 /*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 ]*/ 323 LogError("failed to STRING_construct"); 324 result = BLOB_ERROR; 325 } 326 else 327 { 328 if (STRING_concat(newRelativePath, "&comp=blocklist") != 0) 329 { 330 /*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 ]*/ 331 LogError("failed to STRING_concat"); 332 result = BLOB_ERROR; 333 } 334 else 335 { 336 /*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. ]*/ 337 const char* s = STRING_c_str(blockIDList); 338 BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s)); 339 if (blockIDListAsBuffer == NULL) 340 { 341 /*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 ]*/ 342 LogError("failed to BUFFER_create"); 343 result = BLOB_ERROR; 344 } 345 else 346 { 347 if (HTTPAPIEX_ExecuteRequest( 348 httpApiExHandle, 349 HTTPAPI_REQUEST_PUT, 350 STRING_c_str(newRelativePath), 351 NULL, 352 blockIDListAsBuffer, 353 httpStatus, 354 NULL, 355 httpResponse 356 ) != HTTPAPIEX_OK) 357 { 358 /*Codes_SRS_BLOB_02_031: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/ 359 LogError("unable to HTTPAPIEX_ExecuteRequest"); 360 result = BLOB_HTTP_ERROR; 361 } 362 else 363 { 364 /*Codes_SRS_BLOB_02_032: [ Otherwise, Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/ 365 result = BLOB_OK; 366 } 367 BUFFER_delete(blockIDListAsBuffer); 368 } 369 } 370 STRING_delete(newRelativePath); 371 } 372 } 373 } 374 STRING_delete(blockIDList); 375 } 376 377 } 378 HTTPAPIEX_Destroy(httpApiExHandle); 379 } 380 free(hostname); 381 } 382 } 383 } 384 } 385 } 350 (void)memcpy(hostname, hostnameBegin, hostnameSize); 351 hostname[hostnameSize] = '\0'; 352 353 /*Codes_SRS_BLOB_02_018: [ Blob_UploadMultipleBlocksFromSasUri shall create a new HTTPAPI_EX_HANDLE by calling HTTPAPIEX_Create passing the hostname. ]*/ 354 httpApiExHandle = HTTPAPIEX_Create(hostname); 355 if (httpApiExHandle == NULL) 356 { 357 /*Codes_SRS_BLOB_02_007: [ If HTTPAPIEX_Create fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR. ]*/ 358 LogError("unable to create a HTTPAPIEX_HANDLE"); 359 result = BLOB_ERROR; 360 } 361 else if ((certificates != NULL) && (HTTPAPIEX_SetOption(httpApiExHandle, "TrustedCerts", certificates) == HTTPAPIEX_ERROR)) 362 { 363 LogError("failure in setting trusted certificates"); 364 result = BLOB_ERROR; 365 } 366 else if ((proxyOptions != NULL && proxyOptions->host_address != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_PROXY, proxyOptions) == HTTPAPIEX_ERROR) 367 { 368 LogError("failure in setting proxy options"); 369 result = BLOB_ERROR; 370 } 371 /*Codes_SRS_BLOB_02_028: [ Blob_UploadMultipleBlocksFromSasUri shall construct an XML string with the following content: ]*/ 372 else if ((blockIDList = STRING_construct(blockListXmlBegin)) == NULL) 373 { 374 /*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 ]*/ 375 LogError("failed to STRING_construct"); 376 result = BLOB_HTTP_ERROR; 377 } 378 else if ((result = InvokeUserCallbackAndSendBlobs(httpApiExHandle, relativePath, blockIDList, getDataCallbackEx, context, httpStatus, httpResponse)) != BLOB_OK) 379 { 380 LogError("Failed in invoking callback/sending blob step"); 381 } 382 else if (*httpStatus < 300) 383 { 384 // Per SRS_BLOB_02_026, it possible for us to have a result=BLOB_OK AND a non-success HTTP status code. 385 // In order to maintain back-compat with existing code, we will return the BLOB_OK to the caller but NOT invoke this final step. 386 result = SendBlockIdList(httpApiExHandle, relativePath, blockIDList, httpStatus, httpResponse); 387 } 388 } 389 } 390 } 391 392 HTTPAPIEX_Destroy(httpApiExHandle); 393 STRING_delete(blockIDList); 394 free(hostname); 395 386 396 return result; 387 397 }
Note:
See TracChangeset
for help on using the changeset viewer.