mirror of
https://github.com/espressif/openthread.git
synced 2026-08-10 12:47:47 +00:00
[tcp] add TCP circular send buffer API (#7584)
This commit introduces an API for the circular buffer library. While we ultimately converged on the linked-buffer-based API that has been merged into OpenThread, it was also discussed that we should provide a circular buffer library that is implemented on top of the linked buffer API, to support applications that find a circular-buffer-based interface easier to use.
This commit is contained in:
@@ -84,6 +84,7 @@ openthread_headers = \
|
||||
openthread/srp_server.h \
|
||||
openthread/tasklet.h \
|
||||
openthread/tcp.h \
|
||||
openthread/tcp_ext.h \
|
||||
openthread/thread.h \
|
||||
openthread/thread_ftd.h \
|
||||
openthread/trel.h \
|
||||
|
||||
@@ -109,6 +109,7 @@ source_set("openthread") {
|
||||
"srp_server.h",
|
||||
"tasklet.h",
|
||||
"tcp.h",
|
||||
"tcp_ext.h",
|
||||
"thread.h",
|
||||
"thread_ftd.h",
|
||||
"trel.h",
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Copyright (c) 2022, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief
|
||||
* This file defines extensions to the OpenThread TCP API.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OPENTHREAD_TCP_EXT_H_
|
||||
#define OPENTHREAD_TCP_EXT_H_
|
||||
|
||||
#include <openthread/tcp.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup api-tcp-ext
|
||||
*
|
||||
* @brief
|
||||
* This module includes easy-to-use abstractions on top of the base TCP API.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* This structure represents a circular send buffer for use with a TCP endpoint.
|
||||
*
|
||||
* Using a circular send buffer is optional. Applications can use a TCP
|
||||
* endpoint to send data by managing otLinkedBuffers directly. However, some
|
||||
* applications may find it more convenient to have a circular send buffer;
|
||||
* such applications can call otTcpCircularSendBufferWrite() to "attach" a
|
||||
* circular send buffer to a TCP endpoint and send out data on that TCP
|
||||
* endpoint, relying on the circular send buffer to manage the underlying
|
||||
* otLinkedBuffers.
|
||||
*
|
||||
* otTcpCircularSendBuffer is implemented on top of the otLinkedBuffer-based
|
||||
* API provided by an otTcpEndpoint. Once attached to an otTcpEndpoint, an
|
||||
* otTcpCircularSendBuffer performs all the work of managing otLinkedBuffers
|
||||
* for the connection. This means that, once an otTcpCircularSendBuffer is
|
||||
* attached to an otTcpEndpoint, the application should not call
|
||||
* otTcpSendByReference() or otTcpSendByExtension() on that otTcpEndpoint.
|
||||
* Instead, the application should use otTcpCircularSendBufferWrite() to add
|
||||
* data to the send buffer.
|
||||
*
|
||||
* The otTcpForwardProgress() callback is the intended way for users to learn
|
||||
* when space becomes available in the circular send buffer. On an
|
||||
* otTcpEndpoint to which an otTcpCircularSendBuffer is attached, the
|
||||
* application MUST install an otTcpForwardProgress() callback and call
|
||||
* otTcpCircularSendBufferHandleForwardProgress() on the attached
|
||||
* otTcpCircularSendBuffer at the start of the callback function. It is
|
||||
* recommended that the user NOT install an otTcpSendDone() callback, as all
|
||||
* management of otLinkedBuffers is handled by the circular send buffer.
|
||||
*
|
||||
* The application should not inspect the fields of this structure directly; it
|
||||
* should only interact with it via the TCP Circular Send Buffer API functions
|
||||
* whose signature are provided in this file.
|
||||
*
|
||||
*/
|
||||
typedef struct otTcpCircularSendBuffer
|
||||
{
|
||||
const uint8_t *mDataBuffer; ///< Pointer to data in the circular send buffer
|
||||
size_t mCapacity; ///< Length of the circular send buffer
|
||||
size_t mStartIndex; ///< Index of the first valid byte in the send buffer
|
||||
size_t mCapacityUsed; ///< Number of bytes stored in the send buffer
|
||||
|
||||
otLinkedBuffer mSendLinks[2];
|
||||
uint8_t mFirstSendLinkIndex;
|
||||
} otTcpCircularSendBuffer;
|
||||
|
||||
/**
|
||||
* Initializes a TCP circular send buffer.
|
||||
*
|
||||
* @param[in] aSendBuffer A pointer to the TCP circular send buffer to initialize.
|
||||
* @param[in] aDataBuffer A pointer to memory to use to store data in the TCP circular send buffer.
|
||||
* @param[in] aCapacity The capacity, in bytes, of the TCP circular send buffer, which must equal the size of
|
||||
* the memory pointed to by @p aDataBuffer .
|
||||
*/
|
||||
void otTcpCircularSendBufferInitialize(otTcpCircularSendBuffer *aSendBuffer, void *aDataBuffer, size_t aCapacity);
|
||||
|
||||
/**
|
||||
* Sends out data on a TCP endpoint, using the provided TCP circular send
|
||||
* buffer to manage buffering.
|
||||
*
|
||||
* Once this function is called, @p aSendBuffer and @p aEndpoint are considered
|
||||
* "attached" to each other. While they are attached, ALL send operations for
|
||||
* @p aEndpoint must be made using @p aSendBuffer and ALL operations on
|
||||
* @p aSendBuffer must be associated with @p aEndpoint .
|
||||
*
|
||||
* The only way to "detach" a TCP circular send buffer and a TCP endpoint is to
|
||||
* wait for the send buffer to become completely empty. This can happen in two
|
||||
* ways: (1) all data in the send buffer is sent and acknowledged in the normal
|
||||
* course of TCP protocol operation, or (2) the connection is terminated.
|
||||
*
|
||||
* The recommended usage pattern is to use a single TCP circular send buffer
|
||||
* with a TCP endpoint, and to send data on that TCP endpoint only via its
|
||||
* associated TCP circular buffer. This recommended usage pattern sidesteps the
|
||||
* issues described above by always using a TCP endpoint and TCP circular send
|
||||
* buffer together.
|
||||
*
|
||||
* If the circular send buffer reaches capacity, only a prefix of the provided
|
||||
* data is copied into the circular send buffer.
|
||||
*
|
||||
* @param[in] aEndpoint The TCP endpoint on which to send out data.
|
||||
* @param[in] aSendBuffer The TCP circular send buffer into which to copy data.
|
||||
* @param[in] aData A pointer to data to copy into the TCP circular send buffer.
|
||||
* @param[in] aLength The length of the data pointed to by @p aData to copy into the TCP circular send buffer.
|
||||
* @param[out] aWritten Populated with the amount of data copied into the send buffer, which might be less than
|
||||
* @p aLength if the send buffer reaches capacity.
|
||||
*
|
||||
* @returns OT_ERROR_NONE Successfully copied data into the send buffer and sent it on the TCP endpoint.
|
||||
* @returns OT_ERROR_FAILED Failed to send out data on the TCP endpoint.
|
||||
*/
|
||||
otError otTcpCircularSendBufferWrite(otTcpEndpoint * aEndpoint,
|
||||
otTcpCircularSendBuffer *aSendBuffer,
|
||||
void * aData,
|
||||
size_t aLength,
|
||||
size_t * aWritten);
|
||||
|
||||
/**
|
||||
* Performs circular-send-buffer-specific handling in the otTcpForwardProgress
|
||||
* callback.
|
||||
*
|
||||
* The application is expected to install an otTcpForwardProgress() callback on
|
||||
* the otTcpEndpoint, and call this function at the start of the callback
|
||||
* function for circular-send-buffer-specific processing.
|
||||
*
|
||||
* In the callback function, the application can determine the amount of free
|
||||
* space in the circular send buffer by calling
|
||||
* otTcpCircularSendBufferFreeSpace(), or by comparing @p aInSendBuffer with
|
||||
* the send buffer's capacity, chosen by the user when calling
|
||||
* otTcpCircularSendBufferInitialize().
|
||||
*
|
||||
* @param[in] aSendBuffer A pointer to the TCP circular send buffer for the endpoint for which
|
||||
* otTcpForwardProgress() was invoked.
|
||||
* @param[in] aInSendBuffer Value of @p aInSendBuffer passed to the otTcpForwardProgress() callback.
|
||||
*/
|
||||
void otTcpCircularSendBufferHandleForwardProgress(otTcpCircularSendBuffer *aSendBuffer, size_t aInSendBuffer);
|
||||
|
||||
/**
|
||||
* Returns the amount of free space in the TCP circular send buffer.
|
||||
*
|
||||
* This operation will always succeed.
|
||||
*
|
||||
* @param[in] aSendBuffer A pointer to the TCP circular send buffer whose amount of free space to return.
|
||||
*
|
||||
* @return The amount of free space in the send buffer.
|
||||
*/
|
||||
size_t otTcpCircularSendBufferFreeSpace(otTcpCircularSendBuffer *aSendBuffer);
|
||||
|
||||
/**
|
||||
* Forcibly discards all data in the circular send buffer.
|
||||
*
|
||||
* The application is expected to call this function when a TCP connection is
|
||||
* terminated unceremoniously (e.g., if the application calls
|
||||
* otTcpEndpointAbort() or is informed of a reset connection via the
|
||||
* otTcpConnectionLost() callback).
|
||||
*
|
||||
* Calling this function on a nonempty TCP circular send buffer attached to a
|
||||
* TCP endpoint results in undefined behavior.
|
||||
*
|
||||
* @param[in] aSendBuffer The TCP circular send buffer whose data to discard.
|
||||
*/
|
||||
void otTcpCircularSendBufferForceDiscardAll(otTcpCircularSendBuffer *aSendBuffer);
|
||||
|
||||
/**
|
||||
* Deinitializes a TCP circular send buffer, detaching it if attached.
|
||||
*
|
||||
* If the TCP circular send buffer is not empty, then this operation will fail.
|
||||
*
|
||||
* @param[in] aSendBuffer The TCP circular send buffer to deinitialize.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully deinitialize the TCP circular send buffer.
|
||||
* @retval OT_ERROR_BUSY Circular buffer contains data and cannot be deinitialized.
|
||||
*/
|
||||
otError otTcpCircularSendBufferDeinitialize(otTcpCircularSendBuffer *aSendBuffer);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // OPENTHREAD_TCP_EXT_H_
|
||||
Reference in New Issue
Block a user