Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: azure_umqtt_c iothub_mqtt_transport mbed-rtos mbed wolfSSL Socket lwip-eth lwip-sys lwip
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/xlogging.h" 00020 #include "azure_c_shared_utility/singlylinkedlist.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 #ifndef DONT_USE_UPLOADTOBLOB 00030 SINGLYLINKEDLIST_HANDLE savedDataToBeCleaned; /*list containing UPLOADTOBLOB_SAVED_DATA*/ 00031 #endif 00032 } IOTHUB_CLIENT_INSTANCE; 00033 00034 #ifndef DONT_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 #ifndef DONT_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 = singlylinkedlist_get_head_item(iotHubClientInstance->savedDataToBeCleaned); 00059 while (item != NULL) 00060 { 00061 const UPLOADTOBLOB_SAVED_DATA* savedData = (const UPLOADTOBLOB_SAVED_DATA*)singlylinkedlist_item_get_value(item); 00062 LIST_ITEM_HANDLE old_item = item; 00063 item = singlylinkedlist_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)singlylinkedlist_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 #ifndef DONT_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 = (IOTHUB_CLIENT_INSTANCE *) 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 #ifndef DONT_USE_UPLOADTOBLOB 00208 /*Codes_SRS_IOTHUBCLIENT_02_059: [ IoTHubClient_CreateFromConnectionString shall create a SINGLYLINKEDLIST_HANDLE containing THREAD_HANDLE (created by future calls to IoTHubClient_UploadToBlobAsync). ]*/ 00209 if ((result->savedDataToBeCleaned = singlylinkedlist_create()) == NULL) 00210 { 00211 /*Codes_SRS_IOTHUBCLIENT_02_070: [ If creating the SINGLYLINKEDLIST_HANDLE fails then IoTHubClient_CreateFromConnectionString shall fail and return NULL]*/ 00212 LogError("unable to singlylinkedlist_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 #ifndef DONT_USE_UPLOADTOBLOB 00226 singlylinkedlist_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 #ifndef DONT_USE_UPLOADTOBLOB 00266 /*Codes_SRS_IOTHUBCLIENT_02_060: [ IoTHubClient_Create shall create a SINGLYLINKEDLIST_HANDLE containing THREAD_HANDLE (created by future calls to IoTHubClient_UploadToBlobAsync). ]*/ 00267 if ((result->savedDataToBeCleaned = singlylinkedlist_create()) == NULL) 00268 { 00269 /*Codes_SRS_IOTHUBCLIENT_02_061: [ If creating the SINGLYLINKEDLIST_HANDLE fails then IoTHubClient_Create shall fail and return NULL. ]*/ 00270 LogError("unable to singlylinkedlist_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 #ifndef DONT_USE_UPLOADTOBLOB 00286 singlylinkedlist_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 #ifndef DONT_USE_UPLOADTOBLOB 00326 /*Codes_SRS_IOTHUBCLIENT_02_073: [ IoTHubClient_CreateWithTransport shall create a SINGLYLINKEDLIST_HANDLE that shall be used by IoTHubClient_UploadToBlobAsync. ]*/ 00327 if ((result->savedDataToBeCleaned = singlylinkedlist_create()) == NULL) 00328 { 00329 /*Codes_SRS_IOTHUBCLIENT_02_074: [ If creating the SINGLYLINKEDLIST_HANDLE fails then IoTHubClient_CreateWithTransport shall fail and return NULL. ]*/ 00330 LogError("unable to singlylinkedlist_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 #ifndef DONT_USE_UPLOADTOBLOB 00347 singlylinkedlist_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 #ifndef DONT_USE_UPLOADTOBLOB 00369 singlylinkedlist_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 #ifndef DONT_USE_UPLOADTOBLOB 00380 singlylinkedlist_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 #ifndef DONT_USE_UPLOADTOBLOB 00395 singlylinkedlist_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 int index = 0; 00420 00421 printf("IoTHubClient_Destroy %d\r\n", index++); 00422 /* Codes_SRS_IOTHUBCLIENT_01_008: [IoTHubClient_Destroy shall do nothing if parameter iotHubClientHandle is NULL.] */ 00423 if (iotHubClientHandle != NULL) 00424 { 00425 printf("IoTHubClient_Destroy iotHubClientHandle != NULL %d\r\n", index++); 00426 bool okToJoin; 00427 00428 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00429 00430 /*Codes_SRS_IOTHUBCLIENT_02_043: [ IoTHubClient_Destroy shall lock the serializing lock and signal the worker thread (if any) to end ]*/ 00431 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00432 { 00433 LogError("unable to Lock - - will still proceed to try to end the thread without locking"); 00434 } 00435 00436 #ifndef DONT_USE_UPLOADTOBLOB 00437 /*Codes_SRS_IOTHUBCLIENT_02_069: [ IoTHubClient_Destroy shall free all data created by IoTHubClient_UploadToBlobAsync ]*/ 00438 /*wait for all uploading threads to finish*/ 00439 printf("IoTHubClient_Destroy %d\r\n", index++); 00440 while (singlylinkedlist_get_head_item(iotHubClientInstance->savedDataToBeCleaned) != NULL) 00441 { 00442 garbageCollectorImpl(iotHubClientInstance); 00443 } 00444 #endif 00445 printf("IoTHubClient_Destroy %d\r\n", index++); 00446 if (iotHubClientInstance->ThreadHandle != NULL) 00447 { 00448 iotHubClientInstance->StopThread = 1; 00449 okToJoin = true; 00450 } 00451 else 00452 { 00453 okToJoin = false; 00454 } 00455 00456 printf("IoTHubClient_Destroy %d\r\n", index++); 00457 if (iotHubClientInstance->TransportHandle != NULL) 00458 { 00459 /*Codes_SRS_IOTHUBCLIENT_01_007: [ The thread created as part of executing IoTHubClient_SendEventAsync or IoTHubClient_SetNotificationMessageCallback shall be joined. ]*/ 00460 okToJoin = IoTHubTransport_SignalEndWorkerThread(iotHubClientInstance->TransportHandle, iotHubClientHandle); 00461 } 00462 00463 /* Codes_SRS_IOTHUBCLIENT_01_006: [That includes destroying the IoTHubClient_LL instance by calling IoTHubClient_LL_Destroy.] */ 00464 printf("IoTHubClient_Destroy %d\r\n", index++); 00465 IoTHubClient_LL_Destroy(iotHubClientInstance->IoTHubClientLLHandle); 00466 00467 #ifndef DONT_USE_UPLOADTOBLOB 00468 printf("IoTHubClient_Destroy %d\r\n", index++); 00469 if (iotHubClientInstance->savedDataToBeCleaned != NULL) 00470 { 00471 singlylinkedlist_destroy(iotHubClientInstance->savedDataToBeCleaned); 00472 } 00473 #endif 00474 00475 /*Codes_SRS_IOTHUBCLIENT_02_045: [ IoTHubClient_Destroy shall unlock the serializing lock. ]*/ 00476 printf("IoTHubClient_Destroy %d\r\n", index++); 00477 if (Unlock(iotHubClientInstance->LockHandle) != LOCK_OK) 00478 { 00479 LogError("unable to Unlock"); 00480 } 00481 00482 printf("IoTHubClient_Destroy before okToJoin == true %d\r\n", index++); 00483 if (okToJoin == true) 00484 { 00485 if (iotHubClientInstance->ThreadHandle != NULL) 00486 { 00487 int res; 00488 /*Codes_SRS_IOTHUBCLIENT_01_007: [ The thread created as part of executing IoTHubClient_SendEventAsync or IoTHubClient_SetNotificationMessageCallback shall be joined. ]*/ 00489 printf("IoTHubClient_Destroy before ThreadAPI_Join %d\r\n", index++); 00490 if (ThreadAPI_Join(iotHubClientInstance->ThreadHandle, &res) != THREADAPI_OK) 00491 { 00492 LogError("ThreadAPI_Join failed"); 00493 } 00494 } 00495 if (iotHubClientInstance->TransportHandle != NULL) 00496 { 00497 /*Codes_SRS_IOTHUBCLIENT_01_007: [ The thread created as part of executing IoTHubClient_SendEventAsync or IoTHubClient_SetNotificationMessageCallback shall be joined. ]*/ 00498 printf("IoTHubClient_Destroy before IoTHubTransport_JoinWorkerThread %d\r\n", index++); 00499 IoTHubTransport_JoinWorkerThread(iotHubClientInstance->TransportHandle, iotHubClientHandle); 00500 } 00501 } 00502 00503 printf("IoTHubClient_Destroy %d\r\n", index++); 00504 if (iotHubClientInstance->TransportHandle == NULL) 00505 { 00506 /* Codes_SRS_IOTHUBCLIENT_01_032: [If the lock was allocated in IoTHubClient_Create, it shall be also freed..] */ 00507 Lock_Deinit(iotHubClientInstance->LockHandle); 00508 } 00509 00510 free(iotHubClientInstance); 00511 } 00512 } 00513 00514 IOTHUB_CLIENT_RESULT IoTHubClient_SendEventAsync(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback) 00515 { 00516 IOTHUB_CLIENT_RESULT result; 00517 00518 if (iotHubClientHandle == NULL) 00519 { 00520 /* Codes_SRS_IOTHUBCLIENT_01_011: [If iotHubClientHandle is NULL, IoTHubClient_SendEventAsync shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00521 result = IOTHUB_CLIENT_INVALID_ARG; 00522 LogError("NULL iothubClientHandle"); 00523 } 00524 else 00525 { 00526 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00527 00528 /* Codes_SRS_IOTHUBCLIENT_01_025: [IoTHubClient_SendEventAsync shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00529 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00530 { 00531 /* Codes_SRS_IOTHUBCLIENT_01_026: [If acquiring the lock fails, IoTHubClient_SendEventAsync shall return IOTHUB_CLIENT_ERROR.] */ 00532 result = IOTHUB_CLIENT_ERROR; 00533 LogError("Could not acquire lock"); 00534 } 00535 else 00536 { 00537 /* Codes_SRS_IOTHUBCLIENT_01_009: [IoTHubClient_SendEventAsync shall start the worker thread if it was not previously started.] */ 00538 if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) 00539 { 00540 /* Codes_SRS_IOTHUBCLIENT_01_010: [If starting the thread fails, IoTHubClient_SendEventAsync shall return IOTHUB_CLIENT_ERROR.] */ 00541 result = IOTHUB_CLIENT_ERROR; 00542 LogError("Could not start worker thread"); 00543 } 00544 else 00545 { 00546 /* 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.] */ 00547 /* Codes_SRS_IOTHUBCLIENT_01_013: [When IoTHubClient_LL_SendEventAsync is called, IoTHubClient_SendEventAsync shall return the result of IoTHubClient_LL_SendEventAsync.] */ 00548 result = IoTHubClient_LL_SendEventAsync(iotHubClientInstance->IoTHubClientLLHandle, eventMessageHandle, eventConfirmationCallback, userContextCallback); 00549 } 00550 00551 /* Codes_SRS_IOTHUBCLIENT_01_025: [IoTHubClient_SendEventAsync shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00552 (void)Unlock(iotHubClientInstance->LockHandle); 00553 } 00554 } 00555 00556 return result; 00557 } 00558 00559 IOTHUB_CLIENT_RESULT IoTHubClient_GetSendStatus(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_STATUS *iotHubClientStatus) 00560 { 00561 IOTHUB_CLIENT_RESULT result; 00562 00563 if (iotHubClientHandle == NULL) 00564 { 00565 /* Codes_SRS_IOTHUBCLIENT_01_023: [If iotHubClientHandle is NULL, IoTHubClient_ GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00566 result = IOTHUB_CLIENT_INVALID_ARG; 00567 LogError("NULL iothubClientHandle"); 00568 } 00569 else 00570 { 00571 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00572 00573 /* Codes_SRS_IOTHUBCLIENT_01_033: [IoTHubClient_GetSendStatus shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00574 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00575 { 00576 /* Codes_SRS_IOTHUBCLIENT_01_034: [If acquiring the lock fails, IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_ERROR.] */ 00577 result = IOTHUB_CLIENT_ERROR; 00578 LogError("Could not acquire lock"); 00579 } 00580 else 00581 { 00582 /* 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.] */ 00583 /* Codes_SRS_IOTHUBCLIENT_01_024: [Otherwise, IoTHubClient_GetSendStatus shall return the result of IoTHubClient_LL_GetSendStatus.] */ 00584 result = IoTHubClient_LL_GetSendStatus(iotHubClientInstance->IoTHubClientLLHandle, iotHubClientStatus); 00585 00586 /* Codes_SRS_IOTHUBCLIENT_01_033: [IoTHubClient_GetSendStatus shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00587 (void)Unlock(iotHubClientInstance->LockHandle); 00588 } 00589 } 00590 00591 return result; 00592 } 00593 00594 IOTHUB_CLIENT_RESULT IoTHubClient_SetMessageCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback) 00595 { 00596 IOTHUB_CLIENT_RESULT result; 00597 00598 if (iotHubClientHandle == NULL) 00599 { 00600 /* Codes_SRS_IOTHUBCLIENT_01_016: [If iotHubClientHandle is NULL, IoTHubClient_SetMessageCallback shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00601 result = IOTHUB_CLIENT_INVALID_ARG; 00602 LogError("NULL iothubClientHandle"); 00603 } 00604 else 00605 { 00606 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00607 00608 /* Codes_SRS_IOTHUBCLIENT_01_027: [IoTHubClient_SetMessageCallback shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00609 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00610 { 00611 /* Codes_SRS_IOTHUBCLIENT_01_028: [If acquiring the lock fails, IoTHubClient_SetMessageCallback shall return IOTHUB_CLIENT_ERROR.] */ 00612 result = IOTHUB_CLIENT_ERROR; 00613 LogError("Could not acquire lock"); 00614 } 00615 else 00616 { 00617 /* Codes_SRS_IOTHUBCLIENT_01_014: [IoTHubClient_SetMessageCallback shall start the worker thread if it was not previously started.] */ 00618 if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) 00619 { 00620 /* Codes_SRS_IOTHUBCLIENT_01_015: [If starting the thread fails, IoTHubClient_SetMessageCallback shall return IOTHUB_CLIENT_ERROR.] */ 00621 result = IOTHUB_CLIENT_ERROR; 00622 LogError("Could not start worker thread"); 00623 } 00624 else 00625 { 00626 /* 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.] */ 00627 result = IoTHubClient_LL_SetMessageCallback(iotHubClientInstance->IoTHubClientLLHandle, messageCallback, userContextCallback); 00628 } 00629 00630 /* Codes_SRS_IOTHUBCLIENT_01_027: [IoTHubClient_SetMessageCallback shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00631 (void)Unlock(iotHubClientInstance->LockHandle); 00632 } 00633 } 00634 00635 return result; 00636 } 00637 00638 IOTHUB_CLIENT_RESULT IoTHubClient_SetConnectionStatusCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK connectionStatusCallback, void * userContextCallback) 00639 { 00640 IOTHUB_CLIENT_RESULT result; 00641 00642 if (iotHubClientHandle == NULL) 00643 { 00644 /* Codes_SRS_IOTHUBCLIENT_25_076: [** If `iotHubClientHandle` is `NULL`, `IoTHubClient_SetRetryPolicy` shall return `IOTHUB_CLIENT_INVALID_ARG`. ] */ 00645 result = IOTHUB_CLIENT_INVALID_ARG; 00646 LogError("NULL iothubClientHandle"); 00647 } 00648 else 00649 { 00650 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00651 00652 /* Codes_SRS_IOTHUBCLIENT_25_087: [ `IoTHubClient_SetConnectionStatusCallback` shall be made thread-safe by using the lock created in `IoTHubClient_Create`. ] */ 00653 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00654 { 00655 /* Codes_SRS_IOTHUBCLIENT_25_088: [ If acquiring the lock fails, `IoTHubClient_SetConnectionStatusCallback` shall return `IOTHUB_CLIENT_ERROR`. ]*/ 00656 result = IOTHUB_CLIENT_ERROR; 00657 LogError("Could not acquire lock"); 00658 } 00659 else 00660 { 00661 /* Codes_SRS_IOTHUBCLIENT_25_081: [ `IoTHubClient_SetConnectionStatusCallback` shall start the worker thread if it was not previously started. ]*/ 00662 if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) 00663 { 00664 /* Codes_SRS_IOTHUBCLIENT_25_083: [ If starting the thread fails, `IoTHubClient_SetConnectionStatusCallback` shall return `IOTHUB_CLIENT_ERROR`. ]*/ 00665 result = IOTHUB_CLIENT_ERROR; 00666 LogError("Could not start worker thread"); 00667 } 00668 else 00669 { 00670 /* Codes_SRS_IOTHUBCLIENT_25_085: [ `IoTHubClient_SetConnectionStatusCallback` shall call `IoTHubClient_LL_SetConnectionStatusCallback`, while passing the `IoTHubClient_LL` handle created by `IoTHubClient_Create` and the parameters `connectionStatusCallback` and `userContextCallback`. ]*/ 00671 result = IoTHubClient_LL_SetConnectionStatusCallback(iotHubClientInstance->IoTHubClientLLHandle, connectionStatusCallback, userContextCallback); 00672 } 00673 00674 (void)Unlock(iotHubClientInstance->LockHandle); 00675 } 00676 } 00677 00678 return result; 00679 00680 } 00681 00682 IOTHUB_CLIENT_RESULT IoTHubClient_SetRetryPolicy(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds) 00683 { 00684 IOTHUB_CLIENT_RESULT result; 00685 00686 if (iotHubClientHandle == NULL) 00687 { 00688 /* Codes_SRS_IOTHUBCLIENT_25_076: [** If `iotHubClientHandle` is `NULL`, `IoTHubClient_SetRetryPolicy` shall return `IOTHUB_CLIENT_INVALID_ARG`. ] */ 00689 result = IOTHUB_CLIENT_INVALID_ARG; 00690 LogError("NULL iothubClientHandle"); 00691 } 00692 else 00693 { 00694 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00695 00696 /* Codes_SRS_IOTHUBCLIENT_25_079: [ `IoTHubClient_SetRetryPolicy` shall be made thread-safe by using the lock created in `IoTHubClient_Create`.] */ 00697 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00698 { 00699 /* Codes_SRS_IOTHUBCLIENT_25_080: [ If acquiring the lock fails, `IoTHubClient_SetRetryPolicy` shall return `IOTHUB_CLIENT_ERROR`. ]*/ 00700 result = IOTHUB_CLIENT_ERROR; 00701 LogError("Could not acquire lock"); 00702 } 00703 else 00704 { 00705 /* Codes_SRS_IOTHUBCLIENT_25_073: [ `IoTHubClient_SetRetryPolicy` shall start the worker thread if it was not previously started. ] */ 00706 if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) 00707 { 00708 /* Codes_SRS_IOTHUBCLIENT_25_075: [ If starting the thread fails, `IoTHubClient_SetRetryPolicy` shall return `IOTHUB_CLIENT_ERROR`. ]*/ 00709 result = IOTHUB_CLIENT_ERROR; 00710 LogError("Could not start worker thread"); 00711 } 00712 else 00713 { 00714 /* Codes_SRS_IOTHUBCLIENT_25_077: [ `IoTHubClient_SetRetryPolicy` shall call `IoTHubClient_LL_SetRetryPolicy`, while passing the `IoTHubClient_LL` handle created by `IoTHubClient_Create` and the parameters `retryPolicy` and `retryTimeoutLimitinSeconds`.]*/ 00715 result = IoTHubClient_LL_SetRetryPolicy(iotHubClientInstance->IoTHubClientLLHandle, retryPolicy, retryTimeoutLimitInSeconds); 00716 } 00717 00718 (void)Unlock(iotHubClientInstance->LockHandle); 00719 } 00720 } 00721 00722 return result; 00723 } 00724 00725 IOTHUB_CLIENT_RESULT IoTHubClient_GetRetryPolicy(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY * retryPolicy, size_t * retryTimeoutLimitInSeconds) 00726 { 00727 IOTHUB_CLIENT_RESULT result; 00728 00729 if (iotHubClientHandle == NULL) 00730 { 00731 /* Codes_SRS_IOTHUBCLIENT_25_092: [ If `iotHubClientHandle` is `NULL`, `IoTHubClient_GetRetryPolicy` shall return `IOTHUB_CLIENT_INVALID_ARG`. ]*/ 00732 result = IOTHUB_CLIENT_INVALID_ARG; 00733 LogError("NULL iothubClientHandle"); 00734 } 00735 else 00736 { 00737 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00738 00739 /* Codes_SRS_IOTHUBCLIENT_25_095: [ `IoTHubClient_GetRetryPolicy` shall be made thread-safe by using the lock created in `IoTHubClient_Create`. ]*/ 00740 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00741 { 00742 /* Codes_SRS_IOTHUBCLIENT_25_096: [ If acquiring the lock fails, `IoTHubClient_GetRetryPolicy` shall return `IOTHUB_CLIENT_ERROR`. ]*/ 00743 result = IOTHUB_CLIENT_ERROR; 00744 LogError("Could not acquire lock"); 00745 } 00746 else 00747 { 00748 /* Codes_SRS_IOTHUBCLIENT_25_089: [ `IoTHubClient_GetRetryPolicy` shall start the worker thread if it was not previously started.]*/ 00749 if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) 00750 { 00751 /* Codes_SRS_IOTHUBCLIENT_25_091: [ If starting the thread fails, `IoTHubClient_GetRetryPolicy` shall return `IOTHUB_CLIENT_ERROR`.]*/ 00752 result = IOTHUB_CLIENT_ERROR; 00753 LogError("Could not start worker thread"); 00754 } 00755 else 00756 { 00757 /* Codes_SRS_IOTHUBCLIENT_25_093: [ `IoTHubClient_GetRetryPolicy` shall call `IoTHubClient_LL_GetRetryPolicy`, while passing the `IoTHubClient_LL` handle created by `IoTHubClient_Create` and the parameters `connectionStatusCallback` and `userContextCallback`.]*/ 00758 result = IoTHubClient_LL_GetRetryPolicy(iotHubClientInstance->IoTHubClientLLHandle, retryPolicy, retryTimeoutLimitInSeconds); 00759 } 00760 00761 (void)Unlock(iotHubClientInstance->LockHandle); 00762 } 00763 } 00764 00765 return result; 00766 } 00767 00768 IOTHUB_CLIENT_RESULT IoTHubClient_GetLastMessageReceiveTime(IOTHUB_CLIENT_HANDLE iotHubClientHandle, time_t* lastMessageReceiveTime) 00769 { 00770 IOTHUB_CLIENT_RESULT result; 00771 00772 if (iotHubClientHandle == NULL) 00773 { 00774 /* Codes_SRS_IOTHUBCLIENT_01_020: [If iotHubClientHandle is NULL, IoTHubClient_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00775 result = IOTHUB_CLIENT_INVALID_ARG; 00776 LogError("NULL iothubClientHandle"); 00777 } 00778 else 00779 { 00780 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00781 00782 /* Codes_SRS_IOTHUBCLIENT_01_035: [IoTHubClient_GetLastMessageReceiveTime shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00783 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00784 { 00785 /* Codes_SRS_IOTHUBCLIENT_01_036: [If acquiring the lock fails, IoTHubClient_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_ERROR.] */ 00786 result = IOTHUB_CLIENT_ERROR; 00787 LogError("Could not acquire lock"); 00788 } 00789 else 00790 { 00791 /* 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.] */ 00792 /* Codes_SRS_IOTHUBCLIENT_01_021: [Otherwise, IoTHubClient_GetLastMessageReceiveTime shall return the result of IoTHubClient_LL_GetLastMessageReceiveTime.] */ 00793 result = IoTHubClient_LL_GetLastMessageReceiveTime(iotHubClientInstance->IoTHubClientLLHandle, lastMessageReceiveTime); 00794 00795 /* Codes_SRS_IOTHUBCLIENT_01_035: [IoTHubClient_GetLastMessageReceiveTime shall be made thread-safe by using the lock created in IoTHubClient_Create.] */ 00796 (void)Unlock(iotHubClientInstance->LockHandle); 00797 } 00798 } 00799 00800 return result; 00801 } 00802 00803 IOTHUB_CLIENT_RESULT IoTHubClient_SetOption(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const char* optionName, const void* value) 00804 { 00805 IOTHUB_CLIENT_RESULT result; 00806 /*Codes_SRS_IOTHUBCLIENT_02_034: [If parameter iotHubClientHandle is NULL then IoTHubClient_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00807 /*Codes_SRS_IOTHUBCLIENT_02_035: [ If parameter optionName is NULL then IoTHubClient_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/ 00808 /*Codes_SRS_IOTHUBCLIENT_02_036: [ If parameter value is NULL then IoTHubClient_SetOption shall return IOTHUB_CLIENT_INVALID_ARG. ]*/ 00809 if ( 00810 (iotHubClientHandle == NULL) || 00811 (optionName == NULL) || 00812 (value == NULL) 00813 ) 00814 { 00815 result = IOTHUB_CLIENT_INVALID_ARG; 00816 LogError("invalid arg (NULL)"); 00817 } 00818 else 00819 { 00820 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00821 00822 /* Codes_SRS_IOTHUBCLIENT_01_041: [ IoTHubClient_SetOption shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/ 00823 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00824 { 00825 /* Codes_SRS_IOTHUBCLIENT_01_042: [ If acquiring the lock fails, IoTHubClient_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_ERROR. ]*/ 00826 result = IOTHUB_CLIENT_ERROR; 00827 LogError("Could not acquire lock"); 00828 } 00829 else 00830 { 00831 /*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.] */ 00832 result = IoTHubClient_LL_SetOption(iotHubClientInstance->IoTHubClientLLHandle, optionName, value); 00833 if (result != IOTHUB_CLIENT_OK) 00834 { 00835 LogError("IoTHubClient_LL_SetOption failed"); 00836 } 00837 00838 (void)Unlock(iotHubClientInstance->LockHandle); 00839 } 00840 } 00841 return result; 00842 } 00843 00844 IOTHUB_CLIENT_RESULT IoTHubClient_SetDeviceTwinCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK deviceTwinCallback, void* userContextCallback) 00845 { 00846 IOTHUB_CLIENT_RESULT result; 00847 00848 /*Codes_SRS_IOTHUBCLIENT_10_001: [** `IoTHubClient_SetDeviceTwinCallback` shall fail and return `IOTHUB_CLIENT_INVALID_ARG` if parameter `iotHubClientHandle` is `NULL`. ]*/ 00849 if (iotHubClientHandle == NULL) 00850 { 00851 result = IOTHUB_CLIENT_INVALID_ARG; 00852 LogError("invalid arg (NULL)"); 00853 } 00854 else 00855 { 00856 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00857 00858 /*Codes_SRS_IOTHUBCLIENT_10_020: [** `IoTHubClient_SetDeviceTwinCallback` shall be made thread - safe by using the lock created in IoTHubClient_Create. ]*/ 00859 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00860 { 00861 /*Codes_SRS_IOTHUBCLIENT_10_002: [** If acquiring the lock fails, `IoTHubClient_SetDeviceTwinCallback` shall return `IOTHUB_CLIENT_ERROR`. ]*/ 00862 result = IOTHUB_CLIENT_ERROR; 00863 LogError("Could not acquire lock"); 00864 } 00865 else 00866 { 00867 /*Codes_SRS_IOTHUBCLIENT_10_003: [** If the transport connection is shared, the thread shall be started by calling `IoTHubTransport_StartWorkerThread`. ]*/ 00868 if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) 00869 { 00870 /*Codes_SRS_IOTHUBCLIENT_10_004: [** If starting the thread fails, `IoTHubClient_SetDeviceTwinCallback` shall return `IOTHUB_CLIENT_ERROR`. ]*/ 00871 result = IOTHUB_CLIENT_ERROR; 00872 LogError("Could not start worker thread"); 00873 } 00874 else 00875 { 00876 /*Codes_SRS_IOTHUBCLIENT_10_005: [** `IoTHubClient_LL_SetDeviceTwinCallback` shall call `IoTHubClient_LL_SetDeviceTwinCallback`, while passing the `IoTHubClient_LL handle` created by `IoTHubClient_LL_Create` along with the parameters `reportedStateCallback` and `userContextCallback`. ]*/ 00877 result = IoTHubClient_LL_SetDeviceTwinCallback(iotHubClientInstance->IoTHubClientLLHandle, deviceTwinCallback, userContextCallback); 00878 if (result != IOTHUB_CLIENT_OK) 00879 { 00880 LogError("IoTHubClient_LL_SetDeviceTwinCallback failed"); 00881 } 00882 } 00883 00884 (void)Unlock(iotHubClientInstance->LockHandle); 00885 } 00886 } 00887 return result; 00888 } 00889 00890 IOTHUB_CLIENT_RESULT IoTHubClient_SendReportedState(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const unsigned char* reportedState, size_t size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK reportedStateCallback, void* userContextCallback) 00891 { 00892 IOTHUB_CLIENT_RESULT result; 00893 00894 /*Codes_SRS_IOTHUBCLIENT_10_013: [** If `iotHubClientHandle` is `NULL`, `IoTHubClient_SendReportedState` shall return `IOTHUB_CLIENT_INVALID_ARG`. ]*/ 00895 if (iotHubClientHandle == NULL) 00896 { 00897 result = IOTHUB_CLIENT_INVALID_ARG; 00898 LogError("invalid arg (NULL)"); 00899 } 00900 else 00901 { 00902 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00903 00904 /*Codes_SRS_IOTHUBCLIENT_10_021: [** `IoTHubClient_SendReportedState` shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/ 00905 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00906 { 00907 /*Codes_SRS_IOTHUBCLIENT_10_014: [** If acquiring the lock fails, `IoTHubClient_SendReportedState` shall return `IOTHUB_CLIENT_ERROR`. ]*/ 00908 result = IOTHUB_CLIENT_ERROR; 00909 LogError("Could not acquire lock"); 00910 } 00911 else 00912 { 00913 /*Codes_SRS_IOTHUBCLIENT_10_015: [** If the transport connection is shared, the thread shall be started by calling `IoTHubTransport_StartWorkerThread`. ]*/ 00914 if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) 00915 { 00916 /*Codes_SRS_IOTHUBCLIENT_10_016: [** If starting the thread fails, `IoTHubClient_SendReportedState` shall return `IOTHUB_CLIENT_ERROR`. ]*/ 00917 result = IOTHUB_CLIENT_ERROR; 00918 LogError("Could not start worker thread"); 00919 } 00920 else 00921 { 00922 /*Codes_SRS_IOTHUBCLIENT_10_017: [** `IoTHubClient_SendReportedState` shall call `IoTHubClient_LL_SendReportedState`, while passing the `IoTHubClient_LL handle` created by `IoTHubClient_LL_Create` along with the parameters `reportedState`, `size`, `reportedStateCallback`, and `userContextCallback`. ]*/ 00923 /*Codes_SRS_IOTHUBCLIENT_10_018: [** When `IoTHubClient_LL_SendReportedState` is called, `IoTHubClient_SendReportedState` shall return the result of `IoTHubClient_LL_SendReportedState`. **]*/ 00924 result = IoTHubClient_LL_SendReportedState(iotHubClientInstance->IoTHubClientLLHandle, reportedState, size, reportedStateCallback, userContextCallback); 00925 if (result != IOTHUB_CLIENT_OK) 00926 { 00927 LogError("IoTHubClient_LL_SendReportedState failed"); 00928 } 00929 } 00930 00931 (void)Unlock(iotHubClientInstance->LockHandle); 00932 } 00933 } 00934 return result; 00935 } 00936 00937 IOTHUB_CLIENT_RESULT IoTHubClient_SetDeviceMethodCallback(IOTHUB_CLIENT_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC deviceMethodCallback, void* userContextCallback) 00938 { 00939 IOTHUB_CLIENT_RESULT result; 00940 00941 /*Codes_SRS_IOTHUBCLIENT_12_012: [ If iotHubClientHandle is NULL, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_INVALID_ARG. ]*/ 00942 if (iotHubClientHandle == NULL) 00943 { 00944 result = IOTHUB_CLIENT_INVALID_ARG; 00945 LogError("invalid arg (NULL)"); 00946 } 00947 else 00948 { 00949 IOTHUB_CLIENT_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 00950 00951 /*Codes_SRS_IOTHUBCLIENT_12_018: [ IoTHubClient_SetDeviceMethodCallback shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/ 00952 if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) 00953 { 00954 /*Codes_SRS_IOTHUBCLIENT_12_013: [ If acquiring the lock fails, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_ERROR. ]*/ 00955 result = IOTHUB_CLIENT_ERROR; 00956 LogError("Could not acquire lock"); 00957 } 00958 else 00959 { 00960 /*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. ]*/ 00961 if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) 00962 { 00963 /*Codes_SRS_IOTHUBCLIENT_12_015: [ If starting the thread fails, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_ERROR. ]*/ 00964 result = IOTHUB_CLIENT_ERROR; 00965 LogError("Could not start worker thread"); 00966 } 00967 else 00968 { 00969 /*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. ]*/ 00970 /*Codes_SRS_IOTHUBCLIENT_12_017: [ When IoTHubClient_LL_SetDeviceMethodCallback is called, IoTHubClient_SetDeviceMethodCallback shall return the result of IoTHubClient_LL_SetDeviceMethodCallback. ]*/ 00971 result = IoTHubClient_LL_SetDeviceMethodCallback(iotHubClientInstance->IoTHubClientLLHandle, deviceMethodCallback, userContextCallback); 00972 if (result != IOTHUB_CLIENT_OK) 00973 { 00974 LogError("IoTHubClient_LL_SetDeviceMethodCallback failed"); 00975 } 00976 } 00977 00978 (void)Unlock(iotHubClientInstance->LockHandle); 00979 } 00980 } 00981 return result; 00982 } 00983 00984 00985 #ifndef DONT_USE_UPLOADTOBLOB 00986 static int uploadingThread(void *data) 00987 { 00988 UPLOADTOBLOB_SAVED_DATA* savedData = (UPLOADTOBLOB_SAVED_DATA*)data; 00989 00990 /*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*/ 00991 /*not having it protected means multiple simultaneous uploads can happen*/ 00992 /*Codes_SRS_IOTHUBCLIENT_02_054: [ The thread shall call IoTHubClient_LL_UploadToBlob passing the information packed in the structure. ]*/ 00993 if (IoTHubClient_LL_UploadToBlob(savedData->iotHubClientHandle->IoTHubClientLLHandle, savedData->destinationFileName, savedData->source, savedData->size) != IOTHUB_CLIENT_OK) 00994 { 00995 LogError("unable to IoTHubClient_LL_UploadToBlob"); 00996 /*call the callback*/ 00997 if (savedData->iotHubClientFileUploadCallback != NULL) 00998 { 00999 /*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. ]*/ 01000 savedData->iotHubClientFileUploadCallback(FILE_UPLOAD_ERROR, savedData->context); 01001 } 01002 } 01003 else 01004 { 01005 if (savedData->iotHubClientFileUploadCallback != NULL) 01006 { 01007 /*Codes_SRS_IOTHUBCLIENT_02_056: [ Otherwise the thread iotHubClientFileUploadCallbackInternal passing as result FILE_UPLOAD_OK and the structure from SRS IOTHUBCLIENT 02 051. ]*/ 01008 savedData->iotHubClientFileUploadCallback(FILE_UPLOAD_OK, savedData->context); 01009 } 01010 } 01011 01012 /*Codes_SRS_IOTHUBCLIENT_02_071: [ The thread shall mark itself as disposable. ]*/ 01013 if (Lock(savedData->lockGarbage) != LOCK_OK) 01014 { 01015 LogError("unable to Lock - trying anyway"); 01016 savedData->canBeGarbageCollected = 1; 01017 } 01018 else 01019 { 01020 savedData->canBeGarbageCollected = 1; 01021 01022 if (Unlock(savedData->lockGarbage) != LOCK_OK) 01023 { 01024 LogError("unable to Unlock after locking"); 01025 } 01026 } 01027 return 0; 01028 } 01029 #endif 01030 01031 #ifndef DONT_USE_UPLOADTOBLOB 01032 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) 01033 { 01034 IOTHUB_CLIENT_RESULT result; 01035 /*Codes_SRS_IOTHUBCLIENT_02_047: [ If iotHubClientHandle is NULL then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/ 01036 /*Codes_SRS_IOTHUBCLIENT_02_048: [ If destinationFileName is NULL then IoTHubClient_UploadToBlobAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/ 01037 /*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. ]*/ 01038 if ( 01039 (iotHubClientHandle == NULL) || 01040 (destinationFileName == NULL) || 01041 ((source == NULL) && (size > 0)) 01042 ) 01043 { 01044 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", 01045 iotHubClientHandle, 01046 destinationFileName, 01047 source, 01048 size, 01049 iotHubClientFileUploadCallback, 01050 context 01051 ); 01052 result = IOTHUB_CLIENT_INVALID_ARG; 01053 } 01054 else 01055 { 01056 /*Codes_SRS_IOTHUBCLIENT_02_051: [IoTHubClient_UploadToBlobAsync shall copy the souce, size, iotHubClientFileUploadCallback, context into a structure.]*/ 01057 UPLOADTOBLOB_SAVED_DATA *savedData = (UPLOADTOBLOB_SAVED_DATA *)malloc(sizeof(UPLOADTOBLOB_SAVED_DATA)); 01058 if (savedData == NULL) 01059 { 01060 /*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. ]*/ 01061 LogError("unable to malloc - oom"); 01062 result = IOTHUB_CLIENT_ERROR; 01063 } 01064 else 01065 { 01066 if (mallocAndStrcpy_s((char**)&savedData->destinationFileName, destinationFileName) != 0) 01067 { 01068 /*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. ]*/ 01069 LogError("unable to mallocAndStrcpy_s"); 01070 free(savedData); 01071 result = IOTHUB_CLIENT_ERROR; 01072 } 01073 else 01074 { 01075 savedData->size = size; 01076 int sourceCloned; 01077 if (size == 0) 01078 { 01079 savedData->source = NULL; 01080 sourceCloned = 1; 01081 } 01082 else 01083 { 01084 savedData->source = (unsigned char*)malloc(size); 01085 if (savedData->source == NULL) 01086 { 01087 /*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. ]*/ 01088 LogError("unable to malloc - oom"); 01089 free(savedData->destinationFileName); 01090 free(savedData); 01091 sourceCloned = 0; 01092 01093 } 01094 else 01095 { 01096 sourceCloned = 1; 01097 } 01098 } 01099 01100 if (sourceCloned == 0) 01101 { 01102 result = IOTHUB_CLIENT_ERROR; 01103 } 01104 else 01105 { 01106 savedData->iotHubClientFileUploadCallback = iotHubClientFileUploadCallback; 01107 savedData->context = context; 01108 memcpy(savedData->source, source, size); 01109 IOTHUB_CLIENT_INSTANCE* iotHubClientHandleData = (IOTHUB_CLIENT_INSTANCE*)iotHubClientHandle; 01110 if (Lock(iotHubClientHandleData->LockHandle) != LOCK_OK) /*locking because the next statement is changing blobThreadsToBeJoined*/ 01111 { 01112 LogError("unable to lock"); 01113 free(savedData->source); 01114 free(savedData->destinationFileName); 01115 free(savedData); 01116 result = IOTHUB_CLIENT_ERROR; 01117 } 01118 else 01119 { 01120 if ((result = StartWorkerThreadIfNeeded(iotHubClientHandleData)) != IOTHUB_CLIENT_OK) 01121 { 01122 free(savedData->source); 01123 free(savedData->destinationFileName); 01124 free(savedData); 01125 result = IOTHUB_CLIENT_ERROR; 01126 LogError("Could not start worker thread"); 01127 } 01128 else 01129 { 01130 /*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. ]*/ 01131 LIST_ITEM_HANDLE item = singlylinkedlist_add(iotHubClientHandleData->savedDataToBeCleaned, savedData); 01132 if (item == NULL) 01133 { 01134 LogError("unable to singlylinkedlist_add"); 01135 free(savedData->source); 01136 free(savedData->destinationFileName); 01137 free(savedData); 01138 result = IOTHUB_CLIENT_ERROR; 01139 } 01140 else 01141 { 01142 savedData->iotHubClientHandle = iotHubClientHandle; 01143 savedData->canBeGarbageCollected = 0; 01144 if ((savedData->lockGarbage = Lock_Init()) == NULL) 01145 { 01146 (void)singlylinkedlist_remove(iotHubClientHandleData->savedDataToBeCleaned, item); 01147 free(savedData->source); 01148 free(savedData->destinationFileName); 01149 free(savedData); 01150 result = IOTHUB_CLIENT_ERROR; 01151 LogError("unable to Lock_Init"); 01152 } 01153 else 01154 { 01155 /*Codes_SRS_IOTHUBCLIENT_02_052: [ IoTHubClient_UploadToBlobAsync shall spawn a thread passing the structure build in SRS IOTHUBCLIENT 02 051 as thread data.]*/ 01156 if (ThreadAPI_Create(&savedData->uploadingThreadHandle, uploadingThread, savedData) != THREADAPI_OK) 01157 { 01158 /*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. ]*/ 01159 LogError("unablet to ThreadAPI_Create"); 01160 (void)Lock_Deinit(savedData->lockGarbage); 01161 (void)singlylinkedlist_remove(iotHubClientHandleData->savedDataToBeCleaned, item); 01162 free(savedData->source); 01163 free(savedData->destinationFileName); 01164 free(savedData); 01165 result = IOTHUB_CLIENT_ERROR; 01166 } 01167 else 01168 { 01169 01170 result = IOTHUB_CLIENT_OK; 01171 } 01172 } 01173 } 01174 } 01175 (void)Unlock(iotHubClientHandleData->LockHandle); 01176 } 01177 } 01178 } 01179 } 01180 } 01181 return result; 01182 } 01183 #endif /*DONT_USE_UPLOADTOBLOB*/
Generated on Wed Jul 13 2022 07:19:04 by
1.7.2