• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2021, 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 the OpenThread TCP API.
33  *
34  */
35 
36 #ifndef OPENTHREAD_TCP_H_
37 #define OPENTHREAD_TCP_H_
38 
39 #include <openthread/ip6.h>
40 
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 
45 /**
46  * @addtogroup api-tcp
47  *
48  * @brief
49  *   This module includes functions that control TCP communication.
50  *
51  * @{
52  *
53  */
54 
55 /**
56  * A linked buffer structure for use with TCP.
57  *
58  * A single otLinkedBuffer structure references an array of bytes in memory,
59  * via mData and mLength. The mNext field is used to form a chain of
60  * otLinkedBuffer structures.
61  *
62  */
63 typedef struct otLinkedBuffer
64 {
65     struct otLinkedBuffer *mNext;   ///< Pointer to the next linked buffer in the chain, or NULL if it is the end.
66     const uint8_t *        mData;   ///< Pointer to data referenced by this linked buffer.
67     size_t                 mLength; ///< Length of this linked buffer (number of bytes).
68 } otLinkedBuffer;
69 
70 struct otTcpEndpoint;
71 typedef struct otTcpEndpoint otTcpEndpoint;
72 
73 /**
74  * This callback informs the application that the TCP 3-way handshake is
75  * complete and that the connection is now established.
76  *
77  * @param[in]  aEndpoint  The TCP endpoint whose connection is now established.
78  *
79  */
80 typedef void (*otTcpEstablished)(otTcpEndpoint *aEndpoint);
81 
82 /**
83  * This callback informs the application that data in the provided
84  * @p aData have been acknowledged by the connection peer and that @p aData and
85  * the data it contains can be reclaimed by the application.
86  *
87  * The @p aData are guaranteed to be identical to those passed in to TCP via
88  * otTcpSendByReference(), including any extensions effected via
89  * otTcpSendByExtension().
90  *
91  * @param[in]  aEndpoint  The TCP endpoint for the connection.
92  * @param[in]  aData      A pointer to the otLinkedBuffer that can be reclaimed.
93  *
94  */
95 typedef void (*otTcpSendDone)(otTcpEndpoint *aEndpoint, otLinkedBuffer *aData);
96 
97 /**
98  * This callback informs the application if forward progress has been made in
99  * transferring data from the send buffer to the recipient. This callback is
100  * not necessary for correct TCP operation. Most applications can just rely on
101  * the otTcpSendDone() callback to reclaim linked buffers once the TCP stack is
102  * done using them. The purpose of this callback is to support advanced
103  * applications that benefit from finer-grained information about how the
104  * the connection is making forward progress in transferring data to the
105  * connection peer.
106  *
107  * This callback's operation is closely tied to TCP's send buffer. The send
108  * buffer can be understood as having two regions. First, there is the
109  * "in-flight" region at the head (front) of the send buffer. It corresponds
110  * to data which has been sent to the recipient, but is not yet acknowledged.
111  * Second, there is the "backlog" region, which consists of all data in the
112  * send buffer that is not in the "in-flight" region. The "backlog" region
113  * corresponds to data that is queued for sending, but has not yet been sent.
114  *
115  * The callback is invoked in response to two types of events. First, the
116  * "in-flight" region of the send buffer may shrink (e.g., when the recipient
117  * acknowledges data that we sent earlier). Second, the "backlog" region of the
118  * send buffer may shrink (e.g., new data was sent out). These two conditions
119  * often occur at the same time, in response to an ACK segment from the
120  * connection peer, which is why they are combined in a single callback.
121  *
122  * The TCP stack only uses the @p aInSendBuffer bytes at the tail of the send
123  * buffer; when @p aInSendBuffer decreases by an amount x, it means that x
124  * additional bytes that were formerly at the head of the send buffer are no
125  * longer part of the send buffer and can now be reclaimed (i.e., overwritten)
126  * by the application. Note that the otLinkedBuffer structure itself can only
127  * be reclaimed once all bytes that it references are no longer part of the
128  * send buffer.
129  *
130  * This callback subsumes otTcpSendDone(), in the following sense: applications
131  * can determine when linked buffers can be reclaimed by comparing
132  * @p aInSendBuffer with how many bytes are in each linked buffer. However, we
133  * expect otTcpSendDone(), which directly conveys which otLinkedBuffers can be
134  * reclaimed, to be much simpler to use. If both callbacks are registered and
135  * are triggered by the same event (e.g., the same ACK segment received), then
136  * the otTcpSendDone() callback will be triggered first, followed by this
137  * callback.
138  *
139  * Additionally, this callback provides @p aBacklog, which indicates how many
140  * bytes of data in the send buffer are not yet in flight. For applications
141  * that only want to add data to the send buffer when there is an assurance
142  * that it will be sent out soon, it may be desirable to only send out data
143  * when @p aBacklog is suitably small (0 or close to 0). For example, an
144  * application may use @p aBacklog so that it can react to queue buildup by
145  * dropping or aggregating data to avoid creating a backlog of data.
146  *
147  * After a call to otTcpSendByReference() or otTcpSendByExtension() with a
148  * positive number of bytes, the otTcpForwardProgress() callback is guaranteed
149  * to be called, to indicate when the bytes that were added to the send buffer
150  * are sent out. The call to otTcpForwardProgress() may be made immediately
151  * after the bytes are added to the send buffer (if some of those bytes are
152  * immediately sent out, reducing the backlog), or sometime in the future (once
153  * the connection sends out some or all of the data, reducing the backlog). By
154  * "immediately," we mean that the callback is immediately scheduled for
155  * execution in a tasklet; to avoid reentrancy-related complexity, the
156  * otTcpForwardProgress() callback is never directly called from the
157  * otTcpSendByReference() or otTcpSendByExtension() functions.
158  *
159  * @param[in]  aEndpoint      The TCP endpoint for the connection.
160  * @param[in]  aInSendBuffer  The number of bytes in the send buffer (sum of "in-flight" and "backlog" regions).
161  * @param[in]  aBacklog       The number of bytes that are queued for sending but have not yet been sent (the "backlog"
162  *                            region).
163  *
164  */
165 typedef void (*otTcpForwardProgress)(otTcpEndpoint *aEndpoint, size_t aInSendBuffer, size_t aBacklog);
166 
167 /**
168  * This callback indicates the number of bytes available for consumption from
169  * the receive buffer.
170  *
171  * It is called whenever bytes are added to the receive buffer and when the
172  * end of stream is reached. If the end of the stream has been reached (i.e.,
173  * if no more data will become available to read because the connection peer
174  * has closed their end of the connection for writing), then @p aEndOfStream is
175  * true. Finally, @p aBytesRemaining indicates how much capacity is left in the
176  * receive buffer to hold additional data that arrives.
177  *
178  * @param[in]  aEndpoint        The TCP endpoint for the connection.
179  * @param[in]  aBytesAvailable  The number of bytes in the connection's receive buffer.
180  * @param[in]  aEndOfStream     Indicates if additional data, beyond what is already in the connection's receive buffer,
181  *                              can be received.
182  * @param[in]  aBytesRemaining  The number of additional bytes that can be received before the receive buffer becomes
183  *                              full.
184  *
185  */
186 typedef void (*otTcpReceiveAvailable)(otTcpEndpoint *aEndpoint,
187                                       size_t         aBytesAvailable,
188                                       bool           aEndOfStream,
189                                       size_t         aBytesRemaining);
190 
191 typedef enum otTcpDisconnectedReason
192 {
193     OT_TCP_DISCONNECTED_REASON_NORMAL,
194     OT_TCP_DISCONNECTED_REASON_REFUSED,
195     OT_TCP_DISCONNECTED_REASON_RESET,
196     OT_TCP_DISCONNECTED_REASON_TIME_WAIT,
197     OT_TCP_DISCONNECTED_REASON_TIMED_OUT,
198 } otTcpDisconnectedReason;
199 
200 /**
201  * This callback indicates that the connection was broken and should no longer
202  * be used, or that a connection has entered the TIME-WAIT state.
203  *
204  * It can occur if a connection establishment attempt (initiated by calling
205  * otTcpConnect()) fails, or any point thereafter (e.g., if the connection
206  * times out or an RST segment is received from the connection peer). Once this
207  * callback fires, all resources that the application provided for this
208  * connection (i.e., any `otLinkedBuffers` and memory they reference, but not
209  * the TCP endpoint itself or space for the receive buffers) can be reclaimed.
210  * In the case of a connection entering the TIME-WAIT state, this callback is
211  * called twice, once upon entry into the TIME-WAIT state (with
212  * OT_TCP_DISCONNECTED_REASON_TIME_WAIT, and again when the TIME-WAIT state
213  * expires (with OT_TCP_DISCONNECTED_REASON_NORMAL).
214  *
215  * @param[in]  aEndpoint  The TCP endpoint whose connection has been lost.
216  * @param[in]  aReason    The reason why the connection was lost.
217  *
218  */
219 typedef void (*otTcpDisconnected)(otTcpEndpoint *aEndpoint, otTcpDisconnectedReason aReason);
220 
221 /**
222  * OT_TCP_ENDPOINT_TCB_SIZE_BASE and OT_TCP_ENDPOINT_TCB_NUM_POINTERS are
223  * chosen such that the mTcb field of otTcpEndpoint has the same size as
224  * struct tcpcb in TCPlp. This is necessary because the mTcb field, although
225  * opaque in its declaration, is treated as struct tcpcb in the TCP
226  * implementation.
227  */
228 #define OT_TCP_ENDPOINT_TCB_SIZE_BASE 368
229 #define OT_TCP_ENDPOINT_TCB_NUM_PTR 36
230 
231 /**
232  * This structure represents a TCP endpoint.
233  *
234  * An TCP endpoint acts an endpoint of TCP connection. It can be used to
235  * initiate TCP connections, and, once a TCP connection is established, send
236  * data to and receive data from the connection peer.
237  *
238  * The application should not inspect the fields of this structure directly; it
239  * should only interact with it via the TCP API functions whose signatures are
240  * provided in this file.
241  *
242  */
243 struct otTcpEndpoint
244 {
245     union
246     {
247         uint8_t  mSize[OT_TCP_ENDPOINT_TCB_SIZE_BASE + OT_TCP_ENDPOINT_TCB_NUM_PTR * sizeof(void *)];
248         uint64_t mAlign;
249     } mTcb;
250 
251     struct otTcpEndpoint *mNext;    ///< A pointer to the next TCP endpoint (internal use only)
252     void *                mContext; ///< A pointer to application-specific context
253 
254     otTcpEstablished      mEstablishedCallback;      ///< "Established" callback function
255     otTcpSendDone         mSendDoneCallback;         ///< "Send done" callback function
256     otTcpForwardProgress  mForwardProgressCallback;  ///< "Forward progress" callback function
257     otTcpReceiveAvailable mReceiveAvailableCallback; ///< "Receive available" callback function
258     otTcpDisconnected     mDisconnectedCallback;     ///< "Disconnected" callback function
259 
260     uint32_t mTimers[4];
261 
262     otLinkedBuffer mReceiveLinks[2];
263     otSockAddr     mSockAddr;
264 
265     uint8_t mPendingCallbacks;
266 };
267 
268 /**
269  * This structure contains arguments to the otTcpEndpointInitialize() function.
270  *
271  */
272 typedef struct otTcpEndpointInitializeArgs
273 {
274     void *mContext; ///< Pointer to application-specific context
275 
276     otTcpEstablished      mEstablishedCallback;      ///< "Established" callback function
277     otTcpSendDone         mSendDoneCallback;         ///< "Send done" callback function
278     otTcpForwardProgress  mForwardProgressCallback;  ///< "Forward progress" callback function
279     otTcpReceiveAvailable mReceiveAvailableCallback; ///< "Receive available" callback function
280     otTcpDisconnected     mDisconnectedCallback;     ///< "Disconnected" callback function
281 
282     void * mReceiveBuffer;     ///< Pointer to memory provided to the system for the TCP receive buffer
283     size_t mReceiveBufferSize; ///< Size of memory provided to the system for the TCP receive buffer
284 } otTcpEndpointInitializeArgs;
285 
286 /**
287  * @def OT_TCP_RECEIVE_BUFFER_SIZE_FEW_HOPS
288  *
289  * Recommended buffer size for TCP connections that traverse about 3 wireless
290  * hops or fewer.
291  *
292  * On platforms where memory is particularly constrained and in situations
293  * where high bandwidth is not necessary, it may be desirable to manually
294  * select a smaller buffer size.
295  *
296  */
297 #define OT_TCP_RECEIVE_BUFFER_SIZE_FEW_HOPS 2599
298 
299 /**
300  * @def OT_TCP_RECEIVE_BUFFER_SIZE_MANY_HOPS
301  *
302  * Recommended buffer size for TCP connections that traverse many wireless
303  * hops.
304  *
305  * If the TCP connection traverses a very large number of hops (more than 6 or
306  * so), then it may be advisable to select a large buffer size manually.
307  *
308  */
309 #define OT_TCP_RECEIVE_BUFFER_SIZE_MANY_HOPS 4158
310 
311 /**
312  * Initializes a TCP endpoint.
313  *
314  * Calling this function causes OpenThread to keep track of the TCP endpoint
315  * and store and retrieve TCP data inside the @p aEndpoint. The application
316  * should refrain from directly accessing or modifying the fields in
317  * @p aEndpoint. If the application needs to reclaim the memory backing
318  * @p aEndpoint, it should call otTcpEndpointDeinitialize().
319  *
320  * @param[in]  aInstance  A pointer to an OpenThread instance.
321  * @param[in]  aEndpoint  A pointer to a TCP endpoint structure.
322  * @param[in]  aArgs      A pointer to a structure of arguments.
323  *
324  * @retval OT_ERROR_NONE    Successfully opened the TCP endpoint.
325  * @retval OT_ERROR_FAILED  Failed to open the TCP endpoint.
326  *
327  */
328 otError otTcpEndpointInitialize(otInstance *                       aInstance,
329                                 otTcpEndpoint *                    aEndpoint,
330                                 const otTcpEndpointInitializeArgs *aArgs);
331 
332 /**
333  * Obtains the otInstance that was associated with @p aEndpoint upon
334  * initialization.
335  *
336  * @param[in]  aEndpoint  The TCP endpoint whose instance to obtain.
337  *
338  * @returns  The otInstance pointer associated with @p aEndpoint.
339  *
340  */
341 otInstance *otTcpEndpointGetInstance(otTcpEndpoint *aEndpoint);
342 
343 /**
344  * Obtains the context pointer that was associated with @p aEndpoint upon
345  * initialization.
346  *
347  * @param[in]  aEndpoint  The TCP endpoint whose context to obtain.
348  *
349  * @returns  The context pointer associated with @p aEndpoint.
350  *
351  */
352 void *otTcpEndpointGetContext(otTcpEndpoint *aEndpoint);
353 
354 /**
355  * Obtains a pointer to a TCP endpoint's local host and port.
356  *
357  * The contents of the host and port may be stale if this socket is not in a
358  * connected state and has not been bound after it was last disconnected.
359  *
360  * @param[in]  aEndpoint  The TCP endpoint whose local host and port to obtain.
361  *
362  * @returns  The local host and port of @p aEndpoint.
363  *
364  */
365 const otSockAddr *otTcpGetLocalAddress(const otTcpEndpoint *aEndpoint);
366 
367 /**
368  * Obtains a pointer to a TCP endpoint's peer's host and port.
369  *
370  * The contents of the host and port may be stale if this socket is not in a
371  * connected state.
372  *
373  * @param[in]  aEndpoint  The TCP endpoint whose peer's host and port to obtain.
374  *
375  * @returns  The host and port of the connection peer of @p aEndpoint.
376  *
377  */
378 const otSockAddr *otTcpGetPeerAddress(const otTcpEndpoint *aEndpoint);
379 
380 /**
381  * Binds the TCP endpoint to an IP address and port.
382  *
383  * @param[in]  aEndpoint   A pointer to the TCP endpoint structure to bind.
384  * @param[in]  aSockName   The address and port to which to bind this TCP endpoint.
385  *
386  * @retval OT_ERROR_NONE    Successfully bound the TCP endpoint.
387  * @retval OT_ERROR_FAILED  Failed to bind the TCP endpoint.
388  *
389  */
390 otError otTcpBind(otTcpEndpoint *aEndpoint, const otSockAddr *aSockName);
391 
392 /**
393  * This enumeration defines flags passed to otTcpConnect().
394  *
395  */
396 enum
397 {
398     OT_TCP_CONNECT_NO_FAST_OPEN = 1 << 0,
399 };
400 
401 /**
402  * Records the remote host and port for this connection.
403  *
404  * By default TCP Fast Open is used. This means that this function merely
405  * records the remote host and port, and that the TCP connection establishment
406  * handshake only happens on the first call to otTcpSendByReference(). TCP Fast
407  * Open can be explicitly disabled using @p aFlags, in which case the TCP
408  * connection establishment handshake is initiated immediately.
409  *
410  * @param[in]  aEndpoint  A pointer to the TCP endpoint structure to connect.
411  * @param[in]  aSockName  The IP address and port of the host to which to connect.
412  * @param[in]  aFlags     Flags specifying options for this operation (see enumeration above).
413  *
414  * @retval OT_ERROR_NONE    Successfully completed the operation.
415  * @retval OT_ERROR_FAILED  Failed to complete the operation.
416  *
417  */
418 otError otTcpConnect(otTcpEndpoint *aEndpoint, const otSockAddr *aSockName, uint32_t aFlags);
419 
420 /**
421  * This enumeration defines flags passed to @p otTcpSendByReference.
422  *
423  */
424 enum
425 {
426     OT_TCP_SEND_MORE_TO_COME = 1 << 0,
427 };
428 
429 /**
430  * Adds data referenced by the linked buffer pointed to by @p aBuffer to the
431  * send buffer.
432  *
433  * Upon a successful call to this function, the linked buffer and data it
434  * references are owned by the TCP stack; they should not be modified by the
435  * application until a "send done" callback returns ownership of those objects
436  * to the application. It is acceptable to call this function to add another
437  * linked buffer to the send queue, even if the "send done" callback for a
438  * previous invocation of this function has not yet fired.
439  *
440  * Note that @p aBuffer should not be chained; its mNext field should be
441  * NULL. If additional data will be added right after this call, then the
442  * OT_TCP_SEND_MORE_TO_COME flag should be used as a hint to the TCP
443  * implementation.
444  *
445  * @param[in]  aEndpoint  A pointer to the TCP endpoint structure representing the TCP endpoint on which to send data.
446  * @param[in]  aBuffer    A pointer to the linked buffer chain referencing data to add to the send buffer.
447  * @param[in]  aFlags     Flags specifying options for this operation (see enumeration above).
448  *
449  * @retval OT_ERROR_NONE    Successfully added data to the send buffer.
450  * @retval OT_ERROR_FAILED  Failed to add data to the send buffer.
451  *
452  */
453 otError otTcpSendByReference(otTcpEndpoint *aEndpoint, otLinkedBuffer *aBuffer, uint32_t aFlags);
454 
455 /**
456  * Adds data to the send buffer by extending the length of the final
457  * otLinkedBuffer in the send buffer by the specified amount.
458  *
459  * If the send buffer is empty, then the operation fails.
460  *
461  * @param[in]  aEndpoint  A pointer to the TCP endpoint structure representing the TCP endpoint on which to send data.
462  * @param[in]  aNumBytes  The number of bytes by which to extend the length of the final linked buffer.
463  * @param[in]  aFlags     Flags specifying options for this operation (see enumeration above).
464  *
465  * @retval OT_ERROR_NONE    Successfully added data to the send buffer.
466  * @retval OT_ERROR_FAILED  Failed to add data to the send buffer.
467  *
468  */
469 otError otTcpSendByExtension(otTcpEndpoint *aEndpoint, size_t aNumBytes, uint32_t aFlags);
470 
471 /**
472  * Provides the application with a linked buffer chain referencing data
473  * currently in the TCP receive buffer.
474  *
475  * The linked buffer chain is valid until the "receive ready" callback is next
476  * invoked, or until the next call to otTcpReceiveContiguify() or
477  * otTcpCommitReceive().
478  *
479  * @param[in]   aEndpoint  A pointer to the TCP endpoint structure representing the TCP endpoint on which to receive
480  *                         data.
481  * @param[out]  aBuffer    A pointer to the linked buffer chain referencing data currently in the receive buffer.
482  *
483  * @retval OT_ERROR_NONE    Successfully completed the operation.
484  * @retval OT_ERROR_FAILED  Failed to complete the operation.
485  *
486  */
487 otError otTcpReceiveByReference(otTcpEndpoint *aEndpoint, const otLinkedBuffer **aBuffer);
488 
489 /**
490  * Reorganizes the receive buffer to be entirely contiguous in memory.
491  *
492  * This is optional; an application can simply traverse the linked buffer
493  * chain obtained by calling @p otTcpReceiveByReference. Some
494  * applications may wish to call this function to make the receive buffer
495  * contiguous to simplify their data processing, but this comes at the expense
496  * of CPU time to reorganize the data in the receive buffer.
497  *
498  * @param[in]   aEndpoint  A pointer to the TCP endpoint whose receive buffer to reorganize.
499  *
500  * @retval OT_ERROR_NONE    Successfully completed the operation.
501  * @retval OT_ERROR_FAILED  Failed to complete the operation.
502  *
503  */
504 otError otTcpReceiveContiguify(otTcpEndpoint *aEndpoint);
505 
506 /**
507  * Informs the TCP stack that the application has finished processing
508  * @p aNumBytes bytes of data at the start of the receive buffer and that the
509  * TCP stack need not continue maintaining those bytes in the receive buffer.
510  *
511  * @param[in]  aEndpoint  A pointer to the TCP endpoint structure representing the TCP endpoint on which to receive
512  *                        data.
513  * @param[in]  aNumBytes  The number of bytes consumed.
514  * @param[in]  aFlags     Flags specifying options for this operation (none yet).
515  *
516  * @retval OT_ERROR_NONE    Successfully completed the receive operation.
517  * @retval OT_ERROR_FAILED  Failed to complete the receive operation.
518  *
519  */
520 otError otTcpCommitReceive(otTcpEndpoint *aEndpoint, size_t aNumBytes, uint32_t aFlags);
521 
522 /**
523  * Informs the connection peer that this TCP endpoint will not send more data.
524  *
525  * This should be used when the application has no more data to send to the
526  * connection peer. For this connection, future reads on the connection peer
527  * will result in the "end of stream" condition, and future writes on this
528  * connection endpoint will fail.
529  *
530  * The "end of stream" condition only applies after any data previously
531  * provided to the TCP stack to send out has been received by the connection
532  * peer.
533  *
534  * @param[in]  aEndpoint  A pointer to the TCP endpoint structure representing the TCP endpoint to shut down.
535  *
536  * @retval OT_ERROR_NONE    Successfully queued the "end of stream" condition for transmission.
537  * @retval OT_ERROR_FAILED  Failed to queue the "end of stream" condition for transmission.
538  *
539  */
540 otError otTcpSendEndOfStream(otTcpEndpoint *aEndpoint);
541 
542 /**
543  * Forcibly ends the TCP connection associated with this TCP endpoint.
544  *
545  * This immediately makes the TCP endpoint free for use for another connection
546  * and empties the send and receive buffers, transferring ownership of any data
547  * provided by the application in otTcpSendByReference() and
548  * otTcpSendByExtension() calls back to the application. The TCP endpoint's
549  * callbacks and memory for the receive buffer remain associated with the
550  * TCP endpoint.
551  *
552  * @param[in]  aEndpoint  A pointer to the TCP endpoint structure representing the TCP endpoint to abort.
553  *
554  * @retval OT_ERROR_NONE    Successfully aborted the TCP endpoint's connection.
555  * @retval OT_ERROR_FAILED  Failed to abort the TCP endpoint's connection.
556  *
557  */
558 otError otTcpAbort(otTcpEndpoint *aEndpoint);
559 
560 /**
561  * Deinitializes this TCP endpoint.
562  *
563  * This means that OpenThread no longer keeps track of this TCP endpoint and
564  * deallocates all resources it has internally allocated for this TCP endpoint.
565  * The application can reuse the memory backing the TCP endpoint as it sees fit.
566  *
567  * If it corresponds to a live TCP connection, the connection is terminated
568  * unceremoniously (as in otTcpAbort()). All resources the application has
569  * provided for this TCP endpoint (linked buffers for the send buffer, memory
570  * for the receive buffer, the @p aEndpoint structure itself, etc.) are
571  * immediately returned to the application.
572  *
573  * @param[in]  aEndpoint  A pointer to the TCP endpoint structure to deinitialize.
574  *
575  * @retval OT_ERROR_NONE    Successfully deinitialized the TCP endpoint.
576  * @retval OT_ERROR_FAILED  Failed to deinitialize the TCP endpoint.
577  *
578  */
579 otError otTcpEndpointDeinitialize(otTcpEndpoint *aEndpoint);
580 
581 struct otTcpListener;
582 typedef struct otTcpListener otTcpListener;
583 
584 /**
585  * This enumeration defines incoming connection actions.
586  *
587  * This is used in otTcpAcceptReady() callback.
588  *
589  */
590 typedef enum otTcpIncomingConnectionAction
591 {
592     OT_TCP_INCOMING_CONNECTION_ACTION_ACCEPT, ///< Accept the incoming connection.
593     OT_TCP_INCOMING_CONNECTION_ACTION_DEFER,  ///< Defer (silently ignore) the incoming connection.
594     OT_TCP_INCOMING_CONNECTION_ACTION_REFUSE, ///< Refuse the incoming connection.
595 } otTcpIncomingConnectionAction;
596 
597 /**
598  * This callback indicates that an incoming connection that matches this TCP
599  * listener has arrived.
600  *
601  * The typical response is for the application to accept the incoming
602  * connection. It does so by populating @p aAcceptInto with a pointer to the
603  * otTcpEndpoint into which to accept the incoming connection. This
604  * otTcpEndpoint must already be initialized using otTcpEndpointInitialize().
605  * Then, the application returns OT_TCP_INCOMING_CONNECTION_ACTION_ACCEPT.
606  *
607  * Alternatively, the application can decline to accept the incoming
608  * connection. There are two ways for the application to do this. First, if the
609  * application returns OT_TCP_INCOMING_CONNECTION_ACTION_DEFER, then OpenThread
610  * silently ignores the connection establishment request; the connection peer
611  * will likely retransmit the request, at which point the callback will be
612  * called again. This is valuable if resources are not presently available to
613  * accept the connection, but they may be available when the connection peer
614  * retransmits its connection establishment attempt. Second, if the application
615  * returns OT_TCP_INCOMING_CONNECTION_ACTION_REFUSE, then OpenThread sends a
616  * "connection refused" message to the host that attempted to establish a
617  * connection. If the application declines the incoming connection, it is not
618  * required to populate @p aAcceptInto.
619  *
620  * @param[in]   aListener    The TCP listener that matches the incoming connection.
621  * @param[in]   aPeer        The host and port from which the incoming connection originates.
622  * @param[out]  aAcceptInto  The TCP endpoint into which to accept the incoming connection.
623  *
624  * @returns  Description of how to handle the incoming connection.
625  *
626  */
627 typedef otTcpIncomingConnectionAction (*otTcpAcceptReady)(otTcpListener *   aListener,
628                                                           const otSockAddr *aPeer,
629                                                           otTcpEndpoint **  aAcceptInto);
630 
631 /**
632  * This callback indicates that the TCP connection is now ready for two-way
633  * communication.
634  *
635  * In the case of TCP Fast Open, this may be before the TCP
636  * connection handshake has actually completed. The application is provided
637  * with the context pointers both for the TCP listener that accepted the
638  * connection and the TCP endpoint into which it was accepted. The provided
639  * context is the one associated with the TCP listener.
640  *
641  * @param[in]  aListener  The TCP listener that matches the incoming connection.
642  * @param[in]  aEndpoint  The TCP endpoint into which the incoming connection was accepted.
643  * @param[in]  aPeer      the host and port from which the incoming connection originated.
644  *
645  */
646 typedef void (*otTcpAcceptDone)(otTcpListener *aListener, otTcpEndpoint *aEndpoint, const otSockAddr *aPeer);
647 
648 /**
649  * OT_TCP_LISTENER_TCB_SIZE_BASE and OT_TCP_LISTENER_TCB_NUM_POINTERS are
650  * chosen such that the mTcbListener field of otTcpListener has the same size
651  * as struct tcpcb_listen in TCPlp. This is necessary because the mTcbListen
652  * field, though opaque in its declaration, is treated as struct tcpcb in the
653  * TCP implementation.
654  */
655 #define OT_TCP_LISTENER_TCB_SIZE_BASE 16
656 #define OT_TCP_LISTENER_TCB_NUM_PTR 3
657 
658 /**
659  * This structure represents a TCP listener.
660  *
661  * A TCP listener is used to listen for and accept incoming TCP connections.
662  *
663  * The application should not inspect the fields of this structure directly; it
664  * should only interact with it via the TCP API functions whose signatures are
665  * provided in this file.
666  *
667  */
668 struct otTcpListener
669 {
670     union
671     {
672         uint8_t mSize[OT_TCP_LISTENER_TCB_SIZE_BASE + OT_TCP_LISTENER_TCB_NUM_PTR * sizeof(void *)];
673         void *  mAlign;
674     } mTcbListen;
675 
676     struct otTcpListener *mNext;    ///< A pointer to the next TCP listener (internal use only)
677     void *                mContext; ///< A pointer to application-specific context
678 
679     otTcpAcceptReady mAcceptReadyCallback; ///< "Accept ready" callback function
680     otTcpAcceptDone  mAcceptDoneCallback;  ///< "Accept done" callback function
681 };
682 
683 /**
684  * This structure contains arguments to the otTcpListenerInitialize() function.
685  *
686  */
687 typedef struct otTcpListenerInitializeArgs
688 {
689     void *mContext; ///< Pointer to application-specific context
690 
691     otTcpAcceptReady mAcceptReadyCallback; ///< "Accept ready" callback function
692     otTcpAcceptDone  mAcceptDoneCallback;  ///< "Accept done" callback function
693 } otTcpListenerInitializeArgs;
694 
695 /**
696  * Initializes a TCP listener.
697  *
698  * Calling this function causes OpenThread to keep track of the TCP listener
699  * and store and retrieve TCP data inside @p aListener. The application should
700  * refrain from directly accessing or modifying the fields in @p aListener. If
701  * the application needs to reclaim the memory backing @p aListener, it should
702  * call otTcpListenerDeinitialize().
703  *
704  * @param[in]  aInstance  A pointer to an OpenThread instance.
705  * @param[in]  aListener  A pointer to a TCP listener structure.
706  * @param[in]  aArgs      A pointer to a structure of arguments.
707  *
708  * @retval OT_ERROR_NONE    Successfully opened the TCP listener.
709  * @retval OT_ERROR_FAILED  Failed to open the TCP listener.
710  *
711  */
712 otError otTcpListenerInitialize(otInstance *                       aInstance,
713                                 otTcpListener *                    aListener,
714                                 const otTcpListenerInitializeArgs *aArgs);
715 
716 /**
717  * Obtains the otInstance that was associated with @p aListener upon
718  * initialization.
719  *
720  * @param[in]  aListener  The TCP listener whose instance to obtain.
721  *
722  * @returns  The otInstance pointer associated with @p aListener.
723  *
724  */
725 otInstance *otTcpListenerGetInstance(otTcpListener *aListener);
726 
727 /**
728  * Obtains the context pointer that was associated with @p aListener upon
729  * initialization.
730  *
731  * @param[in]  aListener  The TCP listener whose context to obtain.
732  *
733  * @returns  The context pointer associated with @p aListener.
734  *
735  */
736 void *otTcpListenerGetContext(otTcpListener *aListener);
737 
738 /**
739  * Causes incoming TCP connections that match the specified IP address and port
740  * to trigger this TCP listener's callbacks.
741  *
742  * @param[in]  aListener  A pointer to the TCP listener structure that should begin listening.
743  * @param[in]  aSockName  The address and port on which to listen for incoming connections.
744  *
745  * @retval OT_ERROR_NONE    Successfully initiated listening on the TCP listener.
746  * @retval OT_ERROR_FAILED  Failed to initiate listening on the TCP listener.
747  *
748  */
749 otError otTcpListen(otTcpListener *aListener, const otSockAddr *aSockName);
750 
751 /**
752  * Causes this TCP listener to stop listening for incoming connections.
753  *
754  * @param[in]  aListener  A pointer to the TCP listener structure that should stop listening.
755  *
756  * @retval OT_ERROR_NONE    Successfully stopped listening on the TCP listener.
757  * @retval OT_ERROR_FAILED  Failed to stop listening on the TCP listener.
758  *
759  */
760 otError otTcpStopListening(otTcpListener *aListener);
761 
762 /**
763  * Deinitializes this TCP listener.
764  *
765  * This means that OpenThread no longer keeps track of this TCP listener and
766  * deallocates all resources it has internally allocated for this TCP listener.
767  * The application can reuse the memory backing the TCP listener as it sees
768  * fit.
769  *
770  * If the TCP listener is currently listening, it stops listening.
771  *
772  * @param[in]  aListener  A pointer to the TCP listener structure to deinitialize.
773  *
774  * @retval OT_ERROR_NONE    Successfully deinitialized the TCP listener.
775  * @retval OT_ERROR_FAILED  Failed to deinitialize the TCP listener.
776  *
777  */
778 otError otTcpListenerDeinitialize(otTcpListener *aListener);
779 
780 /**
781  * @}
782  *
783  */
784 
785 #ifdef __cplusplus
786 } // extern "C"
787 #endif
788 
789 #endif // OPENTHREAD_TCP_H_
790