• 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 
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