RaspberrPi project source code
Guo Wenxue
2024-04-11 5b381c80976c76bb7e0d779f1ff878416c93db78
commit | author | age
d6b4a7 1 /*
G 2  * coreMQTT v2.1.1
3  * Copyright (C) 2022 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * SPDX-License-Identifier: MIT
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy of
8  * this software and associated documentation files (the "Software"), to deal in
9  * the Software without restriction, including without limitation the rights to
10  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
11  * the Software, and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24
25 /**
26  * @file transport_interface.h
27  * @brief Transport interface definitions to send and receive data over the
28  * network.
29  */
30 #ifndef TRANSPORT_INTERFACE_H_
31 #define TRANSPORT_INTERFACE_H_
32
33 #include <stdint.h>
34 #include <stddef.h>
35
36 /* *INDENT-OFF* */
37 #ifdef __cplusplus
38     extern "C" {
39 #endif
40 /* *INDENT-ON* */
41
42 /**
43  * @transportpage
44  * @brief The transport interface definition.
45  *
46  * @transportsectionoverview
47  *
48  * The transport interface is a set of APIs that must be implemented using an
49  * external transport layer protocol. The transport interface is defined in
50  * @ref transport_interface.h. This interface allows protocols like MQTT and
51  * HTTP to send and receive data over the transport layer. This
52  * interface does not handle connection and disconnection to the server of
53  * interest. The connection, disconnection, and other transport settings, like
54  * timeout and TLS setup, must be handled in the user application.
55  * <br>
56  *
57  * The functions that must be implemented are:<br>
58  * - [Transport Receive](@ref TransportRecv_t)
59  * - [Transport Send](@ref TransportSend_t)
60  *
61  * Each of the functions above take in an opaque context @ref NetworkContext_t.
62  * The functions above and the context are also grouped together in the
63  * @ref TransportInterface_t structure:<br><br>
64  * @snippet this define_transportinterface
65  * <br>
66  *
67  * @transportsectionimplementation
68  *
69  * The following steps give guidance on implementing the transport interface:
70  *
71  * -# Implementing @ref NetworkContext_t<br><br>
72  * @snippet this define_networkcontext
73  * <br>
74  * @ref NetworkContext_t is the incomplete type <b>struct NetworkContext</b>.
75  * The implemented struct NetworkContext must contain all of the information
76  * that is needed to receive and send data with the @ref TransportRecv_t
77  * and the @ref TransportSend_t implementations.<br>
78  * In the case of TLS over TCP, struct NetworkContext is typically implemented
79  * with the TCP socket context and a TLS context.<br><br>
80  * <b>Example code:</b>
81  * @code{c}
82  * struct NetworkContext
83  * {
84  *     struct MyTCPSocketContext tcpSocketContext;
85  *     struct MyTLSContext tlsContext;
86  * };
87  * @endcode
88  * <br>
89  * -# Implementing @ref TransportRecv_t<br><br>
90  * @snippet this define_transportrecv
91  * <br>
92  * This function is expected to populate a buffer, with bytes received from the
93  * transport, and return the number of bytes placed in the buffer.
94  * In the case of TLS over TCP, @ref TransportRecv_t is typically implemented by
95  * calling the TLS layer function to receive data. In case of plaintext TCP
96  * without TLS, it is typically implemented by calling the TCP layer receive
97  * function. @ref TransportRecv_t may be invoked multiple times by the protocol
98  * library, if fewer bytes than were requested to receive are returned.
99  * <br><br>
100  * <b>Example code:</b>
101  * @code{c}
102  * int32_t myNetworkRecvImplementation( NetworkContext_t * pNetworkContext,
103  *                                      void * pBuffer,
104  *                                      size_t bytesToRecv )
105  * {
106  *     int32_t bytesReceived = 0;
107  *     bool callTlsRecvFunc = true;
108  *
109  *     // For a single byte read request, check if data is available on the network.
110  *     if( bytesToRecv == 1 )
111  *     {
112  *        // If no data is available on the network, do not call TLSRecv
113  *        // to avoid blocking for socket timeout.
114  *        if( TLSRecvCount( pNetworkContext->tlsContext ) == 0 )
115  *        {
116  *            callTlsRecvFunc = false;
117  *        }
118  *     }
119  *
120  *     if( callTlsRecvFunc == true )
121  *     {
122  *        bytesReceived = TLSRecv( pNetworkContext->tlsContext,
123  *                                 pBuffer,
124  *                                 bytesToRecv,
125  *                                 MY_SOCKET_TIMEOUT );
126  *        if( bytesReceived < 0 )
127  *        {
128  *           // If the error code represents a timeout, then the return
129  *           // code should be translated to zero so that the caller
130  *           // can retry the read operation.
131  *           if( bytesReceived == MY_SOCKET_ERROR_TIMEOUT )
132  *           {
133  *              bytesReceived = 0;
134  *           }
135  *        }
136  *        // Handle other cases.
137  *     }
138  *     return bytesReceived;
139  * }
140  * @endcode
141  * <br>
142  * -# Implementing @ref TransportSend_t<br><br>
143  * @snippet this define_transportsend
144  * <br>
145  * This function is expected to send the bytes, in the given buffer over the
146  * transport, and return the number of bytes sent.
147  * In the case of TLS over TCP, @ref TransportSend_t is typically implemented by
148  * calling the TLS layer function to send data. In case of plaintext TCP
149  * without TLS, it is typically implemented by calling the TCP layer send
150  * function. @ref TransportSend_t may be invoked multiple times by the protocol
151  * library, if fewer bytes than were requested to send are returned.
152  * <br><br>
153  * <b>Example code:</b>
154  * @code{c}
155  * int32_t myNetworkSendImplementation( NetworkContext_t * pNetworkContext,
156  *                                      const void * pBuffer,
157  *                                      size_t bytesToSend )
158  * {
159  *     int32_t bytesSent = 0;
160  *     bytesSent = TLSSend( pNetworkContext->tlsContext,
161  *                          pBuffer,
162  *                          bytesToSend,
163  *                          MY_SOCKET_TIMEOUT );
164  *
165  *      // If underlying TCP buffer is full, set the return value to zero
166  *      // so that caller can retry the send operation.
167  *     if( bytesSent == MY_SOCKET_ERROR_BUFFER_FULL )
168  *     {
169  *          bytesSent = 0;
170  *     }
171  *     else if( bytesSent < 0 )
172  *     {
173  *         // Handle socket error.
174  *     }
175  *     // Handle other cases.
176  *
177  *     return bytesSent;
178  * }
179  * @endcode
180  */
181
182 /**
183  * @transportstruct
184  * @typedef NetworkContext_t
185  * @brief The NetworkContext is an incomplete type. An implementation of this
186  * interface must define struct NetworkContext for the system requirements.
187  * This context is passed into the network interface functions.
188  */
189 /* @[define_networkcontext] */
190 struct NetworkContext;
191 typedef struct NetworkContext NetworkContext_t;
192 /* @[define_networkcontext] */
193
194 /**
195  * @transportcallback
196  * @brief Transport interface for receiving data on the network.
197  *
198  * @note It is RECOMMENDED that the transport receive implementation
199  * does NOT block when requested to read a single byte. A single byte
200  * read request can be made by the caller to check whether there is a
201  * new frame available on the network for reading.
202  * However, the receive implementation MAY block for a timeout period when
203  * it is requested to read more than 1 byte. This is because once the caller
204  * is aware that a new frame is available to read on the network, then
205  * the likelihood of reading more than one byte over the network becomes high.
206  *
207  * @param[in] pNetworkContext Implementation-defined network context.
208  * @param[in] pBuffer Buffer to receive the data into.
209  * @param[in] bytesToRecv Number of bytes requested from the network.
210  *
211  * @return The number of bytes received or a negative value to indicate
212  * error.
213  *
214  * @note If no data is available on the network to read and no error
215  * has occurred, zero MUST be the return value. A zero return value
216  * SHOULD represent that the read operation can be retried by calling
217  * the API function. Zero MUST NOT be returned if a network disconnection
218  * has occurred.
219  */
220 /* @[define_transportrecv] */
221 typedef int32_t ( * TransportRecv_t )( NetworkContext_t * pNetworkContext,
222                                        void * pBuffer,
223                                        size_t bytesToRecv );
224 /* @[define_transportrecv] */
225
226 /**
227  * @transportcallback
228  * @brief Transport interface for sending data over the network.
229  *
230  * @param[in] pNetworkContext Implementation-defined network context.
231  * @param[in] pBuffer Buffer containing the bytes to send over the network stack.
232  * @param[in] bytesToSend Number of bytes to send over the network.
233  *
234  * @return The number of bytes sent or a negative value to indicate error.
235  *
236  * @note If no data is transmitted over the network due to a full TX buffer and
237  * no network error has occurred, this MUST return zero as the return value.
238  * A zero return value SHOULD represent that the send operation can be retried
239  * by calling the API function. Zero MUST NOT be returned if a network disconnection
240  * has occurred.
241  */
242 /* @[define_transportsend] */
243 typedef int32_t ( * TransportSend_t )( NetworkContext_t * pNetworkContext,
244                                        const void * pBuffer,
245                                        size_t bytesToSend );
246 /* @[define_transportsend] */
247
248 /**
249  * @brief Transport vector structure for sending multiple messages.
250  */
251 typedef struct TransportOutVector
252 {
253     /**
254      * @brief Base address of data.
255      */
256     const void * iov_base;
257
258     /**
259      * @brief Length of data in buffer.
260      */
261     size_t iov_len;
262 } TransportOutVector_t;
263
264 /**
265  * @transportcallback
266  * @brief Transport interface function for "vectored" / scatter-gather based
267  * writes. This function is expected to iterate over the list of vectors pIoVec
268  * having ioVecCount entries containing portions of one MQTT message at a maximum.
269  * If the proper functionality is available, then the data in the list should be
270  * copied to the underlying TCP buffer before flushing the buffer. Implementing it
271  * in this fashion  will lead to sending of fewer TCP packets for all the values
272  * in the list.
273  *
274  * @note If the proper write functionality is not present for a given device/IP-stack,
275  * then there is no strict requirement to implement write. Only the send and recv
276  * interfaces must be defined for the application to work properly.
277  *
278  * @param[in] pNetworkContext Implementation-defined network context.
279  * @param[in] pIoVec An array of TransportIoVector_t structs.
280  * @param[in] ioVecCount Number of TransportIoVector_t in pIoVec.
281  *
282  * @return The number of bytes written or a negative value to indicate error.
283  *
284  * @note If no data is written to the buffer due to the buffer being full this MUST
285  * return zero as the return value.
286  * A zero return value SHOULD represent that the write operation can be retried
287  * by calling the API function. Zero MUST NOT be returned if a network disconnection
288  * has occurred.
289  */
290 /* @[define_transportwritev] */
291 typedef int32_t ( * TransportWritev_t )( NetworkContext_t * pNetworkContext,
292                                          TransportOutVector_t * pIoVec,
293                                          size_t ioVecCount );
294 /* @[define_transportwritev] */
295
296 /**
297  * @transportstruct
298  * @brief The transport layer interface.
299  */
300 /* @[define_transportinterface] */
301 typedef struct TransportInterface
302 {
303     TransportRecv_t recv;               /**< Transport receive function pointer. */
304     TransportSend_t send;               /**< Transport send function pointer. */
305     TransportWritev_t writev;           /**< Transport writev function pointer. */
306     NetworkContext_t * pNetworkContext; /**< Implementation-defined network context. */
307 } TransportInterface_t;
308 /* @[define_transportinterface] */
309
310 /* *INDENT-OFF* */
311 #ifdef __cplusplus
312     }
313 #endif
314 /* *INDENT-ON* */
315
316 #endif /* ifndef TRANSPORT_INTERFACE_H_ */