corrected version (with typedef struct IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE_DATA* IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE;) included in the sources
Dependents: STM32F746_iothub_client_sample_mqtt
Fork of iothub_client by
iothub_client_ll.c
00001 // Copyright (c) Microsoft. All rights reserved. 00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 00003 00004 #include <stdlib.h> 00005 #ifdef _CRTDBG_MAP_ALLOC 00006 #include <crtdbg.h> 00007 #endif 00008 #include <string.h> 00009 #include "azure_c_shared_utility/gballoc.h" 00010 #include "azure_c_shared_utility/string_tokenizer.h" 00011 #include "azure_c_shared_utility/doublylinkedlist.h" 00012 #include "azure_c_shared_utility/iot_logging.h" 00013 #include "azure_c_shared_utility/tickcounter.h" 00014 00015 #include "iothub_client_ll.h" 00016 #include "iothub_client_private.h" 00017 #include "iothub_client_version.h" 00018 #include "iothub_transport_ll.h" 00019 00020 #ifdef USE_UPLOADTOBLOB 00021 #include "iothub_client_ll_uploadtoblob.h" 00022 #endif 00023 00024 #define LOG_ERROR LogError("result = %s", ENUM_TO_STRING(IOTHUB_CLIENT_RESULT, result)); 00025 #define INDEFINITE_TIME ((time_t)(-1)) 00026 00027 DEFINE_ENUM_STRINGS(IOTHUB_CLIENT_RESULT, IOTHUB_CLIENT_RESULT_VALUES); 00028 00029 typedef struct IOTHUB_CLIENT_LL_HANDLE_DATA_TAG 00030 { 00031 DLIST_ENTRY waitingToSend; 00032 TRANSPORT_LL_HANDLE transportHandle; 00033 bool isSharedTransport; 00034 IOTHUB_DEVICE_HANDLE deviceHandle; 00035 TRANSPORT_PROVIDER_FIELDS; 00036 IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback; 00037 void* messageUserContextCallback; 00038 time_t lastMessageReceiveTime; 00039 TICK_COUNTER_HANDLE tickCounter; /*shared tickcounter used to track message timeouts in waitingToSend list*/ 00040 uint64_t currentMessageTimeout; 00041 #ifdef USE_UPLOADTOBLOB 00042 IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE uploadToBlobHandle; 00043 #endif 00044 00045 }IOTHUB_CLIENT_LL_HANDLE_DATA; 00046 00047 static const char HOSTNAME_TOKEN[] = "HostName"; 00048 static const char DEVICEID_TOKEN[] = "DeviceId"; 00049 static const char DEVICEKEY_TOKEN[] = "SharedAccessKey"; 00050 static const char DEVICESAS_TOKEN[] = "SharedAccessSignature"; 00051 static const char PROTOCOL_GATEWAY_HOST[] = "GatewayHostName"; 00052 00053 IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateFromConnectionString(const char* connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER protocol) 00054 { 00055 IOTHUB_CLIENT_LL_HANDLE result = NULL; 00056 00057 /*Codes_SRS_IOTHUBCLIENT_LL_05_001: [IoTHubClient_LL_CreateFromConnectionString shall obtain the version string by a call to IoTHubClient_GetVersionString.]*/ 00058 /*Codes_SRS_IOTHUBCLIENT_LL_05_002: [IoTHubClient_LL_CreateFromConnectionString shall print the version string to standard output.]*/ 00059 LogInfo("IoT Hub SDK for C, version %s", IoTHubClient_GetVersionString()); 00060 00061 /* Codes_SRS_IOTHUBCLIENT_LL_12_003: [IoTHubClient_LL_CreateFromConnectionString shall verify the input parameter and if it is NULL then return NULL] */ 00062 if (connectionString == NULL) 00063 { 00064 LogError("Input parameter is NULL: connectionString"); 00065 } 00066 else if (protocol == NULL) 00067 { 00068 LogError("Input parameter is NULL: protocol"); 00069 } 00070 else 00071 { 00072 /* Codes_SRS_IOTHUBCLIENT_LL_12_004: [IoTHubClient_LL_CreateFromConnectionString shall allocate IOTHUB_CLIENT_CONFIG structure] */ 00073 IOTHUB_CLIENT_CONFIG* config = malloc(sizeof(IOTHUB_CLIENT_CONFIG)); 00074 if (config == NULL) 00075 { 00076 /* Codes_SRS_IOTHUBCLIENT_LL_12_012: [If the allocation failed IoTHubClient_LL_CreateFromConnectionString returns NULL] */ 00077 LogError("Malloc failed"); 00078 return NULL; 00079 } 00080 else 00081 { 00082 STRING_TOKENIZER_HANDLE tokenizer1 = NULL; 00083 STRING_HANDLE connString = NULL; 00084 STRING_HANDLE tokenString = NULL; 00085 STRING_HANDLE valueString = NULL; 00086 STRING_HANDLE hostNameString = NULL; 00087 STRING_HANDLE hostSuffixString = NULL; 00088 STRING_HANDLE deviceIdString = NULL; 00089 STRING_HANDLE deviceKeyString = NULL; 00090 STRING_HANDLE deviceSasTokenString = NULL; 00091 STRING_HANDLE protocolGateway = NULL; 00092 00093 config->protocol = protocol; 00094 00095 config->iotHubName = NULL; 00096 config->iotHubSuffix = NULL; 00097 config->deviceId = NULL; 00098 config->deviceKey = NULL; 00099 config->deviceSasToken = NULL; 00100 00101 /* Codes_SRS_IOTHUBCLIENT_LL_04_002: [If it does not, it shall pass the protocolGatewayHostName NULL.] */ 00102 config->protocolGatewayHostName = NULL; 00103 00104 if ((connString = STRING_construct(connectionString)) == NULL) 00105 { 00106 LogError("Error constructing connectiong String"); 00107 } 00108 else if ((tokenizer1 = STRING_TOKENIZER_create(connString)) == NULL) 00109 { 00110 LogError("Error creating Tokenizer"); 00111 } 00112 else if ((tokenString = STRING_new()) == NULL) 00113 { 00114 LogError("Error creating Token String"); 00115 } 00116 else if ((valueString = STRING_new()) == NULL) 00117 { 00118 LogError("Error creating Value String"); 00119 } 00120 else if ((hostNameString = STRING_new()) == NULL) 00121 { 00122 LogError("Error creating HostName String"); 00123 } 00124 else if ((hostSuffixString = STRING_new()) == NULL) 00125 { 00126 LogError("Error creating HostSuffix String"); 00127 } 00128 /* Codes_SRS_IOTHUBCLIENT_LL_12_005: [IoTHubClient_LL_CreateFromConnectionString shall try to parse the connectionString input parameter for the following structure: "Key1=value1;key2=value2;key3=value3..."] */ 00129 /* Codes_SRS_IOTHUBCLIENT_LL_12_006: [IoTHubClient_LL_CreateFromConnectionString shall verify the existence of the following Key/Value pairs in the connection string: HostName, DeviceId, SharedAccessKey or SharedAccessSignature.] */ 00130 else 00131 { 00132 while ((STRING_TOKENIZER_get_next_token(tokenizer1, tokenString, "=") == 0)) 00133 { 00134 if (STRING_TOKENIZER_get_next_token(tokenizer1, valueString, ";") != 0) 00135 { 00136 LogError("Tokenizer error"); 00137 break; 00138 } 00139 else 00140 { 00141 if (tokenString != NULL) 00142 { 00143 /* Codes_SRS_IOTHUBCLIENT_LL_12_010: [IoTHubClient_LL_CreateFromConnectionString shall fill up the IOTHUB_CLIENT_CONFIG structure using the following mapping: iotHubName = Name, iotHubSuffix = Suffix, deviceId = DeviceId, deviceKey = SharedAccessKey or deviceSasToken = SharedAccessSignature] */ 00144 const char* s_token = STRING_c_str(tokenString); 00145 if (strcmp(s_token, HOSTNAME_TOKEN) == 0) 00146 { 00147 /* Codes_SRS_IOTHUBCLIENT_LL_12_009: [IoTHubClient_LL_CreateFromConnectionString shall split the value of HostName to Name and Suffix using the first "." as a separator] */ 00148 STRING_TOKENIZER_HANDLE tokenizer2 = NULL; 00149 if ((tokenizer2 = STRING_TOKENIZER_create(valueString)) == NULL) 00150 { 00151 LogError("Error creating Tokenizer"); 00152 break; 00153 } 00154 else 00155 { 00156 /* Codes_SRS_IOTHUBCLIENT_LL_12_015: [If the string split failed, IoTHubClient_LL_CreateFromConnectionString returns NULL ] */ 00157 if (STRING_TOKENIZER_get_next_token(tokenizer2, hostNameString, ".") != 0) 00158 { 00159 LogError("Tokenizer error"); 00160 STRING_TOKENIZER_destroy(tokenizer2); 00161 break; 00162 } 00163 else 00164 { 00165 config->iotHubName = STRING_c_str(hostNameString); 00166 if (STRING_TOKENIZER_get_next_token(tokenizer2, hostSuffixString, ";") != 0) 00167 { 00168 LogError("Tokenizer error"); 00169 STRING_TOKENIZER_destroy(tokenizer2); 00170 break; 00171 } 00172 else 00173 { 00174 config->iotHubSuffix = STRING_c_str(hostSuffixString); 00175 } 00176 } 00177 STRING_TOKENIZER_destroy(tokenizer2); 00178 } 00179 } 00180 else if (strcmp(s_token, DEVICEID_TOKEN) == 0) 00181 { 00182 deviceIdString = STRING_clone(valueString); 00183 if (deviceIdString != NULL) 00184 { 00185 config->deviceId = STRING_c_str(deviceIdString); 00186 } 00187 } 00188 else if (strcmp(s_token, DEVICEKEY_TOKEN) == 0) 00189 { 00190 deviceKeyString = STRING_clone(valueString); 00191 if (deviceKeyString != NULL) 00192 { 00193 config->deviceKey = STRING_c_str(deviceKeyString); 00194 } 00195 } 00196 else if (strcmp(s_token, DEVICESAS_TOKEN) == 0) 00197 { 00198 deviceSasTokenString = STRING_clone(valueString); 00199 if (deviceSasTokenString != NULL) 00200 { 00201 config->deviceSasToken = STRING_c_str(deviceSasTokenString); 00202 } 00203 } 00204 /* Codes_SRS_IOTHUBCLIENT_LL_04_001: [IoTHubClient_LL_CreateFromConnectionString shall verify the existence of key/value pair GatewayHostName. If it does exist it shall pass the value to IoTHubClient_LL_Create API.] */ 00205 else if (strcmp(s_token, PROTOCOL_GATEWAY_HOST) == 0) 00206 { 00207 protocolGateway = STRING_clone(valueString); 00208 if (protocolGateway != NULL) 00209 { 00210 config->protocolGatewayHostName = STRING_c_str(protocolGateway); 00211 } 00212 } 00213 } 00214 } 00215 } 00216 /* parsing is done - check the result */ 00217 if (config->iotHubName == NULL) 00218 { 00219 LogError("iotHubName is not found"); 00220 } 00221 else if (config->iotHubSuffix == NULL) 00222 { 00223 LogError("iotHubSuffix is not found"); 00224 } 00225 else if (config->deviceId == NULL) 00226 { 00227 LogError("deviceId is not found"); 00228 } 00229 else if (config->deviceKey == NULL && config->deviceSasToken == NULL) 00230 { 00231 LogError("deviceKey/deviceSasToken not found"); 00232 } 00233 else if (config->deviceKey != NULL && config->deviceSasToken != NULL) 00234 { 00235 LogError("Both device Key & SAS token are defined. Only one should be provided."); 00236 } 00237 else 00238 { 00239 /* Codes_SRS_IOTHUBCLIENT_LL_12_011: [IoTHubClient_LL_CreateFromConnectionString shall call into the IoTHubClient_LL_Create API with the current structure and returns with the return value of it] */ 00240 00241 result = IoTHubClient_LL_Create(config); 00242 if (result == NULL) 00243 { 00244 LogError("IoTHubClient_LL_Create failed"); 00245 } 00246 else 00247 { 00248 /*return as is*/ 00249 } 00250 } 00251 } 00252 if (deviceSasTokenString != NULL) 00253 STRING_delete(deviceSasTokenString); 00254 if (deviceKeyString != NULL) 00255 STRING_delete(deviceKeyString); 00256 if (deviceIdString != NULL) 00257 STRING_delete(deviceIdString); 00258 if (hostSuffixString != NULL) 00259 STRING_delete(hostSuffixString); 00260 if (hostNameString != NULL) 00261 STRING_delete(hostNameString); 00262 if (valueString != NULL) 00263 STRING_delete(valueString); 00264 if (tokenString != NULL) 00265 STRING_delete(tokenString); 00266 if (connString != NULL) 00267 STRING_delete(connString); 00268 if (protocolGateway != NULL) 00269 STRING_delete(protocolGateway); 00270 00271 if (tokenizer1 != NULL) 00272 STRING_TOKENIZER_destroy(tokenizer1); 00273 00274 free(config); 00275 } 00276 } 00277 return result; 00278 } 00279 00280 static void setTransportProtocol(IOTHUB_CLIENT_LL_HANDLE_DATA* handleData, TRANSPORT_PROVIDER* protocol) 00281 { 00282 handleData->IoTHubTransport_GetHostname = protocol->IoTHubTransport_GetHostname; 00283 handleData->IoTHubTransport_SetOption = protocol->IoTHubTransport_SetOption; 00284 handleData->IoTHubTransport_Create = protocol->IoTHubTransport_Create; 00285 handleData->IoTHubTransport_Destroy = protocol->IoTHubTransport_Destroy; 00286 handleData->IoTHubTransport_Register = protocol->IoTHubTransport_Register; 00287 handleData->IoTHubTransport_Unregister = protocol->IoTHubTransport_Unregister; 00288 handleData->IoTHubTransport_Subscribe = protocol->IoTHubTransport_Subscribe; 00289 handleData->IoTHubTransport_Unsubscribe = protocol->IoTHubTransport_Unsubscribe; 00290 handleData->IoTHubTransport_DoWork = protocol->IoTHubTransport_DoWork; 00291 handleData->IoTHubTransport_GetSendStatus = protocol->IoTHubTransport_GetSendStatus; 00292 00293 } 00294 00295 IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_Create(const IOTHUB_CLIENT_CONFIG* config) 00296 { 00297 IOTHUB_CLIENT_LL_HANDLE result; 00298 /*Codes_SRS_IOTHUBCLIENT_LL_02_001: [IoTHubClient_LL_Create shall return NULL if config parameter is NULL or protocol field is NULL.]*/ 00299 if( 00300 (config == NULL) || 00301 (config->protocol == NULL) 00302 ) 00303 { 00304 result = NULL; 00305 LogError("invalid configuration (NULL detected)"); 00306 } 00307 else 00308 { 00309 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)malloc(sizeof(IOTHUB_CLIENT_LL_HANDLE_DATA)); 00310 if (handleData == NULL) 00311 { 00312 LogError("malloc failed"); 00313 result = NULL; 00314 } 00315 else 00316 { 00317 #ifdef USE_UPLOADTOBLOB 00318 /*Codes_SRS_IOTHUBCLIENT_LL_02_094: [ IoTHubClient_LL_Create shall create a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE from IOTHUB_CLIENT_CONFIG. ]*/ 00319 /*Codes_SRS_IOTHUBCLIENT_LL_02_092: [ IoTHubClient_LL_CreateFromConnectionString shall create a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE from IOTHUB_CLIENT_CONFIG. ]*/ 00320 handleData->uploadToBlobHandle = IoTHubClient_LL_UploadToBlob_Create(config); 00321 if (handleData->uploadToBlobHandle == NULL) 00322 { 00323 /*Codes_SRS_IOTHUBCLIENT_LL_02_093: [ If creating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateFromConnectionString shall fail and return NULL. ]*/ 00324 /*Codes_SRS_IOTHUBCLIENT_LL_02_095: [ If creating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_Create shall fail and return NULL. ]*/ 00325 LogError("unable to IoTHubClient_LL_UploadToBlob_Create"); 00326 free(handleData); 00327 result = NULL; 00328 } 00329 else 00330 #endif 00331 { 00332 /*Codes_SRS_IOTHUBCLIENT_LL_02_045: [ Otherwise IoTHubClient_LL_Create shall create a new TICK_COUNTER_HANDLE ]*/ 00333 if ((handleData->tickCounter = tickcounter_create()) == NULL) 00334 { 00335 #ifdef USE_UPLOADTOBLOB 00336 /*Codes_SRS_IOTHUBCLIENT_LL_02_046: [ If creating the TICK_COUNTER_HANDLE fails then IoTHubClient_LL_Create shall fail and return NULL. ]*/ 00337 IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle); 00338 #endif 00339 LogError("unable to get a tickcounter"); 00340 free(handleData); 00341 result = NULL; 00342 } 00343 else 00344 { 00345 /*Codes_SRS_IOTHUBCLIENT_LL_02_004: [Otherwise IoTHubClient_LL_Create shall initialize a new DLIST (further called "waitingToSend") containing records with fields of the following types: IOTHUB_MESSAGE_HANDLE, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, void*.]*/ 00346 IOTHUBTRANSPORT_CONFIG lowerLayerConfig; 00347 DList_InitializeListHead(&(handleData->waitingToSend)); 00348 setTransportProtocol(handleData, (TRANSPORT_PROVIDER*)config->protocol()); 00349 handleData->messageCallback = NULL; 00350 handleData->messageUserContextCallback = NULL; 00351 handleData->lastMessageReceiveTime = INDEFINITE_TIME; 00352 /*Codes_SRS_IOTHUBCLIENT_LL_02_006: [IoTHubClient_LL_Create shall populate a structure of type IOTHUBTRANSPORT_CONFIG with the information from config parameter and the previous DLIST and shall pass that to the underlying layer _Create function.]*/ 00353 lowerLayerConfig.upperConfig = config; 00354 lowerLayerConfig.waitingToSend = &(handleData->waitingToSend); 00355 /*Codes_SRS_IOTHUBCLIENT_LL_02_007: [If the underlaying layer _Create function fails them IoTHubClient_LL_Create shall fail and return NULL.] */ 00356 if ((handleData->transportHandle = handleData->IoTHubTransport_Create(&lowerLayerConfig)) == NULL) 00357 { 00358 LogError("underlying transport failed"); 00359 #ifdef USE_UPLOADTOBLOB 00360 IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle); 00361 #endif 00362 tickcounter_destroy(handleData->tickCounter); 00363 free(handleData); 00364 result = NULL; 00365 } 00366 else 00367 { 00368 IOTHUB_DEVICE_CONFIG deviceConfig; 00369 00370 deviceConfig.deviceId = config->deviceId; 00371 deviceConfig.deviceKey = config->deviceKey; 00372 deviceConfig.deviceSasToken = config->deviceSasToken; 00373 00374 /*Codes_SRS_IOTHUBCLIENT_LL_17_008: [IoTHubClient_LL_Create shall call the transport _Register function with a populated structure of type IOTHUB_DEVICE_CONFIG and waitingToSend list.] */ 00375 if ((handleData->deviceHandle = handleData->IoTHubTransport_Register(handleData->transportHandle, &deviceConfig, handleData, &(handleData->waitingToSend))) == NULL) 00376 { 00377 /*Codes_SRS_IOTHUBCLIENT_LL_17_009: [If the _Register function fails, this function shall fail and return NULL.]*/ 00378 LogError("Registering device in transport failed"); 00379 handleData->IoTHubTransport_Destroy(handleData->transportHandle); 00380 #ifdef USE_UPLOADTOBLOB 00381 IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle); 00382 #endif 00383 tickcounter_destroy(handleData->tickCounter); 00384 free(handleData); 00385 result = NULL; 00386 } 00387 else 00388 { 00389 /*Codes_SRS_IOTHUBCLIENT_LL_02_008: [Otherwise, IoTHubClient_LL_Create shall succeed and return a non-NULL handle.] */ 00390 handleData->isSharedTransport = false; 00391 /*Codes_SRS_IOTHUBCLIENT_LL_02_042: [ By default, messages shall not timeout. ]*/ 00392 handleData->currentMessageTimeout = 0; 00393 result = handleData; 00394 } 00395 } 00396 } 00397 } 00398 } 00399 } 00400 00401 return result; 00402 } 00403 00404 IOTHUB_CLIENT_LL_HANDLE IoTHubClient_LL_CreateWithTransport(const IOTHUB_CLIENT_DEVICE_CONFIG * config) 00405 { 00406 IOTHUB_CLIENT_LL_HANDLE result; 00407 /*Codes_SRS_IOTHUBCLIENT_LL_17_001: [IoTHubClient_LL_CreateWithTransport shall return NULL if config parameter is NULL, or protocol field is NULL or transportHandle is NULL.]*/ 00408 if ( 00409 (config == NULL) || 00410 (config->protocol == NULL) || 00411 (config->transportHandle == NULL) 00412 ) 00413 { 00414 result = NULL; 00415 LogError("invalid configuration (NULL detected)"); 00416 } 00417 else 00418 { 00419 /*Codes_SRS_IOTHUBCLIENT_LL_17_002: [IoTHubClient_LL_CreateWithTransport shall allocate data for the IOTHUB_CLIENT_LL_HANDLE.]*/ 00420 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)malloc(sizeof(IOTHUB_CLIENT_LL_HANDLE_DATA)); 00421 if (handleData == NULL) 00422 { 00423 /*Codes_SRS_IOTHUBCLIENT_LL_17_003: [If allocation fails, the function shall fail and return NULL.] */ 00424 LogError("malloc failed"); 00425 result = NULL; 00426 } 00427 else 00428 { 00429 handleData->transportHandle = config->transportHandle; 00430 setTransportProtocol(handleData, (TRANSPORT_PROVIDER*)config->protocol()); 00431 00432 #ifdef USE_UPLOADTOBLOB 00433 const char* hostname = STRING_c_str(handleData->IoTHubTransport_GetHostname(handleData->transportHandle)); 00434 /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClient_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/ 00435 /*the first '.' says where the iothubname finishes*/ 00436 const char* whereIsDot = strchr(hostname, '.'); 00437 if (whereIsDot == NULL) 00438 { 00439 /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/ 00440 LogError("unable to determine the IoTHub name"); 00441 free(handleData); 00442 result = NULL; 00443 } 00444 else 00445 { 00446 /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClient_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/ 00447 char* IoTHubName = malloc(whereIsDot - hostname + 1); 00448 if (IoTHubName == NULL) 00449 { 00450 /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/ 00451 LogError("unable to malloc"); 00452 free(handleData); 00453 result = NULL; 00454 } 00455 else 00456 { 00457 const char* IotHubSuffix = whereIsDot + 1; 00458 memcpy(IoTHubName, hostname, whereIsDot - hostname); 00459 IoTHubName[whereIsDot - hostname ] = '\0'; 00460 00461 IOTHUB_CLIENT_CONFIG temp; 00462 temp.deviceId = config->deviceId; 00463 temp.deviceKey = config->deviceKey; 00464 temp.deviceSasToken = config->deviceSasToken; 00465 temp.iotHubName = IoTHubName; 00466 temp.iotHubSuffix = IotHubSuffix; 00467 temp.protocol = NULL; /*irrelevant to IoTHubClient_LL_UploadToBlob*/ 00468 temp.protocolGatewayHostName = NULL; /*irrelevant to IoTHubClient_LL_UploadToBlob*/ 00469 00470 /*Codes_SRS_IOTHUBCLIENT_LL_02_097: [ If creating the data structures fails or instantiating the IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE fails then IoTHubClient_LL_CreateWithTransport shall fail and return NULL. ]*/ 00471 handleData->uploadToBlobHandle = IoTHubClient_LL_UploadToBlob_Create(&temp); 00472 if (handleData->uploadToBlobHandle == NULL) 00473 { 00474 /*Codes_SRS_IOTHUBCLIENT_LL_02_096: [ IoTHubClient_LL_CreateWithTransport shall create the data structures needed to instantiate a IOTHUB_CLIENT_LL_UPLOADTOBLOB_HANDLE. ]*/ 00475 LogError("unable to IoTHubClient_LL_UploadToBlob_Create"); 00476 free(handleData); 00477 result = NULL; 00478 } 00479 else 00480 #endif 00481 { 00482 /*Codes_SRS_IOTHUBCLIENT_LL_02_047: [ IoTHubClient_LL_CreateWithTransport shall create a TICK_COUNTER_HANDLE. ]*/ 00483 if ((handleData->tickCounter = tickcounter_create()) == NULL) 00484 { 00485 /*Codes_SRS_IOTHUBCLIENT_LL_02_048: [ If creating the handle fails, then IoTHubClient_LL_CreateWithTransport shall fail and return NULL ]*/ 00486 LogError("unable to get a tickcounter"); 00487 #ifdef USE_UPLOADTOBLOB 00488 IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle); 00489 #endif 00490 free(handleData); 00491 result = NULL; 00492 } 00493 else 00494 { 00495 /*Codes_SRS_IOTHUBCLIENT_LL_17_004: [IoTHubClient_LL_CreateWithTransport shall initialize a new DLIST (further called "waitingToSend") containing records with fields of the following types: IOTHUB_MESSAGE_HANDLE, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, void*.]*/ 00496 DList_InitializeListHead(&(handleData->waitingToSend)); 00497 00498 handleData->messageCallback = NULL; 00499 handleData->messageUserContextCallback = NULL; 00500 handleData->lastMessageReceiveTime = INDEFINITE_TIME; 00501 00502 00503 IOTHUB_DEVICE_CONFIG deviceConfig; 00504 00505 deviceConfig.deviceId = config->deviceId; 00506 deviceConfig.deviceKey = config->deviceKey; 00507 deviceConfig.deviceSasToken = config->deviceSasToken; 00508 00509 /*Codes_SRS_IOTHUBCLIENT_LL_17_006: [IoTHubClient_LL_CreateWithTransport shall call the transport _Register function with the IOTHUB_DEVICE_CONFIG populated structure and waitingToSend list.]*/ 00510 if ((handleData->deviceHandle = handleData->IoTHubTransport_Register(config->transportHandle, &deviceConfig, handleData, &(handleData->waitingToSend))) == NULL) 00511 { 00512 /*Codes_SRS_IOTHUBCLIENT_LL_17_007: [If the _Register function fails, this function shall fail and return NULL.]*/ 00513 LogError("Registering device in transport failed"); 00514 #ifdef USE_UPLOADTOBLOB 00515 IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle); 00516 #endif 00517 tickcounter_destroy(handleData->tickCounter); 00518 free(handleData); 00519 result = NULL; 00520 } 00521 else 00522 { 00523 /*Codes_SRS_IOTHUBCLIENT_LL_17_005: [IoTHubClient_LL_CreateWithTransport shall save the transport handle and mark this transport as shared.]*/ 00524 handleData->isSharedTransport = true; 00525 /*Codes_SRS_IOTHUBCLIENT_LL_02_042: [ By default, messages shall not timeout. ]*/ 00526 handleData->currentMessageTimeout = 0; 00527 result = handleData; 00528 } 00529 } 00530 } 00531 #ifdef USE_UPLOADTOBLOB 00532 free(IoTHubName); 00533 } 00534 } 00535 #endif 00536 } 00537 } 00538 00539 return result; 00540 } 00541 00542 void IoTHubClient_LL_Destroy(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle) 00543 { 00544 /*Codes_SRS_IOTHUBCLIENT_LL_02_009: [IoTHubClient_LL_Destroy shall do nothing if parameter iotHubClientHandle is NULL.]*/ 00545 if (iotHubClientHandle != NULL) 00546 { 00547 PDLIST_ENTRY unsend; 00548 /*Codes_SRS_IOTHUBCLIENT_LL_17_010: [IoTHubClient_LL_Destroy shall call the underlaying layer's _Unregister function] */ 00549 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle; 00550 handleData->IoTHubTransport_Unregister(handleData->deviceHandle); 00551 if (handleData->isSharedTransport == false) 00552 { 00553 /*Codes_SRS_IOTHUBCLIENT_LL_02_010: [If iotHubClientHandle was not created by IoTHubClient_LL_CreateWithTransport, IoTHubClient_LL_Destroy shall call the underlaying layer's _Destroy function.] */ 00554 handleData->IoTHubTransport_Destroy(handleData->transportHandle); 00555 } 00556 /*if any, remove the items currently not send*/ 00557 while ((unsend = DList_RemoveHeadList(&(handleData->waitingToSend))) != &(handleData->waitingToSend)) 00558 { 00559 IOTHUB_MESSAGE_LIST* temp = containingRecord(unsend, IOTHUB_MESSAGE_LIST, entry); 00560 /*Codes_SRS_IOTHUBCLIENT_LL_02_033: [Otherwise, IoTHubClient_LL_Destroy shall complete all the event message callbacks that are in the waitingToSend list with the result IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY.] */ 00561 if (temp->callback != NULL) 00562 { 00563 temp->callback(IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY, temp->context); 00564 } 00565 IoTHubMessage_Destroy(temp->messageHandle); 00566 free(temp); 00567 } 00568 /*Codes_SRS_IOTHUBCLIENT_LL_17_011: [IoTHubClient_LL_Destroy shall free the resources allocated by IoTHubClient (if any).] */ 00569 tickcounter_destroy(handleData->tickCounter); 00570 #ifdef USE_UPLOADTOBLOB 00571 IoTHubClient_LL_UploadToBlob_Destroy(handleData->uploadToBlobHandle); 00572 #endif 00573 free(handleData); 00574 } 00575 } 00576 00577 /*Codes_SRS_IOTHUBCLIENT_LL_02_044: [ Messages already delivered to IoTHubClient_LL shall not have their timeouts modified by a new call to IoTHubClient_LL_SetOption. ]*/ 00578 /*returns 0 on success, any other value is error*/ 00579 static int attach_ms_timesOutAfter(IOTHUB_CLIENT_LL_HANDLE_DATA* handleData, IOTHUB_MESSAGE_LIST *newEntry) 00580 { 00581 int result; 00582 /*Codes_SRS_IOTHUBCLIENT_LL_02_043: [ Calling IoTHubClient_LL_SetOption with value set to "0" shall disable the timeout mechanism for all new messages. ]*/ 00583 if (handleData->currentMessageTimeout == 0) 00584 { 00585 newEntry->ms_timesOutAfter = 0; /*do not timeout*/ 00586 result = 0; 00587 } 00588 else 00589 { 00590 /*Codes_SRS_IOTHUBCLIENT_LL_02_039: [ "messageTimeout" - once IoTHubClient_LL_SendEventAsync is called the message shall timeout after value miliseconds. Value is a pointer to a uint64. ]*/ 00591 if (tickcounter_get_current_ms(handleData->tickCounter, &newEntry->ms_timesOutAfter) != 0) 00592 { 00593 result = __LINE__; 00594 LogError("unable to get the current relative tickcount"); 00595 } 00596 else 00597 { 00598 newEntry->ms_timesOutAfter += handleData->currentMessageTimeout; 00599 result = 0; 00600 } 00601 } 00602 return result; 00603 } 00604 00605 IOTHUB_CLIENT_RESULT IoTHubClient_LL_SendEventAsync(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_MESSAGE_HANDLE eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK eventConfirmationCallback, void* userContextCallback) 00606 { 00607 IOTHUB_CLIENT_RESULT result; 00608 /*Codes_SRS_IOTHUBCLIENT_LL_02_011: [IoTHubClient_LL_SendEventAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle or eventMessageHandle is NULL.]*/ 00609 if ( 00610 (iotHubClientHandle == NULL) || 00611 (eventMessageHandle == NULL) || 00612 /*Codes_SRS_IOTHUBCLIENT_LL_02_012: [IoTHubClient_LL_SendEventAsync shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter eventConfirmationCallback is NULL and userContextCallback is not NULL.] */ 00613 ((eventConfirmationCallback == NULL) && (userContextCallback != NULL)) 00614 ) 00615 { 00616 result = IOTHUB_CLIENT_INVALID_ARG; 00617 LOG_ERROR; 00618 } 00619 else 00620 { 00621 IOTHUB_MESSAGE_LIST *newEntry = (IOTHUB_MESSAGE_LIST*)malloc(sizeof(IOTHUB_MESSAGE_LIST)); 00622 if (newEntry == NULL) 00623 { 00624 result = IOTHUB_CLIENT_ERROR; 00625 LOG_ERROR; 00626 } 00627 else 00628 { 00629 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle; 00630 00631 if (attach_ms_timesOutAfter(handleData, newEntry) != 0) 00632 { 00633 result = IOTHUB_CLIENT_ERROR; 00634 LOG_ERROR; 00635 free(newEntry); 00636 } 00637 else 00638 { 00639 /*Codes_SRS_IOTHUBCLIENT_LL_02_013: [IoTHubClient_SendEventAsync shall add the DLIST waitingToSend a new record cloning the information from eventMessageHandle, eventConfirmationCallback, userContextCallback.]*/ 00640 if ((newEntry->messageHandle = IoTHubMessage_Clone(eventMessageHandle)) == NULL) 00641 { 00642 /*Codes_SRS_IOTHUBCLIENT_LL_02_014: [If cloning and/or adding the information fails for any reason, IoTHubClient_LL_SendEventAsync shall fail and return IOTHUB_CLIENT_ERROR.] */ 00643 result = IOTHUB_CLIENT_ERROR; 00644 free(newEntry); 00645 LOG_ERROR; 00646 } 00647 else 00648 { 00649 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle; 00650 /*Codes_SRS_IOTHUBCLIENT_LL_02_013: [IoTHubClient_SendEventAsync shall add the DLIST waitingToSend a new record cloning the information from eventMessageHandle, eventConfirmationCallback, userContextCallback.]*/ 00651 newEntry->callback = eventConfirmationCallback; 00652 newEntry->context = userContextCallback; 00653 DList_InsertTailList(&(handleData->waitingToSend), &(newEntry->entry)); 00654 /*Codes_SRS_IOTHUBCLIENT_LL_02_015: [Otherwise IoTHubClient_LL_SendEventAsync shall succeed and return IOTHUB_CLIENT_OK.] */ 00655 result = IOTHUB_CLIENT_OK; 00656 } 00657 } 00658 } 00659 } 00660 return result; 00661 } 00662 00663 IOTHUB_CLIENT_RESULT IoTHubClient_LL_SetMessageCallback(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC messageCallback, void* userContextCallback) 00664 { 00665 IOTHUB_CLIENT_RESULT result; 00666 /*Codes_SRS_IOTHUBCLIENT_LL_02_016: [IoTHubClient_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_INVALID_ARG if parameter iotHubClientHandle is NULL.] */ 00667 if (iotHubClientHandle == NULL) 00668 { 00669 result = IOTHUB_CLIENT_INVALID_ARG; 00670 LOG_ERROR; 00671 } 00672 else 00673 { 00674 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle; 00675 if (messageCallback == NULL) 00676 { 00677 /*Codes_SRS_IOTHUBCLIENT_LL_02_019: [If parameter messageCallback is NULL then IoTHubClient_LL_SetMessageCallback shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */ 00678 handleData->IoTHubTransport_Unsubscribe(handleData->deviceHandle); 00679 handleData->messageCallback = NULL; 00680 handleData->messageUserContextCallback = NULL; 00681 result = IOTHUB_CLIENT_OK; 00682 } 00683 else 00684 { 00685 /*Codes_SRS_IOTHUBCLIENT_LL_02_017: [If parameter messageCallback is non-NULL then IoTHubClient_LL_SetMessageCallback shall call the underlying layer's _Subscribe function.]*/ 00686 if (handleData->IoTHubTransport_Subscribe(handleData->deviceHandle) == 0) 00687 { 00688 handleData->messageCallback = messageCallback; 00689 handleData->messageUserContextCallback = userContextCallback; 00690 result = IOTHUB_CLIENT_OK; 00691 } 00692 else 00693 { 00694 handleData->messageCallback = NULL; 00695 handleData->messageUserContextCallback = NULL; 00696 /*Codes_SRS_IOTHUBCLIENT_LL_02_018: [If the underlying layer's _Subscribe function fails, then IoTHubClient_LL_SetMessageCallback shall fail and return IOTHUB_CLIENT_ERROR. Otherwise IoTHubClient_LL_SetMessageCallback shall succeed and return IOTHUB_CLIENT_OK.]*/ 00697 result = IOTHUB_CLIENT_ERROR; 00698 } 00699 } 00700 } 00701 00702 return result; 00703 } 00704 00705 static void DoTimeouts(IOTHUB_CLIENT_LL_HANDLE_DATA* handleData) 00706 { 00707 uint64_t nowTick; 00708 if (tickcounter_get_current_ms(handleData->tickCounter, &nowTick) != 0) 00709 { 00710 LogError("unable to get the current ms, timeouts will not be processed"); 00711 } 00712 else 00713 { 00714 DLIST_ENTRY* currentItemInWaitingToSend = handleData->waitingToSend.Flink; 00715 while (currentItemInWaitingToSend != &(handleData->waitingToSend)) /*while we are not at the end of the list*/ 00716 { 00717 IOTHUB_MESSAGE_LIST* fullEntry = containingRecord(currentItemInWaitingToSend, IOTHUB_MESSAGE_LIST, entry); 00718 /*Codes_SRS_IOTHUBCLIENT_LL_02_041: [ If more than value miliseconds have passed since the call to IoTHubClient_LL_SendEventAsync then the message callback shall be called with a status code of IOTHUB_CLIENT_CONFIRMATION_TIMEOUT. ]*/ 00719 if ((fullEntry->ms_timesOutAfter != 0) && (fullEntry->ms_timesOutAfter < nowTick)) 00720 { 00721 PDLIST_ENTRY theNext = currentItemInWaitingToSend->Flink; /*need to save the next item, because the below operations are destructive*/ 00722 DList_RemoveEntryList(currentItemInWaitingToSend); 00723 if (fullEntry->callback != NULL) 00724 { 00725 fullEntry->callback(IOTHUB_CLIENT_CONFIRMATION_MESSAGE_TIMEOUT, fullEntry->context); 00726 } 00727 IoTHubMessage_Destroy(fullEntry->messageHandle); /*because it has been cloned*/ 00728 free(fullEntry); 00729 currentItemInWaitingToSend = theNext; 00730 } 00731 else 00732 { 00733 currentItemInWaitingToSend = currentItemInWaitingToSend->Flink; 00734 } 00735 } 00736 } 00737 } 00738 00739 void IoTHubClient_LL_DoWork(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle) 00740 { 00741 /*Codes_SRS_IOTHUBCLIENT_LL_02_020: [If parameter iotHubClientHandle is NULL then IoTHubClient_LL_DoWork shall not perform any action.] */ 00742 if (iotHubClientHandle != NULL) 00743 { 00744 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle; 00745 DoTimeouts(handleData); 00746 00747 /*Codes_SRS_IOTHUBCLIENT_LL_02_021: [Otherwise, IoTHubClient_LL_DoWork shall invoke the underlaying layer's _DoWork function.]*/ 00748 handleData->IoTHubTransport_DoWork(handleData->transportHandle, iotHubClientHandle); 00749 } 00750 } 00751 00752 IOTHUB_CLIENT_RESULT IoTHubClient_LL_GetSendStatus(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_STATUS *iotHubClientStatus) 00753 { 00754 IOTHUB_CLIENT_RESULT result; 00755 00756 /* Codes_SRS_IOTHUBCLIENT_09_007: [IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter] */ 00757 if (iotHubClientHandle == NULL || iotHubClientStatus == NULL) 00758 { 00759 result = IOTHUB_CLIENT_INVALID_ARG; 00760 LOG_ERROR; 00761 } 00762 else 00763 { 00764 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle; 00765 00766 /* Codes_SRS_IOTHUBCLIENT_09_008: [IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there is currently no items to be sent] */ 00767 /* Codes_SRS_IOTHUBCLIENT_09_009: [IoTHubClient_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently items to be sent] */ 00768 result = handleData->IoTHubTransport_GetSendStatus(handleData->deviceHandle, iotHubClientStatus); 00769 } 00770 00771 return result; 00772 } 00773 00774 void IoTHubClient_LL_SendComplete(IOTHUB_CLIENT_LL_HANDLE handle, PDLIST_ENTRY completed, IOTHUB_BATCHSTATE_RESULT result) 00775 { 00776 /*Codes_SRS_IOTHUBCLIENT_LL_02_022: [If parameter completed is NULL, or parameter handle is NULL then IoTHubClient_LL_SendBatch shall return.]*/ 00777 if ( 00778 (handle == NULL) || 00779 (completed == NULL) 00780 ) 00781 { 00782 /*"shall return"*/ 00783 LogError("invalid arg"); 00784 } 00785 else 00786 { 00787 /*Codes_SRS_IOTHUBCLIENT_LL_02_027: [If parameter result is IOTHUB_BACTHSTATE_FAILED then IoTHubClient_LL_SendComplete shall call all the non-NULL callbacks with the result parameter set to IOTHUB_CLIENT_CONFIRMATION_ERROR and the context set to the context passed originally in the SendEventAsync call.] */ 00788 /*Codes_SRS_IOTHUBCLIENT_LL_02_025: [If parameter result is IOTHUB_BATCHSTATE_SUCCESS then IoTHubClient_LL_SendComplete shall call all the non-NULL callbacks with the result parameter set to IOTHUB_CLIENT_CONFIRMATION_OK and the context set to the context passed originally in the SendEventAsync call.]*/ 00789 IOTHUB_CLIENT_CONFIRMATION_RESULT resultToBeCalled = (result == IOTHUB_BATCHSTATE_SUCCESS) ? IOTHUB_CLIENT_CONFIRMATION_OK : IOTHUB_CLIENT_CONFIRMATION_ERROR; 00790 PDLIST_ENTRY oldest; 00791 while ((oldest = DList_RemoveHeadList(completed)) != completed) 00792 { 00793 IOTHUB_MESSAGE_LIST* messageList = (IOTHUB_MESSAGE_LIST*)containingRecord(oldest, IOTHUB_MESSAGE_LIST, entry); 00794 /*Codes_SRS_IOTHUBCLIENT_LL_02_026: [If any callback is NULL then there shall not be a callback call.]*/ 00795 if (messageList->callback != NULL) 00796 { 00797 messageList->callback(resultToBeCalled, messageList->context); 00798 } 00799 IoTHubMessage_Destroy(messageList->messageHandle); 00800 free(messageList); 00801 } 00802 } 00803 } 00804 00805 IOTHUBMESSAGE_DISPOSITION_RESULT IoTHubClient_LL_MessageCallback(IOTHUB_CLIENT_LL_HANDLE handle, IOTHUB_MESSAGE_HANDLE message) 00806 { 00807 int result; 00808 /*Codes_SRS_IOTHUBCLIENT_LL_02_029: [If parameter handle is NULL then IoTHubClient_LL_MessageCallback shall return IOTHUBMESSAGE_ABANDONED.] */ 00809 if (handle == NULL) 00810 { 00811 LogError("invalid argument"); 00812 result = IOTHUBMESSAGE_ABANDONED; 00813 } 00814 else 00815 { 00816 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)handle; 00817 00818 /* Codes_SRS_IOTHUBCLIENT_LL_09_004: [IoTHubClient_LL_GetLastMessageReceiveTime shall return lastMessageReceiveTime in localtime] */ 00819 handleData->lastMessageReceiveTime = get_time(NULL); 00820 00821 /*Codes_SRS_IOTHUBCLIENT_LL_02_030: [IoTHubClient_LL_MessageCallback shall invoke the last callback function (the parameter messageCallback to IoTHubClient_LL_SetMessageCallback) passing the message and the passed userContextCallback.]*/ 00822 if (handleData->messageCallback != NULL) 00823 { 00824 result = handleData->messageCallback(message, handleData->messageUserContextCallback); 00825 } 00826 else 00827 { 00828 /*Codes_SRS_IOTHUBCLIENT_LL_02_032: [If the last callback function was NULL, then IoTHubClient_LL_MessageCallback shall return IOTHUBMESSAGE_ABANDONED.] */ 00829 LogError("user callback was NULL"); 00830 result = IOTHUBMESSAGE_ABANDONED; 00831 } 00832 } 00833 /*Codes_SRS_IOTHUBCLIENT_LL_02_031: [Then IoTHubClient_LL_MessageCallback shall return what the user function returns.]*/ 00834 return result; 00835 } 00836 00837 IOTHUB_CLIENT_RESULT IoTHubClient_LL_GetLastMessageReceiveTime(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, time_t* lastMessageReceiveTime) 00838 { 00839 IOTHUB_CLIENT_RESULT result; 00840 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle; 00841 00842 /* Codes_SRS_IOTHUBCLIENT_LL_09_001: [IoTHubClient_LL_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_INVALID_ARG if any of the arguments is NULL] */ 00843 if (handleData == NULL || lastMessageReceiveTime == NULL) 00844 { 00845 result = IOTHUB_CLIENT_INVALID_ARG; 00846 LOG_ERROR; 00847 } 00848 else 00849 { 00850 /* Codes_SRS_IOTHUBCLIENT_LL_09_002: [IoTHubClient_LL_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_INDEFINITE_TIME - and not set 'lastMessageReceiveTime' - if it is unable to provide the time for the last commands] */ 00851 if (handleData->lastMessageReceiveTime == INDEFINITE_TIME) 00852 { 00853 result = IOTHUB_CLIENT_INDEFINITE_TIME; 00854 LOG_ERROR; 00855 } 00856 else 00857 { 00858 /* Codes_SRS_IOTHUBCLIENT_LL_09_003: [IoTHubClient_LL_GetLastMessageReceiveTime shall return IOTHUB_CLIENT_OK if it wrote in the lastMessageReceiveTime the time when the last command was received] */ 00859 /* Codes_SRS_IOTHUBCLIENT_LL_09_004: [IoTHubClient_LL_GetLastMessageReceiveTime shall return lastMessageReceiveTime in localtime] */ 00860 *lastMessageReceiveTime = handleData->lastMessageReceiveTime; 00861 result = IOTHUB_CLIENT_OK; 00862 } 00863 } 00864 00865 return result; 00866 } 00867 00868 IOTHUB_CLIENT_RESULT IoTHubClient_LL_SetOption(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, const char* optionName, const void* value) 00869 { 00870 00871 IOTHUB_CLIENT_RESULT result; 00872 /*Codes_SRS_IOTHUBCLIENT_LL_02_034: [If iotHubClientHandle is NULL then IoTHubClient_LL_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.]*/ 00873 /*Codes_SRS_IOTHUBCLIENT_LL_02_035: [If optionName is NULL then IoTHubClient_LL_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00874 /*Codes_SRS_IOTHUBCLIENT_LL_02_036: [If value is NULL then IoTHubClient_LL_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */ 00875 if ( 00876 (iotHubClientHandle == NULL) || 00877 (optionName == NULL) || 00878 (value == NULL) 00879 ) 00880 { 00881 result = IOTHUB_CLIENT_INVALID_ARG; 00882 LogError("invalid argument (NULL)"); 00883 } 00884 else 00885 { 00886 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle; 00887 00888 /*Codes_SRS_IOTHUBCLIENT_LL_02_039: [ "messageTimeout" - once IoTHubClient_LL_SendEventAsync is called the message shall timeout after value miliseconds. Value is a pointer to a uint64. ]*/ 00889 if (strcmp(optionName, "messageTimeout") == 0) 00890 { 00891 /*this is an option handled by IoTHubClient_LL*/ 00892 /*Codes_SRS_IOTHUBCLIENT_LL_02_043: [ Calling IoTHubClient_LL_SetOption with value set to "0" shall disable the timeout mechanism for all new messages. ]*/ 00893 handleData->currentMessageTimeout = *(const uint64_t*)value; 00894 result = IOTHUB_CLIENT_OK; 00895 } 00896 else 00897 { 00898 /*Codes_SRS_IOTHUBCLIENT_LL_02_038: [Otherwise, IoTHubClient_LL shall call the function _SetOption of the underlying transport and return what that function is returning.] */ 00899 result = handleData->IoTHubTransport_SetOption(handleData->transportHandle, optionName, value); 00900 00901 if (result != IOTHUB_CLIENT_OK) 00902 { 00903 LogError("underlying transport failed, returned = %s", ENUM_TO_STRING(IOTHUB_CLIENT_RESULT, result)); 00904 } 00905 } 00906 } 00907 return result; 00908 } 00909 00910 #ifdef USE_UPLOADTOBLOB 00911 IOTHUB_CLIENT_RESULT IoTHubClient_LL_UploadToBlob(IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, const char* destinationFileName, const unsigned char* source, size_t size) 00912 { 00913 IOTHUB_CLIENT_RESULT result; 00914 /*Codes_SRS_IOTHUBCLIENT_LL_02_061: [ If iotHubClientHandle is NULL then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/ 00915 /*Codes_SRS_IOTHUBCLIENT_LL_02_062: [ If destinationFileName is NULL then IoTHubClient_LL_UploadToBlob shall fail and return IOTHUB_CLIENT_INVALID_ARG. ]*/ 00916 if ( 00917 (iotHubClientHandle == NULL) || 00918 (destinationFileName == NULL) || 00919 ((source == NULL) && (size >0)) 00920 ) 00921 { 00922 LogError("invalid parameters IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle=%p, const char* destinationFileName=%s, const unsigned char* source=%p, size_t size=%zu", iotHubClientHandle, destinationFileName, source, size); 00923 result = IOTHUB_CLIENT_INVALID_ARG; 00924 } 00925 else 00926 { 00927 IOTHUB_CLIENT_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_LL_HANDLE_DATA*)iotHubClientHandle; 00928 result = IoTHubClient_LL_UploadToBlob_Impl(iotHubClientHandle->uploadToBlobHandle, destinationFileName, source, size); 00929 } 00930 return result; 00931 } 00932 #endif
Generated on Tue Jul 12 2022 19:44:54 by 1.7.2