corrected version (with typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE;) included in the sources
Dependents: STM32F746_iothub_client_sample_mqtt
Fork of iothub_client by
iothub_client.c
00001 // Copyright (c) Microsoft. All rights reserved. 00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 00003 00004 #include <stdlib.h> 00005 #ifdef _CRTDBG_MAP_ALLOC 00006 #include <crtdbg.h> 00007 #endif 00008 #include "azure_c_shared_utility/gballoc.h" 00009 00010 #include <stdlib.h> 00011 #include <signal.h> 00012 #include <stddef.h> 00013 #include "azure_c_shared_utility/crt_abstractions.h" 00014 #include "iothub_client.h" 00015 #include "iothub_client_ll.h" 00016 #include "iothubtransport.h" 00017 #include "azure_c_shared_utility/threadapi.h" 00018 #include "azure_c_shared_utility/lock.h" 00019 #include "azure_c_shared_utility/iot_logging.h" 00020 #include "azure_c_shared_utility/list.h" 00021 00022 typedef struct IOTHUB_CLIENT_INSTANCE_TAG 00023 { 00024 IOTHUB_CLIENT_LL_HANDLE IoTHubClientLLHandle; 00025 TRANSPORT_HANDLE TransportHandle; 00026 THREAD_HANDLE ThreadHandle; 00027 LOCK_HANDLE LockHandle; 00028 sig_atomic_t StopThread; 00029 #ifdef USE_UPLOADTOBLOB 00030 LIST_HANDLE savedDataToBeCleaned; /*list containing UPLOADTOBLOB_SAVED_DATA*/ 00031 #endif 00032 } IOTHUB_CLIENT_INSTANCE; 00033 00034 #ifdef USE_UPLOADTOBLOB 00035 typedef struct UPLOADTOBLOB_SAVED_DATA_TAG 00036 { 00037 unsigned char* source; 00038 size_t size; 00039 char* destinationFileName; 00040 IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback; 00041 void* context; 00042 THREAD_HANDLE uploadingThreadHandle; 00043 IOTHUB_CLIENT_HANDLE iotHubClientHandle; 00044 LOCK_HANDLE lockGarbage; 00045 int canBeGarbageCollected; /*flag indicating that the UPLOADTOBLOB_SAVED_DATA structure can be freed because the thread deadling with it finished*/ 00046 }UPLOADTOBLOB_SAVED_DATA; 00047 #endif 00048 00049 /*used by unittests only*/ 00050 const size_t IoTHubClient_ThreadTerminationOffset = offsetof(IOTHUB_CLIENT_INSTANCE, StopThread); 00051 00052 #ifdef USE_UPLOADTOBLOB 00053 /*this function is called from _Destroy and from ScheduleWork_Thread to join finished blobUpload threads and free that memory*/ 00054 static void garbageCollectorImpl(IOTHUB_CLIENT_INSTANCE* iotHubClientInstance) 00055 { 00056 /*see if any savedData structures can be disposed of*/ 00057 /*Codes_SRS_IOTHUBCLIENT_02_072: [ All threads marked as disposable (upon completion of a file upload) shall be joined and the data structures build for them shall be freed. ]*/ 00058 LIST_ITEM_HANDLE item = list_get_head_item(iotHubClientInstance->savedDataToBeCleaned); 00059 while (item != NULL) 00060 { 00061 const UPLOADTOBLOB_SAVED_DATA* savedData = (const UPLOADTOBLOB_SAVED_DATA*)list_item_get_value(item); 00062 LIST_ITEM_HANDLE old_item = item; 00063 item = list_get_next_item(item); 00064 00065 if (Lock(savedData->lockGarbage) != LOCK_OK) 00066 { 00067 LogError("unable to Lock"); 00068 } 00069 else 00070 { 00071 if (savedData->canBeGarbageCollected == 1) 00072 { 00073 int notUsed; 00074 if (ThreadAPI_Join(savedData->uploadingThreadHandle, ¬Used) != THREADAPI_OK) 00075 { 00076 LogError("unable to ThreadAPI_Join"); 00077 } 00078 (void)list_remove(iotHubClientInstance->savedDataToBeCleaned, old_item); 00079 free((void*)savedData->source); 00080 free((void*)savedData->destinationFileName); 00081 00082 if (Unlock(savedData->lockGarbage) != LOCK_OK) 00083 { 00084 LogError("unable to unlock after locking"); 00085 } 00086 (void)Lock_Deinit(savedData->lockGarbage); 00087 free((void*)savedData); 00088 } 00089 else 00090 { 00091 if (Unlock(savedData->lockGarbage) != LOCK_OK) 00092 { 00093 LogError("unable to unlock after locking"); 00094 } 00095 } 00096 } 00097 } 00098 } 00099 #endif 00100 00101 static int ScheduleWork_Thread(void* threadArgument) 00102 { 00103 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)threadArgument; 00104 00105 while (1) 00106 { 00107 if (Lock(iotHubClientInstance->LockHandle) == LOCK_OK) 00108 { 00109 /*Codes_SRS_IOTHUBCLIENT_01_038: [ The thread shall exit when IoTHubClient_Destroy is called. ]*/ 00110 if (iotHubClientInstance->StopThread) 00111 { 00112 (void)Unlock(iotHubClientInstance->LockHandle); 00113 break; /*gets out of the thread*/ 00114 } 00115 else 00116 { 00117 /* Codes_SRS_IOTHUBCLIENT_01_037: [The thread created by IoTHubClient_SendEvent or IoTHubClient_SetMessageCallback shall call IoTHubClient_LL_DoWork every 1 ms.] */ 00118 /* Codes_SRS_IOTHUBCLIENT_01_039: [All calls to IoTHubClient_LL_DoWork shall be protected by the lock created in IotHubClient_Create.] */ 00119 IoTHubClient_LL_DoWork(iotHubClientInstance->IoTHubClientLLHandle); 00120 00121 #ifdef USE_UPLOADTOBLOB 00122 garbageCollectorImpl(iotHubClientInstance); 00123 #endif 00124 (void)Unlock(iotHubClientInstance->LockHandle); 00125 } 00126 } 00127 else 00128 { 00129 /*Codes_SRS_IOTHUBCLIENT_01_040: [If acquiring the lock fails, IoTHubClient_LL_DoWork shall not be called.]*/ 00130 /*no code, shall retry*/ 00131 } 00132 (void)ThreadAPI_Sleep(1); 00133 } 00134 00135 return 0; 00136 } 00137 00138 static IOTHUB_CLIENT_RESULT StartWorkerThreadIfNeeded(IOTHUB_CLIENT_INSTANCE* iotHubClientInstance) 00139 { 00140 IOTHUB_CLIENT_RESULT result; 00141 if (iotHubClientInstance->TransportHandle == NULL) 00142 { 00143 if (iotHubClientInstance->ThreadHandle == NULL) 00144 { 00145 iotHubClientInstance->StopThread = 0; 00146 if (ThreadAPI_Create(&iotHubClientInstance->ThreadHandle, ScheduleWork_Thread, iotHubClientInstance) != THREADAPI_OK) 00147 { 00148 iotHubClientInstance->ThreadHandle = NULL; 00149 result = IOTHUB_CLIENT_ERROR; 00150 } 00151 else 00152 { 00153 result = IOTHUB_CLIENT_OK; 00154 } 00155 } 00156 else 00157 { 00158 result = IOTHUB_CLIENT_OK; 00159 } 00160 } 00161 else 00162 { 00163 /*Codes_SRS_IOTHUBCLIENT_17_012: [ If the transport connection is shared, the thread shall be started by calling IoTHubTransport_StartWorkerThread. ]*/ 00164 /*Codes_SRS_IOTHUBCLIENT_17_011: [ If the transport connection is shared, the thread shall be started by calling IoTHubTransport_StartWorkerThread*/ 00165 00166 result = IoTHubTransport_StartWorkerThread(iotHubClientInstance->TransportHandle, iotHubClientInstance); 00167 } 00168 return result; 00169 } 00170 00171 IOTHUB_CLIENT_HANDLE IoTHubClient_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol) 00172 { 00173 IOTHUB_CLIENT_INSTANCE* result = NULL; 00174 00175 /* Codes_SRS_IOTHUBCLIENT_12_003: [IoTHubClient_CreateFromConnectionString shall verify the input parameter and if it is NULL then return NULL] */ 00176 if (connectionString == NULL) 00177 { 00178 LogError("Input parameter is NULL: connectionString"); 00179 } 00180 else if (protocol == NULL) 00181 { 00182 LogError("Input parameter is NULL: protocol"); 00183 } 00184 else 00185 { 00186 /* Codes_SRS_IOTHUBCLIENT_12_004: [IoTHubClient_CreateFromConnectionString shall allocate a new IoTHubClient instance.] */ 00187 result = malloc(sizeof(IOTHUB_CLIENT_INSTANCE)); 00188 00189 /* Codes_SRS_IOTHUBCLIENT_12_011: [If the allocation failed, IoTHubClient_CreateFromConnectionString returns NULL] */ 00190 if (result == NULL) 00191 { 00192 LogError("Malloc failed"); 00193 } 00194 else 00195 { 00196 /* Codes_SRS_IOTHUBCLIENT_12_005: [IoTHubClient_CreateFromConnectionString shall create a lock object to be used later for serializing IoTHubClient calls] */ 00197 result->LockHandle = Lock_Init(); 00198 if (result->LockHandle == NULL) 00199 { 00200 /* Codes_SRS_IOTHUBCLIENT_12_009: [If lock creation failed, IoTHubClient_CreateFromConnectionString shall do clean up and return NULL] */ 00201 free(result); 00202 result = NULL; 00203 LogError("Lock_Init failed"); 00204 } 00205 else 00206 { 00207 #ifdef USE_UPLOADTOBLOB 00208 /*Codes_SRS_IOTHUBCLIENT_02_059: [ IoTHubClient_CreateFromConnectionString shall create a LIST_HANDLE containing THREAD_HANDLE (created by future calls to IoTHubClient_UploadToBlobAsync). ]*/ 00209 if ((result->savedDataToBeCleaned = list_create()) == NULL) 00210 { 00211 /*Codes_SRS_IOTHUBCLIENT_02_070: [ If creating the LIST_HANDLE fails then IoTHubClient_CreateFromConnectionString shall fail and return NULL]*/ 00212 LogError("unable to list_create"); 00213 Lock_Deinit(result->LockHandle); 00214 free(result); 00215 result = NULL; 00216 } 00217 else 00218 #endif 00219 { 00220 /* Codes_SRS_IOTHUBCLIENT_12_006: [IoTHubClient_CreateFromConnectionString shall instantiate a new IoTHubClient_LL instance by calling IoTHubClient_LL_CreateFromConnectionString and passing the connectionString] */ 00221 result->IoTHubClientLLHandle = IoTHubClient_LL_CreateFromConnectionString(connectionString, protocol); 00222 if (result->IoTHubClientLLHandle == NULL) 00223 { 00224 /* Codes_SRS_IOTHUBCLIENT_12_010: [If IoTHubClient_LL_CreateFromConnectionString fails then IoTHubClient_CreateFromConnectionString shall do clean - up and return NULL] */ 00225 #ifdef USE_UPLOADTOBLOB 00226 list_destroy(result->savedDataToBeCleaned); 00227 #endif 00228 Lock_Deinit(result->LockHandle); 00229 free(result); 00230 result = NULL; 00231 LogError("IoTHubClient_LL_CreateFromConnectionString failed"); 00232 } 00233 else 00234 { 00235 result->ThreadHandle = NULL; 00236 result->TransportHandle = NULL; 00237 } 00238 } 00239 } 00240 00241 } 00242 } 00243 return result; 00244 } 00245 00246 IOTHUB_CLIENT_HANDLE IoTHubClient_Create(const IOTHUB_CLIENT_CONFIG* config) 00247 { 00248 /* Codes_SRS_IOTHUBCLIENT_01_001: [IoTHubClient_Create shall allocate a new IoTHubClient instance and return a non-NULL handle to it.] */ 00249 IOTHUB_CLIENT_INSTANCE* result = (IOTHUB_CLIENT_INSTANCE*)malloc(sizeof(IOTHUB_CLIENT_INSTANCE)); 00250 00251 /* Codes_SRS_IOTHUBCLIENT_01_004: [If allocating memory for the new IoTHubClient instance fails, then IoTHubClient_Create shall return NULL.] */ 00252 if (result != NULL) 00253 { 00254 /* Codes_SRS_IOTHUBCLIENT_01_029: [IoTHubClient_Create shall create a lock object to be used later for serializing IoTHubClient calls.] */ 00255 result->LockHandle = Lock_Init(); 00256 if (result->LockHandle == NULL) 00257 { 00258 /* Codes_SRS_IOTHUBCLIENT_01_030: [If creating the lock fails, then IoTHubClient_Create shall return NULL.] */ 00259 /* Codes_SRS_IOTHUBCLIENT_01_031: [If IoTHubClient_Create fails, all resources allocated by it shall be freed.] */ 00260 free(result); 00261 result = NULL; 00262 } 00263 else 00264 { 00265 #ifdef USE_UPLOADTOBLOB 00266 /*Codes_SRS_IOTHUBCLIENT_02_060: [ IoTHubClient_Create shall create a LIST_HANDLE containing THREAD_HANDLE (created by future calls to IoTHubClient_UploadToBlobAsync). ]*/ 00267 if ((result->savedDataToBeCleaned = list_create()) == NULL) 00268 { 00269 /*Codes_SRS_IOTHUBCLIENT_02_061: [ If creating the LIST_HANDLE fails then IoTHubClient_Create shall fail and return NULL. ]*/ 00270 LogError("unable to list_create"); 00271 Lock_Deinit(result->LockHandle); 00272 free(result); 00273 result = NULL; 00274 } 00275 else 00276 #endif 00277 { 00278 /* Codes_SRS_IOTHUBCLIENT_01_002: [IoTHubClient_Create shall instantiate a new IoTHubClient_LL instance by calling IoTHubClient_LL_Create and passing the config argument.] */ 00279 result->IoTHubClientLLHandle = IoTHubClient_LL_Create(config); 00280 if (result->IoTHubClientLLHandle == NULL) 00281 { 00282 /* Codes_SRS_IOTHUBCLIENT_01_003: [If IoTHubClient_LL_Create fails, then IoTHubClient_Create shall return NULL.] */ 00283 /* Codes_SRS_IOTHUBCLIENT_01_031: [If IoTHubClient_Create fails, all resources allocated by it shall be freed.] */ 00284 Lock_Deinit(result->LockHandle); 00285 #ifdef USE_UPLOADTOBLOB 00286 list_destroy(result->savedDataToBeCleaned); 00287 #endif 00288 free(result); 00289 result = NULL; 00290 } 00291 else 00292 { 00293 result->TransportHandle = NULL; 00294 result->ThreadHandle = NULL; 00295 } 00296 } 00297 } 00298 } 00299 00300 return result; 00301 } 00302 00303 IOTHUB_CLIENT_HANDLE IoTHubClient_CreateWithTransport(TRANSPORT_HANDLE transportHandle, const IOTHUB_CLIENT_CONFIG* config) 00304 { 00305 IOTHUB_CLIENT_INSTANCE* result; 00306 /*Codes_SRS_IOTHUBCLIENT_17_013: [ IoTHubClient_CreateWithTransport shall return NULL if transportHandle is NULL. ]*/ 00307 /*Codes_SRS_IOTHUBCLIENT_17_014: [ IoTHubClient_CreateWithTransport shall return NULL if config is NULL. ]*/ 00308 if (transportHandle == NULL || config == NULL) 00309 { 00310 LogError("invalid parameter TRANSPORT_HANDLE transportHandle=%p, const IOTHUB_CLIENT_CONFIG* config=%p", transportHandle, config); 00311 result = NULL; 00312 } 00313 else 00314 { 00315 /*Codes_SRS_IOTHUBCLIENT_17_001: [ IoTHubClient_CreateWithTransport shall allocate a new IoTHubClient instance and return a non-NULL handle to it. ]*/ 00316 result = (IOTHUB_CLIENT_INSTANCE*)malloc(sizeof(IOTHUB_CLIENT_INSTANCE)); 00317 /*Codes_SRS_IOTHUBCLIENT_17_002: [ If allocating memory for the new IoTHubClient instance fails, then IoTHubClient_CreateWithTransport shall return NULL. ]*/ 00318 if (result == NULL) 00319 { 00320 LogError("unable to malloc"); 00321 /*return as is*/ 00322 } 00323 else 00324 { 00325 #ifdef USE_UPLOADTOBLOB 00326 /*Codes_SRS_IOTHUBCLIENT_02_073: [ IoTHubClient_CreateWithTransport shall create a LIST_HANDLE that shall be used by IoTHubClient_UploadToBlobAsync. ]*/ 00327 if ((result->savedDataToBeCleaned = list_create()) == NULL) 00328 { 00329 /*Codes_SRS_IOTHUBCLIENT_02_074: [ If creating the LIST_HANDLE fails then IoTHubClient_CreateWithTransport shall fail and return NULL. ]*/ 00330 LogError("unable to list_create"); 00331 free(result); 00332 result = NULL; 00333 } 00334 else 00335 #endif 00336 { 00337 result->ThreadHandle = NULL; 00338 result->TransportHandle = transportHandle; 00339 /*Codes_SRS_IOTHUBCLIENT_17_005: [ IoTHubClient_CreateWithTransport shall call IoTHubTransport_GetLock to get the transport lock to be used later for serializing IoTHubClient calls. ]*/ 00340 LOCK_HANDLE transportLock = IoTHubTransport_GetLock(transportHandle); 00341 result->LockHandle = transportLock; 00342 if (result->LockHandle == NULL) 00343 { 00344 LogError("unable to IoTHubTransport_GetLock"); 00345 /*Codes_SRS_IOTHUBCLIENT_17_006: [ If IoTHubTransport_GetLock fails, then IoTHubClient_CreateWithTransport shall return NULL. ]*/ 00346 #ifdef USE_UPLOADTOBLOB 00347 list_destroy(result->savedDataToBeCleaned); 00348 #endif 00349 free(result); 00350 result = NULL; 00351 } 00352 else 00353 { 00354 IOTHUB_CLIENT_DEVICE_CONFIG deviceConfig; 00355 deviceConfig.deviceId = config->deviceId; 00356 deviceConfig.deviceKey = config->deviceKey; 00357 deviceConfig.protocol = config->protocol; 00358 deviceConfig.deviceSasToken = config->deviceSasToken; 00359 deviceConfig.protocol = config->protocol; 00360 00361 /*Codes_SRS_IOTHUBCLIENT_17_003: [ IoTHubClient_CreateWithTransport shall call IoTHubTransport_GetLLTransport on transportHandle to get lower layer transport. ]*/ 00362 deviceConfig.transportHandle = IoTHubTransport_GetLLTransport(transportHandle); 00363 00364 if (deviceConfig.transportHandle == NULL) 00365 { 00366 LogError("unable to IoTHubTransport_GetLLTransport"); 00367 /*Codes_SRS_IOTHUBCLIENT_17_004: [ If IoTHubTransport_GetLLTransport fails, then IoTHubClient_CreateWithTransport shall return NULL. ]*/ 00368 #ifdef USE_UPLOADTOBLOB 00369 list_destroy(result->savedDataToBeCleaned); 00370 #endif 00371 free(result); 00372 result = NULL; 00373 } 00374 else 00375 { 00376 if (Lock(transportLock) != LOCK_OK) 00377 { 00378 LogError("unable to Lock"); 00379 #ifdef USE_UPLOADTOBLOB 00380 list_destroy(result->savedDataToBeCleaned); 00381 #endif 00382 free(result); 00383 result = NULL; 00384 } 00385 else 00386 { 00387 /*Codes_SRS_IOTHUBCLIENT_17_007: [ IoTHubClient_CreateWithTransport shall instantiate a new IoTHubClient_LL instance by calling IoTHubClient_LL_CreateWithTransport and passing the lower layer transport and config argument. ]*/ 00388 result->IoTHubClientLLHandle = IoTHubClient_LL_CreateWithTransport(&deviceConfig); 00389 if (result->IoTHubClientLLHandle == NULL) 00390 { 00391 LogError("unable to IoTHubClient_LL_CreateWithTransport"); 00392 /*Codes_SRS_IOTHUBCLIENT_17_008: [ If IoTHubClient_LL_CreateWithTransport fails, then IoTHubClient_Create shall return NULL. ]*/ 00393 /*Codes_SRS_IOTHUBCLIENT_17_009: [ If IoTHubClient_LL_CreateWithTransport fails, all resources allocated by it shall be freed. ]*/ 00394 #ifdef USE_UPLOADTOBLOB 00395 list_destroy(result->savedDataToBeCleaned); 00396 #endif 00397 free(result); 00398 result = NULL; 00399 } 00400 00401 if (Unlock(transportLock) != LOCK_OK) 00402 { 00403 LogError("unable to Unlock"); 00404 } 00405 } 00406 } 00407 } 00408 } 00409 } 00410 00411 } 00412 00413 return result; 00414 } 00415 00416 /* Codes_SRS_IOTHUBCLIENT_01_005: [IoTHubClient_Destroy shall free all resources associated with the iotHubClientHandle instance.] */ 00417 void IoTHubClient_Destroy(IOTHUB_CLIENT_HANDLE iotHubClientHandle) 00418 { 00419 /* Codes_SRS_IOTHUBCLIENT_01_008: [IoTHubClient_Destroy shall do nothing if parameter iotHubClientHandle is NULL.] */ 00420 if (iotHubClientHandle != NULL) 00421 { 00422 bool okToJoin; 00423 00424 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00425 00426 /*Codes_SRS_IOTHUBCLIENT_02_043: [ IoTHubClient_Destroy shall lock the serializing lock and signal the worker thread (if any) to end ]*/ 00427 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00428 { 00429 LogError("unable to Lock - - will still proceed to try to end the thread without locking"); 00430 } 00431 00432 #ifdef USE_UPLOADTOBLOB 00433 /*Codes_SRS_IOTHUBCLIENT_02_069: [ IoTHubClient_Destroy shall free all data created by IoTHubClient_UploadToBlobAsync ]*/ 00434 /*wait for all uploading threads to finish*/ 00435 while (list_get_head_item(iotHubClientInstance->savedDataToBeCleaned) != NULL) 00436 { 00437 garbageCollectorImpl(iotHubClientInstance); 00438 } 00439 #endif 00440 if (iotHubClientInstance->ThreadHandle != NULL) 00441 { 00442 iotHubClientInstance->StopThread = 1; 00443 okToJoin = true; 00444 } 00445 else 00446 { 00447 okToJoin = false; 00448 } 00449 00450 if (iotHubClientInstance->TransportHandle != NULL) 00451 { 00452 /*Codes_SRS_IOTHUBCLIENT_01_007: [ The thread created as part of executing IoTHubClient_SendEventAsync or IoTHubClient_SetNotificationMessageCallback shall be joined. ]*/ 00453 okToJoin = IoTHubTransport_SignalEndWorkerThread(iotHubClientInstance->TransportHandle, iotHubClientHandle); 00454 } 00455 00456 /* Codes_SRS_IOTHUBCLIENT_01_006: [That includes destroying the IoTHubClient_LL instance by calling IoTHubClient_LL_Destroy.] */ 00457 IoTHubClient_LL_Destroy(iotHubClientInstance->IoTHubClientLLHandle); 00458 00459 #ifdef USE_UPLOADTOBLOB 00460 if (iotHubClientInstance->savedDataToBeCleaned != NULL) 00461 { 00462 list_destroy(iotHubClientInstance->savedDataToBeCleaned); 00463 } 00464 #endif 00465 00466 /*Codes_SRS_IOTHUBCLIENT_02_045: [ IoTHubClient_Destroy shall unlock the serializing lock. ]*/ 00467 if (Unlock(iotHubClientInstance->LockHandle) != LOCK_OK) 00468 { 00469 LogError("unable to Unlock"); 00470 } 00471 00472 if (okToJoin == true) 00473 { 00474 if (iotHubClientInstance->ThreadHandle != NULL) 00475 { 00476 int res; 00477 /*Codes_SRS_IOTHUBCLIENT_01_007: [ The thread created as part of executing IoTHubClient_SendEventAsync or IoTHubClient_SetNotificationMessageCallback shall be joined. ]*/ 00478 if (ThreadAPI_Join(iotHubClientInstance->ThreadHandle, &res) != THREADAPI_OK) 00479 { 00480 LogError("ThreadAPI_Join failed"); 00481 } 00482 } 00483 if (iotHubClientInstance->TransportHandle != NULL) 00484 { 00485 /*Codes_SRS_IOTHUBCLIENT_01_007: [ The thread created as part of executing IoTHubClient_SendEventAsync or IoTHubClient_SetNotificationMessageCallback shall be joined. ]*/ 00486 IoTHubTransport_JoinWorkerThread(iotHubClientInstance->TransportHandle, iotHubClientHandle); 00487 } 00488 } 00489 00490 if (iotHubClientInstance->TransportHandle == NULL) 00491 { 00492 /* Codes_SRS_IOTHUBCLIENT_01_032: [If the lock was allocated in IoTHubClient_Create, it shall be also freed..] */ 00493 Lock_Deinit(iotHubClientInstance->LockHandle); 00494 } 00495 00496 free(iotHubClientInstance); 00497 } 00498 } 00499 00500 IOTHUB_CLIENT_RESULT IoTHubClient_SendEventAsync(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback) 00501 { 00502 IOTHUB_CLIENT_RESULT result; 00503 00504 if (iotHubClientHandle == NULL) 00505 { 00506 /* Codes_SRS_IOTHUBCLIENT_01_011: [If iotHubClientHandle is NULL, IoTHubClient_SendEventAsync shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00507 result = IOTHUB_CLIENT_INVALID_ARG; 00508 LogError("NULL iothubClientHandle"); 00509 } 00510 else 00511 { 00512 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00513 00514 /* Codes_SRS_IOTHUBCLIENT_01_025: [IoTHubClient_SendEventAsync shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00515 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00516 { 00517 /* Codes_SRS_IOTHUBCLIENT_01_026: [If acquiring the lock fails, IoTHubClient_SendEventAsync shall return IOTHUB_CLIENT_ERROR.] */ 00518 result = IOTHUB_CLIENT_ERROR; 00519 LogError("Could not acquire lock"); 00520 } 00521 else 00522 { 00523 /* Codes_SRS_IOTHUBCLIENT_01_009: [IoTHubClient_SendEventAsync shall start the worker thread if it was not previously started.] */ 00524 if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) 00525 { 00526 /* Codes_SRS_IOTHUBCLIENT_01_010: [If starting the thread fails, IoTHubClient_SendEventAsync shall return IOTHUB_CLIENT_ERROR.] */ 00527 result = IOTHUB_CLIENT_ERROR; 00528 LogError("Could not start worker thread"); 00529 } 00530 else 00531 { 00532 /* Codes_SRS_IOTHUBCLIENT_01_012: [IoTHubClient_SendEventAsync shall call IoTHubClient_LL_SendEventAsync, while passing the IoTHubClient_LL handle created by IoTHubClient_Create and the parameters eventMessageHandle, eventConfirmationCallback and userContextCallback.] */ 00533 /* Codes_SRS_IOTHUBCLIENT_01_013: [When IoTHubClient_LL_SendEventAsync is called, IoTHubClient_SendEventAsync shall return the result of IoTHubClient_LL_SendEventAsync.] */ 00534 result = IoTHubClient_LL_SendEventAsync(iotHubClientInstance->IoTHubClientLLHandle, eventMessageHandle, eventConfirmationCallback, userContextCallback); 00535 } 00536 00537 /* Codes_SRS_IOTHUBCLIENT_01_025: [IoTHubClient_SendEventAsync shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00538 (void)Unlock(iotHubClientInstance->LockHandle); 00539 } 00540 } 00541 00542 return result; 00543 } 00544 00545 IOTHUB_CLIENT_RESULT IoTHubClient_GetSendStatus(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_STATUS *iotHubClientStatus) 00546 { 00547 IOTHUB_CLIENT_RESULT result; 00548 00549 if (iotHubClientHandle == NULL) 00550 { 00551 /* Codes_SRS_IOTHUBCLIENT_01_023: [If iotHubClientHandle is NULL, IoTHubClient_ GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00552 result = IOTHUB_CLIENT_INVALID_ARG; 00553 LogError("NULL iothubClientHandle"); 00554 } 00555 else 00556 { 00557 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00558 00559 /* Codes_SRS_IOTHUBCLIENT_01_033: [IoTHubClient_GetSendStatus shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00560 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00561 { 00562 /* Codes_SRS_IOTHUBCLIENT_01_034: [If acquiring the lock fails, IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_ERROR.] */ 00563 result = IOTHUB_CLIENT_ERROR; 00564 LogError("Could not acquire lock"); 00565 } 00566 else 00567 { 00568 /* Codes_SRS_IOTHUBCLIENT_01_022: [IoTHubClient_GetSendStatus shall call IoTHubClient_LL_GetSendStatus, while passing the IoTHubClient_LL handle created by IoTHubClient_Create and the parameter iotHubClientStatus.] */ 00569 /* Codes_SRS_IOTHUBCLIENT_01_024: [Otherwise, IoTHubClient_GetSendStatus shall return the result of IoTHubClient_LL_GetSendStatus.] */ 00570 result = IoTHubClient_LL_GetSendStatus(iotHubClientInstance->IoTHubClientLLHandle, iotHubClientStatus); 00571 00572 /* Codes_SRS_IOTHUBCLIENT_01_033: [IoTHubClient_GetSendStatus shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00573 (void)Unlock(iotHubClientInstance->LockHandle); 00574 } 00575 } 00576 00577 return result; 00578 } 00579 00580 IOTHUB_CLIENT_RESULT IoTHubClient_SetMessageCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback) 00581 { 00582 IOTHUB_CLIENT_RESULT result; 00583 00584 if (iotHubClientHandle == NULL) 00585 { 00586 /* Codes_SRS_IOTHUBCLIENT_01_016: [If iotHubClientHandle is NULL, IoTHubClient_SetMessageCallback shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00587 result = IOTHUB_CLIENT_INVALID_ARG; 00588 LogError("NULL iothubClientHandle"); 00589 } 00590 else 00591 { 00592 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00593 00594 /* Codes_SRS_IOTHUBCLIENT_01_027: [IoTHubClient_SetMessageCallback shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00595 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00596 { 00597 /* Codes_SRS_IOTHUBCLIENT_01_028: [If acquiring the lock fails, IoTHubClient_SetMessageCallback shall return IOTHUB_CLIENT_ERROR.] */ 00598 result = IOTHUB_CLIENT_ERROR; 00599 LogError("Could not acquire lock"); 00600 } 00601 else 00602 { 00603 /* Codes_SRS_IOTHUBCLIENT_01_014: [IoTHubClient_SetMessageCallback shall start the worker thread if it was not previously started.] */ 00604 if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) 00605 { 00606 /* Codes_SRS_IOTHUBCLIENT_01_015: [If starting the thread fails, IoTHubClient_SetMessageCallback shall return IOTHUB_CLIENT_ERROR.] */ 00607 result = IOTHUB_CLIENT_ERROR; 00608 LogError("Could not start worker thread"); 00609 } 00610 else 00611 { 00612 /* Codes_SRS_IOTHUBCLIENT_01_017: [IoTHubClient_SetMessageCallback shall call IoTHubClient_LL_SetMessageCallback, while passing the IoTHubClient_LL handle created by IoTHubClient_Create and the parameters messageCallback and userContextCallback.] */ 00613 result = IoTHubClient_LL_SetMessageCallback(iotHubClientInstance->IoTHubClientLLHandle, messageCallback, userContextCallback); 00614 } 00615 00616 /* Codes_SRS_IOTHUBCLIENT_01_027: [IoTHubClient_SetMessageCallback shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00617 Unlock(iotHubClientInstance->LockHandle); 00618 } 00619 } 00620 00621 return result; 00622 } 00623 00624 IOTHUB_CLIENT_RESULT IoTHubClient_GetLastMessageReceiveTime(IOTHUB_CLIENT_HANDLE iotHubClientHandle, time_t* lastMessageReceiveTime) 00625 { 00626 IOTHUB_CLIENT_RESULT result; 00627 00628 if (iotHubClientHandle == NULL) 00629 { 00630 /* Codes_SRS_IOTHUBCLIENT_01_020: [If iotHubClientHandle is NULL, IoTHubClient_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00631 result = IOTHUB_CLIENT_INVALID_ARG; 00632 LogError("NULL iothubClientHandle"); 00633 } 00634 else 00635 { 00636 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00637 00638 /* Codes_SRS_IOTHUBCLIENT_01_035: [IoTHubClient_GetLastMessageReceiveTime shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00639 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00640 { 00641 /* Codes_SRS_IOTHUBCLIENT_01_036: [If acquiring the lock fails, IoTHubClient_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_ERROR.] */ 00642 result = IOTHUB_CLIENT_ERROR; 00643 LogError("Could not acquire lock"); 00644 } 00645 else 00646 { 00647 /* Codes_SRS_IOTHUBCLIENT_01_019: [IoTHubClient_GetLastMessageReceiveTime shall call IoTHubClient_LL_GetLastMessageReceiveTime, while passing the IoTHubClient_LL handle created by IoTHubClient_Create and the parameter lastMessageReceiveTime.] */ 00648 /* Codes_SRS_IOTHUBCLIENT_01_021: [Otherwise, IoTHubClient_GetLastMessageReceiveTime shall return the result of IoTHubClient_LL_GetLastMessageReceiveTime.] */ 00649 result = IoTHubClient_LL_GetLastMessageReceiveTime(iotHubClientInstance->IoTHubClientLLHandle, lastMessageReceiveTime); 00650 00651 /* Codes_SRS_IOTHUBCLIENT_01_035: [IoTHubClient_GetLastMessageReceiveTime shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00652 Unlock(iotHubClientInstance->LockHandle); 00653 } 00654 } 00655 00656 return result; 00657 } 00658 00659 IOTHUB_CLIENT_RESULT IoTHubClient_SetOption(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* optionName, const void* value) 00660 { 00661 IOTHUB_CLIENT_RESULT result; 00662 /*Codes_SRS_IOTHUBCLIENT_02_034: [If parameter iotHubClientHandle is NULL then IoTHubClient_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00663 /*Codes_SRS_IOTHUBCLIENT_02_035: [ If parameter optionName is NULL then IoTHubClient_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/ 00664 /*Codes_SRS_IOTHUBCLIENT_02_036: [ If parameter value is NULL then IoTHubClient_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/ 00665 if ( 00666 (iotHubClientHandle == NULL) || 00667 (optionName == NULL) || 00668 (value == NULL) 00669 ) 00670 { 00671 result = IOTHUB_CLIENT_INVALID_ARG; 00672 LogError("invalid arg (NULL)r\n"); 00673 } 00674 else 00675 { 00676 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00677 00678 /* Codes_SRS_IOTHUBCLIENT_01_041: [ IoTHubClient_SetOption shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/ 00679 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00680 { 00681 /* Codes_SRS_IOTHUBCLIENT_01_042: [ If acquiring the lock fails, IoTHubClient_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_ERROR. ]*/ 00682 result = IOTHUB_CLIENT_ERROR; 00683 LogError("Could not acquire lock"); 00684 } 00685 else 00686 { 00687 /*Codes_SRS_IOTHUBCLIENT_02_038: [If optionName doesn't match one of the options handled by this module then IoTHubClient_SetOption shall call IoTHubClient_LL_SetOption passing the same parameters and return what IoTHubClient_LL_SetOption returns.] */ 00688 result = IoTHubClient_LL_SetOption(iotHubClientInstance->IoTHubClientLLHandle, optionName, value); 00689 if (result != IOTHUB_CLIENT_OK) 00690 { 00691 LogError("IoTHubClient_LL_SetOption failed"); 00692 } 00693 00694 Unlock(iotHubClientInstance->LockHandle); 00695 } 00696 } 00697 return result; 00698 } 00699 00700 #ifdef USE_UPLOADTOBLOB 00701 static int uploadingThread(void *data) 00702 { 00703 UPLOADTOBLOB_SAVED_DATA* savedData = (UPLOADTOBLOB_SAVED_DATA*)data; 00704 00705 /*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*/ 00706 /*not having it protected means multiple simultaneous uploads can happen*/ 00707 /*Codes_SRS_IOTHUBCLIENT_02_054: [ The thread shall call IoTHubClient_LL_UploadToBlob passing the information packed in the structure. ]*/ 00708 if (IoTHubClient_LL_UploadToBlob(savedData->iotHubClientHandle->IoTHubClientLLHandle, savedData->destinationFileName, savedData->source, savedData->size) != IOTHUB_CLIENT_OK) 00709 { 00710 LogError("unable to IoTHubClient_LL_UploadToBlob"); 00711 /*call the callback*/ 00712 if (savedData->iotHubClientFileUploadCallback != NULL) 00713 { 00714 /*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. ]*/ 00715 savedData->iotHubClientFileUploadCallback(FILE_UPLOAD_ERROR, savedData->context); 00716 } 00717 } 00718 else 00719 { 00720 if (savedData->iotHubClientFileUploadCallback != NULL) 00721 { 00722 /*Codes_SRS_IOTHUBCLIENT_02_056: [ Otherwise the thread iotHubClientFileUploadCallbackInternal passing as result FILE_UPLOAD_OK and the structure from SRS IOTHUBCLIENT 02 051. ]*/ 00723 savedData->iotHubClientFileUploadCallback(FILE_UPLOAD_OK, savedData->context); 00724 } 00725 } 00726 00727 /*Codes_SRS_IOTHUBCLIENT_02_071: [ The thread shall mark itself as disposable. ]*/ 00728 if (Lock(savedData->lockGarbage) != LOCK_OK) 00729 { 00730 LogError("unable to Lock - trying anyway"); 00731 savedData->canBeGarbageCollected = 1; 00732 } 00733 else 00734 { 00735 savedData->canBeGarbageCollected = 1; 00736 00737 if (Unlock(savedData->lockGarbage) != LOCK_OK) 00738 { 00739 LogError("unable to Unlock after locking"); 00740 } 00741 } 00742 return 0; 00743 } 00744 #endif 00745 00746 #ifdef USE_UPLOADTOBLOB 00747 IOTHUB_CLIENT_RESULT IoTHubClient_UploadToBlobAsync(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* destinationFileName, const unsigned char* source, size_t size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback, void* context) 00748 { 00749 IOTHUB_CLIENT_RESULT result; 00750 /*Codes_SRS_IOTHUBCLIENT_02_047: [ If iotHubClientHandle is NULL then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/ 00751 /*Codes_SRS_IOTHUBCLIENT_02_048: [ If destinationFileName is NULL then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/ 00752 /*Codes_SRS_IOTHUBCLIENT_02_049: [ If source is NULL and size is greated than 0 then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/ 00753 if ( 00754 (iotHubClientHandle == NULL) || 00755 (destinationFileName == NULL) || 00756 ((source == NULL) && (size > 0)) 00757 ) 00758 { 00759 LogError("invalid parameters IOTHUB_CLIENT_HANDLE iotHubClientHandle = %p , const char* destinationFileName = %s, const unsigned char* source= %p, size_t size = %zu, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK iotHubClientFileUploadCallback = %p, void* context = %p", 00760 iotHubClientHandle, 00761 destinationFileName, 00762 source, 00763 size, 00764 iotHubClientFileUploadCallback, 00765 context 00766 ); 00767 result = IOTHUB_CLIENT_INVALID_ARG; 00768 } 00769 else 00770 { 00771 /*Codes_SRS_IOTHUBCLIENT_02_051: [IoTHubClient_UploadToBlobAsync shall copy the souce, size, iotHubClientFileUploadCallback, context into a structure.]*/ 00772 UPLOADTOBLOB_SAVED_DATA *savedData = (UPLOADTOBLOB_SAVED_DATA *)malloc(sizeof(UPLOADTOBLOB_SAVED_DATA)); 00773 if (savedData == NULL) 00774 { 00775 /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ 00776 LogError("unable to malloc - oom"); 00777 result = IOTHUB_CLIENT_ERROR; 00778 } 00779 else 00780 { 00781 if (mallocAndStrcpy_s((char**)&savedData->destinationFileName, destinationFileName) != 0) 00782 { 00783 /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ 00784 LogError("unable to mallocAndStrcpy_s"); 00785 free(savedData); 00786 result = IOTHUB_CLIENT_ERROR; 00787 } 00788 else 00789 { 00790 savedData->size = size; 00791 int sourceCloned; 00792 if (size == 0) 00793 { 00794 savedData->source = NULL; 00795 sourceCloned = 1; 00796 } 00797 else 00798 { 00799 savedData->source = (unsigned char*)malloc(size); 00800 if (savedData->source == NULL) 00801 { 00802 /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ 00803 LogError("unable to malloc - oom"); 00804 free(savedData->destinationFileName); 00805 free(savedData); 00806 sourceCloned = 0; 00807 00808 } 00809 else 00810 { 00811 sourceCloned = 1; 00812 } 00813 } 00814 00815 if (sourceCloned == 0) 00816 { 00817 result = IOTHUB_CLIENT_ERROR; 00818 } 00819 else 00820 { 00821 savedData->iotHubClientFileUploadCallback = iotHubClientFileUploadCallback; 00822 savedData->context = context; 00823 memcpy(savedData->source, source, size); 00824 IOTHUB_CLIENT_INSTANCE* iotHubClientHandleData = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00825 if (Lock(iotHubClientHandleData->LockHandle) != LOCK_OK) /*locking because the next statement is changing blobThreadsToBeJoined*/ 00826 { 00827 LogError("unable to lock"); 00828 free(savedData->source); 00829 free(savedData->destinationFileName); 00830 free(savedData); 00831 result = IOTHUB_CLIENT_ERROR; 00832 } 00833 else 00834 { 00835 if ((result = StartWorkerThreadIfNeeded(iotHubClientHandleData)) != IOTHUB_CLIENT_OK) 00836 { 00837 free(savedData->source); 00838 free(savedData->destinationFileName); 00839 free(savedData); 00840 result = IOTHUB_CLIENT_ERROR; 00841 LogError("Could not start worker thread"); 00842 } 00843 else 00844 { 00845 /*Codes_SRS_IOTHUBCLIENT_02_058: [ IoTHubClient_UploadToBlobAsync shall add the structure to the list of structures that need to be cleaned once file upload finishes. ]*/ 00846 LIST_ITEM_HANDLE item = list_add(iotHubClientHandleData->savedDataToBeCleaned, savedData); 00847 if (item == NULL) 00848 { 00849 LogError("unable to list_add"); 00850 free(savedData->source); 00851 free(savedData->destinationFileName); 00852 free(savedData); 00853 result = IOTHUB_CLIENT_ERROR; 00854 } 00855 else 00856 { 00857 savedData->iotHubClientHandle = iotHubClientHandle; 00858 savedData->canBeGarbageCollected = 0; 00859 if ((savedData->lockGarbage = Lock_Init()) == NULL) 00860 { 00861 (void)list_remove(iotHubClientHandleData->savedDataToBeCleaned, item); 00862 free(savedData->source); 00863 free(savedData->destinationFileName); 00864 free(savedData); 00865 result = IOTHUB_CLIENT_ERROR; 00866 LogError("unable to Lock_Init"); 00867 } 00868 else 00869 { 00870 /*Codes_SRS_IOTHUBCLIENT_02_052: [ IoTHubClient_UploadToBlobAsync shall spawn a thread passing the structure build in SRS IOTHUBCLIENT 02 051 as thread data.]*/ 00871 if (ThreadAPI_Create(&savedData->uploadingThreadHandle, uploadingThread, savedData) != THREADAPI_OK) 00872 { 00873 /*Codes_SRS_IOTHUBCLIENT_02_053: [ If copying to the structure or spawning the thread fails, then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_ERROR. ]*/ 00874 LogError("unablet to ThreadAPI_Create"); 00875 (void)Lock_Deinit(savedData->lockGarbage); 00876 (void)list_remove(iotHubClientHandleData->savedDataToBeCleaned, item); 00877 free(savedData->source); 00878 free(savedData->destinationFileName); 00879 free(savedData); 00880 result = IOTHUB_CLIENT_ERROR; 00881 } 00882 else 00883 { 00884 00885 result = IOTHUB_CLIENT_OK; 00886 } 00887 } 00888 } 00889 } 00890 Unlock(iotHubClientHandleData->LockHandle); 00891 } 00892 } 00893 } 00894 } 00895 } 00896 return result; 00897 } 00898 #endif /*USE_UPLOADTOBLOB*/
Generated on Tue Jul 12 2022 19:44:54 by 1.7.2