coreMQTT v2.1.1
MQTT 3.1.1 Client Library
Transport Interface

The transport interface definition.

Transport Interface Overview

The transport interface is a set of APIs that must be implemented using an external transport layer protocol. The transport interface is defined in transport_interface.h. This interface allows protocols like MQTT and HTTP to send and receive data over the transport layer. This interface does not handle connection and disconnection to the server of interest. The connection, disconnection, and other transport settings, like timeout and TLS setup, must be handled in the user application.

The functions that must be implemented are:

Each of the functions above take in an opaque context NetworkContext_t. The functions above and the context are also grouped together in the TransportInterface_t structure:

typedef struct TransportInterface
{
NetworkContext_t * pNetworkContext;
int32_t(* TransportRecv_t)(NetworkContext_t *pNetworkContext, void *pBuffer, size_t bytesToRecv)
Transport interface for receiving data on the network.
Definition: transport_interface.h:221
int32_t(* TransportSend_t)(NetworkContext_t *pNetworkContext, const void *pBuffer, size_t bytesToSend)
Transport interface for sending data over the network.
Definition: transport_interface.h:243
int32_t(* TransportWritev_t)(NetworkContext_t *pNetworkContext, TransportOutVector_t *pIoVec, size_t ioVecCount)
Transport interface function for "vectored" / scatter-gather based writes. This function is expected ...
Definition: transport_interface.h:291
struct NetworkContext NetworkContext_t
The NetworkContext is an incomplete type. An implementation of this interface must define struct Netw...
Definition: transport_interface.h:191
The transport layer interface.
Definition: transport_interface.h:302


Implementing the Transport Interface

The following steps give guidance on implementing the transport interface:

  1. Implementing NetworkContext_t

    struct NetworkContext;
    typedef struct NetworkContext NetworkContext_t;

    NetworkContext_t is the incomplete type struct NetworkContext. The implemented struct NetworkContext must contain all of the information that is needed to receive and send data with the TransportRecv_t and the TransportSend_t implementations.
    In the case of TLS over TCP, struct NetworkContext is typically implemented with the TCP socket context and a TLS context.

    Example code:
    struct NetworkContext
    {
    struct MyTCPSocketContext tcpSocketContext;
    struct MyTLSContext tlsContext;
    };

  2. Implementing TransportRecv_t

    typedef int32_t ( * TransportRecv_t )( NetworkContext_t * pNetworkContext,
    void * pBuffer,
    size_t bytesToRecv );

    This function is expected to populate a buffer, with bytes received from the transport, and return the number of bytes placed in the buffer. In the case of TLS over TCP, TransportRecv_t is typically implemented by calling the TLS layer function to receive data. In case of plaintext TCP without TLS, it is typically implemented by calling the TCP layer receive function. TransportRecv_t may be invoked multiple times by the protocol library, if fewer bytes than were requested to receive are returned.

    Example code:
    int32_t myNetworkRecvImplementation( NetworkContext_t * pNetworkContext,
    void * pBuffer,
    size_t bytesToRecv )
    {
    int32_t bytesReceived = 0;
    bool callTlsRecvFunc = true;
    // For a single byte read request, check if data is available on the network.
    if( bytesToRecv == 1 )
    {
    // If no data is available on the network, do not call TLSRecv
    // to avoid blocking for socket timeout.
    if( TLSRecvCount( pNetworkContext->tlsContext ) == 0 )
    {
    callTlsRecvFunc = false;
    }
    }
    if( callTlsRecvFunc == true )
    {
    bytesReceived = TLSRecv( pNetworkContext->tlsContext,
    pBuffer,
    bytesToRecv,
    MY_SOCKET_TIMEOUT );
    if( bytesReceived < 0 )
    {
    // If the error code represents a timeout, then the return
    // code should be translated to zero so that the caller
    // can retry the read operation.
    if( bytesReceived == MY_SOCKET_ERROR_TIMEOUT )
    {
    bytesReceived = 0;
    }
    }
    // Handle other cases.
    }
    return bytesReceived;
    }

  3. Implementing TransportSend_t

    typedef int32_t ( * TransportSend_t )( NetworkContext_t * pNetworkContext,
    const void * pBuffer,
    size_t bytesToSend );

    This function is expected to send the bytes, in the given buffer over the transport, and return the number of bytes sent. In the case of TLS over TCP, TransportSend_t is typically implemented by calling the TLS layer function to send data. In case of plaintext TCP without TLS, it is typically implemented by calling the TCP layer send function. TransportSend_t may be invoked multiple times by the protocol library, if fewer bytes than were requested to send are returned.

    Example code:
    int32_t myNetworkSendImplementation( NetworkContext_t * pNetworkContext,
    const void * pBuffer,
    size_t bytesToSend )
    {
    int32_t bytesSent = 0;
    bytesSent = TLSSend( pNetworkContext->tlsContext,
    pBuffer,
    bytesToSend,
    MY_SOCKET_TIMEOUT );
    // If underlying TCP buffer is full, set the return value to zero
    // so that caller can retry the send operation.
    if( bytesSent == MY_SOCKET_ERROR_BUFFER_FULL )
    {
    bytesSent = 0;
    }
    else if( bytesSent < 0 )
    {
    // Handle socket error.
    }
    // Handle other cases.
    return bytesSent;
    }