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
Diff: iothub_client.c
- Revision:
- 62:5a4cdacf5090
- Parent:
- 61:8b85a4e797cf
- Child:
- 66:a419827cb051
diff -r 8b85a4e797cf -r 5a4cdacf5090 iothub_client.c --- a/iothub_client.c Fri Mar 10 11:47:36 2017 -0800 +++ b/iothub_client.c Fri Mar 24 16:35:32 2017 -0700 @@ -37,11 +37,13 @@ IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK event_confirm_callback; IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reported_state_callback; IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK connection_status_callback; - IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK device_method_callback; + IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC device_method_callback; + IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK inbound_device_method_callback; IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC message_callback; struct IOTHUB_QUEUE_CONTEXT_TAG* devicetwin_user_context; struct IOTHUB_QUEUE_CONTEXT_TAG* connection_status_user_context; struct IOTHUB_QUEUE_CONTEXT_TAG* message_user_context; + struct IOTHUB_QUEUE_CONTEXT_TAG* method_user_context; } IOTHUB_CLIENT_INSTANCE; #ifndef DONT_USE_UPLOADTOBLOB @@ -59,12 +61,13 @@ }UPLOADTOBLOB_SAVED_DATA; #endif -#define USER_CALLBACK_TYPE_VALUES \ - CALLBACK_TYPE_DEVICE_TWIN, \ - CALLBACK_TYPE_EVENT_CONFIRM, \ - CALLBACK_TYPE_REPORTED_STATE, \ - CALLBACK_TYPE_CONNECTION_STATUS, \ - CALLBACK_TYPE_DEVICE_METHOD, \ +#define USER_CALLBACK_TYPE_VALUES \ + CALLBACK_TYPE_DEVICE_TWIN, \ + CALLBACK_TYPE_EVENT_CONFIRM, \ + CALLBACK_TYPE_REPORTED_STATE, \ + CALLBACK_TYPE_CONNECTION_STATUS, \ + CALLBACK_TYPE_DEVICE_METHOD, \ + CALLBACK_TYPE_INBOUD_DEVICE_METHOD, \ CALLBACK_TYPE_MESSAGE DEFINE_ENUM(USER_CALLBACK_TYPE, USER_CALLBACK_TYPE_VALUES) @@ -201,52 +204,95 @@ return result; } -static int iothub_ll_inbound_device_method_callback(const char* method_name, const unsigned char* payload, size_t size, METHOD_HANDLE method_id, void* userContextCallback) +static int make_method_calback_queue_context(USER_CALLBACK_INFO* queue_cb_info, const char* method_name, const unsigned char* payload, size_t size, METHOD_HANDLE method_id, IOTHUB_QUEUE_CONTEXT* queue_context) { int result; - IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)userContextCallback; - /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_001: [ if userContextCallback is NULL, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a nonNULL value. ] */ - if (queue_context != NULL) + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [ IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall copy the method_name and payload. ] */ + queue_cb_info->userContextCallback = queue_context->userContextCallback; + queue_cb_info->iothub_callback.method_cb_info.method_id = method_id; + if ((queue_cb_info->iothub_callback.method_cb_info.method_name = STRING_construct(method_name)) == NULL) { - /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [ IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall copy the method_name and payload. ] */ - USER_CALLBACK_INFO queue_cb_info; - queue_cb_info.type = CALLBACK_TYPE_DEVICE_METHOD; - queue_cb_info.userContextCallback = queue_context->userContextCallback; - queue_cb_info.iothub_callback.method_cb_info.method_id = method_id; - if ( (queue_cb_info.iothub_callback.method_cb_info.method_name = STRING_construct(method_name)) == NULL) + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [ If a failure is encountered IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a non-NULL value. ]*/ + LogError("STRING_construct failed"); + result = __FAILURE__; + } + else + { + if ((queue_cb_info->iothub_callback.method_cb_info.payload = BUFFER_create(payload, size)) == NULL) { + STRING_delete(queue_cb_info->iothub_callback.method_cb_info.method_name); /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [ If a failure is encountered IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a non-NULL value. ]*/ - LogError("Failure: STRING_construct"); - result = __FAILURE__; - } - else if ((queue_cb_info.iothub_callback.method_cb_info.payload = BUFFER_create(payload, size)) == NULL) - { - STRING_delete(queue_cb_info.iothub_callback.method_cb_info.method_name); - /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [ If a failure is encountered IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a non-NULL value. ]*/ - LogError("Failure: BUFFER_create"); - result = __FAILURE__; - } - else if (VECTOR_push_back(queue_context->iotHubClientHandle->saved_user_callback_list, &queue_cb_info, 1) != 0) - { - STRING_delete(queue_cb_info.iothub_callback.method_cb_info.method_name); - BUFFER_delete(queue_cb_info.iothub_callback.method_cb_info.payload); - /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [ If a failure is encountered IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a non-NULL value. ]*/ - LogError("connection status callback vector push failed."); + LogError("BUFFER_create failed"); result = __FAILURE__; } else { - /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_004: [ On success IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a 0 value. ]*/ - result = 0; + if (VECTOR_push_back(queue_context->iotHubClientHandle->saved_user_callback_list, queue_cb_info, 1) == 0) + { + result = 0; + } + else + { + STRING_delete(queue_cb_info->iothub_callback.method_cb_info.method_name); + BUFFER_delete(queue_cb_info->iothub_callback.method_cb_info.payload); + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [ If a failure is encountered IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a non-NULL value. ]*/ + LogError("VECTOR_push_back failed"); + result = __FAILURE__; + } } - free(queue_context); + } + return result; +} + +static int iothub_ll_device_method_callback(const char* method_name, const unsigned char* payload, size_t size, METHOD_HANDLE method_id, void* userContextCallback) +{ + int result; + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_001: [ if userContextCallback is NULL, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a nonNULL value. ] */ + if (userContextCallback == NULL) + { + LogError("invalid parameter userContextCallback(NULL)"); + result = __FAILURE__; } else { - /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [ If a failure is encountered IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a non-NULL value. ]*/ - LogError("Invalid parameter: userContextCallback NULL"); + IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)userContextCallback; + + USER_CALLBACK_INFO queue_cb_info; + queue_cb_info.type = CALLBACK_TYPE_DEVICE_METHOD; + + result = make_method_calback_queue_context(&queue_cb_info, method_name, payload, size, method_id, queue_context); + if (result != 0) + { + LogError("construction of method calback queue context failed"); + result = __FAILURE__; + } + } + return result; +} + +static int iothub_ll_inbound_device_method_callback(const char* method_name, const unsigned char* payload, size_t size, METHOD_HANDLE method_id, void* userContextCallback) +{ + int result; + /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_001: [ if userContextCallback is NULL, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK shall return a nonNULL value. ] */ + if (userContextCallback == NULL) + { + LogError("invalid parameter userContextCallback(NULL)"); result = __FAILURE__; } + else + { + IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)userContextCallback; + + USER_CALLBACK_INFO queue_cb_info; + queue_cb_info.type = CALLBACK_TYPE_INBOUD_DEVICE_METHOD; + + result = make_method_calback_queue_context(&queue_cb_info, method_name, payload, size, method_id, queue_context); + if (result != 0) + { + LogError("construction of method calback queue context failed"); + result = __FAILURE__; + } + } return result; } @@ -401,7 +447,38 @@ const char* method_name = STRING_c_str(queued_cb->iothub_callback.method_cb_info.method_name); const unsigned char* payload = BUFFER_u_char(queued_cb->iothub_callback.method_cb_info.payload); size_t payload_len = BUFFER_length(queued_cb->iothub_callback.method_cb_info.payload); - iotHubClientInstance->device_method_callback(method_name, payload, payload_len, queued_cb->iothub_callback.method_cb_info.method_id, queued_cb->userContextCallback); + + unsigned char* payload_resp = NULL; + size_t response_size = 0; + int status = iotHubClientInstance->device_method_callback(method_name, payload, payload_len, &payload_resp, &response_size, queued_cb->userContextCallback); + + if (payload_resp && (response_size > 0)) + { + IOTHUB_CLIENT_HANDLE handle = iotHubClientInstance->method_user_context->iotHubClientHandle; + IOTHUB_CLIENT_RESULT result = IoTHubClient_DeviceMethodResponse(handle, queued_cb->iothub_callback.method_cb_info.method_id, (const unsigned char*)payload_resp, response_size, status); + if (result != IOTHUB_CLIENT_OK) + { + LogError("IoTHubClient_LL_DeviceMethodResponse failed"); + } + } + + BUFFER_delete(queued_cb->iothub_callback.method_cb_info.payload); + STRING_delete(queued_cb->iothub_callback.method_cb_info.method_name); + + if (payload_resp) + { + free(payload_resp); + } + } + break; + case CALLBACK_TYPE_INBOUD_DEVICE_METHOD: + if (iotHubClientInstance->inbound_device_method_callback) + { + const char* method_name = STRING_c_str(queued_cb->iothub_callback.method_cb_info.method_name); + const unsigned char* payload = BUFFER_u_char(queued_cb->iothub_callback.method_cb_info.payload); + size_t payload_len = BUFFER_length(queued_cb->iothub_callback.method_cb_info.payload); + + iotHubClientInstance->inbound_device_method_callback(method_name, payload, payload_len, queued_cb->iothub_callback.method_cb_info.method_id, queued_cb->userContextCallback); BUFFER_delete(queued_cb->iothub_callback.method_cb_info.payload); STRING_delete(queued_cb->iothub_callback.method_cb_info.method_name); @@ -416,11 +493,11 @@ if (Lock(handle->LockHandle) == LOCK_OK) { IOTHUB_CLIENT_RESULT result = IoTHubClient_LL_SendMessageDisposition(handle->IoTHubClientLLHandle, queued_cb->iothub_callback.message_cb_info, disposition); + (void)Unlock(handle->LockHandle); if (result != IOTHUB_CLIENT_OK) { - LogError("IoTHubClient_LL_Send_Message_Disposition failed"); + LogError("IoTHubClient_LL_SendMessageDisposition failed"); } - (void)Unlock(handle->LockHandle); } else { @@ -656,6 +733,7 @@ result->connection_status_user_context = NULL; result->message_callback = NULL; result->message_user_context = NULL; + result->method_user_context = NULL; } } } @@ -724,7 +802,7 @@ if (iotHubClientHandle != NULL) { bool okToJoin; - size_t vector_size; + size_t vector_size; IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; @@ -800,7 +878,7 @@ USER_CALLBACK_INFO* queue_cb_info = (USER_CALLBACK_INFO*)VECTOR_element(iotHubClientInstance->saved_user_callback_list, index); if (queue_cb_info != NULL) { - if (queue_cb_info->type == CALLBACK_TYPE_DEVICE_METHOD) + if ((queue_cb_info->type == CALLBACK_TYPE_DEVICE_METHOD) || (queue_cb_info->type == CALLBACK_TYPE_INBOUD_DEVICE_METHOD)) { STRING_delete(queue_cb_info->iothub_callback.method_cb_info.method_name); BUFFER_delete(queue_cb_info->iothub_callback.method_cb_info.payload); @@ -840,6 +918,10 @@ { free(iotHubClientInstance->message_user_context); } + if (iotHubClientInstance->method_user_context != NULL) + { + free(iotHubClientInstance->method_user_context); + } free(iotHubClientInstance); } } @@ -992,10 +1074,11 @@ if (iotHubClientInstance->message_user_context != NULL) { free(iotHubClientInstance->message_user_context); + iotHubClientInstance->message_user_context = NULL; } if (messageCallback == NULL) { - result = IoTHubClient_LL_SetMessageCallbackEx(iotHubClientInstance->IoTHubClientLLHandle, NULL, iotHubClientInstance->message_user_context); + result = IoTHubClient_LL_SetMessageCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, NULL, iotHubClientInstance->message_user_context); } else if (iotHubClientInstance->created_with_transport_handle != 0) { @@ -1014,9 +1097,9 @@ iotHubClientInstance->message_user_context->iotHubClientHandle = iotHubClientHandle; iotHubClientInstance->message_user_context->userContextCallback = userContextCallback; - /* Codes_SRS_IOTHUBCLIENT_01_017: [IoTHubClient_SetMessageCallback shall call IoTHubClient_LL_SetMessageCallbackEx, while passing the IoTHubClient_LL handle created by IoTHubClient_Create and the local iothub_ll_message_callback wrapper of messageCallback and userContextCallback.] */ - /* Codes_SRS_IOTHUBCLIENT_01_018: [When IoTHubClient_LL_SetMessageCallbackEx is called, IoTHubClient_SetMessageCallback shall return the result of IoTHubClient_LL_SetMessageCallbackEx.] */ - result = IoTHubClient_LL_SetMessageCallbackEx(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_message_callback, iotHubClientInstance->message_user_context); + /* Codes_SRS_IOTHUBCLIENT_01_017: [IoTHubClient_SetMessageCallback shall call IoTHubClient_LL_SetMessageCallback_Ex, while passing the IoTHubClient_LL handle created by IoTHubClient_Create and the local iothub_ll_message_callback wrapper of messageCallback and userContextCallback.] */ + /* Codes_SRS_IOTHUBCLIENT_01_018: [When IoTHubClient_LL_SetMessageCallback_Ex is called, IoTHubClient_SetMessageCallback shall return the result of IoTHubClient_LL_SetMessageCallback_Ex.] */ + result = IoTHubClient_LL_SetMessageCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_message_callback, iotHubClientInstance->message_user_context); if (result != IOTHUB_CLIENT_OK) { LogError("IoTHubClient_LL_SetMessageCallback failed"); @@ -1443,6 +1526,10 @@ } else { + if (iotHubClientInstance->created_with_transport_handle == 0) + { + iotHubClientInstance->device_method_callback = deviceMethodCallback; + } /*Codes_SRS_IOTHUBCLIENT_12_014: [ If the transport handle is null and the worker thread is not initialized, the thread shall be started by calling IoTHubTransport_StartWorkerThread. ]*/ if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) { @@ -1452,12 +1539,38 @@ } else { - /*Codes_SRS_IOTHUBCLIENT_12_016: [ IoTHubClient_SetDeviceMethodCallback shall call IoTHubClient_LL_SetDeviceMethodCallback, while passing the IoTHubClient_LL_handle created by IoTHubClient_LL_Create along with the parameters deviceMethodCallback and userContextCallback. ]*/ - /*Codes_SRS_IOTHUBCLIENT_12_017: [ When IoTHubClient_LL_SetDeviceMethodCallback is called, IoTHubClient_SetDeviceMethodCallback shall return the result of IoTHubClient_LL_SetDeviceMethodCallback. ]*/ - result = IoTHubClient_LL_SetDeviceMethodCallback(iotHubClientInstance->IoTHubClientLLHandle, deviceMethodCallback, userContextCallback); - if (result != IOTHUB_CLIENT_OK) + if (iotHubClientInstance->method_user_context) + { + free(iotHubClientInstance->method_user_context); + iotHubClientInstance->method_user_context = NULL; + } + if (deviceMethodCallback == NULL) + { + result = IoTHubClient_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, NULL, NULL); + } + else { - LogError("IoTHubClient_LL_SetDeviceMethodCallback failed"); + iotHubClientInstance->method_user_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT)); + if (iotHubClientInstance->method_user_context == NULL) + { + result = IOTHUB_CLIENT_ERROR; + LogError("Failed allocating QUEUE_CONTEXT"); + } + else + { + iotHubClientInstance->method_user_context->iotHubClientHandle = iotHubClientHandle; + iotHubClientInstance->method_user_context->userContextCallback = userContextCallback; + + /*Codes_SRS_IOTHUBCLIENT_12_016: [ IoTHubClient_SetDeviceMethodCallback shall call IoTHubClient_LL_SetDeviceMethodCallback, while passing the IoTHubClient_LL_handle created by IoTHubClient_LL_Create along with the parameters deviceMethodCallback and userContextCallback. ]*/ + /*Codes_SRS_IOTHUBCLIENT_12_017: [ When IoTHubClient_LL_SetDeviceMethodCallback is called, IoTHubClient_SetDeviceMethodCallback shall return the result of IoTHubClient_LL_SetDeviceMethodCallback. ]*/ + result = IoTHubClient_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_device_method_callback, iotHubClientInstance->method_user_context); + if (result != IOTHUB_CLIENT_OK) + { + LogError("IoTHubClient_LL_SetDeviceMethodCallback_Ex failed"); + free(iotHubClientInstance->method_user_context); + iotHubClientInstance->method_user_context = NULL; + } + } } } @@ -1492,7 +1605,7 @@ { if (iotHubClientInstance->created_with_transport_handle == 0) { - iotHubClientInstance->device_method_callback = inboundDeviceMethodCallback; + iotHubClientInstance->inbound_device_method_callback = inboundDeviceMethodCallback; } /*Codes_SRS_IOTHUBCLIENT_07_003: [ If the transport handle is NULL and the worker thread is not initialized, the thread shall be started by calling IoTHubTransport_StartWorkerThread. ]*/ if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) @@ -1503,15 +1616,20 @@ } else { - if (iotHubClientInstance->created_with_transport_handle != 0 || inboundDeviceMethodCallback == NULL) + if (iotHubClientInstance->method_user_context) + { + free(iotHubClientInstance->method_user_context); + iotHubClientInstance->method_user_context = NULL; + } + if (inboundDeviceMethodCallback == NULL) { /* Codes_SRS_IOTHUBCLIENT_07_008: [ If inboundDeviceMethodCallback is NULL, IoTHubClient_SetDeviceMethodCallback_Ex shall call IoTHubClient_LL_SetDeviceMethodCallback_Ex, passing NULL for the iothub_ll_inbound_device_method_callback. ] */ result = IoTHubClient_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, NULL, NULL); } else { - IOTHUB_QUEUE_CONTEXT* queue_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT)); - if (queue_context == NULL) + iotHubClientInstance->method_user_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT)); + if (iotHubClientInstance->method_user_context == NULL) { result = IOTHUB_CLIENT_ERROR; LogError("Failed allocating QUEUE_CONTEXT"); @@ -1519,14 +1637,16 @@ else { /*Codes_SRS_IOTHUBCLIENT_07_005: [ IoTHubClient_SetDeviceMethodCallback_Ex shall call IoTHubClient_LL_SetDeviceMethodCallback_Ex, while passing the IoTHubClient_LL_handle created by IoTHubClient_LL_Create along with the parameters iothub_ll_inbound_device_method_callback and IOTHUB_QUEUE_CONTEXT. ]*/ - queue_context->iotHubClientHandle = iotHubClientInstance; - queue_context->userContextCallback = userContextCallback; + iotHubClientInstance->method_user_context->iotHubClientHandle = iotHubClientHandle; + iotHubClientInstance->method_user_context->userContextCallback = userContextCallback; + /* Codes_SRS_IOTHUBCLIENT_07_006: [ When IoTHubClient_LL_SetDeviceMethodCallback_Ex is called, IoTHubClient_SetDeviceMethodCallback_Ex shall return the result of IoTHubClient_LL_SetDeviceMethodCallback_Ex. ] */ - result = IoTHubClient_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_inbound_device_method_callback, queue_context); + result = IoTHubClient_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_inbound_device_method_callback, iotHubClientInstance->method_user_context); if (result != IOTHUB_CLIENT_OK) { - LogError("IoTHubClient_LL_SetDeviceMethodCallback failed"); - free(queue_context); + LogError("IoTHubClient_LL_SetDeviceMethodCallback_Ex failed"); + free(iotHubClientInstance->method_user_context); + iotHubClientInstance->method_user_context = NULL; } } } @@ -1577,26 +1697,32 @@ { UPLOADTOBLOB_SAVED_DATA* savedData = (UPLOADTOBLOB_SAVED_DATA*)data; - /*it so happens that IoTHubClient_LL_UploadToBlob is thread-safe because there's no saved state in the handle and there are no globals, so no need to protect it*/ - /*not having it protected means multiple simultaneous uploads can happen*/ - /*Codes_SRS_IOTHUBCLIENT_02_054: [ The thread shall call IoTHubClient_LL_UploadToBlob passing the information packed in the structure. ]*/ - if (IoTHubClient_LL_UploadToBlob(savedData->iotHubClientHandle->IoTHubClientLLHandle, savedData->destinationFileName, savedData->source, savedData->size) != IOTHUB_CLIENT_OK) + if (Lock(savedData->iotHubClientHandle->LockHandle) == LOCK_OK) { - LogError("unable to IoTHubClient_LL_UploadToBlob"); - /*call the callback*/ + IOTHUB_CLIENT_FILE_UPLOAD_RESULT upload_result; + /*it so happens that IoTHubClient_LL_UploadToBlob is thread-safe because there's no saved state in the handle and there are no globals, so no need to protect it*/ + /*not having it protected means multiple simultaneous uploads can happen*/ + /*Codes_SRS_IOTHUBCLIENT_02_054: [ The thread shall call IoTHubClient_LL_UploadToBlob passing the information packed in the structure. ]*/ + if (IoTHubClient_LL_UploadToBlob(savedData->iotHubClientHandle->IoTHubClientLLHandle, savedData->destinationFileName, savedData->source, savedData->size) == IOTHUB_CLIENT_OK) + { + upload_result = FILE_UPLOAD_OK; + } + else + { + LogError("unable to IoTHubClient_LL_UploadToBlob"); + upload_result = FILE_UPLOAD_ERROR; + } + (void)Unlock(savedData->iotHubClientHandle->LockHandle); + if (savedData->iotHubClientFileUploadCallback != NULL) { /*Codes_SRS_IOTHUBCLIENT_02_055: [ If IoTHubClient_LL_UploadToBlob fails then the thread shall call iotHubClientFileUploadCallbackInternal passing as result FILE_UPLOAD_ERROR and as context the structure from SRS IOTHUBCLIENT 02 051. ]*/ - savedData->iotHubClientFileUploadCallback(FILE_UPLOAD_ERROR, savedData->context); + savedData->iotHubClientFileUploadCallback(upload_result, savedData->context); } } else { - if (savedData->iotHubClientFileUploadCallback != NULL) - { - /*Codes_SRS_IOTHUBCLIENT_02_056: [ Otherwise the thread iotHubClientFileUploadCallbackInternal passing as result FILE_UPLOAD_OK and the structure from SRS IOTHUBCLIENT 02 051. ]*/ - savedData->iotHubClientFileUploadCallback(FILE_UPLOAD_OK, savedData->context); - } + LogError("Lock failed"); } /*Codes_SRS_IOTHUBCLIENT_02_071: [ The thread shall mark itself as disposable. ]*/