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:
Thu Oct 04 09:15:49 2018 -0700
Revision:
93:7c0bbb86b167
Parent:
92:97148cf9aa2a
1.2.10

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