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 36 #ifndef OPENTHREAD_TCP_EXT_H_ 37 #define OPENTHREAD_TCP_EXT_H_ 38 39 #include <openthread/tcp.h> 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 45 /** 46 * @addtogroup api-tcp-ext 47 * 48 * @brief 49 * This module includes easy-to-use abstractions on top of the base TCP API. 50 * 51 * @{ 52 * 53 */ 54 55 /** 56 * Represents a circular send buffer for use with a TCP endpoint. 57 * 58 * Using a circular send buffer is optional. Applications can use a TCP 59 * endpoint to send data by managing otLinkedBuffers directly. However, some 60 * applications may find it more convenient to have a circular send buffer; 61 * such applications can call otTcpCircularSendBufferWrite() to "attach" a 62 * circular send buffer to a TCP endpoint and send out data on that TCP 63 * endpoint, relying on the circular send buffer to manage the underlying 64 * otLinkedBuffers. 65 * 66 * otTcpCircularSendBuffer is implemented on top of the otLinkedBuffer-based 67 * API provided by an otTcpEndpoint. Once attached to an otTcpEndpoint, an 68 * otTcpCircularSendBuffer performs all the work of managing otLinkedBuffers 69 * for the connection. This means that, once an otTcpCircularSendBuffer is 70 * attached to an otTcpEndpoint, the application should not call 71 * otTcpSendByReference() or otTcpSendByExtension() on that otTcpEndpoint. 72 * Instead, the application should use otTcpCircularSendBufferWrite() to add 73 * data to the send buffer. 74 * 75 * The otTcpForwardProgress() callback is the intended way for users to learn 76 * when space becomes available in the circular send buffer. On an 77 * otTcpEndpoint to which an otTcpCircularSendBuffer is attached, the 78 * application MUST install an otTcpForwardProgress() callback and call 79 * otTcpCircularSendBufferHandleForwardProgress() on the attached 80 * otTcpCircularSendBuffer at the start of the callback function. It is 81 * recommended that the user NOT install an otTcpSendDone() callback, as all 82 * management of otLinkedBuffers is handled by the circular send buffer. 83 * 84 * The application should not inspect the fields of this structure directly; it 85 * should only interact with it via the TCP Circular Send Buffer API functions 86 * whose signature are provided in this file. 87 * 88 */ 89 typedef struct otTcpCircularSendBuffer 90 { 91 uint8_t *mDataBuffer; ///< Pointer to data in the circular send buffer 92 size_t mCapacity; ///< Length of the circular send buffer 93 size_t mStartIndex; ///< Index of the first valid byte in the send buffer 94 size_t mCapacityUsed; ///< Number of bytes stored in the send buffer 95 96 otLinkedBuffer mSendLinks[2]; 97 uint8_t mFirstSendLinkIndex; 98 } otTcpCircularSendBuffer; 99 100 /** 101 * Initializes a TCP circular send buffer. 102 * 103 * @param[in] aSendBuffer A pointer to the TCP circular send buffer to initialize. 104 * @param[in] aDataBuffer A pointer to memory to use to store data in the TCP circular send buffer. 105 * @param[in] aCapacity The capacity, in bytes, of the TCP circular send buffer, which must equal the size of 106 * the memory pointed to by @p aDataBuffer . 107 */ 108 void otTcpCircularSendBufferInitialize(otTcpCircularSendBuffer *aSendBuffer, void *aDataBuffer, size_t aCapacity); 109 110 /** 111 * Defines flags passed to @p otTcpCircularSendBufferWrite. 112 * 113 */ 114 enum 115 { 116 OT_TCP_CIRCULAR_SEND_BUFFER_WRITE_MORE_TO_COME = 1 << 0, 117 }; 118 119 /** 120 * Sends out data on a TCP endpoint, using the provided TCP circular send 121 * buffer to manage buffering. 122 * 123 * Once this function is called, @p aSendBuffer and @p aEndpoint are considered 124 * "attached" to each other. While they are attached, ALL send operations for 125 * @p aEndpoint must be made using @p aSendBuffer and ALL operations on 126 * @p aSendBuffer must be associated with @p aEndpoint . 127 * 128 * The only way to "detach" a TCP circular send buffer and a TCP endpoint is to 129 * wait for the send buffer to become completely empty. This can happen in two 130 * ways: (1) all data in the send buffer is sent and acknowledged in the normal 131 * course of TCP protocol operation, or (2) the connection is terminated. 132 * 133 * The recommended usage pattern is to use a single TCP circular send buffer 134 * with a TCP endpoint, and to send data on that TCP endpoint only via its 135 * associated TCP circular buffer. This recommended usage pattern sidesteps the 136 * issues described above by always using a TCP endpoint and TCP circular send 137 * buffer together. 138 * 139 * If the circular send buffer reaches capacity, only a prefix of the provided 140 * data is copied into the circular send buffer. 141 * 142 * @param[in] aEndpoint The TCP endpoint on which to send out data. 143 * @param[in] aSendBuffer The TCP circular send buffer into which to copy data. 144 * @param[in] aData A pointer to data to copy into the TCP circular send buffer. 145 * @param[in] aLength The length of the data pointed to by @p aData to copy into the TCP circular send buffer. 146 * @param[out] aWritten Populated with the amount of data copied into the send buffer, which might be less than 147 * @p aLength if the send buffer reaches capacity. 148 * @param[in] aFlags Flags specifying options for this operation (see enumeration above). 149 * 150 * @retval OT_ERROR_NONE Successfully copied data into the send buffer and sent it on the TCP endpoint. 151 * @retval OT_ERROR_FAILED Failed to send out data on the TCP endpoint. 152 */ 153 otError otTcpCircularSendBufferWrite(otTcpEndpoint *aEndpoint, 154 otTcpCircularSendBuffer *aSendBuffer, 155 const void *aData, 156 size_t aLength, 157 size_t *aWritten, 158 uint32_t aFlags); 159 160 /** 161 * Performs circular-send-buffer-specific handling in the otTcpForwardProgress 162 * callback. 163 * 164 * The application is expected to install an otTcpForwardProgress() callback on 165 * the otTcpEndpoint, and call this function at the start of the callback 166 * function for circular-send-buffer-specific processing. 167 * 168 * In the callback function, the application can determine the amount of free 169 * space in the circular send buffer by calling 170 * otTcpCircularSendBufferFreeSpace(), or by comparing @p aInSendBuffer with 171 * the send buffer's capacity, chosen by the user when calling 172 * otTcpCircularSendBufferInitialize(). 173 * 174 * @param[in] aSendBuffer A pointer to the TCP circular send buffer for the endpoint for which 175 * otTcpForwardProgress() was invoked. 176 * @param[in] aInSendBuffer Value of @p aInSendBuffer passed to the otTcpForwardProgress() callback. 177 */ 178 void otTcpCircularSendBufferHandleForwardProgress(otTcpCircularSendBuffer *aSendBuffer, size_t aInSendBuffer); 179 180 /** 181 * Returns the amount of free space in the TCP circular send buffer. 182 * 183 * This operation will always succeed. 184 * 185 * @param[in] aSendBuffer A pointer to the TCP circular send buffer whose amount of free space to return. 186 * 187 * @returns The amount of free space in the send buffer. 188 */ 189 size_t otTcpCircularSendBufferGetFreeSpace(const otTcpCircularSendBuffer *aSendBuffer); 190 191 /** 192 * Forcibly discards all data in the circular send buffer. 193 * 194 * The application is expected to call this function when a TCP connection is 195 * terminated unceremoniously (e.g., if the application calls 196 * otTcpEndpointAbort() or is informed of a reset connection via the 197 * otTcpConnectionLost() callback). 198 * 199 * Calling this function on a nonempty TCP circular send buffer attached to a 200 * TCP endpoint results in undefined behavior. 201 * 202 * @param[in] aSendBuffer The TCP circular send buffer whose data to discard. 203 */ 204 void otTcpCircularSendBufferForceDiscardAll(otTcpCircularSendBuffer *aSendBuffer); 205 206 /** 207 * Deinitializes a TCP circular send buffer, detaching it if attached. 208 * 209 * If the TCP circular send buffer is not empty, then this operation will fail. 210 * 211 * @param[in] aSendBuffer The TCP circular send buffer to deinitialize. 212 * 213 * @retval OT_ERROR_NONE Successfully deinitialize the TCP circular send buffer. 214 * @retval OT_ERROR_BUSY Circular buffer contains data and cannot be deinitialized. 215 */ 216 otError otTcpCircularSendBufferDeinitialize(otTcpCircularSendBuffer *aSendBuffer); 217 218 /** 219 * Context structure to use with mbedtls_ssl_set_bio. 220 */ 221 typedef struct otTcpEndpointAndCircularSendBuffer 222 { 223 otTcpEndpoint *mEndpoint; 224 otTcpCircularSendBuffer *mSendBuffer; 225 } otTcpEndpointAndCircularSendBuffer; 226 227 /** 228 * Non-blocking send callback to pass to mbedtls_ssl_set_bio. 229 * 230 * @param[in] aCtx A pointer to an otTcpEndpointAndCircularSendBuffer. 231 * @param[in] aBuf The data to add to the send buffer. 232 * @param[in] aLen The amount of data to add to the send buffer. 233 * 234 * @returns The number of bytes sent, or an mbedtls error code. 235 */ 236 int otTcpMbedTlsSslSendCallback(void *aCtx, const unsigned char *aBuf, size_t aLen); 237 238 /** 239 * Non-blocking receive callback to pass to mbedtls_ssl_set_bio. 240 * 241 * @param[in] aCtx A pointer to an otTcpEndpointAndCircularSendBuffer. 242 * @param[out] aBuf The buffer into which to receive data. 243 * @param[in] aLen The maximum amount of data that can be received. 244 * 245 * @returns The number of bytes received, or an mbedtls error code. 246 */ 247 int otTcpMbedTlsSslRecvCallback(void *aCtx, unsigned char *aBuf, size_t aLen); 248 249 /** 250 * @} 251 * 252 */ 253 254 #ifdef __cplusplus 255 } // extern "C" 256 #endif 257 258 #endif // OPENTHREAD_TCP_EXT_H_ 259