diff --git a/libraries/platform/iot_network.h b/libraries/platform/iot_network.h index 77eba836b6..651f0d0ac1 100644 --- a/libraries/platform/iot_network.h +++ b/libraries/platform/iot_network.h @@ -48,6 +48,19 @@ typedef enum IotNetworkError IOT_NETWORK_SYSTEM_ERROR /**< An error occurred when calling a system API. */ } IotNetworkError_t; +/** + * @ingroup platform_datatypes_enums + * @brief Disconnect reasons for [the network close callback](@ref platform_network_function_closecallback). + */ +typedef enum IotNetworkCloseReason +{ + IOT_NETWORK_NOT_CLOSED = 0, /**< Not closed, still open */ + IOT_NETWORK_SERVER_CLOSED, /**< Server closed connection. */ + IOT_NETWORK_TRANSPORT_FAILURE, /**< Transport failed. */ + IOT_NETWORK_CLIENT_CLOSED, /**< Client closed connection. */ + IOT_NETWORK_UNKNOWN_CLOSED /**< Unknown close reason. */ +} IotNetworkCloseReason_t; + /** * @page platform_network_functions Networking * @brief Functions of the network abstraction component. @@ -62,21 +75,25 @@ typedef enum IotNetworkError * Together, they represent a network stack. * - @functionname{platform_network_function_create} * - @functionname{platform_network_function_setreceivecallback} + * - @functionname{platform_network_function_setclosecallback} * - @functionname{platform_network_function_send} * - @functionname{platform_network_function_receive} * - @functionname{platform_network_function_close} * - @functionname{platform_network_function_destroy} * - @functionname{platform_network_function_receivecallback} + * - @functionname{platform_network_function_closecallback} */ /** * @functionpage{IotNetworkInterface_t::create,platform_network,create} * @functionpage{IotNetworkInterface_t::setReceiveCallback,platform_network,setreceivecallback} + * @functionpage{IotNetworkInterface_t::setCloseCallback,platform_network,setclosecallback} * @functionpage{IotNetworkInterface_t::send,platform_network,send} * @functionpage{IotNetworkInterface_t::receive,platform_network,receive} * @functionpage{IotNetworkInterface_t::close,platform_network,close} * @functionpage{IotNetworkInterface_t::destroy,platform_network,destroy} * @functionpage{IotNetworkReceiveCallback_t,platform_network,receivecallback} + * @functionpage{IotNetworkReceiveCallback_t,platform_network,closecallback} */ /** @@ -94,6 +111,178 @@ typedef void ( * IotNetworkReceiveCallback_t )( IotNetworkConnection_t pConnecti void * pContext ); /* @[declare_platform_network_receivecallback] */ +/** + * @brief Provide an asynchronous notification of network closing + * + * A function with this signature may be set with @ref platform_network_function_setclosecallback + * to be invoked when the network connection is closed. + * + * @param[in] pConnection The connection that was closed, defined by + * the network stack. + * @param[in] reason The reason the connection was closed + * @param[in] pContext The third argument passed to @ref platform_network_function_setclosecallback. + */ +/* @[declare_platform_network_closecallback] */ +typedef void ( * IotNetworkCloseCallback_t )( IotNetworkConnection_t pConnection, + IotNetworkCloseReason_t reason, + void * pContext ); +/* @[declare_platform_network_closecallback] */ + +/** + * @brief Create a new network connection. + * + * This function allocates resources and establishes a new network connection. + * @param[in] pServerInfo Represents information needed to set up the + * new connection, defined by the network stack. + * @param[in] pCredentialInfo Represents information needed to secure the + * new connection, defined by the network stack. + * @param[out] pConnection Set to represent a new connection, defined by the + * network stack. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + */ +/* @[declare_platform_network_create] */ +typedef IotNetworkError_t ( * IotNetworkCreate_t )( IotNetworkServerInfo_t pServerInfo, + IotNetworkCredentials_t pCredentialInfo, + IotNetworkConnection_t * pConnection ); +/* @[declare_platform_network_create] */ + +/** + * @brief Register an @ref platform_network_function_receivecallback. + * + * Sets an @ref platform_network_function_receivecallback to be called + * asynchronously when data arrives on the network. The network stack + * should invoke this function "as if" it were the thread routine of a + * detached thread. + * + * Each network connection may only have one receive callback at any time. + * @ref platform_network_function_close is expected to remove any active + * receive callbacks. + * + * @param[in] pConnection The connection to associate with the receive callback. + * @param[in] receiveCallback The function to invoke for incoming network data. + * @param[in] pContext A value to pass as the first parameter to the receive callback. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + * + * @see platform_network_function_receivecallback + */ +/* @[declare_platform_network_setreceivecallback] */ +typedef IotNetworkError_t ( * IotNetworkSetReceiveCallback_t )( IotNetworkConnection_t pConnection, + IotNetworkReceiveCallback_t receiveCallback, + void * pContext ); +/* @[declare_platform_network_setreceivecallback] */ + +/** + * @brief Register an @ref platform_network_function_closecallback. + * + * Sets an @ref platform_network_function_closecallback to be called + * asynchronously when the network connection closes. The network stack + * should invoke this function "as if" it were the thread routine of a + * detached thread. + * + * Each network connection may only have one close callback at any time. + * @ref platform_network_function_close is expected to remove any active + * close callbacks. + * + * @param[in] pConnection The connection to associate with the close callback. + * @param[in] receiveCallback The function to invoke for incoming network close events. + * @param[in] pContext A value to pass as the first parameter to the close callback. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + * + * @see platform_network_function_closecallback + */ +/* @[declare_platform_network_setclosecallback] */ +typedef IotNetworkError_t ( * IotNetworkSetCloseCallback_t )( IotNetworkConnection_t pConnection, + IotNetworkCloseCallback_t closeCallback, + void * pContext ); +/* @[declare_platform_network_setclosecallback] */ + +/** + * @brief Send data over a return connection. + * + * Attempts to transmit `messageLength` bytes of `pMessage` across the + * connection represented by `pConnection`. Returns the number of bytes + * actually sent, `0` on failure. + * + * @param[in] pConnection The connection used to send data, defined by the + * network stack. + * @param[in] pMessage The message to send. + * @param[in] messageLength The length of `pMessage`. + * + * @return The number of bytes successfully sent, `0` on failure. + */ +/* @[declare_platform_network_send] */ +typedef size_t ( * IotNetworkSend_t )( IotNetworkConnection_t pConnection, + const uint8_t * pMessage, + size_t messageLength ); +/* @[declare_platform_network_send] */ + +/** + * @brief Block and wait for incoming network data. + * + * Wait for a message of size `bytesRequested` to arrive on the network and + * place it in `pBuffer`. + * + * @param[in] pConnection The connection to wait on, defined by the network + * stack. + * @param[out] pBuffer Where to place the incoming network data. This buffer + * must be at least `bytesRequested` in size. + * @param[in] bytesRequested How many bytes to wait for. `pBuffer` must be at + * least this size. + * + * @return The number of bytes successfully received. This should be + * `bytesRequested` when successful. Any other value may indicate an error. + */ +/* @[declare_platform_network_receive] */ +typedef size_t ( * IotNetworkReceive_t )( IotNetworkConnection_t pConnection, + uint8_t * pBuffer, + size_t bytesRequested ); +/* @[declare_platform_network_receive] */ + +/** + * @brief Close a network connection. + * + * This function closes the connection, but does not release the resources + * used by the connection. This allows calls to other networking functions + * to return an error and handle a closed connection without the risk of + * crashing. Once it can be guaranteed that `pConnection` will no longer be + * used, the connection can be destroyed with @ref platform_network_function_destroy. + * + * In addition to closing the connection, this function should also remove + * any active [receive callback](@ref platform_network_function_receivecallback). + * + * @param[in] pConnection The network connection to close, defined by the + * network stack. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + * + * @note It must be safe to call this function on an already-closed connection. + */ +/* @[declare_platform_network_close] */ +typedef IotNetworkError_t ( * IotNetworkClose_t )( IotNetworkConnection_t pConnection ); +/* @[declare_platform_network_close] */ + +/** + * @brief Free resources used by a network connection. + * + * This function releases the resources of a closed connection. It should be + * called after @ref platform_network_function_close. + * + * @param[in] pConnection The network connection to destroy, defined by + * the network stack. + * + * @return Any #IotNetworkError_t, as defined by the network stack. + * + * @attention No function should be called on the network connection after + * calling this function. This function must be safe to call from a + * [receive callback](@ref platform_network_function_receivecallback). + */ +/* @[declare_platform_network_destroy] */ +typedef IotNetworkError_t ( * IotNetworkDestroy_t )( IotNetworkConnection_t pConnection ); +/* @[declare_platform_network_destroy] */ + /** * @ingroup platform_datatypes_paramstructs * @brief Represents the functions of a network stack. @@ -103,134 +292,13 @@ typedef void ( * IotNetworkReceiveCallback_t )( IotNetworkConnection_t pConnecti */ typedef struct IotNetworkInterface { - /** - * @brief Create a new network connection. - * - * This function allocates resources and establishes a new network connection. - * @param[in] pServerInfo Represents information needed to set up the - * new connection, defined by the network stack. - * @param[in] pCredentialInfo Represents information needed to secure the - * new connection, defined by the network stack. - * @param[out] pConnection Set to represent a new connection, defined by the - * network stack. - * - * @return Any #IotNetworkError_t, as defined by the network stack. - */ - /* @[declare_platform_network_create] */ - IotNetworkError_t ( * create )( IotNetworkServerInfo_t pServerInfo, - IotNetworkCredentials_t pCredentialInfo, - IotNetworkConnection_t * pConnection ); - /* @[declare_platform_network_create] */ - - /** - * @brief Register an @ref platform_network_function_receivecallback. - * - * Sets an @ref platform_network_function_receivecallback to be called - * asynchronously when data arrives on the network. The network stack - * should invoke this function "as if" it were the thread routine of a - * detached thread. - * - * Each network connection may only have one receive callback at any time. - * @ref platform_network_function_close is expected to remove any active - * receive callbacks. - * - * @param[in] pConnection The connection to associate with the receive callback. - * @param[in] receiveCallback The function to invoke for incoming network data. - * @param[in] pContext A value to pass as the first parameter to the receive callback. - * - * @return Any #IotNetworkError_t, as defined by the network stack. - * - * @see platform_network_function_receivecallback - */ - /* @[declare_platform_network_setreceivecallback] */ - IotNetworkError_t ( * setReceiveCallback )( IotNetworkConnection_t pConnection, - IotNetworkReceiveCallback_t receiveCallback, - void * pContext ); - /* @[declare_platform_network_setreceivecallback] */ - - /** - * @brief Send data over a return connection. - * - * Attempts to transmit `messageLength` bytes of `pMessage` across the - * connection represented by `pConnection`. Returns the number of bytes - * actually sent, `0` on failure. - * - * @param[in] pConnection The connection used to send data, defined by the - * network stack. - * @param[in] pMessage The message to send. - * @param[in] messageLength The length of `pMessage`. - * - * @return The number of bytes successfully sent, `0` on failure. - */ - /* @[declare_platform_network_send] */ - size_t ( * send )( IotNetworkConnection_t pConnection, - const uint8_t * pMessage, - size_t messageLength ); - /* @[declare_platform_network_send] */ - - /** - * @brief Block and wait for incoming network data. - * - * Wait for a message of size `bytesRequested` to arrive on the network and - * place it in `pBuffer`. - * - * @param[in] pConnection The connection to wait on, defined by the network - * stack. - * @param[out] pBuffer Where to place the incoming network data. This buffer - * must be at least `bytesRequested` in size. - * @param[in] bytesRequested How many bytes to wait for. `pBuffer` must be at - * least this size. - * - * @return The number of bytes successfully received. This should be - * `bytesRequested` when successful. Any other value may indicate an error. - */ - /* @[declare_platform_network_receive] */ - size_t ( * receive )( IotNetworkConnection_t pConnection, - uint8_t * pBuffer, - size_t bytesRequested ); - /* @[declare_platform_network_receive] */ - - /** - * @brief Close a network connection. - * - * This function closes the connection, but does not release the resources - * used by the connection. This allows calls to other networking functions - * to return an error and handle a closed connection without the risk of - * crashing. Once it can be guaranteed that `pConnection` will no longer be - * used, the connection can be destroyed with @ref platform_network_function_destroy. - * - * In addition to closing the connection, this function should also remove - * any active [receive callback](@ref platform_network_function_receivecallback). - * - * @param[in] pConnection The network connection to close, defined by the - * network stack. - * - * @return Any #IotNetworkError_t, as defined by the network stack. - * - * @note It must be safe to call this function on an already-closed connection. - */ - /* @[declare_platform_network_close] */ - IotNetworkError_t ( * close )( IotNetworkConnection_t pConnection ); - /* @[declare_platform_network_close] */ - - /** - * @brief Free resources used by a network connection. - * - * This function releases the resources of a closed connection. It should be - * called after @ref platform_network_function_close. - * - * @param[in] pConnection The network connection to destroy, defined by - * the network stack. - * - * @return Any #IotNetworkError_t, as defined by the network stack. - * - * @attention No function should be called on the network connection after - * calling this function. This function must be safe to call from a - * [receive callback](@ref platform_network_function_receivecallback). - */ - /* @[declare_platform_network_destroy] */ - IotNetworkError_t ( * destroy )( IotNetworkConnection_t pConnection ); - /* @[declare_platform_network_destroy] */ + IotNetworkCreate_t create; /**< @brief create network connection. */ + IotNetworkSetReceiveCallback_t setReceiveCallback; /**< @brief set receive callback. */ + IotNetworkSetCloseCallback_t setCloseCallback; /**< @brief set close callback. */ + IotNetworkSend_t send; /**< @brief send data. */ + IotNetworkReceive_t receive; /**< @brief block and wait for receive data. */ + IotNetworkClose_t close; /**< @brief close network connection. */ + IotNetworkDestroy_t destroy; /**< @brief destroy network connection. */ } IotNetworkInterface_t; /** diff --git a/ports/common/include/iot_network_mbedtls.h b/ports/common/include/iot_network_mbedtls.h index 9475a086fa..3cb5bc4441 100644 --- a/ports/common/include/iot_network_mbedtls.h +++ b/ports/common/include/iot_network_mbedtls.h @@ -82,18 +82,18 @@ */ const IotNetworkInterface_t * IotNetworkMbedtls_GetInterface( void ); - /** - * @brief One-time initialization function for this network stack. - * - * This function performs internal setup of this network stack. It must be - * called once (and only once) before calling any other function in this network - * stack. Calling this function more than once without first calling - * #IotNetworkMbedtls_Cleanup may result in a crash. - * - * @return #IOT_NETWORK_SUCCESS or #IOT_NETWORK_FAILURE. - * - * @warning No thread-safety guarantees are provided for this function. - */ +/** + * @brief One-time initialization function for this network stack. + * + * This function performs internal setup of this network stack. It must be + * called once (and only once) before calling any other function in this network + * stack. Calling this function more than once without first calling + * #IotNetworkMbedtls_Cleanup may result in a crash. + * + * @return #IOT_NETWORK_SUCCESS or #IOT_NETWORK_FAILURE. + * + * @warning No thread-safety guarantees are provided for this function. + */ IotNetworkError_t IotNetworkMbedtls_Init( void ); /** @@ -124,6 +124,14 @@ IotNetworkError_t IotNetworkMbedtls_SetReceiveCallback( IotNetworkConnection_t p IotNetworkReceiveCallback_t receiveCallback, void * pContext ); +/** + * @brief An implementation of #IotNetworkInterface_t::setCloseCallback for + * mbed TLS. + */ +IotNetworkError_t IotNetworkMbedtls_SetCloseCallback( IotNetworkConnection_t pConnection, + IotNetworkCloseCallback_t closeCallback, + void * pContext ); + /** * @brief An implementation of #IotNetworkInterface_t::send for mbed TLS. */ diff --git a/ports/common/include/iot_network_openssl.h b/ports/common/include/iot_network_openssl.h index a973318635..357595bca7 100644 --- a/ports/common/include/iot_network_openssl.h +++ b/ports/common/include/iot_network_openssl.h @@ -128,6 +128,14 @@ IotNetworkError_t IotNetworkOpenssl_SetReceiveCallback( IotNetworkConnection_t p IotNetworkReceiveCallback_t receiveCallback, void * pContext ); +/** + * @brief An implementation of #IotNetworkInterface_t::setCloseCallback for + * systems with OpenSSL. + */ +IotNetworkError_t IotNetworkOpenssl_SetCloseCallback( IotNetworkConnection_t pConnection, + IotNetworkCloseCallback_t closeCallback, + void * pContext ); + /** * @brief An implementation of #IotNetworkInterface_t::send for systems * with OpenSSL. diff --git a/ports/common/src/iot_network_mbedtls.c b/ports/common/src/iot_network_mbedtls.c index 82d522f9b3..e8371ac2f7 100644 --- a/ports/common/src/iot_network_mbedtls.c +++ b/ports/common/src/iot_network_mbedtls.c @@ -156,6 +156,8 @@ typedef struct _networkConnection IotNetworkReceiveCallback_t receiveCallback; /**< @brief Network receive callback, if any. */ void * pReceiveContext; /**< @brief The context for the receive callback. */ + IotNetworkCloseCallback_t closeCallback; /**< @brief Network close callback, if any. */ + void * pCloseContext; /**< @brief The context for the close callback. */ IotMutex_t callbackMutex; /**< @brief Synchronizes the receive callback with calls to destroy. */ IotSemaphore_t destroyNotification; /**< @brief Notifies the receive callback that the connection was destroyed. */ @@ -410,6 +412,17 @@ static void _receiveThread( void * pArgument ) } } + /** + * If a close callback has been defined, invoke it now; since we + * don't know what caused the close, use "unknown" as the reason. + */ + if( pConnection->closeCallback != NULL ) + { + pConnection->closeCallback( pConnection, + IOT_NETWORK_UNKNOWN_CLOSED, + pConnection->pCloseContext ); + } + /* Wait for the call to network destroy, then destroy the connection. */ IotSemaphore_Wait( &( pConnection->destroyNotification ) ); _destroyConnection( pConnection ); @@ -930,7 +943,12 @@ IotNetworkError_t IotNetworkMbedtls_SetReceiveCallback( IotNetworkConnection_t p IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_SYSTEM_ERROR ); } - /* Set the callback and parameter. */ + /* Set the callback (must be non-NULL) and parameter. */ + if( receiveCallback == NULL ) + { + IOT_SET_AND_GOTO_CLEANUP( IOT_NETWORK_BAD_PARAMETER ); + } + pConnection->receiveCallback = receiveCallback; pConnection->pReceiveContext = pContext; @@ -978,6 +996,26 @@ IotNetworkError_t IotNetworkMbedtls_SetReceiveCallback( IotNetworkConnection_t p /*-----------------------------------------------------------*/ +IotNetworkError_t IotNetworkMbedtls_SetCloseCallback( IotNetworkConnection_t pConnection, + IotNetworkCloseCallback_t closeCallback, + void * pContext ) +{ + IotNetworkError_t status = IOT_NETWORK_BAD_PARAMETER; + + if( closeCallback != NULL ) + { + /* Set the callback and parameter. */ + pConnection->closeCallback = closeCallback; + pConnection->pCloseContext = pContext; + + status = IOT_NETWORK_SUCCESS; + } + + return status; +} + +/*-----------------------------------------------------------*/ + size_t IotNetworkMbedtls_Send( IotNetworkConnection_t pConnection, const uint8_t * pMessage, size_t messageLength ) diff --git a/ports/common/src/iot_network_metrics.c b/ports/common/src/iot_network_metrics.c index 8bd0b6a1e8..304ec8008b 100644 --- a/ports/common/src/iot_network_metrics.c +++ b/ports/common/src/iot_network_metrics.c @@ -126,71 +126,73 @@ static IotMutex_t _connectionListMutex; /* OpenSSL networking include. */ #include "iot_network_openssl.h" - /** - * @brief Pointer to the metrics-wrapped network creation function. - */ +/** + * @brief Pointer to the metrics-wrapped network creation function. + */ static IotNetworkError_t ( * _networkCreate )( IotNetworkServerInfo_t, IotNetworkCredentials_t, IotNetworkConnection_t * ) = IotNetworkOpenssl_Create; - /** - * @brief Pointer to the metrics-wrapped network close function. - */ +/** + * @brief Pointer to the metrics-wrapped network close function. + */ static IotNetworkError_t ( * _networkClose )( IotNetworkConnection_t ) = IotNetworkOpenssl_Close; - /** - * @brief Pointer to the function that retrieves the socket for a connection. - */ +/** + * @brief Pointer to the function that retrieves the socket for a connection. + */ static int ( * _getSocket )( IotNetworkConnection_t ) = IotNetworkOpenssl_GetSocket; - /** - * @brief An #IotNetworkInterface_t that wraps network abstraction functions with - * metrics. - */ +/** + * @brief An #IotNetworkInterface_t that wraps network abstraction functions with + * metrics. + */ static const IotNetworkInterface_t _networkMetrics = { .create = _metricsNetworkCreate, .setReceiveCallback = IotNetworkOpenssl_SetReceiveCallback, + .setCloseCallback = IotNetworkOpenssl_SetCloseCallback, .send = IotNetworkOpenssl_Send, .receive = IotNetworkOpenssl_Receive, .close = _metricsNetworkClose, .destroy = IotNetworkOpenssl_Destroy }; -#else +#else /* if IOT_NETWORK_USE_OPENSSL == 1 */ /* mbed TLS networking include. */ #include "iot_network_mbedtls.h" - /** - * @brief Pointer to the metrics-wrapped network creation function. - */ +/** + * @brief Pointer to the metrics-wrapped network creation function. + */ static IotNetworkError_t ( * _networkCreate )( IotNetworkServerInfo_t, IotNetworkCredentials_t, IotNetworkConnection_t * ) = IotNetworkMbedtls_Create; - /** - * @brief Pointer to the metrics-wrapped network close function. - */ +/** + * @brief Pointer to the metrics-wrapped network close function. + */ static IotNetworkError_t ( * _networkClose )( IotNetworkConnection_t ) = IotNetworkMbedtls_Close; - /** - * @brief Pointer to the function that retrieves the socket for a connection. - */ +/** + * @brief Pointer to the function that retrieves the socket for a connection. + */ static int ( * _getSocket )( IotNetworkConnection_t ) = IotNetworkMbedtls_GetSocket; - /** - * @brief An #IotNetworkInterface_t that wraps network abstraction functions with - * metrics. - */ +/** + * @brief An #IotNetworkInterface_t that wraps network abstraction functions with + * metrics. + */ static const IotNetworkInterface_t _networkMetrics = { .create = _metricsNetworkCreate, .setReceiveCallback = IotNetworkMbedtls_SetReceiveCallback, + .setCloseCallback = IotNetworkMbedtls_SetCloseCallback, .send = IotNetworkMbedtls_Send, .receive = IotNetworkMbedtls_Receive, .close = _metricsNetworkClose, .destroy = IotNetworkMbedtls_Destroy }; -#endif +#endif /* if IOT_NETWORK_USE_OPENSSL == 1 */ /*-----------------------------------------------------------*/ diff --git a/ports/common/src/iot_network_openssl.c b/ports/common/src/iot_network_openssl.c index ba69d01b54..fa1c27a821 100644 --- a/ports/common/src/iot_network_openssl.c +++ b/ports/common/src/iot_network_openssl.c @@ -111,6 +111,8 @@ typedef struct _networkConnection IotNetworkReceiveCallback_t receiveCallback; /**< @brief Network receive callback, if any. */ void * pReceiveContext; /**< @brief The context for the receive callback. */ + IotNetworkCloseCallback_t closeCallback; /**< @brief Network close callback, if any. */ + void * pCloseContext; /**< @brief The context for the close callback. */ } _networkConnection_t; /*-----------------------------------------------------------*/ @@ -122,6 +124,7 @@ static const IotNetworkInterface_t _networkOpenssl = { .create = IotNetworkOpenssl_Create, .setReceiveCallback = IotNetworkOpenssl_SetReceiveCallback, + .setCloseCallback = IotNetworkOpenssl_SetCloseCallback, .send = IotNetworkOpenssl_Send, .receive = IotNetworkOpenssl_Receive, .close = IotNetworkOpenssl_Close, @@ -181,6 +184,17 @@ static void * _networkReceiveThread( void * pArgument ) pConnection->pReceiveContext ); } + /** + * If a close callback has been defined, invoke it now; since we + * don't know what caused the close, use "unknown" as the reason. + */ + if( pConnection->closeCallback != NULL ) + { + pConnection->closeCallback( pConnection, + IOT_NETWORK_UNKNOWN_CLOSED, + pConnection->pCloseContext ); + } + IotLogDebug( "Network receive thread for socket %d terminating.", pConnection->socket ); @@ -752,28 +766,53 @@ IotNetworkError_t IotNetworkOpenssl_SetReceiveCallback( IotNetworkConnection_t p IotNetworkReceiveCallback_t receiveCallback, void * pContext ) { + IotNetworkError_t status = IOT_NETWORK_BAD_PARAMETER; int posixError = 0; - IotNetworkError_t status = IOT_NETWORK_SUCCESS; - /* Set the callback and parameter. */ - pConnection->receiveCallback = receiveCallback; - pConnection->pReceiveContext = pContext; + /* The receive callback must be non-NULL) */ + if( receiveCallback != NULL ) + { + /* Set the callback and parameter. */ + pConnection->receiveCallback = receiveCallback; + pConnection->pReceiveContext = pContext; - posixError = pthread_create( &pConnection->receiveThread, - NULL, - _networkReceiveThread, - pConnection ); + posixError = pthread_create( &pConnection->receiveThread, + NULL, + _networkReceiveThread, + pConnection ); - if( posixError != 0 ) - { - IotLogError( "Failed to create socket %d network receive thread. errno=%d.", - pConnection->socket, - posixError ); - status = IOT_NETWORK_SYSTEM_ERROR; + if( posixError != 0 ) + { + IotLogError( "Failed to create socket %d network receive thread. errno=%d.", + pConnection->socket, + posixError ); + status = IOT_NETWORK_SYSTEM_ERROR; + } + else + { + pConnection->receiveThreadCreated = true; + status = IOT_NETWORK_SUCCESS; + } } - else + + return status; +} + +/*-----------------------------------------------------------*/ + +IotNetworkError_t IotNetworkOpenssl_SetCloseCallback( IotNetworkConnection_t pConnection, + IotNetworkCloseCallback_t closeCallback, + void * pContext ) +{ + IotNetworkError_t status = IOT_NETWORK_BAD_PARAMETER; + + if( closeCallback != NULL ) { - pConnection->receiveThreadCreated = true; + /* Set the callback and parameter. */ + pConnection->closeCallback = closeCallback; + pConnection->pCloseContext = pContext; + + status = IOT_NETWORK_SUCCESS; } return status;