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
blob.c@62:5a4cdacf5090, 2017-03-24 (annotated)
- Committer:
- AzureIoTClient
- Date:
- Fri Mar 24 16:35:32 2017 -0700
- Revision:
- 62:5a4cdacf5090
- Parent:
- 58:15b0d29b2667
- Child:
- 79:bb88037c05e6
1.1.10
Who changed what in which revision?
User | Revision | Line number | New 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 | 43:038d8511e817 | 12 | |
AzureIoTClient | 43:038d8511e817 | 13 | /*a block has 4MB*/ |
AzureIoTClient | 43:038d8511e817 | 14 | #define BLOCK_SIZE (4*1024*1024) |
AzureIoTClient | 42:448eecc3676e | 15 | |
AzureIoTClient | 62:5a4cdacf5090 | 16 | BLOB_RESULT Blob_UploadFromSasUri(const char* SASURI, const unsigned char* source, size_t size, unsigned int* httpStatus, BUFFER_HANDLE httpResponse, const char* certificates) |
AzureIoTClient | 42:448eecc3676e | 17 | { |
AzureIoTClient | 42:448eecc3676e | 18 | BLOB_RESULT result; |
AzureIoTClient | 42:448eecc3676e | 19 | /*Codes_SRS_BLOB_02_001: [ If SASURI is NULL then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ |
AzureIoTClient | 42:448eecc3676e | 20 | if (SASURI == NULL) |
AzureIoTClient | 42:448eecc3676e | 21 | { |
AzureIoTClient | 42:448eecc3676e | 22 | LogError("parameter SASURI is NULL"); |
AzureIoTClient | 42:448eecc3676e | 23 | result = BLOB_INVALID_ARG; |
AzureIoTClient | 42:448eecc3676e | 24 | } |
AzureIoTClient | 42:448eecc3676e | 25 | else |
AzureIoTClient | 42:448eecc3676e | 26 | { |
AzureIoTClient | 42:448eecc3676e | 27 | /*Codes_SRS_BLOB_02_002: [ If source is NULL and size is not zero then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ |
AzureIoTClient | 42:448eecc3676e | 28 | if ( |
AzureIoTClient | 42:448eecc3676e | 29 | (size > 0) && |
AzureIoTClient | 42:448eecc3676e | 30 | (source == NULL) |
AzureIoTClient | 43:038d8511e817 | 31 | ) |
AzureIoTClient | 42:448eecc3676e | 32 | { |
AzureIoTClient | 43:038d8511e817 | 33 | LogError("combination of source = %p and size = %zu is invalid", source, size); |
AzureIoTClient | 42:448eecc3676e | 34 | result = BLOB_INVALID_ARG; |
AzureIoTClient | 42:448eecc3676e | 35 | } |
AzureIoTClient | 62:5a4cdacf5090 | 36 | /*the below define avoid a "condition always false" on some compilers*/ |
AzureIoTClient | 62:5a4cdacf5090 | 37 | #if SIZE_MAX>UINT32_MAX |
AzureIoTClient | 43:038d8511e817 | 38 | /*Codes_SRS_BLOB_02_034: [ If size is bigger than 50000*4*1024*1024 then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 39 | else if (size > 4 * 1024 * 1024 * 50000ULL) /*https://msdn.microsoft.com/en-us/library/azure/dd179467.aspx says "Each block can be a different size, up to a maximum of 4 MB, and a block blob can include a maximum of 50,000 blocks."*/ |
AzureIoTClient | 42:448eecc3676e | 40 | { |
AzureIoTClient | 43:038d8511e817 | 41 | LogError("size too big (%zu)", size); |
AzureIoTClient | 43:038d8511e817 | 42 | result = BLOB_INVALID_ARG; |
AzureIoTClient | 42:448eecc3676e | 43 | } |
AzureIoTClient | 62:5a4cdacf5090 | 44 | #endif |
AzureIoTClient | 42:448eecc3676e | 45 | else |
AzureIoTClient | 42:448eecc3676e | 46 | { |
AzureIoTClient | 43:038d8511e817 | 47 | /*Codes_SRS_BLOB_02_017: [ Blob_UploadFromSasUri shall copy from SASURI the hostname to a new const char* ]*/ |
AzureIoTClient | 42:448eecc3676e | 48 | /*Codes_SRS_BLOB_02_004: [ Blob_UploadFromSasUri shall copy from SASURI the hostname to a new const char*. ]*/ |
AzureIoTClient | 42:448eecc3676e | 49 | /*to find the hostname, the following logic is applied:*/ |
AzureIoTClient | 42:448eecc3676e | 50 | /*the hostname starts at the first character after "://"*/ |
AzureIoTClient | 42:448eecc3676e | 51 | /*the hostname ends at the first character before the next "/" after "://"*/ |
AzureIoTClient | 42:448eecc3676e | 52 | const char* hostnameBegin = strstr(SASURI, "://"); |
AzureIoTClient | 42:448eecc3676e | 53 | if (hostnameBegin == NULL) |
AzureIoTClient | 42:448eecc3676e | 54 | { |
AzureIoTClient | 42:448eecc3676e | 55 | /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ |
AzureIoTClient | 42:448eecc3676e | 56 | LogError("hostname cannot be determined"); |
AzureIoTClient | 42:448eecc3676e | 57 | result = BLOB_INVALID_ARG; |
AzureIoTClient | 42:448eecc3676e | 58 | } |
AzureIoTClient | 42:448eecc3676e | 59 | else |
AzureIoTClient | 42:448eecc3676e | 60 | { |
AzureIoTClient | 42:448eecc3676e | 61 | hostnameBegin += 3; /*have to skip 3 characters which are "://"*/ |
AzureIoTClient | 42:448eecc3676e | 62 | const char* hostnameEnd = strchr(hostnameBegin, '/'); |
AzureIoTClient | 42:448eecc3676e | 63 | if (hostnameEnd == NULL) |
AzureIoTClient | 42:448eecc3676e | 64 | { |
AzureIoTClient | 42:448eecc3676e | 65 | /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/ |
AzureIoTClient | 42:448eecc3676e | 66 | LogError("hostname cannot be determined"); |
AzureIoTClient | 42:448eecc3676e | 67 | result = BLOB_INVALID_ARG; |
AzureIoTClient | 42:448eecc3676e | 68 | } |
AzureIoTClient | 42:448eecc3676e | 69 | else |
AzureIoTClient | 42:448eecc3676e | 70 | { |
AzureIoTClient | 42:448eecc3676e | 71 | size_t hostnameSize = hostnameEnd - hostnameBegin; |
AzureIoTClient | 42:448eecc3676e | 72 | char* hostname = (char*)malloc(hostnameSize + 1); /*+1 because of '\0' at the end*/ |
AzureIoTClient | 42:448eecc3676e | 73 | if (hostname == NULL) |
AzureIoTClient | 42:448eecc3676e | 74 | { |
AzureIoTClient | 42:448eecc3676e | 75 | /*Codes_SRS_BLOB_02_016: [ If the hostname copy cannot be made then then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 42:448eecc3676e | 76 | LogError("oom - out of memory"); |
AzureIoTClient | 42:448eecc3676e | 77 | result = BLOB_ERROR; |
AzureIoTClient | 42:448eecc3676e | 78 | } |
AzureIoTClient | 42:448eecc3676e | 79 | else |
AzureIoTClient | 42:448eecc3676e | 80 | { |
AzureIoTClient | 42:448eecc3676e | 81 | HTTPAPIEX_HANDLE httpApiExHandle; |
AzureIoTClient | 58:15b0d29b2667 | 82 | (void)memcpy(hostname, hostnameBegin, hostnameSize); |
AzureIoTClient | 42:448eecc3676e | 83 | hostname[hostnameSize] = '\0'; |
AzureIoTClient | 42:448eecc3676e | 84 | |
AzureIoTClient | 42:448eecc3676e | 85 | /*Codes_SRS_BLOB_02_006: [ Blob_UploadFromSasUri shall create a new HTTPAPI_EX_HANDLE by calling HTTPAPIEX_Create passing the hostname. ]*/ |
AzureIoTClient | 43:038d8511e817 | 86 | /*Codes_SRS_BLOB_02_018: [ Blob_UploadFromSasUri shall create a new HTTPAPI_EX_HANDLE by calling HTTPAPIEX_Create passing the hostname. ]*/ |
AzureIoTClient | 42:448eecc3676e | 87 | httpApiExHandle = HTTPAPIEX_Create(hostname); |
AzureIoTClient | 42:448eecc3676e | 88 | if (httpApiExHandle == NULL) |
AzureIoTClient | 42:448eecc3676e | 89 | { |
AzureIoTClient | 42:448eecc3676e | 90 | /*Codes_SRS_BLOB_02_007: [ If HTTPAPIEX_Create fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ |
AzureIoTClient | 42:448eecc3676e | 91 | LogError("unable to create a HTTPAPIEX_HANDLE"); |
AzureIoTClient | 42:448eecc3676e | 92 | result = BLOB_ERROR; |
AzureIoTClient | 42:448eecc3676e | 93 | } |
AzureIoTClient | 42:448eecc3676e | 94 | else |
AzureIoTClient | 42:448eecc3676e | 95 | { |
AzureIoTClient | 62:5a4cdacf5090 | 96 | if ((certificates != NULL)&& (HTTPAPIEX_SetOption(httpApiExHandle, "TrustedCerts", certificates) == HTTPAPIEX_ERROR)) |
AzureIoTClient | 62:5a4cdacf5090 | 97 | { |
AzureIoTClient | 62:5a4cdacf5090 | 98 | LogError("failure in setting trusted certificates"); |
AzureIoTClient | 62:5a4cdacf5090 | 99 | result = BLOB_ERROR; |
AzureIoTClient | 62:5a4cdacf5090 | 100 | } |
AzureIoTClient | 62:5a4cdacf5090 | 101 | else |
AzureIoTClient | 62:5a4cdacf5090 | 102 | { |
AzureIoTClient | 42:448eecc3676e | 103 | |
AzureIoTClient | 62:5a4cdacf5090 | 104 | /*Codes_SRS_BLOB_02_008: [ Blob_UploadFromSasUri shall compute the relative path of the request from the SASURI parameter. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 105 | /*Codes_SRS_BLOB_02_019: [ Blob_UploadFromSasUri shall compute the base relative path of the request from the SASURI parameter. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 106 | const char* relativePath = hostnameEnd; /*this is where the relative path begins in the SasUri*/ |
AzureIoTClient | 62:5a4cdacf5090 | 107 | |
AzureIoTClient | 62:5a4cdacf5090 | 108 | if (size < 64 * 1024 * 1024) /*code path for sizes <64MB*/ |
AzureIoTClient | 42:448eecc3676e | 109 | { |
AzureIoTClient | 62:5a4cdacf5090 | 110 | /*Codes_SRS_BLOB_02_010: [ Blob_UploadFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 111 | BUFFER_HANDLE requestBuffer = BUFFER_create(source, size); |
AzureIoTClient | 62:5a4cdacf5090 | 112 | if (requestBuffer == NULL) |
AzureIoTClient | 42:448eecc3676e | 113 | { |
AzureIoTClient | 42:448eecc3676e | 114 | /*Codes_SRS_BLOB_02_011: [ If any of the previous steps related to building the HTTPAPI_EX_ExecuteRequest parameters fails, then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 115 | LogError("unable to BUFFER_create"); |
AzureIoTClient | 42:448eecc3676e | 116 | result = BLOB_ERROR; |
AzureIoTClient | 42:448eecc3676e | 117 | } |
AzureIoTClient | 42:448eecc3676e | 118 | else |
AzureIoTClient | 42:448eecc3676e | 119 | { |
AzureIoTClient | 62:5a4cdacf5090 | 120 | /*Codes_SRS_BLOB_02_009: [ Blob_UploadFromSasUri shall create an HTTP_HEADERS_HANDLE for the request HTTP headers carrying the following headers: ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 121 | HTTP_HEADERS_HANDLE requestHttpHeaders = HTTPHeaders_Alloc(); |
AzureIoTClient | 62:5a4cdacf5090 | 122 | if (requestHttpHeaders == NULL) |
AzureIoTClient | 43:038d8511e817 | 123 | { |
AzureIoTClient | 43:038d8511e817 | 124 | /*Codes_SRS_BLOB_02_011: [ If any of the previous steps related to building the HTTPAPI_EX_ExecuteRequest parameters fails, then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 125 | LogError("unable to HTTPHeaders_Alloc"); |
AzureIoTClient | 43:038d8511e817 | 126 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 127 | } |
AzureIoTClient | 43:038d8511e817 | 128 | else |
AzureIoTClient | 42:448eecc3676e | 129 | { |
AzureIoTClient | 62:5a4cdacf5090 | 130 | if (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "x-ms-blob-type", "BlockBlob") != HTTP_HEADERS_OK) |
AzureIoTClient | 43:038d8511e817 | 131 | { |
AzureIoTClient | 62:5a4cdacf5090 | 132 | /*Codes_SRS_BLOB_02_011: [ If any of the previous steps related to building the HTTPAPI_EX_ExecuteRequest parameters fails, then Blob_UploadFromSasUri shall fail and return BLOB_ERROR. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 133 | LogError("unable to HTTPHeaders_AddHeaderNameValuePair"); |
AzureIoTClient | 62:5a4cdacf5090 | 134 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 135 | } |
AzureIoTClient | 43:038d8511e817 | 136 | else |
AzureIoTClient | 43:038d8511e817 | 137 | { |
AzureIoTClient | 62:5a4cdacf5090 | 138 | /*Codes_SRS_BLOB_02_012: [ Blob_UploadFromSasUri shall call HTTPAPIEX_ExecuteRequest passing the parameters previously build, httpStatus and httpResponse ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 139 | if (HTTPAPIEX_ExecuteRequest(httpApiExHandle, HTTPAPI_REQUEST_PUT, relativePath, requestHttpHeaders, requestBuffer, httpStatus, NULL, httpResponse) != HTTPAPIEX_OK) |
AzureIoTClient | 62:5a4cdacf5090 | 140 | { |
AzureIoTClient | 62:5a4cdacf5090 | 141 | /*Codes_SRS_BLOB_02_013: [ If HTTPAPIEX_ExecuteRequest fails, then Blob_UploadFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 142 | LogError("failed to HTTPAPIEX_ExecuteRequest"); |
AzureIoTClient | 62:5a4cdacf5090 | 143 | result = BLOB_HTTP_ERROR; |
AzureIoTClient | 62:5a4cdacf5090 | 144 | } |
AzureIoTClient | 62:5a4cdacf5090 | 145 | else |
AzureIoTClient | 62:5a4cdacf5090 | 146 | { |
AzureIoTClient | 62:5a4cdacf5090 | 147 | /*Codes_SRS_BLOB_02_015: [ Otherwise, HTTPAPIEX_ExecuteRequest shall succeed and return BLOB_OK. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 148 | result = BLOB_OK; |
AzureIoTClient | 62:5a4cdacf5090 | 149 | } |
AzureIoTClient | 43:038d8511e817 | 150 | } |
AzureIoTClient | 62:5a4cdacf5090 | 151 | HTTPHeaders_Free(requestHttpHeaders); |
AzureIoTClient | 43:038d8511e817 | 152 | } |
AzureIoTClient | 62:5a4cdacf5090 | 153 | BUFFER_delete(requestBuffer); |
AzureIoTClient | 43:038d8511e817 | 154 | } |
AzureIoTClient | 43:038d8511e817 | 155 | } |
AzureIoTClient | 62:5a4cdacf5090 | 156 | else /*code path for size >= 64MB*/ |
AzureIoTClient | 43:038d8511e817 | 157 | { |
AzureIoTClient | 62:5a4cdacf5090 | 158 | size_t toUpload = size; |
AzureIoTClient | 62:5a4cdacf5090 | 159 | /*Codes_SRS_BLOB_02_028: [ Blob_UploadFromSasUri shall construct an XML string with the following content: ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 160 | STRING_HANDLE xml = STRING_construct("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<BlockList>"); /*the XML "build as we go"*/ |
AzureIoTClient | 62:5a4cdacf5090 | 161 | if (xml == NULL) |
AzureIoTClient | 62:5a4cdacf5090 | 162 | { |
AzureIoTClient | 62:5a4cdacf5090 | 163 | /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 164 | LogError("failed to STRING_construct"); |
AzureIoTClient | 62:5a4cdacf5090 | 165 | result = BLOB_HTTP_ERROR; |
AzureIoTClient | 62:5a4cdacf5090 | 166 | } |
AzureIoTClient | 62:5a4cdacf5090 | 167 | else |
AzureIoTClient | 43:038d8511e817 | 168 | { |
AzureIoTClient | 62:5a4cdacf5090 | 169 | /*Codes_SRS_BLOB_02_021: [ For every block of 4MB the following operations shall happen: ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 170 | unsigned int blockID = 0; |
AzureIoTClient | 62:5a4cdacf5090 | 171 | result = BLOB_ERROR; |
AzureIoTClient | 62:5a4cdacf5090 | 172 | |
AzureIoTClient | 62:5a4cdacf5090 | 173 | int isError = 0; /*used to cleanly exit the loop*/ |
AzureIoTClient | 62:5a4cdacf5090 | 174 | do |
AzureIoTClient | 43:038d8511e817 | 175 | { |
AzureIoTClient | 62:5a4cdacf5090 | 176 | /*setting this block size*/ |
AzureIoTClient | 62:5a4cdacf5090 | 177 | size_t thisBlockSize = (toUpload > BLOCK_SIZE) ? BLOCK_SIZE : toUpload; |
AzureIoTClient | 62:5a4cdacf5090 | 178 | /*Codes_SRS_BLOB_02_020: [ Blob_UploadFromSasUri shall construct a BASE64 encoded string from the block ID (000000... 0499999) ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 179 | char temp[7]; /*this will contain 000000... 049999*/ |
AzureIoTClient | 62:5a4cdacf5090 | 180 | if (sprintf(temp, "%6u", (unsigned int)blockID) != 6) /*produces 000000... 049999*/ |
AzureIoTClient | 43:038d8511e817 | 181 | { |
AzureIoTClient | 43:038d8511e817 | 182 | /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 183 | LogError("failed to sprintf"); |
AzureIoTClient | 43:038d8511e817 | 184 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 185 | isError = 1; |
AzureIoTClient | 43:038d8511e817 | 186 | } |
AzureIoTClient | 43:038d8511e817 | 187 | else |
AzureIoTClient | 43:038d8511e817 | 188 | { |
AzureIoTClient | 62:5a4cdacf5090 | 189 | STRING_HANDLE blockIdString = Base64_Encode_Bytes((const unsigned char*)temp, 6); |
AzureIoTClient | 62:5a4cdacf5090 | 190 | if (blockIdString == NULL) |
AzureIoTClient | 43:038d8511e817 | 191 | { |
AzureIoTClient | 43:038d8511e817 | 192 | /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 193 | LogError("unable to Base64_Encode_Bytes"); |
AzureIoTClient | 43:038d8511e817 | 194 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 195 | isError = 1; |
AzureIoTClient | 43:038d8511e817 | 196 | } |
AzureIoTClient | 43:038d8511e817 | 197 | else |
AzureIoTClient | 43:038d8511e817 | 198 | { |
AzureIoTClient | 62:5a4cdacf5090 | 199 | /*add the blockId base64 encoded to the XML*/ |
AzureIoTClient | 62:5a4cdacf5090 | 200 | if (!( |
AzureIoTClient | 62:5a4cdacf5090 | 201 | (STRING_concat(xml, "<Latest>") == 0) && |
AzureIoTClient | 62:5a4cdacf5090 | 202 | (STRING_concat_with_STRING(xml, blockIdString) == 0) && |
AzureIoTClient | 62:5a4cdacf5090 | 203 | (STRING_concat(xml, "</Latest>") == 0) |
AzureIoTClient | 62:5a4cdacf5090 | 204 | )) |
AzureIoTClient | 43:038d8511e817 | 205 | { |
AzureIoTClient | 43:038d8511e817 | 206 | /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 207 | LogError("unable to STRING_concat"); |
AzureIoTClient | 43:038d8511e817 | 208 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 209 | isError = 1; |
AzureIoTClient | 43:038d8511e817 | 210 | } |
AzureIoTClient | 43:038d8511e817 | 211 | else |
AzureIoTClient | 43:038d8511e817 | 212 | { |
AzureIoTClient | 62:5a4cdacf5090 | 213 | /*Codes_SRS_BLOB_02_022: [ Blob_UploadFromSasUri shall construct a new relativePath from following string: base relativePath + "&comp=block&blockid=BASE64 encoded string of blockId" ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 214 | STRING_HANDLE newRelativePath = STRING_construct(relativePath); |
AzureIoTClient | 62:5a4cdacf5090 | 215 | if (newRelativePath == NULL) |
AzureIoTClient | 43:038d8511e817 | 216 | { |
AzureIoTClient | 43:038d8511e817 | 217 | /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 218 | LogError("unable to STRING_construct"); |
AzureIoTClient | 43:038d8511e817 | 219 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 220 | isError = 1; |
AzureIoTClient | 43:038d8511e817 | 221 | } |
AzureIoTClient | 43:038d8511e817 | 222 | else |
AzureIoTClient | 43:038d8511e817 | 223 | { |
AzureIoTClient | 62:5a4cdacf5090 | 224 | if (!( |
AzureIoTClient | 62:5a4cdacf5090 | 225 | (STRING_concat(newRelativePath, "&comp=block&blockid=") == 0) && |
AzureIoTClient | 62:5a4cdacf5090 | 226 | (STRING_concat_with_STRING(newRelativePath, blockIdString) == 0) |
AzureIoTClient | 62:5a4cdacf5090 | 227 | )) |
AzureIoTClient | 43:038d8511e817 | 228 | { |
AzureIoTClient | 43:038d8511e817 | 229 | /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 230 | LogError("unable to STRING concatenate"); |
AzureIoTClient | 43:038d8511e817 | 231 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 232 | isError = 1; |
AzureIoTClient | 43:038d8511e817 | 233 | } |
AzureIoTClient | 43:038d8511e817 | 234 | else |
AzureIoTClient | 43:038d8511e817 | 235 | { |
AzureIoTClient | 62:5a4cdacf5090 | 236 | /*Codes_SRS_BLOB_02_023: [ Blob_UploadFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 237 | BUFFER_HANDLE requestContent = BUFFER_create(source + (size - toUpload), thisBlockSize); |
AzureIoTClient | 62:5a4cdacf5090 | 238 | if (requestContent == NULL) |
AzureIoTClient | 43:038d8511e817 | 239 | { |
AzureIoTClient | 62:5a4cdacf5090 | 240 | /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 241 | LogError("unable to BUFFER_create"); |
AzureIoTClient | 62:5a4cdacf5090 | 242 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 243 | isError = 1; |
AzureIoTClient | 43:038d8511e817 | 244 | } |
AzureIoTClient | 43:038d8511e817 | 245 | else |
AzureIoTClient | 43:038d8511e817 | 246 | { |
AzureIoTClient | 62:5a4cdacf5090 | 247 | /*Codes_SRS_BLOB_02_024: [ Blob_UploadFromSasUri shall call HTTPAPIEX_ExecuteRequest with a PUT operation, passing httpStatus and httpResponse. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 248 | if (HTTPAPIEX_ExecuteRequest( |
AzureIoTClient | 62:5a4cdacf5090 | 249 | httpApiExHandle, |
AzureIoTClient | 62:5a4cdacf5090 | 250 | HTTPAPI_REQUEST_PUT, |
AzureIoTClient | 62:5a4cdacf5090 | 251 | STRING_c_str(newRelativePath), |
AzureIoTClient | 62:5a4cdacf5090 | 252 | NULL, |
AzureIoTClient | 62:5a4cdacf5090 | 253 | requestContent, |
AzureIoTClient | 62:5a4cdacf5090 | 254 | httpStatus, |
AzureIoTClient | 62:5a4cdacf5090 | 255 | NULL, |
AzureIoTClient | 62:5a4cdacf5090 | 256 | httpResponse) != HTTPAPIEX_OK |
AzureIoTClient | 62:5a4cdacf5090 | 257 | ) |
AzureIoTClient | 62:5a4cdacf5090 | 258 | { |
AzureIoTClient | 62:5a4cdacf5090 | 259 | /*Codes_SRS_BLOB_02_025: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 260 | LogError("unable to HTTPAPIEX_ExecuteRequest"); |
AzureIoTClient | 62:5a4cdacf5090 | 261 | result = BLOB_HTTP_ERROR; |
AzureIoTClient | 62:5a4cdacf5090 | 262 | isError = 1; |
AzureIoTClient | 62:5a4cdacf5090 | 263 | } |
AzureIoTClient | 62:5a4cdacf5090 | 264 | else if (*httpStatus >= 300) |
AzureIoTClient | 62:5a4cdacf5090 | 265 | { |
AzureIoTClient | 62:5a4cdacf5090 | 266 | /*Codes_SRS_BLOB_02_026: [ Otherwise, if HTTP response code is >=300 then Blob_UploadFromSasUri shall succeed and return BLOB_OK. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 267 | LogError("HTTP status from storage does not indicate success (%d)", (int)*httpStatus); |
AzureIoTClient | 62:5a4cdacf5090 | 268 | result = BLOB_OK; |
AzureIoTClient | 62:5a4cdacf5090 | 269 | isError = 1; |
AzureIoTClient | 62:5a4cdacf5090 | 270 | } |
AzureIoTClient | 62:5a4cdacf5090 | 271 | else |
AzureIoTClient | 62:5a4cdacf5090 | 272 | { |
AzureIoTClient | 62:5a4cdacf5090 | 273 | /*Codes_SRS_BLOB_02_027: [ Otherwise Blob_UploadFromSasUri shall continue execution. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 274 | } |
AzureIoTClient | 62:5a4cdacf5090 | 275 | BUFFER_delete(requestContent); |
AzureIoTClient | 43:038d8511e817 | 276 | } |
AzureIoTClient | 43:038d8511e817 | 277 | } |
AzureIoTClient | 62:5a4cdacf5090 | 278 | STRING_delete(newRelativePath); |
AzureIoTClient | 43:038d8511e817 | 279 | } |
AzureIoTClient | 43:038d8511e817 | 280 | } |
AzureIoTClient | 62:5a4cdacf5090 | 281 | STRING_delete(blockIdString); |
AzureIoTClient | 43:038d8511e817 | 282 | } |
AzureIoTClient | 43:038d8511e817 | 283 | } |
AzureIoTClient | 43:038d8511e817 | 284 | |
AzureIoTClient | 62:5a4cdacf5090 | 285 | blockID++; |
AzureIoTClient | 62:5a4cdacf5090 | 286 | toUpload -= thisBlockSize; |
AzureIoTClient | 62:5a4cdacf5090 | 287 | } while ((toUpload > 0) && !isError); |
AzureIoTClient | 43:038d8511e817 | 288 | |
AzureIoTClient | 62:5a4cdacf5090 | 289 | if (isError) |
AzureIoTClient | 43:038d8511e817 | 290 | { |
AzureIoTClient | 62:5a4cdacf5090 | 291 | /*do nothing, it will be reported "as is"*/ |
AzureIoTClient | 43:038d8511e817 | 292 | } |
AzureIoTClient | 43:038d8511e817 | 293 | else |
AzureIoTClient | 43:038d8511e817 | 294 | { |
AzureIoTClient | 62:5a4cdacf5090 | 295 | /*complete the XML*/ |
AzureIoTClient | 62:5a4cdacf5090 | 296 | if (STRING_concat(xml, "</BlockList>") != 0) |
AzureIoTClient | 43:038d8511e817 | 297 | { |
AzureIoTClient | 43:038d8511e817 | 298 | /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 299 | LogError("failed to STRING_concat"); |
AzureIoTClient | 43:038d8511e817 | 300 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 301 | } |
AzureIoTClient | 43:038d8511e817 | 302 | else |
AzureIoTClient | 43:038d8511e817 | 303 | { |
AzureIoTClient | 62:5a4cdacf5090 | 304 | /*Codes_SRS_BLOB_02_029: [Blob_UploadFromSasUri shall construct a new relativePath from following string : base relativePath + "&comp=blocklist"]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 305 | STRING_HANDLE newRelativePath = STRING_construct(relativePath); |
AzureIoTClient | 62:5a4cdacf5090 | 306 | if (newRelativePath == NULL) |
AzureIoTClient | 43:038d8511e817 | 307 | { |
AzureIoTClient | 43:038d8511e817 | 308 | /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 309 | LogError("failed to STRING_construct"); |
AzureIoTClient | 43:038d8511e817 | 310 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 311 | } |
AzureIoTClient | 43:038d8511e817 | 312 | else |
AzureIoTClient | 43:038d8511e817 | 313 | { |
AzureIoTClient | 62:5a4cdacf5090 | 314 | if (STRING_concat(newRelativePath, "&comp=blocklist") != 0) |
AzureIoTClient | 43:038d8511e817 | 315 | { |
AzureIoTClient | 43:038d8511e817 | 316 | /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 317 | LogError("failed to STRING_concat"); |
AzureIoTClient | 43:038d8511e817 | 318 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 319 | } |
AzureIoTClient | 43:038d8511e817 | 320 | else |
AzureIoTClient | 43:038d8511e817 | 321 | { |
AzureIoTClient | 62:5a4cdacf5090 | 322 | /*Codes_SRS_BLOB_02_030: [ Blob_UploadFromSasUri shall call HTTPAPIEX_ExecuteRequest with a PUT operation, passing the new relativePath, httpStatus and httpResponse and the XML string as content. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 323 | const char* s = STRING_c_str(xml); |
AzureIoTClient | 62:5a4cdacf5090 | 324 | BUFFER_HANDLE xmlAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s)); |
AzureIoTClient | 62:5a4cdacf5090 | 325 | if (xmlAsBuffer == NULL) |
AzureIoTClient | 43:038d8511e817 | 326 | { |
AzureIoTClient | 62:5a4cdacf5090 | 327 | /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadFromSasUri shall fail and return BLOB_ERROR ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 328 | LogError("failed to BUFFER_create"); |
AzureIoTClient | 62:5a4cdacf5090 | 329 | result = BLOB_ERROR; |
AzureIoTClient | 43:038d8511e817 | 330 | } |
AzureIoTClient | 43:038d8511e817 | 331 | else |
AzureIoTClient | 43:038d8511e817 | 332 | { |
AzureIoTClient | 62:5a4cdacf5090 | 333 | if (HTTPAPIEX_ExecuteRequest( |
AzureIoTClient | 62:5a4cdacf5090 | 334 | httpApiExHandle, |
AzureIoTClient | 62:5a4cdacf5090 | 335 | HTTPAPI_REQUEST_PUT, |
AzureIoTClient | 62:5a4cdacf5090 | 336 | STRING_c_str(newRelativePath), |
AzureIoTClient | 62:5a4cdacf5090 | 337 | NULL, |
AzureIoTClient | 62:5a4cdacf5090 | 338 | xmlAsBuffer, |
AzureIoTClient | 62:5a4cdacf5090 | 339 | httpStatus, |
AzureIoTClient | 62:5a4cdacf5090 | 340 | NULL, |
AzureIoTClient | 62:5a4cdacf5090 | 341 | httpResponse |
AzureIoTClient | 62:5a4cdacf5090 | 342 | ) != HTTPAPIEX_OK) |
AzureIoTClient | 62:5a4cdacf5090 | 343 | { |
AzureIoTClient | 62:5a4cdacf5090 | 344 | /*Codes_SRS_BLOB_02_031: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 345 | LogError("unable to HTTPAPIEX_ExecuteRequest"); |
AzureIoTClient | 62:5a4cdacf5090 | 346 | result = BLOB_HTTP_ERROR; |
AzureIoTClient | 62:5a4cdacf5090 | 347 | } |
AzureIoTClient | 62:5a4cdacf5090 | 348 | else |
AzureIoTClient | 62:5a4cdacf5090 | 349 | { |
AzureIoTClient | 62:5a4cdacf5090 | 350 | /*Codes_SRS_BLOB_02_032: [ Otherwise, Blob_UploadFromSasUri shall succeed and return BLOB_OK. ]*/ |
AzureIoTClient | 62:5a4cdacf5090 | 351 | result = BLOB_OK; |
AzureIoTClient | 62:5a4cdacf5090 | 352 | } |
AzureIoTClient | 62:5a4cdacf5090 | 353 | BUFFER_delete(xmlAsBuffer); |
AzureIoTClient | 43:038d8511e817 | 354 | } |
AzureIoTClient | 43:038d8511e817 | 355 | } |
AzureIoTClient | 62:5a4cdacf5090 | 356 | STRING_delete(newRelativePath); |
AzureIoTClient | 43:038d8511e817 | 357 | } |
AzureIoTClient | 43:038d8511e817 | 358 | } |
AzureIoTClient | 42:448eecc3676e | 359 | } |
AzureIoTClient | 62:5a4cdacf5090 | 360 | STRING_delete(xml); |
AzureIoTClient | 42:448eecc3676e | 361 | } |
AzureIoTClient | 42:448eecc3676e | 362 | } |
AzureIoTClient | 42:448eecc3676e | 363 | } |
AzureIoTClient | 42:448eecc3676e | 364 | HTTPAPIEX_Destroy(httpApiExHandle); |
AzureIoTClient | 42:448eecc3676e | 365 | } |
AzureIoTClient | 42:448eecc3676e | 366 | free(hostname); |
AzureIoTClient | 42:448eecc3676e | 367 | } |
AzureIoTClient | 42:448eecc3676e | 368 | } |
AzureIoTClient | 42:448eecc3676e | 369 | } |
AzureIoTClient | 42:448eecc3676e | 370 | } |
AzureIoTClient | 42:448eecc3676e | 371 | } |
AzureIoTClient | 42:448eecc3676e | 372 | return result; |
AzureIoTClient | 42:448eecc3676e | 373 | } |