[388] | 1 | // Copyright (c) Microsoft. All rights reserved.
|
---|
| 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
---|
| 3 |
|
---|
| 4 | #ifndef DONT_USE_UPLOADTOBLOB
|
---|
| 5 |
|
---|
| 6 | #include <stdlib.h>
|
---|
| 7 | #include <string.h>
|
---|
| 8 | #include "azure_c_shared_utility/optimize_size.h"
|
---|
| 9 | #include "azure_c_shared_utility/gballoc.h"
|
---|
| 10 | #include "azure_c_shared_utility/string_tokenizer.h"
|
---|
| 11 | #include "azure_c_shared_utility/doublylinkedlist.h"
|
---|
| 12 | #include "azure_c_shared_utility/xlogging.h"
|
---|
| 13 | #include "azure_c_shared_utility/tickcounter.h"
|
---|
| 14 | #include "azure_c_shared_utility/httpapiexsas.h"
|
---|
| 15 | #include "azure_c_shared_utility/shared_util_options.h"
|
---|
| 16 | #include "azure_c_shared_utility/urlencode.h"
|
---|
| 17 |
|
---|
| 18 | #include "iothub_client_core_ll.h"
|
---|
| 19 | #include "iothub_client_options.h"
|
---|
| 20 | #include "internal/iothub_client_private.h"
|
---|
| 21 | #include "iothub_client_version.h"
|
---|
| 22 | #include "iothub_transport_ll.h"
|
---|
| 23 | #include "parson.h"
|
---|
| 24 | #include "internal/iothub_client_ll_uploadtoblob.h"
|
---|
| 25 | #include "internal/iothub_client_authorization.h"
|
---|
| 26 | #include "internal/blob.h"
|
---|
| 27 |
|
---|
| 28 | #define API_VERSION "?api-version=2016-11-14"
|
---|
| 29 |
|
---|
| 30 | #ifdef WINCE
|
---|
| 31 | #include <stdarg.h>
|
---|
| 32 | // Returns number of characters copied.
|
---|
| 33 | int snprintf(char * s, size_t n, const char * format, ...)
|
---|
| 34 | {
|
---|
| 35 | int result;
|
---|
| 36 | va_list args;
|
---|
| 37 | va_start(args, format);
|
---|
| 38 | result = vsnprintf(s, n, format, args);
|
---|
| 39 | va_end(args);
|
---|
| 40 | return result;
|
---|
| 41 | }
|
---|
| 42 | #endif
|
---|
| 43 |
|
---|
| 44 | /*Codes_SRS_IOTHUBCLIENT_LL_02_085: [ IoTHubClient_LL_UploadToBlob shall use the same authorization as step 1. to prepare and perform a HTTP request with the following parameters: ]*/
|
---|
| 45 | #define FILE_UPLOAD_FAILED_BODY "{ \"isSuccess\":false, \"statusCode\":-1,\"statusDescription\" : \"client not able to connect with the server\" }"
|
---|
| 46 | #define FILE_UPLOAD_ABORTED_BODY "{ \"isSuccess\":false, \"statusCode\":-1,\"statusDescription\" : \"file upload aborted\" }"
|
---|
| 47 | #define INDEFINITE_TIME ((time_t)-1)
|
---|
| 48 |
|
---|
| 49 | static const char* const EMPTY_STRING = "";
|
---|
| 50 | static const char* const HEADER_AUTHORIZATION = "Authorization";
|
---|
| 51 | static const char* const HEADER_APP_JSON = "application/json";
|
---|
| 52 |
|
---|
| 53 | typedef struct UPLOADTOBLOB_X509_CREDENTIALS_TAG
|
---|
| 54 | {
|
---|
| 55 | char* x509certificate;
|
---|
| 56 | char* x509privatekey;
|
---|
| 57 | } UPLOADTOBLOB_X509_CREDENTIALS;
|
---|
| 58 |
|
---|
| 59 | typedef enum UPOADTOBLOB_CURL_VERBOSITY_TAG
|
---|
| 60 | {
|
---|
| 61 | UPOADTOBLOB_CURL_VERBOSITY_UNSET,
|
---|
| 62 | UPOADTOBLOB_CURL_VERBOSITY_ON,
|
---|
| 63 | UPOADTOBLOB_CURL_VERBOSITY_OFF
|
---|
| 64 | } UPOADTOBLOB_CURL_VERBOSITY;
|
---|
| 65 |
|
---|
| 66 | typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA_TAG
|
---|
| 67 | {
|
---|
| 68 | const char* deviceId;
|
---|
| 69 | char* hostname;
|
---|
| 70 | IOTHUB_AUTHORIZATION_HANDLE authorization_module;
|
---|
| 71 | IOTHUB_CREDENTIAL_TYPE cred_type;
|
---|
| 72 | union
|
---|
| 73 | {
|
---|
| 74 | UPLOADTOBLOB_X509_CREDENTIALS x509_credentials;
|
---|
| 75 | char* supplied_sas_token;
|
---|
| 76 | } credentials;
|
---|
| 77 |
|
---|
| 78 | char* certificates;
|
---|
| 79 | HTTP_PROXY_OPTIONS http_proxy_options;
|
---|
| 80 | UPOADTOBLOB_CURL_VERBOSITY curl_verbosity_level;
|
---|
| 81 | size_t blob_upload_timeout_secs;
|
---|
| 82 | }IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA;
|
---|
| 83 |
|
---|
| 84 | typedef struct BLOB_UPLOAD_CONTEXT_TAG
|
---|
| 85 | {
|
---|
| 86 | const unsigned char* blobSource; /* source to upload */
|
---|
| 87 | size_t blobSourceSize; /* size of the source */
|
---|
| 88 | size_t remainingSizeToUpload; /* size not yet uploaded */
|
---|
| 89 | } BLOB_UPLOAD_CONTEXT;
|
---|
| 90 |
|
---|
| 91 | static int send_http_sas_request(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_client, const char* uri_resource, HTTPAPIEX_HANDLE http_api_handle, const char* relative_path, HTTP_HEADERS_HANDLE request_header, BUFFER_HANDLE blobBuffer, BUFFER_HANDLE response_buff)
|
---|
| 92 | {
|
---|
| 93 | int result;
|
---|
| 94 | unsigned int statusCode;
|
---|
| 95 |
|
---|
| 96 | /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 97 | HTTPAPIEX_SAS_HANDLE http_sas_handle = HTTPAPIEX_SAS_Create_From_String(IoTHubClient_Auth_Get_DeviceKey(upload_client->authorization_module), uri_resource, EMPTY_STRING);
|
---|
| 98 | if (http_sas_handle == NULL)
|
---|
| 99 | {
|
---|
| 100 | LogError("unable to HTTPAPIEX_SAS_Create");
|
---|
| 101 | result = MU_FAILURE;
|
---|
| 102 | }
|
---|
| 103 | else
|
---|
| 104 | {
|
---|
| 105 | /*Codes_SRS_IOTHUBCLIENT_LL_32_003: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall execute HTTPAPIEX_ExecuteRequest passing the following information for arguments: ]*/
|
---|
| 106 | if (HTTPAPIEX_SAS_ExecuteRequest(http_sas_handle, http_api_handle, HTTPAPI_REQUEST_POST, relative_path, request_header,
|
---|
| 107 | blobBuffer, &statusCode, NULL, response_buff) != HTTPAPIEX_OK)
|
---|
| 108 | {
|
---|
| 109 | /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 110 | result = MU_FAILURE;
|
---|
| 111 | LogError("unable to HTTPAPIEX_ExecuteRequest");
|
---|
| 112 | }
|
---|
| 113 | else if (statusCode >= 300)
|
---|
| 114 | {
|
---|
| 115 | result = MU_FAILURE;
|
---|
| 116 | LogError("HTTP code was %u", statusCode);
|
---|
| 117 | }
|
---|
| 118 | else
|
---|
| 119 | {
|
---|
| 120 | result = 0;
|
---|
| 121 | }
|
---|
| 122 | HTTPAPIEX_SAS_Destroy(http_sas_handle);
|
---|
| 123 | }
|
---|
| 124 | return result;
|
---|
| 125 | }
|
---|
| 126 |
|
---|
| 127 | static int send_http_request(HTTPAPIEX_HANDLE http_api_handle, const char* relative_path, HTTP_HEADERS_HANDLE request_header, BUFFER_HANDLE blobBuffer, BUFFER_HANDLE response_buff)
|
---|
| 128 | {
|
---|
| 129 | int result;
|
---|
| 130 | unsigned int statusCode;
|
---|
| 131 | /*Codes_SRS_IOTHUBCLIENT_LL_32_003: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall execute HTTPAPIEX_ExecuteRequest passing the following information for arguments: ]*/
|
---|
| 132 | if (HTTPAPIEX_ExecuteRequest(http_api_handle, HTTPAPI_REQUEST_POST, relative_path, request_header,
|
---|
| 133 | blobBuffer, &statusCode, NULL, response_buff) != HTTPAPIEX_OK)
|
---|
| 134 | {
|
---|
| 135 | /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 136 | result = MU_FAILURE;
|
---|
| 137 | LogError("unable to HTTPAPIEX_ExecuteRequest");
|
---|
| 138 | }
|
---|
| 139 | else if (statusCode >= 300)
|
---|
| 140 | {
|
---|
| 141 | result = MU_FAILURE;
|
---|
| 142 | LogError("HTTP code was %u", statusCode);
|
---|
| 143 | }
|
---|
| 144 | else
|
---|
| 145 | {
|
---|
| 146 | result = 0;
|
---|
| 147 | }
|
---|
| 148 | return result;
|
---|
| 149 | }
|
---|
| 150 |
|
---|
| 151 | static int parse_result_json(const char* json_response, STRING_HANDLE correlation_id, STRING_HANDLE sas_uri)
|
---|
| 152 | {
|
---|
| 153 | int result;
|
---|
| 154 |
|
---|
| 155 | JSON_Object* json_obj;
|
---|
| 156 | /*Codes_SRS_IOTHUBCLIENT_LL_02_081: [ Otherwise, IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall use parson to extract and save the following information from the response buffer: correlationID and SasUri. ]*/
|
---|
| 157 | JSON_Value* json = json_parse_string(json_response);
|
---|
| 158 | if (json == NULL)
|
---|
| 159 | {
|
---|
| 160 | /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 161 | LogError("unable to json_parse_string");
|
---|
| 162 | result = MU_FAILURE;
|
---|
| 163 |
|
---|
| 164 | }
|
---|
| 165 | else
|
---|
| 166 | {
|
---|
| 167 | if ((json_obj = json_value_get_object(json)) == NULL)
|
---|
| 168 | {
|
---|
| 169 | LogError("unable to get json_value_get_object");
|
---|
| 170 | result = MU_FAILURE;
|
---|
| 171 | }
|
---|
| 172 | else
|
---|
| 173 | {
|
---|
| 174 | const char* json_corr_id;
|
---|
| 175 | const char* json_hostname;
|
---|
| 176 | const char* json_container_name;
|
---|
| 177 | const char* json_blob_name;
|
---|
| 178 | const char* json_sas_token;
|
---|
| 179 | STRING_HANDLE filename;
|
---|
| 180 | if ((json_corr_id = json_object_get_string(json_obj, "correlationId")) == NULL)
|
---|
| 181 | {
|
---|
| 182 | LogError("unable to retrieve correlation Id from json");
|
---|
| 183 | result = MU_FAILURE;
|
---|
| 184 | }
|
---|
| 185 | else if ((json_hostname = json_object_get_string(json_obj, "hostName")) == NULL)
|
---|
| 186 | {
|
---|
| 187 | LogError("unable to retrieve hostname Id from json");
|
---|
| 188 | result = MU_FAILURE;
|
---|
| 189 | }
|
---|
| 190 | else if ((json_container_name = json_object_get_string(json_obj, "containerName")) == NULL)
|
---|
| 191 | {
|
---|
| 192 | LogError("unable to retrieve container name Id from json");
|
---|
| 193 | result = MU_FAILURE;
|
---|
| 194 | }
|
---|
| 195 | else if ((json_blob_name = json_object_get_string(json_obj, "blobName")) == NULL)
|
---|
| 196 | {
|
---|
| 197 | LogError("unable to retrieve blob name Id from json");
|
---|
| 198 | result = MU_FAILURE;
|
---|
| 199 | }
|
---|
| 200 | else if ((json_sas_token = json_object_get_string(json_obj, "sasToken")) == NULL)
|
---|
| 201 | {
|
---|
| 202 | LogError("unable to retrieve sas token from json");
|
---|
| 203 | result = MU_FAILURE;
|
---|
| 204 | }
|
---|
| 205 | /*Codes_SRS_IOTHUBCLIENT_LL_32_008: [ The returned file name shall be URL encoded before passing back to the cloud. ]*/
|
---|
| 206 | else if ((filename = URL_EncodeString(json_blob_name)) == NULL)
|
---|
| 207 | {
|
---|
| 208 | /*Codes_SRS_IOTHUBCLIENT_LL_32_009: [ If URL_EncodeString fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 209 | LogError("unable to URL encode of filename");
|
---|
| 210 | result = MU_FAILURE;
|
---|
| 211 | }
|
---|
| 212 | else
|
---|
| 213 | {
|
---|
| 214 | if (STRING_sprintf(sas_uri, "https://%s/%s/%s%s", json_hostname, json_container_name, STRING_c_str(filename), json_sas_token) != 0)
|
---|
| 215 | {
|
---|
| 216 | /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 217 | LogError("unable to construct uri string");
|
---|
| 218 | result = MU_FAILURE;
|
---|
| 219 | }
|
---|
| 220 | else if (STRING_copy(correlation_id, json_corr_id) != 0)
|
---|
| 221 | {
|
---|
| 222 | /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 223 | LogError("unable to copy correlation Id");
|
---|
| 224 | result = MU_FAILURE;
|
---|
| 225 | STRING_empty(sas_uri);
|
---|
| 226 | }
|
---|
| 227 | else
|
---|
| 228 | {
|
---|
| 229 | result = 0;
|
---|
| 230 | }
|
---|
| 231 | STRING_delete(filename);
|
---|
| 232 | }
|
---|
| 233 | }
|
---|
| 234 | json_value_free(json);
|
---|
| 235 | }
|
---|
| 236 | return result;
|
---|
| 237 | }
|
---|
| 238 |
|
---|
| 239 | IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE IoTHubClient_LL_UploadToBlob_Create(const IOTHUB_CLIENT_CONFIG* config, IOTHUB_AUTHORIZATION_HANDLE auth_handle)
|
---|
| 240 | {
|
---|
| 241 | IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data;
|
---|
| 242 | if (auth_handle == NULL || config == NULL)
|
---|
| 243 | {
|
---|
| 244 | LogError("Invalid arguments auth_handle: %p, config: %p", auth_handle, config);
|
---|
| 245 | upload_data = NULL;
|
---|
| 246 | }
|
---|
| 247 | else
|
---|
| 248 | {
|
---|
| 249 | upload_data = malloc(sizeof(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA));
|
---|
| 250 | if (upload_data == NULL)
|
---|
| 251 | {
|
---|
| 252 | LogError("Failed malloc allocation");
|
---|
| 253 | /*return as is*/
|
---|
| 254 | }
|
---|
| 255 | else
|
---|
| 256 | {
|
---|
| 257 | memset(upload_data, 0, sizeof(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA));
|
---|
| 258 |
|
---|
| 259 | upload_data->authorization_module = auth_handle;
|
---|
| 260 |
|
---|
| 261 | size_t iotHubNameLength = strlen(config->iotHubName);
|
---|
| 262 | size_t iotHubSuffixLength = strlen(config->iotHubSuffix);
|
---|
| 263 | upload_data->hostname = malloc(iotHubNameLength + 1 + iotHubSuffixLength + 1); /*first +1 is because "." the second +1 is because \0*/
|
---|
| 264 | if (upload_data->hostname == NULL)
|
---|
| 265 | {
|
---|
| 266 | LogError("Failed malloc allocation");
|
---|
| 267 | free(upload_data);
|
---|
| 268 | upload_data = NULL;
|
---|
| 269 | }
|
---|
| 270 | else if ((upload_data->deviceId = IoTHubClient_Auth_Get_DeviceId(upload_data->authorization_module)) == NULL)
|
---|
| 271 | {
|
---|
| 272 | LogError("Failed retrieving device ID");
|
---|
| 273 | free(upload_data->hostname);
|
---|
| 274 | free(upload_data);
|
---|
| 275 | upload_data = NULL;
|
---|
| 276 | }
|
---|
| 277 | else
|
---|
| 278 | {
|
---|
| 279 | char* insert_pos = (char*)upload_data->hostname;
|
---|
| 280 | (void)memcpy((char*)insert_pos, config->iotHubName, iotHubNameLength);
|
---|
| 281 | insert_pos += iotHubNameLength;
|
---|
| 282 | *insert_pos = '.';
|
---|
| 283 | insert_pos += 1;
|
---|
| 284 | (void)memcpy(insert_pos, config->iotHubSuffix, iotHubSuffixLength); /*+1 will copy the \0 too*/
|
---|
| 285 | insert_pos += iotHubSuffixLength;
|
---|
| 286 | *insert_pos = '\0';
|
---|
| 287 |
|
---|
| 288 | upload_data->cred_type = IoTHubClient_Auth_Get_Credential_Type(upload_data->authorization_module);
|
---|
| 289 | // If the credential type is unknown then it means that we are using x509 because the certs need to get
|
---|
| 290 | // passed down later in the process.
|
---|
| 291 | if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_UNKNOWN || upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509)
|
---|
| 292 | {
|
---|
| 293 | upload_data->cred_type = IOTHUB_CREDENTIAL_TYPE_X509;
|
---|
| 294 | upload_data->credentials.x509_credentials.x509certificate = NULL;
|
---|
| 295 | upload_data->credentials.x509_credentials.x509privatekey = NULL;
|
---|
| 296 | }
|
---|
| 297 | else if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC)
|
---|
| 298 | {
|
---|
| 299 | if (IoTHubClient_Auth_Get_x509_info(upload_data->authorization_module, &upload_data->credentials.x509_credentials.x509certificate, &upload_data->credentials.x509_credentials.x509privatekey) != 0)
|
---|
| 300 | {
|
---|
| 301 | LogError("Failed getting x509 certificate information");
|
---|
| 302 | free(upload_data->hostname);
|
---|
| 303 | free(upload_data);
|
---|
| 304 | upload_data = NULL;
|
---|
| 305 | }
|
---|
| 306 | }
|
---|
| 307 | else if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN)
|
---|
| 308 | {
|
---|
| 309 | upload_data->credentials.supplied_sas_token = IoTHubClient_Auth_Get_SasToken(upload_data->authorization_module, NULL, 0, EMPTY_STRING);
|
---|
| 310 | if (upload_data->credentials.supplied_sas_token == NULL)
|
---|
| 311 | {
|
---|
| 312 | LogError("Failed retrieving supplied sas token");
|
---|
| 313 | free(upload_data->hostname);
|
---|
| 314 | free(upload_data);
|
---|
| 315 | upload_data = NULL;
|
---|
| 316 | }
|
---|
| 317 | }
|
---|
| 318 | }
|
---|
| 319 | }
|
---|
| 320 | }
|
---|
| 321 | return (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE)upload_data;
|
---|
| 322 |
|
---|
| 323 | }
|
---|
| 324 |
|
---|
| 325 | /*returns 0 when correlationId, sasUri contain data*/
|
---|
| 326 | static int IoTHubClient_LL_UploadToBlob_step1and2(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, HTTPAPIEX_HANDLE iotHubHttpApiExHandle, HTTP_HEADERS_HANDLE requestHttpHeaders, const char* destinationFileName, STRING_HANDLE correlationId, STRING_HANDLE sasUri)
|
---|
| 327 | {
|
---|
| 328 | int result;
|
---|
| 329 |
|
---|
| 330 | /*Codes_SRS_IOTHUBCLIENT_LL_02_066: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall create an HTTP relative path formed from "/devices/" + deviceId + "/files/" + "?api-version=API_VERSION". ]*/
|
---|
| 331 | STRING_HANDLE relativePath = STRING_construct_sprintf("/devices/%s/files/%s", upload_data->deviceId, API_VERSION);
|
---|
| 332 | if (relativePath == NULL)
|
---|
| 333 | {
|
---|
| 334 | /*Codes_SRS_IOTHUBCLIENT_LL_02_067: [ If creating the relativePath fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 335 | LogError("Failure constructing string");
|
---|
| 336 | result = MU_FAILURE;
|
---|
| 337 | }
|
---|
| 338 | else
|
---|
| 339 | {
|
---|
| 340 | /*Codes_SRS_IOTHUBCLIENT_LL_32_001: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall create a JSON string formed from "{ \"blobName\": \" + destinationFileName + "\" }" */
|
---|
| 341 | STRING_HANDLE blobName = STRING_construct_sprintf("{ \"blobName\": \"%s\" }", destinationFileName);
|
---|
| 342 | if (blobName == NULL)
|
---|
| 343 | {
|
---|
| 344 | /*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 345 | LogError("Failure constructing string");
|
---|
| 346 | result = MU_FAILURE;
|
---|
| 347 | }
|
---|
| 348 | else
|
---|
| 349 | {
|
---|
| 350 | BUFFER_HANDLE responseContent;
|
---|
| 351 | size_t len = STRING_length(blobName);
|
---|
| 352 | BUFFER_HANDLE blobBuffer = BUFFER_create((const unsigned char *)STRING_c_str(blobName), len);
|
---|
| 353 | if (blobBuffer == NULL)
|
---|
| 354 | {
|
---|
| 355 | /*Codes_SRS_IOTHUBCLIENT_LL_32_002: [ If creating the JSON string fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 356 | LogError("unable to create BUFFER");
|
---|
| 357 | result = MU_FAILURE;
|
---|
| 358 | }
|
---|
| 359 | else
|
---|
| 360 | {
|
---|
| 361 | /*Codes_SRS_IOTHUBCLIENT_LL_02_068: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall create an HTTP responseContent BUFFER_HANDLE. ]*/
|
---|
| 362 | if ((responseContent = BUFFER_new()) == NULL)
|
---|
| 363 | {
|
---|
| 364 | /*Codes_SRS_IOTHUBCLIENT_LL_02_069: [ If creating the HTTP response buffer handle fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 365 | result = MU_FAILURE;
|
---|
| 366 | LogError("unable to BUFFER_new");
|
---|
| 367 | }
|
---|
| 368 | else
|
---|
| 369 | {
|
---|
| 370 | /*Codes_SRS_IOTHUBCLIENT_LL_02_072: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall add the following name:value to request HTTP headers: ] "Content-Type": "application/json" "Accept": "application/json" "User-Agent": "iothubclient/" IOTHUB_SDK_VERSION*/
|
---|
| 371 | /*Codes_SRS_IOTHUBCLIENT_LL_02_107: [ - "Authorization" header shall not be build. ]*/
|
---|
| 372 | if (!(
|
---|
| 373 | (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Content-Type", HEADER_APP_JSON) == HTTP_HEADERS_OK) &&
|
---|
| 374 | (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "Accept", HEADER_APP_JSON) == HTTP_HEADERS_OK) &&
|
---|
| 375 | (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, "User-Agent", "iothubclient/" IOTHUB_SDK_VERSION) == HTTP_HEADERS_OK) &&
|
---|
| 376 | ((upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509 || upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC) ||
|
---|
| 377 | (HTTPHeaders_AddHeaderNameValuePair(requestHttpHeaders, HEADER_AUTHORIZATION, EMPTY_STRING) == HTTP_HEADERS_OK))
|
---|
| 378 | ))
|
---|
| 379 | {
|
---|
| 380 | /*Codes_SRS_IOTHUBCLIENT_LL_02_071: [ If creating the HTTP headers fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 381 | LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
|
---|
| 382 | result = MU_FAILURE;
|
---|
| 383 | }
|
---|
| 384 | else
|
---|
| 385 | {
|
---|
| 386 | int wasIoTHubRequestSuccess = 0; /*!=0 means responseContent has a buffer that should be parsed by parson after executing the below switch*/
|
---|
| 387 | /* set the result to error by default */
|
---|
| 388 | result = MU_FAILURE;
|
---|
| 389 | switch (upload_data->cred_type)
|
---|
| 390 | {
|
---|
| 391 | default:
|
---|
| 392 | {
|
---|
| 393 | /*wasIoTHubRequestSuccess takes care of the return value*/
|
---|
| 394 | LogError("Internal Error: unexpected value in auth schema = %d", upload_data->cred_type);
|
---|
| 395 | result = MU_FAILURE;
|
---|
| 396 | break;
|
---|
| 397 | }
|
---|
| 398 | case IOTHUB_CREDENTIAL_TYPE_X509_ECC:
|
---|
| 399 | case IOTHUB_CREDENTIAL_TYPE_X509:
|
---|
| 400 | {
|
---|
| 401 | if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0)
|
---|
| 402 | {
|
---|
| 403 | /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 404 | result = MU_FAILURE;
|
---|
| 405 | LogError("unable to HTTPAPIEX_ExecuteRequest");
|
---|
| 406 | }
|
---|
| 407 | else
|
---|
| 408 | {
|
---|
| 409 | wasIoTHubRequestSuccess = 1;
|
---|
| 410 | }
|
---|
| 411 | break;
|
---|
| 412 | }
|
---|
| 413 | case IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY:
|
---|
| 414 | case IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH:
|
---|
| 415 | {
|
---|
| 416 | STRING_HANDLE uri_resource = STRING_construct_sprintf("%s/devices/%s", upload_data->hostname, upload_data->deviceId);
|
---|
| 417 | if (uri_resource == NULL)
|
---|
| 418 | {
|
---|
| 419 | /*Codes_SRS_IOTHUBCLIENT_LL_02_089: [ If creating the HTTPAPIEX_SAS_HANDLE fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 420 | result = MU_FAILURE;
|
---|
| 421 | LogError("Failure constructing string");
|
---|
| 422 | }
|
---|
| 423 | else
|
---|
| 424 | {
|
---|
| 425 | if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH)
|
---|
| 426 | {
|
---|
| 427 | time_t curr_time;
|
---|
| 428 | if ((curr_time = get_time(NULL)) == INDEFINITE_TIME)
|
---|
| 429 | {
|
---|
| 430 | result = MU_FAILURE;
|
---|
| 431 | LogError("failure retrieving time");
|
---|
| 432 | }
|
---|
| 433 | else
|
---|
| 434 | {
|
---|
| 435 | size_t expiry = (size_t)(difftime(curr_time, 0) + 3600);
|
---|
| 436 | char* sas_token = IoTHubClient_Auth_Get_SasToken(upload_data->authorization_module, STRING_c_str(uri_resource), expiry, EMPTY_STRING);
|
---|
| 437 | if (sas_token == NULL)
|
---|
| 438 | {
|
---|
| 439 | result = MU_FAILURE;
|
---|
| 440 | LogError("unable to retrieve sas token");
|
---|
| 441 | }
|
---|
| 442 | else
|
---|
| 443 | {
|
---|
| 444 | if (HTTPHeaders_ReplaceHeaderNameValuePair(requestHttpHeaders, HEADER_AUTHORIZATION, sas_token) != HTTP_HEADERS_OK)
|
---|
| 445 | {
|
---|
| 446 | /*Codes_SRS_IOTHUBCLIENT_LL_02_074: [ If adding "Authorization" fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR ]*/
|
---|
| 447 | result = MU_FAILURE;
|
---|
| 448 | LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
|
---|
| 449 | }
|
---|
| 450 | else if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0)
|
---|
| 451 | {
|
---|
| 452 | /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 453 | result = MU_FAILURE;
|
---|
| 454 | LogError("unable to HTTPAPIEX_ExecuteRequest");
|
---|
| 455 | }
|
---|
| 456 | else
|
---|
| 457 | {
|
---|
| 458 | wasIoTHubRequestSuccess = 1;
|
---|
| 459 | }
|
---|
| 460 | }
|
---|
| 461 | free(sas_token);
|
---|
| 462 | }
|
---|
| 463 | }
|
---|
| 464 | else
|
---|
| 465 | {
|
---|
| 466 | if (send_http_sas_request(upload_data, STRING_c_str(uri_resource), iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0)
|
---|
| 467 | {
|
---|
| 468 | /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 469 | result = MU_FAILURE;
|
---|
| 470 | LogError("unable to HTTPAPIEX_ExecuteRequest");
|
---|
| 471 | }
|
---|
| 472 | else
|
---|
| 473 | {
|
---|
| 474 | wasIoTHubRequestSuccess = 1;
|
---|
| 475 | }
|
---|
| 476 | }
|
---|
| 477 | STRING_delete(uri_resource);
|
---|
| 478 | }
|
---|
| 479 | break;
|
---|
| 480 | }
|
---|
| 481 | case IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN:
|
---|
| 482 | {
|
---|
| 483 | /*Codes_SRS_IOTHUBCLIENT_LL_02_073: [ If the credentials used to create handle have "sasToken" then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall add the following HTTP request headers: ]*/
|
---|
| 484 | if (HTTPHeaders_ReplaceHeaderNameValuePair(requestHttpHeaders, HEADER_AUTHORIZATION, upload_data->credentials.supplied_sas_token) != HTTP_HEADERS_OK)
|
---|
| 485 | {
|
---|
| 486 | /*Codes_SRS_IOTHUBCLIENT_LL_02_074: [ If adding "Authorization" fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR ]*/
|
---|
| 487 | result = MU_FAILURE;
|
---|
| 488 | LogError("unable to HTTPHeaders_AddHeaderNameValuePair");
|
---|
| 489 | }
|
---|
| 490 | else if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePath), requestHttpHeaders, blobBuffer, responseContent) != 0)
|
---|
| 491 | {
|
---|
| 492 | /*Codes_SRS_IOTHUBCLIENT_LL_02_076: [ If HTTPAPIEX_ExecuteRequest call fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 493 | result = MU_FAILURE;
|
---|
| 494 | LogError("unable to HTTPAPIEX_ExecuteRequest");
|
---|
| 495 | }
|
---|
| 496 | else
|
---|
| 497 | {
|
---|
| 498 | wasIoTHubRequestSuccess = 1;
|
---|
| 499 | }
|
---|
| 500 | break;
|
---|
| 501 | }
|
---|
| 502 | }
|
---|
| 503 | if (wasIoTHubRequestSuccess == 1)
|
---|
| 504 | {
|
---|
| 505 | const unsigned char*responseContent_u_char = BUFFER_u_char(responseContent);
|
---|
| 506 | size_t responseContent_length = BUFFER_length(responseContent);
|
---|
| 507 | STRING_HANDLE responseAsString = STRING_from_byte_array(responseContent_u_char, responseContent_length);
|
---|
| 508 | if (responseAsString == NULL)
|
---|
| 509 | {
|
---|
| 510 | result = MU_FAILURE;
|
---|
| 511 | LogError("unable to get the response as string");
|
---|
| 512 | }
|
---|
| 513 | else
|
---|
| 514 | {
|
---|
| 515 | if (parse_result_json(STRING_c_str(responseAsString), correlationId, sasUri) != 0)
|
---|
| 516 | {
|
---|
| 517 | /*Codes_SRS_IOTHUBCLIENT_LL_02_082: [ If extracting and saving the correlationId or SasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 518 | LogError("unable to parse json result");
|
---|
| 519 | result = MU_FAILURE;
|
---|
| 520 | }
|
---|
| 521 | else
|
---|
| 522 | {
|
---|
| 523 | result = 0;
|
---|
| 524 | }
|
---|
| 525 | STRING_delete(responseAsString);
|
---|
| 526 | }
|
---|
| 527 | }
|
---|
| 528 | }
|
---|
| 529 | BUFFER_delete(responseContent);
|
---|
| 530 | }
|
---|
| 531 | BUFFER_delete(blobBuffer);
|
---|
| 532 | }
|
---|
| 533 | STRING_delete(blobName);
|
---|
| 534 | }
|
---|
| 535 | STRING_delete(relativePath);
|
---|
| 536 | }
|
---|
| 537 | return result;
|
---|
| 538 | }
|
---|
| 539 |
|
---|
| 540 | /*returns 0 when the IoTHub has been informed about the file upload status*/
|
---|
| 541 | static int IoTHubClient_LL_UploadToBlob_step3(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, STRING_HANDLE correlationId, HTTPAPIEX_HANDLE iotHubHttpApiExHandle, HTTP_HEADERS_HANDLE requestHttpHeaders, BUFFER_HANDLE messageBody)
|
---|
| 542 | {
|
---|
| 543 | int result;
|
---|
| 544 | /*here is step 3. depending on the outcome of step 2 it needs to inform IoTHub about the file upload status*/
|
---|
| 545 | /*if step 1 failed, there's nothing that step 3 needs to report.*/
|
---|
| 546 | /*this POST "tries" to happen*/
|
---|
| 547 |
|
---|
| 548 | /*Codes_SRS_IOTHUBCLIENT_LL_02_085: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall use the same authorization as step 1. to prepare and perform a HTTP request with the following parameters: ]*/
|
---|
| 549 | STRING_HANDLE relativePathNotification = STRING_construct_sprintf("/devices/%s/files/notifications/%s%s", upload_data->deviceId, STRING_c_str(correlationId), API_VERSION);
|
---|
| 550 | if (relativePathNotification == NULL)
|
---|
| 551 | {
|
---|
| 552 | result = MU_FAILURE;
|
---|
| 553 | LogError("Failure constructing string");
|
---|
| 554 | }
|
---|
| 555 | else
|
---|
| 556 | {
|
---|
| 557 | /*Codes_SRS_IOTHUBCLIENT_LL_02_086: [ If performing the HTTP request fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 558 | switch (upload_data->cred_type)
|
---|
| 559 | {
|
---|
| 560 | default:
|
---|
| 561 | {
|
---|
| 562 | LogError("internal error: unknown authorization Scheme");
|
---|
| 563 | result = MU_FAILURE;
|
---|
| 564 | break;
|
---|
| 565 | }
|
---|
| 566 | case IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN:
|
---|
| 567 | case IOTHUB_CREDENTIAL_TYPE_X509:
|
---|
| 568 | case IOTHUB_CREDENTIAL_TYPE_X509_ECC:
|
---|
| 569 | case IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH:
|
---|
| 570 | {
|
---|
| 571 | if (send_http_request(iotHubHttpApiExHandle, STRING_c_str(relativePathNotification), requestHttpHeaders, messageBody, NULL) != 0)
|
---|
| 572 | {
|
---|
| 573 | LogError("unable to execute HTTPAPIEX_ExecuteRequest");
|
---|
| 574 | result = MU_FAILURE;
|
---|
| 575 | }
|
---|
| 576 | else
|
---|
| 577 | {
|
---|
| 578 | result = 0;
|
---|
| 579 | }
|
---|
| 580 | break;
|
---|
| 581 | }
|
---|
| 582 | case IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY:
|
---|
| 583 | {
|
---|
| 584 | STRING_HANDLE uriResource = STRING_construct_sprintf("%s/devices/%s/files/notifications", upload_data->hostname, upload_data->deviceId);
|
---|
| 585 | if (uriResource == NULL)
|
---|
| 586 | {
|
---|
| 587 | LogError("Failure constructing string");
|
---|
| 588 | result = MU_FAILURE;
|
---|
| 589 | }
|
---|
| 590 | else
|
---|
| 591 | {
|
---|
| 592 | if (send_http_sas_request(upload_data, STRING_c_str(uriResource), iotHubHttpApiExHandle, STRING_c_str(relativePathNotification), requestHttpHeaders, messageBody, NULL) != 0)
|
---|
| 593 | {
|
---|
| 594 | LogError("unable to execute HTTPAPIEX_ExecuteRequest");
|
---|
| 595 | result = MU_FAILURE;
|
---|
| 596 | }
|
---|
| 597 | else
|
---|
| 598 | {
|
---|
| 599 | result = 0;
|
---|
| 600 | }
|
---|
| 601 | STRING_delete(uriResource);
|
---|
| 602 | }
|
---|
| 603 | break;
|
---|
| 604 | }
|
---|
| 605 | }
|
---|
| 606 | STRING_delete(relativePathNotification);
|
---|
| 607 | }
|
---|
| 608 | return result;
|
---|
| 609 | }
|
---|
| 610 |
|
---|
| 611 | // this callback splits the source data into blocks to be fed to IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex)_Impl
|
---|
| 612 | static IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT FileUpload_GetData_Callback(IOTHUB_CLIENT_FILE_UPLOAD_RESULT result, unsigned char const ** data, size_t* size, void* context)
|
---|
| 613 | {
|
---|
| 614 | BLOB_UPLOAD_CONTEXT* uploadContext = (BLOB_UPLOAD_CONTEXT*) context;
|
---|
| 615 |
|
---|
| 616 | if (data == NULL || size == NULL)
|
---|
| 617 | {
|
---|
| 618 | // This is the last call, nothing to do
|
---|
| 619 | }
|
---|
| 620 | else if (result != FILE_UPLOAD_OK)
|
---|
| 621 | {
|
---|
| 622 | // Last call failed
|
---|
| 623 | *data = NULL;
|
---|
| 624 | *size = 0;
|
---|
| 625 | }
|
---|
| 626 | else if (uploadContext->remainingSizeToUpload == 0)
|
---|
| 627 | {
|
---|
| 628 | // Everything has been uploaded
|
---|
| 629 | *data = NULL;
|
---|
| 630 | *size = 0;
|
---|
| 631 | }
|
---|
| 632 | else
|
---|
| 633 | {
|
---|
| 634 | // Upload next block
|
---|
| 635 | size_t thisBlockSize = (uploadContext->remainingSizeToUpload > BLOCK_SIZE) ? BLOCK_SIZE : uploadContext->remainingSizeToUpload;
|
---|
| 636 | *data = (unsigned char*)uploadContext->blobSource + (uploadContext->blobSourceSize - uploadContext->remainingSizeToUpload);
|
---|
| 637 | *size = thisBlockSize;
|
---|
| 638 | uploadContext->remainingSizeToUpload -= thisBlockSize;
|
---|
| 639 | }
|
---|
| 640 |
|
---|
| 641 | return IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_OK;
|
---|
| 642 | }
|
---|
| 643 |
|
---|
| 644 | static HTTPAPIEX_RESULT set_transfer_timeout(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data, HTTPAPIEX_HANDLE iotHubHttpApiExHandle)
|
---|
| 645 | {
|
---|
| 646 | HTTPAPIEX_RESULT result;
|
---|
| 647 | if (upload_data->blob_upload_timeout_secs != 0)
|
---|
| 648 | {
|
---|
| 649 | // Convert the timeout to milliseconds for curl
|
---|
| 650 | long http_timeout = (long)upload_data->blob_upload_timeout_secs * 1000;
|
---|
| 651 | result = HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_HTTP_TIMEOUT, &http_timeout);
|
---|
| 652 | }
|
---|
| 653 | else
|
---|
| 654 | {
|
---|
| 655 | result = HTTPAPIEX_OK;
|
---|
| 656 | }
|
---|
| 657 | return result;
|
---|
| 658 | }
|
---|
| 659 |
|
---|
| 660 | IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context)
|
---|
| 661 | {
|
---|
| 662 | IOTHUB_CLIENT_RESULT result;
|
---|
| 663 |
|
---|
| 664 | /*Codes_SRS_IOTHUBCLIENT_LL_02_061: [ If handle is NULL then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
|
---|
| 665 | /*Codes_SRS_IOTHUBCLIENT_LL_02_062: [ If destinationFileName is NULL then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
|
---|
| 666 |
|
---|
| 667 | if (handle == NULL || destinationFileName == NULL || getDataCallbackEx == NULL)
|
---|
| 668 | {
|
---|
| 669 | LogError("invalid argument detected handle=%p destinationFileName=%p getDataCallbackEx=%p", handle, destinationFileName, getDataCallbackEx);
|
---|
| 670 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
| 671 | }
|
---|
| 672 | else
|
---|
| 673 | {
|
---|
| 674 | IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle;
|
---|
| 675 |
|
---|
| 676 | /*Codes_SRS_IOTHUBCLIENT_LL_02_064: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall create an HTTPAPIEX_HANDLE to the IoTHub hostname. ]*/
|
---|
| 677 | HTTPAPIEX_HANDLE iotHubHttpApiExHandle = HTTPAPIEX_Create(upload_data->hostname);
|
---|
| 678 | /*Codes_SRS_IOTHUBCLIENT_LL_02_065: [ If creating the HTTPAPIEX_HANDLE fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 679 | if (iotHubHttpApiExHandle == NULL)
|
---|
| 680 | {
|
---|
| 681 | LogError("unable to HTTPAPIEX_Create");
|
---|
| 682 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 683 | }
|
---|
| 684 | /*Codes_SRS_IOTHUBCLIENT_LL_30_020: [ If the blob_upload_timeout_secs option has been set to non-zero, IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall set the timeout on the underlying transport accordingly. ]*/
|
---|
| 685 | else if (set_transfer_timeout(upload_data, iotHubHttpApiExHandle) != HTTPAPIEX_OK)
|
---|
| 686 | {
|
---|
| 687 | LogError("unable to set blob transfer timeout");
|
---|
| 688 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 689 | }
|
---|
| 690 | else
|
---|
| 691 | {
|
---|
| 692 | if (upload_data->curl_verbosity_level != UPOADTOBLOB_CURL_VERBOSITY_UNSET)
|
---|
| 693 | {
|
---|
| 694 | size_t curl_verbose = (upload_data->curl_verbosity_level == UPOADTOBLOB_CURL_VERBOSITY_ON);
|
---|
| 695 | (void)HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_CURL_VERBOSE, &curl_verbose);
|
---|
| 696 | }
|
---|
| 697 |
|
---|
| 698 | /*transmit the x509certificate and x509privatekey*/
|
---|
| 699 | /*Codes_SRS_IOTHUBCLIENT_LL_02_106: [ - x509certificate and x509privatekey saved options shall be passed on the HTTPAPIEX_SetOption ]*/
|
---|
| 700 | if ((upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509 || upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC) &&
|
---|
| 701 | ((HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_X509_CERT, upload_data->credentials.x509_credentials.x509certificate) != HTTPAPIEX_OK) ||
|
---|
| 702 | (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_X509_PRIVATE_KEY, upload_data->credentials.x509_credentials.x509privatekey) != HTTPAPIEX_OK))
|
---|
| 703 | )
|
---|
| 704 | {
|
---|
| 705 | LogError("unable to HTTPAPIEX_SetOption for x509 certificate");
|
---|
| 706 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 707 | }
|
---|
| 708 | else
|
---|
| 709 | {
|
---|
| 710 | /*Codes_SRS_IOTHUBCLIENT_LL_02_111: [ If certificates is non-NULL then certificates shall be passed to HTTPAPIEX_SetOption with optionName TrustedCerts. ]*/
|
---|
| 711 | if ((upload_data->certificates != NULL) && (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_TRUSTED_CERT, upload_data->certificates) != HTTPAPIEX_OK))
|
---|
| 712 | {
|
---|
| 713 | LogError("unable to set TrustedCerts!");
|
---|
| 714 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 715 | }
|
---|
| 716 | else
|
---|
| 717 | {
|
---|
| 718 |
|
---|
| 719 | if (upload_data->http_proxy_options.host_address != NULL)
|
---|
| 720 | {
|
---|
| 721 | HTTP_PROXY_OPTIONS proxy_options;
|
---|
| 722 | proxy_options = upload_data->http_proxy_options;
|
---|
| 723 |
|
---|
| 724 | if (HTTPAPIEX_SetOption(iotHubHttpApiExHandle, OPTION_HTTP_PROXY, &proxy_options) != HTTPAPIEX_OK)
|
---|
| 725 | {
|
---|
| 726 | LogError("unable to set http proxy!");
|
---|
| 727 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 728 | }
|
---|
| 729 | else
|
---|
| 730 | {
|
---|
| 731 | result = IOTHUB_CLIENT_OK;
|
---|
| 732 | }
|
---|
| 733 | }
|
---|
| 734 | else
|
---|
| 735 | {
|
---|
| 736 | result = IOTHUB_CLIENT_OK;
|
---|
| 737 | }
|
---|
| 738 |
|
---|
| 739 | if (result != IOTHUB_CLIENT_ERROR)
|
---|
| 740 | {
|
---|
| 741 | STRING_HANDLE sasUri;
|
---|
| 742 | STRING_HANDLE correlationId;
|
---|
| 743 | if ((correlationId = STRING_new()) == NULL)
|
---|
| 744 | {
|
---|
| 745 | LogError("unable to STRING_new");
|
---|
| 746 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 747 | }
|
---|
| 748 | else if ((sasUri = STRING_new()) == NULL)
|
---|
| 749 | {
|
---|
| 750 | LogError("unable to create sas uri");
|
---|
| 751 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 752 | STRING_delete(correlationId);
|
---|
| 753 | }
|
---|
| 754 | else
|
---|
| 755 | {
|
---|
| 756 | /*Codes_SRS_IOTHUBCLIENT_LL_02_070: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall create request HTTP headers. ]*/
|
---|
| 757 | HTTP_HEADERS_HANDLE requestHttpHeaders = HTTPHeaders_Alloc(); /*these are build by step 1 and used by step 3 too*/
|
---|
| 758 | if (requestHttpHeaders == NULL)
|
---|
| 759 | {
|
---|
| 760 | LogError("unable to HTTPHeaders_Alloc");
|
---|
| 761 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 762 | }
|
---|
| 763 | else
|
---|
| 764 | {
|
---|
| 765 | /*do step 1*/
|
---|
| 766 | if (IoTHubClient_LL_UploadToBlob_step1and2(upload_data, iotHubHttpApiExHandle, requestHttpHeaders, destinationFileName, correlationId, sasUri) != 0)
|
---|
| 767 | {
|
---|
| 768 | LogError("error in IoTHubClient_LL_UploadToBlob_step1");
|
---|
| 769 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 770 | }
|
---|
| 771 | else
|
---|
| 772 | {
|
---|
| 773 | /*do step 2.*/
|
---|
| 774 |
|
---|
| 775 | unsigned int httpResponse;
|
---|
| 776 | BUFFER_HANDLE responseToIoTHub = BUFFER_new();
|
---|
| 777 | if (responseToIoTHub == NULL)
|
---|
| 778 | {
|
---|
| 779 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 780 | LogError("unable to BUFFER_new");
|
---|
| 781 | }
|
---|
| 782 | else
|
---|
| 783 | {
|
---|
| 784 | /*Codes_SRS_IOTHUBCLIENT_LL_02_083: [ IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall call Blob_UploadFromSasUri and capture the HTTP return code and HTTP body. ]*/
|
---|
| 785 | BLOB_RESULT uploadMultipleBlocksResult = Blob_UploadMultipleBlocksFromSasUri(STRING_c_str(sasUri), getDataCallbackEx, context, &httpResponse, responseToIoTHub, upload_data->certificates, &(upload_data->http_proxy_options));
|
---|
| 786 | if (uploadMultipleBlocksResult == BLOB_ABORTED)
|
---|
| 787 | {
|
---|
| 788 | /*Codes_SRS_IOTHUBCLIENT_LL_99_008: [ If step 2 is aborted by the client, then the HTTP message body shall look like: ]*/
|
---|
| 789 | LogInfo("Blob_UploadFromSasUri aborted file upload");
|
---|
| 790 |
|
---|
| 791 | if (BUFFER_build(responseToIoTHub, (const unsigned char*)FILE_UPLOAD_ABORTED_BODY, sizeof(FILE_UPLOAD_ABORTED_BODY) / sizeof(FILE_UPLOAD_ABORTED_BODY[0])) == 0)
|
---|
| 792 | {
|
---|
| 793 | if (IoTHubClient_LL_UploadToBlob_step3(upload_data, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, responseToIoTHub) != 0)
|
---|
| 794 | {
|
---|
| 795 | LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
|
---|
| 796 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 797 | }
|
---|
| 798 | else
|
---|
| 799 | {
|
---|
| 800 | /*Codes_SRS_IOTHUBCLIENT_LL_99_009: [ If step 2 is aborted by the client and if step 3 succeeds, then `IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex)` shall return `IOTHUB_CLIENT_OK`. ] */
|
---|
| 801 | result = IOTHUB_CLIENT_OK;
|
---|
| 802 | }
|
---|
| 803 | }
|
---|
| 804 | else
|
---|
| 805 | {
|
---|
| 806 | LogError("Unable to BUFFER_build, can't perform IoTHubClient_LL_UploadToBlob_step3");
|
---|
| 807 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 808 | }
|
---|
| 809 | }
|
---|
| 810 | else if (uploadMultipleBlocksResult != BLOB_OK)
|
---|
| 811 | {
|
---|
| 812 | /*Codes_SRS_IOTHUBCLIENT_LL_02_084: [ If Blob_UploadFromSasUri fails then IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex) shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 813 | LogError("unable to Blob_UploadFromSasUri");
|
---|
| 814 |
|
---|
| 815 | /*do step 3*/ /*try*/
|
---|
| 816 | /*Codes_SRS_IOTHUBCLIENT_LL_02_091: [ If step 2 fails without establishing an HTTP dialogue, then the HTTP message body shall look like: ]*/
|
---|
| 817 | if (BUFFER_build(responseToIoTHub, (const unsigned char*)FILE_UPLOAD_FAILED_BODY, sizeof(FILE_UPLOAD_FAILED_BODY) / sizeof(FILE_UPLOAD_FAILED_BODY[0])) == 0)
|
---|
| 818 | {
|
---|
| 819 | if (IoTHubClient_LL_UploadToBlob_step3(upload_data, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, responseToIoTHub) != 0)
|
---|
| 820 | {
|
---|
| 821 | LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
|
---|
| 822 | }
|
---|
| 823 | }
|
---|
| 824 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 825 | }
|
---|
| 826 | else
|
---|
| 827 | {
|
---|
| 828 | /*must make a json*/
|
---|
| 829 | unsigned char * response = BUFFER_u_char(responseToIoTHub);
|
---|
| 830 | STRING_HANDLE req_string;
|
---|
| 831 | if(response == NULL)
|
---|
| 832 | {
|
---|
| 833 | req_string = STRING_construct_sprintf("{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":""}", ((httpResponse < 300) ? "true" : "false"), httpResponse);
|
---|
[396] | 834 | }
|
---|
[388] | 835 | else
|
---|
| 836 | {
|
---|
| 837 | req_string = STRING_construct_sprintf("{\"isSuccess\":%s, \"statusCode\":%d, \"statusDescription\":\"%s\"}", ((httpResponse < 300) ? "true" : "false"), httpResponse, response);
|
---|
| 838 | }
|
---|
| 839 | if (req_string == NULL)
|
---|
| 840 | {
|
---|
| 841 | LogError("Failure constructing string");
|
---|
| 842 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 843 | }
|
---|
| 844 | else
|
---|
| 845 | {
|
---|
| 846 | /*do again snprintf*/
|
---|
| 847 | BUFFER_HANDLE toBeTransmitted = NULL;
|
---|
| 848 | size_t req_string_len = STRING_length(req_string);
|
---|
| 849 | const char* required_string = STRING_c_str(req_string);
|
---|
| 850 | if ((toBeTransmitted = BUFFER_create((const unsigned char*)required_string, req_string_len)) == NULL)
|
---|
| 851 | {
|
---|
| 852 | LogError("unable to BUFFER_create");
|
---|
| 853 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 854 | }
|
---|
| 855 | else
|
---|
| 856 | {
|
---|
| 857 | if (IoTHubClient_LL_UploadToBlob_step3(upload_data, correlationId, iotHubHttpApiExHandle, requestHttpHeaders, toBeTransmitted) != 0)
|
---|
| 858 | {
|
---|
| 859 | LogError("IoTHubClient_LL_UploadToBlob_step3 failed");
|
---|
| 860 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 861 | }
|
---|
| 862 | else
|
---|
| 863 | {
|
---|
| 864 | result = (httpResponse < 300) ? IOTHUB_CLIENT_OK : IOTHUB_CLIENT_ERROR;
|
---|
| 865 | }
|
---|
| 866 | BUFFER_delete(toBeTransmitted);
|
---|
| 867 | }
|
---|
| 868 | STRING_delete(req_string);
|
---|
| 869 | }
|
---|
| 870 | }
|
---|
| 871 | BUFFER_delete(responseToIoTHub);
|
---|
| 872 | }
|
---|
| 873 | }
|
---|
| 874 | HTTPHeaders_Free(requestHttpHeaders);
|
---|
| 875 | }
|
---|
| 876 | STRING_delete(sasUri);
|
---|
| 877 | STRING_delete(correlationId);
|
---|
| 878 | }
|
---|
| 879 | }
|
---|
| 880 | }
|
---|
| 881 | }
|
---|
| 882 | HTTPAPIEX_Destroy(iotHubHttpApiExHandle);
|
---|
| 883 | }
|
---|
| 884 |
|
---|
| 885 | /*Codes_SRS_IOTHUBCLIENT_LL_99_003: [ If `IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex)` return `IOTHUB_CLIENT_OK`, it shall call `getDataCallbackEx` with `result` set to `FILE_UPLOAD_OK`, and `data` and `size` set to NULL. ]*/
|
---|
| 886 | /*Codes_SRS_IOTHUBCLIENT_LL_99_004: [ If `IoTHubClient_LL_UploadMultipleBlocksToBlob(Ex)` does not return `IOTHUB_CLIENT_OK`, it shall call `getDataCallbackEx` with `result` set to `FILE_UPLOAD_ERROR`, and `data` and `size` set to NULL. ]*/
|
---|
| 887 | (void)getDataCallbackEx(result == IOTHUB_CLIENT_OK ? FILE_UPLOAD_OK : FILE_UPLOAD_ERROR, NULL, NULL, context);
|
---|
| 888 | }
|
---|
| 889 | return result;
|
---|
| 890 | }
|
---|
| 891 |
|
---|
| 892 | IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_Impl(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* destinationFileName, const unsigned char* source, size_t size)
|
---|
| 893 | {
|
---|
| 894 | IOTHUB_CLIENT_RESULT result;
|
---|
| 895 |
|
---|
| 896 | if (handle == NULL || destinationFileName == NULL)
|
---|
| 897 | {
|
---|
| 898 | LogError("Invalid parameter handle:%p destinationFileName:%p", handle, destinationFileName);
|
---|
| 899 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
| 900 | }
|
---|
| 901 | /*Codes_SRS_IOTHUBCLIENT_LL_02_063: [ If source is NULL and size is greater than 0 then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/
|
---|
| 902 | else if (source == NULL && size > 0)
|
---|
| 903 | {
|
---|
| 904 | LogError("Invalid source and size combination: source=%p size=%lu", source, (unsigned long)size);
|
---|
| 905 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
| 906 | }
|
---|
| 907 | else
|
---|
| 908 | {
|
---|
| 909 | /*Codes_SRS_IOTHUBCLIENT_LL_99_001: [ `IoTHubClient_LL_UploadToBlob` shall create a struct containing the `source`, the `size`, and the remaining size to upload.]*/
|
---|
| 910 | BLOB_UPLOAD_CONTEXT context;
|
---|
| 911 | context.blobSource = source;
|
---|
| 912 | context.blobSourceSize = size;
|
---|
| 913 | context.remainingSizeToUpload = size;
|
---|
| 914 |
|
---|
| 915 | /*Codes_SRS_IOTHUBCLIENT_LL_99_002: [ `IoTHubClient_LL_UploadToBlob` shall call `IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl` with `FileUpload_GetData_Callback` as `getDataCallbackEx` and pass the struct created at step SRS_IOTHUBCLIENT_LL_99_001 as `context` ]*/
|
---|
| 916 | result = IoTHubClient_LL_UploadMultipleBlocksToBlob_Impl(handle, destinationFileName, FileUpload_GetData_Callback, &context);
|
---|
| 917 | }
|
---|
| 918 | return result;
|
---|
| 919 | }
|
---|
| 920 |
|
---|
| 921 | void IoTHubClient_LL_UploadToBlob_Destroy(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle)
|
---|
| 922 | {
|
---|
| 923 | if (handle == NULL)
|
---|
| 924 | {
|
---|
| 925 | LogError("unexpected NULL argument");
|
---|
| 926 | }
|
---|
| 927 | else
|
---|
| 928 | {
|
---|
| 929 | IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle;
|
---|
| 930 |
|
---|
| 931 | if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509 || upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC)
|
---|
| 932 | {
|
---|
| 933 | free(upload_data->credentials.x509_credentials.x509certificate);
|
---|
| 934 | free(upload_data->credentials.x509_credentials.x509privatekey);
|
---|
| 935 | }
|
---|
| 936 | else if (upload_data->cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN)
|
---|
| 937 | {
|
---|
| 938 | free(upload_data->credentials.supplied_sas_token);
|
---|
| 939 | }
|
---|
| 940 |
|
---|
| 941 | free((void*)upload_data->hostname);
|
---|
| 942 | if (upload_data->certificates != NULL)
|
---|
| 943 | {
|
---|
| 944 | free(upload_data->certificates);
|
---|
| 945 | }
|
---|
| 946 | if (upload_data->http_proxy_options.host_address != NULL)
|
---|
| 947 | {
|
---|
| 948 | free((char *)upload_data->http_proxy_options.host_address);
|
---|
| 949 | }
|
---|
| 950 | if (upload_data->http_proxy_options.username != NULL)
|
---|
| 951 | {
|
---|
| 952 | free((char *)upload_data->http_proxy_options.username);
|
---|
| 953 | }
|
---|
| 954 | if (upload_data->http_proxy_options.password != NULL)
|
---|
| 955 | {
|
---|
| 956 | free((char *)upload_data->http_proxy_options.password);
|
---|
| 957 | }
|
---|
| 958 | free(upload_data);
|
---|
| 959 | }
|
---|
| 960 | }
|
---|
| 961 |
|
---|
| 962 | IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob_SetOption(IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle, const char* optionName, const void* value)
|
---|
| 963 | {
|
---|
| 964 | IOTHUB_CLIENT_RESULT result;
|
---|
| 965 | /*Codes_SRS_IOTHUBCLIENT_LL_02_110: [ If parameter handle is NULL then IoTHubClient_LL_UploadToBlob_SetOption shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 966 | if (handle == NULL)
|
---|
| 967 | {
|
---|
| 968 | LogError("invalid argument detected: IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE handle=%p, const char* optionName=%s, const void* value=%p", handle, optionName, value);
|
---|
| 969 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 970 | }
|
---|
| 971 | else
|
---|
| 972 | {
|
---|
| 973 | IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* upload_data = (IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA*)handle;
|
---|
| 974 |
|
---|
| 975 | /*Codes_SRS_IOTHUBCLIENT_LL_02_100: [ x509certificate - then value then is a null terminated string that contains the x509 certificate. ]*/
|
---|
| 976 | if (strcmp(optionName, OPTION_X509_CERT) == 0)
|
---|
| 977 | {
|
---|
| 978 | /*Codes_SRS_IOTHUBCLIENT_LL_02_109: [ If the authentication scheme is NOT x509 then IoTHubClient_LL_UploadToBlob_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
|
---|
| 979 | if (upload_data->cred_type != IOTHUB_CREDENTIAL_TYPE_X509)
|
---|
| 980 | {
|
---|
| 981 | LogError("trying to set a x509 certificate while the authentication scheme is not x509");
|
---|
| 982 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
| 983 | }
|
---|
| 984 | else
|
---|
| 985 | {
|
---|
| 986 | /*Codes_SRS_IOTHUBCLIENT_LL_02_103: [ The options shall be saved. ]*/
|
---|
| 987 | /*try to make a copy of the certificate*/
|
---|
| 988 | char* temp;
|
---|
| 989 | if (mallocAndStrcpy_s(&temp, value) != 0)
|
---|
| 990 | {
|
---|
| 991 | /*Codes_SRS_IOTHUBCLIENT_LL_02_104: [ If saving fails, then IoTHubClient_LL_UploadToBlob_SetOption shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 992 | LogError("unable to mallocAndStrcpy_s");
|
---|
| 993 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 994 | }
|
---|
| 995 | else
|
---|
| 996 | {
|
---|
| 997 | /*Codes_SRS_IOTHUBCLIENT_LL_02_105: [ Otherwise IoTHubClient_LL_UploadToBlob_SetOption shall succeed and return IOTHUB_CLIENT_OK. ]*/
|
---|
| 998 | if (upload_data->credentials.x509_credentials.x509certificate != NULL) /*free any previous values, if any*/
|
---|
| 999 | {
|
---|
| 1000 | free(upload_data->credentials.x509_credentials.x509certificate);
|
---|
| 1001 | }
|
---|
| 1002 | upload_data->credentials.x509_credentials.x509certificate = temp;
|
---|
| 1003 | result = IOTHUB_CLIENT_OK;
|
---|
| 1004 | }
|
---|
| 1005 | }
|
---|
| 1006 | }
|
---|
| 1007 | /*Codes_SRS_IOTHUBCLIENT_LL_02_101: [ x509privatekey - then value is a null terminated string that contains the x509 privatekey. ]*/
|
---|
| 1008 | else if (strcmp(optionName, OPTION_X509_PRIVATE_KEY) == 0)
|
---|
| 1009 | {
|
---|
| 1010 | /*Codes_SRS_IOTHUBCLIENT_LL_02_109: [ If the authentication scheme is NOT x509 then IoTHubClient_LL_UploadToBlob_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
|
---|
| 1011 | if (upload_data->cred_type != IOTHUB_CREDENTIAL_TYPE_X509)
|
---|
| 1012 | {
|
---|
| 1013 | LogError("trying to set a x509 privatekey while the authentication scheme is not x509");
|
---|
| 1014 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
| 1015 | }
|
---|
| 1016 | else
|
---|
| 1017 | {
|
---|
| 1018 | /*Codes_SRS_IOTHUBCLIENT_LL_02_103: [ The options shall be saved. ]*/
|
---|
| 1019 | /*try to make a copy of the privatekey*/
|
---|
| 1020 | char* temp;
|
---|
| 1021 | if (mallocAndStrcpy_s(&temp, value) != 0)
|
---|
| 1022 | {
|
---|
| 1023 | /*Codes_SRS_IOTHUBCLIENT_LL_02_104: [ If saving fails, then IoTHubClient_LL_UploadToBlob_SetOption shall fail and return IOTHUB_CLIENT_ERROR. ]*/
|
---|
| 1024 | LogError("unable to mallocAndStrcpy_s");
|
---|
| 1025 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 1026 | }
|
---|
| 1027 | else
|
---|
| 1028 | {
|
---|
| 1029 | /*Codes_SRS_IOTHUBCLIENT_LL_02_105: [ Otherwise IoTHubClient_LL_UploadToBlob_SetOption shall succeed and return IOTHUB_CLIENT_OK. ]*/
|
---|
| 1030 | if (upload_data->credentials.x509_credentials.x509privatekey != NULL) /*free any previous values, if any*/
|
---|
| 1031 | {
|
---|
| 1032 | free(upload_data->credentials.x509_credentials.x509privatekey);
|
---|
| 1033 | }
|
---|
| 1034 | upload_data->credentials.x509_credentials.x509privatekey = temp;
|
---|
| 1035 | result = IOTHUB_CLIENT_OK;
|
---|
| 1036 | }
|
---|
| 1037 | }
|
---|
| 1038 | }
|
---|
| 1039 | else if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0)
|
---|
| 1040 | {
|
---|
| 1041 | if (value == NULL)
|
---|
| 1042 | {
|
---|
| 1043 | LogError("NULL is a not a valid value for TrustedCerts");
|
---|
| 1044 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
| 1045 | }
|
---|
| 1046 | else
|
---|
| 1047 | {
|
---|
| 1048 | char* tempCopy;
|
---|
| 1049 | if (mallocAndStrcpy_s(&tempCopy, value) != 0)
|
---|
| 1050 | {
|
---|
| 1051 | LogError("failure in mallocAndStrcpy_s");
|
---|
| 1052 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 1053 | }
|
---|
| 1054 | else
|
---|
| 1055 | {
|
---|
| 1056 | if (upload_data->certificates != NULL)
|
---|
| 1057 | {
|
---|
| 1058 | free(upload_data->certificates);
|
---|
| 1059 | }
|
---|
| 1060 | upload_data->certificates = tempCopy;
|
---|
| 1061 | result = IOTHUB_CLIENT_OK;
|
---|
| 1062 | }
|
---|
| 1063 | }
|
---|
| 1064 | }
|
---|
| 1065 | /*Codes_SRS_IOTHUBCLIENT_LL_32_008: [ OPTION_HTTP_PROXY - then the value will be a pointer to HTTP_PROXY_OPTIONS structure. ]*/
|
---|
| 1066 | else if (strcmp(optionName, OPTION_HTTP_PROXY) == 0)
|
---|
| 1067 | {
|
---|
| 1068 | HTTP_PROXY_OPTIONS* proxy_options = (HTTP_PROXY_OPTIONS *)value;
|
---|
| 1069 |
|
---|
| 1070 | if (proxy_options->host_address == NULL)
|
---|
| 1071 | {
|
---|
| 1072 | /* Codes_SRS_IOTHUBCLIENT_LL_32_006: [ If `host_address` is NULL, `IoTHubClient_LL_UploadToBlob_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
|
---|
| 1073 | LogError("NULL host_address in proxy options");
|
---|
| 1074 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
| 1075 | }
|
---|
| 1076 | /* Codes_SRS_IOTHUBCLIENT_LL_32_007: [ If only one of `username` and `password` is NULL, `IoTHubClient_LL_UploadToBlob_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
|
---|
| 1077 | else if (((proxy_options->username == NULL) || (proxy_options->password == NULL)) &&
|
---|
| 1078 | (proxy_options->username != proxy_options->password))
|
---|
| 1079 | {
|
---|
| 1080 | LogError("Only one of username and password for proxy settings was NULL");
|
---|
| 1081 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
| 1082 | }
|
---|
| 1083 | else
|
---|
| 1084 | {
|
---|
| 1085 | if (upload_data->http_proxy_options.host_address != NULL)
|
---|
| 1086 | {
|
---|
| 1087 | free((char *)upload_data->http_proxy_options.host_address);
|
---|
| 1088 | upload_data->http_proxy_options.host_address = NULL;
|
---|
| 1089 | }
|
---|
| 1090 | if (upload_data->http_proxy_options.username != NULL)
|
---|
| 1091 | {
|
---|
| 1092 | free((char *)upload_data->http_proxy_options.username);
|
---|
| 1093 | upload_data->http_proxy_options.username = NULL;
|
---|
| 1094 | }
|
---|
| 1095 | if (upload_data->http_proxy_options.password != NULL)
|
---|
| 1096 | {
|
---|
| 1097 | free((char *)upload_data->http_proxy_options.password);
|
---|
| 1098 | upload_data->http_proxy_options.password = NULL;
|
---|
| 1099 | }
|
---|
| 1100 |
|
---|
| 1101 | upload_data->http_proxy_options.port = proxy_options->port;
|
---|
| 1102 |
|
---|
| 1103 | if (mallocAndStrcpy_s((char **)(&upload_data->http_proxy_options.host_address), proxy_options->host_address) != 0)
|
---|
| 1104 | {
|
---|
| 1105 | LogError("failure in mallocAndStrcpy_s - upload_data->http_proxy_options.host_address");
|
---|
| 1106 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 1107 | }
|
---|
| 1108 | else if (proxy_options->username != NULL && mallocAndStrcpy_s((char **)(&upload_data->http_proxy_options.username), proxy_options->username) != 0)
|
---|
| 1109 | {
|
---|
| 1110 | LogError("failure in mallocAndStrcpy_s - upload_data->http_proxy_options.username");
|
---|
| 1111 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 1112 | }
|
---|
| 1113 | else if (proxy_options->password != NULL && mallocAndStrcpy_s((char **)(&upload_data->http_proxy_options.password), proxy_options->password) != 0)
|
---|
| 1114 | {
|
---|
| 1115 | LogError("failure in mallocAndStrcpy_s - upload_data->http_proxy_options.password");
|
---|
| 1116 | result = IOTHUB_CLIENT_ERROR;
|
---|
| 1117 | }
|
---|
| 1118 | else
|
---|
| 1119 | {
|
---|
| 1120 | result = IOTHUB_CLIENT_OK;
|
---|
| 1121 | }
|
---|
| 1122 | }
|
---|
| 1123 | }
|
---|
| 1124 | else if (strcmp(optionName, OPTION_CURL_VERBOSE) == 0)
|
---|
| 1125 | {
|
---|
| 1126 | upload_data->curl_verbosity_level = ((*(bool*)value) == 0) ? UPOADTOBLOB_CURL_VERBOSITY_OFF : UPOADTOBLOB_CURL_VERBOSITY_ON;
|
---|
| 1127 | result = IOTHUB_CLIENT_OK;
|
---|
| 1128 | }
|
---|
| 1129 | else if (strcmp(optionName, OPTION_BLOB_UPLOAD_TIMEOUT_SECS) == 0)
|
---|
| 1130 | {
|
---|
| 1131 | upload_data->blob_upload_timeout_secs = *(size_t*)value;
|
---|
| 1132 | result = IOTHUB_CLIENT_OK;
|
---|
| 1133 | }
|
---|
| 1134 | else
|
---|
| 1135 | {
|
---|
| 1136 | /*Codes_SRS_IOTHUBCLIENT_LL_02_102: [ If an unknown option is presented then IoTHubClient_LL_UploadToBlob_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
|
---|
| 1137 | result = IOTHUB_CLIENT_INVALID_ARG;
|
---|
| 1138 | }
|
---|
| 1139 | }
|
---|
| 1140 | return result;
|
---|
| 1141 | }
|
---|
| 1142 |
|
---|
| 1143 | #endif /*DONT_USE_UPLOADTOBLOB*/
|
---|
| 1144 |
|
---|
| 1145 |
|
---|