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 * This structure 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 const 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 * Sends out data on a TCP endpoint, using the provided TCP circular send 112 * buffer to manage buffering. 113 * 114 * Once this function is called, @p aSendBuffer and @p aEndpoint are considered 115 * "attached" to each other. While they are attached, ALL send operations for 116 * @p aEndpoint must be made using @p aSendBuffer and ALL operations on 117 * @p aSendBuffer must be associated with @p aEndpoint . 118 * 119 * The only way to "detach" a TCP circular send buffer and a TCP endpoint is to 120 * wait for the send buffer to become completely empty. This can happen in two 121 * ways: (1) all data in the send buffer is sent and acknowledged in the normal 122 * course of TCP protocol operation, or (2) the connection is terminated. 123 * 124 * The recommended usage pattern is to use a single TCP circular send buffer 125 * with a TCP endpoint, and to send data on that TCP endpoint only via its 126 * associated TCP circular buffer. This recommended usage pattern sidesteps the 127 * issues described above by always using a TCP endpoint and TCP circular send 128 * buffer together. 129 * 130 * If the circular send buffer reaches capacity, only a prefix of the provided 131 * data is copied into the circular send buffer. 132 * 133 * @param[in] aEndpoint The TCP endpoint on which to send out data. 134 * @param[in] aSendBuffer The TCP circular send buffer into which to copy data. 135 * @param[in] aData A pointer to data to copy into the TCP circular send buffer. 136 * @param[in] aLength The length of the data pointed to by @p aData to copy into the TCP circular send buffer. 137 * @param[out] aWritten Populated with the amount of data copied into the send buffer, which might be less than 138 * @p aLength if the send buffer reaches capacity. 139 * 140 * @returns OT_ERROR_NONE Successfully copied data into the send buffer and sent it on the TCP endpoint. 141 * @returns OT_ERROR_FAILED Failed to send out data on the TCP endpoint. 142 */ 143 otError otTcpCircularSendBufferWrite(otTcpEndpoint * aEndpoint, 144 otTcpCircularSendBuffer *aSendBuffer, 145 void * aData, 146 size_t aLength, 147 size_t * aWritten); 148 149 /** 150 * Performs circular-send-buffer-specific handling in the otTcpForwardProgress 151 * callback. 152 * 153 * The application is expected to install an otTcpForwardProgress() callback on 154 * the otTcpEndpoint, and call this function at the start of the callback 155 * function for circular-send-buffer-specific processing. 156 * 157 * In the callback function, the application can determine the amount of free 158 * space in the circular send buffer by calling 159 * otTcpCircularSendBufferFreeSpace(), or by comparing @p aInSendBuffer with 160 * the send buffer's capacity, chosen by the user when calling 161 * otTcpCircularSendBufferInitialize(). 162 * 163 * @param[in] aSendBuffer A pointer to the TCP circular send buffer for the endpoint for which 164 * otTcpForwardProgress() was invoked. 165 * @param[in] aInSendBuffer Value of @p aInSendBuffer passed to the otTcpForwardProgress() callback. 166 */ 167 void otTcpCircularSendBufferHandleForwardProgress(otTcpCircularSendBuffer *aSendBuffer, size_t aInSendBuffer); 168 169 /** 170 * Returns the amount of free space in the TCP circular send buffer. 171 * 172 * This operation will always succeed. 173 * 174 * @param[in] aSendBuffer A pointer to the TCP circular send buffer whose amount of free space to return. 175 * 176 * @return The amount of free space in the send buffer. 177 */ 178 size_t otTcpCircularSendBufferFreeSpace(otTcpCircularSendBuffer *aSendBuffer); 179 180 /** 181 * Forcibly discards all data in the circular send buffer. 182 * 183 * The application is expected to call this function when a TCP connection is 184 * terminated unceremoniously (e.g., if the application calls 185 * otTcpEndpointAbort() or is informed of a reset connection via the 186 * otTcpConnectionLost() callback). 187 * 188 * Calling this function on a nonempty TCP circular send buffer attached to a 189 * TCP endpoint results in undefined behavior. 190 * 191 * @param[in] aSendBuffer The TCP circular send buffer whose data to discard. 192 */ 193 void otTcpCircularSendBufferForceDiscardAll(otTcpCircularSendBuffer *aSendBuffer); 194 195 /** 196 * Deinitializes a TCP circular send buffer, detaching it if attached. 197 * 198 * If the TCP circular send buffer is not empty, then this operation will fail. 199 * 200 * @param[in] aSendBuffer The TCP circular send buffer to deinitialize. 201 * 202 * @retval OT_ERROR_NONE Successfully deinitialize the TCP circular send buffer. 203 * @retval OT_ERROR_BUSY Circular buffer contains data and cannot be deinitialized. 204 */ 205 otError otTcpCircularSendBufferDeinitialize(otTcpCircularSendBuffer *aSendBuffer); 206 207 /** 208 * @} 209 * 210 */ 211 212 #ifdef __cplusplus 213 } // extern "C" 214 #endif 215 216 #endif // OPENTHREAD_TCP_EXT_H_ 217