transport_interface.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. * coreMQTT <DEVELOPMENT BRANCH>
  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. * @file transport_interface.h
  26. * @brief Transport interface definitions to send and receive data over the
  27. * network.
  28. */
  29. #ifndef TRANSPORT_INTERFACE_H_
  30. #define TRANSPORT_INTERFACE_H_
  31. #include <stdint.h>
  32. #include <stddef.h>
  33. /* *INDENT-OFF* */
  34. #ifdef __cplusplus
  35. extern "C" {
  36. #endif
  37. /* *INDENT-ON* */
  38. /**
  39. * @transportpage
  40. * @brief The transport interface definition.
  41. *
  42. * @transportsectionoverview
  43. *
  44. * The transport interface is a set of APIs that must be implemented using an
  45. * external transport layer protocol. The transport interface is defined in
  46. * @ref transport_interface.h. This interface allows protocols like MQTT and
  47. * HTTP to send and receive data over the transport layer. This
  48. * interface does not handle connection and disconnection to the server of
  49. * interest. The connection, disconnection, and other transport settings, like
  50. * timeout and TLS setup, must be handled in the user application.
  51. * <br>
  52. *
  53. * The functions that must be implemented are:<br>
  54. * - [Transport Receive](@ref TransportRecv_t)
  55. * - [Transport Send](@ref TransportSend_t)
  56. *
  57. * Each of the functions above take in an opaque context @ref NetworkContext_t.
  58. * The functions above and the context are also grouped together in the
  59. * @ref TransportInterface_t structure:<br><br>
  60. * @snippet this define_transportinterface
  61. * <br>
  62. *
  63. * @transportsectionimplementation
  64. *
  65. * The following steps give guidance on implementing the transport interface:
  66. *
  67. * -# Implementing @ref NetworkContext_t<br><br>
  68. * @snippet this define_networkcontext
  69. * <br>
  70. * @ref NetworkContext_t is the incomplete type <b>struct NetworkContext</b>.
  71. * The implemented struct NetworkContext must contain all of the information
  72. * that is needed to receive and send data with the @ref TransportRecv_t
  73. * and the @ref TransportSend_t implementations.<br>
  74. * In the case of TLS over TCP, struct NetworkContext is typically implemented
  75. * with the TCP socket context and a TLS context.<br><br>
  76. * <b>Example code:</b>
  77. * @code{c}
  78. * struct NetworkContext
  79. * {
  80. * struct MyTCPSocketContext tcpSocketContext;
  81. * struct MyTLSContext tlsContext;
  82. * };
  83. * @endcode
  84. * <br>
  85. * -# Implementing @ref TransportRecv_t<br><br>
  86. * @snippet this define_transportrecv
  87. * <br>
  88. * This function is expected to populate a buffer, with bytes received from the
  89. * transport, and return the number of bytes placed in the buffer.
  90. * In the case of TLS over TCP, @ref TransportRecv_t is typically implemented by
  91. * calling the TLS layer function to receive data. In case of plaintext TCP
  92. * without TLS, it is typically implemented by calling the TCP layer receive
  93. * function. @ref TransportRecv_t may be invoked multiple times by the protocol
  94. * library, if fewer bytes than were requested to receive are returned.
  95. * Please note that it is HIGHLY RECOMMENDED that the transport receive implementation does NOT block.
  96. * <br><br>
  97. * <b>Example code:</b>
  98. * @code{c}
  99. * int32_t myNetworkRecvImplementation( NetworkContext_t * pNetworkContext,
  100. * void * pBuffer,
  101. * size_t bytesToRecv )
  102. * {
  103. * int32_t bytesReceived = 0;
  104. * bool callTlsRecvFunc = true;
  105. *
  106. * // For a single byte read request, check if data is available on the network.
  107. * if( bytesToRecv == 1 )
  108. * {
  109. * // If no data is available on the network, do not call TLSRecv
  110. * // to avoid blocking for socket timeout.
  111. * if( TLSRecvCount( pNetworkContext->tlsContext ) == 0 )
  112. * {
  113. * callTlsRecvFunc = false;
  114. * }
  115. * }
  116. *
  117. * if( callTlsRecvFunc == true )
  118. * {
  119. * bytesReceived = TLSRecv( pNetworkContext->tlsContext,
  120. * pBuffer,
  121. * bytesToRecv,
  122. * MY_SOCKET_TIMEOUT );
  123. * if( bytesReceived < 0 )
  124. * {
  125. * // If the error code represents a timeout, then the return
  126. * // code should be translated to zero so that the caller
  127. * // can retry the read operation.
  128. * if( bytesReceived == MY_SOCKET_ERROR_TIMEOUT )
  129. * {
  130. * bytesReceived = 0;
  131. * }
  132. * }
  133. * // Handle other cases.
  134. * }
  135. * return bytesReceived;
  136. * }
  137. * @endcode
  138. * <br>
  139. * -# Implementing @ref TransportSend_t<br><br>
  140. * @snippet this define_transportsend
  141. * <br>
  142. * This function is expected to send the bytes, in the given buffer over the
  143. * transport, and return the number of bytes sent.
  144. * In the case of TLS over TCP, @ref TransportSend_t is typically implemented by
  145. * calling the TLS layer function to send data. In case of plaintext TCP
  146. * without TLS, it is typically implemented by calling the TCP layer send
  147. * function. @ref TransportSend_t may be invoked multiple times by the protocol
  148. * library, if fewer bytes than were requested to send are returned.
  149. * <br><br>
  150. * <b>Example code:</b>
  151. * @code{c}
  152. * int32_t myNetworkSendImplementation( NetworkContext_t * pNetworkContext,
  153. * const void * pBuffer,
  154. * size_t bytesToSend )
  155. * {
  156. * int32_t bytesSent = 0;
  157. * bytesSent = TLSSend( pNetworkContext->tlsContext,
  158. * pBuffer,
  159. * bytesToSend,
  160. * MY_SOCKET_TIMEOUT );
  161. *
  162. * // If underlying TCP buffer is full, set the return value to zero
  163. * // so that caller can retry the send operation.
  164. * if( bytesSent == MY_SOCKET_ERROR_BUFFER_FULL )
  165. * {
  166. * bytesSent = 0;
  167. * }
  168. * else if( bytesSent < 0 )
  169. * {
  170. * // Handle socket error.
  171. * }
  172. * // Handle other cases.
  173. *
  174. * return bytesSent;
  175. * }
  176. * @endcode
  177. */
  178. /**
  179. * @transportstruct
  180. * @typedef NetworkContext_t
  181. * @brief The NetworkContext is an incomplete type. An implementation of this
  182. * interface must define struct NetworkContext for the system requirements.
  183. * This context is passed into the network interface functions.
  184. */
  185. /* @[define_networkcontext] */
  186. struct NetworkContext;
  187. typedef struct NetworkContext NetworkContext_t;
  188. /* @[define_networkcontext] */
  189. /**
  190. * @transportcallback
  191. * @brief Transport interface for receiving data on the network.
  192. *
  193. * @note It is HIGHLY RECOMMENDED that the transport receive
  194. * implementation does NOT block.
  195. * coreMQTT will continue to call the transport interface if it receives
  196. * a partial packet until it accumulates enough data to get the complete
  197. * MQTT packet.
  198. * A non‐blocking implementation is also essential so that the library's inbuilt
  199. * keep‐alive mechanism can work properly, given the user chooses to use
  200. * that over their own keep alive mechanism.
  201. *
  202. * @param[in] pNetworkContext Implementation-defined network context.
  203. * @param[in] pBuffer Buffer to receive the data into.
  204. * @param[in] bytesToRecv Number of bytes requested from the network.
  205. *
  206. * @return The number of bytes received or a negative value to indicate
  207. * error.
  208. *
  209. * @note If no data is available on the network to read and no error
  210. * has occurred, zero MUST be the return value. A zero return value
  211. * SHOULD represent that the read operation can be retried by calling
  212. * the API function. Zero MUST NOT be returned if a network disconnection
  213. * has occurred.
  214. */
  215. /* @[define_transportrecv] */
  216. typedef int32_t ( * TransportRecv_t )( NetworkContext_t * pNetworkContext,
  217. void * pBuffer,
  218. size_t bytesToRecv );
  219. /* @[define_transportrecv] */
  220. /**
  221. * @transportcallback
  222. * @brief Transport interface for sending data over the network.
  223. *
  224. * @param[in] pNetworkContext Implementation-defined network context.
  225. * @param[in] pBuffer Buffer containing the bytes to send over the network stack.
  226. * @param[in] bytesToSend Number of bytes to send over the network.
  227. *
  228. * @return The number of bytes sent or a negative value to indicate error.
  229. *
  230. * @note If no data is transmitted over the network due to a full TX buffer and
  231. * no network error has occurred, this MUST return zero as the return value.
  232. * A zero return value SHOULD represent that the send operation can be retried
  233. * by calling the API function. Zero MUST NOT be returned if a network disconnection
  234. * has occurred.
  235. */
  236. /* @[define_transportsend] */
  237. typedef int32_t ( * TransportSend_t )( NetworkContext_t * pNetworkContext,
  238. const void * pBuffer,
  239. size_t bytesToSend );
  240. /* @[define_transportsend] */
  241. /**
  242. * @brief Transport vector structure for sending multiple messages.
  243. */
  244. typedef struct TransportOutVector
  245. {
  246. /**
  247. * @brief Base address of data.
  248. */
  249. const void * iov_base;
  250. /**
  251. * @brief Length of data in buffer.
  252. */
  253. size_t iov_len;
  254. } TransportOutVector_t;
  255. /**
  256. * @transportcallback
  257. * @brief Transport interface function for "vectored" / scatter-gather based
  258. * writes. This function is expected to iterate over the list of vectors pIoVec
  259. * having ioVecCount entries containing portions of one MQTT message at a maximum.
  260. * If the proper functionality is available, then the data in the list should be
  261. * copied to the underlying TCP buffer before flushing the buffer. Implementing it
  262. * in this fashion will lead to sending of fewer TCP packets for all the values
  263. * in the list.
  264. *
  265. * @note If the proper write functionality is not present for a given device/IP-stack,
  266. * then there is no strict requirement to implement write. Only the send and recv
  267. * interfaces must be defined for the application to work properly.
  268. *
  269. * @param[in] pNetworkContext Implementation-defined network context.
  270. * @param[in] pIoVec An array of TransportIoVector_t structs.
  271. * @param[in] ioVecCount Number of TransportIoVector_t in pIoVec.
  272. *
  273. * @return The number of bytes written or a negative value to indicate error.
  274. *
  275. * @note If no data is written to the buffer due to the buffer being full this MUST
  276. * return zero as the return value.
  277. * A zero return value SHOULD represent that the write operation can be retried
  278. * by calling the API function. Zero MUST NOT be returned if a network disconnection
  279. * has occurred.
  280. */
  281. /* @[define_transportwritev] */
  282. typedef int32_t ( * TransportWritev_t )( NetworkContext_t * pNetworkContext,
  283. TransportOutVector_t * pIoVec,
  284. size_t ioVecCount );
  285. /* @[define_transportwritev] */
  286. /**
  287. * @transportstruct
  288. * @brief The transport layer interface.
  289. */
  290. /* @[define_transportinterface] */
  291. typedef struct TransportInterface
  292. {
  293. TransportRecv_t recv; /**< Transport receive function pointer. */
  294. TransportSend_t send; /**< Transport send function pointer. */
  295. TransportWritev_t writev; /**< Transport writev function pointer. */
  296. NetworkContext_t * pNetworkContext; /**< Implementation-defined network context. */
  297. } TransportInterface_t;
  298. /* @[define_transportinterface] */
  299. /* *INDENT-OFF* */
  300. #ifdef __cplusplus
  301. }
  302. #endif
  303. /* *INDENT-ON* */
  304. #endif /* ifndef TRANSPORT_INTERFACE_H_ */