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:
Tue Mar 20 10:29:00 2018 -0700
Revision:
85:de16c0a8a196
Parent:
71:0d498da5ece1
Child:
88:248736be106e
1.2.1

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