[udp6] update UDP socket definitions (#5231)

This commit updates the  public OT `otUdp{}` (like `otUdpConnect`, or
`otUpdSend()`) functions to requires a pointer the OpenThread instance
to be passed as their first parameter (this harmonizes the definitions
with other public APIs and removes the need for `otUdpSocket` to track
the instance).

The core implementation in `udp6` module is updated to define
`SocketHandle` as an internal mirror of `otUdpSocket` structure. The
socket related methods `Open`(), `Bind()`, `Connect()`, etc., are
moved to `Udp` class itself (with a `SocketHandle` passed as a
parameter). For core internal use `Socket` class is defined as a
sub-class of `SocketHandle` and `InstanceLocator` providing same
helper methods. The separation between `SocketHandle` and `Socket`
type addresses the problem that can be caused by the treating/casting
publicly provided `otUdpSockt` objects as `InstanceLocator`.
This commit is contained in:
Abtin Keshavarzian
2020-07-14 10:03:03 -07:00
committed by GitHub
parent 9c660f6425
commit dc1d47d2c0
14 changed files with 408 additions and 349 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ extern "C" {
* @note This number versions both OpenThread platform and user APIs.
*
*/
#define OPENTHREAD_API_VERSION (14)
#define OPENTHREAD_API_VERSION (15)
/**
* @addtogroup api-instance
+30 -53
View File
@@ -126,7 +126,7 @@ typedef struct otUdpSocket
otSockAddr mPeerName; ///< The peer IPv6 socket address.
otUdpReceive mHandler; ///< A function pointer to the application callback.
void * mContext; ///< A pointer to application-specific context.
void * mHandle; ///< A handle to platform's UDP
void * mHandle; ///< A handle to platform's UDP.
struct otUdpSocket *mNext; ///< A pointer to the next UDP socket (internal use only).
} otUdpSocket;
@@ -137,7 +137,7 @@ typedef struct otUdpSocket
* OT_MESSAGE_PRIORITY_NORMAL by default.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aSettings A pointer to the message settings or NULL to set default settings.
* @param[in] aSettings A pointer to the message settings or NULL to use default settings.
*
* @returns A pointer to the message buffer or NULL if no message buffers are available or parameters are invalid.
*
@@ -157,68 +157,51 @@ otMessage *otUdpNewMessage(otInstance *aInstance, const otMessageSettings *aSett
* @retval OT_ERROR_NONE Successfully opened the socket.
* @retval OT_ERROR_FAILED Failed to open the socket.
*
* @sa otUdpNewMessage
* @sa otUdpClose
* @sa otUdpBind
* @sa otUdpConnect
* @sa otUdpSend
*
*/
otError otUdpOpen(otInstance *aInstance, otUdpSocket *aSocket, otUdpReceive aCallback, void *aContext);
/**
* Close a UDP/IPv6 socket.
*
* @param[in] aSocket A pointer to a UDP socket structure.
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aSocket A pointer to a UDP socket structure.
*
* @retval OT_ERROR_NONE Successfully closed the socket.
*
* @sa otUdpNewMessage
* @sa otUdpOpen
* @sa otUdpBind
* @sa otUdpConnect
* @sa otUdpSend
* @retval OT_ERROR_NONE Successfully closed the socket.
* @retval OT_ERROR_FAILED Failed to close UDP Socket.
*
*/
otError otUdpClose(otUdpSocket *aSocket);
otError otUdpClose(otInstance *aInstance, otUdpSocket *aSocket);
/**
* Bind a UDP/IPv6 socket.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aSocket A pointer to a UDP socket structure.
* @param[in] aSockName A pointer to an IPv6 socket address structure.
*
* @retval OT_ERROR_NONE Bind operation was successful.
*
* @sa otUdpNewMessage
* @sa otUdpOpen
* @sa otUdpConnect
* @sa otUdpClose
* @sa otUdpSend
* @retval OT_ERROR_NONE Bind operation was successful.
* @retval OT_ERROR_FAILED Failed to bind UDP socket.
*
*/
otError otUdpBind(otUdpSocket *aSocket, otSockAddr *aSockName);
otError otUdpBind(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName);
/**
* Connect a UDP/IPv6 socket.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aSocket A pointer to a UDP socket structure.
* @param[in] aSockName A pointer to an IPv6 socket address structure.
*
* @retval OT_ERROR_NONE Connect operation was successful.
*
* @sa otUdpNewMessage
* @sa otUdpOpen
* @sa otUdpBind
* @sa otUdpClose
* @sa otUdpSend
* @retval OT_ERROR_NONE Connect operation was successful.
* @retval OT_ERROR_FAILED Failed to connect UDP socket.
*
*/
otError otUdpConnect(otUdpSocket *aSocket, otSockAddr *aSockName);
otError otUdpConnect(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName);
/**
* Send a UDP/IPv6 message.
*
* @param[in] aInstance A pointer to an OpenThread instance.
* @param[in] aSocket A pointer to a UDP socket structure.
* @param[in] aMessage A pointer to a message buffer.
* @param[in] aMessageInfo A pointer to a message info structure.
@@ -227,18 +210,22 @@ otError otUdpConnect(otUdpSocket *aSocket, otSockAddr *aSockName);
* reference @p aMessage. If the return value is not OT_ERROR_NONE, the caller retains ownership of @p aMessage,
* including freeing @p aMessage if the message buffer is no longer needed.
*
* @retval OT_ERROR_NONE The message is successfully scheduled for sending.
* @retval OT_ERROR_INVALID_ARGS Invalid arguments are given.
*
* @sa otUdpNewMessage
* @sa otUdpOpen
* @sa otUdpClose
* @sa otUdpBind
* @sa otUdpConnect
* @sa otUdpSend
* @retval OT_ERROR_NONE The message is successfully scheduled for sending.
* @retval OT_ERROR_INVALID_ARGS Invalid arguments are given.
* @retval OT_ERROR_NO_BUFS Insufficient available buffer to add the UDP and IPv6 headers.
*
*/
otError otUdpSend(otUdpSocket *aSocket, otMessage *aMessage, const otMessageInfo *aMessageInfo);
otError otUdpSend(otInstance *aInstance, otUdpSocket *aSocket, otMessage *aMessage, const otMessageInfo *aMessageInfo);
/**
* This function gets the head of linked list of UDP Sockets.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns A pointer to the head of UDP Socket linked list.
*
*/
otUdpSocket *otUdpGetSockets(otInstance *aInstance);
/**
* @}
@@ -302,16 +289,6 @@ void otUdpForwardReceive(otInstance * aInstance,
const otIp6Address *aPeerAddr,
uint16_t aSockPort);
/**
* This function gets the existing UDP Sockets.
*
* @param[in] aInstance A pointer to an OpenThread instance.
*
* @returns A pointer to the first UDP Socket.
*
*/
otUdpSocket *otUdpGetSockets(otInstance *aInstance);
/**
* @}
*
+4 -4
View File
@@ -86,7 +86,7 @@ otError UdpExample::ProcessBind(uint8_t aArgsLength, char *aArgs[])
sockaddr.mPort = static_cast<uint16_t>(value);
error = otUdpBind(&mSocket, &sockaddr);
error = otUdpBind(mInterpreter.mInstance, &mSocket, &sockaddr);
exit:
return error;
@@ -110,7 +110,7 @@ otError UdpExample::ProcessConnect(uint8_t aArgsLength, char *aArgs[])
sockaddr.mPort = static_cast<uint16_t>(value);
error = otUdpConnect(&mSocket, &sockaddr);
error = otUdpConnect(mInterpreter.mInstance, &mSocket, &sockaddr);
exit:
return error;
@@ -121,7 +121,7 @@ otError UdpExample::ProcessClose(uint8_t aArgsLength, char *aArgs[])
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
return otUdpClose(&mSocket);
return otUdpClose(mInterpreter.mInstance, &mSocket);
}
otError UdpExample::ProcessOpen(uint8_t aArgsLength, char *aArgs[])
@@ -218,7 +218,7 @@ otError UdpExample::ProcessSend(uint8_t aArgsLength, char *aArgs[])
}
}
error = otUdpSend(&mSocket, message, &messageInfo);
error = otUdpSend(mInterpreter.mInstance, &mSocket, message, &messageInfo);
exit:
+28 -28
View File
@@ -51,41 +51,48 @@ otMessage *otUdpNewMessage(otInstance *aInstance, const otMessageSettings *aSett
otError otUdpOpen(otInstance *aInstance, otUdpSocket *aSocket, otUdpReceive aCallback, void *aContext)
{
otError error;
Instance & instance = *static_cast<Instance *>(aInstance);
Ip6::Udp::Socket &socket = *new (aSocket) Ip6::Udp::Socket(instance.Get<Ip6::Udp>());
Instance &instance = *static_cast<Instance *>(aInstance);
error = socket.Open(aCallback, aContext);
return error;
return instance.Get<Ip6::Udp>().Open(*static_cast<Ip6::Udp::SocketHandle *>(aSocket), aCallback, aContext);
}
otError otUdpClose(otUdpSocket *aSocket)
otError otUdpClose(otInstance *aInstance, otUdpSocket *aSocket)
{
otError error = OT_ERROR_INVALID_STATE;
Ip6::Udp::Socket &socket = *static_cast<Ip6::Udp::Socket *>(aSocket);
Instance &instance = *static_cast<Instance *>(aInstance);
error = socket.Close();
return error;
return instance.Get<Ip6::Udp>().Close(*static_cast<Ip6::Udp::SocketHandle *>(aSocket));
}
otError otUdpBind(otUdpSocket *aSocket, otSockAddr *aSockName)
otError otUdpBind(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName)
{
Ip6::Udp::Socket &socket = *static_cast<Ip6::Udp::Socket *>(aSocket);
return socket.Bind(*static_cast<const Ip6::SockAddr *>(aSockName));
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<Ip6::Udp>().Bind(*static_cast<Ip6::Udp::SocketHandle *>(aSocket),
*static_cast<const Ip6::SockAddr *>(aSockName));
}
otError otUdpConnect(otUdpSocket *aSocket, otSockAddr *aSockName)
otError otUdpConnect(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName)
{
Ip6::Udp::Socket &socket = *static_cast<Ip6::Udp::Socket *>(aSocket);
return socket.Connect(*static_cast<const Ip6::SockAddr *>(aSockName));
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<Ip6::Udp>().Connect(*static_cast<Ip6::Udp::SocketHandle *>(aSocket),
*static_cast<const Ip6::SockAddr *>(aSockName));
}
otError otUdpSend(otUdpSocket *aSocket, otMessage *aMessage, const otMessageInfo *aMessageInfo)
otError otUdpSend(otInstance *aInstance, otUdpSocket *aSocket, otMessage *aMessage, const otMessageInfo *aMessageInfo)
{
Ip6::Udp::Socket &socket = *static_cast<Ip6::Udp::Socket *>(aSocket);
return socket.SendTo(*static_cast<Message *>(aMessage), *static_cast<const Ip6::MessageInfo *>(aMessageInfo));
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<Ip6::Udp>().SendTo(*static_cast<Ip6::Udp::SocketHandle *>(aSocket),
*static_cast<Message *>(aMessage),
*static_cast<const Ip6::MessageInfo *>(aMessageInfo));
}
otUdpSocket *otUdpGetSockets(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<Ip6::Udp>().GetUdpSockets();
}
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
@@ -119,13 +126,6 @@ void otUdpForwardReceive(otInstance * aInstance,
}
#endif // OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
otUdpSocket *otUdpGetSockets(otInstance *aInstance)
{
Instance &instance = *static_cast<Instance *>(aInstance);
return instance.Get<Ip6::Udp>().GetUdpSockets();
}
otError otUdpAddReceiver(otInstance *aInstance, otUdpReceiver *aUdpReceiver)
{
Instance &instance = *static_cast<Instance *>(aInstance);
+1 -1
View File
@@ -1014,7 +1014,7 @@ const otCoapTxParameters TxParameters::kDefaultTxParameters = {
Coap::Coap(Instance &aInstance)
: CoapBase(aInstance, &Coap::Send)
, mSocket(aInstance.Get<Ip6::Udp>())
, mSocket(aInstance)
{
}
+1 -1
View File
@@ -73,7 +73,7 @@ Dtls::Dtls(Instance &aInstance, bool aLayerTwoSecurity)
, mConnectedHandler(nullptr)
, mReceiveHandler(nullptr)
, mContext(nullptr)
, mSocket(Get<Ip6::Udp>())
, mSocket(aInstance)
, mTransportCallback(nullptr)
, mTransportContext(nullptr)
, mMessageSubType(Message::kSubTypeNone)
+1 -1
View File
@@ -56,7 +56,7 @@ namespace MeshCoP {
JoinerRouter::JoinerRouter(Instance &aInstance)
: InstanceLocator(aInstance)
, Notifier::Receiver(aInstance, JoinerRouter::HandleNotifierEvents)
, mSocket(aInstance.Get<Ip6::Udp>())
, mSocket(aInstance)
, mRelayTransmit(OT_URI_PATH_RELAY_TX, &JoinerRouter::HandleRelayTransmit, this)
, mTimer(aInstance, JoinerRouter::HandleTimer, this)
, mJoinerUdpPort(0)
+1 -1
View File
@@ -53,7 +53,7 @@ namespace Dhcp6 {
Dhcp6Client::Dhcp6Client(Instance &aInstance)
: InstanceLocator(aInstance)
, mSocket(Get<Ip6::Udp>())
, mSocket(aInstance)
, mTrickleTimer(aInstance, Dhcp6Client::HandleTrickleTimer, nullptr, this)
, mStartTime(0)
, mIdentityAssociationCurrent(nullptr)
+1 -1
View File
@@ -48,7 +48,7 @@ namespace Dhcp6 {
Dhcp6Server::Dhcp6Server(Instance &aInstance)
: InstanceLocator(aInstance)
, mSocket(Get<Ip6::Udp>())
, mSocket(aInstance)
, mPrefixAgentsCount(0)
, mPrefixAgentsMask(0)
{
+1 -1
View File
@@ -73,7 +73,7 @@ QueryMetadata::QueryMetadata(otDnsResponseHandler aHandler, void *aContext)
}
Client::Client(Ip6::Netif &aNetif)
: mSocket(aNetif.Get<Ip6::Udp>())
: mSocket(aNetif.GetInstance())
, mMessageId(0)
, mRetransmissionTimer(aNetif.GetInstance(), Client::HandleRetransmissionTimer, this)
{
+1 -1
View File
@@ -90,7 +90,7 @@ QueryMetadata::QueryMetadata(otSntpResponseHandler aHandler, void *aContext)
}
Client::Client(Ip6::Netif &aNetif)
: mSocket(aNetif.Get<Ip6::Udp>())
: mSocket(aNetif.GetInstance())
, mRetransmissionTimer(aNetif.GetInstance(), Client::HandleRetransmissionTimer, this)
, mUnixEra(0)
{
+189 -167
View File
@@ -48,168 +48,7 @@ using ot::Encoding::BigEndian::HostSwap16;
namespace ot {
namespace Ip6 {
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
static bool IsMle(Instance &aInstance, uint16_t aPort)
{
#if OPENTHREAD_FTD
return aPort == ot::Mle::kUdpPort || aPort == aInstance.Get<MeshCoP::JoinerRouter>().GetJoinerUdpPort();
#else
OT_UNUSED_VARIABLE(aInstance);
return aPort == ot::Mle::kUdpPort;
#endif
}
#endif
Udp::Socket::Socket(Udp &aUdp)
: InstanceLocator(aUdp.GetInstance())
{
mHandle = nullptr;
}
Message *Udp::Socket::NewMessage(uint16_t aReserved, const Message::Settings &aSettings)
{
return Get<Udp>().NewMessage(aReserved, aSettings);
}
otError Udp::Socket::Open(otUdpReceive aHandler, void *aContext)
{
otError error = OT_ERROR_NONE;
GetSockName().Clear();
GetPeerName().Clear();
mHandler = aHandler;
mContext = aContext;
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
SuccessOrExit(error = otPlatUdpSocket(this));
#endif
Get<Udp>().AddSocket(*this);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
exit:
#endif
return error;
}
otError Udp::Socket::Bind(const SockAddr &aSockAddr)
{
otError error = OT_ERROR_NONE;
mSockName = aSockAddr;
if (!IsBound())
{
do
{
mSockName.mPort = Get<Udp>().GetEphemeralPort();
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpBind(this);
#endif
} while (error != OT_ERROR_NONE);
}
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
else if (!IsMle(GetInstance(), mSockName.mPort))
{
error = otPlatUdpBind(this);
}
#endif
return error;
}
otError Udp::Socket::Connect(const SockAddr &aSockAddr)
{
otError error = OT_ERROR_NONE;
mPeerName = aSockAddr;
if (!IsBound())
{
SuccessOrExit(error = Bind(GetSockName()));
}
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
if (!IsMle(GetInstance(), mSockName.mPort))
{
error = otPlatUdpConnect(this);
}
#endif
exit:
return error;
}
otError Udp::Socket::Close(void)
{
otError error = OT_ERROR_NONE;
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
SuccessOrExit(error = otPlatUdpClose(this));
#endif
Get<Udp>().RemoveSocket(*this);
GetSockName().Clear();
GetPeerName().Clear();
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
exit:
#endif
return error;
}
otError Udp::Socket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo)
{
otError error = OT_ERROR_NONE;
MessageInfo messageInfoLocal;
VerifyOrExit((aMessageInfo.GetSockPort() == 0) || (GetSockName().mPort == aMessageInfo.GetSockPort()),
error = OT_ERROR_INVALID_ARGS);
messageInfoLocal = aMessageInfo;
if (messageInfoLocal.GetPeerAddr().IsUnspecified())
{
VerifyOrExit(!GetPeerName().GetAddress().IsUnspecified(), error = OT_ERROR_INVALID_ARGS);
messageInfoLocal.SetPeerAddr(GetPeerName().GetAddress());
}
if (messageInfoLocal.mPeerPort == 0)
{
VerifyOrExit(GetPeerName().mPort != 0, error = OT_ERROR_INVALID_ARGS);
messageInfoLocal.mPeerPort = GetPeerName().mPort;
}
if (messageInfoLocal.GetSockAddr().IsUnspecified())
{
messageInfoLocal.SetSockAddr(GetSockName().GetAddress());
}
if (!IsBound())
{
SuccessOrExit(error = Bind(GetSockName()));
}
messageInfoLocal.SetSockPort(GetSockName().mPort);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
if (!IsMle(GetInstance(), mSockName.mPort) &&
!(mSockName.mPort == ot::kCoapUdpPort && aMessage.GetSubType() == Message::kSubTypeJoinerEntrust))
{
SuccessOrExit(error = otPlatUdpSend(this, &aMessage, &messageInfoLocal));
}
else
#endif
{
SuccessOrExit(error = Get<Udp>().SendDatagram(aMessage, messageInfoLocal, kProtoUdp));
}
exit:
return error;
}
bool Udp::Socket::Matches(const MessageInfo &aMessageInfo) const
bool Udp::SocketHandle::Matches(const MessageInfo &aMessageInfo) const
{
bool matches = false;
@@ -235,6 +74,42 @@ exit:
return matches;
}
Udp::Socket::Socket(Instance &aInstance)
: InstanceLocator(aInstance)
{
mHandle = nullptr;
}
Message *Udp::Socket::NewMessage(uint16_t aReserved, const Message::Settings &aSettings)
{
return Get<Udp>().NewMessage(aReserved, aSettings);
}
otError Udp::Socket::Open(otUdpReceive aHandler, void *aContext)
{
return Get<Udp>().Open(*this, aHandler, aContext);
}
otError Udp::Socket::Bind(const SockAddr &aSockAddr)
{
return Get<Udp>().Bind(*this, aSockAddr);
}
otError Udp::Socket::Connect(const SockAddr &aSockAddr)
{
return Get<Udp>().Connect(*this, aSockAddr);
}
otError Udp::Socket::Close(void)
{
return Get<Udp>().Close(*this);
}
otError Udp::Socket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo)
{
return Get<Udp>().SendTo(*this, aMessage, aMessageInfo);
}
Udp::Udp(Instance &aInstance)
: InstanceLocator(aInstance)
, mEphemeralPort(kDynamicPortMin)
@@ -263,12 +138,148 @@ exit:
return error;
}
void Udp::AddSocket(Socket &aSocket)
otError Udp::Open(SocketHandle &aSocket, otUdpReceive aHandler, void *aContext)
{
otError error = OT_ERROR_NONE;
aSocket.GetSockName().Clear();
aSocket.GetPeerName().Clear();
aSocket.mHandler = aHandler;
aSocket.mContext = aContext;
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpSocket(&aSocket);
#endif
SuccessOrExit(error);
AddSocket(aSocket);
exit:
return error;
}
otError Udp::Bind(SocketHandle &aSocket, const SockAddr &aSockAddr)
{
otError error = OT_ERROR_NONE;
aSocket.mSockName = aSockAddr;
if (!aSocket.IsBound())
{
do
{
aSocket.mSockName.mPort = GetEphemeralPort();
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpBind(&aSocket);
#endif
} while (error != OT_ERROR_NONE);
}
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
else if (!IsMlePort(aSocket.mSockName.mPort))
{
error = otPlatUdpBind(&aSocket);
}
#endif
return error;
}
otError Udp::Connect(SocketHandle &aSocket, const SockAddr &aSockAddr)
{
otError error = OT_ERROR_NONE;
aSocket.mPeerName = aSockAddr;
if (!aSocket.IsBound())
{
SuccessOrExit(error = Bind(aSocket, aSocket.GetSockName()));
}
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
if (!IsMlePort(aSocket.mSockName.mPort))
{
error = otPlatUdpConnect(&aSocket);
}
#endif
exit:
return error;
}
otError Udp::Close(SocketHandle &aSocket)
{
otError error = OT_ERROR_NONE;
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
error = otPlatUdpClose(&aSocket);
#endif
SuccessOrExit(error);
RemoveSocket(aSocket);
aSocket.GetSockName().Clear();
aSocket.GetPeerName().Clear();
exit:
return error;
}
otError Udp::SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo &aMessageInfo)
{
otError error = OT_ERROR_NONE;
MessageInfo messageInfoLocal;
VerifyOrExit((aMessageInfo.GetSockPort() == 0) || (aSocket.GetSockName().mPort == aMessageInfo.GetSockPort()),
error = OT_ERROR_INVALID_ARGS);
messageInfoLocal = aMessageInfo;
if (messageInfoLocal.GetPeerAddr().IsUnspecified())
{
VerifyOrExit(!aSocket.GetPeerName().GetAddress().IsUnspecified(), error = OT_ERROR_INVALID_ARGS);
messageInfoLocal.SetPeerAddr(aSocket.GetPeerName().GetAddress());
}
if (messageInfoLocal.mPeerPort == 0)
{
VerifyOrExit(aSocket.GetPeerName().mPort != 0, error = OT_ERROR_INVALID_ARGS);
messageInfoLocal.mPeerPort = aSocket.GetPeerName().mPort;
}
if (messageInfoLocal.GetSockAddr().IsUnspecified())
{
messageInfoLocal.SetSockAddr(aSocket.GetSockName().GetAddress());
}
if (!aSocket.IsBound())
{
SuccessOrExit(error = Bind(aSocket, aSocket.GetSockName()));
}
messageInfoLocal.SetSockPort(aSocket.GetSockName().mPort);
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
if (!IsMlePort(aSocket.mSockName.mPort) &&
!(aSocket.mSockName.mPort == ot::kCoapUdpPort && aMessage.GetSubType() == Message::kSubTypeJoinerEntrust))
{
SuccessOrExit(error = otPlatUdpSend(&aSocket, &aMessage, &messageInfoLocal));
}
else
#endif
{
SuccessOrExit(error = SendDatagram(aMessage, messageInfoLocal, kProtoUdp));
}
exit:
return error;
}
void Udp::AddSocket(SocketHandle &aSocket)
{
IgnoreError(mSockets.Add(aSocket));
}
void Udp::RemoveSocket(Socket &aSocket)
void Udp::RemoveSocket(SocketHandle &aSocket)
{
SuccessOrExit(mSockets.Remove(aSocket));
aSocket.SetNext(nullptr);
@@ -358,7 +369,7 @@ otError Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo)
aMessageInfo.mSockPort = udpHeader.GetDestinationPort();
#if OPENTHREAD_CONFIG_PLATFORM_UDP_ENABLE
VerifyOrExit(IsMle(GetInstance(), aMessageInfo.mSockPort), OT_NOOP);
VerifyOrExit(IsMlePort(aMessageInfo.mSockPort), OT_NOOP);
#endif
for (Receiver *receiver = mReceivers.GetHead(); receiver; receiver = receiver->GetNext())
@@ -374,8 +385,8 @@ exit:
void Udp::HandlePayload(Message &aMessage, MessageInfo &aMessageInfo)
{
Socket *socket;
Socket *prev;
SocketHandle *socket;
SocketHandle *prev;
socket = mSockets.FindMatching(aMessageInfo, prev);
VerifyOrExit(socket != nullptr, OT_NOOP);
@@ -401,5 +412,16 @@ void Udp::UpdateChecksum(Message &aMessage, uint16_t aChecksum)
aMessage.Write(aMessage.GetOffset() + Header::kChecksumFieldOffset, sizeof(aChecksum), &aChecksum);
}
bool Udp::IsMlePort(uint16_t aPort) const
{
bool isMlePort = (aPort == Mle::kUdpPort);
#if OPENTHREAD_FTD
isMlePort = isMlePort || (aPort == Get<MeshCoP::JoinerRouter>().GetJoinerUdpPort());
#endif
return isMlePort;
}
} // namespace Ip6
} // namespace ot
+148 -88
View File
@@ -68,54 +68,12 @@ public:
* This class implements a UDP/IPv6 socket.
*
*/
class Socket : public otUdpSocket, public InstanceLocator, public LinkedListEntry<Socket>
class SocketHandle : public otUdpSocket, public LinkedListEntry<SocketHandle>
{
friend class Udp;
friend class LinkedList<Socket>;
friend class LinkedList<SocketHandle>;
public:
/**
* This constructor initializes the object.
*
* @param[in] aUdp A reference to the UDP transport object.
*
*/
explicit Socket(Udp &aUdp);
/**
* This method returns a new UDP message with sufficient header space reserved.
*
* @param[in] aReserved The number of header bytes to reserve after the UDP header.
* @param[in] aSettings The message settings (default is used if not provided).
*
* @returns A pointer to the message or nullptr if no buffers are available.
*
*/
Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault());
/**
* This method opens the UDP socket.
*
* @param[in] aHandler A pointer to a function that is called when receiving UDP messages.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval OT_ERROR_NONE Successfully opened the socket.
* @retval OT_ERROR_ALREADY The socket is already open.
*
*/
otError Open(otUdpReceive aHandler, void *aContext);
/**
* This method binds the UDP socket.
*
* @param[in] aSockAddr A reference to the socket address.
*
* @retval OT_ERROR_NONE Successfully bound the socket.
* @retval OT_ERROR_FAILED Failed to bind UDP Socket.
*
*/
otError Bind(const SockAddr &aSockAddr);
/**
* This method indicates whether or not the socket is bound.
*
@@ -125,39 +83,6 @@ public:
*/
bool IsBound(void) const { return mSockName.mPort != 0; }
/**
* This method connects the UDP socket.
*
* @param[in] aSockAddr A reference to the socket address.
*
* @retval OT_ERROR_NONE Successfully connected the socket.
* @retval OT_ERROR_FAILED Failed to connect UDP Socket.
*
*/
otError Connect(const SockAddr &aSockAddr);
/**
* This method closes the UDP socket.
*
* @retval OT_ERROR_NONE Successfully closed the UDP socket.
* @retval OT_ERROR_FAILED Failed to close UDP Socket.
*
*/
otError Close(void);
/**
* This method sends a UDP message.
*
* @param[in] aMessage The message to send.
* @param[in] aMessageInfo The message info associated with @p aMessage.
*
* @retval OT_ERROR_NONE Successfully sent the UDP message.
* @retval OT_ERROR_INVALID_ARGS If no peer is specified in @p aMessageInfo or by connect().
* @retval OT_ERROR_NO_BUFS Insufficient available buffer to add the UDP and IPv6 headers.
*
*/
otError SendTo(Message &aMessage, const MessageInfo &aMessageInfo);
/**
* This method returns the local socket address.
*
@@ -199,6 +124,91 @@ public:
}
};
/**
* This class implements a UDP/IPv6 socket.
*
*/
class Socket : public InstanceLocator, public SocketHandle
{
friend class Udp;
public:
/**
* This constructor initializes the object.
*
* @param[in] aInstance A reference to OpenThread instance.
*
*/
explicit Socket(Instance &aInstance);
/**
* This method returns a new UDP message with sufficient header space reserved.
*
* @param[in] aReserved The number of header bytes to reserve after the UDP header.
* @param[in] aSettings The message settings (default is used if not provided).
*
* @returns A pointer to the message or nullptr if no buffers are available.
*
*/
Message *NewMessage(uint16_t aReserved, const Message::Settings &aSettings = Message::Settings::GetDefault());
/**
* This method opens the UDP socket.
*
* @param[in] aHandler A pointer to a function that is called when receiving UDP messages.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval OT_ERROR_NONE Successfully opened the socket.
* @retval OT_ERROR_FAILED Failed to open the socket.
*
*/
otError Open(otUdpReceive aHandler, void *aContext);
/**
* This method binds the UDP socket.
*
* @param[in] aSockAddr A reference to the socket address.
*
* @retval OT_ERROR_NONE Successfully bound the socket.
* @retval OT_ERROR_FAILED Failed to bind UDP Socket.
*
*/
otError Bind(const SockAddr &aSockAddr);
/**
* This method connects the UDP socket.
*
* @param[in] aSockAddr A reference to the socket address.
*
* @retval OT_ERROR_NONE Successfully connected the socket.
* @retval OT_ERROR_FAILED Failed to connect UDP Socket.
*
*/
otError Connect(const SockAddr &aSockAddr);
/**
* This method closes the UDP socket.
*
* @retval OT_ERROR_NONE Successfully closed the UDP socket.
* @retval OT_ERROR_FAILED Failed to close UDP Socket.
*
*/
otError Close(void);
/**
* This method sends a UDP message.
*
* @param[in] aMessage The message to send.
* @param[in] aMessageInfo The message info associated with @p aMessage.
*
* @retval OT_ERROR_NONE Successfully sent the UDP message.
* @retval OT_ERROR_INVALID_ARGS If no peer is specified in @p aMessageInfo or by Connect().
* @retval OT_ERROR_NO_BUFS Insufficient available buffer to add the UDP and IPv6 headers.
*
*/
otError SendTo(Message &aMessage, const MessageInfo &aMessageInfo);
};
/**
* This class implements a UDP receiver.
*
@@ -320,7 +330,7 @@ public:
/**
* This constructor initializes the object.
*
* @param[in] aIp6 A reference to OpenThread instance.
* @param[in] aInstance A reference to OpenThread instance.
*
*/
explicit Udp(Instance &aInstance);
@@ -348,20 +358,66 @@ public:
otError RemoveReceiver(Receiver &aReceiver);
/**
* This method adds a UDP socket.
* This method opens a UDP socket.
*
* @param[in] aSocket A reference to the UDP socket.
* @param[in] aSocket A reference to the socket.
* @param[in] aHandler A pointer to a function that is called when receiving UDP messages.
* @param[in] aContext A pointer to arbitrary context information.
*
* @retval OT_ERROR_NONE Successfully opened the socket.
* @retval OT_ERROR_FAILED Failed to open the socket.
*
*/
void AddSocket(Socket &aSocket);
otError Open(SocketHandle &aSocket, otUdpReceive aHandler, void *aContext);
/**
* This method removes a UDP socket.
* This method binds a UDP socket.
*
* @param[in] aSocket A reference to the UDP socket.
* @param[in] aSocket A reference to the socket.
* @param[in] aSockAddr A reference to the socket address.
*
* @retval OT_ERROR_NONE Successfully bound the socket.
* @retval OT_ERROR_FAILED Failed to bind UDP Socket.
*
*/
void RemoveSocket(Socket &aSocket);
otError Bind(SocketHandle &aSocket, const SockAddr &aSockAddr);
/**
* This method connects a UDP socket.
*
* @param[in] aSocket A reference to the socket.
* @param[in] aSockAddr A reference to the socket address.
*
* @retval OT_ERROR_NONE Successfully connected the socket.
* @retval OT_ERROR_FAILED Failed to connect UDP Socket.
*
*/
otError Connect(SocketHandle &aSocket, const SockAddr &aSockAddr);
/**
* This method closes the UDP socket.
*
* @param[in] aSocket A reference to the socket.
*
* @retval OT_ERROR_NONE Successfully closed the UDP socket.
* @retval OT_ERROR_FAILED Failed to close UDP Socket.
*
*/
otError Close(SocketHandle &aSocket);
/**
* This method sends a UDP message using a socket.
*
* @param[in] aSocket A reference to the socket.
* @param[in] aMessage The message to send.
* @param[in] aMessageInfo The message info associated with @p aMessage.
*
* @retval OT_ERROR_NONE Successfully sent the UDP message.
* @retval OT_ERROR_INVALID_ARGS If no peer is specified in @p aMessageInfo or by Connect().
* @retval OT_ERROR_NO_BUFS Insufficient available buffer to add the UDP and IPv6 headers.
*
*/
otError SendTo(SocketHandle &aSocket, Message &aMessage, const MessageInfo &aMessageInfo);
/**
* This method returns a new ephemeral port.
@@ -431,7 +487,7 @@ public:
* @returns A pointer to the head of UDP Socket linked list.
*
*/
Socket *GetUdpSockets(void) { return mSockets.GetHead(); }
SocketHandle *GetUdpSockets(void) { return mSockets.GetHead(); }
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
/**
@@ -455,9 +511,13 @@ private:
kDynamicPortMax = 65535, ///< Service Name and Transport Protocol Port Number Registry
};
uint16_t mEphemeralPort;
LinkedList<Receiver> mReceivers;
LinkedList<Socket> mSockets;
void AddSocket(SocketHandle &aSocket);
void RemoveSocket(SocketHandle &aSocket);
bool IsMlePort(uint16_t aPort) const;
uint16_t mEphemeralPort;
LinkedList<Receiver> mReceivers;
LinkedList<SocketHandle> mSockets;
#if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
void * mUdpForwarderContext;
otUdpForwarder mUdpForwarder;
+1 -1
View File
@@ -89,7 +89,7 @@ Mle::Mle(Instance &aInstance)
, mParentLinkMargin(0)
, mParentIsSingleton(false)
, mReceivedResponseFromParent(false)
, mSocket(aInstance.Get<Ip6::Udp>())
, mSocket(aInstance)
, mTimeout(kMleEndDeviceTimeout)
#if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
, mPreviousParentRloc(Mac::kShortAddrInvalid)