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