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