Microsoft Azure IoTHub client libraries

Dependents:   sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp f767zi_mqtt ... more

This library implements the Microsoft Azure IoTHub client library. The code is replicated from https://github.com/Azure/azure-iot-sdks

Committer:
AzureIoTClient
Date:
Mon Jun 11 15:39:23 2018 -0700
Revision:
88:248736be106e
Parent:
71:0d498da5ece1
Child:
89:a2ed767a532e
1.2.5

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Azure.IoT Build 37:18310e4d888d 1 // Copyright (c) Microsoft. All rights reserved.
Azure.IoT Build 37:18310e4d888d 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
Azure.IoT Build 37:18310e4d888d 3
Azure.IoT Build 37:18310e4d888d 4 #include <stdlib.h>
Azure.IoT Build 37:18310e4d888d 5 #include <signal.h>
Azure.IoT Build 37:18310e4d888d 6 #include <stddef.h>
AzureIoTClient 88:248736be106e 7 #include "azure_c_shared_utility/gballoc.h"
Azure.IoT Build 38:a05929a75111 8 #include "azure_c_shared_utility/crt_abstractions.h"
Azure.IoT Build 38:a05929a75111 9 #include "azure_c_shared_utility/threadapi.h"
Azure.IoT Build 38:a05929a75111 10 #include "azure_c_shared_utility/lock.h"
Azure.IoT Build 45:54c11b1b1407 11 #include "azure_c_shared_utility/xlogging.h"
Azure.IoT Build 38:a05929a75111 12 #include "azure_c_shared_utility/vector.h"
Azure.IoT Build 37:18310e4d888d 13
AzureIoTClient 88:248736be106e 14 #include "internal/iothubtransport.h"
AzureIoTClient 88:248736be106e 15 #include "internal/iothub_client_private.h"
AzureIoTClient 88:248736be106e 16 #include "iothub_transport_ll.h"
AzureIoTClient 88:248736be106e 17 #include "iothub_client_core.h"
AzureIoTClient 88:248736be106e 18
Azure.IoT Build 37:18310e4d888d 19 typedef struct TRANSPORT_HANDLE_DATA_TAG
Azure.IoT Build 37:18310e4d888d 20 {
AzureIoTClient 66:a419827cb051 21 TRANSPORT_LL_HANDLE transportLLHandle;
Azure.IoT Build 37:18310e4d888d 22 THREAD_HANDLE workerThreadHandle;
Azure.IoT Build 37:18310e4d888d 23 LOCK_HANDLE lockHandle;
Azure.IoT Build 37:18310e4d888d 24 sig_atomic_t stopThread;
AzureIoTClient 66:a419827cb051 25 TRANSPORT_PROVIDER_FIELDS;
AzureIoTClient 66:a419827cb051 26 VECTOR_HANDLE clients;
AzureIoTClient 66:a419827cb051 27 LOCK_HANDLE clientsLockHandle;
AzureIoTClient 66:a419827cb051 28 IOTHUB_CLIENT_MULTIPLEXED_DO_WORK clientDoWork;
Azure.IoT Build 37:18310e4d888d 29 } TRANSPORT_HANDLE_DATA;
Azure.IoT Build 37:18310e4d888d 30
Azure.IoT Build 37:18310e4d888d 31 /* Used for Unit test */
Azure.IoT Build 37:18310e4d888d 32 const size_t IoTHubTransport_ThreadTerminationOffset = offsetof(TRANSPORT_HANDLE_DATA, stopThread);
Azure.IoT Build 37:18310e4d888d 33
AzureIoTClient 88:248736be106e 34 TRANSPORT_HANDLE IoTHubTransport_Create(IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol, const char* iotHubName, const char* iotHubSuffix)
Azure.IoT Build 37:18310e4d888d 35 {
AzureIoTClient 66:a419827cb051 36 TRANSPORT_HANDLE_DATA *result;
Azure.IoT Build 37:18310e4d888d 37
AzureIoTClient 66:a419827cb051 38 if (protocol == NULL || iotHubName == NULL || iotHubSuffix == NULL)
AzureIoTClient 66:a419827cb051 39 {
AzureIoTClient 66:a419827cb051 40 /*Codes_SRS_IOTHUBTRANSPORT_17_002: [ If protocol is NULL, this function shall return NULL. ]*/
AzureIoTClient 66:a419827cb051 41 /*Codes_SRS_IOTHUBTRANSPORT_17_003: [ If iotHubName is NULL, this function shall return NULL. ]*/
AzureIoTClient 66:a419827cb051 42 /*Codes_SRS_IOTHUBTRANSPORT_17_004: [ If iotHubSuffix is NULL, this function shall return NULL. ]*/
AzureIoTClient 66:a419827cb051 43 LogError("Invalid NULL argument, protocol [%p], name [%p], suffix [%p].", protocol, iotHubName, iotHubSuffix);
AzureIoTClient 66:a419827cb051 44 result = NULL;
AzureIoTClient 66:a419827cb051 45 }
AzureIoTClient 66:a419827cb051 46 else
AzureIoTClient 66:a419827cb051 47 {
AzureIoTClient 66:a419827cb051 48 /*Codes_SRS_IOTHUBTRANSPORT_17_032: [ IoTHubTransport_Create shall allocate memory for the transport data. ]*/
AzureIoTClient 66:a419827cb051 49 result = (TRANSPORT_HANDLE_DATA*)malloc(sizeof(TRANSPORT_HANDLE_DATA));
AzureIoTClient 66:a419827cb051 50 if (result == NULL)
AzureIoTClient 66:a419827cb051 51 {
AzureIoTClient 66:a419827cb051 52 /*Codes_SRS_IOTHUBTRANSPORT_17_040: [ If memory allocation fails, IoTHubTransport_Create shall return NULL. ]*/
AzureIoTClient 66:a419827cb051 53 LogError("Transport handle was not allocated.");
AzureIoTClient 66:a419827cb051 54 }
AzureIoTClient 66:a419827cb051 55 else
AzureIoTClient 66:a419827cb051 56 {
AzureIoTClient 66:a419827cb051 57 TRANSPORT_PROVIDER * transportProtocol = (TRANSPORT_PROVIDER*)(protocol());
AzureIoTClient 66:a419827cb051 58 IOTHUB_CLIENT_CONFIG upperConfig;
AzureIoTClient 66:a419827cb051 59 upperConfig.deviceId = NULL;
AzureIoTClient 66:a419827cb051 60 upperConfig.deviceKey = NULL;
AzureIoTClient 66:a419827cb051 61 upperConfig.iotHubName = iotHubName;
AzureIoTClient 66:a419827cb051 62 upperConfig.iotHubSuffix = iotHubSuffix;
AzureIoTClient 66:a419827cb051 63 upperConfig.protocol = protocol;
AzureIoTClient 66:a419827cb051 64 upperConfig.protocolGatewayHostName = NULL;
Azure.IoT Build 37:18310e4d888d 65
AzureIoTClient 66:a419827cb051 66 IOTHUBTRANSPORT_CONFIG transportLLConfig;
AzureIoTClient 66:a419827cb051 67 memset(&transportLLConfig, 0, sizeof(IOTHUBTRANSPORT_CONFIG));
AzureIoTClient 66:a419827cb051 68 transportLLConfig.upperConfig = &upperConfig;
AzureIoTClient 66:a419827cb051 69 transportLLConfig.waitingToSend = NULL;
Azure.IoT Build 37:18310e4d888d 70
AzureIoTClient 66:a419827cb051 71 /*Codes_SRS_IOTHUBTRANSPORT_17_005: [ IoTHubTransport_Create shall create the lower layer transport by calling the protocol's IoTHubTransport_Create function. ]*/
AzureIoTClient 66:a419827cb051 72 result->transportLLHandle = transportProtocol->IoTHubTransport_Create(&transportLLConfig);
AzureIoTClient 66:a419827cb051 73 if (result->transportLLHandle == NULL)
AzureIoTClient 66:a419827cb051 74 {
AzureIoTClient 66:a419827cb051 75 /*Codes_SRS_IOTHUBTRANSPORT_17_006: [ If the creation of the transport fails, IoTHubTransport_Create shall return NULL. ]*/
AzureIoTClient 66:a419827cb051 76 LogError("Lower Layer transport not created.");
AzureIoTClient 66:a419827cb051 77 free(result);
AzureIoTClient 66:a419827cb051 78 result = NULL;
AzureIoTClient 66:a419827cb051 79 }
AzureIoTClient 66:a419827cb051 80 else
AzureIoTClient 66:a419827cb051 81 {
AzureIoTClient 66:a419827cb051 82 /*Codes_SRS_IOTHUBTRANSPORT_17_007: [ IoTHubTransport_Create shall create the transport lock by Calling Lock_Init. ]*/
AzureIoTClient 66:a419827cb051 83 result->lockHandle = Lock_Init();
AzureIoTClient 66:a419827cb051 84 if (result->lockHandle == NULL)
AzureIoTClient 66:a419827cb051 85 {
AzureIoTClient 66:a419827cb051 86 /*Codes_SRS_IOTHUBTRANSPORT_17_008: [ If the lock creation fails, IoTHubTransport_Create shall return NULL. ]*/
AzureIoTClient 66:a419827cb051 87 LogError("transport Lock not created.");
AzureIoTClient 66:a419827cb051 88 transportProtocol->IoTHubTransport_Destroy(result->transportLLHandle);
AzureIoTClient 66:a419827cb051 89 free(result);
AzureIoTClient 66:a419827cb051 90 result = NULL;
AzureIoTClient 66:a419827cb051 91 }
AzureIoTClient 66:a419827cb051 92 else if ((result->clientsLockHandle = Lock_Init()) == NULL)
AzureIoTClient 66:a419827cb051 93 {
AzureIoTClient 66:a419827cb051 94 LogError("clients Lock not created.");
AzureIoTClient 66:a419827cb051 95 Lock_Deinit(result->lockHandle);
AzureIoTClient 66:a419827cb051 96 transportProtocol->IoTHubTransport_Destroy(result->transportLLHandle);
AzureIoTClient 66:a419827cb051 97 free(result);
AzureIoTClient 66:a419827cb051 98 result = NULL;
AzureIoTClient 66:a419827cb051 99 }
AzureIoTClient 66:a419827cb051 100 else
AzureIoTClient 66:a419827cb051 101 {
AzureIoTClient 88:248736be106e 102 /*Codes_SRS_IOTHUBTRANSPORT_17_038: [ IoTHubTransport_Create shall call VECTOR_Create to make a list of IOTHUB_CLIENT_CORE_HANDLE using this transport. ]*/
AzureIoTClient 88:248736be106e 103 result->clients = VECTOR_create(sizeof(IOTHUB_CLIENT_CORE_HANDLE));
AzureIoTClient 66:a419827cb051 104 if (result->clients == NULL)
AzureIoTClient 66:a419827cb051 105 {
AzureIoTClient 66:a419827cb051 106 /*Codes_SRS_IOTHUBTRANSPORT_17_039: [ If the Vector creation fails, IoTHubTransport_Create shall return NULL. ]*/
AzureIoTClient 66:a419827cb051 107 /*Codes_SRS_IOTHUBTRANSPORT_17_009: [ IoTHubTransport_Create shall clean up any resources it creates if the function does not succeed. ]*/
AzureIoTClient 66:a419827cb051 108 LogError("clients list not created.");
AzureIoTClient 66:a419827cb051 109 Lock_Deinit(result->clientsLockHandle);
AzureIoTClient 66:a419827cb051 110 Lock_Deinit(result->lockHandle);
AzureIoTClient 66:a419827cb051 111 transportProtocol->IoTHubTransport_Destroy(result->transportLLHandle);
AzureIoTClient 66:a419827cb051 112 free(result);
AzureIoTClient 66:a419827cb051 113 result = NULL;
AzureIoTClient 66:a419827cb051 114 }
AzureIoTClient 66:a419827cb051 115 else
AzureIoTClient 66:a419827cb051 116 {
AzureIoTClient 66:a419827cb051 117 /*Codes_SRS_IOTHUBTRANSPORT_17_001: [ IoTHubTransport_Create shall return a non-NULL handle on success.]*/
AzureIoTClient 66:a419827cb051 118 result->stopThread = 1;
AzureIoTClient 66:a419827cb051 119 result->clientDoWork = NULL;
AzureIoTClient 66:a419827cb051 120 result->workerThreadHandle = NULL; /* create thread when work needs to be done */
AzureIoTClient 43:038d8511e817 121 result->IoTHubTransport_GetHostname = transportProtocol->IoTHubTransport_GetHostname;
AzureIoTClient 66:a419827cb051 122 result->IoTHubTransport_SetOption = transportProtocol->IoTHubTransport_SetOption;
AzureIoTClient 66:a419827cb051 123 result->IoTHubTransport_Create = transportProtocol->IoTHubTransport_Create;
AzureIoTClient 66:a419827cb051 124 result->IoTHubTransport_Destroy = transportProtocol->IoTHubTransport_Destroy;
AzureIoTClient 66:a419827cb051 125 result->IoTHubTransport_Register = transportProtocol->IoTHubTransport_Register;
AzureIoTClient 66:a419827cb051 126 result->IoTHubTransport_Unregister = transportProtocol->IoTHubTransport_Unregister;
AzureIoTClient 66:a419827cb051 127 result->IoTHubTransport_Subscribe = transportProtocol->IoTHubTransport_Subscribe;
AzureIoTClient 66:a419827cb051 128 result->IoTHubTransport_Unsubscribe = transportProtocol->IoTHubTransport_Unsubscribe;
AzureIoTClient 66:a419827cb051 129 result->IoTHubTransport_DoWork = transportProtocol->IoTHubTransport_DoWork;
AzureIoTClient 53:1e5a1ca1f274 130 result->IoTHubTransport_SetRetryPolicy = transportProtocol->IoTHubTransport_SetRetryPolicy;
AzureIoTClient 66:a419827cb051 131 result->IoTHubTransport_GetSendStatus = transportProtocol->IoTHubTransport_GetSendStatus;
AzureIoTClient 66:a419827cb051 132 }
AzureIoTClient 66:a419827cb051 133 }
AzureIoTClient 66:a419827cb051 134 }
AzureIoTClient 66:a419827cb051 135 }
AzureIoTClient 66:a419827cb051 136 }
AzureIoTClient 66:a419827cb051 137
AzureIoTClient 66:a419827cb051 138 return result;
AzureIoTClient 66:a419827cb051 139 }
AzureIoTClient 66:a419827cb051 140
AzureIoTClient 66:a419827cb051 141 static void multiplexed_client_do_work(TRANSPORT_HANDLE_DATA* transportData)
AzureIoTClient 66:a419827cb051 142 {
AzureIoTClient 66:a419827cb051 143 if (Lock(transportData->clientsLockHandle) != LOCK_OK)
AzureIoTClient 66:a419827cb051 144 {
AzureIoTClient 66:a419827cb051 145 LogError("failed to lock for multiplexed_client_do_work");
AzureIoTClient 66:a419827cb051 146 }
AzureIoTClient 66:a419827cb051 147 else
AzureIoTClient 66:a419827cb051 148 {
AzureIoTClient 66:a419827cb051 149 size_t numberOfClients;
AzureIoTClient 66:a419827cb051 150 size_t iterator;
AzureIoTClient 66:a419827cb051 151
AzureIoTClient 66:a419827cb051 152 numberOfClients = VECTOR_size(transportData->clients);
AzureIoTClient 66:a419827cb051 153 for (iterator = 0; iterator < numberOfClients; iterator++)
AzureIoTClient 66:a419827cb051 154 {
AzureIoTClient 88:248736be106e 155 IOTHUB_CLIENT_CORE_HANDLE* clientHandle = (IOTHUB_CLIENT_CORE_HANDLE*)VECTOR_element(transportData->clients, iterator);
AzureIoTClient 66:a419827cb051 156
AzureIoTClient 66:a419827cb051 157 if (clientHandle != NULL)
AzureIoTClient 66:a419827cb051 158 {
AzureIoTClient 66:a419827cb051 159 transportData->clientDoWork(*clientHandle);
AzureIoTClient 66:a419827cb051 160 }
AzureIoTClient 66:a419827cb051 161 }
AzureIoTClient 66:a419827cb051 162
AzureIoTClient 66:a419827cb051 163 if (Unlock(transportData->clientsLockHandle) != LOCK_OK)
AzureIoTClient 66:a419827cb051 164 {
AzureIoTClient 66:a419827cb051 165 LogError("failed to unlock on multiplexed_client_do_work");
AzureIoTClient 66:a419827cb051 166 }
AzureIoTClient 66:a419827cb051 167 }
Azure.IoT Build 37:18310e4d888d 168 }
Azure.IoT Build 37:18310e4d888d 169
Azure.IoT Build 37:18310e4d888d 170 static int transport_worker_thread(void* threadArgument)
Azure.IoT Build 37:18310e4d888d 171 {
AzureIoTClient 66:a419827cb051 172 TRANSPORT_HANDLE_DATA* transportData = (TRANSPORT_HANDLE_DATA*)threadArgument;
Azure.IoT Build 37:18310e4d888d 173
AzureIoTClient 66:a419827cb051 174 while (1)
AzureIoTClient 66:a419827cb051 175 {
AzureIoTClient 66:a419827cb051 176 /*Codes_SRS_IOTHUBTRANSPORT_17_030: [ All calls to lower layer transport DoWork shall be protected by the lock created in IoTHubTransport_Create. ]*/
AzureIoTClient 66:a419827cb051 177 if (Lock(transportData->lockHandle) == LOCK_OK)
AzureIoTClient 66:a419827cb051 178 {
AzureIoTClient 66:a419827cb051 179 /*Codes_SRS_IOTHUBTRANSPORT_17_031: [ If acquiring the lock fails, lower layer transport DoWork shall not be called. ]*/
AzureIoTClient 66:a419827cb051 180 if (transportData->stopThread)
AzureIoTClient 66:a419827cb051 181 {
AzureIoTClient 66:a419827cb051 182 /*Codes_SRS_IOTHUBTRANSPORT_17_028: [ The thread shall exit when IoTHubTransport_EndWorkerThread has been called for each clientHandle which invoked IoTHubTransport_StartWorkerThread. ]*/
AzureIoTClient 66:a419827cb051 183 (void)Unlock(transportData->lockHandle);
AzureIoTClient 66:a419827cb051 184 break;
AzureIoTClient 66:a419827cb051 185 }
AzureIoTClient 66:a419827cb051 186 else
AzureIoTClient 66:a419827cb051 187 {
AzureIoTClient 66:a419827cb051 188 (transportData->IoTHubTransport_DoWork)(transportData->transportLLHandle, NULL);
Azure.IoT Build 37:18310e4d888d 189
AzureIoTClient 66:a419827cb051 190 (void)Unlock(transportData->lockHandle);
AzureIoTClient 66:a419827cb051 191 }
AzureIoTClient 66:a419827cb051 192 }
AzureIoTClient 66:a419827cb051 193
AzureIoTClient 66:a419827cb051 194 multiplexed_client_do_work(transportData);
AzureIoTClient 66:a419827cb051 195
AzureIoTClient 66:a419827cb051 196 /*Codes_SRS_IOTHUBTRANSPORT_17_029: [ The thread shall call lower layer transport DoWork every 1 ms. ]*/
AzureIoTClient 66:a419827cb051 197 ThreadAPI_Sleep(1);
AzureIoTClient 66:a419827cb051 198 }
AzureIoTClient 66:a419827cb051 199
AzureIoTClient 71:0d498da5ece1 200 ThreadAPI_Exit(0);
AzureIoTClient 66:a419827cb051 201 return 0;
Azure.IoT Build 37:18310e4d888d 202 }
Azure.IoT Build 37:18310e4d888d 203
Azure.IoT Build 37:18310e4d888d 204 static bool find_by_handle(const void* element, const void* value)
Azure.IoT Build 37:18310e4d888d 205 {
AzureIoTClient 66:a419827cb051 206 /* data stored at element is device handle */
AzureIoTClient 88:248736be106e 207 const IOTHUB_CLIENT_CORE_HANDLE * guess = (const IOTHUB_CLIENT_CORE_HANDLE *)element;
AzureIoTClient 88:248736be106e 208 const IOTHUB_CLIENT_CORE_HANDLE match = (const IOTHUB_CLIENT_CORE_HANDLE)value;
AzureIoTClient 66:a419827cb051 209 return (*guess == match);
Azure.IoT Build 37:18310e4d888d 210 }
Azure.IoT Build 37:18310e4d888d 211
AzureIoTClient 88:248736be106e 212 static IOTHUB_CLIENT_RESULT start_worker_if_needed(TRANSPORT_HANDLE_DATA * transportData, IOTHUB_CLIENT_CORE_HANDLE clientHandle)
Azure.IoT Build 37:18310e4d888d 213 {
AzureIoTClient 66:a419827cb051 214 IOTHUB_CLIENT_RESULT result;
AzureIoTClient 66:a419827cb051 215 if (transportData->workerThreadHandle == NULL)
AzureIoTClient 66:a419827cb051 216 {
AzureIoTClient 66:a419827cb051 217 /*Codes_SRS_IOTHUBTRANSPORT_17_018: [ If the worker thread does not exist, IoTHubTransport_StartWorkerThread shall start the thread using ThreadAPI_Create. ]*/
AzureIoTClient 66:a419827cb051 218 transportData->stopThread = 0;
AzureIoTClient 66:a419827cb051 219 if (ThreadAPI_Create(&transportData->workerThreadHandle, transport_worker_thread, transportData) != THREADAPI_OK)
AzureIoTClient 66:a419827cb051 220 {
AzureIoTClient 66:a419827cb051 221 transportData->workerThreadHandle = NULL;
AzureIoTClient 66:a419827cb051 222 }
AzureIoTClient 66:a419827cb051 223 }
AzureIoTClient 66:a419827cb051 224 if (transportData->workerThreadHandle != NULL)
AzureIoTClient 66:a419827cb051 225 {
AzureIoTClient 66:a419827cb051 226 if (Lock(transportData->clientsLockHandle) != LOCK_OK)
AzureIoTClient 66:a419827cb051 227 {
AzureIoTClient 66:a419827cb051 228 LogError("failed to lock for start_worker_if_needed");
AzureIoTClient 66:a419827cb051 229 result = IOTHUB_CLIENT_ERROR;
AzureIoTClient 66:a419827cb051 230 }
AzureIoTClient 66:a419827cb051 231 else
AzureIoTClient 66:a419827cb051 232 {
AzureIoTClient 66:a419827cb051 233 /*Codes_SRS_IOTHUBTRANSPORT_17_020: [ IoTHubTransport_StartWorkerThread shall search for IoTHubClient clientHandle in the list of IoTHubClient handles. ]*/
AzureIoTClient 66:a419827cb051 234 bool addToList = ((VECTOR_size(transportData->clients) == 0) || (VECTOR_find_if(transportData->clients, find_by_handle, clientHandle) == NULL));
AzureIoTClient 66:a419827cb051 235 if (addToList)
AzureIoTClient 66:a419827cb051 236 {
AzureIoTClient 66:a419827cb051 237 /*Codes_SRS_IOTHUBTRANSPORT_17_021: [ If handle is not found, then clientHandle shall be added to the list. ]*/
AzureIoTClient 66:a419827cb051 238 if (VECTOR_push_back(transportData->clients, &clientHandle, 1) != 0)
AzureIoTClient 66:a419827cb051 239 {
AzureIoTClient 66:a419827cb051 240 LogError("Failed adding device to list (VECTOR_push_back failed)");
AzureIoTClient 66:a419827cb051 241 /*Codes_SRS_IOTHUBTRANSPORT_17_042: [ If Adding to the client list fails, IoTHubTransport_StartWorkerThread shall return IOTHUB_CLIENT_ERROR. ]*/
AzureIoTClient 66:a419827cb051 242 result = IOTHUB_CLIENT_ERROR;
AzureIoTClient 66:a419827cb051 243 }
AzureIoTClient 66:a419827cb051 244 else
AzureIoTClient 66:a419827cb051 245 {
AzureIoTClient 66:a419827cb051 246 result = IOTHUB_CLIENT_OK;
AzureIoTClient 66:a419827cb051 247 }
AzureIoTClient 66:a419827cb051 248 }
AzureIoTClient 66:a419827cb051 249 else
AzureIoTClient 66:a419827cb051 250 {
AzureIoTClient 66:a419827cb051 251 result = IOTHUB_CLIENT_OK;
AzureIoTClient 66:a419827cb051 252 }
AzureIoTClient 66:a419827cb051 253
AzureIoTClient 66:a419827cb051 254 if (Unlock(transportData->clientsLockHandle) != LOCK_OK)
AzureIoTClient 66:a419827cb051 255 {
AzureIoTClient 66:a419827cb051 256 LogError("failed to unlock on start_worker_if_needed");
AzureIoTClient 66:a419827cb051 257 }
AzureIoTClient 66:a419827cb051 258 }
AzureIoTClient 66:a419827cb051 259 }
AzureIoTClient 66:a419827cb051 260 else
AzureIoTClient 66:a419827cb051 261 {
AzureIoTClient 66:a419827cb051 262 result = IOTHUB_CLIENT_ERROR;
AzureIoTClient 66:a419827cb051 263 }
AzureIoTClient 66:a419827cb051 264 return result;
Azure.IoT Build 37:18310e4d888d 265 }
Azure.IoT Build 37:18310e4d888d 266
Azure.IoT Build 37:18310e4d888d 267 static void stop_worker_thread(TRANSPORT_HANDLE_DATA * transportData)
Azure.IoT Build 37:18310e4d888d 268 {
AzureIoTClient 66:a419827cb051 269 /*Codes_SRS_IOTHUBTRANSPORT_17_043: [** IoTHubTransport_SignalEndWorkerThread shall signal the worker thread to end.*/
AzureIoTClient 66:a419827cb051 270 transportData->stopThread = 1;
Azure.IoT Build 37:18310e4d888d 271 }
Azure.IoT Build 37:18310e4d888d 272
Azure.IoT Build 37:18310e4d888d 273 static void wait_worker_thread(TRANSPORT_HANDLE_DATA * transportData)
Azure.IoT Build 37:18310e4d888d 274 {
AzureIoTClient 66:a419827cb051 275 if (transportData->workerThreadHandle != NULL)
AzureIoTClient 66:a419827cb051 276 {
AzureIoTClient 66:a419827cb051 277 int res;
AzureIoTClient 66:a419827cb051 278 /*Codes_SRS_IOTHUBTRANSPORT_17_027: [ If handle list is empty, IoTHubTransport_EndWorkerThread shall be joined. ]*/
AzureIoTClient 66:a419827cb051 279 if (ThreadAPI_Join(transportData->workerThreadHandle, &res) != THREADAPI_OK)
AzureIoTClient 66:a419827cb051 280 {
AzureIoTClient 66:a419827cb051 281 LogError("ThreadAPI_Join failed");
AzureIoTClient 66:a419827cb051 282 }
AzureIoTClient 66:a419827cb051 283 else
AzureIoTClient 66:a419827cb051 284 {
AzureIoTClient 66:a419827cb051 285 transportData->workerThreadHandle = NULL;
AzureIoTClient 66:a419827cb051 286 }
AzureIoTClient 66:a419827cb051 287 }
Azure.IoT Build 37:18310e4d888d 288 }
Azure.IoT Build 37:18310e4d888d 289
AzureIoTClient 88:248736be106e 290 static bool signal_end_worker_thread(TRANSPORT_HANDLE_DATA * transportData, IOTHUB_CLIENT_CORE_HANDLE clientHandle)
Azure.IoT Build 37:18310e4d888d 291 {
AzureIoTClient 66:a419827cb051 292 bool okToJoin;
AzureIoTClient 66:a419827cb051 293
AzureIoTClient 66:a419827cb051 294 if (Lock(transportData->clientsLockHandle) != LOCK_OK)
AzureIoTClient 66:a419827cb051 295 {
AzureIoTClient 66:a419827cb051 296 LogError("failed to lock for signal_end_worker_thread");
AzureIoTClient 66:a419827cb051 297 okToJoin = false;
AzureIoTClient 66:a419827cb051 298 }
AzureIoTClient 66:a419827cb051 299 else
AzureIoTClient 66:a419827cb051 300 {
AzureIoTClient 66:a419827cb051 301 void* element = VECTOR_find_if(transportData->clients, find_by_handle, clientHandle);
AzureIoTClient 66:a419827cb051 302 if (element != NULL)
AzureIoTClient 66:a419827cb051 303 {
AzureIoTClient 66:a419827cb051 304 /*Codes_SRS_IOTHUBTRANSPORT_17_026: [ IoTHubTransport_EndWorkerThread shall remove clientHandlehandle from handle list. ]*/
AzureIoTClient 66:a419827cb051 305 VECTOR_erase(transportData->clients, element, 1);
AzureIoTClient 66:a419827cb051 306 }
AzureIoTClient 66:a419827cb051 307 /*Codes_SRS_IOTHUBTRANSPORT_17_025: [ If the worker thread does not exist, then IoTHubTransport_EndWorkerThread shall return. ]*/
AzureIoTClient 66:a419827cb051 308 if (transportData->workerThreadHandle != NULL)
AzureIoTClient 66:a419827cb051 309 {
AzureIoTClient 66:a419827cb051 310 if (VECTOR_size(transportData->clients) == 0)
AzureIoTClient 66:a419827cb051 311 {
AzureIoTClient 66:a419827cb051 312 stop_worker_thread(transportData);
AzureIoTClient 66:a419827cb051 313 okToJoin = true;
AzureIoTClient 66:a419827cb051 314 }
AzureIoTClient 66:a419827cb051 315 else
AzureIoTClient 66:a419827cb051 316 {
AzureIoTClient 66:a419827cb051 317 okToJoin = false;
AzureIoTClient 66:a419827cb051 318 }
AzureIoTClient 66:a419827cb051 319 }
AzureIoTClient 66:a419827cb051 320 else
AzureIoTClient 66:a419827cb051 321 {
AzureIoTClient 66:a419827cb051 322 okToJoin = false;
AzureIoTClient 66:a419827cb051 323 }
AzureIoTClient 66:a419827cb051 324
AzureIoTClient 66:a419827cb051 325 if (Unlock(transportData->clientsLockHandle) != LOCK_OK)
AzureIoTClient 66:a419827cb051 326 {
AzureIoTClient 66:a419827cb051 327 LogError("failed to unlock on signal_end_worker_thread");
AzureIoTClient 66:a419827cb051 328 }
AzureIoTClient 66:a419827cb051 329 }
AzureIoTClient 66:a419827cb051 330 return okToJoin;
Azure.IoT Build 37:18310e4d888d 331 }
Azure.IoT Build 37:18310e4d888d 332
Azure.IoT Build 38:a05929a75111 333 void IoTHubTransport_Destroy(TRANSPORT_HANDLE transportHandle)
Azure.IoT Build 37:18310e4d888d 334 {
AzureIoTClient 66:a419827cb051 335 /*Codes_SRS_IOTHUBTRANSPORT_17_011: [ IoTHubTransport_Destroy shall do nothing if transportHandle is NULL. ]*/
AzureIoTClient 66:a419827cb051 336 if (transportHandle != NULL)
AzureIoTClient 66:a419827cb051 337 {
AzureIoTClient 66:a419827cb051 338 TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
AzureIoTClient 66:a419827cb051 339 /*Codes_SRS_IOTHUBTRANSPORT_17_033: [ IoTHubTransport_Destroy shall lock the transport lock. ]*/
AzureIoTClient 66:a419827cb051 340 if (Lock(transportData->lockHandle) != LOCK_OK)
AzureIoTClient 66:a419827cb051 341 {
AzureIoTClient 66:a419827cb051 342 LogError("Unable to lock - will still attempt to end thread without thread safety");
AzureIoTClient 66:a419827cb051 343 stop_worker_thread(transportData);
AzureIoTClient 66:a419827cb051 344 }
AzureIoTClient 66:a419827cb051 345 else
AzureIoTClient 66:a419827cb051 346 {
AzureIoTClient 66:a419827cb051 347 stop_worker_thread(transportData);
AzureIoTClient 66:a419827cb051 348 (void)Unlock(transportData->lockHandle);
AzureIoTClient 66:a419827cb051 349 }
AzureIoTClient 66:a419827cb051 350 wait_worker_thread(transportData);
AzureIoTClient 66:a419827cb051 351 /*Codes_SRS_IOTHUBTRANSPORT_17_010: [ IoTHubTransport_Destroy shall free all resources. ]*/
AzureIoTClient 66:a419827cb051 352 Lock_Deinit(transportData->lockHandle);
AzureIoTClient 66:a419827cb051 353 (transportData->IoTHubTransport_Destroy)(transportData->transportLLHandle);
AzureIoTClient 66:a419827cb051 354 VECTOR_destroy(transportData->clients);
AzureIoTClient 66:a419827cb051 355 Lock_Deinit(transportData->clientsLockHandle);
AzureIoTClient 66:a419827cb051 356 free(transportHandle);
AzureIoTClient 66:a419827cb051 357 }
Azure.IoT Build 37:18310e4d888d 358 }
Azure.IoT Build 37:18310e4d888d 359
Azure.IoT Build 38:a05929a75111 360 LOCK_HANDLE IoTHubTransport_GetLock(TRANSPORT_HANDLE transportHandle)
Azure.IoT Build 37:18310e4d888d 361 {
AzureIoTClient 66:a419827cb051 362 LOCK_HANDLE lock;
AzureIoTClient 66:a419827cb051 363 if (transportHandle == NULL)
AzureIoTClient 66:a419827cb051 364 {
AzureIoTClient 66:a419827cb051 365 /*Codes_SRS_IOTHUBTRANSPORT_17_013: [ If transportHandle is NULL, IoTHubTransport_GetLock shall return NULL. ]*/
AzureIoTClient 66:a419827cb051 366 lock = NULL;
AzureIoTClient 66:a419827cb051 367 }
AzureIoTClient 66:a419827cb051 368 else
AzureIoTClient 66:a419827cb051 369 {
AzureIoTClient 66:a419827cb051 370 /*Codes_SRS_IOTHUBTRANSPORT_17_012: [ IoTHubTransport_GetLock shall return a handle to the transport lock. ]*/
AzureIoTClient 66:a419827cb051 371 TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
AzureIoTClient 66:a419827cb051 372 lock = transportData->lockHandle;
AzureIoTClient 66:a419827cb051 373 }
AzureIoTClient 66:a419827cb051 374 return lock;
Azure.IoT Build 37:18310e4d888d 375 }
Azure.IoT Build 37:18310e4d888d 376
Azure.IoT Build 38:a05929a75111 377 TRANSPORT_LL_HANDLE IoTHubTransport_GetLLTransport(TRANSPORT_HANDLE transportHandle)
Azure.IoT Build 37:18310e4d888d 378 {
AzureIoTClient 66:a419827cb051 379 TRANSPORT_LL_HANDLE llTransport;
AzureIoTClient 66:a419827cb051 380 if (transportHandle == NULL)
AzureIoTClient 66:a419827cb051 381 {
AzureIoTClient 66:a419827cb051 382 /*Codes_SRS_IOTHUBTRANSPORT_17_015: [ If transportHandle is NULL, IoTHubTransport_GetLLTransport shall return NULL. ]*/
AzureIoTClient 66:a419827cb051 383 llTransport = NULL;
AzureIoTClient 66:a419827cb051 384 }
AzureIoTClient 66:a419827cb051 385 else
AzureIoTClient 66:a419827cb051 386 {
AzureIoTClient 66:a419827cb051 387 /*Codes_SRS_IOTHUBTRANSPORT_17_014: [ IoTHubTransport_GetLLTransport shall return a handle to the lower layer transport. ]*/
AzureIoTClient 66:a419827cb051 388 TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
AzureIoTClient 66:a419827cb051 389 llTransport = transportData->transportLLHandle;
AzureIoTClient 66:a419827cb051 390 }
AzureIoTClient 66:a419827cb051 391 return llTransport;
Azure.IoT Build 37:18310e4d888d 392 }
Azure.IoT Build 37:18310e4d888d 393
AzureIoTClient 88:248736be106e 394 IOTHUB_CLIENT_RESULT IoTHubTransport_StartWorkerThread(TRANSPORT_HANDLE transportHandle, IOTHUB_CLIENT_CORE_HANDLE clientHandle, IOTHUB_CLIENT_MULTIPLEXED_DO_WORK muxDoWork)
Azure.IoT Build 37:18310e4d888d 395 {
AzureIoTClient 66:a419827cb051 396 IOTHUB_CLIENT_RESULT result;
AzureIoTClient 66:a419827cb051 397 if (transportHandle == NULL || clientHandle == NULL)
AzureIoTClient 66:a419827cb051 398 {
AzureIoTClient 66:a419827cb051 399 /*Codes_SRS_IOTHUBTRANSPORT_17_016: [ If transportHandle is NULL, IoTHubTransport_StartWorkerThread shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
AzureIoTClient 66:a419827cb051 400 /*Codes_SRS_IOTHUBTRANSPORT_17_017: [ If clientHandle is NULL, IoTHubTransport_StartWorkerThread shall return IOTHUB_CLIENT_INVALID_ARG. ]*/
AzureIoTClient 66:a419827cb051 401 result = IOTHUB_CLIENT_INVALID_ARG;
AzureIoTClient 66:a419827cb051 402 }
AzureIoTClient 66:a419827cb051 403 else
AzureIoTClient 66:a419827cb051 404 {
AzureIoTClient 66:a419827cb051 405 TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
Azure.IoT Build 37:18310e4d888d 406
AzureIoTClient 66:a419827cb051 407 if (transportData->clientDoWork == NULL)
AzureIoTClient 66:a419827cb051 408 {
AzureIoTClient 66:a419827cb051 409 transportData->clientDoWork = muxDoWork;
AzureIoTClient 66:a419827cb051 410 }
AzureIoTClient 66:a419827cb051 411
AzureIoTClient 66:a419827cb051 412 if ((result = start_worker_if_needed(transportData, clientHandle)) != IOTHUB_CLIENT_OK)
AzureIoTClient 66:a419827cb051 413 {
AzureIoTClient 66:a419827cb051 414 /*Codes_SRS_IOTHUBTRANSPORT_17_019: [ If thread creation fails, IoTHubTransport_StartWorkerThread shall return IOTHUB_CLIENT_ERROR. */
AzureIoTClient 66:a419827cb051 415 LogError("Unable to start thread safely");
AzureIoTClient 66:a419827cb051 416 }
AzureIoTClient 66:a419827cb051 417 else
AzureIoTClient 66:a419827cb051 418 {
AzureIoTClient 66:a419827cb051 419 /*Codes_SRS_IOTHUBTRANSPORT_17_022: [ Upon success, IoTHubTransport_StartWorkerThread shall return IOTHUB_CLIENT_OK. ]*/
AzureIoTClient 66:a419827cb051 420 result = IOTHUB_CLIENT_OK;
AzureIoTClient 66:a419827cb051 421 }
AzureIoTClient 66:a419827cb051 422 }
AzureIoTClient 66:a419827cb051 423 return result;
Azure.IoT Build 37:18310e4d888d 424 }
Azure.IoT Build 37:18310e4d888d 425
AzureIoTClient 88:248736be106e 426 bool IoTHubTransport_SignalEndWorkerThread(TRANSPORT_HANDLE transportHandle, IOTHUB_CLIENT_CORE_HANDLE clientHandle)
Azure.IoT Build 37:18310e4d888d 427 {
AzureIoTClient 66:a419827cb051 428 bool okToJoin;
AzureIoTClient 66:a419827cb051 429 /*Codes_SRS_IOTHUBTRANSPORT_17_023: [ If transportHandle is NULL, IoTHubTransport_EndWorkerThread shall return. ]*/
AzureIoTClient 66:a419827cb051 430 /*Codes_SRS_IOTHUBTRANSPORT_17_024: [ If clientHandle is NULL, IoTHubTransport_EndWorkerThread shall return. ]*/
AzureIoTClient 66:a419827cb051 431 if (!(transportHandle == NULL || clientHandle == NULL))
AzureIoTClient 66:a419827cb051 432 {
AzureIoTClient 66:a419827cb051 433 TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
AzureIoTClient 66:a419827cb051 434 okToJoin = signal_end_worker_thread(transportData, clientHandle);
AzureIoTClient 66:a419827cb051 435 }
AzureIoTClient 66:a419827cb051 436 else
AzureIoTClient 66:a419827cb051 437 {
AzureIoTClient 66:a419827cb051 438 okToJoin = false;
AzureIoTClient 66:a419827cb051 439 }
AzureIoTClient 66:a419827cb051 440 return okToJoin;
Azure.IoT Build 37:18310e4d888d 441 }
Azure.IoT Build 37:18310e4d888d 442
AzureIoTClient 88:248736be106e 443 void IoTHubTransport_JoinWorkerThread(TRANSPORT_HANDLE transportHandle, IOTHUB_CLIENT_CORE_HANDLE clientHandle)
Azure.IoT Build 37:18310e4d888d 444 {
AzureIoTClient 66:a419827cb051 445 /*Codes_SRS_IOTHUBTRANSPORT_17_044: [ If transportHandle is NULL, IoTHubTransport_JoinWorkerThread shall do nothing. ]*/
AzureIoTClient 66:a419827cb051 446 /*Codes_SRS_IOTHUBTRANSPORT_17_045: [ If clientHandle is NULL, IoTHubTransport_JoinWorkerThread shall do nothing. ]*/
AzureIoTClient 66:a419827cb051 447 if (!(transportHandle == NULL || clientHandle == NULL))
AzureIoTClient 66:a419827cb051 448 {
AzureIoTClient 66:a419827cb051 449 TRANSPORT_HANDLE_DATA * transportData = (TRANSPORT_HANDLE_DATA*)transportHandle;
AzureIoTClient 66:a419827cb051 450 /*Codes_SRS_IOTHUBTRANSPORT_17_027: [ The worker thread shall be joined. ]*/
AzureIoTClient 66:a419827cb051 451 wait_worker_thread(transportData);
AzureIoTClient 66:a419827cb051 452 }
Azure.IoT Build 37:18310e4d888d 453 }