1 /* 2 * Copyright (c) 2022, The OpenThread Authors. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 3. Neither the name of the copyright holder nor the 13 * names of its contributors may be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @file 31 * @brief 32 * This file defines extensions to the OpenThread TCP API. 33 */ 34 35 #ifndef OPENTHREAD_TCP_EXT_H_ 36 #define OPENTHREAD_TCP_EXT_H_ 37 38 #include <openthread/tcp.h> 39 40 #ifdef __cplusplus 41 extern "C" { 42 #endif 43 44 /** 45 * @addtogroup api-tcp-ext 46 * 47 * @brief 48 * This module includes easy-to-use abstractions on top of the base TCP API. 49 * 50 * @{ 51 */ 52 53 /** 54 * Represents a circular send buffer for use with a TCP endpoint. 55 * 56 * Using a circular send buffer is optional. Applications can use a TCP 57 * endpoint to send data by managing otLinkedBuffers directly. However, some 58 * applications may find it more convenient to have a circular send buffer; 59 * such applications can call otTcpCircularSendBufferWrite() to "attach" a 60 * circular send buffer to a TCP endpoint and send out data on that TCP 61 * endpoint, relying on the circular send buffer to manage the underlying 62 * otLinkedBuffers. 63 * 64 * otTcpCircularSendBuffer is implemented on top of the otLinkedBuffer-based 65 * API provided by an otTcpEndpoint. Once attached to an otTcpEndpoint, an 66 * otTcpCircularSendBuffer performs all the work of managing otLinkedBuffers 67 * for the connection. This means that, once an otTcpCircularSendBuffer is 68 * attached to an otTcpEndpoint, the application should not call 69 * otTcpSendByReference() or otTcpSendByExtension() on that otTcpEndpoint. 70 * Instead, the application should use otTcpCircularSendBufferWrite() to add 71 * data to the send buffer. 72 * 73 * The otTcpForwardProgress() callback is the intended way for users to learn 74 * when space becomes available in the circular send buffer. On an 75 * otTcpEndpoint to which an otTcpCircularSendBuffer is attached, the 76 * application MUST install an otTcpForwardProgress() callback and call 77 * otTcpCircularSendBufferHandleForwardProgress() on the attached 78 * otTcpCircularSendBuffer at the start of the callback function. It is 79 * recommended that the user NOT install an otTcpSendDone() callback, as all 80 * management of otLinkedBuffers is handled by the circular send buffer. 81 * 82 * The application should not inspect the fields of this structure directly; it 83 * should only interact with it via the TCP Circular Send Buffer API functions 84 * whose signature are provided in this file. 85 */ 86 typedef struct otTcpCircularSendBuffer 87 { 88 uint8_t *mDataBuffer; ///< Pointer to data in the circular send buffer 89 size_t mCapacity; ///< Length of the circular send buffer 90 size_t mStartIndex; ///< Index of the first valid byte in the send buffer 91 size_t mCapacityUsed; ///< Number of bytes stored in the send buffer 92 93 otLinkedBuffer mSendLinks[2]; 94 uint8_t mFirstSendLinkIndex; 95 } otTcpCircularSendBuffer; 96 97 /** 98 * Initializes a TCP circular send buffer. 99 * 100 * @param[in] aSendBuffer A pointer to the TCP circular send buffer to initialize. 101 * @param[in] aDataBuffer A pointer to memory to use to store data in the TCP circular send buffer. 102 * @param[in] aCapacity The capacity, in bytes, of the TCP circular send buffer, which must equal the size of 103 * the memory pointed to by @p aDataBuffer . 104 */ 105 void otTcpCircularSendBufferInitialize(otTcpCircularSendBuffer *aSendBuffer, void *aDataBuffer, size_t aCapacity); 106 107 /** 108 * Defines flags passed to @p otTcpCircularSendBufferWrite. 109 */ 110 enum 111 { 112 OT_TCP_CIRCULAR_SEND_BUFFER_WRITE_MORE_TO_COME = 1 << 0, 113 }; 114 115 /** 116 * Sends out data on a TCP endpoint, using the provided TCP circular send 117 * buffer to manage buffering. 118 * 119 * Once this function is called, @p aSendBuffer and @p aEndpoint are considered 120 * "attached" to each other. While they are attached, ALL send operations for 121 * @p aEndpoint must be made using @p aSendBuffer and ALL operations on 122 * @p aSendBuffer must be associated with @p aEndpoint . 123 * 124 * The only way to "detach" a TCP circular send buffer and a TCP endpoint is to 125 * wait for the send buffer to become completely empty. This can happen in two 126 * ways: (1) all data in the send buffer is sent and acknowledged in the normal 127 * course of TCP protocol operation, or (2) the connection is terminated. 128 * 129 * The recommended usage pattern is to use a single TCP circular send buffer 130 * with a TCP endpoint, and to send data on that TCP endpoint only via its 131 * associated TCP circular buffer. This recommended usage pattern sidesteps the 132 * issues described above by always using a TCP endpoint and TCP circular send 133 * buffer together. 134 * 135 * If the circular send buffer reaches capacity, only a prefix of the provided 136 * data is copied into the circular send buffer. 137 * 138 * @param[in] aEndpoint The TCP endpoint on which to send out data. 139 * @param[in] aSendBuffer The TCP circular send buffer into which to copy data. 140 * @param[in] aData A pointer to data to copy into the TCP circular send buffer. 141 * @param[in] aLength The length of the data pointed to by @p aData to copy into the TCP circular send buffer. 142 * @param[out] aWritten Populated with the amount of data copied into the send buffer, which might be less than 143 * @p aLength if the send buffer reaches capacity. 144 * @param[in] aFlags Flags specifying options for this operation (see enumeration above). 145 * 146 * @retval OT_ERROR_NONE Successfully copied data into the send buffer and sent it on the TCP endpoint. 147 * @retval OT_ERROR_FAILED Failed to send out data on the TCP endpoint. 148 */ 149 otError otTcpCircularSendBufferWrite(otTcpEndpoint *aEndpoint, 150 otTcpCircularSendBuffer *aSendBuffer, 151 const void *aData, 152 size_t aLength, 153 size_t *aWritten, 154 uint32_t aFlags); 155 156 /** 157 * Performs circular-send-buffer-specific handling in the otTcpForwardProgress 158 * callback. 159 * 160 * The application is expected to install an otTcpForwardProgress() callback on 161 * the otTcpEndpoint, and call this function at the start of the callback 162 * function for circular-send-buffer-specific processing. 163 * 164 * In the callback function, the application can determine the amount of free 165 * space in the circular send buffer by calling 166 * otTcpCircularSendBufferFreeSpace(), or by comparing @p aInSendBuffer with 167 * the send buffer's capacity, chosen by the user when calling 168 * otTcpCircularSendBufferInitialize(). 169 * 170 * @param[in] aSendBuffer A pointer to the TCP circular send buffer for the endpoint for which 171 * otTcpForwardProgress() was invoked. 172 * @param[in] aInSendBuffer Value of @p aInSendBuffer passed to the otTcpForwardProgress() callback. 173 */ 174 void otTcpCircularSendBufferHandleForwardProgress(otTcpCircularSendBuffer *aSendBuffer, size_t aInSendBuffer); 175 176 /** 177 * Returns the amount of free space in the TCP circular send buffer. 178 * 179 * This operation will always succeed. 180 * 181 * @param[in] aSendBuffer A pointer to the TCP circular send buffer whose amount of free space to return. 182 * 183 * @returns The amount of free space in the send buffer. 184 */ 185 size_t otTcpCircularSendBufferGetFreeSpace(const otTcpCircularSendBuffer *aSendBuffer); 186 187 /** 188 * Forcibly discards all data in the circular send buffer. 189 * 190 * The application is expected to call this function when a TCP connection is 191 * terminated unceremoniously (e.g., if the application calls 192 * otTcpEndpointAbort() or is informed of a reset connection via the 193 * otTcpConnectionLost() callback). 194 * 195 * Calling this function on a nonempty TCP circular send buffer attached to a 196 * TCP endpoint results in undefined behavior. 197 * 198 * @param[in] aSendBuffer The TCP circular send buffer whose data to discard. 199 */ 200 void otTcpCircularSendBufferForceDiscardAll(otTcpCircularSendBuffer *aSendBuffer); 201 202 /** 203 * Deinitializes a TCP circular send buffer, detaching it if attached. 204 * 205 * If the TCP circular send buffer is not empty, then this operation will fail. 206 * 207 * @param[in] aSendBuffer The TCP circular send buffer to deinitialize. 208 * 209 * @retval OT_ERROR_NONE Successfully deinitialize the TCP circular send buffer. 210 * @retval OT_ERROR_BUSY Circular buffer contains data and cannot be deinitialized. 211 */ 212 otError otTcpCircularSendBufferDeinitialize(otTcpCircularSendBuffer *aSendBuffer); 213 214 /** 215 * Context structure to use with mbedtls_ssl_set_bio. 216 */ 217 typedef struct otTcpEndpointAndCircularSendBuffer 218 { 219 otTcpEndpoint *mEndpoint; 220 otTcpCircularSendBuffer *mSendBuffer; 221 } otTcpEndpointAndCircularSendBuffer; 222 223 /** 224 * Non-blocking send callback to pass to mbedtls_ssl_set_bio. 225 * 226 * @param[in] aCtx A pointer to an otTcpEndpointAndCircularSendBuffer. 227 * @param[in] aBuf The data to add to the send buffer. 228 * @param[in] aLen The amount of data to add to the send buffer. 229 * 230 * @returns The number of bytes sent, or an mbedtls error code. 231 */ 232 int otTcpMbedTlsSslSendCallback(void *aCtx, const unsigned char *aBuf, size_t aLen); 233 234 /** 235 * Non-blocking receive callback to pass to mbedtls_ssl_set_bio. 236 * 237 * @param[in] aCtx A pointer to an otTcpEndpointAndCircularSendBuffer. 238 * @param[out] aBuf The buffer into which to receive data. 239 * @param[in] aLen The maximum amount of data that can be received. 240 * 241 * @returns The number of bytes received, or an mbedtls error code. 242 */ 243 int otTcpMbedTlsSslRecvCallback(void *aCtx, unsigned char *aBuf, size_t aLen); 244 245 /** 246 * @} 247 */ 248 249 #ifdef __cplusplus 250 } // extern "C" 251 #endif 252 253 #endif // OPENTHREAD_TCP_EXT_H_ 254