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
iothubtransport.c@89:a2ed767a532e, 2018-06-26 (annotated)
- Committer:
- AzureIoTClient
- Date:
- Tue Jun 26 19:14:28 2018 -0700
- Revision:
- 89:a2ed767a532e
- Parent:
- 88:248736be106e
- Child:
- 92:97148cf9aa2a
1.2.6
Who changed what in which revision?
User | Revision | Line number | New 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" |
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 | 66:a419827cb051 | 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 | } |