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