• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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