Ignore:
Timestamp:
Jun 22, 2021, 9:00:19 PM (3 years ago)
Author:
coas-nagasima
Message:

WolfSSLとAzure IoT SDKを更新

Location:
azure_iot_hub_f767zi/trunk/azure_iot_sdk
Files:
42 edited
1 moved

Legend:

Unmodified
Added
Removed
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/.vscode/c_cpp_properties.json

    r457 r464  
    2020                "${workspaceFolder}/../azure_iot_sdk/deps/parson",
    2121                "${workspaceFolder}/../azure_iot_sdk/umqtt/inc",
    22                 "${workspaceFolder}/../wolfssl-4.4.0/wolfssl",
    23                 "${workspaceFolder}/../wolfssl-4.4.0/wolfssl/wolfcrypt",
    24                 "${workspaceFolder}/../wolfssl-4.4.0",
     22                "${workspaceFolder}/../wolfssl-4.7.0/wolfssl",
     23                "${workspaceFolder}/../wolfssl-4.7.0/wolfssl/wolfcrypt",
     24                "${workspaceFolder}/../wolfssl-4.7.0",
    2525                "${workspaceFolder}/../zlib-1.2.11/src"
    2626            ],
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/Makefile

    r457 r464  
    9999OBJECTS += certs/certs.o
    100100OBJECTS += deps/parson/parson.o
     101OBJECTS += deps/uhttp/src/uhttp.o
    101102OBJECTS += iothub_client/src/blob.o
    102103OBJECTS += iothub_client/src/iothub.o
     
    144145OBJECTS += serializer/src/codefirst.o
    145146OBJECTS += serializer/src/commanddecoder.o
    146 OBJECTS += uhttp/src/uhttp.o
    147147OBJECTS += umqtt/src/mqtt_client.o
    148148OBJECTS += umqtt/src/mqtt_codec.o
     
    171171INCLUDE_PATHS += -I../../azure_iot_sdk/deps/parson
    172172INCLUDE_PATHS += -I../../azure_iot_sdk/deps/azure-macro-utils-c/inc
     173INCLUDE_PATHS += -I../../azure_iot_sdk/deps/uhttp/inc
    173174INCLUDE_PATHS += -I../../azure_iot_sdk/deps/umock-c/inc
    174175INCLUDE_PATHS += -I../../azure_iot_sdk/serializer/inc
    175 INCLUDE_PATHS += -I../../azure_iot_sdk/uhttp/inc
    176176INCLUDE_PATHS += -I../../azure_iot_sdk/umqtt/inc
    177 INCLUDE_PATHS += -I../../wolfssl-4.4.0/wolfssl
    178 INCLUDE_PATHS += -I../../wolfssl-4.4.0/wolfssl/wolfcrypt
    179 INCLUDE_PATHS += -I../../wolfssl-4.4.0
     177INCLUDE_PATHS += -I../../wolfssl-4.7.0/wolfssl
     178INCLUDE_PATHS += -I../../wolfssl-4.7.0/wolfssl/wolfcrypt
     179INCLUDE_PATHS += -I../../wolfssl-4.7.0
    180180INCLUDE_PATHS += -I../../zlib-1.2.11/src
    181181
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/adapters/httpapi_compact.c

    r457 r464  
    5151    char*           x509ClientCertificate;
    5252    char*           x509ClientPrivateKey;
    53     const char*     proxy_host;
    54     int             proxy_port;
    55     const char*     proxy_username;
    56     const char*     proxy_password;
    5753    XIO_HANDLE      xio_handle;
    5854    size_t          received_bytes_count;
     
    205201{
    206202    HTTP_HANDLE_DATA* http_instance;
     203    TLSIO_CONFIG tlsio_config;
    207204
    208205    if (hostName == NULL)
     
    226223            LogError("There is no memory to control the http connection");
    227224        }
    228         else if(mallocAndStrcpy_s((char**)&(http_instance->hostName), hostName) != 0)
    229         {
    230             LogError("failure allocate host name");
     225        else if (mallocAndStrcpy_s(&http_instance->hostName, hostName) != 0)
     226        {
     227            LogError("Failed copying hostname");
    231228            free(http_instance);
    232229            http_instance = NULL;
     
    234231        else
    235232        {
    236             http_instance->xio_handle = NULL;
    237             http_instance->is_connected = 0;
    238             http_instance->is_io_error = 0;
    239             http_instance->received_bytes_count = 0;
    240             http_instance->received_bytes = NULL;
    241             http_instance->certificate = NULL;
    242             http_instance->x509ClientCertificate = NULL;
    243             http_instance->x509ClientPrivateKey = NULL;
    244             http_instance->proxy_host = NULL;
    245             http_instance->proxy_port = 0;
    246             http_instance->proxy_username = NULL;
    247             http_instance->proxy_password = NULL;
     233            tlsio_config.hostname = http_instance->hostName;
     234            tlsio_config.port = 443;
     235            tlsio_config.underlying_io_interface = NULL;
     236            tlsio_config.underlying_io_parameters = NULL;
     237
     238            http_instance->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config);
     239
     240            /*Codes_SRS_HTTPAPI_COMPACT_21_016: [ If the HTTPAPI_CreateConnection failed to create the connection, it shall return NULL as the handle. ]*/
     241            if (http_instance->xio_handle == NULL)
     242            {
     243                LogError("Create connection failed");
     244                free(http_instance->hostName);
     245                free(http_instance);
     246                http_instance = NULL;
     247            }
     248            else
     249            {
     250                http_instance->is_connected = 0;
     251                http_instance->is_io_error = 0;
     252                http_instance->received_bytes_count = 0;
     253                http_instance->received_bytes = NULL;
     254                http_instance->certificate = NULL;
     255                http_instance->x509ClientCertificate = NULL;
     256                http_instance->x509ClientPrivateKey = NULL;
     257            }
    248258        }
    249259    }
     
    311321        }
    312322
    313         if (http_instance->hostName != NULL)
    314         {
    315             free((void*)http_instance->hostName);
    316         }
    317 
    318323#ifndef DO_NOT_COPY_TRUSTED_CERTS_STRING
    319324        /*Codes_SRS_HTTPAPI_COMPACT_21_018: [ If there is a certificate associated to this connection, the HTTPAPI_CloseConnection shall free all allocated memory for the certificate. ]*/
     
    336341        }
    337342
    338         if (http_instance->proxy_host != NULL)
    339         {
    340             free((void*)http_instance->proxy_host);
    341         }
    342         if (http_instance->proxy_username != NULL)
    343         {
    344             free((void*)http_instance->proxy_username);
    345         }
    346         if (http_instance->proxy_password != NULL)
    347         {
    348             free((void*)http_instance->proxy_password);
     343        if (http_instance->hostName)
     344        {
     345            free(http_instance->hostName);
    349346        }
    350347
     
    714711{
    715712    HTTPAPI_RESULT result;
    716     TLSIO_CONFIG tlsio_config;
    717     HTTP_PROXY_IO_CONFIG http_proxy_io_config;
    718713
    719714    if (http_instance->is_connected != 0)
     
    725720    {
    726721        http_instance->is_io_error = 0;
    727         tlsio_config.hostname = http_instance->hostName;
    728         tlsio_config.port = 443;
    729 
    730         if (http_instance->proxy_host != NULL) {
    731             tlsio_config.underlying_io_interface = http_proxy_io_get_interface_description();
    732         }
    733         else {
    734             tlsio_config.underlying_io_interface = NULL;
    735         }
    736 
    737         if (tlsio_config.underlying_io_interface != NULL) {
    738             tlsio_config.underlying_io_parameters = (void*)&http_proxy_io_config;
    739 
    740             http_proxy_io_config.proxy_hostname = http_instance->proxy_host;
    741             http_proxy_io_config.proxy_port = http_instance->proxy_port;
    742             http_proxy_io_config.username = http_instance->proxy_username;
    743             http_proxy_io_config.password = http_instance->proxy_password;
    744             http_proxy_io_config.hostname = http_instance->hostName;
    745             http_proxy_io_config.port = 443;
    746         }
    747         else {
    748             tlsio_config.underlying_io_parameters = NULL;
    749         }
    750 
    751         http_instance->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config);
    752 
    753         if (http_instance->xio_handle == NULL)
    754         {
    755             LogError("Create connection failed");
    756             free(http_instance);
    757             http_instance = NULL;
    758             result = HTTPAPI_ERROR;
    759         }
     722
    760723        /*Codes_SRS_HTTPAPI_COMPACT_21_022: [ If a Certificate was provided, the HTTPAPI_ExecuteRequest shall set this option on the transport layer. ]*/
    761         else if ((http_instance->certificate != NULL) &&
     724        if ((http_instance->certificate != NULL) &&
    762725            (xio_setoption(http_instance->xio_handle, OPTION_TRUSTED_CERT, http_instance->certificate) != 0))
    763726        {
     
    777740            (xio_setoption(http_instance->xio_handle, SU_OPTION_X509_PRIVATE_KEY, http_instance->x509ClientPrivateKey) != 0))
    778741        {
     742
    779743            /*Codes_SRS_HTTPAPI_COMPACT_06_006: [ If the transport failed setting the client certificate private key, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ] */
    780744            result = HTTPAPI_SET_OPTION_FAILED;
     
    800764                {
    801765                    xio_dowork(http_instance->xio_handle);
    802                     //LogInfo("Waiting for TLS connection");
     766                    LogInfo("Waiting for TLS connection");
    803767                    if ((countRetry--) < 0)
    804768                    {
     
    13471311#endif // DO_NOT_COPY_TRUSTED_CERTS_STRING
    13481312    }
    1349     else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
     1313    else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0 || strcmp(OPTION_X509_ECC_CERT, optionName) == 0)
    13501314    {
    13511315        int len;
     
    13701334        }
    13711335    }
    1372     else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
     1336    else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0 || strcmp(OPTION_X509_ECC_KEY, optionName) == 0)
    13731337    {
    13741338        int len;
     
    13951359    else if (strcmp(OPTION_HTTP_PROXY, optionName) == 0)
    13961360    {
    1397         HTTP_PROXY_OPTIONS* proxy_data = (HTTP_PROXY_OPTIONS*)value;
    1398         if (proxy_data->host_address == NULL || proxy_data->port <= 0)
    1399         {
    1400             LogError("invalid proxy_data values ( host_address = %p, port = %d)", proxy_data->host_address, proxy_data->port);
     1361        TLSIO_CONFIG tlsio_config;
     1362        HTTP_PROXY_IO_CONFIG proxy_config;
     1363        HTTP_PROXY_OPTIONS* proxy_options = (HTTP_PROXY_OPTIONS*)value;
     1364
     1365        if (proxy_options->host_address == NULL)
     1366        {
     1367            LogError("NULL host_address in proxy options");
    14011368            result = HTTPAPI_ERROR;
    14021369        }
     1370        else if (((proxy_options->username == NULL) || (proxy_options->password == NULL)) &&
     1371                (proxy_options->username != proxy_options->password))
     1372        {
     1373            LogError("Only one of username and password for proxy settings was NULL");
     1374            result = HTTPAPI_ERROR;
     1375        }
    14031376        else
    14041377        {
    1405             if(http_instance->proxy_host != NULL)
    1406             {
    1407                 free((void*)http_instance->proxy_host);
    1408                 http_instance->proxy_host = NULL;
    1409             }
    1410             if(mallocAndStrcpy_s((char**)&(http_instance->proxy_host), (const char*)proxy_data->host_address) != 0)
    1411             {
    1412                 LogError("failure allocate proxy host");
     1378
     1379            /* Workaround: xio interface is already created when HTTPAPI_CreateConnection is call without proxy support
     1380             * need to destroy the interface and create a new one with proxy information
     1381             */
     1382            OPTIONHANDLER_HANDLE xio_options;
     1383            if ((xio_options = xio_retrieveoptions(http_instance->xio_handle)) == NULL)
     1384            {
     1385                LogError("failed saving underlying I/O transport options");
    14131386                result = HTTPAPI_ERROR;
    14141387            }
    14151388            else
    14161389            {
    1417                 http_instance->proxy_port = proxy_data->port;
    1418 
    1419                 if (proxy_data->username != NULL && proxy_data->password != NULL)
    1420                 {
    1421                     if(http_instance->proxy_username != NULL)
     1390                xio_destroy(http_instance->xio_handle);
     1391
     1392                proxy_config.hostname = http_instance->hostName;
     1393                proxy_config.proxy_hostname = proxy_options->host_address;
     1394                proxy_config.password = proxy_options->password;
     1395                proxy_config.username = proxy_options->username;
     1396                proxy_config.proxy_port = proxy_options->port;
     1397                proxy_config.port = 443;
     1398
     1399                tlsio_config.hostname = http_instance->hostName;
     1400                tlsio_config.port = 443;
     1401                tlsio_config.underlying_io_interface =  http_proxy_io_get_interface_description();
     1402                tlsio_config.underlying_io_parameters = &proxy_config;
     1403
     1404                http_instance->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config);
     1405
     1406                if (http_instance->xio_handle == NULL)
     1407                {
     1408                    LogError("Failed to create xio handle with proxy configuration");
     1409                    result = HTTPAPI_ERROR;
     1410                }
     1411                else
     1412                {
     1413                    if (OptionHandler_FeedOptions(xio_options, http_instance->xio_handle) != OPTIONHANDLER_OK)
    14221414                    {
    1423                         free((void*)http_instance->proxy_username);
    1424                         http_instance->proxy_username = NULL;
    1425                     }
    1426                     if(mallocAndStrcpy_s((char**)&(http_instance->proxy_username), (const char*)proxy_data->username) != 0)
    1427                     {
    1428                         LogError("failure allocate proxy username");
    1429                         free((void*)http_instance->proxy_host);
    1430                         http_instance->proxy_host = NULL;
     1415                        LogError("Failed feeding existing options to new xio instance.");
    14311416                        result = HTTPAPI_ERROR;
    14321417                    }
    14331418                    else
    14341419                    {
    1435                         if(http_instance->proxy_password != NULL)
    1436                         {
    1437                           free((void*)http_instance->proxy_password);
    1438                           http_instance->proxy_password = NULL;
    1439                         }
    1440                         if(mallocAndStrcpy_s((char**)&(http_instance->proxy_password), (const char*)proxy_data->password) != 0)
    1441                         {
    1442                             LogError("failure allocate proxy password");
    1443                             free((void*)http_instance->proxy_host);
    1444                             http_instance->proxy_host = NULL;
    1445                             free((void*)http_instance->proxy_username);
    1446                             http_instance->proxy_username = NULL;
    1447                             result = HTTPAPI_ERROR;
    1448                         }
    1449                         else
    1450                         {
    1451                           result = HTTPAPI_OK;
    1452                         }
     1420                        result = HTTPAPI_OK;
    14531421                    }
    14541422                }
    1455                 else
    1456                 {
    1457                     result = HTTPAPI_OK;
    1458                 }
     1423
     1424                OptionHandler_Destroy(xio_options);
    14591425            }
    14601426        }
     
    14661432        LogInfo("unknown option %s", optionName);
    14671433    }
     1434
    14681435    return result;
    14691436}
     
    15101477#endif // DO_NOT_COPY_TRUSTED_CERTS_STRING
    15111478    }
    1512     else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
     1479    else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0 || strcmp(OPTION_X509_ECC_CERT, optionName) == 0)
    15131480    {
    15141481        certLen = strlen((const char*)value);
     
    15271494        }
    15281495    }
    1529     else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
     1496    else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0 || strcmp(OPTION_X509_ECC_KEY, optionName) == 0)
    15301497    {
    15311498        certLen = strlen((const char*)value);
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/adapters/platform_toppers.c

    r457 r464  
    5252const IO_INTERFACE_DESCRIPTION* platform_get_default_tlsio(void)
    5353{
    54         //return tlsio_esp_at_get_interface_description();
    55         return tlsio_wolfssl_get_interface_description();
     54        return tlsio_esp_at_get_interface_description();
     55        //return tlsio_wolfssl_get_interface_description();
    5656}
    5757
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/adapters/tlsio_wolfssl.c

    r457 r464  
    1919#include "azure_c_shared_utility/xlogging.h"
    2020#include "azure_c_shared_utility/shared_util_options.h"
    21 #include "azure_c_shared_utility/threadapi.h"
    2221
    2322typedef enum TLSIO_STATE_ENUM_TAG
     
    5352    char* x509privatekey;
    5453    int wolfssl_device_id;
    55     size_t socket_reads;
     54    char* hostname;
     55    bool ignore_host_name_check;
    5656} TLS_IO_INSTANCE;
    5757
    5858STATIC_VAR_UNUSED const char* const OPTION_WOLFSSL_SET_DEVICE_ID = "SetDeviceId";
    59 static const size_t SOCKET_READ_LIMIT = 10000; // 10,000 ms ?
     59static const size_t SOCKET_READ_LIMIT = 5;
    6060
    6161/*this function will clone an option given by name and value*/
     
    106106            }
    107107        }
     108        #ifdef INVALID_DEVID
     109        else if(strcmp(name, OPTION_WOLFSSL_SET_DEVICE_ID) == 0 )
     110        {
     111             int* value_clone;
     112
     113             if ((value_clone = malloc(sizeof(int))) == NULL)
     114             {
     115                 LogError("unable to clone device id option");
     116             }
     117             else
     118             {
     119                 *value_clone = *(int*)value;
     120             }
     121
     122             result = value_clone;
     123        }
     124        #endif
    108125        else
    109126        {
     
    127144        if ((strcmp(name, OPTION_TRUSTED_CERT) == 0) ||
    128145            (strcmp(name, SU_OPTION_X509_CERT) == 0) ||
    129             (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0))
     146            (strcmp(name, SU_OPTION_X509_PRIVATE_KEY) == 0) ||
     147            (strcmp(name, OPTION_WOLFSSL_SET_DEVICE_ID) == 0))
    130148        {
    131149            free((void*)value);
     
    185203                result = NULL;
    186204            }
     205            #ifdef INVALID_DEVID
     206            else if (
     207                (tls_io_instance->wolfssl_device_id != INVALID_DEVID) &&
     208                (OptionHandler_AddOption(result, OPTION_WOLFSSL_SET_DEVICE_ID, &tls_io_instance->wolfssl_device_id) != OPTIONHANDLER_OK)
     209                )
     210            {
     211                LogError("unable to save deviceid option");
     212                OptionHandler_Destroy(result);
     213                result = NULL;
     214            }
     215            #endif
    187216            else
    188217            {
     
    258287        int res;
    259288        tls_io_instance->tlsio_state = TLSIO_STATE_IN_HANDSHAKE;
    260         tls_io_instance->socket_reads = 0;
    261289
    262290        res = wolfSSL_connect(tls_io_instance->ssl);
    263291        if (res != SSL_SUCCESS)
    264292        {
    265             LogError("WolfSSL connect failed");
     293            // Error codes explained in https://www.wolfssl.com/docs/wolfssl-manual/appendix-c/
     294            LogError("WolfSSL connect failed (%d)", wolfSSL_get_error(tls_io_instance->ssl, res));
    266295            indicate_open_complete(tls_io_instance, IO_OPEN_ERROR);
    267296            tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
     
    355384        TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
    356385        unsigned char* new_socket_io_read_bytes;
     386        size_t socket_reads = 0;
    357387
    358388        AZURE_UNREFERENCED_PARAMETER(ssl);
    359         if (tls_io_instance->socket_io_read_byte_count == 0)
    360         {
    361             if (tls_io_instance->socket_reads >= SOCKET_READ_LIMIT) {
    362                 return WOLFSSL_CBIO_ERR_TIMEOUT;
    363             }
     389        while (tls_io_instance->socket_io_read_byte_count == 0 && socket_reads < SOCKET_READ_LIMIT)
     390        {
    364391            xio_dowork(tls_io_instance->socket_io);
    365             if (tls_io_instance->tlsio_state == TLSIO_STATE_IN_HANDSHAKE)
    366             {
    367                 tls_io_instance->socket_reads++;
    368                 ThreadAPI_Sleep(1);
    369                 return 0;
    370             }
     392            if (tls_io_instance->tlsio_state != TLSIO_STATE_IN_HANDSHAKE)
     393            {
     394                break;
     395            }
     396            socket_reads++;
    371397        }
    372398
     
    417443}
    418444
    419 static void on_send_complete(void* context, IO_SEND_RESULT send_result)
    420 {
    421         TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
    422         if ((tls_io_instance == NULL) || (tls_io_instance->on_send_complete == NULL))
    423                 return;
    424 
    425         tls_io_instance->on_send_complete(tls_io_instance->on_send_complete_callback_context, send_result);
    426 
    427         tls_io_instance->on_send_complete = NULL;
    428         tls_io_instance->on_send_complete_callback_context = NULL;
    429 }
    430 
    431445static int on_io_send(WOLFSSL *ssl, char *buf, int sz, void *context)
    432446{
    433     int result, ret;
     447    int result;
    434448    AZURE_UNREFERENCED_PARAMETER(ssl);
    435449
    436450    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
    437451
    438     if ((ret = xio_send(tls_io_instance->socket_io, buf, sz, on_send_complete, tls_io_instance)) != 0)
    439     {
    440         LogError("Failed sending bytes through underlying IO %d", ret);
     452    if (xio_send(tls_io_instance->socket_io, buf, sz, tls_io_instance->on_send_complete, tls_io_instance->on_send_complete_callback_context) != 0)
     453    {
     454        LogError("Failed sending bytes through underlying IO");
    441455        tls_io_instance->tlsio_state = TLSIO_STATE_ERROR;
    442456        indicate_error(tls_io_instance);
    443         result = 0;
     457        result = WOLFSSL_CBIO_ERR_GENERAL;
    444458    }
    445459    else
     
    455469    AZURE_UNREFERENCED_PARAMETER(ssl);
    456470    TLS_IO_INSTANCE* tls_io_instance = (TLS_IO_INSTANCE*)context;
    457     if (tls_io_instance->tlsio_state == TLSIO_STATE_OPEN) {
    458         LogInfo("on_handshake_done called in TLSIO_STATE_OPEN state");
    459     }
    460     else if (tls_io_instance->tlsio_state != TLSIO_STATE_IN_HANDSHAKE)
     471    if (tls_io_instance->tlsio_state != TLSIO_STATE_IN_HANDSHAKE)
    461472    {
    462473        LogInfo("on_handshake_done called when not in IN_HANDSHAKE state");
     
    558569}
    559570
     571static int enable_domain_check(TLS_IO_INSTANCE* tls_io_instance)
     572{
     573    int result = 0;
     574
     575    if (!tls_io_instance->ignore_host_name_check)
     576    {
     577        if (wolfSSL_check_domain_name(tls_io_instance->ssl, tls_io_instance->hostname) != WOLFSSL_SUCCESS)
     578        {
     579            result = MU_FAILURE;
     580        }
     581    }
     582
     583    return result;
     584}
     585
    560586static int prepare_wolfssl_open(TLS_IO_INSTANCE* tls_io_instance)
    561587{
    562588    int result;
    563     if (add_certificate_to_store(tls_io_instance) != 0)
     589
     590    if (enable_domain_check(tls_io_instance))
     591    {
     592        LogError("Failed to configure domain name verification");
     593        result = MU_FAILURE;
     594    }
     595    else if (add_certificate_to_store(tls_io_instance) != 0)
    564596    {
    565597        LogError("Failed to add certificates to store");
     
    575607        result = MU_FAILURE;
    576608    }
    577 #ifdef INVALID_DEVID
    578     else if (tls_io_instance->wolfssl_device_id != INVALID_DEVID && wolfSSL_SetDevId(tls_io_instance->ssl, tls_io_instance->wolfssl_device_id) != WOLFSSL_SUCCESS)
    579     {
    580         LogError("Failure setting device id");
    581         result = MU_FAILURE;
    582     }
    583 #endif
    584609    else
    585610    {
     
    628653            {
    629654                LogError("Cannot create the wolfSSL context");
     655                free(result);
     656                result = NULL;
     657            }
     658            else if (mallocAndStrcpy_s(&result->hostname, tls_io_config->hostname) != 0)
     659            {
     660                LogError("Failed copying the target hostname.");
    630661                free(result);
    631662                result = NULL;
     
    660691                    LogError("Failed getting socket IO interface description.");
    661692                    wolfSSL_CTX_free(result->ssl_context);
     693                    free(result->hostname);
    662694                    free(result);
    663695                    result = NULL;
     
    670702                        LogError("Failure connecting to underlying socket_io");
    671703                        wolfSSL_CTX_free(result->ssl_context);
     704                        free(result->hostname);
    672705                        free(result);
    673706                        result = NULL;
     
    677710                        LogError("Failure connecting to underlying socket_io");
    678711                        wolfSSL_CTX_free(result->ssl_context);
     712                        free(result->hostname);
    679713                        free(result);
    680714                        result = NULL;
     
    719753
    720754        xio_destroy(tls_io_instance->socket_io);
     755        free(tls_io_instance->hostname);
    721756        free(tls_io);
    722757    }
     
    843878            result = MU_FAILURE;
    844879        }
    845         if (tls_io_instance->on_send_complete != NULL)
    846         {
    847             LogError("Error writing data");
    848             result = MU_FAILURE;
    849         }
    850880        else
    851881        {
     
    882912            (tls_io_instance->tlsio_state != TLSIO_STATE_ERROR))
    883913        {
    884             if (tls_io_instance->tlsio_state != TLSIO_STATE_OPENING_UNDERLYING_IO)
    885                 decode_ssl_received_bytes(tls_io_instance);
     914            decode_ssl_received_bytes(tls_io_instance);
    886915            xio_dowork(tls_io_instance->socket_io);
    887916        }
     
    892921static int process_option(char** destination, const char* name, const char* value)
    893922{
     923
     924    (void) name;
     925   
    894926    int result;
    895927    if (*destination != NULL)
     
    944976        {
    945977            int device_id = *((int *)value);
    946             if (tls_io_instance->ssl != NULL)
    947             {
    948                 if (tls_io_instance->ssl != NULL && wolfSSL_SetDevId(tls_io_instance->ssl, device_id) != WOLFSSL_SUCCESS)
    949                 {
    950                     LogError("Failure setting device id on ssl");
    951                     result = MU_FAILURE;
    952                 }
    953                 else
    954                 {
    955                     result = 0;
    956                 }
     978            if (tls_io_instance->ssl != NULL && wolfSSL_SetDevId(tls_io_instance->ssl, device_id) != WOLFSSL_SUCCESS)
     979            {
     980                LogError("Failure setting device id on ssl");
     981                result = MU_FAILURE;
    957982            }
    958983            else
    959984            {
    960                 // Save the id till we create the ssl object
     985                // Save the device Id even if ssl object not yet created.
    961986                tls_io_instance->wolfssl_device_id = device_id;
    962987                result = 0;
     
    964989        }
    965990#endif
     991        else if (strcmp("ignore_host_name_check", optionName) == 0)
     992        {
     993            bool* server_name_check = (bool*)value;
     994            tls_io_instance->ignore_host_name_check = *server_name_check;
     995            result = 0;
     996        }
    966997        else
    967998        {
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/crt_abstractions.h

    r457 r464  
    66
    77#ifdef __cplusplus
     8#include <cstdint>
    89#include <cstdio>
    910#include <cstring>
     
    1112#include <cmath>
    1213#else // __cplusplus
     14#include <stdint.h>
    1315#include <stdio.h>
    1416#include <string.h>
     
    9698MOCKABLE_FUNCTION(, int, unsignedIntToString, char*, destination, size_t, destinationSize, unsigned int, value);
    9799MOCKABLE_FUNCTION(, int, size_tToString, char*, destination, size_t, destinationSize, size_t, value);
     100MOCKABLE_FUNCTION(, int, uint64_tToString, char*, destination, size_t, destinationSize, uint64_t, value);
    98101
    99102/*following logic shall define the TOUPPER and ISDIGIT, we do that because the SDK is not happy with some Arduino implementation of it.*/
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/sastoken.h

    r457 r464  
    44#ifndef SASTOKEN_H
    55#define SASTOKEN_H
     6
     7#include <stdint.h>
    68
    79#ifdef __cplusplus
     
    1820
    1921    MOCKABLE_FUNCTION(, bool, SASToken_Validate, STRING_HANDLE, sasToken);
    20     MOCKABLE_FUNCTION(, STRING_HANDLE, SASToken_Create, STRING_HANDLE, key, STRING_HANDLE, scope, STRING_HANDLE, keyName, size_t, expiry);
    21     MOCKABLE_FUNCTION(, STRING_HANDLE, SASToken_CreateString, const char*, key, const char*, scope, const char*, keyName, size_t, expiry);
     22    MOCKABLE_FUNCTION(, STRING_HANDLE, SASToken_Create, STRING_HANDLE, key, STRING_HANDLE, scope, STRING_HANDLE, keyName, uint64_t, expiry);
     23    MOCKABLE_FUNCTION(, STRING_HANDLE, SASToken_CreateString, const char*, key, const char*, scope, const char*, keyName, uint64_t, expiry);
    2224
    2325#ifdef __cplusplus
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/shared_util_options.h

    r457 r464  
    2929    static STATIC_VAR_UNUSED const char* const OPTION_OPENSSL_CIPHER_SUITE = "CipherSuite";
    3030
     31    static STATIC_VAR_UNUSED const char* const OPTION_OPENSSL_ENGINE = "Engine";
     32    static STATIC_VAR_UNUSED const char* const OPTION_OPENSSL_PRIVATE_KEY_TYPE = "x509PrivatekeyType";
     33
     34    typedef enum OPTION_OPENSSL_KEY_TYPE_TAG
     35    {
     36        KEY_TYPE_DEFAULT,
     37        KEY_TYPE_ENGINE
     38    } OPTION_OPENSSL_KEY_TYPE;
     39
    3140    static STATIC_VAR_UNUSED const char* const SU_OPTION_X509_CERT = "x509certificate";
    3241    static STATIC_VAR_UNUSED const char* const SU_OPTION_X509_PRIVATE_KEY = "x509privatekey";
     
    4554    static STATIC_VAR_UNUSED const char* const OPTION_SET_TLS_RENEGOTIATION = "tls_renegotiation";
    4655
    47     // DEPRECATED: The underlying security library for your platform will use a secure TLS version 
     56    // DEPRECATED: The underlying security library for your platform will use a secure TLS version
    4857    // that in general  should not be overridden with OPTION_TLS_VERSION.
    4958    static STATIC_VAR_UNUSED const char* const OPTION_TLS_VERSION = "tls_version";
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/inc/azure_c_shared_utility/tickcounter.h

    r457 r464  
    1818#endif /* __cplusplus */
    1919
    20 #if defined(_WIN32) || defined(__MBED__) || defined(__APPLE__)
    2120    typedef uint_fast64_t tickcounter_ms_t; // Use 64-bit because of 32-bit is going to roll over back to zero after roughly 49.7 days that is not good for IoT devices which need keep running for months
    22 #else
    23     typedef uint_fast32_t tickcounter_ms_t;
    24 #endif
    2521    typedef struct TICK_COUNTER_INSTANCE_TAG *TICK_COUNTER_HANDLE;
    2622
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/src/buffer.c

    r457 r464  
    541541        {
    542542            //put b2 ahead of b1: [b2][b1], return b1
    543             if (b2->size ==0)
     543            if (b2->size == 0)
    544544            {
    545545                // do nothing
    546546                result = 0;
     547            }
     548            else if (b1->size + b2->size < b2->size)
     549            {
     550                LogError("Failure: size_t overflow.");
     551                result = MU_FAILURE;
    547552            }
    548553            else
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/src/crt_abstractions.c

    r457 r464  
    66#include <stdlib.h>
    77#include <stdarg.h>
     8#include <stdint.h>
    89#include <string.h>
    910#include <limits.h>
     
    598599        case FST_NUMBER:
    599600            val = fraction * pow(10.0, (double)exponential) * (double)signal;
    600             if ((val >= (FLT_MAX * (-1.0f))) && (val <= FLT_MAX))
     601            if ((val >= ((double)FLT_MAX * (-1.0))) && (val <= (double)FLT_MAX))
    601602            {
    602603                /*Codes_SRS_CRT_ABSTRACTIONS_21_016: [The strtof_s must return the float that represents the value in the initial part of the string. If any.]*/
     
    836837    return result;
    837838}
     839
     840/*takes "value" and transforms it into a decimal string*/
     841/*10 => "10"*/
     842/*return 0 when everything went ok*/
     843int uint64_tToString(char* destination, size_t destinationSize, uint64_t value)
     844{
     845    int result;
     846    size_t pos;
     847    /*the below loop gets the number in reverse order*/
     848    if (
     849        (destination == NULL) ||
     850        (destinationSize < 2) /*because the smallest number is '0\0' which requires 2 characters*/
     851        )
     852    {
     853        result = MU_FAILURE;
     854    }
     855    else
     856    {
     857        pos = 0;
     858        do
     859        {
     860            destination[pos++] = '0' + (value % 10);
     861            value /= 10;
     862        } while ((value > 0) && (pos < (destinationSize - 1)));
     863
     864        if (value == 0)
     865        {
     866            size_t w;
     867            destination[pos] = '\0';
     868            /*all converted and they fit*/
     869            for (w = 0; w <= (pos - 1) >> 1; w++)
     870            {
     871                char temp;
     872                temp = destination[w];
     873                destination[w] = destination[pos - 1 - w];
     874                destination[pos - 1 - w] = temp;
     875            }
     876            result = 0;
     877        }
     878        else
     879        {
     880            result = MU_FAILURE;
     881        }
     882    }
     883    return result;
     884}
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/src/httpapiexsas.c

    r457 r464  
    107107{
    108108    /*Codes_SRS_HTTPAPIEXSAS_06_005: [If the parameter handle is NULL then HTTAPIEX_SAS_Destroy shall do nothing and return.]*/
    109     if (handle)
     109    HTTPAPIEX_SAS_STATE* state = (HTTPAPIEX_SAS_STATE*)handle;
     110    if (state)
    110111    {
    111         HTTPAPIEX_SAS_STATE* state = (HTTPAPIEX_SAS_STATE*)handle;
    112112        /*Codes_SRS_HTTPAPIEXSAS_06_006: [HTTAPIEX_SAS_Destroy shall deallocate any structures denoted by the parameter handle.]*/
    113113        if (state->key)
     
    159159                        /*Codes_SRS_HTTPAPIEXSAS_06_011: [SASToken_Create shall be invoked.]*/
    160160                        /*Codes_SRS_HTTPAPIEXSAS_06_012: [If the return result of SASToken_Create is NULL then fallthrough.]*/
    161                         size_t expiry = (size_t)(difftime(currentTime, 0) + 3600);
     161                        uint64_t expiry = (uint64_t)(difftime(currentTime, 0) + 3600);
    162162                        newSASToken = SASToken_CreateString(state->key, state->uriResource, state->keyName, expiry);
    163163                    }
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/src/sastoken.c

    r457 r464  
    2424        if (expiryASCII[i] >= '0' && expiryASCII[i] <= '9')
    2525        {
    26             value = value * 10 + (double)(expiryASCII[i] - '0');
     26            value = value * 10 + ((double)expiryASCII[i] - (double)'0');
    2727        }
    2828        else
     
    203203}
    204204
    205 static STRING_HANDLE construct_sas_token(const char* key, const char* scope, const char* keyname, size_t expiry)
     205static STRING_HANDLE construct_sas_token(const char* key, const char* scope, const char* keyname, uint64_t expiry)
    206206{
    207207    STRING_HANDLE result;
     
    221221    {
    222222        /*Codes_SRS_SASTOKEN_06_026: [If the conversion to string form fails for any reason then SASToken_Create shall return NULL.]*/
    223         if (size_tToString(tokenExpirationTime, sizeof(tokenExpirationTime), expiry) != 0)
     223        if (uint64_tToString(tokenExpirationTime, sizeof(tokenExpirationTime), expiry) != 0)
    224224        {
    225225            LogError("For some reason converting seconds to a string failed.  No SAS can be generated.");
     
    303303}
    304304
    305 STRING_HANDLE SASToken_Create(STRING_HANDLE key, STRING_HANDLE scope, STRING_HANDLE keyName, size_t expiry)
     305STRING_HANDLE SASToken_Create(STRING_HANDLE key, STRING_HANDLE scope, STRING_HANDLE keyName, uint64_t expiry)
    306306{
    307307    STRING_HANDLE result;
     
    326326}
    327327
    328 STRING_HANDLE SASToken_CreateString(const char* key, const char* scope, const char* keyName, size_t expiry)
     328STRING_HANDLE SASToken_CreateString(const char* key, const char* scope, const char* keyName, uint64_t expiry)
    329329{
    330330    STRING_HANDLE result;
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/c-utility/src/sha384-512.c

    r457 r464  
    469469    if (!length)
    470470        return shaSuccess;
     471   
     472    if (length > (sizeof(context->Message_Block) / sizeof(context->Message_Block[0])))
     473        return shaBadParam;
    471474
    472475    if (!context || !message_array)
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/deps/uhttp/src/uhttp.c

    r457 r464  
    136136    int spaceFound = 0;
    137137    const char* initSpace = NULL;
    138     char status_code[4];
     138    char status_code[4] = { 0 };
    139139
    140140    for (index = 0; index < len; index++)
     
    186186        {
    187187            colonEncountered = true;
    188             size_t keyLen = (&buffer[index])-targetPos;
    189 
    190             if (headerKey != NULL)
    191             {
    192                 free(headerKey);
    193                 headerKey = NULL;
    194             }
    195             headerKey = (char*)malloc(keyLen+1);
    196             if (headerKey == NULL)
    197             {
     188            size_t keyLen = (&buffer[index]) - targetPos;
     189
     190            if (keyLen == 0)
     191            {
     192                LogError("Invalid header name with zero length.");
    198193                result = MU_FAILURE;
    199194                continueProcessing = false;
     
    201196            else
    202197            {
    203                 memcpy(headerKey, targetPos, keyLen);
    204                 headerKey[keyLen] = '\0';
    205 
    206                 // Convert to lower case
    207                 for (size_t inner = 0; inner < keyLen; inner++)
    208                 {
    209                     headerKey[inner] = (char)tolower(headerKey[inner]);
    210                 }
    211 
    212                 targetPos = buffer+index+1;
    213                 crlfEncounted = false;
     198                if (headerKey != NULL)
     199                {
     200                    free(headerKey);
     201                    headerKey = NULL;
     202                }
     203                headerKey = (char*)malloc(keyLen + 1);
     204                if (headerKey == NULL)
     205                {
     206                    result = MU_FAILURE;
     207                    continueProcessing = false;
     208                }
     209                else
     210                {
     211                    memcpy(headerKey, targetPos, keyLen);
     212                    headerKey[keyLen] = '\0';
     213
     214                    // Convert to lower case
     215                    for (size_t inner = 0; inner < keyLen; inner++)
     216                    {
     217                        headerKey[inner] = (char)tolower(headerKey[inner]);
     218                    }
     219
     220                    targetPos = buffer+index+1;
     221                    crlfEncounted = false;
     222                }
    214223            }
    215224        }
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_client_authorization.h

    r457 r464  
    4242MOCKABLE_FUNCTION(, IOTHUB_CREDENTIAL_TYPE, IoTHubClient_Auth_Set_x509_Type, IOTHUB_AUTHORIZATION_HANDLE, handle, bool, enable_x509);
    4343MOCKABLE_FUNCTION(, IOTHUB_CREDENTIAL_TYPE, IoTHubClient_Auth_Get_Credential_Type, IOTHUB_AUTHORIZATION_HANDLE, handle);
    44 MOCKABLE_FUNCTION(, char*, IoTHubClient_Auth_Get_SasToken, IOTHUB_AUTHORIZATION_HANDLE, handle, const char*, scope, size_t, expiry_time_relative_seconds, const char*, key_name);
     44MOCKABLE_FUNCTION(, char*, IoTHubClient_Auth_Get_SasToken, IOTHUB_AUTHORIZATION_HANDLE, handle, const char*, scope, uint64_t, expiry_time_relative_seconds, const char*, key_name);
    4545MOCKABLE_FUNCTION(, int, IoTHubClient_Auth_Set_xio_Certificate, IOTHUB_AUTHORIZATION_HANDLE, handle, XIO_HANDLE, xio);
    4646MOCKABLE_FUNCTION(, const char*, IoTHubClient_Auth_Get_DeviceId, IOTHUB_AUTHORIZATION_HANDLE, handle);
     
    4949MOCKABLE_FUNCTION(, SAS_TOKEN_STATUS, IoTHubClient_Auth_Is_SasToken_Valid, IOTHUB_AUTHORIZATION_HANDLE, handle);
    5050MOCKABLE_FUNCTION(, int, IoTHubClient_Auth_Get_x509_info, IOTHUB_AUTHORIZATION_HANDLE, handle, char**, x509_cert, char**, x509_key);
    51 MOCKABLE_FUNCTION(, int, IoTHubClient_Auth_Set_SasToken_Expiry, IOTHUB_AUTHORIZATION_HANDLE, handle, size_t, expiry_time_seconds);
    52 MOCKABLE_FUNCTION(, size_t, IoTHubClient_Auth_Get_SasToken_Expiry, IOTHUB_AUTHORIZATION_HANDLE, handle);
     51MOCKABLE_FUNCTION(, int, IoTHubClient_Auth_Set_SasToken_Expiry, IOTHUB_AUTHORIZATION_HANDLE, handle, uint64_t, expiry_time_seconds);
     52MOCKABLE_FUNCTION(, uint64_t, IoTHubClient_Auth_Get_SasToken_Expiry, IOTHUB_AUTHORIZATION_HANDLE, handle);
    5353
    5454
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/inc/internal/iothub_internal_consts.h

    r457 r464  
    1010#endif
    1111
    12     static const char* IOTHUB_API_VERSION = "2019-10-01";
    13     // TODO: https://github.com/Azure/azure-iot-sdk-c/issues/1547 tracks removing this preview
    14     // variable once the underlying logic is enabled on all IoTHubs.
    15     static const char* IOTHUB_API_PREVIEW_VERSION = "2020-05-31-preview";
    16 
     12    static const char* IOTHUB_API_VERSION = "2020-09-30";
    1713    static const char* SECURITY_INTERFACE_INTERNAL_ID = "iothub-interface-internal-id";
    1814    static const char* SECURITY_INTERFACE_INTERNAL_ID_VALUE = "security*azureiot*com^SecurityAgent^1*0*0";
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/inc/iothub_client.h

    r457 r464  
    22// Licensed under the MIT license. See LICENSE file in the project root for full license information.
    33
     4//**********************************************************************
     5// NOTE: THIS HEADER IS DEPRECATED
     6//
     7// Functions in this header will be maintained for backward compatability.
     8// New applications should use iothub_device_client.h.
     9//
     10//**********************************************************************
     11
    412/** @file iothub_client.h
    5 *    @brief Extends the IoTHubCLient_LL module with additional features.
     13*    @brief Extends the IoTHubClient_LL with additional features.
    614*
    715*    @note  DEPRECATED. New users use iothub_device_client.h for IoTHubClient APIs.
     
    3846
    3947    /**
    40     * @brief    Creates a IoT Hub client for communication with an existing
    41     *             IoT Hub using the specified connection string parameter.
    42     *
    43     * @param    connectionString    Pointer to a character string
    44     * @param    protocol            Function pointer for protocol implementation
    45     *
    46     *            Sample connection string:
    47     *                <blockquote>
    48     *                    <pre>HostName=[IoT Hub name goes here].[IoT Hub suffix goes here, e.g., private.azure-devices-int.net];DeviceId=[Device ID goes here];SharedAccessKey=[Device key goes here];</pre>
    49     *                   <pre>HostName=[IoT Hub name goes here].[IoT Hub suffix goes here, e.g., private.azure-devices-int.net];DeviceId=[Device ID goes here];SharedAccessSignature=SharedAccessSignature sr=[IoT Hub name goes here].[IoT Hub suffix goes here, e.g., private.azure-devices-int.net]/devices/[Device ID goes here]&sig=[SAS Token goes here]&se=[Expiry Time goes here];</pre>
    50     *                </blockquote>
    51     *
    52     * @return    A non-NULL @c IOTHUB_CLIENT_HANDLE value that is used when
    53     *             invoking other functions for IoT Hub client and @c NULL on failure.
     48    * @deprecated IoTHubClient_CreateFromConnectionString is deprecated.  Use IoTHubDeviceClient_CreateFromConnectionString instead.
    5449    */
    5550    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_HANDLE, IoTHubClient_CreateFromConnectionString, const char*, connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
    5651
    5752    /**
    58     * @brief    Creates a IoT Hub client for communication with an existing IoT
    59     *             Hub using the specified parameters.
    60     *
    61     * @param    config    Pointer to an @c IOTHUB_CLIENT_CONFIG structure
    62     *
    63     *            The API does not allow sharing of a connection across multiple
    64     *            devices. This is a blocking call.
    65     *
    66     * @return    A non-NULL @c IOTHUB_CLIENT_HANDLE value that is used when
    67     *             invoking other functions for IoT Hub client and @c NULL on failure.
     53    * @deprecated IoTHubClient_Create is deprecated.  Use IoTHubDeviceClient_Create instead.
    6854    */
    6955    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_HANDLE, IoTHubClient_Create, const IOTHUB_CLIENT_CONFIG*, config);
    7056
    7157    /**
    72     * @brief    Creates a IoT Hub client for communication with an existing IoT
    73     *             Hub using the specified parameters.
    74     *
    75     * @param    transportHandle    TRANSPORT_HANDLE which represents a connection.
    76     * @param    config    Pointer to an @c IOTHUB_CLIENT_CONFIG structure
    77     *
    78     *            The API allows sharing of a connection across multiple
    79     *            devices. This is a blocking call.
    80     *
    81     * @return    A non-NULL @c IOTHUB_CLIENT_HANDLE value that is used when
    82     *             invoking other functions for IoT Hub client and @c NULL on failure.
     58    * @deprecated IoTHubClient_CreateWithTransport is deprecated.  Use IoTHubDeviceClient_CreateWithTransport instead.
    8359    */
    8460    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_HANDLE, IoTHubClient_CreateWithTransport, TRANSPORT_HANDLE, transportHandle, const IOTHUB_CLIENT_CONFIG*, config);
    8561
    8662    /**
    87     * @brief    Creates a IoT Hub client for communication with an existing IoT
    88     *             Hub using the device auth module.
    89     *
    90     * @param    iothub_uri    Pointer to an ioThub hostname received in the registration process
    91     * @param    device_id    Pointer to the device Id of the device
    92     * @param    protocol    Function pointer for protocol implementation
    93     *
    94     * @return    A non-NULL @c IOTHUB_CLIENT_LL_HANDLE value that is used when
    95     *             invoking other functions for IoT Hub client and @c NULL on failure.
     63    * @deprecated IoTHubClient_CreateFromDeviceAuth is deprecated.  Use IoTHubDeviceClient_CreateFromDeviceAuth instead.
    9664    */
    9765    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_HANDLE, IoTHubClient_CreateFromDeviceAuth, const char*, iothub_uri, const char*, device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
    9866
    9967    /**
    100     * @brief    Disposes of resources allocated by the IoT Hub client. This is a
    101     *             blocking call.
    102     *
    103     * @param    iotHubClientHandle    The handle created by a call to the create function.
     68    * @deprecated IoTHubClient_Destroy is deprecated.  Use IoTHubDeviceClient_Destroy instead.
    10469    */
    10570    MOCKABLE_FUNCTION(, void, IoTHubClient_Destroy, IOTHUB_CLIENT_HANDLE, iotHubClientHandle);
    10671
    10772    /**
    108     * @brief    Asynchronous call to send the message specified by @p eventMessageHandle.
    109     *
    110     * @param    iotHubClientHandle               The handle created by a call to the create function.
    111     * @param    eventMessageHandle               The handle to an IoT Hub message.
    112     * @param    eventConfirmationCallback      The callback specified by the device for receiving
    113     *                                         confirmation of the delivery of the IoT Hub message.
    114     *                                         This callback can be expected to invoke the
    115     *                                         ::IoTHubClient_SendEventAsync function for the
    116     *                                         same message in an attempt to retry sending a failing
    117     *                                         message. The user can specify a @c NULL value here to
    118     *                                         indicate that no callback is required.
    119     * @param    userContextCallback            User specified context that will be provided to the
    120     *                                         callback. This can be @c NULL.
    121     *
    122     *            @b NOTE: The application behavior is undefined if the user calls
    123     *            the ::IoTHubClient_Destroy function from within any callback.
    124     * @remarks
    125     *            The IOTHUB_MESSAGE_HANDLE instance provided as argument is copied by the function,
    126     *            so this argument can be destroyed by the calling application right after IoTHubClient_SendEventAsync returns.
    127     *            The copy of @c eventMessageHandle is later destroyed by the iothub client when the message is effectively sent, if a failure sending it occurs, or if the client is destroyed.
    128     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     73    * @deprecated IoTHubClient_SendEventAsync is deprecated.  Use IoTHubDeviceClient_SendEventAsync instead.
    12974    */
    13075    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SendEventAsync, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback);
    13176
    13277    /**
    133     * @brief    This function returns the current sending status for IoTHubClient.
    134     *
    135     * @param    iotHubClientHandle        The handle created by a call to the create function.
    136     * @param    iotHubClientStatus        The sending state is populated at the address pointed
    137     *                                     at by this parameter. The value will be set to
    138     *                                     @c IOTHUBCLIENT_SENDSTATUS_IDLE if there is currently
    139     *                                     no item to be sent and @c IOTHUBCLIENT_SENDSTATUS_BUSY
    140     *                                     if there are.
    141     *
    142     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     78    * @deprecated IoTHubClient_GetSendStatus is deprecated.  Use IoTHubDeviceClient_GetSendStatus instead.
    14379    */
    14480    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_GetSendStatus, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_STATUS*, iotHubClientStatus);
    14581
    14682    /**
    147     * @brief    Sets up the message callback to be invoked when IoT Hub issues a
    148     *             message to the device. This is a blocking call.
    149     *
    150     * @param    iotHubClientHandle               The handle created by a call to the create function.
    151     * @param    messageCallback                The callback specified by the device for receiving
    152     *                                         messages from IoT Hub.
    153     * @param    userContextCallback            User specified context that will be provided to the
    154     *                                         callback. This can be @c NULL.
    155     *
    156     *            @b NOTE: The application behavior is undefined if the user calls
    157     *            the ::IoTHubClient_Destroy function from within any callback.
    158     *
    159     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     83    * @deprecated IoTHubClient_SetMessageCallback is deprecated.  Use IoTHubDeviceClient_SetMessageCallback instead.
    16084    */
    16185    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetMessageCallback, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC, messageCallback, void*, userContextCallback);
    16286
    16387    /**
    164     * @brief    Sets up the connection status callback to be invoked representing the status of
    165     * the connection to IOT Hub. This is a blocking call.
    166     *
    167     * @param    iotHubClientHandle                       The handle created by a call to the create function.
    168     * @param    connectionStatusCallback                The callback specified by the device for receiving
    169     *                                                 updates about the status of the connection to IoT Hub.
    170     * @param    userContextCallback                    User specified context that will be provided to the
    171     *                                                 callback. This can be @c NULL.
    172     *
    173     *            @b NOTE: The application behavior is undefined if the user calls
    174     *            the ::IoTHubClient_LL_Destroy function from within any callback.
    175     *
    176     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     88    * @deprecated IoTHubClient_SetConnectionStatusCallback is deprecated.  Use IoTHubDeviceClient_SetConnectionStatusCallback instead.
    17789    */
    17890    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetConnectionStatusCallback, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK, connectionStatusCallback, void*, userContextCallback);
    17991
    18092    /**
    181     * @brief    Sets up the connection status callback to be invoked representing the status of
    182     * the connection to IOT Hub. This is a blocking call.
    183     *
    184     * @param    iotHubClientHandle                       The handle created by a call to the create function.
    185     * @param    retryPolicy                             The policy to use to reconnect to IoT Hub when a
    186     *                                               connection drops.
    187     * @param    retryTimeoutLimitInSeconds            Maximum amount of time(seconds) to attempt reconnection when a
    188     *                                               connection drops to IOT Hub.
    189     *
    190     *            @b NOTE: The application behavior is undefined if the user calls
    191     *            the ::IoTHubClient_LL_Destroy function from within any callback.
    192     *
    193     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     93    * @deprecated IoTHubClient_SetRetryPolicy is deprecated.  Use IoTHubDeviceClient_SetRetryPolicy instead.
    19494    */
    19595    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetRetryPolicy, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY, retryPolicy, size_t, retryTimeoutLimitInSeconds);
    19696
    19797    /**
    198     * @brief    Sets up the connection status callback to be invoked representing the status of
    199     * the connection to IOT Hub. This is a blocking call.
    200     *
    201     * @param    iotHubClientHandle                       The handle created by a call to the create function.
    202     * @param    retryPolicy                             Out parameter containing the policy to use to reconnect to IoT Hub.
    203     * @param    retryTimeoutLimitInSeconds            Out parameter containing maximum amount of time in seconds to attempt reconnection
    204     to IOT Hub.
    205     *
    206     *            @b NOTE: The application behavior is undefined if the user calls
    207     *            the ::IoTHubClient_LL_Destroy function from within any callback.
    208     *
    209     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     98    * @deprecated IoTHubClient_GetRetryPolicy is deprecated.  Use IoTHubDeviceClient_GetRetryPolicy instead.
    21099    */
    211100    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_GetRetryPolicy, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY*, retryPolicy, size_t*, retryTimeoutLimitInSeconds);
    212101
    213102    /**
    214     * @brief    This function returns in the out parameter @p lastMessageReceiveTime
    215     *             what was the value of the @c time function when the last message was
    216     *             received at the client.
    217     *
    218     * @param    iotHubClientHandle                The handle created by a call to the create function.
    219     * @param    lastMessageReceiveTime          Out parameter containing the value of @c time function
    220     *                                             when the last message was received.
    221     *
    222     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     103    * @deprecated IoTHubClient_GetLastMessageReceiveTime is deprecated.  Use IoTHubDeviceClient_GetLastMessageReceiveTime instead.
    223104    */
    224105    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_GetLastMessageReceiveTime, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, time_t*, lastMessageReceiveTime);
    225106
    226107    /**
    227     * @brief    This API sets a runtime option identified by parameter @p optionName
    228     *             to a value pointed to by @p value. @p optionName and the data type
    229     *             @p value is pointing to are specific for every option.
    230     *
    231     * @param    iotHubClientHandle    The handle created by a call to the create function.
    232     * @param    optionName              Name of the option.
    233     * @param    value                  The value.
    234     *
    235     *            The options that can be set via this API are:
    236     *                - @b timeout - the maximum time in milliseconds a communication is
    237     *                  allowed to use. @p value is a pointer to an @c unsigned @c int with
    238     *                  the timeout value in milliseconds. This is only supported for the HTTP
    239     *                  protocol as of now. When the HTTP protocol uses CURL, the meaning of
    240     *                  the parameter is <em>total request time</em>. When the HTTP protocol uses
    241     *                  winhttp, the meaning is the same as the @c dwSendTimeout and
    242     *                  @c dwReceiveTimeout parameters of the
    243     *                  <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa384116(v=vs.85).aspx">
    244     *                  WinHttpSetTimeouts</a> API.
    245     *                - @b CURLOPT_LOW_SPEED_LIMIT - only available for HTTP protocol and only
    246     *                  when CURL is used. It has the same meaning as CURL's option with the same
    247     *                  name. @p value is pointer to a long.
    248     *                - @b CURLOPT_LOW_SPEED_TIME - only available for HTTP protocol and only
    249     *                  when CURL is used. It has the same meaning as CURL's option with the same
    250     *                  name. @p value is pointer to a long.
    251     *                - @b CURLOPT_FORBID_REUSE - only available for HTTP protocol and only
    252     *                  when CURL is used. It has the same meaning as CURL's option with the same
    253     *                  name. @p value is pointer to a long.
    254     *                - @b CURLOPT_FRESH_CONNECT - only available for HTTP protocol and only
    255     *                  when CURL is used. It has the same meaning as CURL's option with the same
    256     *                  name. @p value is pointer to a long.
    257     *                - @b CURLOPT_VERBOSE - only available for HTTP protocol and only
    258     *                  when CURL is used. It has the same meaning as CURL's option with the same
    259     *                  name. @p value is pointer to a long.
    260     *                - @b messageTimeout - the maximum time in milliseconds until a message
    261     *                 is timeouted. The time starts at IoTHubClient_SendEventAsync. By default,
    262     *                 messages do not expire. @p is a pointer to a uint64_t
    263     *                - @b svc2cl_keep_alive_timeout_secs - the AMQP service side keep alive interval in seconds.
    264     *                 After the connection established the client requests the server to set the
    265     *                 keep alive interval for given time.
    266     *                 If it is not set then the default 240 sec applies.
    267     *                 If it is set to zero the server will not send keep alive messages to the client.
    268     *                - @b cl2svc_keep_alive_send_ratio - the AMQP client side keep alive interval in seconds.
    269     *                 After the connection established the server requests the client to set the
    270     *                 keep alive interval for given time.
    271     *                 If it is not set then the default ratio of 1/2 is applied.
    272     *                 The ratio has to be greater than 0.0 and equal to or less than 0.9
    273 
    274     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
    275     */
     108    * @deprecated IoTHubClient_SetOption is deprecated.  Use IoTHubDeviceClient_SetOption instead.
     109    */   
    276110    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetOption, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, const char*, optionName, const void*, value);
    277111
    278112    /**
    279     * @brief    This API specifies a call back to be used when the device receives a state update.
    280     *
    281     * @param    iotHubClientHandle        The handle created by a call to the create function.
    282     * @param    deviceTwinCallback        The callback specified by the device client to be used for updating
    283     *                                    the desired state. The callback will be called in response to a
    284     *                                    request send by the IoTHub services. The payload will be passed to the
    285     *                                    callback, along with two version numbers:
    286     *                                        - Desired:
    287     *                                        - LastSeenReported:
    288     * @param    userContextCallback        User specified context that will be provided to the
    289     *                                     callback. This can be @c NULL.
    290     *
    291     *            @b NOTE: The application behavior is undefined if the user calls
    292     *            the ::IoTHubClient_Destroy function from within any callback.
    293     *
    294     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     113    * @deprecated IoTHubClient_SetDeviceTwinCallback is deprecated.  Use IoTHubDeviceClient_SetDeviceTwinCallback instead.
    295114    */
    296115    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetDeviceTwinCallback, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, deviceTwinCallback, void*, userContextCallback);
    297116
    298117    /**
    299     * @brief    This API sends a report of the device's properties and their current values.
    300     *
    301     * @param    iotHubClientHandle        The handle created by a call to the create function.
    302     * @param    reportedState            The current device property values to be 'reported' to the IoTHub.
    303     * @param    reportedStateCallback    The callback specified by the device client to be called with the
    304     *                                    result of the transaction.
    305     * @param    userContextCallback        User specified context that will be provided to the
    306     *                                     callback. This can be @c NULL.
    307     *
    308     *            @b NOTE: The application behavior is undefined if the user calls
    309     *            the ::IoTHubClient_Destroy function from within any callback.
    310     *
    311     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     118    * @deprecated IoTHubClient_SendReportedState is deprecated.  Use IoTHubDeviceClient_SendReportedState instead.
    312119    */
    313120    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SendReportedState, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, const unsigned char*, reportedState, size_t, size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK, reportedStateCallback, void*, userContextCallback);
    314121
    315122    /**
    316     * @brief    This API sets callback for cloud to device method call.
    317     *
    318     * @param    iotHubClientHandle        The handle created by a call to the create function.
    319     * @param    deviceMethodCallback    The callback which will be called by IoTHub.
    320     * @param    userContextCallback        User specified context that will be provided to the
    321     *                                     callback. This can be @c NULL.
    322     *
    323     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     123    * @deprecated IoTHubClient_SetDeviceMethodCallback is deprecated.  Use IoTHubDeviceClient_SetDeviceMethodCallback instead.
    324124    */
    325125    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetDeviceMethodCallback, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC, deviceMethodCallback, void*, userContextCallback);
    326126
    327127    /**
    328     * @brief    This API sets callback for async cloud to device method call.
    329     *
    330     * @param    iotHubClientHandle                The handle created by a call to the create function.
    331     * @param    inboundDeviceMethodCallback     The callback which will be called by IoTHub.
    332     * @param    userContextCallback                User specified context that will be provided to the
    333     *                                             callback. This can be @c NULL.
    334     *
    335     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     128    * @deprecated IoTHubClient_SetDeviceMethodCallback_Ex is deprecated.  Use IoTHubDeviceClient_SetDeviceMethodCallback instead.
    336129    */
    337130    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_SetDeviceMethodCallback_Ex, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK, inboundDeviceMethodCallback, void*, userContextCallback);
    338131
    339132    /**
    340     * @brief    This API responses to a asnyc method callback identified the methodId.
    341     *
    342     * @param    iotHubClientHandle      The handle created by a call to the create function.
    343     * @param    methodId                The methodId of the Device Method callback.
    344     * @param    response                The response data for the method callback.
    345     * @param    response_size           The size of the response data buffer.
    346     * @param    status_response         The status response of the method callback.
    347     *
    348     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     133    * @deprecated IoTHubClient_DeviceMethodResponse is deprecated.  Use IoTHubDeviceClient_SetDeviceMethodCallback instead.
    349134    */
    350135    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_DeviceMethodResponse, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, METHOD_HANDLE, methodId, const unsigned char*, response, size_t, response_size, int, statusCode);
     
    352137#ifndef DONT_USE_UPLOADTOBLOB
    353138    /**
    354     * @brief    IoTHubClient_UploadToBlobAsync uploads data from memory to a file in Azure Blob Storage.
    355     *
    356     * @param    iotHubClientHandle                    The handle created by a call to the IoTHubClient_Create function.
    357     * @param    destinationFileName                    The name of the file to be created in Azure Blob Storage.
    358     * @param    source                              The source of data.
    359     * @param    size                                The size of data.
    360     * @param    iotHubClientFileUploadCallback      A callback to be invoked when the file upload operation has finished.
    361     * @param    context                             A user-provided context to be passed to the file upload callback.
    362     *
    363     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     139    * @deprecated IoTHubClient_UploadToBlobAsync is deprecated.  Use IoTHubDeviceClient_UploadToBlobAsync instead.
    364140    */
    365141    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_UploadToBlobAsync, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size, IOTHUB_CLIENT_FILE_UPLOAD_CALLBACK, iotHubClientFileUploadCallback, void*, context);
    366142
    367143    /**
    368     ** DEPRECATED: Use IoTHubClient_UploadMultipleBlocksToBlobAsyncEx instead **
    369     * @brief                          Uploads a file to a Blob storage in chunks, fed through the callback function provided by the user.
    370     * @remarks                        This function allows users to upload large files in chunks, not requiring the whole file content to be passed in memory.
    371     * @param iotHubClientHandle       The handle created by a call to the IoTHubClient_Create function.
    372     * @param destinationFileName      The name of the file to be created in Azure Blob Storage.
    373     * @param getDataCallback          A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block.
    374     * @param context                  Any data provided by the user to serve as context on getDataCallback.
    375     * @returns                        An IOTHUB_CLIENT_RESULT value indicating the success or failure of the API call.
    376     ** DEPRECATED: Use IoTHubClient_UploadMultipleBlocksToBlobAsyncEx instead **
     144    * @deprecated IoTHubClient_UploadMultipleBlocksToBlobAsync is deprecated.  Use IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync instead.
    377145    */
    378146    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_UploadMultipleBlocksToBlobAsync, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, void*, context);
    379147
    380148    /**
    381     * @brief                          Uploads a file to a Blob storage in chunks, fed through the callback function provided by the user.
    382     * @remarks                        This function allows users to upload large files in chunks, not requiring the whole file content to be passed in memory.
    383     * @param iotHubClientHandle       The handle created by a call to the IoTHubClient_Create function.
    384     * @param destinationFileName      The name of the file to be created in Azure Blob Storage.
    385     * @param getDataCallbackEx        A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block.
    386     * @param context                  Any data provided by the user to serve as context on getDataCallback.
    387     * @returns                        An IOTHUB_CLIENT_RESULT value indicating the success or failure of the API call.*/
     149    * @deprecated IoTHubClient_UploadMultipleBlocksToBlobAsyncEx is deprecated.  Use IoTHubDeviceClient_UploadMultipleBlocksToBlobAsync instead.
     150    */
    388151    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_UploadMultipleBlocksToBlobAsyncEx, IOTHUB_CLIENT_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
    389152
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_core.h

    r457 r464  
    22// Licensed under the MIT license. See LICENSE file in the project root for full license information.
    33
    4 /** @file iothub_client_core.h
    5 *    @brief Extends the IoTHubClientCore_LL module with additional features.
    6 *
    7 *    @details IoTHubClientCore is a module that extends the IoTHubClientCore_LL
    8 *             module with 2 features:
    9 *                - scheduling the work for the IoTHubCLient from a
    10 *                  thread, so that the user does not need to create their
    11 *                  own thread
    12 *                - thread-safe APIs
    13 */
     4//**********************************************************************
     5// NOTE: THIS HEADER IS FOR INTERNAL USE ONLY
     6//
     7// Applications should use iothub_device_client.h or iothub_module_client.h
     8// instead for the official API.
     9//
     10//**********************************************************************
    1411
    1512#ifndef IOTHUB_CLIENT_CORE_H
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_core_ll.h

    r457 r464  
    22// Licensed under the MIT license. See LICENSE file in the project root for full license information.
    33
    4 /** @file iothub_client_core_ll.h
    5 *    @brief     APIs that allow a user (usually a device) to communicate
    6 *             with an Azure IoTHub.
    7 *
    8 *    @details IoTHubClientCore_LL is a module that allows a user (usually a
    9 *             device) to communicate with an Azure IoTHub. It can send events
    10 *             and receive messages. At any given moment in time there can only
    11 *             be at most 1 message callback function.
    12 *
    13 *             This API surface contains a set of APIs that allows the user to
    14 *             interact with the lower layer portion of the IoTHubClient. These APIs
    15 *             contain @c _LL_ in their name, but retain the same functionality like the
    16 *             @c IoTHubClient_... APIs, with one difference. If the @c _LL_ APIs are
    17 *             used then the user is responsible for scheduling when the actual work done
    18 *             by the IoTHubClient happens (when the data is sent/received on/from the wire).
    19 *             This is useful for constrained devices where spinning a separate thread is
    20 *             often not desired.
    21 */
     4//**********************************************************************
     5// NOTE: THIS HEADER IS FOR INTERNAL USE ONLY
     6//
     7// Applications should use iothub_device_client_ll.h or iothub_module_client_ll.h
     8// instead for the official API.
     9//
     10//**********************************************************************
    2211
    2312#ifndef IOTHUB_CLIENT_CORE_LL_H
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_ll.h

    r457 r464  
    11// Copyright (c) Microsoft. All rights reserved.
    22// Licensed under the MIT license. See LICENSE file in the project root for full license information.
     3
     4//**********************************************************************
     5// NOTE: THIS HEADER IS DEPRECATED
     6//
     7// Functions in this header will be maintained for backward compatability.
     8// New applications should use iothub_device_client_ll.h.
     9//
     10//**********************************************************************
     11
    312
    413/** @file iothub_client_ll.h
     
    615*             with an Azure IoTHub.
    716*
    8 *    @details IoTHubClient_LL is a module that allows a user (usually a
     17*    @details IoTHubClient_LL allows a user (usually a
    918*             device) to communicate with an Azure IoTHub. It can send events
    1019*             and receive messages. At any given moment in time there can only
     
    3847typedef struct IOTHUB_CLIENT_CORE_LL_HANDLE_DATA_TAG* IOTHUB_CLIENT_LL_HANDLE;
    3948
     49    /**
     50    * @deprecated IoTHubClient_LL_CreateFromConnectionString is deprecated.  Use IoTHubDeviceClient_LL_CreateFromConnectionString instead.
     51    */
     52    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_CreateFromConnectionString, const char*, connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
    4053
    4154    /**
    42     * @brief    Creates a IoT Hub client for communication with an existing
    43     *             IoT Hub using the specified connection string parameter.
    44     *
    45     * @param    connectionString    Pointer to a character string
    46     * @param    protocol            Function pointer for protocol implementation
    47     *
    48     *            Sample connection string:
    49     *                <blockquote>
    50     *                    <pre>HostName=[IoT Hub name goes here].[IoT Hub suffix goes here, e.g., private.azure-devices-int.net];DeviceId=[Device ID goes here];SharedAccessKey=[Device key goes here];</pre>
    51     *                </blockquote>
    52     *
    53     * @return    A non-NULL @c IOTHUB_CLIENT_LL_HANDLE value that is used when
    54     *             invoking other functions for IoT Hub client and @c NULL on failure.
     55    * @deprecated IoTHubClient_LL_Create is deprecated.  Use IoTHubDeviceClient_LL_Create instead.
    5556    */
    56      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_CreateFromConnectionString, const char*, connectionString, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
     57    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_Create, const IOTHUB_CLIENT_CONFIG*, config);
    5758
    5859    /**
    59     * @brief    Creates a IoT Hub client for communication with an existing IoT
    60     *             Hub using the specified parameters.
    61     *
    62     * @param    config    Pointer to an @c IOTHUB_CLIENT_CONFIG structure
    63     *
    64     *            The API does not allow sharing of a connection across multiple
    65     *            devices. This is a blocking call.
    66     *
    67     * @return    A non-NULL @c IOTHUB_CLIENT_LL_HANDLE value that is used when
    68     *             invoking other functions for IoT Hub client and @c NULL on failure.
     60    * @deprecated IoTHubClient_LL_CreateWithTransport is deprecated.  Use IoTHubDeviceClient_LL_CreateWithTransport instead.
    6961    */
    70      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_Create, const IOTHUB_CLIENT_CONFIG*, config);
     62    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_CreateWithTransport, const IOTHUB_CLIENT_DEVICE_CONFIG*, config);
    7163
    7264    /**
    73     * @brief    Creates a IoT Hub client for communication with an existing IoT
    74     *             Hub using an existing transport.
    75     *
    76     * @param    config    Pointer to an @c IOTHUB_CLIENT_DEVICE_CONFIG structure
    77     *
    78     *            The API *allows* sharing of a connection across multiple
    79     *            devices. This is a blocking call.
    80     *
    81     * @return    A non-NULL @c IOTHUB_CLIENT_LL_HANDLE value that is used when
    82     *             invoking other functions for IoT Hub client and @c NULL on failure.
     65    * @deprecated IoTHubClient_LL_CreateFromDeviceAuth is deprecated.  Use IoTHubDeviceClient_LL_CreateFromDeviceAuth instead.
    8366    */
    84      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_CreateWithTransport, const IOTHUB_CLIENT_DEVICE_CONFIG*, config);
    85 
    86      /**
    87      * @brief    Creates a IoT Hub client for communication with an existing IoT
    88      *             Hub using the device auth module.
    89      *
    90      * @param    iothub_uri    Pointer to an ioThub hostname received in the registration process
    91      * @param    device_id    Pointer to the device Id of the device
    92      * @param    device_auth_handle    a device auth handle used to generate the connection string
    93      * @param    protocol            Function pointer for protocol implementation
    94      *
    95      * @return    A non-NULL @c IOTHUB_CLIENT_LL_HANDLE value that is used when
    96      *             invoking other functions for IoT Hub client and @c NULL on failure.
    97      */
    98      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_CreateFromDeviceAuth, const char*, iothub_uri, const char*, device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
     67    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_LL_HANDLE, IoTHubClient_LL_CreateFromDeviceAuth, const char*, iothub_uri, const char*, device_id, IOTHUB_CLIENT_TRANSPORT_PROVIDER, protocol);
    9968
    10069    /**
    101     * @brief    Disposes of resources allocated by the IoT Hub client. This is a
    102     *             blocking call.
    103     *
    104     * @param    iotHubClientHandle    The handle created by a call to the create function.
     70    * @deprecated IoTHubClient_LL_Destroy is deprecatedDevice.  Use IoTHubClient_LL_Destroy instead.
    10571    */
    106      MOCKABLE_FUNCTION(, void, IoTHubClient_LL_Destroy, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle);
     72    MOCKABLE_FUNCTION(, void, IoTHubClient_LL_Destroy, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle);
    10773
    10874    /**
    109     * @brief    Asynchronous call to send the message specified by @p eventMessageHandle.
    110     *
    111     * @param    iotHubClientHandle               The handle created by a call to the create function.
    112     * @param    eventMessageHandle               The handle to an IoT Hub message.
    113     * @param    eventConfirmationCallback      The callback specified by the device for receiving
    114     *                                         confirmation of the delivery of the IoT Hub message.
    115     *                                         This callback can be expected to invoke the
    116     *                                         ::IoTHubClient_LL_SendEventAsync function for the
    117     *                                         same message in an attempt to retry sending a failing
    118     *                                         message. The user can specify a @c NULL value here to
    119     *                                         indicate that no callback is required.
    120     * @param    userContextCallback            User specified context that will be provided to the
    121     *                                         callback. This can be @c NULL.
    122     *
    123     *            @b NOTE: The application behavior is undefined if the user calls
    124     *            the ::IoTHubClient_LL_Destroy function from within any callback.
    125     * @remarks
    126     *            The IOTHUB_MESSAGE_HANDLE instance provided as argument is copied by the function,
    127     *            so this argument can be destroyed by the calling application right after IoTHubClient_LL_SendEventAsync returns.
    128     *            The copy of @c eventMessageHandle is later destroyed by the iothub client when the message is effectively sent, if a failure sending it occurs, or if the client is destroyed.
    129     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     75    * @deprecated IoTHubClient_LL_SendEventAsync is deprecated.  Use IoTHubDeviceClient_LL_SendEventAsync instead.
    13076    */
    131      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SendEventAsync, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback);
     77    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SendEventAsync, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_MESSAGE_HANDLE, eventMessageHandle, IOTHUB_CLIENT_EVENT_CONFIRMATION_CALLBACK, eventConfirmationCallback, void*, userContextCallback);
    13278
    13379    /**
    134     * @brief    This function returns the current sending status for IoTHubClient.
    135     *
    136     * @param    iotHubClientHandle        The handle created by a call to the create function.
    137     * @param    iotHubClientStatus        The sending state is populated at the address pointed
    138     *                                     at by this parameter. The value will be set to
    139     *                                     @c IOTHUBCLIENT_SENDSTATUS_IDLE if there is currently
    140     *                                     no item to be sent and @c IOTHUBCLIENT_SENDSTATUS_BUSY
    141     *                                     if there are.
    142     *
    143     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     80    * @deprecated IoTHubClient_LL_GetSendStatus is deprecated.  UseDevice IoTHubClient_LL_GetSendStatus instead.
    14481    */
    145      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_GetSendStatus, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_STATUS*, iotHubClientStatus);
     82    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_GetSendStatus, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_STATUS*, iotHubClientStatus);
    14683
    14784    /**
    148     * @brief    Sets up the message callback to be invoked when IoT Hub issues a
    149     *             message to the device. This is a blocking call.
    150     *
    151     * @param    iotHubClientHandle               The handle created by a call to the create function.
    152     * @param    messageCallback                The callback specified by the device for receiving
    153     *                                         messages from IoT Hub.
    154     * @param    userContextCallback            User specified context that will be provided to the
    155     *                                         callback. This can be @c NULL.
    156     *
    157     *            @b NOTE: The application behavior is undefined if the user calls
    158     *            the ::IoTHubClient_LL_Destroy function from within any callback.
    159     *
    160     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     85    * @deprecated IoTHubClient_LL_SetMessageCallback is deprecated.  Use IoTHubDeviceClient_LL_SetMessageCallback instead.
    16186    */
    162      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetMessageCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC, messageCallback, void*, userContextCallback);
     87    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetMessageCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC, messageCallback, void*, userContextCallback);
    16388
    16489    /**
    165     * @brief    Sets up the connection status callback to be invoked representing the status of
    166     * the connection to IOT Hub. This is a blocking call.
    167     *
    168     * @param    iotHubClientHandle                       The handle created by a call to the create function.
    169     * @param    connectionStatusCallback                The callback specified by the device for receiving
    170     *                                                 updates about the status of the connection to IoT Hub.
    171     * @param    userContextCallback                    User specified context that will be provided to the
    172     *                                                 callback. This can be @c NULL.
    173     *
    174     *            @b NOTE: The application behavior is undefined if the user calls
    175     *            the ::IoTHubClient_LL_Destroy function from within any callback.
    176     *
    177     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     90    * @deprecated IoTHubClient_LL_SetConnectionStatusCallback is deprecated.  Use IoTHubDeviceClient_LL_SetConnectionStatusCallback instead.
    17891    */
    179      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetConnectionStatusCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK, connectionStatusCallback, void*, userContextCallback);
     92    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetConnectionStatusCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK, connectionStatusCallback, void*, userContextCallback);
    18093
    18194    /**
    182     * @brief    Sets up the connection status callback to be invoked representing the status of
    183     * the connection to IOT Hub. This is a blocking call.
    184     *
    185     * @param    iotHubClientHandle                       The handle created by a call to the create function.
    186     * @param    retryPolicy                             The policy to use to reconnect to IoT Hub when a
    187     *                                               connection drops.
    188     * @param    retryTimeoutLimitInSeconds            Maximum amount of time(seconds) to attempt reconnection when a
    189     *                                               connection drops to IOT Hub.
    190     *
    191     *            @b NOTE: The application behavior is undefined if the user calls
    192     *            the ::IoTHubClient_LL_Destroy function from within any callback.
    193     *
    194     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     95    * @deprecated IoTHubClient_LL_SetRetryPolicy is deprecated.  Use IoTHubDeviceClient_LL_SetRetryPolicy instead.
    19596    */
    196      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetRetryPolicy, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY, retryPolicy, size_t, retryTimeoutLimitInSeconds);
    197 
     97    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetRetryPolicy, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY, retryPolicy, size_t, retryTimeoutLimitInSeconds);
    19898
    19999    /**
    200     * @brief    Sets up the connection status callback to be invoked representing the status of
    201     * the connection to IOT Hub. This is a blocking call.
    202     *
    203     * @param    iotHubClientHandle                       The handle created by a call to the create function.
    204     * @param    retryPolicy                             Out parameter containing the policy to use to reconnect to IoT Hub.
    205     * @param    retryTimeoutLimitInSeconds            Out parameter containing maximum amount of time in seconds to attempt reconnection
    206                                                     to IOT Hub.
    207     *
    208     *            @b NOTE: The application behavior is undefined if the user calls
    209     *            the ::IoTHubClient_LL_Destroy function from within any callback.
    210     *
    211     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     100    * @deprecated IoTHubClient_LL_GetRetryPolicy is deprecated.  Use IoTHubDeviceClient_LL_GetRetryPolicy instead.
    212101    */
    213      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_GetRetryPolicy, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY*, retryPolicy, size_t*, retryTimeoutLimitInSeconds);
     102    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_GetRetryPolicy, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_RETRY_POLICY*, retryPolicy, size_t*, retryTimeoutLimitInSeconds);
    214103
    215104    /**
    216     * @brief    This function returns in the out parameter @p lastMessageReceiveTime
    217     *             what was the value of the @c time function when the last message was
    218     *             received at the client.
    219     *
    220     * @param    iotHubClientHandle                The handle created by a call to the create function.
    221     * @param    lastMessageReceiveTime          Out parameter containing the value of @c time function
    222     *                                             when the last message was received.
    223     *
    224     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     105    * @deprecated IoTHubClient_LL_GetLastMessageReceiveTime is deprecated.  Use IoTHubDeviceClient_LL_GetLastMessageReceiveTime instead.
    225106    */
    226      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_GetLastMessageReceiveTime, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, time_t*, lastMessageReceiveTime);
     107    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_GetLastMessageReceiveTime, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, time_t*, lastMessageReceiveTime);
    227108
    228109    /**
    229     * @brief    This function is meant to be called by the user when work
    230     *             (sending/receiving) can be done by the IoTHubClient.
    231     *
    232     * @param    iotHubClientHandle    The handle created by a call to the create function.
    233     *
    234     *            All IoTHubClient interactions (in regards to network traffic
    235     *            and/or user level callbacks) are the effect of calling this
    236     *            function and they take place synchronously inside _DoWork.
     110    * @deprecated IoTHubClient_LL_DoWork is deprecateDeviced.  Use IoTHubDeviceClient_LL_DoWork instead.
    237111    */
    238      MOCKABLE_FUNCTION(, void, IoTHubClient_LL_DoWork, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle);
     112    MOCKABLE_FUNCTION(, void, IoTHubClient_LL_DoWork, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle);
    239113
    240114    /**
    241     * @brief    This API sets a runtime option identified by parameter @p optionName
    242     *             to a value pointed to by @p value. @p optionName and the data type
    243     *             @p value is pointing to are specific for every option.
    244     *
    245     * @param    iotHubClientHandle    The handle created by a call to the create function.
    246     * @param    optionName              Name of the option.
    247     * @param    value                  The value.
    248     *
    249     *            The options that can be set via this API are:
    250     *                - @b timeout - the maximum time in milliseconds a communication is
    251     *                  allowed to use. @p value is a pointer to an @c unsigned @c int with
    252     *                  the timeout value in milliseconds. This is only supported for the HTTP
    253     *                  protocol as of now. When the HTTP protocol uses CURL, the meaning of
    254     *                  the parameter is <em>total request time</em>. When the HTTP protocol uses
    255     *                  winhttp, the meaning is the same as the @c dwSendTimeout and
    256     *                  @c dwReceiveTimeout parameters of the
    257     *                  <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa384116(v=vs.85).aspx">
    258     *                  WinHttpSetTimeouts</a> API.
    259     *                - @b CURLOPT_LOW_SPEED_LIMIT - only available for HTTP protocol and only
    260     *                  when CURL is used. It has the same meaning as CURL's option with the same
    261     *                  name. @p value is pointer to a long.
    262     *                - @b CURLOPT_LOW_SPEED_TIME - only available for HTTP protocol and only
    263     *                  when CURL is used. It has the same meaning as CURL's option with the same
    264     *                  name. @p value is pointer to a long.
    265     *                - @b CURLOPT_FORBID_REUSE - only available for HTTP protocol and only
    266     *                  when CURL is used. It has the same meaning as CURL's option with the same
    267     *                  name. @p value is pointer to a long.
    268     *                - @b CURLOPT_FRESH_CONNECT - only available for HTTP protocol and only
    269     *                  when CURL is used. It has the same meaning as CURL's option with the same
    270     *                  name. @p value is pointer to a long.
    271     *                - @b CURLOPT_VERBOSE - only available for HTTP protocol and only
    272     *                  when CURL is used. It has the same meaning as CURL's option with the same
    273     *                  name. @p value is pointer to a long.
    274     *              - @b keepalive - available for MQTT protocol.  Integer value that sets the
    275     *                interval in seconds when pings are sent to the server.
    276     *              - @b logtrace - available for MQTT protocol.  Boolean value that turns on and
    277     *                off the diagnostic logging.
    278     *              - @b sas_token_lifetime - available for MQTT & AMQP protocol.  size_t value that that determines the
    279     *                sas token timeout length.
    280     *
    281     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     115    * @deprecated IoTHubClient_LL_SetOption is deprecated. Device Use IoTHubDeviceClient_LL_SetOption instead.
    282116    */
    283      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetOption, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, optionName, const void*, value);
     117    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetOption, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, optionName, const void*, value);
    284118
    285119    /**
    286     * @brief    This API specifies a call back to be used when the device receives a desired state update.
    287     *
    288     * @param    iotHubClientHandle        The handle created by a call to the create function.
    289     * @param    deviceTwinCallback        The callback specified by the device client to be used for updating
    290     *                                    the desired state. The callback will be called in response to patch
    291     *                                    request send by the IoTHub services. The payload will be passed to the
    292     *                                    callback, along with two version numbers:
    293     *                                        - Desired:
    294     *                                        - LastSeenReported:
    295     * @param    userContextCallback        User specified context that will be provided to the
    296     *                                     callback. This can be @c NULL.
    297     *
    298     *            @b NOTE: The application behavior is undefined if the user calls
    299     *            the ::IoTHubClient_LL_Destroy function from within any callback.
    300     *
    301     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     120    * @deprecated IoTHubClient_LL_SetDeviceTwinCallback is deprecated.  Use IoTHubDeviceClient_LL_SetDeviceTwinCallback instead.
    302121    */
    303      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetDeviceTwinCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, deviceTwinCallback, void*, userContextCallback);
     122    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetDeviceTwinCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK, deviceTwinCallback, void*, userContextCallback);
    304123
    305124    /**
    306     * @brief    This API sneds a report of the device's properties and their current values.
    307     *
    308     * @param    iotHubClientHandle        The handle created by a call to the create function.
    309     * @param    reportedState            The current device property values to be 'reported' to the IoTHub.
    310     * @param    reportedStateCallback    The callback specified by the device client to be called with the
    311     *                                    result of the transaction.
    312     * @param    userContextCallback        User specified context that will be provided to the
    313     *                                     callback. This can be @c NULL.
    314     *
    315     *            @b NOTE: The application behavior is undefined if the user calls
    316     *            the ::IoTHubClient_LL_Destroy function from within any callback.
    317     *
    318     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     125    * @deprecated IoTHubClient_LL_SendReportedState is deprecated.  Use IoTHubDeviceClient_LL_SendReportedState instead.
    319126    */
    320      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SendReportedState, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const unsigned char*, reportedState, size_t, size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK, reportedStateCallback, void*, userContextCallback);
     127    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SendReportedState, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const unsigned char*, reportedState, size_t, size, IOTHUB_CLIENT_REPORTED_STATE_CALLBACK, reportedStateCallback, void*, userContextCallback);
    321128
    322      /**
    323      * @brief    This API sets callback for cloud to device method call.
    324      *
    325      * @param    iotHubClientHandle        The handle created by a call to the create function.
    326      * @param    deviceMethodCallback    The callback which will be called by IoTHub.
    327      * @param    userContextCallback        User specified context that will be provided to the
    328      *                                     callback. This can be @c NULL.
    329      *
    330      * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
    331      */
    332      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetDeviceMethodCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC, deviceMethodCallback, void*, userContextCallback);
     129    /**
     130    * @deprecated IoTHubClient_LL_SetDeviceMethodCallback is deprecated.  Use IoTHubDeviceClient_LL_SetDeviceMethodCallback instead.
     131    */
     132    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetDeviceMethodCallback, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC, deviceMethodCallback, void*, userContextCallback);
    333133
    334      /**
    335      * @brief    This API sets callback for async cloud to device method call.
    336      *
    337      * @param    iotHubClientHandle                The handle created by a call to the create function.
    338      * @param    inboundDeviceMethodCallback     The callback which will be called by IoTHub.
    339      * @param    userContextCallback                User specified context that will be provided to the
    340      *                                             callback. This can be @c NULL.
    341      *
    342      * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
    343      */
    344      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetDeviceMethodCallback_Ex, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK, inboundDeviceMethodCallback, void*, userContextCallback);
     134    /**
     135    * @deprecated IoTHubClient_LL_SetDeviceMethodCallback_Ex is deprecated.  Use IoTHubDeviceClient_LL_SetDeviceMethodCallback instead.
     136    */
     137    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_SetDeviceMethodCallback_Ex, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK, inboundDeviceMethodCallback, void*, userContextCallback);
    345138
    346      /**
    347      * @brief    This API responses to a asnyc method callback identified the methodId.
    348      *
    349      * @param    iotHubClientHandle      The handle created by a call to the create function.
    350      * @param    methodId                The methodId of the Device Method callback.
    351      * @param    response                The response data for the method callback.
    352      * @param    response_size           The size of the response data buffer.
    353      * @param    status_response         The status response of the method callback.
    354      *
    355      * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
    356      */
    357      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_DeviceMethodResponse, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, METHOD_HANDLE, methodId, const unsigned char*, response, size_t, respSize, int, statusCode);
     139    /**
     140    * @deprecated IoTHubClient_LL_DeviceMethodResponse is deprecated.  Use IoTHubDeviceClient_LL_SetDeviceMethodCallback instead.
     141    */
     142    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_DeviceMethodResponse, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, METHOD_HANDLE, methodId, const unsigned char*, response, size_t, respSize, int, statusCode);
    358143
    359144#ifndef DONT_USE_UPLOADTOBLOB
    360145    /**
    361     * @brief    This API uploads to Azure Storage the content pointed to by @p source having the size @p size
    362     *           under the blob name devicename/@pdestinationFileName
    363     *
    364     * @param    iotHubClientHandle        The handle created by a call to the create function.
    365     * @param    destinationFileName     name of the file.
    366     * @param    source                  pointer to the source for file content (can be NULL)
    367     * @param    size                    the size of the source in memory (if @p source is NULL then size needs to be 0).
    368     *
    369     * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     146    * @deprecated IoTHubClient_LL_UploadToBlob is deprecated.  UsDevicee IoTHubDeviceClient_LL_UploadToBlob instead.
    370147    */
    371      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size);
     148    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadToBlob, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, const unsigned char*, source, size_t, size);
    372149
    373      /**
    374      ** DEPRECATED: Use IoTHubClient_LL_UploadMultipleBlocksToBlobAsyncEx instead **
    375      * @brief    This API uploads to Azure Storage the content provided block by block by @p getDataCallback
    376      *           under the blob name devicename/@pdestinationFileName
    377      *
    378      * @param    iotHubClientHandle      The handle created by a call to the create function.
    379      * @param    destinationFileName     name of the file.
    380      * @param    getDataCallback         A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block.
    381      * @param    context                 Any data provided by the user to serve as context on getDataCallback.
    382      *
    383      * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
    384      ** DEPRECATED: Use IoTHubClient_LL_UploadMultipleBlocksToBlobAsyncEx instead **
    385      */
    386      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadMultipleBlocksToBlob, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, void*, context);
     150    /**
     151    * @deprecated IoTHubClient_LL_UploadMultipleBlocksToBlob is deprecated.  Use IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob instead.
     152    */
     153    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadMultipleBlocksToBlob, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK, getDataCallback, void*, context);
    387154
    388      /**
    389      * @brief    This API uploads to Azure Storage the content provided block by block by @p getDataCallback
    390      *           under the blob name devicename/@pdestinationFileName
    391      *
    392      * @param    iotHubClientHandle      The handle created by a call to the create function.
    393      * @param    destinationFileName     name of the file.
    394      * @param    getDataCallbackEx       A callback to be invoked to acquire the file chunks to be uploaded, as well as to indicate the status of the upload of the previous block.
    395      * @param    context                 Any data provided by the user to serve as context on getDataCallback.
    396      *
    397      * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
    398      */
    399      MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadMultipleBlocksToBlobEx, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
     155    /**
     156    * @deprecated IoTHubClient_LL_UploadMultipleBlocksToBlobEx is deprecated.  Use IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob instead.
     157    */
     158    MOCKABLE_FUNCTION(, IOTHUB_CLIENT_RESULT, IoTHubClient_LL_UploadMultipleBlocksToBlobEx, IOTHUB_CLIENT_LL_HANDLE, iotHubClientHandle, const char*, destinationFileName, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX, getDataCallbackEx, void*, context);
    400159
    401160#endif /*DONT_USE_UPLOADTOBLOB*/
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_options.h

    r457 r464  
    2828    static STATIC_VAR_UNUSED const char* OPTION_CONNECTION_TIMEOUT = "connect_timeout";
    2929
     30    /* None of the OPTION_PROXY_* options below are implemented.  Use OPTION_HTTP_PROXY
     31    from shared_util_options.h in https://github.com/Azure/azure-c-shared-utility/ repo instead */
    3032    static STATIC_VAR_UNUSED const char* OPTION_PROXY_HOST = "proxy_address";
    3133    static STATIC_VAR_UNUSED const char* OPTION_PROXY_USERNAME = "proxy_username";
     
    8789    static STATIC_VAR_UNUSED const char* OPTION_DO_WORK_FREQUENCY_IN_MS = "do_work_freq_ms";
    8890
     91// Minimum percentage (in the 0 to 1 range) of multiplexed registered devices that must be failing for a transport-wide reconnection to be triggered.
     92// A value of zero results in a single registered device to be able to cause a general transport reconnection
     93// (thus causing all other multiplexed registered devices to be also reconnected, meaning an agressive reconnection strategy).
     94// Setting this parameter to one indicates that 100% of the multiplexed registered devices must be failing in parallel for a
     95// transport-wide reconnection to be triggered (resulting in a very lenient reconnection strategy). 
     96#define DEVICE_MULTIPLEXING_FAULTY_DEVICE_RATIO_RECONNECTION_THRESHOLD 0
     97
     98// Minimum number of consecutive failures an individual registered device must have to be considered a faulty device.
     99// This is used along with DEVICE_MULTIPLEXING_FAULTY_DEVICE_RATIO_RECONNECTION_THRESHOLD to trigger transport-wide reconnections.
     100// The device may fail to authenticate, timeout establishing the connection, get disconnected by the service for some reason or fail sending messages.
     101// In all these cases the failures are cummulatively counted; if the count is equal to or greater than DEVICE_FAILURE_COUNT_RECONNECTION_THRESHOLD
     102// the device is considered to be in a faulty state.   
     103#define DEVICE_FAILURE_COUNT_RECONNECTION_THRESHOLD 5
     104
    89105#ifdef __cplusplus
    90106}
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/inc/iothub_client_version.h

    r457 r464  
    99#define IOTHUB_CLIENT_VERSION_H
    1010
    11 #define IOTHUB_SDK_VERSION "1.3.8"
     11#define IOTHUB_SDK_VERSION "1.6.0"
    1212
    1313#include "umock_c/umock_c_prod.h"
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/inc/iothub_device_client_ll.h

    r457 r464  
    66*             with an Azure IoTHub.
    77*
    8 *    @details IoTHubDeviceClient_LL is a module that allows a user (usually a
     8*    @details IoTHubDeviceClient_LL allows a user (usually a
    99*             device) to communicate with an Azure IoTHub. It can send events
    1010*             and receive messages. At any given moment in time there can only
     
    1616*             @c IoTHubDeviceClient_... APIs, with one difference. If the @c _LL_ APIs are
    1717*             used then the user is responsible for scheduling when the actual work done
    18 *             by the IoTHubClient happens (when the data is sent/received on/from the wire).
     18*             by the IoTHubClient happens (when the data is sent/received on/from the network).
    1919*             This is useful for constrained devices where spinning a separate thread is
    2020*             often not desired.
     
    8888     /**
    8989     * @brief    Creates a IoT Hub client for communication with an existing IoT
    90      *           Hub using the device auth module.
     90     *           Hub using the device auth.
    9191     *
    9292     * @param    iothub_uri             Pointer to an ioThub hostname received in the registration process
     
    116116    *                                           confirmation of the delivery of the IoT Hub message.
    117117    *                                           This callback can be expected to invoke the
    118     *                                           ::IoTHubDeviceClient_LL_SendEventAsync function for the
     118    *                                           IoTHubDeviceClient_LL_SendEventAsync function for the
    119119    *                                           same message in an attempt to retry sending a failing
    120120    *                                           message. The user can specify a @c NULL value here to
     
    124124    *
    125125    *           @b NOTE: The application behavior is undefined if the user calls
    126     *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
     126    *           the IoTHubDeviceClient_LL_Destroy function from within any callback.
    127127    * @remarks
    128128    *           The IOTHUB_MESSAGE_HANDLE instance provided as argument is copied by the function,
     
    139139    * @param    iotHubClientStatus        The sending state is populated at the address pointed
    140140    *                                     at by this parameter. The value will be set to
    141     *                                     @c IOTHUBCLIENT_SENDSTATUS_IDLE if there is currently
    142     *                                     no item to be sent and @c IOTHUBCLIENT_SENDSTATUS_BUSY
     141    *                                     @c IOTHUB_CLIENT_SEND_STATUS_IDLE if there is currently
     142    *                                     no item to be sent and @c IOTHUB_CLIENT_SEND_STATUS_BUSY
    143143    *                                     if there are.
     144    *
     145    * @remark    Does not return information related to uploads initiated by IoTHubDeviceClient_LL_UploadToBlob or IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob.
    144146    *
    145147    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     
    158160    *
    159161    *           @b NOTE: The application behavior is undefined if the user calls
    160     *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
     162    *           the IoTHubDeviceClient_LL_Destroy function from within any callback.
    161163    *
    162164    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
     
    175177    *
    176178    *           @b NOTE: The application behavior is undefined if the user calls
    177     *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
     179    *           the IoTHubDeviceClient_LL_Destroy function from within any callback.
     180    *
     181    * @remark   Callback specified will not receive connection status change notifications for upload connections created with IoTHubDeviceClient_LL_UploadToBlob or IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob.
    178182    *
    179183    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
     
    192196    *
    193197    *           @b NOTE: The application behavior is undefined if the user calls
    194     *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
     198    *           the IoTHubDeviceClient_LL_Destroy function from within any callback.
     199    *
     200    * @remark   Uploads initiated by IoTHubDeviceClient_LL_UploadToBlob or IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob do not have automatic retries and do not honor the retryPolicy settings.
    195201    *
    196202    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
     
    209215    *
    210216    *           @b NOTE: The application behavior is undefined if the user calls
    211     *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
     217    *           the IoTHubDeviceClient_LL_Destroy function from within any callback.
    212218    *
    213219    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
     
    229235
    230236    /**
    231     * @brief    This function MUST be called by the user so work (sending/receiving data on the wire,
     237    * @brief    This function MUST be called by the user so work (sending/receiving data on the network,
    232238    *           computing and enforcing timeout controls, managing the connection to the IoT Hub) can
    233239    *           be done by the IoTHubClient.
     
    251257    * @param    value                   The value.
    252258    *
    253     *           The options that can be set via this API are:
    254     *                - @b timeout - the maximum time in milliseconds a communication is
    255     *                  allowed to use. @p value is a pointer to an @c unsigned @c int with
    256     *                  the timeout value in milliseconds. This is only supported for the HTTP
    257     *                  protocol as of now. When the HTTP protocol uses CURL, the meaning of
    258     *                  the parameter is <em>total request time</em>. When the HTTP protocol uses
    259     *                  winhttp, the meaning is the same as the @c dwSendTimeout and
    260     *                  @c dwReceiveTimeout parameters of the
    261     *                  <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa384116(v=vs.85).aspx">
    262     *                  WinHttpSetTimeouts</a> API.
    263     *                - @b CURLOPT_LOW_SPEED_LIMIT - only available for HTTP protocol and only
    264     *                  when CURL is used. It has the same meaning as CURL's option with the same
    265     *                  name. @p value is pointer to a long.
    266     *                - @b CURLOPT_LOW_SPEED_TIME - only available for HTTP protocol and only
    267     *                  when CURL is used. It has the same meaning as CURL's option with the same
    268     *                  name. @p value is pointer to a long.
    269     *                - @b CURLOPT_FORBID_REUSE - only available for HTTP protocol and only
    270     *                  when CURL is used. It has the same meaning as CURL's option with the same
    271     *                  name. @p value is pointer to a long.
    272     *                - @b CURLOPT_FRESH_CONNECT - only available for HTTP protocol and only
    273     *                  when CURL is used. It has the same meaning as CURL's option with the same
    274     *                  name. @p value is pointer to a long.
    275     *                - @b CURLOPT_VERBOSE - only available for HTTP protocol and only
    276     *                  when CURL is used. It has the same meaning as CURL's option with the same
    277     *                  name. @p value is pointer to a long.
    278     *                - @b keepalive - available for MQTT protocol.  Integer value that sets the
    279     *                  interval in seconds when pings are sent to the server.
    280     *                - @b logtrace - available for MQTT protocol.  Boolean value that turns on and
    281     *                  off the diagnostic logging.
    282     *                - @b sas_token_lifetime - available for MQTT & AMQP protocol.  size_t value that that determines the
    283     *                  sas token timeout length.
    284     *                - @b OPTION_TRUSTED_CERT - Azure Server certificate used to validate TLS connection to iothub.
     259    * @remarks  Documentation for configuration options is available at https://github.com/Azure/azure-iot-sdk-c/blob/master/doc/Iothub_sdk_options.md.
    285260    *
    286261    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
     
    302277    *
    303278    *           @b NOTE: The application behavior is undefined if the user calls
    304     *           the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
     279    *           the IoTHubDeviceClient_LL_Destroy function from within any callback.
    305280    *
    306281    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
     
    319294    *
    320295    *            @b NOTE: The application behavior is undefined if the user calls
    321     *            the ::IoTHubDeviceClient_LL_Destroy function from within any callback.
     296    *            the IoTHubDeviceClient_LL_Destroy function from within any callback.
    322297    *
    323298    * @return    IOTHUB_CLIENT_OK upon success or an error code upon failure.
     
    334309     *
    335310     *                  @b NOTE: The application behavior is undefined if the user calls
    336      *                  the ::IoTHubClient_LL_Destroy function from within any callback.
     311     *                  the IoTHubClient_LL_Destroy function from within any callback.
    337312     *
    338313     * @return  IOTHUB_CLIENT_OK upon success or an error code upon failure.
     
    374349    * @param    source                  pointer to the source for file content (can be NULL)
    375350    * @param    size                    the size of the source in memory (if @p source is NULL then size needs to be 0).
     351    *
     352    * @warning  Other _LL_ functions such as IoTHubDeviceClient_LL_SendEventAsync queue work to be performed later and do not block.  IoTHubDeviceClient_LL_UploadToBlob
     353    *           will block however until the upload is completed or fails, which may take a while.
    376354    *
    377355    * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
     
    388366     * @param    context                 Any data provided by the user to serve as context on getDataCallback.
    389367     *
     368     * @warning  Other _LL_ functions such as IoTHubDeviceClient_LL_SendEventAsync queue work to be performed later and do not block.  IoTHubDeviceClient_LL_UploadMultipleBlocksToBlob
     369     *           will block however until the upload is completed or fails, which may take a while.
     370     *
    390371     * @return   IOTHUB_CLIENT_OK upon success or an error code upon failure.
    391372     */
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/inc/iothub_message.h

    r457 r464  
    192192* @param   iotHubMessageHandle Handle to the message.
    193193*
    194 * @param   key name of the property to set.  Note that when sending messages via the HTTP transport, this value must not contain spaces.
    195 *
    196 * @param   value of the property to set.
     194* @param   key name of the property to set. Note that when sending messages via the HTTP transport, this value must not contain spaces.
     195*
     196* @param   value of the property to set.
     197*
     198*            @b NOTE: The accepted character sets for the key name and value parameters are dependent on different factors, such as the protocol
     199*            being used. For more information on the character sets accepted by Azure IoT Hub, see
     200*            <a href="https://docs.microsoft.com/azure/iot-hub/iot-hub-devguide-messages-construct">Create and read IoT Hub messages</a>.
    197201*
    198202* @return  An @c IOTHUB_MESSAGE_RESULT value indicating the result of setting the property.
     
    252256* @param   correlationId Pointer to the memory location of the messageId
    253257*
    254 * @return  Returns IOTHUB_MESSAGE_OK if the messageId was set successfully
     258* @return  Returns IOTHUB_MESSAGE_OK if the CorrelationId was set successfully
    255259*          or an error code otherwise.
    256260*/
     
    295299* @param   outputName Pointer to the queue to output message to
    296300*
    297 * @return  Returns IOTHUB_MESSAGE_OK if the DiagnosticData was set successfully
     301* @return  Returns IOTHUB_MESSAGE_OK if the outputName was set successfully
    298302*          or an error code otherwise.
    299303*/
     
    318322* @param   inputName Pointer to the queue to input message to
    319323*
    320 * @return  Returns IOTHUB_MESSAGE_OK if the DiagnosticData was set successfully
     324* @return  Returns IOTHUB_MESSAGE_OK if the inputName was set successfully
    321325*          or an error code otherwise.
    322326*/
     
    340344* @param   connectionModuleId Pointer to the module ID of connector
    341345*
    342 * @return  Returns IOTHUB_MESSAGE_OK if the DiagnosticData was set successfully
     346* @return  Returns IOTHUB_MESSAGE_OK if the connectionModuleId was set successfully
    343347*          or an error code otherwise.
    344348*/
    345349MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetConnectionModuleId, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, connectionModuleId);
    346350
    347 
    348351/**
    349352* @brief   Gets the connection device ID from the IOTHUB_MESSAGE_HANDLE. No new memory is allocated,
     
    356359*/
    357360MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetConnectionDeviceId, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
     361
     362/**
     363* @brief   Sets the message creation time in UTC.
     364*
     365* @param   iotHubMessageHandle Handle to the message.
     366* @param   messageCreationTimeUtc Pointer to the message creation time as null-terminated string
     367*
     368* @return  Returns IOTHUB_MESSAGE_OK if the messageCreationTimeUtc was set successfully
     369*          or an error code otherwise.
     370*/
     371MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetMessageCreationTimeUtcSystemProperty, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, messageCreationTimeUtc);
     372
     373/**
     374* @brief   Gets the message creation time in UTC from the IOTHUB_MESSAGE_HANDLE. No new memory is allocated,
     375*          the caller is not responsible for freeing the memory. The memory
     376*          is valid until IoTHubMessage_Destroy is called on the message.
     377*
     378* @param   iotHubMessageHandle Handle to the message.
     379*
     380* @return  A const char* pointing to the message creation time in UTC.
     381*/
     382MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetMessageCreationTimeUtcSystemProperty, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
     383
     384/**
     385* @brief   Sets the message user id. CAUTION: SDK user should not call it directly, it is for internal use only.
     386*
     387* @param   iotHubMessageHandle Handle to the message.
     388* @param   userId Pointer to the message user id as null-terminated string
     389*
     390* @return  Returns IOTHUB_MESSAGE_OK if the userId was set successfully or an error code otherwise.
     391*/
     392MOCKABLE_FUNCTION(, IOTHUB_MESSAGE_RESULT, IoTHubMessage_SetMessageUserIdSystemProperty, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle, const char*, userId);
     393
     394/**
     395* @brief   Gets the message user id from the IOTHUB_MESSAGE_HANDLE. No new memory is allocated,
     396*          the caller is not responsible for freeing the memory. The memory
     397*          is valid until IoTHubMessage_Destroy is called on the message.
     398*
     399* @param   iotHubMessageHandle Handle to the message.
     400*
     401* @return  A const char* pointing to the message user id.
     402*/
     403MOCKABLE_FUNCTION(, const char*, IoTHubMessage_GetMessageUserIdSystemProperty, IOTHUB_MESSAGE_HANDLE, iotHubMessageHandle);
    358404
    359405/**
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/src/blob.c

    r457 r464  
    1313#include "azure_c_shared_utility/azure_base64.h"
    1414#include "azure_c_shared_utility/shared_util_options.h"
     15
     16static const char blockListXmlBegin[]  = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<BlockList>";
     17static const char blockListXmlEnd[] = "</BlockList>";
     18static const char blockListUriMarker[] = "&comp=blocklist";
    1519
    1620BLOB_RESULT Blob_UploadBlock(
     
    132136}
    133137
     138
     139// InvokeUserCallbackAndSendBlobs invokes the application's getDataCallbackEx as many time as callback requests and, for each call,
     140// sends the blob contents to the server.
     141static BLOB_RESULT InvokeUserCallbackAndSendBlobs(HTTPAPIEX_HANDLE httpApiExHandle, const char* relativePath, STRING_HANDLE blockIDList, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context, unsigned int* httpStatus, BUFFER_HANDLE httpResponse)
     142{
     143    BLOB_RESULT result;
     144
     145    /*Codes_SRS_BLOB_02_021: [ For every block returned by `getDataCallbackEx` the following operations shall happen: ]*/
     146    unsigned int blockID = 0; /* incremented for each new block */
     147    unsigned int isError = 0; /* set to 1 if a block upload fails or if getDataCallbackEx returns incorrect blocks to upload */
     148    unsigned int uploadOneMoreBlock = 1; /* set to 1 while getDataCallbackEx returns correct blocks to upload */
     149    unsigned char const * source = NULL; /* data set by getDataCallbackEx */
     150    size_t size = 0; /* source size set by getDataCallbackEx */
     151    IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataReturnValue;
     152
     153    do
     154    {
     155        getDataReturnValue = getDataCallbackEx(FILE_UPLOAD_OK, &source, &size, context);
     156        if (getDataReturnValue == IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT)
     157        {
     158            /*Codes_SRS_BLOB_99_004: [ If `getDataCallbackEx` returns `IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT_ABORT`, then `Blob_UploadMultipleBlocksFromSasUri` shall exit the loop and return `BLOB_ABORTED`. ]*/
     159            LogInfo("Upload to blob has been aborted by the user");
     160            uploadOneMoreBlock = 0;
     161            result = BLOB_ABORTED;
     162        }
     163        else if (source == NULL || size == 0)
     164        {
     165            /*Codes_SRS_BLOB_99_002: [ If the size of the block returned by `getDataCallbackEx` is 0 or if the data is NULL, then `Blob_UploadMultipleBlocksFromSasUri` shall exit the loop. ]*/
     166            uploadOneMoreBlock = 0;
     167            result = BLOB_OK;
     168        }
     169        else
     170        {
     171            if (size > BLOCK_SIZE)
     172            {
     173                /*Codes_SRS_BLOB_99_001: [ If the size of the block returned by `getDataCallbackEx` is bigger than 4MB, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/
     174                LogError("tried to upload block of size %lu, max allowed size is %d", (unsigned long)size, BLOCK_SIZE);
     175                result = BLOB_INVALID_ARG;
     176                isError = 1;
     177            }
     178            else if (blockID >= MAX_BLOCK_COUNT)
     179            {
     180                /*Codes_SRS_BLOB_99_003: [ If `getDataCallbackEx` returns more than 50000 blocks, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/
     181                LogError("unable to upload more than %lu blocks in one blob", (unsigned long)MAX_BLOCK_COUNT);
     182                result = BLOB_INVALID_ARG;
     183                isError = 1;
     184            }
     185            else
     186            {
     187                /*Codes_SRS_BLOB_02_023: [ Blob_UploadMultipleBlocksFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/
     188                BUFFER_HANDLE requestContent = BUFFER_create(source, size);
     189                if (requestContent == NULL)
     190                {
     191                    /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
     192                    LogError("unable to BUFFER_create");
     193                    result = BLOB_ERROR;
     194                    isError = 1;
     195                }
     196                else
     197                {
     198                    result = Blob_UploadBlock(
     199                            httpApiExHandle,
     200                            relativePath,
     201                            requestContent,
     202                            blockID,
     203                            blockIDList,
     204                            httpStatus,
     205                            httpResponse);
     206
     207                    BUFFER_delete(requestContent);
     208                }
     209
     210                /*Codes_SRS_BLOB_02_026: [ Otherwise, if HTTP response code is >=300 then Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
     211                if (result != BLOB_OK)
     212                {
     213                    LogError("unable to Blob_UploadBlock. Returned value=%d", result);
     214                    isError = 1;
     215                }
     216                else if (*httpStatus >= 300)
     217                {
     218                    LogError("unable to Blob_UploadBlock. Returned httpStatus=%u", (unsigned int)*httpStatus);
     219                    isError = 1;
     220                }
     221            }
     222            blockID++;
     223        }
     224    }
     225    while(uploadOneMoreBlock && !isError);
     226
     227    return result;
     228}
     229
     230// SendBlockIdList to send an XML of uploaded blockIds to the server after the application's payload block(s) have been transfered.
     231static BLOB_RESULT SendBlockIdList(HTTPAPIEX_HANDLE httpApiExHandle, const char* relativePath, STRING_HANDLE blockIDList, unsigned int* httpStatus, BUFFER_HANDLE httpResponse)
     232{
     233    BLOB_RESULT result;
     234   
     235    /*complete the XML*/
     236    if (STRING_concat(blockIDList, blockListXmlEnd) != 0)
     237    {
     238        /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
     239        LogError("failed to STRING_concat");
     240        result = BLOB_ERROR;
     241    }
     242    else
     243    {
     244        /*Codes_SRS_BLOB_02_029: [Blob_UploadMultipleBlocksFromSasUri shall construct a new relativePath from following string : base relativePath + "&comp=blocklist"]*/
     245        STRING_HANDLE newRelativePath = STRING_construct(relativePath);
     246        if (newRelativePath == NULL)
     247        {
     248            /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
     249            LogError("failed to STRING_construct");
     250            result = BLOB_ERROR;
     251        }
     252        else
     253        {
     254            if (STRING_concat(newRelativePath, blockListUriMarker) != 0)
     255            {
     256                /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
     257                LogError("failed to STRING_concat");
     258                result = BLOB_ERROR;
     259            }
     260            else
     261            {
     262                /*Codes_SRS_BLOB_02_030: [ Blob_UploadMultipleBlocksFromSasUri shall call HTTPAPIEX_ExecuteRequest with a PUT operation, passing the new relativePath, httpStatus and httpResponse and the XML string as content. ]*/
     263                const char* s = STRING_c_str(blockIDList);
     264                BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s));
     265                if (blockIDListAsBuffer == NULL)
     266                {
     267                    /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
     268                    LogError("failed to BUFFER_create");
     269                    result = BLOB_ERROR;
     270                }
     271                else
     272                {
     273                    if (HTTPAPIEX_ExecuteRequest(
     274                        httpApiExHandle,
     275                        HTTPAPI_REQUEST_PUT,
     276                        STRING_c_str(newRelativePath),
     277                        NULL,
     278                        blockIDListAsBuffer,
     279                        httpStatus,
     280                        NULL,
     281                        httpResponse
     282                    ) != HTTPAPIEX_OK)
     283                    {
     284                        /*Codes_SRS_BLOB_02_031: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/
     285                        LogError("unable to HTTPAPIEX_ExecuteRequest");
     286                        result = BLOB_HTTP_ERROR;
     287                    }
     288                    else
     289                    {
     290                        /*Codes_SRS_BLOB_02_032: [ Otherwise, Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
     291                        result = BLOB_OK;
     292                    }
     293                    BUFFER_delete(blockIDListAsBuffer);
     294                }
     295            }
     296            STRING_delete(newRelativePath);
     297        }
     298    }
     299
     300    return result;
     301}
     302
     303
    134304BLOB_RESULT Blob_UploadMultipleBlocksFromSasUri(const char* SASURI, IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx, void* context, unsigned int* httpStatus, BUFFER_HANDLE httpResponse, const char* certificates, HTTP_PROXY_OPTIONS *proxyOptions)
    135305{
    136306    BLOB_RESULT result;
     307    const char* hostnameBegin;
     308    STRING_HANDLE blockIDList = NULL;
     309    HTTPAPIEX_HANDLE httpApiExHandle = NULL;
     310    char* hostname = NULL;
     311   
    137312    /*Codes_SRS_BLOB_02_001: [ If SASURI is NULL then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
    138     if (SASURI == NULL)
    139     {
    140         LogError("parameter SASURI is NULL");
     313    /*Codes_SRS_BLOB_02_002: [ If getDataCallbackEx is NULL then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
     314    if ((SASURI == NULL) || (getDataCallbackEx == NULL))
     315    {
     316        LogError("One or more required values is NULL, SASURI=%p, getDataCallbackEx=%p", SASURI, getDataCallbackEx);
    141317        result = BLOB_INVALID_ARG;
    142318    }
     319    /*Codes_SRS_BLOB_02_017: [ Blob_UploadMultipleBlocksFromSasUri shall copy from SASURI the hostname to a new const char* ]*/
     320    /*to find the hostname, the following logic is applied:*/
     321    /*the hostname starts at the first character after "://"*/
     322    /*the hostname ends at the first character before the next "/" after "://"*/
     323    else if ((hostnameBegin = strstr(SASURI, "://")) == NULL)
     324    {
     325        /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
     326        LogError("hostname cannot be determined");
     327        result = BLOB_INVALID_ARG;
     328    }
    143329    else
    144330    {
    145         /*Codes_SRS_BLOB_02_002: [ If getDataCallbackEx is NULL then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
    146         if (getDataCallbackEx == NULL)
    147         {
    148             LogError("IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_CALLBACK_EX getDataCallbackEx is NULL");
     331        hostnameBegin += 3; /*have to skip 3 characters which are "://"*/
     332        const char* relativePath = strchr(hostnameBegin, '/');
     333        if (relativePath == NULL)
     334        {
     335            /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
     336            LogError("hostname cannot be determined");
    149337            result = BLOB_INVALID_ARG;
    150338        }
    151         /*the below define avoid a "condition always false" on some compilers*/
    152339        else
    153340        {
    154             /*Codes_SRS_BLOB_02_017: [ Blob_UploadMultipleBlocksFromSasUri shall copy from SASURI the hostname to a new const char* ]*/
    155             /*to find the hostname, the following logic is applied:*/
    156             /*the hostname starts at the first character after "://"*/
    157             /*the hostname ends at the first character before the next "/" after "://"*/
    158             const char* hostnameBegin = strstr(SASURI, "://");
    159             if (hostnameBegin == NULL)
    160             {
    161                 /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
    162                 LogError("hostname cannot be determined");
    163                 result = BLOB_INVALID_ARG;
     341            size_t hostnameSize = relativePath - hostnameBegin;
     342            if ((hostname = (char*)malloc(hostnameSize + 1)) == NULL)
     343            {
     344                /*Codes_SRS_BLOB_02_016: [ If the hostname copy cannot be made then then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
     345                LogError("oom - out of memory");
     346                result = BLOB_ERROR;
    164347            }
    165348            else
    166349            {
    167                 hostnameBegin += 3; /*have to skip 3 characters which are "://"*/
    168                 const char* hostnameEnd = strchr(hostnameBegin, '/');
    169                 if (hostnameEnd == NULL)
    170                 {
    171                     /*Codes_SRS_BLOB_02_005: [ If the hostname cannot be determined, then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_INVALID_ARG. ]*/
    172                     LogError("hostname cannot be determined");
    173                     result = BLOB_INVALID_ARG;
    174                 }
    175                 else
    176                 {
    177                     size_t hostnameSize = hostnameEnd - hostnameBegin;
    178                     char* hostname = (char*)malloc(hostnameSize + 1); /*+1 because of '\0' at the end*/
    179                     if (hostname == NULL)
    180                     {
    181                         /*Codes_SRS_BLOB_02_016: [ If the hostname copy cannot be made then then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
    182                         LogError("oom - out of memory");
    183                         result = BLOB_ERROR;
    184                     }
    185                     else
    186                     {
    187                         HTTPAPIEX_HANDLE httpApiExHandle;
    188                         (void)memcpy(hostname, hostnameBegin, hostnameSize);
    189                         hostname[hostnameSize] = '\0';
    190 
    191                         /*Codes_SRS_BLOB_02_018: [ Blob_UploadMultipleBlocksFromSasUri shall create a new HTTPAPI_EX_HANDLE by calling HTTPAPIEX_Create passing the hostname. ]*/
    192                         httpApiExHandle = HTTPAPIEX_Create(hostname);
    193                         if (httpApiExHandle == NULL)
    194                         {
    195                             /*Codes_SRS_BLOB_02_007: [ If HTTPAPIEX_Create fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR. ]*/
    196                             LogError("unable to create a HTTPAPIEX_HANDLE");
    197                             result = BLOB_ERROR;
    198                         }
    199                         else
    200                         {
    201                             if ((certificates != NULL)&& (HTTPAPIEX_SetOption(httpApiExHandle, "TrustedCerts", certificates) == HTTPAPIEX_ERROR))
    202                             {
    203                                 LogError("failure in setting trusted certificates");
    204                                 result = BLOB_ERROR;
    205                             }
    206                             else if ((proxyOptions != NULL && proxyOptions->host_address != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_PROXY, proxyOptions) == HTTPAPIEX_ERROR)
    207                             {
    208                                 LogError("failure in setting proxy options");
    209                                 result = BLOB_ERROR;
    210                             }
    211                             else
    212                             {
    213                                 /*Codes_SRS_BLOB_02_019: [ Blob_UploadMultipleBlocksFromSasUri shall compute the base relative path of the request from the SASURI parameter. ]*/
    214                                 const char* relativePath = hostnameEnd; /*this is where the relative path begins in the SasUri*/
    215 
    216                                 /*Codes_SRS_BLOB_02_028: [ Blob_UploadMultipleBlocksFromSasUri shall construct an XML string with the following content: ]*/
    217                                 STRING_HANDLE blockIDList = STRING_construct("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n<BlockList>"); /*the XML "build as we go"*/
    218                                 if (blockIDList == NULL)
    219                                 {
    220                                     /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
    221                                     LogError("failed to STRING_construct");
    222                                     result = BLOB_HTTP_ERROR;
    223                                 }
    224                                 else
    225                                 {
    226                                     /*Codes_SRS_BLOB_02_021: [ For every block returned by `getDataCallbackEx` the following operations shall happen: ]*/
    227                                     unsigned int blockID = 0; /* incremented for each new block */
    228                                     unsigned int isError = 0; /* set to 1 if a block upload fails or if getDataCallbackEx returns incorrect blocks to upload */
    229                                     unsigned int uploadOneMoreBlock = 1; /* set to 1 while getDataCallbackEx returns correct blocks to upload */
    230                                     unsigned char const * source; /* data set by getDataCallbackEx */
    231                                     size_t size; /* source size set by getDataCallbackEx */
    232                                     IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT getDataReturnValue;
    233 
    234                                     do
    235                                     {
    236                                         getDataReturnValue = getDataCallbackEx(FILE_UPLOAD_OK, &source, &size, context);
    237                                         if (getDataReturnValue == IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_ABORT)
    238                                         {
    239                                             /*Codes_SRS_BLOB_99_004: [ If `getDataCallbackEx` returns `IOTHUB_CLIENT_FILE_UPLOAD_GET_DATA_RESULT_ABORT`, then `Blob_UploadMultipleBlocksFromSasUri` shall exit the loop and return `BLOB_ABORTED`. ]*/
    240                                             LogInfo("Upload to blob has been aborted by the user");
    241                                             uploadOneMoreBlock = 0;
    242                                             result = BLOB_ABORTED;
    243                                         }
    244                                         else if (source == NULL || size == 0)
    245                                         {
    246                                             /*Codes_SRS_BLOB_99_002: [ If the size of the block returned by `getDataCallbackEx` is 0 or if the data is NULL, then `Blob_UploadMultipleBlocksFromSasUri` shall exit the loop. ]*/
    247                                             uploadOneMoreBlock = 0;
    248                                             result = BLOB_OK;
    249                                         }
    250                                         else
    251                                         {
    252                                             if (size > BLOCK_SIZE)
    253                                             {
    254                                                 /*Codes_SRS_BLOB_99_001: [ If the size of the block returned by `getDataCallbackEx` is bigger than 4MB, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/
    255                                                 LogError("tried to upload block of size %lu, max allowed size is %d", (unsigned long)size, BLOCK_SIZE);
    256                                                 result = BLOB_INVALID_ARG;
    257                                                 isError = 1;
    258                                             }
    259                                             else if (blockID >= MAX_BLOCK_COUNT)
    260                                             {
    261                                                 /*Codes_SRS_BLOB_99_003: [ If `getDataCallbackEx` returns more than 50000 blocks, then `Blob_UploadMultipleBlocksFromSasUri` shall fail and return `BLOB_INVALID_ARG`. ]*/
    262                                                 LogError("unable to upload more than %lu blocks in one blob", (unsigned long)MAX_BLOCK_COUNT);
    263                                                 result = BLOB_INVALID_ARG;
    264                                                 isError = 1;
    265                                             }
    266                                             else
    267                                             {
    268                                                 /*Codes_SRS_BLOB_02_023: [ Blob_UploadMultipleBlocksFromSasUri shall create a BUFFER_HANDLE from source and size parameters. ]*/
    269                                                 BUFFER_HANDLE requestContent = BUFFER_create(source, size);
    270                                                 if (requestContent == NULL)
    271                                                 {
    272                                                     /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
    273                                                     LogError("unable to BUFFER_create");
    274                                                     result = BLOB_ERROR;
    275                                                     isError = 1;
    276                                                 }
    277                                                 else
    278                                                 {
    279                                                     result = Blob_UploadBlock(
    280                                                             httpApiExHandle,
    281                                                             relativePath,
    282                                                             requestContent,
    283                                                             blockID,
    284                                                             blockIDList,
    285                                                             httpStatus,
    286                                                             httpResponse);
    287 
    288                                                     BUFFER_delete(requestContent);
    289                                                 }
    290 
    291                                                 /*Codes_SRS_BLOB_02_026: [ Otherwise, if HTTP response code is >=300 then Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
    292                                                 if (result != BLOB_OK || *httpStatus >= 300)
    293                                                 {
    294                                                     LogError("unable to Blob_UploadBlock. Returned value=%d, httpStatus=%u", result, (unsigned int)*httpStatus);
    295                                                     isError = 1;
    296                                                 }
    297                                             }
    298                                             blockID++;
    299                                         }
    300                                     }
    301                                     while(uploadOneMoreBlock && !isError);
    302 
    303                                     if (isError || result != BLOB_OK)
    304                                     {
    305                                         /*do nothing, it will be reported "as is"*/
    306                                     }
    307                                     else
    308                                     {
    309                                         /*complete the XML*/
    310                                         if (STRING_concat(blockIDList, "</BlockList>") != 0)
    311                                         {
    312                                             /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
    313                                             LogError("failed to STRING_concat");
    314                                             result = BLOB_ERROR;
    315                                         }
    316                                         else
    317                                         {
    318                                             /*Codes_SRS_BLOB_02_029: [Blob_UploadMultipleBlocksFromSasUri shall construct a new relativePath from following string : base relativePath + "&comp=blocklist"]*/
    319                                             STRING_HANDLE newRelativePath = STRING_construct(relativePath);
    320                                             if (newRelativePath == NULL)
    321                                             {
    322                                                 /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
    323                                                 LogError("failed to STRING_construct");
    324                                                 result = BLOB_ERROR;
    325                                             }
    326                                             else
    327                                             {
    328                                                 if (STRING_concat(newRelativePath, "&comp=blocklist") != 0)
    329                                                 {
    330                                                     /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
    331                                                     LogError("failed to STRING_concat");
    332                                                     result = BLOB_ERROR;
    333                                                 }
    334                                                 else
    335                                                 {
    336                                                     /*Codes_SRS_BLOB_02_030: [ Blob_UploadMultipleBlocksFromSasUri shall call HTTPAPIEX_ExecuteRequest with a PUT operation, passing the new relativePath, httpStatus and httpResponse and the XML string as content. ]*/
    337                                                     const char* s = STRING_c_str(blockIDList);
    338                                                     BUFFER_HANDLE blockIDListAsBuffer = BUFFER_create((const unsigned char*)s, strlen(s));
    339                                                     if (blockIDListAsBuffer == NULL)
    340                                                     {
    341                                                         /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
    342                                                         LogError("failed to BUFFER_create");
    343                                                         result = BLOB_ERROR;
    344                                                     }
    345                                                     else
    346                                                     {
    347                                                         if (HTTPAPIEX_ExecuteRequest(
    348                                                             httpApiExHandle,
    349                                                             HTTPAPI_REQUEST_PUT,
    350                                                             STRING_c_str(newRelativePath),
    351                                                             NULL,
    352                                                             blockIDListAsBuffer,
    353                                                             httpStatus,
    354                                                             NULL,
    355                                                             httpResponse
    356                                                         ) != HTTPAPIEX_OK)
    357                                                         {
    358                                                             /*Codes_SRS_BLOB_02_031: [ If HTTPAPIEX_ExecuteRequest fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_HTTP_ERROR. ]*/
    359                                                             LogError("unable to HTTPAPIEX_ExecuteRequest");
    360                                                             result = BLOB_HTTP_ERROR;
    361                                                         }
    362                                                         else
    363                                                         {
    364                                                             /*Codes_SRS_BLOB_02_032: [ Otherwise, Blob_UploadMultipleBlocksFromSasUri shall succeed and return BLOB_OK. ]*/
    365                                                             result = BLOB_OK;
    366                                                         }
    367                                                         BUFFER_delete(blockIDListAsBuffer);
    368                                                     }
    369                                                 }
    370                                                 STRING_delete(newRelativePath);
    371                                             }
    372                                         }
    373                                     }
    374                                     STRING_delete(blockIDList);
    375                                 }
    376 
    377                             }
    378                             HTTPAPIEX_Destroy(httpApiExHandle);
    379                         }
    380                         free(hostname);
    381                     }
    382                 }
    383             }
    384         }
    385     }
     350                (void)memcpy(hostname, hostnameBegin, hostnameSize);
     351                hostname[hostnameSize] = '\0';
     352
     353                /*Codes_SRS_BLOB_02_018: [ Blob_UploadMultipleBlocksFromSasUri shall create a new HTTPAPI_EX_HANDLE by calling HTTPAPIEX_Create passing the hostname. ]*/
     354                httpApiExHandle = HTTPAPIEX_Create(hostname);
     355                if (httpApiExHandle == NULL)
     356                {
     357                    /*Codes_SRS_BLOB_02_007: [ If HTTPAPIEX_Create fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR. ]*/
     358                    LogError("unable to create a HTTPAPIEX_HANDLE");
     359                    result = BLOB_ERROR;
     360                }
     361                else if ((certificates != NULL) && (HTTPAPIEX_SetOption(httpApiExHandle, "TrustedCerts", certificates) == HTTPAPIEX_ERROR))
     362                {
     363                    LogError("failure in setting trusted certificates");
     364                    result = BLOB_ERROR;
     365                }
     366                else if ((proxyOptions != NULL && proxyOptions->host_address != NULL) && HTTPAPIEX_SetOption(httpApiExHandle, OPTION_HTTP_PROXY, proxyOptions) == HTTPAPIEX_ERROR)
     367                {
     368                    LogError("failure in setting proxy options");
     369                    result = BLOB_ERROR;
     370                }
     371                /*Codes_SRS_BLOB_02_028: [ Blob_UploadMultipleBlocksFromSasUri shall construct an XML string with the following content: ]*/
     372                else if ((blockIDList = STRING_construct(blockListXmlBegin)) == NULL)
     373                {
     374                    /*Codes_SRS_BLOB_02_033: [ If any previous operation that doesn't have an explicit failure description fails then Blob_UploadMultipleBlocksFromSasUri shall fail and return BLOB_ERROR ]*/
     375                    LogError("failed to STRING_construct");
     376                    result = BLOB_HTTP_ERROR;
     377                }
     378                else if ((result = InvokeUserCallbackAndSendBlobs(httpApiExHandle, relativePath, blockIDList, getDataCallbackEx, context, httpStatus, httpResponse)) != BLOB_OK)
     379                {
     380                   LogError("Failed in invoking callback/sending blob step");
     381                }
     382                else if (*httpStatus < 300)
     383                {
     384                    // Per SRS_BLOB_02_026, it possible for us to have a result=BLOB_OK AND a non-success HTTP status code.
     385                    // In order to maintain back-compat with existing code, we will return the BLOB_OK to the caller but NOT invoke this final step.
     386                    result = SendBlockIdList(httpApiExHandle, relativePath, blockIDList, httpStatus, httpResponse);
     387                }
     388            }
     389        }
     390    }
     391
     392    HTTPAPIEX_Destroy(httpApiExHandle);
     393    STRING_delete(blockIDList);
     394    free(hostname);
     395
    386396    return result;
    387397}
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/src/iothub_client_authorization.c

    r457 r464  
    3131    char* device_id;
    3232    char* module_id;
    33     size_t token_expiry_time_sec;
     33    uint64_t token_expiry_time_sec;
    3434    IOTHUB_CREDENTIAL_TYPE cred_type;
    3535#ifdef USE_PROV_MODULE
     
    3838} IOTHUB_AUTHORIZATION_DATA;
    3939
    40 static int get_seconds_since_epoch(size_t* seconds)
     40static int get_seconds_since_epoch(uint64_t* seconds)
    4141{
    4242    int result;
     
    4949    else
    5050    {
    51         *seconds = (size_t)get_difftime(current_time, (time_t)0);
     51        *seconds = (uint64_t)get_difftime(current_time, (time_t)0);
    5252        result = 0;
    5353    }
     
    384384}
    385385
    386 char* IoTHubClient_Auth_Get_SasToken(IOTHUB_AUTHORIZATION_HANDLE handle, const char* scope, size_t expiry_time_relative_seconds, const char* key_name)
     386char* IoTHubClient_Auth_Get_SasToken(IOTHUB_AUTHORIZATION_HANDLE handle, const char* scope, uint64_t expiry_time_relative_seconds, const char* key_name)
    387387{
    388388    char* result;
     
    400400#ifdef USE_PROV_MODULE
    401401            DEVICE_AUTH_CREDENTIAL_INFO dev_auth_cred;
    402             size_t sec_since_epoch;
     402            uint64_t sec_since_epoch;
    403403
    404404            if (get_seconds_since_epoch(&sec_since_epoch) != 0)
     
    410410            {
    411411                memset(&dev_auth_cred, 0, sizeof(DEVICE_AUTH_CREDENTIAL_INFO));
    412                 size_t expiry_time = sec_since_epoch + handle->token_expiry_time_sec;
     412                uint64_t expiry_time = sec_since_epoch + handle->token_expiry_time_sec;
    413413                dev_auth_cred.sas_info.expiry_seconds = expiry_time;
    414414                dev_auth_cred.sas_info.token_scope = scope;
     
    465465            {
    466466                STRING_HANDLE sas_token;
    467                 size_t sec_since_epoch;
     467                uint64_t sec_since_epoch;
    468468
    469469                /* Codes_SRS_IoTHub_Authorization_07_010: [ IoTHubClient_Auth_Get_SasToken` shall construct the expiration time using the handle->token_expiry_time_sec added to epoch time. ] */
     
    477477                {
    478478                    /* Codes_SRS_IoTHub_Authorization_07_011: [ IoTHubClient_Auth_Get_ConnString shall call SASToken_CreateString to construct the sas token. ] */
    479                     size_t expiry_time = sec_since_epoch + handle->token_expiry_time_sec;
     479                    uint64_t expiry_time = sec_since_epoch + handle->token_expiry_time_sec;
    480480                    if ( (sas_token = SASToken_CreateString(handle->device_key, scope, key_name, expiry_time)) == NULL)
    481481                    {
     
    691691#endif
    692692
    693 int IoTHubClient_Auth_Set_SasToken_Expiry(IOTHUB_AUTHORIZATION_HANDLE handle, size_t expiry_time_seconds)
     693int IoTHubClient_Auth_Set_SasToken_Expiry(IOTHUB_AUTHORIZATION_HANDLE handle, uint64_t expiry_time_seconds)
    694694{
    695695    int result;
     
    713713}
    714714
    715 size_t IoTHubClient_Auth_Get_SasToken_Expiry(IOTHUB_AUTHORIZATION_HANDLE handle)
    716 {
    717     size_t result;
     715uint64_t IoTHubClient_Auth_Get_SasToken_Expiry(IOTHUB_AUTHORIZATION_HANDLE handle)
     716{
     717    uint64_t result;
    718718    if (handle == NULL)
    719719    {
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/src/iothub_client_core.c

    r457 r464  
    2626
    2727#define DO_WORK_FREQ_DEFAULT 1
     28#define DO_WORK_MAXIMUM_ALLOWED_FREQUENCY 100
    2829
    2930struct IOTHUB_QUEUE_CONTEXT_TAG;
     
    17221723            {
    17231724                /* Codes_SRS_IOTHUBCLIENT_41_003: [ The value for `OPTION_DO_WORK_FREQUENCY_IN_MS` shall be limited to 100 to follow SDK best practices by not reducing the DoWork frequency below 10 Hz ]*/
    1724                 if (0 < * (unsigned int *)value && * (unsigned int *)value <= 100)
     1725                if (0 < * (unsigned int *)value && * (unsigned int *)value <= DO_WORK_MAXIMUM_ALLOWED_FREQUENCY)
    17251726                {
    17261727                    /* Codes_SRS_IOTHUBCLIENT_41_004: [ If `currentMessageTimeout` is not greater than `do_work_freq_ms`, `IotHubClientCore_SetOption` shall return `IOTHUB_CLIENT_INVALID_ARG` ]*/
     
    17401741                {
    17411742                    result = IOTHUB_CLIENT_INVALID_ARG;
    1742                     LogError("Invalid value: OPTION_DO_WORK_FREQUENCY_IN_MS cannot exceed 100 ms. If you wish to reduce the frequency further, consider using the LL layer.");
     1743                    LogError("Invalid value: OPTION_DO_WORK_FREQUENCY_IN_MS cannot exceed %d ms. If you wish to reduce the frequency further, consider using the LL layer.", DO_WORK_MAXIMUM_ALLOWED_FREQUENCY);
    17431744                }
    17441745            }
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/src/iothub_client_core_ll.c

    r457 r464  
    23482348        else if (strcmp(optionName, OPTION_SAS_TOKEN_REFRESH_TIME) == 0 || strcmp(optionName, OPTION_SAS_TOKEN_LIFETIME) == 0)
    23492349        {
    2350             if (IoTHubClient_Auth_Set_SasToken_Expiry(handleData->authorization_module, *(size_t*)value) != 0)
     2350            // API compat: while IoTHubClient_Auth_Set_SasToken_Expiry accepts uint64_t, we cannot change the public API.
     2351            if (IoTHubClient_Auth_Set_SasToken_Expiry(handleData->authorization_module, (uint64_t)(*(size_t*)value)) != 0)
    23512352            {
    23522353                LogError("Failed setting the Token Expiry time");
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/src/iothub_client_ll_uploadtoblob.c

    r457 r464  
    437437                                        else
    438438                                        {
    439                                             size_t expiry = (size_t)(difftime(curr_time, 0) + 3600);
     439                                            uint64_t expiry = (uint64_t)(difftime(curr_time, 0) + 3600);
    440440                                            char* sas_token = IoTHubClient_Auth_Get_SasToken(upload_data->authorization_module, STRING_c_str(uri_resource), expiry, EMPTY_STRING);
    441441                                            if (sas_token == NULL)
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/src/iothub_message.c

    r457 r464  
    3434    IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA_HANDLE diagnosticData;
    3535    bool is_security_message;
     36    char* creationTimeUtc;
     37    char* userId;
    3638}IOTHUB_MESSAGE_HANDLE_DATA;
    3739
    38 static bool ContainsOnlyUsAscii(const char* asciiValue)
     40static bool ContainsValidUsAscii(const char* asciiValue)
    3941{
    4042    bool result = true;
     
    4244    while (iterator != NULL && *iterator != '\0')
    4345    {
    44         // Allow only printable ascii char
     46        // Union of all allowed ASCII characters for the different protocols (HTTPS, MQTT, AMQP) is [dec 32, dec 126].
    4547        if (*iterator < ' ' || *iterator > '~')
    4648        {
     
    5052        iterator++;
    5153    }
    52     return result;
    53 }
    54 
    55 /* Codes_SRS_IOTHUBMESSAGE_07_008: [ValidateAsciiCharactersFilter shall loop through the mapKey and mapValue strings to ensure that they only contain valid US-Ascii characters Ascii value 32 - 126.] */
     54
     55    return result;
     56}
     57
     58/* Codes_SRS_IOTHUBMESSAGE_07_008: [ValidateAsciiCharactersFilter shall loop through the mapKey and mapValue strings to ensure that they only contain valid US-Ascii characters.*/
    5659static int ValidateAsciiCharactersFilter(const char* mapKey, const char* mapValue)
    5760{
    5861    int result;
    59     if (!ContainsOnlyUsAscii(mapKey) || !ContainsOnlyUsAscii(mapValue))
     62    if (!ContainsValidUsAscii(mapKey) || !ContainsValidUsAscii(mapValue))
    6063    {
    6164        result = MU_FAILURE;
     
    101104    free(handleData->connectionModuleId);
    102105    free(handleData->connectionDeviceId);
     106    free(handleData->creationTimeUtc);
     107    free(handleData->userId);
    103108    free(handleData);
    104109}
     
    123128        }
    124129        handleData->contentEncoding = tmp_encoding;
     130        result = 0;
     131    }
     132    return result;
     133}
     134
     135static int set_message_creation_time(IOTHUB_MESSAGE_HANDLE_DATA* handleData, const char* messageCreationTimeUtc)
     136{
     137    int result;
     138    char* tmp_message_creation_time;
     139
     140    if (handleData->creationTimeUtc != NULL)
     141    {
     142        free(handleData->creationTimeUtc);
     143        handleData->creationTimeUtc = NULL;
     144    }
     145
     146    if (mallocAndStrcpy_s(&tmp_message_creation_time, messageCreationTimeUtc) != 0)
     147    {
     148        LogError("Failed saving a copy of messageCreationTimeUtc");
     149        result = MU_FAILURE;
     150    }
     151    else
     152    {
     153        handleData->creationTimeUtc = tmp_message_creation_time;
     154        result = 0;
     155    }
     156    return result;
     157}
     158
     159static int set_message_user_id(IOTHUB_MESSAGE_HANDLE_DATA* handleData, const char* userId)
     160{
     161    int result;
     162    char* tmp_message_user_id;
     163
     164    if (handleData->userId != NULL)
     165    {
     166        free(handleData->userId);
     167        handleData->userId = NULL;
     168    }
     169
     170    if (mallocAndStrcpy_s(&tmp_message_user_id, userId) != 0)
     171    {
     172        LogError("Failed saving a copy of userId");
     173        result = MU_FAILURE;
     174    }
     175    else
     176    {
     177        handleData->userId = tmp_message_user_id;
    125178        result = 0;
    126179    }
     
    349402                result = NULL;
    350403            }
     404            else if (source->creationTimeUtc != NULL && mallocAndStrcpy_s(&result->creationTimeUtc, source->creationTimeUtc) != 0)
     405            {
     406                LogError("unable to copy creationTimeUtc");
     407                DestroyMessageData(result);
     408                result = NULL;
     409            }
     410            else if (source->userId != NULL && mallocAndStrcpy_s(&result->userId, source->userId) != 0)
     411            {
     412                LogError("unable to copy userId");
     413                DestroyMessageData(result);
     414                result = NULL;
     415            }
    351416            else if (source->connectionModuleId != NULL && mallocAndStrcpy_s(&result->connectionModuleId, source->connectionModuleId) != 0)
    352417            {
     
    509574    else
    510575    {
    511         if (Map_AddOrUpdate(msg_handle->properties, key, value) != MAP_OK)
     576        MAP_RESULT map_result = Map_AddOrUpdate(msg_handle->properties, key, value);
     577        if (map_result == MAP_FILTER_REJECT)
     578        {
     579            LogError("Failure validating property as ASCII");
     580            result = IOTHUB_MESSAGE_INVALID_TYPE;
     581        }
     582        else if (map_result != MAP_OK)
    512583        {
    513584            LogError("Failure adding property to internal map");
     
    748819        // Codes_SRS_IOTHUBMESSAGE_09_011: [IoTHubMessage_GetContentEncodingSystemProperty shall return the `contentEncoding` as a const char* ]
    749820        result = (const char*)handleData->contentEncoding;
     821    }
     822
     823    return result;
     824}
     825
     826IOTHUB_MESSAGE_RESULT IoTHubMessage_SetMessageCreationTimeUtcSystemProperty(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* creationTimeUtc)
     827{
     828    IOTHUB_MESSAGE_RESULT result;
     829
     830    if (iotHubMessageHandle == NULL || creationTimeUtc == NULL)
     831    {
     832        LogError("Invalid argument (iotHubMessageHandle=%p, creationTimeUtc=%p)", iotHubMessageHandle, creationTimeUtc);
     833        result = IOTHUB_MESSAGE_INVALID_ARG;
     834    }
     835    else
     836    {
     837        if (set_message_creation_time(iotHubMessageHandle, creationTimeUtc) != 0)
     838        {
     839            LogError("Failed saving a copy of creationTimeUtc");
     840            result = IOTHUB_MESSAGE_ERROR;
     841        }
     842        else
     843        {
     844            result = IOTHUB_MESSAGE_OK;
     845        }
     846    }
     847    return result;
     848}
     849
     850const char* IoTHubMessage_GetMessageCreationTimeUtcSystemProperty(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
     851{
     852    const char* result;
     853
     854    if (iotHubMessageHandle == NULL)
     855    {
     856        LogError("Invalid argument (iotHubMessageHandle is NULL)");
     857        result = NULL;
     858    }
     859    else
     860    {
     861        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
     862        result = (const char*)handleData->creationTimeUtc;
     863    }
     864
     865    return result;
     866}
     867
     868IOTHUB_MESSAGE_RESULT IoTHubMessage_SetMessageUserIdSystemProperty(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle, const char* userId)
     869{
     870    IOTHUB_MESSAGE_RESULT result;
     871
     872    if (iotHubMessageHandle == NULL || userId == NULL)
     873    {
     874        LogError("Invalid argument (iotHubMessageHandle=%p, userId=%p)", iotHubMessageHandle, userId);
     875        result = IOTHUB_MESSAGE_INVALID_ARG;
     876    }
     877    else
     878    {
     879        if (set_message_user_id(iotHubMessageHandle, userId) != 0)
     880        {
     881            LogError("Failed saving a copy of userId");
     882            result = IOTHUB_MESSAGE_ERROR;
     883        }
     884        else
     885        {
     886            result = IOTHUB_MESSAGE_OK;
     887        }
     888    }
     889    return result;
     890}
     891
     892const char* IoTHubMessage_GetMessageUserIdSystemProperty(IOTHUB_MESSAGE_HANDLE iotHubMessageHandle)
     893{
     894    const char* result;
     895
     896    if (iotHubMessageHandle == NULL)
     897    {
     898        LogError("Invalid argument (iotHubMessageHandle is NULL)");
     899        result = NULL;
     900    }
     901    else
     902    {
     903        IOTHUB_MESSAGE_HANDLE_DATA* handleData = iotHubMessageHandle;
     904        result = (const char*)handleData->userId;
    750905    }
    751906
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/iothub_client/src/iothubtransport_mqtt_common.c

    r457 r464  
    8282
    8383static const char* MESSAGE_ID_PROPERTY = "mid";
     84static const char* MESSAGE_CREATION_TIME_UTC = "ctime";
     85static const char* MESSAGE_USER_ID = "uid";
    8486static const char* CORRELATION_ID_PROPERTY = "cid";
    8587static const char* CONTENT_TYPE_PROPERTY = "ct";
     
    200202    MQTT_CLIENT_STATUS mqttClientStatus;
    201203    bool isDestroyCalled;
    202     bool isRetryExpiredCallbackSet;
     204    bool isRetryExpiredCallbackCalled;
    203205    bool device_twin_get_sent;
    204206    bool twin_resp_sub_recv;
     
    274276} DEVICE_METHOD_INFO;
    275277
    276 static void free_proxy_data(MQTTTRANSPORT_HANDLE_DATA* mqtt_transport_instance)
    277 {
    278     if (mqtt_transport_instance->http_proxy_hostname != NULL)
    279     {
    280         free(mqtt_transport_instance->http_proxy_hostname);
    281         mqtt_transport_instance->http_proxy_hostname = NULL;
    282     }
    283 
    284     if (mqtt_transport_instance->http_proxy_username != NULL)
    285     {
    286         free(mqtt_transport_instance->http_proxy_username);
    287         mqtt_transport_instance->http_proxy_username = NULL;
    288     }
    289 
    290     if (mqtt_transport_instance->http_proxy_password != NULL)
    291     {
    292         free(mqtt_transport_instance->http_proxy_password);
    293         mqtt_transport_instance->http_proxy_password = NULL;
    294     }
    295 }
    296 
    297 // Destroys xio transport associated with MQTT handle and resets appropriate state
     278//
     279// InternStrnicmp implements strnicmp.  strnicmp isn't available on all platforms.
     280//
     281static int InternStrnicmp(const char* s1, const char* s2, size_t n)
     282{
     283    int result;
     284
     285    if (s1 == NULL)
     286    {
     287        result = -1;
     288    }
     289    else if (s2 == NULL)
     290    {
     291        result = 1;
     292    }
     293    else
     294    {
     295        result = 0;
     296
     297        while (n-- && result == 0)
     298        {
     299            if (*s1 == 0) result = -1;
     300            else if (*s2 == 0) result = 1;
     301            else
     302            {
     303
     304                result = TOLOWER(*s1) - TOLOWER(*s2);
     305                ++s1;
     306                ++s2;
     307            }
     308        }
     309    }
     310    return result;
     311}
     312
     313//
     314// freeProxyData free()'s and resets proxy related settings of the mqtt_transport_instance.
     315//
     316static void freeProxyData(MQTTTRANSPORT_HANDLE_DATA* transport_data)
     317{
     318    if (transport_data->http_proxy_hostname != NULL)
     319    {
     320        free(transport_data->http_proxy_hostname);
     321        transport_data->http_proxy_hostname = NULL;
     322    }
     323
     324    if (transport_data->http_proxy_username != NULL)
     325    {
     326        free(transport_data->http_proxy_username);
     327        transport_data->http_proxy_username = NULL;
     328    }
     329
     330    if (transport_data->http_proxy_password != NULL)
     331    {
     332        free(transport_data->http_proxy_password);
     333        transport_data->http_proxy_password = NULL;
     334    }
     335}
     336
     337//
     338// DestroyXioTransport frees resources associated with MQTT handle and resets appropriate state
     339//
    298340static void DestroyXioTransport(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    299341{
     342    mqtt_client_clear_xio(transport_data->mqttClient);
    300343    xio_destroy(transport_data->xioTransport);
    301344    transport_data->xioTransport = NULL;
    302345}
    303346
    304 static void set_saved_tls_options(PMQTTTRANSPORT_HANDLE_DATA transport, OPTIONHANDLER_HANDLE new_options)
     347//
     348// setSavedTlsOptions saves off TLS specific options.  This is used
     349// so that during a disconnection, we have these values available for next reconnection.
     350//
     351static void setSavedTlsOptions(PMQTTTRANSPORT_HANDLE_DATA transport, OPTIONHANDLER_HANDLE new_options)
    305352{
    306353    if (transport->saved_tls_options != NULL)
     
    311358}
    312359
    313 static void free_transport_handle_data(MQTTTRANSPORT_HANDLE_DATA* transport_data)
     360//
     361// freeTransportHandleData free()'s 'the transport_data and all members that were allocated by it.
     362//
     363static void freeTransportHandleData(MQTTTRANSPORT_HANDLE_DATA* transport_data)
    314364{
    315365    if (transport_data->mqttClient != NULL)
    316366    {
    317367        mqtt_client_deinit(transport_data->mqttClient);
     368        transport_data->mqttClient = NULL;
    318369    }
    319370
     
    323374    }
    324375
    325     set_saved_tls_options(transport_data, NULL);
     376    setSavedTlsOptions(transport_data, NULL);
    326377
    327378    tickcounter_destroy(transport_data->msgTickCounter);
    328379
    329     free_proxy_data(transport_data);
     380    freeProxyData(transport_data);
    330381
    331382    STRING_delete(transport_data->devicesAndModulesPath);
     
    346397}
    347398
    348 int IoTHubTransport_MQTT_Common_SetRetryPolicy(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
    349 {
    350     int result;
    351 
    352     if (handle == NULL)
    353     {
    354         /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_25_041: [**If any handle is NULL then IoTHubTransport_MQTT_Common_SetRetryPolicy shall return resultant line.] */
    355         LogError("Invalid handle parameter. NULL.");
    356         result = MU_FAILURE;
    357     }
    358     else
    359     {
    360         RETRY_CONTROL_HANDLE new_retry_control_handle;
    361 
    362         // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_006: [ IoTHubTransport_MQTT_Common_SetRetryPolicy shall set the retry logic by calling retry_control_create() with retry policy and retryTimeout as parameters]
    363         // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_009: [ If retry_control_create() fails then IoTHubTransport_MQTT_Common_SetRetryPolicy shall revert to previous retry policy and return non-zero value ]
    364         if ((new_retry_control_handle = retry_control_create(retryPolicy, (unsigned int)retryTimeoutLimitInSeconds)) == NULL)
    365         {
    366             LogError("Failed creating new retry control handle");
    367             result = MU_FAILURE;
    368         }
    369         else
    370         {
    371             PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
    372             RETRY_CONTROL_HANDLE previous_retry_control_handle = transport_data->retry_control_handle;
    373 
    374             transport_data->retry_control_handle = new_retry_control_handle;
    375             retry_control_destroy(previous_retry_control_handle);
    376 
    377             /*Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_25_045: [**If retry logic for specified parameters of retry policy and retryTimeoutLimitInSeconds is created successfully then IoTHubTransport_MQTT_Common_SetRetryPolicy shall return 0]*/
    378             result = 0;
    379         }
    380     }
    381 
    382     return result;
    383 }
    384 
    385 static uint16_t get_next_packet_id(PMQTTTRANSPORT_HANDLE_DATA transport_data)
     399//
     400// getNextPacketId gets the next Packet Id to use and increments internal counter.
     401//
     402static uint16_t getNextPacketId(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    386403{
    387404    if (transport_data->packetId + 1 >= USHRT_MAX)
     
    397414
    398415#ifndef NO_LOGGING
    399 static const char* retrieve_mqtt_return_codes(CONNECT_RETURN_CODE rtn_code)
     416//
     417// retrieveMqttReturnCodes returns friendly representation of connection code for logging purposes.
     418//
     419static const char* retrieveMqttReturnCodes(CONNECT_RETURN_CODE rtn_code)
    400420{
    401421    switch (rtn_code)
     
    420440#endif // NO_LOGGING
    421441
    422 static int retrieve_device_method_rid_info(const char* resp_topic, STRING_HANDLE method_name, STRING_HANDLE request_id)
     442//
     443// retrievDeviceMethodRidInfo parses an incoming MQTT topic for a device method and retrieves the request ID it specifies.
     444//
     445static int retrievDeviceMethodRidInfo(const char* resp_topic, STRING_HANDLE method_name, STRING_HANDLE request_id)
    423446{
    424447    int result;
     
    484507}
    485508
    486 static int parse_device_twin_topic_info(const char* resp_topic, bool* patch_msg, size_t* request_id, int* status_code)
     509//
     510// parseDeviceTwinTopicInfo parses information about a topic PUBLISH'd to this device/module.
     511//
     512static int parseDeviceTwinTopicInfo(const char* resp_topic, bool* patch_msg, size_t* request_id, int* status_code)
    487513{
    488514    int result;
     
    548574}
    549575
    550 static int InternStrnicmp(const char* s1, const char* s2, size_t n)
    551 {
    552     int result;
    553 
    554     if (s1 == NULL) result = -1;
    555     else if (s2 == NULL) result = 1;
    556     else
    557     {
    558         result = 0;
    559 
    560         while (n-- && result == 0)
    561         {
    562             if (*s1 == 0) result = -1;
    563             else if (*s2 == 0) result = 1;
    564             else
    565             {
    566 
    567                 result = TOLOWER(*s1) - TOLOWER(*s2);
    568                 ++s1;
    569                 ++s2;
    570             }
    571         }
    572     }
    573     return result;
    574 }
    575 
    576 static IOTHUB_IDENTITY_TYPE retrieve_topic_type(const char* topic_resp, const char* input_queue)
     576//
     577// retrieveTopicType translates an MQTT topic PUBLISH'd to this device/module into what type (e.g. twin, method, etc.) it represents.
     578//
     579static IOTHUB_IDENTITY_TYPE retrieveTopicType(const char* topic_resp, const char* input_queue)
    577580{
    578581    IOTHUB_IDENTITY_TYPE type;
     
    598601}
    599602
    600 static void sendMsgComplete(IOTHUB_MESSAGE_LIST* iothubMsgList, PMQTTTRANSPORT_HANDLE_DATA transport_data, IOTHUB_CLIENT_CONFIRMATION_RESULT confirmResult)
     603//
     604// notifyApplicationOfSendMessageComplete lets application know that messages in the iothubMsgList have completed (or should be considered failed) with confirmResult status.
     605//
     606static void notifyApplicationOfSendMessageComplete(IOTHUB_MESSAGE_LIST* iothubMsgList, PMQTTTRANSPORT_HANDLE_DATA transport_data, IOTHUB_CLIENT_CONFIRMATION_RESULT confirmResult)
    601607{
    602608    DLIST_ENTRY messageCompleted;
     
    606612}
    607613
     614//
     615// addUserPropertiesTouMqttMessage translates application properties in iothub_message_handle (set by the application with IoTHubMessage_SetProperty e.g.)
     616// into a representation in the MQTT TOPIC topic_string.
     617//
    608618static int addUserPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, STRING_HANDLE topic_string, size_t* index_ptr, bool urlencode)
    609619{
     
    660670}
    661671
     672//
     673// addSystemPropertyToTopicString appends a given "system" property from iothub_message_handle (set by the application with APIs such as IoTHubMessage_SetMessageId,
     674// IoTHubMessage_SetContentTypeSystemProperty, etc.) onto the MQTT TOPIC topic_string.
     675//
    662676static int addSystemPropertyToTopicString(STRING_HANDLE topic_string, size_t index, const char* property_key, const char* property_value, bool urlencode)
    663677{
     
    690704}
    691705
     706//
     707// addSystemPropertyToTopicString appends all "system" property from iothub_message_handle (set by the application with APIs such as IoTHubMessage_SetMessageId,
     708// IoTHubMessage_SetContentTypeSystemProperty, etc.) onto the MQTT TOPIC topic_string.
     709//
    692710static int addSystemPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, STRING_HANDLE topic_string, size_t* index_ptr, bool urlencode)
    693711{
     
    734752        }
    735753    }
     754
     755    if (result == 0)
     756    {
     757        const char* message_creation_time_utc = IoTHubMessage_GetMessageCreationTimeUtcSystemProperty(iothub_message_handle);
     758        if (message_creation_time_utc != NULL)
     759        {
     760            result = addSystemPropertyToTopicString(topic_string, index, MESSAGE_CREATION_TIME_UTC, message_creation_time_utc, urlencode);
     761            index++;
     762        }
     763    }
     764
    736765    if (result == 0)
    737766    {
     
    754783}
    755784
     785//
     786// addDiagnosticPropertiesTouMqttMessage appends diagnostic data (as specified by IoTHubMessage_SetDiagnosticPropertyData) onto
     787// the MQTT topic topic_string.
     788//
    756789static int addDiagnosticPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, STRING_HANDLE topic_string, size_t* index_ptr)
    757790{
     
    821854}
    822855
    823 
     856//
     857// addPropertiesTouMqttMessage adds user, "system", and diagnostic messages onto MQTT topic string.  Note that "system" properties is a
     858// construct of the SDK and IoT Hub.  The MQTT protocol itself does not assign any significance to system and user properties (as opposed to AMQP).
     859// The IOTHUB_MESSAGE_HANDLE structure however does have well-known properties (e.g. IoTHubMessage_SetMessageId) that the SDK treats as system
     860// properties where we can automatically fill in the key value for in the key=value list.
     861//
    824862static STRING_HANDLE addPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, const char* eventTopic, bool urlencode)
    825863{
     
    868906}
    869907
    870 static int publish_mqtt_telemetry_msg(PMQTTTRANSPORT_HANDLE_DATA transport_data, MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry, const unsigned char* payload, size_t len)
     908//
     909// publishTelemetryMsg invokes the umqtt layer to send a PUBLISH message.
     910//
     911static int publishTelemetryMsg(PMQTTTRANSPORT_HANDLE_DATA transport_data, MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry, const unsigned char* payload, size_t len)
    871912{
    872913    int result;
     
    912953}
    913954
    914 static int publish_device_method_message(MQTTTRANSPORT_HANDLE_DATA* transport_data, int status_code, STRING_HANDLE request_id, const unsigned char* response, size_t response_size)
     955//
     956// publishDeviceMethodResponseMsg invokes the umqtt to send a PUBLISH message that contains device method call results.
     957//
     958static int publishDeviceMethodResponseMsg(MQTTTRANSPORT_HANDLE_DATA* transport_data, int status_code, STRING_HANDLE request_id, const unsigned char* response, size_t response_size)
    915959{
    916960    int result;
    917     uint16_t packet_id = get_next_packet_id(transport_data);
     961    uint16_t packet_id = getNextPacketId(transport_data);
    918962
    919963    STRING_HANDLE msg_topic = STRING_construct_sprintf(DEVICE_METHOD_RESPONSE_TOPIC, status_code, STRING_c_str(request_id));
     
    949993}
    950994
    951 
    952 static void destroy_device_twin_get_message(MQTT_DEVICE_TWIN_ITEM* msg_entry)
     995//
     996// destroyDeviceTwinGetMsg frees msg_entry and any data associated with it.
     997//
     998static void destroyDeviceTwinGetMsg(MQTT_DEVICE_TWIN_ITEM* msg_entry)
    953999{
    9541000    free(msg_entry);
    9551001}
    9561002
    957 static MQTT_DEVICE_TWIN_ITEM* create_device_twin_message(MQTTTRANSPORT_HANDLE_DATA* transport_data, DEVICE_TWIN_MSG_TYPE device_twin_msg_type, uint32_t iothub_msg_id)
     1003//
     1004// createDeviceTwinMsg allocates and fills in structure for MQTT_DEVICE_TWIN_ITEM.
     1005//
     1006static MQTT_DEVICE_TWIN_ITEM* createDeviceTwinMsg(MQTTTRANSPORT_HANDLE_DATA* transport_data, DEVICE_TWIN_MSG_TYPE device_twin_msg_type, uint32_t iothub_msg_id)
    9581007{
    9591008    MQTT_DEVICE_TWIN_ITEM* result;
     
    9741023        memset(result, 0, sizeof(*result));
    9751024        result->msgCreationTime = current_time;
    976         result->packet_id = get_next_packet_id(transport_data);
     1025        result->packet_id = getNextPacketId(transport_data);
    9771026        result->iothub_msg_id = iothub_msg_id;
    9781027        result->device_twin_msg_type = device_twin_msg_type;
     
    9821031}
    9831032
    984 static int publish_device_twin_get_message(MQTTTRANSPORT_HANDLE_DATA* transport_data, MQTT_DEVICE_TWIN_ITEM* mqtt_info)
     1033//
     1034// publishDeviceTwinGetMsg invokes umqtt to PUBLISH a request to get the twin information.
     1035//
     1036static int publishDeviceTwinGetMsg(MQTTTRANSPORT_HANDLE_DATA* transport_data, MQTT_DEVICE_TWIN_ITEM* mqtt_info)
    9851037{
    9861038    int result;
     
    10201072}
    10211073
     1074//
     1075// sendPendingGetTwinRequests will send any queued up GetTwin requests during a DoWork loop.
     1076//
    10221077static void sendPendingGetTwinRequests(PMQTTTRANSPORT_HANDLE_DATA transportData)
    10231078{
     
    10311086        (void)DList_RemoveEntryList(dev_twin_item);
    10321087
    1033         if (publish_device_twin_get_message(transportData, msg_entry) != 0)
     1088        if (publishDeviceTwinGetMsg(transportData, msg_entry) != 0)
    10341089        {
    10351090            LogError("Failed sending pending get twin request");
    1036             destroy_device_twin_get_message(msg_entry);
     1091            destroyDeviceTwinGetMsg(msg_entry);
    10371092        }
    10381093        else
     
    10451100}
    10461101
    1047 
     1102//
     1103// removeExpiredTwinRequestsFromList removes any requests that have timed out.
     1104//
    10481105static void removeExpiredTwinRequestsFromList(PMQTTTRANSPORT_HANDLE_DATA transport_data, tickcounter_ms_t current_ms, DLIST_ENTRY* twin_list)
    10491106{
    10501107    PDLIST_ENTRY list_item = twin_list->Flink;
    1051    
     1108
    10521109    while (list_item != twin_list)
    10531110    {
     
    10761133        {
    10771134            (void)DList_RemoveEntryList(list_item);
    1078             destroy_device_twin_get_message(msg_entry);
     1135            destroyDeviceTwinGetMsg(msg_entry);
    10791136        }
    10801137
     
    10841141}
    10851142
     1143//
     1144// removeExpiredTwinRequests removes any requests that have timed out, regardless of how the request invoked.
     1145//
    10861146static void removeExpiredTwinRequests(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    10871147{
     
    10951155}
    10961156
    1097 static int publish_device_twin_message(MQTTTRANSPORT_HANDLE_DATA* transport_data, IOTHUB_DEVICE_TWIN* device_twin_info, MQTT_DEVICE_TWIN_ITEM* mqtt_info)
     1157//
     1158// publishDeviceTwinMsg invokes umqtt to PUBLISH a request for the twin.
     1159//
     1160static int publishDeviceTwinMsg(MQTTTRANSPORT_HANDLE_DATA* transport_data, IOTHUB_DEVICE_TWIN* device_twin_info, MQTT_DEVICE_TWIN_ITEM* mqtt_info)
    10981161{
    10991162    int result;
     
    11491212}
    11501213
     1214//
     1215// changeStateToSubscribeIfAllowed attempts to transition the state machine to subscribe, if our
     1216// current state will allow it. 
     1217// This function does NOT immediately send the SUBSCRIBE however, instead setting things up
     1218// so the next time DoWork is invoked then the SUBSCRIBE will happen.
     1219//
    11511220static void changeStateToSubscribeIfAllowed(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    11521221{
     
    11601229}
    11611230
     1231//
     1232// subscribeToNotifyStateIfNeeded sets up to subscribe to the server.
     1233//
    11621234static int subscribeToNotifyStateIfNeeded(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    11631235{
     
    11911263}
    11921264
    1193 
     1265//
     1266// isSystemProperty returns whether a given property name in an MQTT TOPIC published to this device/module
     1267// is considered a "system".  MQTT does not have a protocol defined concept of system properties.  In this usage
     1268// it implies that the IOTHUB_MESSAGE_HANDLE has an API for direct manipulation of the property (e.g. IoTHubMessage_GetMessageId).
     1269//
    11941270static bool isSystemProperty(const char* tokenData)
    11951271{
     
    11971273    size_t propCount = sizeof(sysPropList) / sizeof(sysPropList[0]);
    11981274    size_t index = 0;
     1275    size_t tokenDataLength = strlen(tokenData);
     1276
    11991277    for (index = 0; index < propCount; index++)
    12001278    {
    1201         if (memcmp(tokenData, sysPropList[index].propName, sysPropList[index].propLength) == 0)
     1279        if (tokenDataLength >= sysPropList[index].propLength &&
     1280            memcmp(tokenData, sysPropList[index].propName, sysPropList[index].propLength) == 0)
    12021281        {
    12031282            result = true;
     
    12081287}
    12091288
    1210 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_061: [ If the message is sent to an input queue, `IoTHubTransport_MQTT_Common_DoWork` shall parse out to the input queue name and store it in the message with IoTHubMessage_SetInputName ]
    1211 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_062: [ If IoTHubTransport_MQTT_Common_DoWork receives a malformatted inputQueue, it shall fail ]
    1212 static int addInputNamePropertyToMessage(IOTHUB_MESSAGE_HANDLE IoTHubMessage, const char* topic_name)
    1213 {
     1289//
     1290// addInputNamePropertyToMsg translates the input name (embedded in the MQTT topic name) into the IoTHubMessage handle
     1291// such that the application can call IoTHubMessage_GetInputName() to retrieve this.  This is only currently used
     1292// in IoT Edge module to module message communication, so that this module receiving the message can know which module invoked in.
     1293//
     1294static int addInputNamePropertyToMsg(IOTHUB_MESSAGE_HANDLE IoTHubMessage, const char* topic_name)
     1295{
     1296    // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_061: [ If the message is sent to an input queue, `IoTHubTransport_MQTT_Common_DoWork` shall parse out to the input queue name and store it in the message with IoTHubMessage_SetInputName ]
     1297    // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_062: [ If IoTHubTransport_MQTT_Common_DoWork receives a malformatted inputQueue, it shall fail ]
     1298
    12141299    int result = MU_FAILURE;
    12151300    int number_tokens_read = 0;
     
    12611346}
    12621347
     1348//
     1349// setMqttMessagePropertyIfPossible attempts to translate a "system" property into the IOTHUB_MESSAGE_HANDLE that will be provided to the
     1350// application's callback.
     1351//
    12631352static int setMqttMessagePropertyIfPossible(IOTHUB_MESSAGE_HANDLE IoTHubMessage, const char* propName, const char* propValue, size_t nameLen)
    12641353{
     
    12661355    int result = 0;
    12671356
     1357    if (nameLen > 5)
     1358    {
     1359        if (strcmp((const char*)&propName[nameLen - 5], MESSAGE_CREATION_TIME_UTC) == 0)
     1360        {
     1361            if (IoTHubMessage_SetMessageCreationTimeUtcSystemProperty(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
     1362            {
     1363                LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'CreationTimeUtc' property.");
     1364                result = MU_FAILURE;
     1365            }
     1366            return result;
     1367        }
     1368    }
     1369
    12681370    if (nameLen > 4)
    12691371    {
     
    13091411            return result;
    13101412        }
     1413        else if (strcmp((const char*)&propName[nameLen - 3], MESSAGE_USER_ID) == 0)
     1414        {
     1415            if (IoTHubMessage_SetMessageUserIdSystemProperty(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
     1416            {
     1417                LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'userId' property.");
     1418                result = MU_FAILURE;
     1419            }
     1420            return result;
     1421        }
    13111422    }
    13121423
     
    13381449}
    13391450
     1451//
     1452// extractMqttProperties parses the MQTT topic PUBLISH'd to this device/module, retrieves properties and fills out the
     1453// IOTHUB_MESSAGE_HANDLE which will ultimately be delivered to the application callback.
     1454//
    13401455static int extractMqttProperties(IOTHUB_MESSAGE_HANDLE IoTHubMessage, const char* topic_name, bool urldecode)
    13411456{
     
    15031618}
    15041619
    1505 static void mqtt_notification_callback(MQTT_MESSAGE_HANDLE msgHandle, void* callbackCtx)
    1506 {
    1507     /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_051: [ If msgHandle or callbackCtx is NULL, mqtt_notification_callback shall do nothing. ] */
    1508     if (msgHandle != NULL && callbackCtx != NULL)
    1509     {
    1510         /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_052: [ mqtt_notification_callback shall extract the topic Name from the MQTT_MESSAGE_HANDLE. ] */
    1511         const char* topic_resp = mqttmessage_getTopicName(msgHandle);
    1512         if (topic_resp == NULL)
    1513         {
    1514             LogError("Failure: NULL topic name encountered");
     1620//
     1621// processTwinNotification processes device and module twin updates made by IoT Hub / IoT Edge.
     1622//
     1623static void processTwinNotification(PMQTTTRANSPORT_HANDLE_DATA transportData, MQTT_MESSAGE_HANDLE msgHandle, const char* topic_resp)
     1624{
     1625    size_t request_id;
     1626    int status_code;
     1627    bool notification_msg;
     1628
     1629    if (parseDeviceTwinTopicInfo(topic_resp, &notification_msg, &request_id, &status_code) != 0)
     1630    {
     1631        LogError("Failure: parsing device topic info");
     1632    }
     1633    else
     1634    {
     1635        const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(msgHandle);
     1636        if (notification_msg)
     1637        {
     1638            transportData->transport_callbacks.twin_retrieve_prop_complete_cb(DEVICE_TWIN_UPDATE_PARTIAL, payload->message, payload->length, transportData->transport_ctx);
    15151639        }
    15161640        else
    15171641        {
    1518             PMQTTTRANSPORT_HANDLE_DATA transportData = (PMQTTTRANSPORT_HANDLE_DATA)callbackCtx;
    1519 
    1520             IOTHUB_IDENTITY_TYPE type = retrieve_topic_type(topic_resp, STRING_c_str(transportData->topic_InputQueue));
    1521             if (type == IOTHUB_TYPE_DEVICE_TWIN)
    1522             {
    1523                 size_t request_id;
    1524                 int status_code;
    1525                 bool notification_msg;
    1526                 if (parse_device_twin_topic_info(topic_resp, &notification_msg, &request_id, &status_code) != 0)
    1527                 {
    1528                     LogError("Failure: parsing device topic info");
    1529                 }
    1530                 else
    1531                 {
    1532                     const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(msgHandle);
    1533                     if (notification_msg)
     1642            PDLIST_ENTRY dev_twin_item = transportData->ack_waiting_queue.Flink;
     1643            while (dev_twin_item != &transportData->ack_waiting_queue)
     1644            {
     1645                DLIST_ENTRY saveListEntry;
     1646                saveListEntry.Flink = dev_twin_item->Flink;
     1647                MQTT_DEVICE_TWIN_ITEM* msg_entry = containingRecord(dev_twin_item, MQTT_DEVICE_TWIN_ITEM, entry);
     1648                if (request_id == msg_entry->packet_id)
     1649                {
     1650                    (void)DList_RemoveEntryList(dev_twin_item);
     1651                    if (msg_entry->device_twin_msg_type == RETRIEVE_PROPERTIES)
    15341652                    {
    1535                         transportData->transport_callbacks.twin_retrieve_prop_complete_cb(DEVICE_TWIN_UPDATE_PARTIAL, payload->message, payload->length, transportData->transport_ctx);
     1653                        if (msg_entry->userCallback == NULL)
     1654                        {
     1655                            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_054: [ If type is IOTHUB_TYPE_DEVICE_TWIN, then on success if msg_type is RETRIEVE_PROPERTIES then mqttNotificationCallback shall call IoTHubClientCore_LL_RetrievePropertyComplete... ] */
     1656                            transportData->transport_callbacks.twin_retrieve_prop_complete_cb(DEVICE_TWIN_UPDATE_COMPLETE, payload->message, payload->length, transportData->transport_ctx);
     1657                            // Only after receiving device twin request should we start listening for patches.
     1658                            (void)subscribeToNotifyStateIfNeeded(transportData);
     1659                        }
     1660                        else
     1661                        {
     1662                            // This is a on-demand get twin request.
     1663                            msg_entry->userCallback(DEVICE_TWIN_UPDATE_COMPLETE, payload->message, payload->length, msg_entry->userContext);
     1664                        }
    15361665                    }
    15371666                    else
    15381667                    {
    1539                         PDLIST_ENTRY dev_twin_item = transportData->ack_waiting_queue.Flink;
    1540                         while (dev_twin_item != &transportData->ack_waiting_queue)
    1541                         {
    1542                             DLIST_ENTRY saveListEntry;
    1543                             saveListEntry.Flink = dev_twin_item->Flink;
    1544                             MQTT_DEVICE_TWIN_ITEM* msg_entry = containingRecord(dev_twin_item, MQTT_DEVICE_TWIN_ITEM, entry);
    1545                             if (request_id == msg_entry->packet_id)
    1546                             {
    1547                                 (void)DList_RemoveEntryList(dev_twin_item);
    1548                                 if (msg_entry->device_twin_msg_type == RETRIEVE_PROPERTIES)
    1549                                 {
    1550                                     if (msg_entry->userCallback == NULL)
    1551                                     {
    1552                                         /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_054: [ If type is IOTHUB_TYPE_DEVICE_TWIN, then on success if msg_type is RETRIEVE_PROPERTIES then mqtt_notification_callback shall call IoTHubClientCore_LL_RetrievePropertyComplete... ] */
    1553                                         transportData->transport_callbacks.twin_retrieve_prop_complete_cb(DEVICE_TWIN_UPDATE_COMPLETE, payload->message, payload->length, transportData->transport_ctx);
    1554                                         // Only after receiving device twin request should we start listening for patches.
    1555                                         (void)subscribeToNotifyStateIfNeeded(transportData);
    1556                                     }
    1557                                     else
    1558                                     {
    1559                                         // This is a on-demand get twin request.
    1560                                         msg_entry->userCallback(DEVICE_TWIN_UPDATE_COMPLETE, payload->message, payload->length, msg_entry->userContext);
    1561                                     }
    1562                                 }
    1563                                 else
    1564                                 {
    1565                                     /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_055: [ if device_twin_msg_type is not RETRIEVE_PROPERTIES then mqtt_notification_callback shall call IoTHubClientCore_LL_ReportedStateComplete ] */
    1566                                     transportData->transport_callbacks.twin_rpt_state_complete_cb(msg_entry->iothub_msg_id, status_code, transportData->transport_ctx);
    1567                                     // Only after receiving device twin request should we start listening for patches.
    1568                                     (void)subscribeToNotifyStateIfNeeded(transportData);
    1569                                 }
    1570 
    1571                                 destroy_device_twin_get_message(msg_entry);
    1572                                 break;
    1573                             }
    1574                             dev_twin_item = saveListEntry.Flink;
    1575                         }
     1668                        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_055: [ if device_twin_msg_type is not RETRIEVE_PROPERTIES then mqttNotificationCallback shall call IoTHubClientCore_LL_ReportedStateComplete ] */
     1669                        transportData->transport_callbacks.twin_rpt_state_complete_cb(msg_entry->iothub_msg_id, status_code, transportData->transport_ctx);
     1670                        // Only after receiving device twin request should we start listening for patches.
     1671                        (void)subscribeToNotifyStateIfNeeded(transportData);
    15761672                    }
    1577                 }
     1673
     1674                    destroyDeviceTwinGetMsg(msg_entry);
     1675                    break;
     1676                }
     1677                dev_twin_item = saveListEntry.Flink;
     1678            }
     1679        }
     1680    }
     1681}
     1682
     1683//
     1684// processDeviceMethodNotification processes a device and module method invocations made by IoT Hub / IoT Edge.
     1685//
     1686static void processDeviceMethodNotification(PMQTTTRANSPORT_HANDLE_DATA transportData, MQTT_MESSAGE_HANDLE msgHandle, const char* topic_resp)
     1687{
     1688    STRING_HANDLE method_name = STRING_new();
     1689    if (method_name == NULL)
     1690    {
     1691        LogError("Failure: allocating method_name string value");
     1692    }
     1693    else
     1694    {
     1695        DEVICE_METHOD_INFO* dev_method_info = malloc(sizeof(DEVICE_METHOD_INFO));
     1696        if (dev_method_info == NULL)
     1697        {
     1698            LogError("Failure: allocating DEVICE_METHOD_INFO object");
     1699        }
     1700        else
     1701        {
     1702            dev_method_info->request_id = STRING_new();
     1703            if (dev_method_info->request_id == NULL)
     1704            {
     1705                LogError("Failure constructing request_id string");
     1706                free(dev_method_info);
     1707            }
     1708            else if (retrievDeviceMethodRidInfo(topic_resp, method_name, dev_method_info->request_id) != 0)
     1709            {
     1710                LogError("Failure: retrieve device topic info");
     1711                STRING_delete(dev_method_info->request_id);
     1712                free(dev_method_info);
     1713            }
     1714            else
     1715            {
     1716                /* CodesSRS_IOTHUB_MQTT_TRANSPORT_07_053: [ If type is IOTHUB_TYPE_DEVICE_METHODS, then on success mqttNotificationCallback shall call IoTHubClientCore_LL_DeviceMethodComplete. ] */
     1717                const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(msgHandle);
     1718                if (transportData->transport_callbacks.method_complete_cb(STRING_c_str(method_name), payload->message, payload->length, (void*)dev_method_info, transportData->transport_ctx) != 0)
     1719                {
     1720                    LogError("Failure: IoTHubClientCore_LL_DeviceMethodComplete");
     1721                    STRING_delete(dev_method_info->request_id);
     1722                    free(dev_method_info);
     1723                }
     1724            }
     1725        }
     1726        STRING_delete(method_name);
     1727    }
     1728}
     1729
     1730//
     1731// processIncomingMessageNotification processes both C2D messages and messages sent from one IoT Edge module into this module
     1732//
     1733static void processIncomingMessageNotification(PMQTTTRANSPORT_HANDLE_DATA transportData, MQTT_MESSAGE_HANDLE msgHandle, const char* topic_resp, IOTHUB_IDENTITY_TYPE type)
     1734{
     1735    const APP_PAYLOAD* appPayload = mqttmessage_getApplicationMsg(msgHandle);
     1736    IOTHUB_MESSAGE_HANDLE IoTHubMessage = IoTHubMessage_CreateFromByteArray(appPayload->message, appPayload->length);
     1737    if (IoTHubMessage == NULL)
     1738    {
     1739        LogError("Failure: IotHub Message creation has failed.");
     1740    }
     1741    else if ((type == IOTHUB_TYPE_EVENT_QUEUE) && (addInputNamePropertyToMsg(IoTHubMessage, topic_resp) != 0))
     1742    {
     1743        LogError("failure adding input name to property.");
     1744    }
     1745    else if (extractMqttProperties(IoTHubMessage, topic_resp, transportData->auto_url_encode_decode) != 0)
     1746    {
     1747        LogError("failure extracting mqtt properties.");
     1748    }
     1749    else
     1750    {
     1751        MESSAGE_CALLBACK_INFO* messageData = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
     1752        if (messageData == NULL)
     1753        {
     1754            LogError("malloc failed");
     1755        }
     1756        else
     1757        {
     1758            messageData->messageHandle = IoTHubMessage;
     1759            messageData->transportContext = NULL;
     1760
     1761            if (type == IOTHUB_TYPE_EVENT_QUEUE)
     1762            {
     1763                // Codes_SRS_IOTHUB_MQTT_TRANSPORT_31_065: [ If type is IOTHUB_TYPE_TELEMETRY and sent to an input queue, then on success `mqttNotificationCallback` shall call `IoTHubClient_LL_MessageCallback`. ]
     1764                if (!transportData->transport_callbacks.msg_input_cb(messageData, transportData->transport_ctx))
     1765                {
     1766                    LogError("IoTHubClientCore_LL_MessageCallbackreturned false");
     1767
     1768                    IoTHubMessage_Destroy(IoTHubMessage);
     1769                    free(messageData);
     1770                }
     1771            }
     1772            else
     1773            {
     1774                /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_056: [ If type is IOTHUB_TYPE_TELEMETRY, then on success mqttNotificationCallback shall call IoTHubClientCore_LL_MessageCallback. ] */
     1775                if (!transportData->transport_callbacks.msg_cb(messageData, transportData->transport_ctx))
     1776                {
     1777                    LogError("IoTHubClientCore_LL_MessageCallback returned false");
     1778                    IoTHubMessage_Destroy(IoTHubMessage);
     1779                    free(messageData);
     1780                }
     1781            }
     1782        }
     1783    }
     1784}
     1785
     1786//
     1787// mqttNotificationCallback processes incoming PUBLISH messages sent from Hub (or IoT Edge) to this device.
     1788// This function is invoked by umqtt.  It determines what topic the PUBLISH was directed at (e.g. Device Twin, Method, etc.),
     1789// performs further parsing based on topic, and translates this call up to "iothub_client" layer for ultimate delivery to application callback.
     1790//
     1791static void mqttNotificationCallback(MQTT_MESSAGE_HANDLE msgHandle, void* callbackCtx)
     1792{
     1793    /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_051: [ If msgHandle or callbackCtx is NULL, mqttNotificationCallback shall do nothing. ] */
     1794    if (msgHandle != NULL && callbackCtx != NULL)
     1795    {
     1796        /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_052: [ mqttNotificationCallback shall extract the topic Name from the MQTT_MESSAGE_HANDLE. ] */
     1797        const char* topic_resp = mqttmessage_getTopicName(msgHandle);
     1798        if (topic_resp == NULL)
     1799        {
     1800            LogError("Failure: NULL topic name encountered");
     1801        }
     1802        else
     1803        {
     1804            PMQTTTRANSPORT_HANDLE_DATA transportData = (PMQTTTRANSPORT_HANDLE_DATA)callbackCtx;
     1805
     1806            IOTHUB_IDENTITY_TYPE type = retrieveTopicType(topic_resp, STRING_c_str(transportData->topic_InputQueue));
     1807            if (type == IOTHUB_TYPE_DEVICE_TWIN)
     1808            {
     1809                processTwinNotification(transportData, msgHandle, topic_resp);
    15781810            }
    15791811            else if (type == IOTHUB_TYPE_DEVICE_METHODS)
    15801812            {
    1581                 STRING_HANDLE method_name = STRING_new();
    1582                 if (method_name == NULL)
    1583                 {
    1584                     LogError("Failure: allocating method_name string value");
    1585                 }
    1586                 else
    1587                 {
    1588                     DEVICE_METHOD_INFO* dev_method_info = malloc(sizeof(DEVICE_METHOD_INFO));
    1589                     if (dev_method_info == NULL)
    1590                     {
    1591                         LogError("Failure: allocating DEVICE_METHOD_INFO object");
    1592                     }
    1593                     else
    1594                     {
    1595                         dev_method_info->request_id = STRING_new();
    1596                         if (dev_method_info->request_id == NULL)
    1597                         {
    1598                             LogError("Failure constructing request_id string");
    1599                             free(dev_method_info);
    1600                         }
    1601                         else if (retrieve_device_method_rid_info(topic_resp, method_name, dev_method_info->request_id) != 0)
    1602                         {
    1603                             LogError("Failure: retrieve device topic info");
    1604                             STRING_delete(dev_method_info->request_id);
    1605                             free(dev_method_info);
    1606                         }
    1607                         else
    1608                         {
    1609                             /* CodesSRS_IOTHUB_MQTT_TRANSPORT_07_053: [ If type is IOTHUB_TYPE_DEVICE_METHODS, then on success mqtt_notification_callback shall call IoTHubClientCore_LL_DeviceMethodComplete. ] */
    1610                             const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(msgHandle);
    1611                             if (transportData->transport_callbacks.method_complete_cb(STRING_c_str(method_name), payload->message, payload->length, (void*)dev_method_info, transportData->transport_ctx) != 0)
    1612                             {
    1613                                 LogError("Failure: IoTHubClientCore_LL_DeviceMethodComplete");
    1614                                 STRING_delete(dev_method_info->request_id);
    1615                                 free(dev_method_info);
    1616                             }
    1617                         }
    1618                     }
    1619                     STRING_delete(method_name);
    1620                 }
     1813                processDeviceMethodNotification(transportData, msgHandle, topic_resp);
    16211814            }
    16221815            else
    16231816            {
    1624                 const APP_PAYLOAD* appPayload = mqttmessage_getApplicationMsg(msgHandle);
    1625                 IOTHUB_MESSAGE_HANDLE IoTHubMessage = IoTHubMessage_CreateFromByteArray(appPayload->message, appPayload->length);
    1626                 if (IoTHubMessage == NULL)
    1627                 {
    1628                     LogError("Failure: IotHub Message creation has failed.");
    1629                 }
    1630                 else
    1631                 {
    1632                     if ((type == IOTHUB_TYPE_EVENT_QUEUE) && (addInputNamePropertyToMessage(IoTHubMessage, topic_resp) != 0))
    1633                     {
    1634                         LogError("failure adding input name to property.");
    1635                     }
    1636                     // Will need to update this when the service has messages that can be rejected
    1637                     else if (extractMqttProperties(IoTHubMessage, topic_resp, transportData->auto_url_encode_decode) != 0)
    1638                     {
    1639                         LogError("failure extracting mqtt properties.");
    1640                     }
    1641                     else
    1642                     {
    1643                         MESSAGE_CALLBACK_INFO* messageData = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
    1644                         if (messageData == NULL)
    1645                         {
    1646                             LogError("malloc failed");
    1647                         }
    1648                         else
    1649                         {
    1650                             messageData->messageHandle = IoTHubMessage;
    1651                             messageData->transportContext = NULL;
    1652 
    1653                             if (type == IOTHUB_TYPE_EVENT_QUEUE)
    1654                             {
    1655                                 // Codes_SRS_IOTHUB_MQTT_TRANSPORT_31_065: [ If type is IOTHUB_TYPE_TELEMETRY and sent to an input queue, then on success `mqtt_notification_callback` shall call `IoTHubClient_LL_MessageCallback`. ]
    1656                                 if (!transportData->transport_callbacks.msg_input_cb(messageData, transportData->transport_ctx))
    1657                                 {
    1658                                     LogError("IoTHubClientCore_LL_MessageCallbackreturned false");
    1659 
    1660                                     IoTHubMessage_Destroy(IoTHubMessage);
    1661                                     free(messageData);
    1662                                 }
    1663                             }
    1664                             else
    1665                             {
    1666                                 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_056: [ If type is IOTHUB_TYPE_TELEMETRY, then on success mqtt_notification_callback shall call IoTHubClientCore_LL_MessageCallback. ] */
    1667                                 if (!transportData->transport_callbacks.msg_cb(messageData, transportData->transport_ctx))
    1668                                 {
    1669                                     LogError("IoTHubClientCore_LL_MessageCallback returned false");
    1670                                     IoTHubMessage_Destroy(IoTHubMessage);
    1671                                     free(messageData);
    1672                                 }
    1673                             }
    1674                         }
    1675                     }
    1676                 }
    1677             }
    1678         }
    1679     }
    1680 }
    1681 
    1682 static void mqtt_operation_complete_callback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_RESULT actionResult, const void* msgInfo, void* callbackCtx)
     1817                processIncomingMessageNotification(transportData, msgHandle, topic_resp, type);
     1818            }
     1819        }
     1820    }
     1821}
     1822
     1823//
     1824// mqttOperationCompleteCallback is invoked by umqtt when an operation initiated by the device completes.
     1825// Examples of device initiated operations include PUBLISH, CONNECT, and SUBSCRIBE.
     1826//
     1827static void mqttOperationCompleteCallback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_RESULT actionResult, const void* msgInfo, void* callbackCtx)
    16831828{
    16841829    (void)handle;
     
    17051850                        {
    17061851                            (void)DList_RemoveEntryList(currentListEntry); //First remove the item from Waiting for Ack List.
    1707                             sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_OK);
     1852                            notifyApplicationOfSendMessageComplete(mqttMsgEntry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_OK);
    17081853                            free(mqttMsgEntry);
    17091854                        }
     
    17531898                            transport_data->isRecoverableError = false;
    17541899                        }
    1755                         LogError("Connection Not Accepted: 0x%x: %s", connack->returnCode, retrieve_mqtt_return_codes(connack->returnCode));
     1900                        LogError("Connection Not Accepted: 0x%x: %s", connack->returnCode, retrieveMqttReturnCodes(connack->returnCode));
    17561901                        transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_PENDING_CLOSE;
    17571902                        transport_data->currPacketState = PACKET_TYPE_ERROR;
     
    18221967    {
    18231968        OPTIONHANDLER_HANDLE options = xio_retrieveoptions(transport_data->xioTransport);
    1824         set_saved_tls_options(transport_data, options);
     1969        setSavedTlsOptions(transport_data, options);
    18251970        DestroyXioTransport(transport_data);
    18261971    }
    18271972}
    18281973
    1829 static void mqtt_disconnect_cb(void* ctx)
     1974//
     1975// processDisconnectCallback is a callback invoked by umqtt to signal that the disconnection has completed.
     1976//
     1977static void processDisconnectCallback(void* ctx)
    18301978{
    18311979    if (ctx != NULL)
     
    18361984}
    18371985
     1986//
     1987// DisconnectFromClient will tear down the existing MQTT connection, trying to gracefully send an MQTT DISCONNECT (with a timeout),
     1988// destroy the underlying xio for network communication, and update the transport_data state machine appropriately.
     1989//
     1990//NOTE: After a call to DisconnectFromClient, determine if appropriate to also call
     1991//      transport_data->transport_callbacks.connection_status_cb().
    18381992static void DisconnectFromClient(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    18391993{
     
    18431997        {
    18441998            OPTIONHANDLER_HANDLE options = xio_retrieveoptions(transport_data->xioTransport);
    1845             set_saved_tls_options(transport_data, options);
     1999            setSavedTlsOptions(transport_data, options);
    18462000        }
    18472001        // Ensure the disconnect message is sent
     
    18492003        {
    18502004            transport_data->disconnect_recv_flag = 0;
    1851             (void)mqtt_client_disconnect(transport_data->mqttClient, mqtt_disconnect_cb, &transport_data->disconnect_recv_flag);
     2005            (void)mqtt_client_disconnect(transport_data->mqttClient, processDisconnectCallback, &transport_data->disconnect_recv_flag);
    18522006            size_t disconnect_ctr = 0;
    18532007            do
     
    18662020}
    18672021
    1868 static void mqtt_error_callback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_ERROR error, void* callbackCtx)
     2022//
     2023// processErrorCallback is invoked by umqtt when an error has occurred.
     2024//
     2025static void processErrorCallback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_ERROR error, void* callbackCtx)
    18692026{
    18702027    (void)handle;
     
    19352092}
    19362093
     2094//
     2095// SubscribeToMqttProtocol determines which topics we should SUBSCRIBE to, based on existing state, and then
     2096// invokes the underlying umqtt layer to send the SUBSCRIBE across the network.
     2097//
    19372098static void SubscribeToMqttProtocol(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    19382099{
     
    19412102        uint32_t topic_subscription = 0;
    19422103        size_t subscribe_count = 0;
    1943         uint16_t packet_id = get_next_packet_id(transport_data);
     2104        uint16_t packet_id = getNextPacketId(transport_data);
    19442105        SUBSCRIBE_PAYLOAD subscribe[SUBSCRIBE_TOPIC_COUNT];
    19452106        if ((transport_data->topic_MqttMessage != NULL) && (SUBSCRIBE_TELEMETRY_TOPIC & transport_data->topics_ToSubscribe))
     
    20082169}
    20092170
     2171//
     2172// RetrieveMessagePayload translates the payload set by the application in messageHandle into payload/length for sending across the network.
     2173//
    20102174static bool RetrieveMessagePayload(IOTHUB_MESSAGE_HANDLE messageHandle, const unsigned char** payload, size_t* length)
    20112175{
     
    20482212}
    20492213
    2050 static void process_queued_ack_messages(PMQTTTRANSPORT_HANDLE_DATA transport_data)
     2214//
     2215// ProcessPendingTelemetryMessages examines each telemetry message the device/module has sent that hasn't yet been PUBACK'd. 
     2216// For each message, it might:
     2217// * Ignore it, if its timeout has not yet been reached.
     2218// * Attempt to retry PUBLISH the message, if has remaining retries left.
     2219// * Stop attempting to send the message.  This will result in tearing down the underlying MQTT/TCP connection because it indicates
     2220//   something is wrong.
     2221//
     2222static void ProcessPendingTelemetryMessages(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    20512223{
    20522224    PDLIST_ENTRY current_entry = transport_data->telemetry_waitingForAck.Flink;
     
    20632235            if (msg_detail_entry->retryCount >= MAX_SEND_RECOUNT_LIMIT)
    20642236            {
    2065                 sendMsgComplete(msg_detail_entry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_MESSAGE_TIMEOUT);
     2237                notifyApplicationOfSendMessageComplete(msg_detail_entry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_MESSAGE_TIMEOUT);
    20662238                (void)DList_RemoveEntryList(current_entry);
    20672239                free(msg_detail_entry);
    20682240
    20692241                DisconnectFromClient(transport_data);
     2242                if (!transport_data->isRetryExpiredCallbackCalled) // Only call once
     2243                {
     2244                    transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_RETRY_EXPIRED, transport_data->transport_ctx);
     2245                    transport_data->isRetryExpiredCallbackCalled = true;
     2246                }
    20702247            }
    20712248            else
     
    20802257                    {
    20812258                        (void)DList_RemoveEntryList(current_entry);
    2082                         sendMsgComplete(msg_detail_entry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
     2259                        notifyApplicationOfSendMessageComplete(msg_detail_entry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
    20832260                    }
    20842261                    else
    20852262                    {
    2086                         if (publish_mqtt_telemetry_msg(transport_data, msg_detail_entry, messagePayload, messageLength) != 0)
     2263                        if (publishTelemetryMsg(transport_data, msg_detail_entry, messagePayload, messageLength) != 0)
    20872264                        {
    20882265                            (void)DList_RemoveEntryList(current_entry);
    2089                             sendMsgComplete(msg_detail_entry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
     2266                            notifyApplicationOfSendMessageComplete(msg_detail_entry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
    20902267                            free(msg_detail_entry);
    20912268                        }
     
    21032280}
    21042281
    2105 static int GetTransportProviderIfNecessary(PMQTTTRANSPORT_HANDLE_DATA transport_data)
     2282//
     2283// CreateTransportProviderIfNecessary will create the underlying xioTransport (which handles networking I/O) and
     2284// set its options, assuming the xioTransport does not already exist.
     2285//
     2286static int CreateTransportProviderIfNecessary(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    21062287{
    21072288    int result;
     
    21382319                {
    21392320                    // The tlsio has the options, so our copy can be deleted
    2140                     set_saved_tls_options(transport_data, NULL);
     2321                    setSavedTlsOptions(transport_data, NULL);
    21412322                    result = 0;
    21422323                }
     
    21672348}
    21682349
     2350//
     2351// buildClientId creates the MQTT ClientId of this device or module.
     2352//
    21692353static STRING_HANDLE buildClientId(const char* device_id, const char* module_id)
    21702354{
     
    21792363}
    21802364
     2365//
     2366// buildConfigForUsernameStep2IfNeeded builds the MQTT username.  IoT Hub uses the query string of the userName to optionally
     2367// specify SDK information, product information optionally specified by the application, and optionally the PnP ModelId.
     2368//
    21812369static int buildConfigForUsernameStep2IfNeeded(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    21822370{
     
    21912379        // TODO: The preview API version in SDK is only scoped to scenarios that require the modelId to be set.
    21922380        // https://github.com/Azure/azure-iot-sdk-c/issues/1547 tracks removing this once non-preview API versions support modelId.
    2193         const char* apiVersion = (modelId != NULL) ? IOTHUB_API_PREVIEW_VERSION : IOTHUB_API_VERSION;
     2381        const char* apiVersion = IOTHUB_API_VERSION;
    21942382        const char* appSpecifiedProductInfo = transport_data->transport_callbacks.prod_info_cb(transport_data->transport_ctx);
    2195         STRING_HANDLE productInfoEncoded = NULL; 
     2383        STRING_HANDLE productInfoEncoded = NULL;
    21962384
    21972385        if ((productInfoEncoded = URL_EncodeString((appSpecifiedProductInfo != NULL) ? appSpecifiedProductInfo : DEFAULT_IOTHUB_PRODUCT_IDENTIFIER)) == NULL)
     
    22542442}
    22552443
     2444//
     2445// SendMqttConnectMsg sends the MQTT CONNECT message across the network.  This function may also
     2446// perform security functionality for building up the required token (optionally invoking into DPS if configured to do so)
     2447//
    22562448static int SendMqttConnectMsg(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    22572449{
     
    23222514            options.qualityOfServiceValue = DELIVER_AT_LEAST_ONCE;
    23232515
    2324             if (GetTransportProviderIfNecessary(transport_data) == 0)
     2516            if (CreateTransportProviderIfNecessary(transport_data) == 0)
    23252517            {
    23262518                transport_data->conn_attempted = true;
     
    23332525                {
    23342526                    transport_data->currPacketState = CONNECT_TYPE;
    2335                     transport_data->isRetryExpiredCallbackSet = false;
     2527                    transport_data->isRetryExpiredCallbackCalled = false;
    23362528                    (void)tickcounter_get_current_ms(transport_data->msgTickCounter, &transport_data->mqtt_connect_time);
    23372529                    result = 0;
     
    23532545}
    23542546
    2355 static int InitializeConnection(PMQTTTRANSPORT_HANDLE_DATA transport_data)
     2547//
     2548// UpdateMqttConnectionStateIfNeeded is used for updating MQTT's underlying connection status during a DoWork loop.
     2549// Among this function's responsibilities:
     2550// * Attempt to establish an MQTT connection if one has not been already.
     2551// * Retries failed connection, if in the correct state.
     2552// * Processes deferred disconnect requests
     2553// * Checks timeouts, for instance on connection establishment time as well as SaS token lifetime (if SAS used)
     2554static int UpdateMqttConnectionStateIfNeeded(PMQTTTRANSPORT_HANDLE_DATA transport_data)
    23562555{
    23572556    int result = 0;
     
    23932592            {
    23942593                // Set callback if retry expired
    2395                 if (!transport_data->isRetryExpiredCallbackSet)
     2594                if (!transport_data->isRetryExpiredCallbackCalled)
    23962595                {
    23972596                    transport_data->transport_callbacks.connection_status_cb(IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_RETRY_EXPIRED, transport_data->transport_ctx);
    2398                     transport_data->isRetryExpiredCallbackSet = true;
     2597                    transport_data->isRetryExpiredCallbackCalled = true;
    23992598                }
    24002599                result = MU_FAILURE;
     
    24432642                if (cred_type != IOTHUB_CREDENTIAL_TYPE_X509 && cred_type != IOTHUB_CREDENTIAL_TYPE_X509_ECC)
    24442643                {
    2445                     size_t sas_token_expiry = IoTHubClient_Auth_Get_SasToken_Expiry(transport_data->authorization_module);
     2644                    uint64_t sas_token_expiry = IoTHubClient_Auth_Get_SasToken_Expiry(transport_data->authorization_module);
    24462645                    if ((current_time - transport_data->mqtt_connect_time) / 1000 > (sas_token_expiry*SAS_REFRESH_MULTIPLIER))
    24472646                    {
     
    24942693}
    24952694
     2695//
     2696// buildMqttEventString creates the MQTT topic for this device (and optionally module) to PUBLISH telemetry to.
     2697//
    24962698static STRING_HANDLE buildMqttEventString(const char* device_id, const char* module_id)
    24972699{
     
    25062708}
    25072709
     2710//
     2711// buildDevicesAndModulesPath builds the path used when generating a SaS token for this request.
     2712//
    25082713static STRING_HANDLE buildDevicesAndModulesPath(const IOTHUB_CLIENT_CONFIG* upperConfig, const char* moduleId)
    25092714{
     
    25182723}
    25192724
     2725//
     2726// buildTopicMqttMsg builds the MQTT topic that is used for C2D messages sent to a device or module-to-module messages for a module running in IoT Edge
     2727//
     2728static STRING_HANDLE buildTopicMqttMsg(const char* device_id, const char* module_id)
     2729{
     2730    if (module_id == NULL)
     2731    {
     2732        return STRING_construct_sprintf(TOPIC_DEVICE_MSG, device_id);
     2733    }
     2734    else
     2735    {
     2736        return STRING_construct_sprintf(TOPIC_DEVICE_MODULE_MSG, device_id, module_id);
     2737    }
     2738}
     2739
     2740//
     2741// checkModuleIdsEqual verifies that module Ids coming from different upper layers are equal.
     2742//
     2743static bool checkModuleIdsEqual(const char* transportModuleId, const char* deviceModuleId)
     2744{
     2745    if ((transportModuleId != NULL) && (deviceModuleId == NULL))
     2746    {
     2747        return false;
     2748    }
     2749    else if ((transportModuleId == NULL) && (deviceModuleId != NULL))
     2750    {
     2751        return false;
     2752    }
     2753    else if ((transportModuleId == NULL) && (deviceModuleId == NULL))
     2754    {
     2755        return true;
     2756    }
     2757    else
     2758    {
     2759        return (0 == strcmp(transportModuleId, deviceModuleId));
     2760    }
     2761}
     2762
     2763//
     2764// InitializeTransportHandleData creates a MQTTTRANSPORT_HANDLE_DATA.
     2765//
    25202766static PMQTTTRANSPORT_HANDLE_DATA InitializeTransportHandleData(const IOTHUB_CLIENT_CONFIG* upperConfig, PDLIST_ENTRY waitingToSend, IOTHUB_AUTHORIZATION_HANDLE auth_module, const char* moduleId)
    25212767{
     
    25312777        {
    25322778            LogError("Invalid Argument: iotHubName is empty");
    2533             free_transport_handle_data(state);
     2779            freeTransportHandleData(state);
    25342780            state = NULL;
    25352781        }
     
    25382784        {
    25392785            LogError("Failed creating default retry control");
    2540             free_transport_handle_data(state);
     2786            freeTransportHandleData(state);
    25412787            state = NULL;
    25422788        }
     
    25442790        {
    25452791            LogError("failure constructing device_id.");
    2546             free_transport_handle_data(state);
     2792            freeTransportHandleData(state);
    25472793            state = NULL;
    25482794        }
     
    25502796        {
    25512797            LogError("failure constructing module_id.");
    2552             free_transport_handle_data(state);
     2798            freeTransportHandleData(state);
    25532799            state = NULL;
    25542800        }
     
    25562802        {
    25572803            LogError("failure constructing devicesPath.");
    2558             free_transport_handle_data(state);
     2804            freeTransportHandleData(state);
    25592805            state = NULL;
    25602806        }
     
    25642810            {
    25652811                LogError("Could not create topic_MqttEvent for MQTT");
    2566                 free_transport_handle_data(state);
     2812                freeTransportHandleData(state);
    25672813                state = NULL;
    25682814            }
    25692815            else
    25702816            {
    2571                 state->mqttClient = mqtt_client_init(mqtt_notification_callback, mqtt_operation_complete_callback, state, mqtt_error_callback, state);
     2817                state->mqttClient = mqtt_client_init(mqttNotificationCallback, mqttOperationCompleteCallback, state, processErrorCallback, state);
    25722818                if (state->mqttClient == NULL)
    25732819                {
    25742820                    LogError("failure initializing mqtt client.");
    2575                     free_transport_handle_data(state);
     2821                    freeTransportHandleData(state);
    25762822                    state = NULL;
    25772823                }
     
    25912837                    {
    25922838                        LogError("failure constructing host address.");
    2593                         free_transport_handle_data(state);
     2839                        freeTransportHandleData(state);
    25942840                        state = NULL;
    25952841                    }
    25962842                    else if ((state->configPassedThroughUsername = buildConfigForUsernameStep1(upperConfig, moduleId)) == NULL)
    25972843                    {
    2598                         free_transport_handle_data(state);
     2844                        freeTransportHandleData(state);
    25992845                        state = NULL;
    26002846                    }
     
    26172863
    26182864                        state->isDestroyCalled = false;
    2619                         state->isRetryExpiredCallbackSet = false;
     2865                        state->isRetryExpiredCallbackCalled = false;
    26202866                        state->isRegistered = false;
    26212867                        state->device_twin_get_sent = false;
     
    26412887}
    26422888
     2889//
     2890// ProcessSubackDoWork processes state transitions responding to a SUBACK packet.
     2891// This does NOT occur once we receive the SUBACK packet immediately; instead the work is
     2892// deferred to the DoWork loop.
     2893//
     2894static void ProcessSubackDoWork(PMQTTTRANSPORT_HANDLE_DATA transport_data)
     2895{
     2896    if ((transport_data->topic_NotifyState != NULL || transport_data->topic_GetState != NULL) &&
     2897        !transport_data->device_twin_get_sent)
     2898    {
     2899        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_055: [ IoTHubTransport_MQTT_Common_DoWork shall send a device twin get property message upon successfully retrieving a SUBACK on device twin topics. ] */
     2900        MQTT_DEVICE_TWIN_ITEM* mqtt_info;
     2901
     2902        if ((mqtt_info = createDeviceTwinMsg(transport_data, RETRIEVE_PROPERTIES, 0)) == NULL)
     2903        {
     2904            LogError("Failure: could not create message for twin get command");
     2905        }
     2906        else if (publishDeviceTwinGetMsg(transport_data, mqtt_info) == 0)
     2907        {
     2908            transport_data->device_twin_get_sent = true;
     2909        }
     2910        else
     2911        {
     2912            LogError("Failure: sending device twin get command.");
     2913            destroyDeviceTwinGetMsg(mqtt_info);
     2914        }
     2915    }
     2916
     2917    // Publish can be called now and in any event we need to transition out of this state.
     2918    transport_data->currPacketState = PUBLISH_TYPE;
     2919}
     2920
     2921//
     2922// ProcessPublishStateDoWork traverses all messages waiting to be sent and attempts to PUBLISH them.
     2923//
     2924static void ProcessPublishStateDoWork(PMQTTTRANSPORT_HANDLE_DATA transport_data)
     2925{
     2926    PDLIST_ENTRY currentListEntry = transport_data->waitingToSend->Flink;
     2927    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransport_MQTT_Common_DoWork shall inspect the "waitingToSend" DLIST passed in config structure.] */
     2928    while (currentListEntry != transport_data->waitingToSend)
     2929    {
     2930        IOTHUB_MESSAGE_LIST* iothubMsgList = containingRecord(currentListEntry, IOTHUB_MESSAGE_LIST, entry);
     2931        DLIST_ENTRY savedFromCurrentListEntry;
     2932        savedFromCurrentListEntry.Flink = currentListEntry->Flink;
     2933
     2934        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransport_MQTT_Common_DoWork shall inspect the "waitingToSend" DLIST passed in config structure.] */
     2935        size_t messageLength;
     2936        const unsigned char* messagePayload = NULL;
     2937        if (!RetrieveMessagePayload(iothubMsgList->messageHandle, &messagePayload, &messageLength))
     2938        {
     2939            (void)(DList_RemoveEntryList(currentListEntry));
     2940            notifyApplicationOfSendMessageComplete(iothubMsgList, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
     2941            LogError("Failure result from IoTHubMessage_GetData");
     2942        }
     2943        else
     2944        {
     2945            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_029: [IoTHubTransport_MQTT_Common_DoWork shall create a MQTT_MESSAGE_HANDLE and pass this to a call to mqtt_client_publish.] */
     2946            MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = (MQTT_MESSAGE_DETAILS_LIST*)malloc(sizeof(MQTT_MESSAGE_DETAILS_LIST));
     2947            if (mqttMsgEntry == NULL)
     2948            {
     2949                LogError("Allocation Error: Failure allocating MQTT Message Detail List.");
     2950            }
     2951            else
     2952            {
     2953                mqttMsgEntry->retryCount = 0;
     2954                mqttMsgEntry->iotHubMessageEntry = iothubMsgList;
     2955                mqttMsgEntry->packet_id = getNextPacketId(transport_data);
     2956                if (publishTelemetryMsg(transport_data, mqttMsgEntry, messagePayload, messageLength) != 0)
     2957                {
     2958                    (void)(DList_RemoveEntryList(currentListEntry));
     2959                    notifyApplicationOfSendMessageComplete(iothubMsgList, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
     2960                    free(mqttMsgEntry);
     2961                }
     2962                else
     2963                {
     2964                    // Remove the message from the waiting queue ...
     2965                    (void)(DList_RemoveEntryList(currentListEntry));
     2966                    // and add it to the ack queue
     2967                    DList_InsertTailList(&(transport_data->telemetry_waitingForAck), &(mqttMsgEntry->entry));
     2968                }
     2969            }
     2970        }
     2971        currentListEntry = savedFromCurrentListEntry.Flink;
     2972    }
     2973
     2974    if (transport_data->twin_resp_sub_recv)
     2975    {
     2976        sendPendingGetTwinRequests(transport_data);
     2977    }
     2978}
     2979
    26432980TRANSPORT_LL_HANDLE IoTHubTransport_MQTT_Common_Create(const IOTHUBTRANSPORT_CONFIG* config, MQTT_GET_IO_TRANSPORT get_io_transport, TRANSPORT_CALLBACKS_INFO* cb_info, void* ctx)
    26442981{
     
    27413078            PDLIST_ENTRY currentEntry = DList_RemoveHeadList(&transport_data->telemetry_waitingForAck);
    27423079            MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = containingRecord(currentEntry, MQTT_MESSAGE_DETAILS_LIST, entry);
    2743             sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY);
     3080            notifyApplicationOfSendMessageComplete(mqttMsgEntry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY);
    27443081            free(mqttMsgEntry);
    27453082        }
     
    27583095            }
    27593096
    2760             destroy_device_twin_get_message(mqtt_device_twin);
     3097            destroyDeviceTwinGetMsg(mqtt_device_twin);
    27613098        }
    27623099        while (!DList_IsListEmpty(&transport_data->pending_get_twin_queue))
     
    27683105            mqtt_device_twin->userCallback(DEVICE_TWIN_UPDATE_COMPLETE, NULL, 0, mqtt_device_twin->userContext);
    27693106
    2770             destroy_device_twin_get_message(mqtt_device_twin);
     3107            destroyDeviceTwinGetMsg(mqtt_device_twin);
    27713108        }
    27723109
    27733110        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_014: [IoTHubTransport_MQTT_Common_Destroy shall free all the resources currently in use.] */
    27743111        /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_012: [ `IoTHubTransport_MQTT_Common_Destroy` shall free the stored proxy options. ]*/
    2775         free_transport_handle_data(transport_data);
     3112        freeTransportHandleData(transport_data);
    27763113    }
    27773114}
     
    28603197        MQTT_DEVICE_TWIN_ITEM* mqtt_info;
    28613198
    2862         if ((mqtt_info = create_device_twin_message(transport_data, RETRIEVE_PROPERTIES, 0)) == NULL)
     3199        if ((mqtt_info = createDeviceTwinMsg(transport_data, RETRIEVE_PROPERTIES, 0)) == NULL)
    28633200        {
    28643201            LogError("Failed creating the device twin get request message");
     
    28693206        {
    28703207            LogError("Failed setting the get twin request enqueue time");
    2871             destroy_device_twin_get_message(mqtt_info);
     3208            destroyDeviceTwinGetMsg(mqtt_info);
    28723209            // Codes_SRS_IOTHUB_MQTT_TRANSPORT_09_003: [ If any failure occurs, IoTHubTransport_MQTT_Common_GetTwinAsync shall return IOTHUB_CLIENT_ERROR ]
    28733210            result = IOTHUB_CLIENT_ERROR;
     
    29493286
    29503287            /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_011 : [IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod shall send the unsubscribe.]*/
    2951             if (mqtt_client_unsubscribe(transport_data->mqttClient, get_next_packet_id(transport_data), unsubscribe, 1) != 0)
     3288            if (mqtt_client_unsubscribe(transport_data->mqttClient, getNextPacketId(transport_data), unsubscribe, 1) != 0)
    29523289            {
    29533290                LogError("Failure calling mqtt_client_unsubscribe");
     
    29813318        else
    29823319        {
    2983             if (publish_device_method_message(transport_data, status, dev_method_info->request_id, response, respSize) != 0)
     3320            if (publishDeviceMethodResponseMsg(transport_data, status, dev_method_info->request_id, response, respSize) != 0)
    29843321            {
    29853322                /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_051: [ If any error is encountered, IoTHubTransport_MQTT_Common_DeviceMethod_Response shall return a non-zero value. ] */
     
    30043341}
    30053342
    3006 static STRING_HANDLE buildTopicMqttMessage(const char* device_id, const char* module_id)
    3007 {
    3008     if (module_id == NULL)
    3009     {
    3010         return STRING_construct_sprintf(TOPIC_DEVICE_MSG, device_id);
    3011     }
    3012     else
    3013     {
    3014         return STRING_construct_sprintf(TOPIC_DEVICE_MODULE_MSG, device_id, module_id);
    3015     }
    3016 }
    3017 
    30183343int IoTHubTransport_MQTT_Common_Subscribe(TRANSPORT_LL_HANDLE handle)
    30193344{
     
    30293354    {
    30303355        /* Code_SRS_IOTHUB_MQTT_TRANSPORT_07_016: [IoTHubTransport_MQTT_Common_Subscribe shall set a flag to enable mqtt_client_subscribe to be called to subscribe to the Message Topic.] */
    3031         transport_data->topic_MqttMessage = buildTopicMqttMessage(STRING_c_str(transport_data->device_id), STRING_c_str(transport_data->module_id));
     3356        transport_data->topic_MqttMessage = buildTopicMqttMsg(STRING_c_str(transport_data->device_id), STRING_c_str(transport_data->module_id));
    30323357        if (transport_data->topic_MqttMessage == NULL)
    30333358        {
     
    30553380        const char* unsubscribe[1];
    30563381        unsubscribe[0] = STRING_c_str(transport_data->topic_MqttMessage);
    3057         if (mqtt_client_unsubscribe(transport_data->mqttClient, get_next_packet_id(transport_data), unsubscribe, 1) != 0)
     3382        if (mqtt_client_unsubscribe(transport_data->mqttClient, getNextPacketId(transport_data), unsubscribe, 1) != 0)
    30583383        {
    30593384            LogError("Failure calling mqtt_client_unsubscribe");
     
    30873412            if (item_type == IOTHUB_TYPE_DEVICE_TWIN && transport_data->twin_resp_sub_recv)
    30883413            {
    3089                 MQTT_DEVICE_TWIN_ITEM* mqtt_info = create_device_twin_message(transport_data, REPORTED_STATE, iothub_item->device_twin->item_id);
     3414                MQTT_DEVICE_TWIN_ITEM* mqtt_info = createDeviceTwinMsg(transport_data, REPORTED_STATE, iothub_item->device_twin->item_id);
    30903415                if (mqtt_info == NULL)
    30913416                {
     
    30993424                    DList_InsertTailList(&transport_data->ack_waiting_queue, &mqtt_info->entry);
    31003425
    3101                     if (publish_device_twin_message(transport_data, iothub_item->device_twin, mqtt_info) != 0)
     3426                    if (publishDeviceTwinMsg(transport_data, iothub_item->device_twin, mqtt_info) != 0)
    31023427                    {
    31033428                        DList_RemoveEntryList(&mqtt_info->entry);
     
    31353460    if (transport_data != NULL)
    31363461    {
    3137         if (InitializeConnection(transport_data) == 0)
     3462        if (UpdateMqttConnectionStateIfNeeded(transport_data) == 0)
    31383463        {
    31393464            if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_PENDING_CLOSE)
     
    31483473            else if (transport_data->currPacketState == SUBACK_TYPE)
    31493474            {
    3150                 if ((transport_data->topic_NotifyState != NULL || transport_data->topic_GetState != NULL) &&
    3151                     !transport_data->device_twin_get_sent)
    3152                 {
    3153                     /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_055: [ IoTHubTransport_MQTT_Common_DoWork shall send a device twin get property message upon successfully retrieving a SUBACK on device twin topics. ] */
    3154                     MQTT_DEVICE_TWIN_ITEM* mqtt_info;
    3155 
    3156                     if ((mqtt_info = create_device_twin_message(transport_data, RETRIEVE_PROPERTIES, 0)) == NULL)
    3157                     {
    3158                         LogError("Failure: could not create message for twin get command");
    3159                     }
    3160                     else if (publish_device_twin_get_message(transport_data, mqtt_info) == 0)
    3161                     {
    3162                         transport_data->device_twin_get_sent = true;
    3163                     }
    3164                     else
    3165                     {
    3166                         LogError("Failure: sending device twin get property command.");
    3167                         destroy_device_twin_get_message(mqtt_info);
    3168                     }
    3169                 }
    3170                 // Publish can be called now
    3171                 transport_data->currPacketState = PUBLISH_TYPE;
     3475                ProcessSubackDoWork(transport_data);
    31723476            }
    31733477            else if (transport_data->currPacketState == PUBLISH_TYPE)
    31743478            {
    3175                 PDLIST_ENTRY currentListEntry = transport_data->waitingToSend->Flink;
    3176                 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransport_MQTT_Common_DoWork shall inspect the "waitingToSend" DLIST passed in config structure.] */
    3177                 while (currentListEntry != transport_data->waitingToSend)
    3178                 {
    3179                     IOTHUB_MESSAGE_LIST* iothubMsgList = containingRecord(currentListEntry, IOTHUB_MESSAGE_LIST, entry);
    3180                     DLIST_ENTRY savedFromCurrentListEntry;
    3181                     savedFromCurrentListEntry.Flink = currentListEntry->Flink;
    3182 
    3183                     /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransport_MQTT_Common_DoWork shall inspect the "waitingToSend" DLIST passed in config structure.] */
    3184                     size_t messageLength;
    3185                     const unsigned char* messagePayload = NULL;
    3186                     if (!RetrieveMessagePayload(iothubMsgList->messageHandle, &messagePayload, &messageLength))
    3187                     {
    3188                         (void)(DList_RemoveEntryList(currentListEntry));
    3189                         sendMsgComplete(iothubMsgList, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
    3190                         LogError("Failure result from IoTHubMessage_GetData");
    3191                     }
    3192                     else
    3193                     {
    3194                         /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_029: [IoTHubTransport_MQTT_Common_DoWork shall create a MQTT_MESSAGE_HANDLE and pass this to a call to mqtt_client_publish.] */
    3195                         MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = (MQTT_MESSAGE_DETAILS_LIST*)malloc(sizeof(MQTT_MESSAGE_DETAILS_LIST));
    3196                         if (mqttMsgEntry == NULL)
    3197                         {
    3198                             LogError("Allocation Error: Failure allocating MQTT Message Detail List.");
    3199                         }
    3200                         else
    3201                         {
    3202                             mqttMsgEntry->retryCount = 0;
    3203                             mqttMsgEntry->iotHubMessageEntry = iothubMsgList;
    3204                             mqttMsgEntry->packet_id = get_next_packet_id(transport_data);
    3205                             if (publish_mqtt_telemetry_msg(transport_data, mqttMsgEntry, messagePayload, messageLength) != 0)
    3206                             {
    3207                                 (void)(DList_RemoveEntryList(currentListEntry));
    3208                                 sendMsgComplete(iothubMsgList, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
    3209                                 free(mqttMsgEntry);
    3210                             }
    3211                             else
    3212                             {
    3213                                 // Remove the message from the waiting queue ...
    3214                                 (void)(DList_RemoveEntryList(currentListEntry));
    3215                                 // and add it to the ack queue
    3216                                 DList_InsertTailList(&(transport_data->telemetry_waitingForAck), &(mqttMsgEntry->entry));
    3217                             }
    3218                         }
    3219                     }
    3220                     currentListEntry = savedFromCurrentListEntry.Flink;
    3221                 }
    3222 
    3223                 if (transport_data->twin_resp_sub_recv)
    3224                 {
    3225                     sendPendingGetTwinRequests(transport_data);
    3226                 }
     3479                ProcessPublishStateDoWork(transport_data);
    32273480            }
    32283481            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_030: [IoTHubTransport_MQTT_Common_DoWork shall call mqtt_client_dowork everytime it is called if it is connected.] */
     
    32313484
    32323485        // Check the ack messages timeouts
    3233         process_queued_ack_messages(transport_data);
     3486        ProcessPendingTelemetryMessages(transport_data);
    32343487        removeExpiredTwinRequests(transport_data);
    32353488    }
    32363489}
    32373490
     3491int IoTHubTransport_MQTT_Common_SetRetryPolicy(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
     3492{
     3493    int result;
     3494
     3495    if (handle == NULL)
     3496    {
     3497        /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_25_041: [**If any handle is NULL then IoTHubTransport_MQTT_Common_SetRetryPolicy shall return resultant line.] */
     3498        LogError("Invalid handle parameter. NULL.");
     3499        result = MU_FAILURE;
     3500    }
     3501    else
     3502    {
     3503        RETRY_CONTROL_HANDLE new_retry_control_handle;
     3504
     3505        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_006: [ IoTHubTransport_MQTT_Common_SetRetryPolicy shall set the retry logic by calling retry_control_create() with retry policy and retryTimeout as parameters]
     3506        // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_009: [ If retry_control_create() fails then IoTHubTransport_MQTT_Common_SetRetryPolicy shall revert to previous retry policy and return non-zero value ]
     3507        if ((new_retry_control_handle = retry_control_create(retryPolicy, (unsigned int)retryTimeoutLimitInSeconds)) == NULL)
     3508        {
     3509            LogError("Failed creating new retry control handle");
     3510            result = MU_FAILURE;
     3511        }
     3512        else
     3513        {
     3514            PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
     3515            RETRY_CONTROL_HANDLE previous_retry_control_handle = transport_data->retry_control_handle;
     3516
     3517            transport_data->retry_control_handle = new_retry_control_handle;
     3518            retry_control_destroy(previous_retry_control_handle);
     3519
     3520            /*Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_25_045: [**If retry logic for specified parameters of retry policy and retryTimeoutLimitInSeconds is created successfully then IoTHubTransport_MQTT_Common_SetRetryPolicy shall return 0]*/
     3521            result = 0;
     3522        }
     3523    }
     3524
     3525    return result;
     3526}
     3527
     3528
    32383529IOTHUB_CLIENT_RESULT IoTHubTransport_MQTT_Common_GetSendStatus(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
    32393530{
     
    32423533    if (handle == NULL || iotHubClientStatus == NULL)
    32433534    {
    3244     /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_023: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */
    3245     LogError("invalid arument.");
    3246     result = IOTHUB_CLIENT_INVALID_ARG;
    3247     }
    3248     else
    3249     {
    3250     MQTTTRANSPORT_HANDLE_DATA* handleData = (MQTTTRANSPORT_HANDLE_DATA*)handle;
    3251     if (!DList_IsListEmpty(handleData->waitingToSend) || !DList_IsListEmpty(&(handleData->telemetry_waitingForAck)))
    3252     {
    3253         /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_025: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent.] */
    3254         *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_BUSY;
    3255     }
    3256     else
    3257     {
    3258         /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_024: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent.] */
    3259         *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_IDLE;
    3260     }
    3261     result = IOTHUB_CLIENT_OK;
     3535        /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_023: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */
     3536        LogError("invalid argument.");
     3537        result = IOTHUB_CLIENT_INVALID_ARG;
     3538    }
     3539    else
     3540    {
     3541        MQTTTRANSPORT_HANDLE_DATA* handleData = (MQTTTRANSPORT_HANDLE_DATA*)handle;
     3542        if (!DList_IsListEmpty(handleData->waitingToSend) || !DList_IsListEmpty(&(handleData->telemetry_waitingForAck)))
     3543        {
     3544            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_025: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent.] */
     3545            *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_BUSY;
     3546        }
     3547        else
     3548        {
     3549            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_024: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent.] */
     3550            *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_IDLE;
     3551        }
     3552        result = IOTHUB_CLIENT_OK;
    32623553    }
    32633554    return result;
     
    34233714                {
    34243715                    /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_009: [ When setting the proxy options succeeds any previously saved proxy options shall be freed. ]*/
    3425                     free_proxy_data(transport_data);
     3716                    freeProxyData(transport_data);
    34263717
    34273718                    transport_data->http_proxy_hostname = copied_proxy_hostname;
     
    34433734
    34443735            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_032: [IoTHubTransport_MQTT_Common_SetOption shall pass down the option to xio_setoption if the option parameter is not a known option string for the MQTT transport.] */
    3445             if (GetTransportProviderIfNecessary(transport_data) == 0)
     3736            if (CreateTransportProviderIfNecessary(transport_data) == 0)
    34463737            {
    34473738                if (xio_setoption(transport_data->xioTransport, option, value) == 0)
     
    34623753    }
    34633754    return result;
    3464 }
    3465 
    3466 static bool check_module_ids_equal(const char* transportModuleId, const char* deviceModuleId)
    3467 {
    3468     if ((transportModuleId != NULL) && (deviceModuleId == NULL))
    3469     {
    3470         return false;
    3471     }
    3472     else if ((transportModuleId == NULL) && (deviceModuleId != NULL))
    3473     {
    3474         return false;
    3475     }
    3476     else if ((transportModuleId == NULL) && (deviceModuleId == NULL))
    3477     {
    3478         return true;
    3479     }
    3480     else
    3481     {
    3482         return (0 == strcmp(transportModuleId, deviceModuleId));
    3483     }
    34843755}
    34853756
     
    35193790                result = NULL;
    35203791            }
    3521             else if (!check_module_ids_equal(STRING_c_str(transport_data->module_id), device->moduleId))
     3792            else if (!checkModuleIdsEqual(STRING_c_str(transport_data->module_id), device->moduleId))
    35223793            {
    35233794                LogError("IoTHubTransport_MQTT_Common_Register: moduleId does not match.");
     
    36503921        const char* unsubscribe[1];
    36513922        unsubscribe[0] = STRING_c_str(transport_data->topic_InputQueue);
    3652         if (mqtt_client_unsubscribe(transport_data->mqttClient, get_next_packet_id(transport_data), unsubscribe, 1) != 0)
     3923        if (mqtt_client_unsubscribe(transport_data->mqttClient, getNextPacketId(transport_data), unsubscribe, 1) != 0)
    36533924        {
    36543925            LogError("Failure calling mqtt_client_unsubscribe");
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_client_const.h

    r457 r464  
    55#define PROV_CLIENT_CONST_H
    66
    7 #define PROV_DEVICE_CLIENT_VERSION "1.3.8"
     7#define PROV_DEVICE_CLIENT_VERSION "1.6.0"
    88#define PROV_GET_THROTTLE_TIME      1
    99#define MAX_PROV_GET_THROTTLE_TIME  5*60
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_device_client.h

    r457 r464  
    2626#include "umock_c/umock_c_prod.h"
    2727#include "azure_macro_utils/macro_utils.h"
     28#include "azure_c_shared_utility/const_defines.h"
    2829#include "azure_prov_client/prov_transport.h"
    2930
     
    3233{
    3334#endif
     35
     36static STATIC_VAR_UNUSED const char* const PROV_OPTION_DO_WORK_FREQUENCY_IN_MS = "do_work_freq_ms";
    3437
    3538MOCKABLE_FUNCTION(, PROV_DEVICE_HANDLE, Prov_Device_Create, const char*, uri, const char*, scope_id, PROV_DEVICE_TRANSPORT_PROVIDER_FUNCTION, protocol);
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/provisioning_client/inc/azure_prov_client/prov_device_ll_client.h

    r457 r464  
    77#include "umock_c/umock_c_prod.h"
    88#include "azure_macro_utils/macro_utils.h"
     9#include "azure_c_shared_utility/const_defines.h"
    910#include "azure_prov_client/prov_transport.h"
    1011
     
    4344MU_DEFINE_ENUM_WITHOUT_INVALID(PROV_DEVICE_REG_STATUS, PROV_DEVICE_REG_STATUS_VALUES);
    4445
    45 static const char* const PROV_REGISTRATION_ID = "registration_id";
    46 static const char* const PROV_OPTION_LOG_TRACE = "logtrace";
    47 static const char* const PROV_OPTION_TIMEOUT = "provisioning_timeout";
     46static STATIC_VAR_UNUSED const char* const PROV_REGISTRATION_ID = "registration_id";
     47static STATIC_VAR_UNUSED const char* const PROV_OPTION_LOG_TRACE = "logtrace";
     48static STATIC_VAR_UNUSED const char* const PROV_OPTION_TIMEOUT = "provisioning_timeout";
    4849
    4950typedef void(*PROV_DEVICE_CLIENT_REGISTER_DEVICE_CALLBACK)(PROV_DEVICE_RESULT register_result, const char* iothub_uri, const char* device_id, void* user_context);
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/provisioning_client/src/prov_device_client.c

    r457 r464  
    1515
    1616#define DO_WORK_FREQ_DEFAULT 1
    17 
    18 static const char* const OPTION_DO_WORK_FREQUENCY_IN_MS = "do_work_freq_ms";
    1917
    2018typedef struct PROV_DEVICE_INSTANCE_TAG
     
    260258        {
    261259            /* Codes_SRS_PROV_DEVICE_CLIENT_41_001: [ If parameter `optionName` is `OPTION_DO_WORK_FREQUENCY_IN_MS` then `IoTHubClientCore_SetOption` shall set `do_work_freq_ms` parameter of `prov_device_instance` ] */
    262             if (strcmp(OPTION_DO_WORK_FREQUENCY_IN_MS, optionName) == 0)
     260            if (strcmp(PROV_OPTION_DO_WORK_FREQUENCY_IN_MS, optionName) == 0)
    263261            {
    264262                prov_device_instance->do_work_freq_ms = *((uint16_t *)value);
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/provisioning_client/src/prov_device_ll_client.c

    r457 r464  
    9393    TICK_COUNTER_HANDLE tick_counter;
    9494
    95     tickcounter_ms_t status_throttle;
     95    tickcounter_ms_t last_send_time_ms;
    9696    tickcounter_ms_t timeout_value;
    97     uint32_t retry_after_value;
     97    size_t retry_after_ms;
    9898
    9999    uint8_t prov_timeout;
     
    784784        PROV_INSTANCE_INFO* prov_info = (PROV_INSTANCE_INFO*)user_ctx;
    785785
    786         prov_info->retry_after_value = retry_interval;
     786        prov_info->retry_after_ms = (size_t)retry_interval * 1000; // retry_interval is in seconds.
    787787
    788788        switch (transport_status)
     
    880880            /* Codes_SRS_PROV_CLIENT_07_028: [ CLIENT_STATE_READY is the initial state after the object is created which will send a uhttp_client_open call to the http endpoint. ] */
    881881            result->prov_state = CLIENT_STATE_READY;
    882             result->retry_after_value = PROV_GET_THROTTLE_TIME;
     882            result->retry_after_ms = PROV_GET_THROTTLE_TIME * 1000;
    883883            result->prov_transport_protocol = protocol();
    884884            result->error_reason = PROV_DEVICE_RESULT_OK;
     
    931931                {
    932932                    // Ensure that we are passed the throttling time and send on the first send
    933                     (void)tickcounter_get_current_ms(result->tick_counter, &result->status_throttle);
    934                     result->status_throttle += (result->retry_after_value * 1000);
     933                    (void)tickcounter_get_current_ms(result->tick_counter, &result->last_send_time_ms);
     934                    result->last_send_time_ms += result->retry_after_ms;
    935935                }
    936936            }
     
    11191119        if (prov_info->is_connected || prov_info->prov_state == CLIENT_STATE_ERROR)
    11201120        {
     1121            tickcounter_ms_t current_time = 0;
     1122
    11211123            switch (prov_info->prov_state)
    11221124            {
    11231125                case CLIENT_STATE_REGISTER_SEND:
    1124                     /* Codes_SRS_PROV_CLIENT_07_013: [ CLIENT_STATE_REGISTER_SEND which shall construct an initial call to the service with endorsement information ] */
    1125                     if (prov_info->prov_transport_protocol->prov_transport_register(prov_info->transport_handle, prov_transport_process_json_reply, prov_transport_create_json_payload, prov_info) != 0)
    1126                     {
    1127                         LogError("Failure registering device");
    1128                         if (prov_info->error_reason == PROV_DEVICE_RESULT_OK)
    1129                         {
    1130                             prov_info->error_reason = PROV_DEVICE_RESULT_TRANSPORT;
    1131                         }
    1132                         prov_info->prov_state = CLIENT_STATE_ERROR;
    1133                     }
    1134                     else
    1135                     {
    1136                         (void)tickcounter_get_current_ms(prov_info->tick_counter, &prov_info->timeout_value);
    1137                         prov_info->prov_state = CLIENT_STATE_REGISTER_SENT;
    1138                     }
    1139                     break;
    1140 
    1141                 case CLIENT_STATE_STATUS_SEND:
    1142                 {
    1143                     tickcounter_ms_t current_time = 0;
    11441126                    if (tickcounter_get_current_ms(prov_info->tick_counter, &current_time) != 0)
    11451127                    {
     
    11501132                    else
    11511133                    {
    1152                         if ((current_time - prov_info->status_throttle) / 1000 > prov_info->retry_after_value)
     1134                        if ((current_time - prov_info->last_send_time_ms) > prov_info->retry_after_ms)
     1135                        {
     1136                            /* Codes_SRS_PROV_CLIENT_07_013: [ CLIENT_STATE_REGISTER_SEND which shall construct an initial call to the service with endorsement information ] */
     1137                            if (prov_info->prov_transport_protocol->prov_transport_register(prov_info->transport_handle, prov_transport_process_json_reply, prov_transport_create_json_payload, prov_info) != 0)
     1138                            {
     1139                                LogError("Failure registering device");
     1140                                if (prov_info->error_reason == PROV_DEVICE_RESULT_OK)
     1141                                {
     1142                                    prov_info->error_reason = PROV_DEVICE_RESULT_TRANSPORT;
     1143                                }
     1144                                prov_info->prov_state = CLIENT_STATE_ERROR;
     1145                            }
     1146                            else
     1147                            {
     1148                                (void)tickcounter_get_current_ms(prov_info->tick_counter, &prov_info->timeout_value);
     1149                                prov_info->prov_state = CLIENT_STATE_REGISTER_SENT;
     1150                            }
     1151                            prov_info->last_send_time_ms = current_time;
     1152                        }
     1153                    }
     1154                    break;
     1155
     1156                case CLIENT_STATE_STATUS_SEND:
     1157                {
     1158                    if (tickcounter_get_current_ms(prov_info->tick_counter, &current_time) != 0)
     1159                    {
     1160                        LogError("Failure getting the current time");
     1161                        prov_info->error_reason = PROV_DEVICE_RESULT_ERROR;
     1162                        prov_info->prov_state = CLIENT_STATE_ERROR;
     1163                    }
     1164                    else
     1165                    {
     1166                        if ((current_time - prov_info->last_send_time_ms) > prov_info->retry_after_ms)
    11531167                        {
    11541168                            /* Codes_SRS_PROV_CLIENT_07_026: [ Upon receiving the reply of the CLIENT_STATE_URL_REQ_SEND message from  iothub_client shall process the the reply of the CLIENT_STATE_URL_REQ_SEND state ] */
     
    11721186                                }
    11731187                            }
    1174                             prov_info->status_throttle = current_time;
     1188                            prov_info->last_send_time_ms = current_time;
    11751189                        }
    11761190                    }
     
    11831197                    if (prov_info->prov_timeout > 0)
    11841198                    {
    1185                         tickcounter_ms_t current_time = 0;
    11861199                        (void)tickcounter_get_current_ms(prov_info->tick_counter, &current_time);
    11871200                        if ((current_time - prov_info->timeout_value) / 1000 > prov_info->prov_timeout)
     
    12791292            if (value == NULL)
    12801293            {
    1281                 LogError("setting proxy options");
     1294                LogError("setting PROV_OPTION_TIMEOUT option");
    12821295                result = PROV_DEVICE_RESULT_ERROR;
    12831296            }
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/provisioning_client/src/prov_transport_mqtt_common.c

    r457 r464  
    320320            if (memcmp(MQTT_TOPIC_STATUS_PREFIX, topic_resp, status_pos) == 0)
    321321            {
    322                 // If the status code is > 429 then this is a transient error
     322                // If the status code is >= 429 then this is a transient error
    323323                long status_code = atol(topic_resp + status_pos);
    324324                if (status_code >= PROV_STATUS_CODE_TRANSIENT_ERROR)
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqtt_client.h

    r457 r464  
    4949typedef void(*ON_MQTT_DISCONNECTED_CALLBACK)(void* callbackCtx);
    5050
     51MOCKABLE_FUNCTION(, void, mqtt_client_clear_xio, MQTT_CLIENT_HANDLE, handle);
    5152MOCKABLE_FUNCTION(, MQTT_CLIENT_HANDLE, mqtt_client_init, ON_MQTT_MESSAGE_RECV_CALLBACK, msgRecv, ON_MQTT_OPERATION_CALLBACK, opCallback, void*, opCallbackCtx, ON_MQTT_ERROR_CALLBACK, onErrorCallBack, void*, errorCBCtx);
    5253MOCKABLE_FUNCTION(, void, mqtt_client_deinit, MQTT_CLIENT_HANDLE, handle);
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/umqtt/inc/azure_umqtt_c/mqttconst.h

    r457 r464  
    3333    DISCONNECT_TYPE, 0xE0, \
    3434    PACKET_TYPE_ERROR, 0xE1, /* 0xE1 was assigned because ENUM_2 needs it */ \
    35     UNKNOWN_TYPE, 0xE2 /* 0xE2 was assigned because ENUM_2 needs it */
     35    UNKNOWN_TYPE, 0xE2,      /* 0xE2 was assigned because ENUM_2 needs it */ \
     36    PACKET_INVALID1_TYPE, 0x00, \
     37    PACKET_INVALID2_TYPE, 0xF0
    3638
    3739MU_DEFINE_ENUM_2(CONTROL_PACKET_TYPE, CONTROL_PACKET_TYPE_VALUES)
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/umqtt/src/mqtt_client.c

    r457 r464  
    770770                    /*Codes_SRS_MQTT_CLIENT_07_028: [If the actionResult parameter is of type CONNECT_ACK then the msgInfo value shall be a CONNECT_ACK structure.]*/
    771771                    CONNECT_ACK connack = { 0 };
    772                     connack.isSessionPresent = (byteutil_readByte(&iterator) == 0x1) ? true : false;
     772                    if (packetLength != 2) // CONNACK payload must be only 2 bytes
     773                    {
     774                        LogError("Invalid CONNACK packet.");
     775                        set_error_callback(mqtt_client, MQTT_CLIENT_COMMUNICATION_ERROR);
     776                        break;
     777                    }
     778
     779                    uint8_t connect_acknowledge_flags = byteutil_readByte(&iterator);
     780                    if (connect_acknowledge_flags & 0xFE) // bits 7-1 must be zero
     781                    {
     782                        LogError("Invalid CONNACK packet.");
     783                        set_error_callback(mqtt_client, MQTT_CLIENT_COMMUNICATION_ERROR);
     784                        break;
     785                    }
     786
     787                    connack.isSessionPresent = (connect_acknowledge_flags == 0x1) ? true : false;
    773788                    uint8_t rc = byteutil_readByte(&iterator);
    774789                    connack.returnCode =
     
    802817                case PUBCOMP_TYPE:
    803818                {
     819                    if (packetLength != 2) // PUBXXX payload must be only 2 bytes
     820                    {
     821                        LogError("Invalid packet length.");
     822                        set_error_callback(mqtt_client, MQTT_CLIENT_COMMUNICATION_ERROR);
     823                        break;
     824                    }
     825
    804826                    /*Codes_SRS_MQTT_CLIENT_07_029: [If the actionResult parameter are of types PUBACK_TYPE, PUBREC_TYPE, PUBREL_TYPE or PUBCOMP_TYPE then the msgInfo value shall be a PUBLISH_ACK structure.]*/
    805827                    MQTT_CLIENT_EVENT_RESULT action = (packet == PUBACK_TYPE) ? MQTT_CLIENT_ON_PUBLISH_ACK :
     
    876898                        {
    877899                            uint8_t qosRet = byteutil_readByte(&iterator);
     900                            if (qosRet & 0x7C) // SUBACK QOS bits 6-2 must be zero
     901                            {
     902                                LogError("Invalid SUBACK_TYPE packet.");
     903                                set_error_callback(mqtt_client, MQTT_CLIENT_COMMUNICATION_ERROR);
     904                                break;
     905                            }
    878906                            suback.qosReturn[suback.qosCount++] =
    879907                                (qosRet <= ((uint8_t)DELIVER_EXACTLY_ONCE)) ?
     
    909937                    /*Codes_SRS_MQTT_CLIENT_07_031: [If the actionResult parameter is of type UNSUBACK_TYPE then the msgInfo value shall be a UNSUBSCRIBE_ACK structure.]*/
    910938                    UNSUBSCRIBE_ACK unsuback = { 0 };
     939                    if (packetLength != 2) // UNSUBACK_TYPE payload must be only 2 bytes
     940                    {
     941                        LogError("Invalid UNSUBACK packet length.");
     942                        set_error_callback(mqtt_client, MQTT_CLIENT_COMMUNICATION_ERROR);
     943                        break;
     944                    }
     945
    911946                    unsuback.packetId = byteutil_read_uint16(&iterator, packetLength);
    912947
     
    943978    {
    944979        LogError("recvCompleteCallback context failed.");
     980    }
     981}
     982
     983void mqtt_client_clear_xio(MQTT_CLIENT_HANDLE handle)
     984{
     985    if (handle != NULL)
     986    {
     987        MQTT_CLIENT *mqtt_client = (MQTT_CLIENT *)handle;
     988
     989        // The upstream transport handle allocates and deallocates the xio handle.
     990        // The reference to that xio handle is shared between this layer (mqtt layer)
     991        // and the upstream layer. The clearing done here is to signal to this layer
     992        // that the handle is no longer available to be used. This is different from
     993        // deiniting the mqtt client in that we do not want an entire teardown, but
     994        // only a possible re-upping of the xio in the future.
     995        mqtt_client->xioHandle = NULL;
    945996    }
    946997}
  • azure_iot_hub_f767zi/trunk/azure_iot_sdk/umqtt/src/mqtt_codec.c

    r457 r464  
    568568            }
    569569        }
     570    }
     571    else if (codecData->remainLenIndex == (sizeof(codecData->storeRemainLen) / sizeof(codecData->storeRemainLen[0])))
     572    {
     573        // The maximum number of bytes in the Remaining Length field is four
     574        // This allows applications to send Control Packets of size up to 268,435,455 (256 MB).
     575        // The representation of this number on the wire is: 0xFF, 0xFF, 0xFF, 0x7F.
     576
     577        // The last byte has exceed the max value of 0x7F
     578        LogError("MQTT packet len is invalid");
     579        result = MU_FAILURE;
    570580    }
    571581    return result;
     
    10671077                {
    10681078                    codec_Data->currPacket = processControlPacketType(iterator, &codec_Data->headerFlags);
     1079
     1080                    // validate packet type and invalid reserved header flags
     1081                    switch (codec_Data->currPacket)
     1082                    {
     1083                        case PACKET_INVALID1_TYPE:
     1084                        case PACKET_INVALID2_TYPE:
     1085                            codec_Data->currPacket = PACKET_TYPE_ERROR;
     1086                            result = MU_FAILURE;
     1087                            break;
     1088
     1089                        case CONNECT_TYPE:
     1090                        case CONNACK_TYPE:
     1091                        case PUBACK_TYPE:
     1092                        case PUBREC_TYPE:
     1093                        case PUBCOMP_TYPE:
     1094                        case SUBACK_TYPE:
     1095                        case UNSUBACK_TYPE:
     1096                        case PINGREQ_TYPE:
     1097                        case PINGRESP_TYPE:
     1098                        case DISCONNECT_TYPE:
     1099                            if (codec_Data->headerFlags & 0x0F) // flags must be all zeros
     1100                            {
     1101                                codec_Data->currPacket = PACKET_TYPE_ERROR;
     1102                                result = MU_FAILURE;
     1103                            }
     1104                            break;
     1105
     1106                        case PUBREL_TYPE:
     1107                        case SUBSCRIBE_TYPE:
     1108                        case UNSUBSCRIBE_TYPE:
     1109                            if ((codec_Data->headerFlags & 0x0F) != 0x02) // only bit 1 must be set
     1110                            {
     1111                                codec_Data->currPacket = PACKET_TYPE_ERROR;
     1112                                result = MU_FAILURE;
     1113                            }
     1114                            break;
     1115
     1116                        case PUBLISH_TYPE:
     1117                        case CONTROL_PACKET_TYPE_INVALID:
     1118                        case PACKET_TYPE_ERROR:
     1119                        case UNKNOWN_TYPE:
     1120                            break;
     1121                    }
    10691122                }
    10701123                else
     
    10781131                    else if (codec_Data->currPacket == PINGRESP_TYPE)
    10791132                    {
    1080                         /* Codes_SRS_MQTT_CODEC_07_034: [Upon a constructing a complete MQTT packet mqtt_codec_bytesReceived shall call the ON_PACKET_COMPLETE_CALLBACK function.] */
    1081                         completePacketData(codec_Data);
     1133                        // PINGRESP must not have a payload
     1134                        if (((int8_t*)buffer)[index] == 0)
     1135                        {
     1136                            /* Codes_SRS_MQTT_CODEC_07_034: [Upon a constructing a complete MQTT packet mqtt_codec_bytesReceived shall call the ON_PACKET_COMPLETE_CALLBACK function.] */
     1137                            completePacketData(codec_Data);
     1138                        }
     1139                        else
     1140                        {
     1141                            codec_Data->currPacket = PACKET_TYPE_ERROR;
     1142                            result = MU_FAILURE;
     1143                        }
    10821144                    }
    10831145                }
Note: See TracChangeset for help on using the changeset viewer.