Select your cookie preferences

We use essential cookies and similar tools that are necessary to provide our site and services. We use performance cookies to collect anonymous statistics, so we can understand how customers use our site and make improvements. Essential cookies cannot be deactivated, but you can choose “Customize” or “Decline” to decline performance cookies.

If you agree, AWS and approved third parties will also use cookies to provide useful site features, remember your preferences, and display relevant content, including relevant advertising. To accept or decline all non-essential cookies, choose “Accept” or “Decline.” To make more detailed choices, choose “Customize.”

Updated Mar 2025

Transport Interface

Introduction

coreMQTT and coreHTTP has no dependency on any particular TCP/IP stack. Therefore, in order to use either the coreMQTT or coreHTTP library, you'll need to provide a Transport Interface structure. An instance of the Transport Interface contains function pointers and context data required to send and receive data on a single network connection. The FreeRTOS distribution includes example implementations of the Transport Interface which you can use in your applications.

Custom Implementations

Applications can provide their own implementation of the Transport Interface if the example implementations don't match the underlying network or TLS stack. An implementation has two parts. The first is the definition of a network context data structure that wraps an underlying data stream, such as a socket handle or a TLS context. The second is a pair of functions that can send and receive data on that network context - these two functions just wrap whichever network send and receive functions you are already using within functions that have the prototype expected by the transport interface structure. There is a worked example below.

The Transport Interface structure is defined as follows:

1/*
2 * The NetworkContext is an incomplete type. An implementation of this
3 * interface must define struct NetworkContext for the system's requirements.
4 * For example, a plain-text implemention of the NetworkContext type might
5 * include a socket, and a TLS implementation might add a TLS context. This
6 * context is passed into the network interface send() and recv() functions.
7 */
8struct NetworkContext;
9typedef struct NetworkContext NetworkContext_t;
10
11/*
12 * @brief Transport interface for receiving data on the network.
13 *
14 * @note It is RECOMMENDED that the transport receive implementation
15 * does NOT block when requested to read a single byte. A single byte
16 * read request can be made by the caller to check whether there is a
17 * new frame available on the network for reading.
18 * However, the receive implementation MAY block for a timeout period when
19 * it is requested to read more than 1 byte. This is because once the caller
20 * is aware that a new frame is available to read on the network, then
21 * the likelihood of reading more than one byte over the network becomes high.
22 *
23 * @param[in, out] pNetworkContext Implementation-defined network context.
24 * @param[in, out] pBuffer Buffer to receive the data into.
25 * @param[in] bytesToRecv Number of bytes requested from the network.
26 *
27 * @return The number of bytes received or a negative value to indicate
28 * error.
29 *
30 * @note If no data is available on the network to read and no error
31 * has occurred, zero MUST be the return value. A zero return value
32 * SHOULD represent that the read operation can be retried by calling
33 * the API function. Zero MUST NOT be returned if a network disconnection
34 * has occurred.
35 */
36typedef int32_t ( * TransportRecv_t )( NetworkContext_t * pNetworkContext,
37 void * pBuffer,
38 size_t bytesToRecv );
39
40/*
41 * @brief Transport interface for sending data over the network.
42 *
43 * @note It is RECOMMENDED that a non-fatal failure in transmitting bytes over
44 * the network, like a full transmit buffer of the underlying TCP stack, is
45 * treated as a retriable error operation by returning a zero return value.
46 *
47 * @param[in, out] pNetworkContext Implementation-defined network context.
48 * @param[in] pBuffer Buffer containing the bytes to send over the network.
49 * @param[in] bytesToSend Number of bytes to send over the network.
50 *
51 * @return The number of bytes sent or a negative value to indicate error.
52 *
53 * @note If no data is transmitted over the network and no network error
54 * has occurred, this MUST return zero as the return value.
55 * A zero return value SHOULD represent that the send operation can be retried
56 * by calling the API function. Zero MUST NOT be returned if a network
57 * disconnection has occurred.
58 */
59typedef int32_t ( * TransportSend_t )( NetworkContext_t * pNetworkContext,
60 const void * pBuffer,
61 size_t bytesToSend );
62
63typedef struct TransportInterface
64{
65 TransportRecv_t recv; /* Receive function (see above) */
66 TransportSend_t send; /* Send function (see above) */
67 NetworkContext_t * pNetworkContext; /* Network context (see above) */
68} TransportInterface_t;
69

Transport Interface Structure

Worked Example

This example describes how to create a transport interface for the FreeRTOS-Plus-TCP stack (this is for demonstration purposes only as the FreeRTOS source code download already contains a transport interface for FreeRTOS-Plus-TCP). For simplicity the example is using TCP without TLS or other form of encryption. Production IoT devices should always use encrypted connections and the FreeRTOS download includes transport interfaces that use FreeRTOS-Plus-TCP with TLS stacks.

Starting point

It is recommended to ensure your application is able to successfully send and receive from the network before creating a network transport interface - that way the transport interface is just wrapping send and receive functions that are already working.

Defining the NetworkContext structure

FreeRTOS-Plus-TCP sockets are stored in variables of type Socket_t. So the NetworkContext structure can be defined as:

1/* The network context just contains the FreeRTOS-Plus-TCP socket
2 * (Note: production systems should use TLS, not just the underlying
3 * socket, so could use the TLS context here instead of the socket) */
4struct NetworkContext
5{
6 Socket_t tcpSocket;
7};

Defining a NetworkContext structure that just contains a FreeRTOS-Plus-TCP socket.

Implementing the send and receive wrappers

Next, the FreeRTOS-Plus-TCP send and receive functions need to be wrapped by functions that have the prototype expected by the transport interface's send and receive functions. The example below also demonstrates how to obtain the socket used by the send and receive functions from the NetworkContext parameter:

1/* The prototypes of the following send and receive functions match that
2 expected by the transport interface's function pointers. These simple
3 implementations show how to use the network context structure defined
4 above. */
5
6int32_t transport_recv( NetworkContext_t * pNetworkContext,
7 void * pBuffer,
8 size_t bytesToRecv )
9{
10 int32_t socketStatus = 1;
11
12 /* The TCP socket may have a receive block time. If bytesToRecv is greater
13 * than 1, then a frame is likely already part way through reception and
14 * blocking to wait for the desired number of bytes to be available is the
15 * most efficient thing to do. If bytesToRecv is 1, then this may be a
16 * speculative call to read to find the start of a new frame, in which case
17 * blocking is not desirable as it could block an entire protocol agent
18 * task for the duration of the read block time and therefore negatively
19 * impact performance. So if bytesToRecv is 1, then don't call recv unless
20 * it is known that bytes are already available. */
21 if( bytesToRecv == 1 )
22 {
23 socketStatus = ( int32_t ) FreeRTOS_recvcount( pPlaintextTransportParams->tcpSocket );
24 }
25
26 if( socketStatus > 0 )
27 {
28 socketStatus = FreeRTOS_recv( pNetworkContext->tcpSocket, pBuffer, bytesToRecv, 0 );
29 }
30
31 return socketStatus;
32}
33
34int32_t transport_send( NetworkContext_t * pNetworkContext,
35 const void * pBuffer,
36 size_t bytesToSend )
37{
38 int32_t socketStatus;
39
40 socketStatus = FreeRTOS_send( pNetworkContext->tcpSocket, pBuffer, bytesToSend, 0 );
41
42 if( socketStatus == -pdFREERTOS_ERRNO_ENOSPC )
43 {
44 /* The TCP buffers could not accept any more bytes so zero bytes were sent.
45 * This is not necessarily an error that should cause a disconnect unless
46 * it persists so return 0 bytes received rather than an error. */
47 socketStatus = 0;
48 }
49
50 return socketStatus;
51}
52

Implementing the transport send and receive functions for FreeRTOS-Plus-TCP

Populating the TransportInterface_t structure

Finally, the code below shows how to populate the transport interface structure with the NetworkContext structure, and transport_send() and transport_recv() functions defined above:

1/* Populating the TransportInterface_t structure with the definitions above. */
2void init_transport_from_socket( Socket_t tcpSocket,
3 NetworkContext_t * pNetworkContext,
4 TransportInterface_t * pTransport )
5{
6 pNetworkContext->tcpSocket = tcpSocket;
7 pTransport->recv = transport_recv;
8 pTransport->send = transport_send;
9 pTransport->pNetworkContext = pNetworkContext;
10}
11

Defines the NetworkContext declared in transport_interface.h

Example Implementations

Examples for both plain-text and TLS communication are includedexternal_link. We strongly recommend that production applications use TLS for communication. This provides a Transport Interface which is both authenticated and encrypted, as demonstrated in the MQTT TLS demo.

The transport interface implementations included in the FreeRTOS download are split into two files - a wrapper C file specific to the TCP stack, and a supplemental C file specific to using a TLS stack with the selected TCP stack. For example, to use FreeRTOS-Plus-TCP with mbedTLS, build sockets_wrapper.c from the network_transport/freertos_plus_tcp directoryexternal_link in the source code distribution, then build using_mbedtls.c from the using_mbedtls subdirectory.