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