mirror of
https://github.com/espressif/openthread.git
synced 2026-06-05 21:14:49 +00:00
[tcp] add rewrite of TCPlp's interface code to support OpenThread's TCP API (#7190)
This commit is contained in:
@@ -53,7 +53,7 @@ extern "C" {
|
||||
* @note This number versions both OpenThread platform and user APIs.
|
||||
*
|
||||
*/
|
||||
#define OPENTHREAD_API_VERSION (187)
|
||||
#define OPENTHREAD_API_VERSION (188)
|
||||
|
||||
/**
|
||||
* @addtogroup api-instance
|
||||
|
||||
+39
-10
@@ -191,6 +191,16 @@ typedef enum otTcpDisconnectedReason
|
||||
*/
|
||||
typedef void (*otTcpDisconnected)(otTcpEndpoint *aEndpoint, otTcpDisconnectedReason aReason);
|
||||
|
||||
/**
|
||||
* OT_TCP_ENDPOINT_TCB_SIZE_BASE and OT_TCP_ENDPOINT_TCB_NUM_POINTERS are
|
||||
* chosen such that the mTcb field of otTcpEndpoint has the same size as
|
||||
* struct tcpcb in TCPlp. This is necessary because the mTcb field, although
|
||||
* opaque in its declaration, is treated as struct tcpcb in the TCP
|
||||
* implementation.
|
||||
*/
|
||||
#define OT_TCP_ENDPOINT_TCB_SIZE_BASE 368
|
||||
#define OT_TCP_ENDPOINT_TCB_NUM_PTR 36
|
||||
|
||||
/**
|
||||
* This structure represents a TCP endpoint.
|
||||
*
|
||||
@@ -205,9 +215,14 @@ typedef void (*otTcpDisconnected)(otTcpEndpoint *aEndpoint, otTcpDisconnectedRea
|
||||
*/
|
||||
struct otTcpEndpoint
|
||||
{
|
||||
struct otTcpEndpoint *mNext; ///< A pointer to the next TCP endpoint (internal use only)
|
||||
otInstance * mInstance; ///< A pointer to the OpenThread instance associated with this TCP endpoint
|
||||
void * mContext; ///< A pointer to application-specific context
|
||||
union
|
||||
{
|
||||
uint8_t mSize[OT_TCP_ENDPOINT_TCB_SIZE_BASE + OT_TCP_ENDPOINT_TCB_NUM_PTR * sizeof(void *)];
|
||||
uint64_t mAlign;
|
||||
} mTcb;
|
||||
|
||||
struct otTcpEndpoint *mNext; ///< A pointer to the next TCP endpoint (internal use only)
|
||||
void * mContext; ///< A pointer to application-specific context
|
||||
|
||||
otTcpEstablished mEstablishedCallback; ///< "Established" callback function
|
||||
otTcpSendDone mSendDoneCallback; ///< "Send done" callback function
|
||||
@@ -217,7 +232,8 @@ struct otTcpEndpoint
|
||||
|
||||
uint32_t mTimers[4];
|
||||
|
||||
/* Other implementation-defined fields go here. */
|
||||
otLinkedBuffer mReceiveLinks[2];
|
||||
otSockAddr mSockAddr;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -438,7 +454,7 @@ otError otTcpSendByExtension(otTcpEndpoint *aEndpoint, size_t aNumBytes, uint32_
|
||||
* @retval OT_ERROR_FAILED Failed to complete the operation.
|
||||
*
|
||||
*/
|
||||
otError otTcpReceiveByReference(const otTcpEndpoint *aEndpoint, const otLinkedBuffer **aBuffer);
|
||||
otError otTcpReceiveByReference(otTcpEndpoint *aEndpoint, const otLinkedBuffer **aBuffer);
|
||||
|
||||
/**
|
||||
* Reorganizes the receive buffer to be entirely contiguous in memory.
|
||||
@@ -598,6 +614,16 @@ typedef otTcpIncomingConnectionAction (*otTcpAcceptReady)(otTcpListener * aLis
|
||||
*/
|
||||
typedef void (*otTcpAcceptDone)(otTcpListener *aListener, otTcpEndpoint *aEndpoint, const otSockAddr *aPeer);
|
||||
|
||||
/**
|
||||
* OT_TCP_LISTENER_TCB_SIZE_BASE and OT_TCP_LISTENER_TCB_NUM_POINTERS are
|
||||
* chosen such that the mTcbListener field of otTcpListener has the same size
|
||||
* as struct tcpcb_listen in TCPlp. This is necessary because the mTcbListen
|
||||
* field, though opaque in its declaration, is treated as struct tcpcb in the
|
||||
* TCP implementation.
|
||||
*/
|
||||
#define OT_TCP_LISTENER_TCB_SIZE_BASE 16
|
||||
#define OT_TCP_LISTENER_TCB_NUM_PTR 3
|
||||
|
||||
/**
|
||||
* This structure represents a TCP listener.
|
||||
*
|
||||
@@ -610,14 +636,17 @@ typedef void (*otTcpAcceptDone)(otTcpListener *aListener, otTcpEndpoint *aEndpoi
|
||||
*/
|
||||
struct otTcpListener
|
||||
{
|
||||
struct otTcpListener *mNext; ///< A pointer to the next TCP listener (internal use only)
|
||||
otInstance * mInstance; ///< A pointer to the OpenThread instance associated with this TCP listener
|
||||
void * mContext; ///< A pointer to application-specific context
|
||||
union
|
||||
{
|
||||
uint8_t mSize[OT_TCP_LISTENER_TCB_SIZE_BASE + OT_TCP_LISTENER_TCB_NUM_PTR * sizeof(void *)];
|
||||
void * mAlign;
|
||||
} mTcbListen;
|
||||
|
||||
struct otTcpListener *mNext; ///< A pointer to the next TCP listener (internal use only)
|
||||
void * mContext; ///< A pointer to application-specific context
|
||||
|
||||
otTcpAcceptReady mAcceptReadyCallback; ///< "Accept ready" callback function
|
||||
otTcpAcceptDone mAcceptDoneCallback; ///< "Accept done" callback function
|
||||
|
||||
/* Other implementation-defined fields go here. */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -87,7 +87,7 @@ otError otTcpSendByExtension(otTcpEndpoint *aEndpoint, size_t aNumBytes, uint32_
|
||||
return AsCoreType(aEndpoint).SendByExtension(aNumBytes, aFlags);
|
||||
}
|
||||
|
||||
otError otTcpReceiveByReference(const otTcpEndpoint *aEndpoint, const otLinkedBuffer **aBuffer)
|
||||
otError otTcpReceiveByReference(otTcpEndpoint *aEndpoint, const otLinkedBuffer **aBuffer)
|
||||
{
|
||||
return AsCoreType(aEndpoint).ReceiveByReference(*aBuffer);
|
||||
}
|
||||
|
||||
+671
-47
@@ -42,11 +42,19 @@
|
||||
#include "common/error.hpp"
|
||||
#include "common/instance.hpp"
|
||||
#include "common/logging.hpp"
|
||||
#include "common/random.hpp"
|
||||
#include "net/checksum.hpp"
|
||||
#include "net/ip6.hpp"
|
||||
#include "net/netif.hpp"
|
||||
|
||||
#include "../../third_party/tcplp/tcplp.h"
|
||||
|
||||
namespace ot {
|
||||
namespace Ip6 {
|
||||
|
||||
using ot::Encoding::BigEndian::HostSwap16;
|
||||
using ot::Encoding::BigEndian::HostSwap32;
|
||||
|
||||
Tcp::Tcp(Instance &aInstance)
|
||||
: InstanceLocator(aInstance)
|
||||
, mTimer(aInstance, Tcp::HandleTimer)
|
||||
@@ -57,7 +65,8 @@ Tcp::Tcp(Instance &aInstance)
|
||||
|
||||
Error Tcp::Endpoint::Initialize(Instance &aInstance, otTcpEndpointInitializeArgs &aArgs)
|
||||
{
|
||||
Error error;
|
||||
Error error;
|
||||
struct tcpcb &tp = GetTcb();
|
||||
|
||||
SuccessOrExit(error = aInstance.Get<Tcp>().mEndpoints.Add(*this));
|
||||
|
||||
@@ -68,9 +77,30 @@ Error Tcp::Endpoint::Initialize(Instance &aInstance, otTcpEndpointInitializeArgs
|
||||
mReceiveAvailableCallback = aArgs.mReceiveAvailableCallback;
|
||||
mDisconnectedCallback = aArgs.mDisconnectedCallback;
|
||||
|
||||
mInstance = &aInstance;
|
||||
|
||||
memset(mTimers, 0x00, sizeof(mTimers));
|
||||
memset(&mSockAddr, 0x00, sizeof(mSockAddr));
|
||||
memset(&tp, 0x00, sizeof(tp));
|
||||
|
||||
/*
|
||||
* Initialize buffers --- formerly in initialize_tcb.
|
||||
*/
|
||||
{
|
||||
uint8_t *recvbuf = static_cast<uint8_t *>(aArgs.mReceiveBuffer);
|
||||
size_t recvbuflen = aArgs.mReceiveBufferSize - ((aArgs.mReceiveBufferSize + 8) / 9);
|
||||
uint8_t *reassbmp = recvbuf + recvbuflen;
|
||||
|
||||
lbuf_init(&tp.sendbuf);
|
||||
cbuf_init(&tp.recvbuf, recvbuf, recvbuflen);
|
||||
tp.reassbmp = reassbmp;
|
||||
bmp_init(tp.reassbmp, BITS_TO_BYTES(recvbuflen));
|
||||
}
|
||||
|
||||
tp.accepted_from = nullptr;
|
||||
initialize_tcb(&tp);
|
||||
|
||||
/* Note that we do not need to zero-initialize mReceiveLinks. */
|
||||
|
||||
tp.instance = &aInstance;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -78,57 +108,100 @@ exit:
|
||||
|
||||
Instance &Tcp::Endpoint::GetInstance(void)
|
||||
{
|
||||
return AsCoreType(mInstance);
|
||||
struct tcpcb &tp = GetTcb();
|
||||
|
||||
return AsCoreType(tp.instance);
|
||||
}
|
||||
|
||||
const SockAddr &Tcp::Endpoint::GetLocalAddress(void) const
|
||||
{
|
||||
const struct tcpcb &tp = GetTcb();
|
||||
|
||||
static otSockAddr temp;
|
||||
|
||||
memcpy(&temp.mAddress, &tp.laddr, sizeof(temp.mAddress));
|
||||
temp.mPort = HostSwap16(tp.lport);
|
||||
|
||||
return AsCoreType(&temp);
|
||||
}
|
||||
|
||||
const SockAddr &Tcp::Endpoint::GetPeerAddress(void) const
|
||||
{
|
||||
const struct tcpcb &tp = GetTcb();
|
||||
|
||||
static otSockAddr temp;
|
||||
|
||||
memcpy(&temp.mAddress, &tp.faddr, sizeof(temp.mAddress));
|
||||
temp.mPort = HostSwap16(tp.fport);
|
||||
|
||||
return AsCoreType(&temp);
|
||||
}
|
||||
|
||||
Error Tcp::Endpoint::Bind(const SockAddr &aSockName)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aSockName);
|
||||
Error error;
|
||||
struct tcpcb &tp = GetTcb();
|
||||
|
||||
return kErrorNotImplemented;
|
||||
VerifyOrExit(!AsCoreType(&aSockName.mAddress).IsUnspecified(), error = kErrorInvalidArgs);
|
||||
VerifyOrExit(GetInstance().Get<Tcp>().CanBind(aSockName), error = kErrorInvalidState);
|
||||
|
||||
memcpy(&tp.laddr, &aSockName.mAddress, sizeof(tp.laddr));
|
||||
tp.lport = HostSwap16(aSockName.mPort);
|
||||
error = kErrorNone;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Tcp::Endpoint::Connect(const SockAddr &aSockName, uint32_t aFlags)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aSockName);
|
||||
Error error = kErrorNone;
|
||||
struct tcpcb & tp = GetTcb();
|
||||
struct sockaddr_in6 sin6p;
|
||||
|
||||
OT_UNUSED_VARIABLE(aFlags);
|
||||
|
||||
return kErrorNotImplemented;
|
||||
VerifyOrExit(tp.t_state == TCP6S_CLOSED, error = kErrorInvalidState);
|
||||
|
||||
memcpy(&sin6p.sin6_addr, &aSockName.mAddress, sizeof(sin6p.sin6_addr));
|
||||
sin6p.sin6_port = HostSwap16(aSockName.mPort);
|
||||
error = BsdErrorToOtError(tcp6_usr_connect(&tp, &sin6p));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Tcp::Endpoint::SendByReference(otLinkedBuffer &aBuffer, uint32_t aFlags)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aBuffer);
|
||||
OT_UNUSED_VARIABLE(aFlags);
|
||||
struct tcpcb &tp = GetTcb();
|
||||
|
||||
return kErrorNotImplemented;
|
||||
return BsdErrorToOtError(tcp_usr_send(&tp, (aFlags & OT_TCP_SEND_MORE_TO_COME) != 0, &aBuffer, 0));
|
||||
}
|
||||
|
||||
Error Tcp::Endpoint::SendByExtension(size_t aNumBytes, uint32_t aFlags)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aNumBytes);
|
||||
OT_UNUSED_VARIABLE(aFlags);
|
||||
Error error;
|
||||
bool moreToCome = (aFlags & OT_TCP_SEND_MORE_TO_COME) != 0;
|
||||
struct tcpcb &tp = GetTcb();
|
||||
int bsdError;
|
||||
|
||||
return kErrorNotImplemented;
|
||||
VerifyOrExit(lbuf_head(&tp.sendbuf) != nullptr, error = kErrorInvalidState);
|
||||
|
||||
bsdError = tcp_usr_send(&tp, moreToCome ? 1 : 0, nullptr, aNumBytes);
|
||||
SuccessOrExit(error = BsdErrorToOtError(bsdError));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Tcp::Endpoint::ReceiveByReference(const otLinkedBuffer *&aBuffer) const
|
||||
Error Tcp::Endpoint::ReceiveByReference(const otLinkedBuffer *&aBuffer)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aBuffer);
|
||||
struct tcpcb &tp = GetTcb();
|
||||
|
||||
return kErrorNotImplemented;
|
||||
cbuf_reference(&tp.recvbuf, &mReceiveLinks[0], &mReceiveLinks[1]);
|
||||
aBuffer = &mReceiveLinks[0];
|
||||
|
||||
return kErrorNone;
|
||||
}
|
||||
|
||||
Error Tcp::Endpoint::ReceiveContiguify(void)
|
||||
@@ -138,20 +211,35 @@ Error Tcp::Endpoint::ReceiveContiguify(void)
|
||||
|
||||
Error Tcp::Endpoint::CommitReceive(size_t aNumBytes, uint32_t aFlags)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aNumBytes);
|
||||
Error error = kErrorNone;
|
||||
struct tcpcb &tp = GetTcb();
|
||||
|
||||
OT_UNUSED_VARIABLE(aFlags);
|
||||
|
||||
return kErrorNotImplemented;
|
||||
VerifyOrExit(cbuf_used_space(&tp.recvbuf) >= aNumBytes, error = kErrorFailed);
|
||||
VerifyOrExit(aNumBytes > 0, error = kErrorNone);
|
||||
|
||||
cbuf_pop(&tp.recvbuf, aNumBytes);
|
||||
error = BsdErrorToOtError(tcp_usr_rcvd(&tp));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Tcp::Endpoint::SendEndOfStream(void)
|
||||
{
|
||||
return kErrorNotImplemented;
|
||||
struct tcpcb &tp = GetTcb();
|
||||
|
||||
return BsdErrorToOtError(tcp_usr_shutdown(&tp));
|
||||
}
|
||||
|
||||
Error Tcp::Endpoint::Abort(void)
|
||||
{
|
||||
return kErrorNotImplemented;
|
||||
struct tcpcb &tp = GetTcb();
|
||||
|
||||
tcp_usr_abort(&tp);
|
||||
/* connection_lost will do any reinitialization work for this socket. */
|
||||
return kErrorNone;
|
||||
}
|
||||
|
||||
Error Tcp::Endpoint::Deinitialize(void)
|
||||
@@ -163,25 +251,59 @@ Error Tcp::Endpoint::Deinitialize(void)
|
||||
SuccessOrExit(error = tcp.mEndpoints.Remove(*this));
|
||||
SetNext(nullptr);
|
||||
|
||||
SuccessOrExit(error = Abort());
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
uint8_t Tcp::Endpoint::TimerFlagToIndex(uint8_t aTimerFlag)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aTimerFlag);
|
||||
/*
|
||||
* TODO: Convert from the timer flag provided by TCPlp to the index in
|
||||
* our timers array.
|
||||
*/
|
||||
return 0;
|
||||
uint8_t timerIndex = 0;
|
||||
|
||||
switch (aTimerFlag)
|
||||
{
|
||||
case TT_DELACK:
|
||||
timerIndex = kTimerDelack;
|
||||
break;
|
||||
case TT_REXMT:
|
||||
case TT_PERSIST:
|
||||
timerIndex = kTimerRexmtPersist;
|
||||
break;
|
||||
case TT_KEEP:
|
||||
timerIndex = kTimerKeep;
|
||||
break;
|
||||
case TT_2MSL:
|
||||
timerIndex = kTimer2Msl;
|
||||
break;
|
||||
}
|
||||
|
||||
return timerIndex;
|
||||
}
|
||||
|
||||
bool Tcp::Endpoint::IsTimerActive(uint8_t aTimerIndex)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aTimerIndex);
|
||||
/* TODO: Check whether TCPlp has marked this timer as active. */
|
||||
return false;
|
||||
bool active = false;
|
||||
struct tcpcb *tp = &GetTcb();
|
||||
|
||||
OT_ASSERT(aTimerIndex < kNumTimers);
|
||||
switch (aTimerIndex)
|
||||
{
|
||||
case kTimerDelack:
|
||||
active = tcp_timer_active(tp, TT_DELACK);
|
||||
break;
|
||||
case kTimerRexmtPersist:
|
||||
active = tcp_timer_active(tp, TT_REXMT) || tcp_timer_active(tp, TT_PERSIST);
|
||||
break;
|
||||
case kTimerKeep:
|
||||
active = tcp_timer_active(tp, TT_KEEP);
|
||||
break;
|
||||
case kTimer2Msl:
|
||||
active = tcp_timer_active(tp, TT_2MSL);
|
||||
break;
|
||||
}
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
void Tcp::Endpoint::SetTimer(uint8_t aTimerFlag, uint32_t aDelay)
|
||||
@@ -219,6 +341,9 @@ void Tcp::Endpoint::CancelTimer(uint8_t aTimerFlag)
|
||||
|
||||
bool Tcp::Endpoint::FirePendingTimers(TimeMilli aNow, bool &aHasFutureTimer, TimeMilli &aEarliestFutureExpiry)
|
||||
{
|
||||
bool calledUserCallback = false;
|
||||
struct tcpcb *tp = &GetTcb();
|
||||
|
||||
/*
|
||||
* NOTE: Firing a timer might potentially activate/deactivate other timers.
|
||||
* If timers x and y expire at the same time, but the callback for timer x
|
||||
@@ -242,8 +367,36 @@ bool Tcp::Endpoint::FirePendingTimers(TimeMilli aNow, bool &aHasFutureTimer, Tim
|
||||
|
||||
if (expiry <= aNow)
|
||||
{
|
||||
/* TODO: Call TCPlp's callback for this timer. */
|
||||
/* If a user callback is called, then return true. */
|
||||
/*
|
||||
* If a user callback is called, then return true. For TCPlp,
|
||||
* this only happens if the connection is dropped (e.g., it
|
||||
* times out).
|
||||
*/
|
||||
int dropped;
|
||||
|
||||
switch (timerIndex)
|
||||
{
|
||||
case kTimerDelack:
|
||||
dropped = tcp_timer_delack(tp);
|
||||
break;
|
||||
case kTimerRexmtPersist:
|
||||
if (tcp_timer_active(tp, TT_REXMT))
|
||||
{
|
||||
dropped = tcp_timer_rexmt(tp);
|
||||
}
|
||||
else
|
||||
{
|
||||
dropped = tcp_timer_persist(tp);
|
||||
}
|
||||
break;
|
||||
case kTimerKeep:
|
||||
dropped = tcp_timer_keep(tp);
|
||||
break;
|
||||
case kTimer2Msl:
|
||||
dropped = tcp_timer_2msl(tp);
|
||||
break;
|
||||
}
|
||||
VerifyOrExit(dropped == 0, calledUserCallback = true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -253,12 +406,31 @@ bool Tcp::Endpoint::FirePendingTimers(TimeMilli aNow, bool &aHasFutureTimer, Tim
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
exit:
|
||||
return calledUserCallback;
|
||||
}
|
||||
|
||||
bool Tcp::Endpoint::Matches(const MessageInfo &aMessageInfo) const
|
||||
{
|
||||
bool matches = false;
|
||||
const struct tcpcb *tp = &GetTcb();
|
||||
|
||||
VerifyOrExit(tp->t_state != TCP6S_CLOSED);
|
||||
VerifyOrExit(tp->lport == HostSwap16(aMessageInfo.GetSockPort()));
|
||||
VerifyOrExit(tp->fport == HostSwap16(aMessageInfo.GetPeerPort()));
|
||||
VerifyOrExit(GetLocalIp6Address().IsUnspecified() || GetLocalIp6Address() == aMessageInfo.GetSockAddr());
|
||||
VerifyOrExit(GetForeignIp6Address() == aMessageInfo.GetPeerAddr());
|
||||
|
||||
matches = true;
|
||||
|
||||
exit:
|
||||
return matches;
|
||||
}
|
||||
|
||||
Error Tcp::Listener::Initialize(Instance &aInstance, otTcpListenerInitializeArgs &aArgs)
|
||||
{
|
||||
Error error;
|
||||
Error error;
|
||||
struct tcpcb_listen *tpl = &GetTcbListen();
|
||||
|
||||
SuccessOrExit(error = aInstance.Get<Tcp>().mListeners.Add(*this));
|
||||
|
||||
@@ -266,7 +438,8 @@ Error Tcp::Listener::Initialize(Instance &aInstance, otTcpListenerInitializeArgs
|
||||
mAcceptReadyCallback = aArgs.mAcceptReadyCallback;
|
||||
mAcceptDoneCallback = aArgs.mAcceptDoneCallback;
|
||||
|
||||
mInstance = &aInstance;
|
||||
memset(tpl, 0x00, sizeof(struct tcpcb_listen));
|
||||
tpl->instance = &aInstance;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -274,19 +447,36 @@ exit:
|
||||
|
||||
Instance &Tcp::Listener::GetInstance(void)
|
||||
{
|
||||
return AsCoreType(mInstance);
|
||||
struct tcpcb_listen *tpl = &GetTcbListen();
|
||||
|
||||
return AsCoreType(tpl->instance);
|
||||
}
|
||||
|
||||
Error Tcp::Listener::Listen(const SockAddr &aSockName)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aSockName);
|
||||
Error error;
|
||||
uint16_t port = HostSwap16(aSockName.mPort);
|
||||
struct tcpcb_listen *tpl = &GetTcbListen();
|
||||
|
||||
return kErrorNotImplemented;
|
||||
VerifyOrExit(GetInstance().Get<Tcp>().CanBind(aSockName), error = kErrorInvalidState);
|
||||
|
||||
memcpy(&tpl->laddr, &aSockName.mAddress, sizeof(tpl->laddr));
|
||||
tpl->lport = port;
|
||||
tpl->t_state = TCP6S_LISTEN;
|
||||
error = kErrorNone;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Tcp::Listener::StopListening(void)
|
||||
{
|
||||
return kErrorNotImplemented;
|
||||
struct tcpcb_listen *tpl = &GetTcbListen();
|
||||
|
||||
memset(&tpl->laddr, 0x00, sizeof(tpl->laddr));
|
||||
tpl->lport = 0;
|
||||
tpl->t_state = TCP6S_CLOSED;
|
||||
return kErrorNone;
|
||||
}
|
||||
|
||||
Error Tcp::Listener::Deinitialize(void)
|
||||
@@ -302,27 +492,238 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
bool Tcp::Listener::Matches(const MessageInfo &aMessageInfo) const
|
||||
{
|
||||
bool matches = false;
|
||||
const struct tcpcb_listen *tpl = &GetTcbListen();
|
||||
|
||||
VerifyOrExit(tpl->t_state == TCP6S_LISTEN);
|
||||
VerifyOrExit(tpl->lport == HostSwap16(aMessageInfo.GetSockPort()));
|
||||
VerifyOrExit(GetLocalIp6Address().IsUnspecified() || GetLocalIp6Address() == aMessageInfo.GetSockAddr());
|
||||
|
||||
matches = true;
|
||||
|
||||
exit:
|
||||
return matches;
|
||||
}
|
||||
|
||||
Error Tcp::HandleMessage(ot::Ip6::Header &aIp6Header, Message &aMessage, MessageInfo &aMessageInfo)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aIp6Header);
|
||||
OT_UNUSED_VARIABLE(aMessage);
|
||||
OT_UNUSED_VARIABLE(aMessageInfo);
|
||||
|
||||
Error error = kErrorNotImplemented;
|
||||
|
||||
for (Endpoint &active : mEndpoints)
|
||||
/*
|
||||
* The type uint32_t was chosen for alignment purposes. The size is the
|
||||
* maximum TCP header size, including options.
|
||||
*/
|
||||
uint32_t header[15];
|
||||
|
||||
uint16_t length = aIp6Header.GetPayloadLength();
|
||||
uint8_t headerSize;
|
||||
|
||||
struct ip6_hdr *ip6Header;
|
||||
struct tcphdr * tcpHeader;
|
||||
|
||||
Endpoint *endpoint;
|
||||
Endpoint *endpointPrev;
|
||||
|
||||
Listener *listener;
|
||||
Listener *listenerPrev;
|
||||
|
||||
VerifyOrExit(length == aMessage.GetLength() - aMessage.GetOffset(), error = kErrorParse);
|
||||
VerifyOrExit(length >= sizeof(Tcp::Header), error = kErrorParse);
|
||||
SuccessOrExit(error = aMessage.Read(aMessage.GetOffset() + offsetof(struct tcphdr, th_off_x2), headerSize));
|
||||
headerSize = static_cast<uint8_t>((headerSize >> TH_OFF_SHIFT) << 2);
|
||||
VerifyOrExit(headerSize >= sizeof(struct tcphdr) && headerSize <= sizeof(header) &&
|
||||
static_cast<uint16_t>(headerSize) <= length,
|
||||
error = kErrorParse);
|
||||
SuccessOrExit(error = Checksum::VerifyMessageChecksum(aMessage, aMessageInfo, kProtoTcp));
|
||||
SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), &header[0], headerSize));
|
||||
|
||||
ip6Header = reinterpret_cast<struct ip6_hdr *>(&aIp6Header);
|
||||
tcpHeader = reinterpret_cast<struct tcphdr *>(&header[0]);
|
||||
tcp_fields_to_host(tcpHeader);
|
||||
|
||||
aMessageInfo.mPeerPort = HostSwap16(tcpHeader->th_sport);
|
||||
aMessageInfo.mSockPort = HostSwap16(tcpHeader->th_dport);
|
||||
|
||||
endpoint = mEndpoints.FindMatching(aMessageInfo, endpointPrev);
|
||||
if (endpoint != nullptr)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(active);
|
||||
struct signals sig;
|
||||
int nextAction;
|
||||
struct tcpcb * tp = &endpoint->GetTcb();
|
||||
|
||||
otLinkedBuffer *priorHead = lbuf_head(&tp->sendbuf);
|
||||
|
||||
memset(&sig, 0x00, sizeof(sig));
|
||||
nextAction = tcp_input(ip6Header, tcpHeader, &aMessage, tp, nullptr, &sig);
|
||||
if (nextAction != RELOOKUP_REQUIRED)
|
||||
{
|
||||
ProcessSignals(*endpoint, priorHead, sig);
|
||||
ExitNow();
|
||||
}
|
||||
/* If the matching socket was in the TIME-WAIT state, then we try passive sockets. */
|
||||
}
|
||||
|
||||
for (Listener &passive : mListeners)
|
||||
listener = mListeners.FindMatching(aMessageInfo, listenerPrev);
|
||||
if (listener != nullptr)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(passive);
|
||||
struct tcpcb_listen *tpl = &listener->GetTcbListen();
|
||||
|
||||
tcp_input(ip6Header, tcpHeader, &aMessage, nullptr, tpl, nullptr);
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
tcp_dropwithreset(ip6Header, tcpHeader, nullptr, &InstanceLocator::GetInstance(), length - headerSize,
|
||||
ECONNREFUSED);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void Tcp::ProcessSignals(Endpoint &aEndpoint, otLinkedBuffer *aPriorHead, struct signals &aSignals)
|
||||
{
|
||||
VerifyOrExit(IsInitialized(aEndpoint) && !aEndpoint.IsClosed());
|
||||
if (aEndpoint.mSendDoneCallback != nullptr)
|
||||
{
|
||||
otLinkedBuffer *curr = aPriorHead;
|
||||
|
||||
for (int i = 0; i != aSignals.links_popped; i++)
|
||||
{
|
||||
otLinkedBuffer *next = curr->mNext;
|
||||
|
||||
VerifyOrExit(i == 0 || (IsInitialized(aEndpoint) && !aEndpoint.IsClosed()));
|
||||
|
||||
curr->mNext = nullptr;
|
||||
aEndpoint.mSendDoneCallback(&aEndpoint, curr);
|
||||
curr = next;
|
||||
}
|
||||
}
|
||||
|
||||
VerifyOrExit(IsInitialized(aEndpoint) && !aEndpoint.IsClosed());
|
||||
if (aSignals.conn_established && aEndpoint.mEstablishedCallback != nullptr)
|
||||
{
|
||||
aEndpoint.mEstablishedCallback(&aEndpoint);
|
||||
}
|
||||
|
||||
VerifyOrExit(IsInitialized(aEndpoint) && !aEndpoint.IsClosed());
|
||||
if ((aSignals.recvbuf_notempty || aSignals.rcvd_fin) && aEndpoint.mReceiveAvailableCallback != nullptr)
|
||||
{
|
||||
aEndpoint.mReceiveAvailableCallback(&aEndpoint, cbuf_used_space(&aEndpoint.GetTcb().recvbuf),
|
||||
aEndpoint.GetTcb().reass_fin_index != -1,
|
||||
cbuf_free_space(&aEndpoint.GetTcb().recvbuf));
|
||||
}
|
||||
|
||||
VerifyOrExit(IsInitialized(aEndpoint) && !aEndpoint.IsClosed());
|
||||
if (aEndpoint.GetTcb().t_state == TCP6S_TIME_WAIT && aEndpoint.mDisconnectedCallback != nullptr)
|
||||
{
|
||||
aEndpoint.mDisconnectedCallback(&aEndpoint, OT_TCP_DISCONNECTED_REASON_TIME_WAIT);
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
Error Tcp::BsdErrorToOtError(int aBsdError)
|
||||
{
|
||||
Error error = kErrorFailed;
|
||||
|
||||
switch (aBsdError)
|
||||
{
|
||||
case 0:
|
||||
error = kErrorNone;
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
bool Tcp::CanBind(const SockAddr &aSockName)
|
||||
{
|
||||
uint16_t port = HostSwap16(aSockName.mPort);
|
||||
bool allowed = false;
|
||||
|
||||
for (Endpoint *endpoint = mEndpoints.GetHead(); endpoint != nullptr; endpoint = endpoint->GetNext())
|
||||
{
|
||||
struct tcpcb *tp = &endpoint->GetTcb();
|
||||
|
||||
if (tp->lport == port)
|
||||
{
|
||||
VerifyOrExit(!aSockName.GetAddress().IsUnspecified());
|
||||
VerifyOrExit(!reinterpret_cast<Address *>(&tp->laddr)->IsUnspecified());
|
||||
VerifyOrExit(memcmp(&endpoint->GetTcb().laddr, &aSockName.mAddress, sizeof(tp->laddr)) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
for (Listener *listener = mListeners.GetHead(); listener != nullptr; listener = listener->GetNext())
|
||||
{
|
||||
struct tcpcb_listen *tpl = &listener->GetTcbListen();
|
||||
|
||||
if (tpl->lport == port)
|
||||
{
|
||||
VerifyOrExit(!aSockName.GetAddress().IsUnspecified());
|
||||
VerifyOrExit(!reinterpret_cast<Address *>(&tpl->laddr)->IsUnspecified());
|
||||
VerifyOrExit(memcmp(&tpl->laddr, &aSockName.mAddress, sizeof(tpl->laddr)) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
allowed = true;
|
||||
|
||||
exit:
|
||||
return allowed;
|
||||
}
|
||||
|
||||
bool Tcp::AutoBind(const SockAddr &aPeer, SockAddr &aToBind, bool aBindAddress, bool aBindPort)
|
||||
{
|
||||
bool success;
|
||||
|
||||
if (aBindAddress)
|
||||
{
|
||||
MessageInfo peerInfo;
|
||||
const Netif::UnicastAddress *netifAddress;
|
||||
|
||||
peerInfo.Clear();
|
||||
peerInfo.SetPeerAddr(aPeer.GetAddress());
|
||||
netifAddress = InstanceLocator::GetInstance().Get<Ip6>().SelectSourceAddress(peerInfo);
|
||||
VerifyOrExit(netifAddress != nullptr, success = false);
|
||||
aToBind.GetAddress() = netifAddress->GetAddress();
|
||||
}
|
||||
|
||||
if (aBindPort)
|
||||
{
|
||||
/*
|
||||
* TODO: Use a less naive algorithm to allocate ephemeral ports. For
|
||||
* example, see RFC 6056.
|
||||
*/
|
||||
|
||||
for (uint16_t i = 0; i != kDynamicPortMax - kDynamicPortMin + 1; i++)
|
||||
{
|
||||
aToBind.SetPort(mEphemeralPort);
|
||||
|
||||
if (mEphemeralPort == kDynamicPortMax)
|
||||
{
|
||||
mEphemeralPort = kDynamicPortMin;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEphemeralPort++;
|
||||
}
|
||||
|
||||
if (CanBind(aToBind))
|
||||
{
|
||||
ExitNow(success = true);
|
||||
}
|
||||
}
|
||||
|
||||
ExitNow(success = false);
|
||||
}
|
||||
|
||||
success = CanBind(aToBind);
|
||||
|
||||
exit:
|
||||
return success;
|
||||
}
|
||||
|
||||
void Tcp::HandleTimer(Timer &aTimer)
|
||||
{
|
||||
OT_ASSERT(&aTimer == &aTimer.GetInstance().Get<Tcp>().mTimer);
|
||||
@@ -395,4 +796,227 @@ restart:
|
||||
} // namespace Ip6
|
||||
} // namespace ot
|
||||
|
||||
/*
|
||||
* Implement TCPlp system stubs declared in tcplp.h.
|
||||
*
|
||||
* Because these functions have C linkage, it is important that only one
|
||||
* definition is given for each function name, regardless of the namespace it
|
||||
* in. For example, if we give two definitions of tcplp_sys_new_message, we
|
||||
* will get errors, even if they are in different namespaces. To avoid
|
||||
* confusion, I've put these functions outside of any namespace.
|
||||
*/
|
||||
|
||||
using namespace ot;
|
||||
using namespace ot::Ip6;
|
||||
|
||||
extern "C" {
|
||||
|
||||
otMessage *tcplp_sys_new_message(otInstance *aInstance)
|
||||
{
|
||||
Instance &instance = AsCoreType(aInstance);
|
||||
Message * message = instance.Get<ot::Ip6::Ip6>().NewMessage(0);
|
||||
|
||||
if (message)
|
||||
{
|
||||
message->SetLinkSecurityEnabled(true);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
void tcplp_sys_free_message(otInstance *aInstance, otMessage *aMessage)
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
Message &message = AsCoreType(aMessage);
|
||||
message.Free();
|
||||
}
|
||||
|
||||
void tcplp_sys_send_message(otInstance *aInstance, otMessage *aMessage, otMessageInfo *aMessageInfo)
|
||||
{
|
||||
Instance & instance = AsCoreType(aInstance);
|
||||
Message & message = AsCoreType(aMessage);
|
||||
MessageInfo &info = AsCoreType(aMessageInfo);
|
||||
|
||||
otLogDebgTcp("Sending TCP segment: payload_size = %d", static_cast<int>(message.GetLength()));
|
||||
|
||||
IgnoreError(instance.Get<ot::Ip6::Ip6>().SendDatagram(message, info, kProtoTcp));
|
||||
}
|
||||
|
||||
uint32_t tcplp_sys_get_ticks(void)
|
||||
{
|
||||
return TimerMilli::GetNow().GetValue();
|
||||
}
|
||||
|
||||
uint32_t tcplp_sys_get_millis(void)
|
||||
{
|
||||
return TimerMilli::GetNow().GetValue();
|
||||
}
|
||||
|
||||
void tcplp_sys_set_timer(struct tcpcb *aTcb, uint8_t aTimerFlag, uint32_t aDelay)
|
||||
{
|
||||
Tcp::Endpoint &endpoint = Tcp::Endpoint::FromTcb(*aTcb);
|
||||
endpoint.SetTimer(aTimerFlag, aDelay);
|
||||
}
|
||||
|
||||
void tcplp_sys_stop_timer(struct tcpcb *aTcb, uint8_t aTimerFlag)
|
||||
{
|
||||
Tcp::Endpoint &endpoint = Tcp::Endpoint::FromTcb(*aTcb);
|
||||
endpoint.CancelTimer(aTimerFlag);
|
||||
}
|
||||
|
||||
struct tcpcb *tcplp_sys_accept_ready(struct tcpcb_listen *aTcbListen, struct in6_addr *aAddr, uint16_t aPort)
|
||||
{
|
||||
Tcp::Listener & listener = Tcp::Listener::FromTcbListen(*aTcbListen);
|
||||
Tcp & tcp = listener.GetInstance().Get<Tcp>();
|
||||
struct tcpcb * rv = (struct tcpcb *)-1;
|
||||
otSockAddr addr;
|
||||
otTcpEndpoint * endpointPtr;
|
||||
otTcpIncomingConnectionAction action;
|
||||
|
||||
VerifyOrExit(listener.mAcceptReadyCallback != nullptr);
|
||||
|
||||
memcpy(&addr.mAddress, aAddr, sizeof(addr.mAddress));
|
||||
addr.mPort = HostSwap16(aPort);
|
||||
action = listener.mAcceptReadyCallback(&listener, &addr, &endpointPtr);
|
||||
|
||||
VerifyOrExit(tcp.IsInitialized(listener) && !listener.IsClosed());
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case OT_TCP_INCOMING_CONNECTION_ACTION_ACCEPT:
|
||||
{
|
||||
Tcp::Endpoint &endpoint = AsCoreType(endpointPtr);
|
||||
|
||||
/*
|
||||
* The documentation says that the user must initialize the
|
||||
* endpoint before passing it here, so we do a sanity check to make
|
||||
* sure the endpoint is initialized and closed. That check may not
|
||||
* be necessary, but we do it anyway.
|
||||
*/
|
||||
VerifyOrExit(tcp.IsInitialized(endpoint) && endpoint.IsClosed());
|
||||
|
||||
rv = &endpoint.GetTcb();
|
||||
|
||||
break;
|
||||
}
|
||||
case OT_TCP_INCOMING_CONNECTION_ACTION_DEFER:
|
||||
rv = nullptr;
|
||||
break;
|
||||
case OT_TCP_INCOMING_CONNECTION_ACTION_REFUSE:
|
||||
rv = (struct tcpcb *)-1;
|
||||
break;
|
||||
}
|
||||
|
||||
exit:
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool tcplp_sys_accepted_connection(struct tcpcb_listen *aTcbListen,
|
||||
struct tcpcb * aAccepted,
|
||||
struct in6_addr * aAddr,
|
||||
uint16_t aPort)
|
||||
{
|
||||
Tcp::Listener &listener = Tcp::Listener::FromTcbListen(*aTcbListen);
|
||||
Tcp::Endpoint &endpoint = Tcp::Endpoint::FromTcb(*aAccepted);
|
||||
Tcp & tcp = endpoint.GetInstance().Get<Tcp>();
|
||||
bool accepted = true;
|
||||
|
||||
if (listener.mAcceptDoneCallback != nullptr)
|
||||
{
|
||||
otSockAddr addr;
|
||||
|
||||
memcpy(&addr.mAddress, aAddr, sizeof(addr.mAddress));
|
||||
addr.mPort = HostSwap16(aPort);
|
||||
listener.mAcceptDoneCallback(&listener, &endpoint, &addr);
|
||||
|
||||
if (!tcp.IsInitialized(endpoint) || endpoint.IsClosed())
|
||||
{
|
||||
accepted = false;
|
||||
}
|
||||
}
|
||||
|
||||
return accepted;
|
||||
}
|
||||
|
||||
void tcplp_sys_connection_lost(struct tcpcb *aTcb, uint8_t aErrNum)
|
||||
{
|
||||
Tcp::Endpoint &endpoint = Tcp::Endpoint::FromTcb(*aTcb);
|
||||
|
||||
if (endpoint.mDisconnectedCallback != nullptr)
|
||||
{
|
||||
otTcpDisconnectedReason reason;
|
||||
|
||||
switch (aErrNum)
|
||||
{
|
||||
case CONN_LOST_NORMAL:
|
||||
reason = OT_TCP_DISCONNECTED_REASON_NORMAL;
|
||||
break;
|
||||
case ECONNREFUSED:
|
||||
reason = OT_TCP_DISCONNECTED_REASON_REFUSED;
|
||||
break;
|
||||
case ETIMEDOUT:
|
||||
reason = OT_TCP_DISCONNECTED_REASON_TIMED_OUT;
|
||||
break;
|
||||
case ECONNRESET:
|
||||
default:
|
||||
reason = OT_TCP_DISCONNECTED_REASON_RESET;
|
||||
break;
|
||||
}
|
||||
endpoint.mDisconnectedCallback(&endpoint, reason);
|
||||
}
|
||||
}
|
||||
|
||||
void tcplp_sys_on_state_change(struct tcpcb *aTcb, int aNewState)
|
||||
{
|
||||
if (aNewState == TCP6S_CLOSED)
|
||||
{
|
||||
/* Re-initialize the TCB. */
|
||||
cbuf_pop(&aTcb->recvbuf, cbuf_used_space(&aTcb->recvbuf));
|
||||
aTcb->accepted_from = nullptr;
|
||||
initialize_tcb(aTcb);
|
||||
}
|
||||
/* Any adaptive changes to the sleep interval would go here. */
|
||||
}
|
||||
|
||||
void tcplp_sys_log(const char *aFormat, ...)
|
||||
{
|
||||
char buffer[128];
|
||||
va_list args;
|
||||
va_start(args, aFormat);
|
||||
vsnprintf(buffer, sizeof(buffer), aFormat, args);
|
||||
va_end(args);
|
||||
|
||||
otLogDebgTcp(buffer);
|
||||
}
|
||||
|
||||
bool tcplp_sys_autobind(otInstance * aInstance,
|
||||
const otSockAddr *aPeer,
|
||||
otSockAddr * aToBind,
|
||||
bool aBindAddress,
|
||||
bool aBindPort)
|
||||
{
|
||||
Instance &instance = AsCoreType(aInstance);
|
||||
|
||||
return instance.Get<Tcp>().AutoBind(*static_cast<const SockAddr *>(aPeer), *static_cast<SockAddr *>(aToBind),
|
||||
aBindAddress, aBindPort);
|
||||
}
|
||||
|
||||
uint32_t tcplp_sys_generate_isn()
|
||||
{
|
||||
uint32_t isn;
|
||||
IgnoreError(Random::Crypto::FillBuffer(reinterpret_cast<uint8_t *>(&isn), sizeof(isn)));
|
||||
return isn;
|
||||
}
|
||||
|
||||
uint16_t tcplp_sys_hostswap16(uint16_t aHostPort)
|
||||
{
|
||||
return HostSwap16(aHostPort);
|
||||
}
|
||||
|
||||
uint32_t tcplp_sys_hostswap32(uint32_t aHostPort)
|
||||
{
|
||||
return HostSwap32(aHostPort);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_CONFIG_TCP_ENABLE
|
||||
|
||||
+113
-1
@@ -46,6 +46,8 @@
|
||||
#include "net/ip6_headers.hpp"
|
||||
#include "net/socket.hpp"
|
||||
|
||||
#include "../../third_party/tcplp/tcplp.h"
|
||||
|
||||
namespace ot {
|
||||
namespace Ip6 {
|
||||
|
||||
@@ -73,6 +75,7 @@ public:
|
||||
class Endpoint : public otTcpEndpoint, public LinkedListEntry<Endpoint>
|
||||
{
|
||||
friend class Tcp;
|
||||
friend class LinkedList<Endpoint>;
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -236,7 +239,7 @@ public:
|
||||
* @retval kErrorNone Successfully completed the operation.
|
||||
* @retval kErrorFailed Failed to complete the operation.
|
||||
*/
|
||||
Error ReceiveByReference(const otLinkedBuffer *&aBuffer) const;
|
||||
Error ReceiveByReference(const otLinkedBuffer *&aBuffer);
|
||||
|
||||
/**
|
||||
* Reorganizes the receive buffer to be entirely contiguous in memory.
|
||||
@@ -329,7 +332,32 @@ public:
|
||||
*/
|
||||
Error Deinitialize(void);
|
||||
|
||||
/**
|
||||
* Converts a reference to a struct tcpcb to a reference to its
|
||||
* enclosing Endpoint.
|
||||
*/
|
||||
static Endpoint &FromTcb(struct tcpcb &aTcb) { return *reinterpret_cast<Endpoint *>(&aTcb); }
|
||||
|
||||
/**
|
||||
* Obtains a reference to this Endpoint's struct tcpcb.
|
||||
*/
|
||||
struct tcpcb &GetTcb(void) { return *reinterpret_cast<struct tcpcb *>(&mTcb); }
|
||||
|
||||
/**
|
||||
* Obtains a const reference to this Endpoint's struct tcpcb.
|
||||
*/
|
||||
const struct tcpcb &GetTcb(void) const { return *reinterpret_cast<const struct tcpcb *>(&mTcb); }
|
||||
|
||||
/**
|
||||
* Checks if this Endpoint is in the closed state.
|
||||
*/
|
||||
bool IsClosed(void) const { return GetTcb().t_state == TCP6S_CLOSED; }
|
||||
|
||||
private:
|
||||
friend void ::tcplp_sys_set_timer(struct tcpcb *aTcb, uint8_t aTimerFlag, uint32_t aDelay);
|
||||
friend void ::tcplp_sys_stop_timer(struct tcpcb *aTcb, uint8_t aTimerFlag);
|
||||
friend void ::tcplp_sys_connection_lost(struct tcpcb *aTcb, uint8_t aErrNum);
|
||||
|
||||
enum : uint8_t
|
||||
{
|
||||
kTimerDelack = 0,
|
||||
@@ -345,14 +373,27 @@ public:
|
||||
void SetTimer(uint8_t aTimerFlag, uint32_t aDelay);
|
||||
void CancelTimer(uint8_t aTimerFlag);
|
||||
bool FirePendingTimers(TimeMilli aNow, bool &aHasFutureTimer, TimeMilli &aEarliestFutureExpiry);
|
||||
|
||||
Address & GetLocalIp6Address(void) { return *reinterpret_cast<Address *>(&GetTcb().laddr); }
|
||||
const Address &GetLocalIp6Address(void) const { return *reinterpret_cast<const Address *>(&GetTcb().laddr); }
|
||||
Address & GetForeignIp6Address(void) { return *reinterpret_cast<Address *>(&GetTcb().faddr); }
|
||||
const Address &GetForeignIp6Address(void) const { return *reinterpret_cast<const Address *>(&GetTcb().faddr); }
|
||||
bool Matches(const MessageInfo &aMessageInfo) const;
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct tcpcb) == sizeof(Endpoint::mTcb), "mTcb field in otTcpEndpoint is sized incorrectly");
|
||||
static_assert(alignof(struct tcpcb) == alignof(decltype(Endpoint::mTcb)),
|
||||
"mTcb field in otTcpEndpoint is aligned incorrectly");
|
||||
static_assert(offsetof(Endpoint, mTcb) == 0, "mTcb field in otTcpEndpoint has nonzero offset");
|
||||
|
||||
/**
|
||||
* This class represents a TCP/IPv6 listener.
|
||||
*
|
||||
*/
|
||||
class Listener : public otTcpListener, public LinkedListEntry<Listener>
|
||||
{
|
||||
friend class LinkedList<Listener>;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Initializes a TCP listener.
|
||||
@@ -438,8 +479,49 @@ public:
|
||||
*
|
||||
*/
|
||||
Error Deinitialize(void);
|
||||
|
||||
/**
|
||||
* Converts a reference to a struct tcpcb_listen to a reference to its
|
||||
* enclosing Listener.
|
||||
*/
|
||||
static Listener &FromTcbListen(struct tcpcb_listen &aTcbListen)
|
||||
{
|
||||
return *reinterpret_cast<Listener *>(&aTcbListen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a reference to this Listener's struct tcpcb_listen.
|
||||
*/
|
||||
struct tcpcb_listen &GetTcbListen(void) { return *reinterpret_cast<struct tcpcb_listen *>(&mTcbListen); }
|
||||
|
||||
/**
|
||||
* Obtains a const reference to this Listener's struct tcpcb_listen.
|
||||
*/
|
||||
const struct tcpcb_listen &GetTcbListen(void) const
|
||||
{
|
||||
return *reinterpret_cast<const struct tcpcb_listen *>(&mTcbListen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this Listener is in the closed state.
|
||||
*/
|
||||
bool IsClosed(void) const { return GetTcbListen().t_state == TCP6S_CLOSED; }
|
||||
|
||||
private:
|
||||
Address & GetLocalIp6Address(void) { return *reinterpret_cast<Address *>(&GetTcbListen().laddr); }
|
||||
const Address &GetLocalIp6Address(void) const
|
||||
{
|
||||
return *reinterpret_cast<const Address *>(&GetTcbListen().laddr);
|
||||
}
|
||||
bool Matches(const MessageInfo &aMessageInfo) const;
|
||||
};
|
||||
|
||||
static_assert(sizeof(struct tcpcb_listen) == sizeof(Listener::mTcbListen),
|
||||
"mTcbListen field in otTcpListener is sized incorrectly");
|
||||
static_assert(alignof(struct tcpcb_listen) == alignof(decltype(Listener::mTcbListen)),
|
||||
"mTcbListen field in otTcpListener is aligned incorrectly");
|
||||
static_assert(offsetof(Listener, mTcbListen) == 0, "mTcbListen field in otTcpEndpoint has nonzero offset");
|
||||
|
||||
/**
|
||||
* This class implements TCP header parsing.
|
||||
*
|
||||
@@ -546,6 +628,31 @@ public:
|
||||
*/
|
||||
Error HandleMessage(ot::Ip6::Header &aIp6Header, Message &aMessage, MessageInfo &aMessageInfo);
|
||||
|
||||
/**
|
||||
* Automatically selects a local address and/or port for communication with the specified peer.
|
||||
*
|
||||
* @param[in] aPeer The peer's address and port.
|
||||
* @param[in,out] aToBind The SockAddr into which to store the selected address and/or port.
|
||||
* @param[in] aBindAddress If true, the local address is selected; if not, the current address
|
||||
* in @p aToBind is treated as a given.
|
||||
* @param[in] aBindPort If true, the local port is selected; if not, the current port in
|
||||
* @p aToBind is treated as a given.
|
||||
*
|
||||
* @returns True if successful, false otherwise.
|
||||
*
|
||||
*/
|
||||
bool AutoBind(const SockAddr &aPeer, SockAddr &aToBind, bool aBindAddress, bool aBindPort);
|
||||
|
||||
/**
|
||||
* Checks if an Endpoint is in the list of initialized endpoints.
|
||||
*/
|
||||
bool IsInitialized(const Endpoint &aEndpoint) const { return mEndpoints.Contains(aEndpoint); }
|
||||
|
||||
/**
|
||||
* Checks if a Listener is in the list of initialized Listeners.
|
||||
*/
|
||||
bool IsInitialized(const Listener &aListener) const { return mListeners.Contains(aListener); }
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
@@ -553,6 +660,11 @@ private:
|
||||
kDynamicPortMax = 65535, ///< Service Name and Transport Protocol Port Number Registry
|
||||
};
|
||||
|
||||
void ProcessSignals(Endpoint &aEndpoint, otLinkedBuffer *aPriorHead, struct signals &aSignals);
|
||||
|
||||
static Error BsdErrorToOtError(int aBsdError);
|
||||
bool CanBind(const SockAddr &aSockName);
|
||||
|
||||
static void HandleTimer(Timer &aTimer);
|
||||
void ProcessTimers(void);
|
||||
|
||||
|
||||
+125
-82
@@ -28,6 +28,8 @@
|
||||
|
||||
include $(abs_top_nlbuild_autotools_dir)/automake/pre.am
|
||||
|
||||
COMMON_LIBTOOLFLAGS = --preserve-dup-deps
|
||||
|
||||
#
|
||||
# Local headers to build against and distribute but not to install
|
||||
# since they are not part of the package.
|
||||
@@ -74,7 +76,6 @@ AM_CPPFLAGS += \
|
||||
endif
|
||||
|
||||
COMMON_LDADD = \
|
||||
$(top_builddir)/third_party/tcplp/libtcplp.a \
|
||||
$(NULL)
|
||||
|
||||
if OPENTHREAD_ENABLE_NCP
|
||||
@@ -84,6 +85,8 @@ COMMON_LDADD += \
|
||||
endif
|
||||
|
||||
COMMON_LDADD += \
|
||||
$(top_builddir)/src/core/libopenthread-ftd.a \
|
||||
$(top_builddir)/third_party/tcplp/libtcplp.a \
|
||||
$(top_builddir)/src/core/libopenthread-ftd.a \
|
||||
-lpthread \
|
||||
$(NULL)
|
||||
@@ -184,128 +187,168 @@ COMMON_SOURCES = test_platform.cpp test_util.cpp
|
||||
|
||||
# Source, compiler, and linker options for test programs.
|
||||
|
||||
ot_test_aes_LDADD = $(COMMON_LDADD)
|
||||
ot_test_aes_SOURCES = $(COMMON_SOURCES) test_aes.cpp
|
||||
ot_test_aes_LDADD = $(COMMON_LDADD)
|
||||
ot_test_aes_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_aes_SOURCES = $(COMMON_SOURCES) test_aes.cpp
|
||||
|
||||
ot_test_array_LDADD = $(COMMON_LDADD)
|
||||
ot_test_array_SOURCES = $(COMMON_SOURCES) test_array.cpp
|
||||
ot_test_array_LDADD = $(COMMON_LDADD)
|
||||
ot_test_array_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_array_SOURCES = $(COMMON_SOURCES) test_array.cpp
|
||||
|
||||
ot_test_binary_search_LDADD = $(COMMON_LDADD)
|
||||
ot_test_binary_search_SOURCES = $(COMMON_SOURCES) test_binary_search.cpp
|
||||
ot_test_binary_search_LDADD = $(COMMON_LDADD)
|
||||
ot_test_binary_search_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_binary_search_SOURCES = $(COMMON_SOURCES) test_binary_search.cpp
|
||||
|
||||
ot_test_checksum_LDADD = $(COMMON_LDADD)
|
||||
ot_test_checksum_SOURCES = $(COMMON_SOURCES) test_checksum.cpp
|
||||
ot_test_checksum_LDADD = $(COMMON_LDADD)
|
||||
ot_test_checksum_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_checksum_SOURCES = $(COMMON_SOURCES) test_checksum.cpp
|
||||
|
||||
ot_test_child_LDADD = $(COMMON_LDADD)
|
||||
ot_test_child_SOURCES = $(COMMON_SOURCES) test_child.cpp
|
||||
ot_test_child_LDADD = $(COMMON_LDADD)
|
||||
ot_test_child_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_child_SOURCES = $(COMMON_SOURCES) test_child.cpp
|
||||
|
||||
ot_test_child_table_LDADD = $(COMMON_LDADD)
|
||||
ot_test_child_table_SOURCES = $(COMMON_SOURCES) test_child_table.cpp
|
||||
ot_test_child_table_LDADD = $(COMMON_LDADD)
|
||||
ot_test_child_table_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_child_table_SOURCES = $(COMMON_SOURCES) test_child_table.cpp
|
||||
|
||||
ot_test_cmd_line_parser_LDADD = $(COMMON_LDADD)
|
||||
ot_test_cmd_line_parser_SOURCES = $(COMMON_SOURCES) test_cmd_line_parser.cpp
|
||||
ot_test_cmd_line_parser_LDADD = $(COMMON_LDADD)
|
||||
ot_test_cmd_line_parser_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_cmd_line_parser_SOURCES = $(COMMON_SOURCES) test_cmd_line_parser.cpp
|
||||
|
||||
ot_test_data_LDADD = $(COMMON_LDADD)
|
||||
ot_test_data_SOURCES = $(COMMON_SOURCES) test_data.cpp
|
||||
ot_test_data_LDADD = $(COMMON_LDADD)
|
||||
ot_test_data_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_data_SOURCES = $(COMMON_SOURCES) test_data.cpp
|
||||
|
||||
ot_test_dns_LDADD = $(COMMON_LDADD)
|
||||
ot_test_dns_SOURCES = $(COMMON_SOURCES) test_dns.cpp
|
||||
ot_test_dns_LDADD = $(COMMON_LDADD)
|
||||
ot_test_dns_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_dns_SOURCES = $(COMMON_SOURCES) test_dns.cpp
|
||||
|
||||
ot_test_dso_LDADD = $(COMMON_LDADD)
|
||||
ot_test_dso_SOURCES = $(COMMON_SOURCES) test_dso.cpp
|
||||
ot_test_dso_LDADD = $(COMMON_LDADD)
|
||||
ot_test_dso_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_dso_SOURCES = $(COMMON_SOURCES) test_dso.cpp
|
||||
|
||||
ot_test_ecdsa_LDADD = $(COMMON_LDADD)
|
||||
ot_test_ecdsa_SOURCES = $(COMMON_SOURCES) test_ecdsa.cpp
|
||||
ot_test_ecdsa_LDADD = $(COMMON_LDADD)
|
||||
ot_test_ecdsa_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_ecdsa_SOURCES = $(COMMON_SOURCES) test_ecdsa.cpp
|
||||
|
||||
ot_test_flash_LDADD = $(COMMON_LDADD)
|
||||
ot_test_flash_SOURCES = $(COMMON_SOURCES) test_flash.cpp
|
||||
ot_test_flash_LDADD = $(COMMON_LDADD)
|
||||
ot_test_flash_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_flash_SOURCES = $(COMMON_SOURCES) test_flash.cpp
|
||||
|
||||
ot_test_hdlc_LDADD = $(COMMON_LDADD)
|
||||
ot_test_hdlc_SOURCES = $(COMMON_SOURCES) test_hdlc.cpp
|
||||
ot_test_hdlc_LDADD = $(COMMON_LDADD)
|
||||
ot_test_hdlc_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_hdlc_SOURCES = $(COMMON_SOURCES) test_hdlc.cpp
|
||||
|
||||
ot_test_heap_LDADD = $(COMMON_LDADD)
|
||||
ot_test_heap_SOURCES = $(COMMON_SOURCES) test_heap.cpp
|
||||
ot_test_heap_LDADD = $(COMMON_LDADD)
|
||||
ot_test_heap_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_heap_SOURCES = $(COMMON_SOURCES) test_heap.cpp
|
||||
|
||||
ot_test_heap_string_LDADD = $(COMMON_LDADD)
|
||||
ot_test_heap_string_SOURCES = $(COMMON_SOURCES) test_heap_string.cpp
|
||||
ot_test_heap_string_LDADD = $(COMMON_LDADD)
|
||||
ot_test_heap_string_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_heap_string_SOURCES = $(COMMON_SOURCES) test_heap_string.cpp
|
||||
|
||||
ot_test_hkdf_sha256_LDADD = $(COMMON_LDADD)
|
||||
ot_test_hkdf_sha256_SOURCES = $(COMMON_SOURCES) test_hkdf_sha256.cpp
|
||||
ot_test_hkdf_sha256_LDADD = $(COMMON_LDADD)
|
||||
ot_test_hkdf_sha256_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_hkdf_sha256_SOURCES = $(COMMON_SOURCES) test_hkdf_sha256.cpp
|
||||
|
||||
ot_test_hmac_sha256_LDADD = $(COMMON_LDADD)
|
||||
ot_test_hmac_sha256_SOURCES = $(COMMON_SOURCES) test_hmac_sha256.cpp
|
||||
ot_test_hmac_sha256_LDADD = $(COMMON_LDADD)
|
||||
ot_test_hmac_sha256_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_hmac_sha256_SOURCES = $(COMMON_SOURCES) test_hmac_sha256.cpp
|
||||
|
||||
ot_test_ip_address_LDADD = $(COMMON_LDADD)
|
||||
ot_test_ip_address_SOURCES = $(COMMON_SOURCES) test_ip_address.cpp
|
||||
ot_test_ip_address_LDADD = $(COMMON_LDADD)
|
||||
ot_test_ip_address_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_ip_address_SOURCES = $(COMMON_SOURCES) test_ip_address.cpp
|
||||
|
||||
ot_test_link_quality_LDADD = $(COMMON_LDADD)
|
||||
ot_test_link_quality_SOURCES = $(COMMON_SOURCES) test_link_quality.cpp
|
||||
ot_test_link_quality_LDADD = $(COMMON_LDADD)
|
||||
ot_test_link_quality_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_link_quality_SOURCES = $(COMMON_SOURCES) test_link_quality.cpp
|
||||
|
||||
ot_test_linked_list_LDADD = $(COMMON_LDADD)
|
||||
ot_test_linked_list_SOURCES = $(COMMON_SOURCES) test_linked_list.cpp
|
||||
ot_test_linked_list_LDADD = $(COMMON_LDADD)
|
||||
ot_test_linked_list_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_linked_list_SOURCES = $(COMMON_SOURCES) test_linked_list.cpp
|
||||
|
||||
ot_test_lowpan_LDADD = $(COMMON_LDADD)
|
||||
ot_test_lowpan_SOURCES = $(COMMON_SOURCES) test_lowpan.cpp
|
||||
ot_test_lowpan_LDADD = $(COMMON_LDADD)
|
||||
ot_test_lowpan_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_lowpan_SOURCES = $(COMMON_SOURCES) test_lowpan.cpp
|
||||
|
||||
ot_test_mac_frame_LDADD = $(COMMON_LDADD)
|
||||
ot_test_mac_frame_SOURCES = $(COMMON_SOURCES) test_mac_frame.cpp
|
||||
ot_test_mac_frame_LDADD = $(COMMON_LDADD)
|
||||
ot_test_mac_frame_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_mac_frame_SOURCES = $(COMMON_SOURCES) test_mac_frame.cpp
|
||||
|
||||
ot_test_macros_LDADD = $(COMMON_LDADD)
|
||||
ot_test_macros_SOURCES = $(COMMON_SOURCES) test_macros.cpp
|
||||
ot_test_macros_LDADD = $(COMMON_LDADD)
|
||||
ot_test_macros_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_macros_SOURCES = $(COMMON_SOURCES) test_macros.cpp
|
||||
|
||||
ot_test_message_LDADD = $(COMMON_LDADD)
|
||||
ot_test_message_SOURCES = $(COMMON_SOURCES) test_message.cpp
|
||||
ot_test_message_LDADD = $(COMMON_LDADD)
|
||||
ot_test_message_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_message_SOURCES = $(COMMON_SOURCES) test_message.cpp
|
||||
|
||||
ot_test_message_queue_LDADD = $(COMMON_LDADD)
|
||||
ot_test_message_queue_SOURCES = $(COMMON_SOURCES) test_message_queue.cpp
|
||||
ot_test_message_queue_LDADD = $(COMMON_LDADD)
|
||||
ot_test_message_queue_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_message_queue_SOURCES = $(COMMON_SOURCES) test_message_queue.cpp
|
||||
|
||||
ot_test_multicast_listeners_table_LDADD = $(COMMON_LDADD)
|
||||
ot_test_multicast_listeners_table_LDADD = $(COMMON_LDADD)
|
||||
ot_test_multicast_listeners_table_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_multicast_listeners_table_SOURCES = $(COMMON_SOURCES) test_multicast_listeners_table.cpp
|
||||
|
||||
ot_test_spinel_buffer_LDADD = $(COMMON_LDADD)
|
||||
ot_test_spinel_buffer_SOURCES = $(COMMON_SOURCES) test_spinel_buffer.cpp
|
||||
ot_test_spinel_buffer_LDADD = $(COMMON_LDADD)
|
||||
ot_test_spinel_buffer_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_spinel_buffer_SOURCES = $(COMMON_SOURCES) test_spinel_buffer.cpp
|
||||
|
||||
ot_test_ndproxy_table_LDADD = $(COMMON_LDADD)
|
||||
ot_test_ndproxy_table_SOURCES = $(COMMON_SOURCES) test_ndproxy_table.cpp
|
||||
ot_test_ndproxy_table_LDADD = $(COMMON_LDADD)
|
||||
ot_test_ndproxy_table_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_ndproxy_table_SOURCES = $(COMMON_SOURCES) test_ndproxy_table.cpp
|
||||
|
||||
ot_test_netif_LDADD = $(COMMON_LDADD)
|
||||
ot_test_netif_SOURCES = $(COMMON_SOURCES) test_netif.cpp
|
||||
ot_test_netif_LDADD = $(COMMON_LDADD)
|
||||
ot_test_netif_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_netif_SOURCES = $(COMMON_SOURCES) test_netif.cpp
|
||||
|
||||
ot_test_network_data_LDADD = $(COMMON_LDADD)
|
||||
ot_test_network_data_SOURCES = $(COMMON_SOURCES) test_network_data.cpp
|
||||
ot_test_network_data_LDADD = $(COMMON_LDADD)
|
||||
ot_test_network_data_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_network_data_SOURCES = $(COMMON_SOURCES) test_network_data.cpp
|
||||
|
||||
ot_test_pool_LDADD = $(COMMON_LDADD)
|
||||
ot_test_pool_SOURCES = $(COMMON_SOURCES) test_pool.cpp
|
||||
ot_test_pool_LDADD = $(COMMON_LDADD)
|
||||
ot_test_pool_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_pool_SOURCES = $(COMMON_SOURCES) test_pool.cpp
|
||||
|
||||
ot_test_priority_queue_LDADD = $(COMMON_LDADD)
|
||||
ot_test_priority_queue_SOURCES = $(COMMON_SOURCES) test_priority_queue.cpp
|
||||
ot_test_priority_queue_LDADD = $(COMMON_LDADD)
|
||||
ot_test_priority_queue_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_priority_queue_SOURCES = $(COMMON_SOURCES) test_priority_queue.cpp
|
||||
|
||||
ot_test_pskc_LDADD = $(COMMON_LDADD)
|
||||
ot_test_pskc_SOURCES = $(COMMON_SOURCES) test_pskc.cpp
|
||||
ot_test_pskc_LDADD = $(COMMON_LDADD)
|
||||
ot_test_pskc_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_pskc_SOURCES = $(COMMON_SOURCES) test_pskc.cpp
|
||||
|
||||
ot_test_smart_ptrs_LDADD = $(COMMON_LDADD)
|
||||
ot_test_smart_ptrs_SOURCES = $(COMMON_SOURCES) test_smart_ptrs.cpp
|
||||
ot_test_smart_ptrs_LDADD = $(COMMON_LDADD)
|
||||
ot_test_smart_ptrs_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_smart_ptrs_SOURCES = $(COMMON_SOURCES) test_smart_ptrs.cpp
|
||||
|
||||
ot_test_meshcop_LDADD = $(COMMON_LDADD)
|
||||
ot_test_meshcop_SOURCES = $(COMMON_SOURCES) test_meshcop.cpp
|
||||
ot_test_meshcop_LDADD = $(COMMON_LDADD)
|
||||
ot_test_meshcop_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_meshcop_SOURCES = $(COMMON_SOURCES) test_meshcop.cpp
|
||||
|
||||
ot_test_serial_number_LDADD = $(COMMON_LDADD)
|
||||
ot_test_serial_number_SOURCES = $(COMMON_SOURCES) test_serial_number.cpp
|
||||
ot_test_serial_number_LDADD = $(COMMON_LDADD)
|
||||
ot_test_serial_number_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_serial_number_SOURCES = $(COMMON_SOURCES) test_serial_number.cpp
|
||||
|
||||
ot_test_string_LDADD = $(COMMON_LDADD)
|
||||
ot_test_string_SOURCES = $(COMMON_SOURCES) test_string.cpp
|
||||
ot_test_string_LDADD = $(COMMON_LDADD)
|
||||
ot_test_string_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_string_SOURCES = $(COMMON_SOURCES) test_string.cpp
|
||||
|
||||
ot_test_spinel_decoder_LDADD = $(COMMON_LDADD)
|
||||
ot_test_spinel_decoder_SOURCES = $(COMMON_SOURCES) test_spinel_decoder.cpp
|
||||
ot_test_spinel_decoder_LDADD = $(COMMON_LDADD)
|
||||
ot_test_spinel_decoder_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_spinel_decoder_SOURCES = $(COMMON_SOURCES) test_spinel_decoder.cpp
|
||||
|
||||
ot_test_spinel_encoder_LDADD = $(COMMON_LDADD)
|
||||
ot_test_spinel_encoder_SOURCES = $(COMMON_SOURCES) test_spinel_encoder.cpp
|
||||
ot_test_spinel_encoder_LDADD = $(COMMON_LDADD)
|
||||
ot_test_spinel_encoder_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_spinel_encoder_SOURCES = $(COMMON_SOURCES) test_spinel_encoder.cpp
|
||||
|
||||
ot_test_timer_LDADD = $(COMMON_LDADD)
|
||||
ot_test_timer_SOURCES = $(COMMON_SOURCES) test_timer.cpp
|
||||
ot_test_timer_LDADD = $(COMMON_LDADD)
|
||||
ot_test_timer_LIBTOOLFLAGS = $(COMMON_LIBTOOLFLAGS)
|
||||
ot_test_timer_SOURCES = $(COMMON_SOURCES) test_timer.cpp
|
||||
|
||||
ot_test_toolchain_LDADD = $(NULL)
|
||||
ot_test_toolchain_SOURCES = test_toolchain.cpp test_toolchain_c.c
|
||||
ot_test_toolchain_LDADD = $(NULL)
|
||||
ot_test_toolchain_SOURCES = test_toolchain.cpp test_toolchain_c.c
|
||||
|
||||
if OPENTHREAD_BUILD_COVERAGE
|
||||
CLEANFILES = $(wildcard *.gcda *.gcno)
|
||||
|
||||
Vendored
+15
-1
@@ -43,9 +43,23 @@
|
||||
#include "tcp_var.h"
|
||||
#include "tcp_timer.h"
|
||||
|
||||
/*
|
||||
* samkumar: these are TCPlp-specific constants that I added. They were not
|
||||
* present in the FreeBSD-derived code.
|
||||
*/
|
||||
|
||||
#define FRAMES_PER_SEG 5
|
||||
#define FRAMECAP_6LOWPAN (122 - 11 - 5)
|
||||
#define IP6HDR_SIZE (2 + 1 + 1 + 16 + 16) // IPHC header (2) + Next header (1) + Hop count (1) + Dest. addr (16) + Src. addr (16)
|
||||
#define MSS_6LOWPAN ((FRAMES_PER_SEG * FRAMECAP_6LOWPAN) - IP6HDR_SIZE - sizeof(struct tcphdr))
|
||||
|
||||
// I may change some of these flags later
|
||||
/*
|
||||
* samkumar: The remaining constants were present in the original FreeBSD code,
|
||||
* but I set their values.
|
||||
*/
|
||||
|
||||
#define hz 1000 // number of ticks per second, assuming millisecond ticks
|
||||
|
||||
enum tcp_input_consts {
|
||||
tcp_keepcnt = TCPTV_KEEPCNT,
|
||||
tcp_fast_finwait2_recycle = 0,
|
||||
|
||||
Vendored
+5
-5
@@ -48,12 +48,12 @@
|
||||
|
||||
#include "tcp_const.h"
|
||||
|
||||
/* samkumar: Eventually, replace this with OpenThread's random generator. */
|
||||
// A simple linear congruential number generator
|
||||
tcp_seq seed = (tcp_seq) 0xbeaddeed;
|
||||
/*
|
||||
* samkumar: This is rewritten to have the host network stack to generate the
|
||||
* ISN with appropriate randomness.
|
||||
*/
|
||||
tcp_seq tcp_new_isn(struct tcpcb* tp) {
|
||||
seed = (((tcp_seq) 0xfaded011) * seed) + (tcp_seq) 0x1ead1eaf;
|
||||
return seed;
|
||||
return (uint32_t) tcplp_sys_generate_isn();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Vendored
+23
-10
@@ -59,10 +59,11 @@ int V_tcp_pmtud_blackhole_activated_min_mss = 0;
|
||||
/*
|
||||
* samkumar: I changed these functions to accept "struct tcpcb* tp" their
|
||||
* argument instead of "void *xtp". This is possible since we're no longer
|
||||
* relying on FreeBSD's callout subsystem in TCPlp.
|
||||
* relying on FreeBSD's callout subsystem in TCPlp. I also changed them to
|
||||
* return 1 if the connection is dropped, or 0 otherwise.
|
||||
*/
|
||||
|
||||
void
|
||||
int
|
||||
tcp_timer_delack(struct tcpcb* tp)
|
||||
{
|
||||
/* samkumar: I added this, to replace the code I removed below. */
|
||||
@@ -80,9 +81,10 @@ tcp_timer_delack(struct tcpcb* tp)
|
||||
*/
|
||||
tp->t_flags |= TF_ACKNOW;
|
||||
(void) tcp_output(tp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
tcp_timer_keep(struct tcpcb* tp)
|
||||
{
|
||||
uint32_t ticks = tcplp_sys_get_ticks();
|
||||
@@ -158,17 +160,19 @@ tcp_timer_keep(struct tcpcb* tp)
|
||||
* that handled debug tracing/probes, vnet, and locking. I removed that
|
||||
* code.
|
||||
*/
|
||||
return;
|
||||
return 0;
|
||||
|
||||
dropit:
|
||||
tp = tcp_drop(tp, ETIMEDOUT);
|
||||
(void) tp; /* samkumar: prevent a compiler warning */
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
tcp_timer_persist(struct tcpcb* tp)
|
||||
{
|
||||
uint32_t ticks = tcplp_sys_get_ticks();
|
||||
int dropped = 0;
|
||||
|
||||
/* samkumar: I added this, to replace the code I removed below. */
|
||||
KASSERT(tpistimeractive(tp, TT_PERSIST), ("Persist timer running, but unmarked\n"));
|
||||
@@ -202,6 +206,7 @@ tcp_timer_persist(struct tcpcb* tp)
|
||||
(ticks - tp->t_rcvtime >= tcp_maxpersistidle ||
|
||||
ticks - tp->t_rcvtime >= TCP_REXMTVAL(tp) * tcp_totbackoff)) {
|
||||
tp = tcp_drop(tp, ETIMEDOUT);
|
||||
dropped = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -212,6 +217,7 @@ tcp_timer_persist(struct tcpcb* tp)
|
||||
if (tp->t_state > TCPS_CLOSE_WAIT &&
|
||||
(ticks - tp->t_rcvtime) >= TCPTV_PERSMAX) {
|
||||
tp = tcp_drop(tp, ETIMEDOUT);
|
||||
dropped = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -227,13 +233,14 @@ out:
|
||||
* tracing/probes, vnet, and locking. I removed that code.
|
||||
*/
|
||||
(void) tp; /* samkumar: prevent a compiler warning */
|
||||
return;
|
||||
return dropped;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
tcp_timer_2msl(struct tcpcb* tp)
|
||||
{
|
||||
uint32_t ticks = tcplp_sys_get_ticks();
|
||||
int dropped = 0;
|
||||
|
||||
/* samkumar: I added this, to replace the code I removed below. */
|
||||
KASSERT(tpistimeractive(tp, TT_2MSL), ("2MSL timer running, but unmarked\n"));
|
||||
@@ -281,7 +288,8 @@ tcp_timer_2msl(struct tcpcb* tp)
|
||||
if (tp->t_state == TCP6S_TIME_WAIT) {
|
||||
tp = tcp_close(tp);
|
||||
tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL);
|
||||
return;
|
||||
dropped = 1;
|
||||
return dropped;
|
||||
}
|
||||
/*
|
||||
* samkumar: This if statement also used to check that an inpcb is still
|
||||
@@ -297,6 +305,7 @@ tcp_timer_2msl(struct tcpcb* tp)
|
||||
tpiscantrcv(tp)) {
|
||||
tp = tcp_close(tp);
|
||||
tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL);
|
||||
dropped = 1;
|
||||
} else {
|
||||
if (ticks - tp->t_rcvtime <= TP_MAXIDLE(tp)) {
|
||||
/*
|
||||
@@ -308,19 +317,22 @@ tcp_timer_2msl(struct tcpcb* tp)
|
||||
} else {
|
||||
tp = tcp_close(tp);
|
||||
tcplp_sys_connection_lost(tp, CONN_LOST_NORMAL);
|
||||
dropped = 1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* samkumar: There used to be some code here that handled debug
|
||||
* tracing/probes, vnet, and locking. I removed that code.
|
||||
*/
|
||||
return dropped;
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
tcp_timer_rexmt(struct tcpcb *tp)
|
||||
{
|
||||
int rexmt;
|
||||
uint32_t ticks = tcplp_sys_get_ticks();
|
||||
int dropped = 0;
|
||||
|
||||
/* samkumar: I added this, to replace the code I removed below. */
|
||||
KASSERT(tpistimeractive(tp, TT_REXMT), ("Rexmt timer running, but unmarked\n"));
|
||||
@@ -348,6 +360,7 @@ tcp_timer_rexmt(struct tcpcb *tp)
|
||||
|
||||
tp = tcp_drop(tp, tp->t_softerror ?
|
||||
tp->t_softerror : ETIMEDOUT);
|
||||
dropped = 1;
|
||||
goto out;
|
||||
}
|
||||
if (tp->t_state == TCPS_SYN_SENT) {
|
||||
@@ -450,7 +463,7 @@ out:
|
||||
* tracing/probes, vnet, and locking. I removed that code.
|
||||
*/
|
||||
(void) tp; /* samkumar: Prevent a compiler warning */
|
||||
return;
|
||||
return dropped;
|
||||
}
|
||||
|
||||
int
|
||||
|
||||
Vendored
+9
-5
@@ -154,11 +154,15 @@ static const int tcp_backoff[TCP_MAXRXTSHIFT + 1] =
|
||||
|
||||
static const int tcp_totbackoff = 2559; /* sum of tcp_backoff[] */
|
||||
|
||||
void tcp_timer_delack(struct tcpcb* tp);
|
||||
void tcp_timer_keep(struct tcpcb* tp);
|
||||
void tcp_timer_persist(struct tcpcb* tp);
|
||||
void tcp_timer_2msl(struct tcpcb* tp);
|
||||
void tcp_timer_rexmt(struct tcpcb *tp);
|
||||
/*
|
||||
* samkumar: Changed return value to int to indicate whether connection was
|
||||
* dropped or not.
|
||||
*/
|
||||
int tcp_timer_delack(struct tcpcb* tp);
|
||||
int tcp_timer_keep(struct tcpcb* tp);
|
||||
int tcp_timer_persist(struct tcpcb* tp);
|
||||
int tcp_timer_2msl(struct tcpcb* tp);
|
||||
int tcp_timer_rexmt(struct tcpcb *tp);
|
||||
int tcp_timer_active(struct tcpcb *tp, uint32_t timer_type);
|
||||
|
||||
/*
|
||||
|
||||
Vendored
+1
-8
@@ -50,14 +50,6 @@ extern "C" {
|
||||
#include <openthread/ip6.h>
|
||||
#include <openthread/message.h>
|
||||
|
||||
#define hz 1000 // number of ticks per second
|
||||
#define MICROS_PER_TICK 1000 // number of microseconds per tick
|
||||
|
||||
#define FRAMES_PER_SEG 5
|
||||
#define FRAMECAP_6LOWPAN (122 - 11 - 5)
|
||||
|
||||
#define IP6HDR_SIZE (2 + 1 + 1 + 16 + 16) // IPHC header (2) + Next header (1) + Hop count (1) + Dest. addr (16) + Src. addr (16)
|
||||
|
||||
#define RELOOKUP_REQUIRED -1
|
||||
#define CONN_LOST_NORMAL 0
|
||||
|
||||
@@ -85,6 +77,7 @@ void tcplp_sys_connection_lost(struct tcpcb* tcb, uint8_t errnum);
|
||||
void tcplp_sys_on_state_change(struct tcpcb* tcb, int newstate);
|
||||
void tcplp_sys_log(const char* format, ...);
|
||||
bool tcplp_sys_autobind(otInstance *aInstance, const otSockAddr *aPeer, otSockAddr *aToBind, bool aBindAddress, bool aBindPort);
|
||||
uint32_t tcplp_sys_generate_isn();
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
||||
Reference in New Issue
Block a user