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