From dc1d47d2c0f36e1ef5004adcf7e4bd4ba4f1372c Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Tue, 14 Jul 2020 10:03:03 -0700 Subject: [PATCH] [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`. --- include/openthread/instance.h | 2 +- include/openthread/udp.h | 83 +++---- src/cli/cli_udp.cpp | 8 +- src/core/api/udp_api.cpp | 56 ++--- src/core/coap/coap.cpp | 2 +- src/core/meshcop/dtls.cpp | 2 +- src/core/meshcop/joiner_router.cpp | 2 +- src/core/net/dhcp6_client.cpp | 2 +- src/core/net/dhcp6_server.cpp | 2 +- src/core/net/dns_client.cpp | 2 +- src/core/net/sntp_client.cpp | 2 +- src/core/net/udp6.cpp | 356 +++++++++++++++-------------- src/core/net/udp6.hpp | 236 ++++++++++++------- src/core/thread/mle.cpp | 2 +- 14 files changed, 408 insertions(+), 349 deletions(-) diff --git a/include/openthread/instance.h b/include/openthread/instance.h index af9f2d9b5..e0e4010bb 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -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 diff --git a/include/openthread/udp.h b/include/openthread/udp.h index 6e925ff04..f11d5d740 100644 --- a/include/openthread/udp.h +++ b/include/openthread/udp.h @@ -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); - /** * @} * diff --git a/src/cli/cli_udp.cpp b/src/cli/cli_udp.cpp index 24bdbe5df..145490819 100644 --- a/src/cli/cli_udp.cpp +++ b/src/cli/cli_udp.cpp @@ -86,7 +86,7 @@ otError UdpExample::ProcessBind(uint8_t aArgsLength, char *aArgs[]) sockaddr.mPort = static_cast(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(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: diff --git a/src/core/api/udp_api.cpp b/src/core/api/udp_api.cpp index 2cd17a7c3..bd907e721 100644 --- a/src/core/api/udp_api.cpp +++ b/src/core/api/udp_api.cpp @@ -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(aInstance); - Ip6::Udp::Socket &socket = *new (aSocket) Ip6::Udp::Socket(instance.Get()); + Instance &instance = *static_cast(aInstance); - error = socket.Open(aCallback, aContext); - - return error; + return instance.Get().Open(*static_cast(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(aSocket); + Instance &instance = *static_cast(aInstance); - error = socket.Close(); - - return error; + return instance.Get().Close(*static_cast(aSocket)); } -otError otUdpBind(otUdpSocket *aSocket, otSockAddr *aSockName) +otError otUdpBind(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName) { - Ip6::Udp::Socket &socket = *static_cast(aSocket); - return socket.Bind(*static_cast(aSockName)); + Instance &instance = *static_cast(aInstance); + + return instance.Get().Bind(*static_cast(aSocket), + *static_cast(aSockName)); } -otError otUdpConnect(otUdpSocket *aSocket, otSockAddr *aSockName) +otError otUdpConnect(otInstance *aInstance, otUdpSocket *aSocket, const otSockAddr *aSockName) { - Ip6::Udp::Socket &socket = *static_cast(aSocket); - return socket.Connect(*static_cast(aSockName)); + Instance &instance = *static_cast(aInstance); + + return instance.Get().Connect(*static_cast(aSocket), + *static_cast(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(aSocket); - return socket.SendTo(*static_cast(aMessage), *static_cast(aMessageInfo)); + Instance &instance = *static_cast(aInstance); + + return instance.Get().SendTo(*static_cast(aSocket), + *static_cast(aMessage), + *static_cast(aMessageInfo)); +} + +otUdpSocket *otUdpGetSockets(otInstance *aInstance) +{ + Instance &instance = *static_cast(aInstance); + + return instance.Get().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(aInstance); - - return instance.Get().GetUdpSockets(); -} - otError otUdpAddReceiver(otInstance *aInstance, otUdpReceiver *aUdpReceiver) { Instance &instance = *static_cast(aInstance); diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp index 9f7e27102..5e345392c 100644 --- a/src/core/coap/coap.cpp +++ b/src/core/coap/coap.cpp @@ -1014,7 +1014,7 @@ const otCoapTxParameters TxParameters::kDefaultTxParameters = { Coap::Coap(Instance &aInstance) : CoapBase(aInstance, &Coap::Send) - , mSocket(aInstance.Get()) + , mSocket(aInstance) { } diff --git a/src/core/meshcop/dtls.cpp b/src/core/meshcop/dtls.cpp index 9364f1529..a97d79acd 100644 --- a/src/core/meshcop/dtls.cpp +++ b/src/core/meshcop/dtls.cpp @@ -73,7 +73,7 @@ Dtls::Dtls(Instance &aInstance, bool aLayerTwoSecurity) , mConnectedHandler(nullptr) , mReceiveHandler(nullptr) , mContext(nullptr) - , mSocket(Get()) + , mSocket(aInstance) , mTransportCallback(nullptr) , mTransportContext(nullptr) , mMessageSubType(Message::kSubTypeNone) diff --git a/src/core/meshcop/joiner_router.cpp b/src/core/meshcop/joiner_router.cpp index 1d4b69e80..51075627b 100644 --- a/src/core/meshcop/joiner_router.cpp +++ b/src/core/meshcop/joiner_router.cpp @@ -56,7 +56,7 @@ namespace MeshCoP { JoinerRouter::JoinerRouter(Instance &aInstance) : InstanceLocator(aInstance) , Notifier::Receiver(aInstance, JoinerRouter::HandleNotifierEvents) - , mSocket(aInstance.Get()) + , mSocket(aInstance) , mRelayTransmit(OT_URI_PATH_RELAY_TX, &JoinerRouter::HandleRelayTransmit, this) , mTimer(aInstance, JoinerRouter::HandleTimer, this) , mJoinerUdpPort(0) diff --git a/src/core/net/dhcp6_client.cpp b/src/core/net/dhcp6_client.cpp index 45841fa66..63faa1ca7 100644 --- a/src/core/net/dhcp6_client.cpp +++ b/src/core/net/dhcp6_client.cpp @@ -53,7 +53,7 @@ namespace Dhcp6 { Dhcp6Client::Dhcp6Client(Instance &aInstance) : InstanceLocator(aInstance) - , mSocket(Get()) + , mSocket(aInstance) , mTrickleTimer(aInstance, Dhcp6Client::HandleTrickleTimer, nullptr, this) , mStartTime(0) , mIdentityAssociationCurrent(nullptr) diff --git a/src/core/net/dhcp6_server.cpp b/src/core/net/dhcp6_server.cpp index bf99652aa..6bf2368c2 100644 --- a/src/core/net/dhcp6_server.cpp +++ b/src/core/net/dhcp6_server.cpp @@ -48,7 +48,7 @@ namespace Dhcp6 { Dhcp6Server::Dhcp6Server(Instance &aInstance) : InstanceLocator(aInstance) - , mSocket(Get()) + , mSocket(aInstance) , mPrefixAgentsCount(0) , mPrefixAgentsMask(0) { diff --git a/src/core/net/dns_client.cpp b/src/core/net/dns_client.cpp index a8afec9f0..0919d6256 100644 --- a/src/core/net/dns_client.cpp +++ b/src/core/net/dns_client.cpp @@ -73,7 +73,7 @@ QueryMetadata::QueryMetadata(otDnsResponseHandler aHandler, void *aContext) } Client::Client(Ip6::Netif &aNetif) - : mSocket(aNetif.Get()) + : mSocket(aNetif.GetInstance()) , mMessageId(0) , mRetransmissionTimer(aNetif.GetInstance(), Client::HandleRetransmissionTimer, this) { diff --git a/src/core/net/sntp_client.cpp b/src/core/net/sntp_client.cpp index d7f7a417b..a8bc0e46c 100644 --- a/src/core/net/sntp_client.cpp +++ b/src/core/net/sntp_client.cpp @@ -90,7 +90,7 @@ QueryMetadata::QueryMetadata(otSntpResponseHandler aHandler, void *aContext) } Client::Client(Ip6::Netif &aNetif) - : mSocket(aNetif.Get()) + : mSocket(aNetif.GetInstance()) , mRetransmissionTimer(aNetif.GetInstance(), Client::HandleRetransmissionTimer, this) , mUnixEra(0) { diff --git a/src/core/net/udp6.cpp b/src/core/net/udp6.cpp index 9174eecfe..f0743a8a3 100644 --- a/src/core/net/udp6.cpp +++ b/src/core/net/udp6.cpp @@ -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().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().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().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().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().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().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().NewMessage(aReserved, aSettings); +} + +otError Udp::Socket::Open(otUdpReceive aHandler, void *aContext) +{ + return Get().Open(*this, aHandler, aContext); +} + +otError Udp::Socket::Bind(const SockAddr &aSockAddr) +{ + return Get().Bind(*this, aSockAddr); +} + +otError Udp::Socket::Connect(const SockAddr &aSockAddr) +{ + return Get().Connect(*this, aSockAddr); +} + +otError Udp::Socket::Close(void) +{ + return Get().Close(*this); +} + +otError Udp::Socket::SendTo(Message &aMessage, const MessageInfo &aMessageInfo) +{ + return Get().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().GetJoinerUdpPort()); +#endif + + return isMlePort; +} + } // namespace Ip6 } // namespace ot diff --git a/src/core/net/udp6.hpp b/src/core/net/udp6.hpp index 35abc5169..5cc29fe7f 100644 --- a/src/core/net/udp6.hpp +++ b/src/core/net/udp6.hpp @@ -68,54 +68,12 @@ public: * This class implements a UDP/IPv6 socket. * */ - class Socket : public otUdpSocket, public InstanceLocator, public LinkedListEntry + class SocketHandle : public otUdpSocket, public LinkedListEntry { friend class Udp; - friend class LinkedList; + friend class LinkedList; 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 mReceivers; - LinkedList mSockets; + void AddSocket(SocketHandle &aSocket); + void RemoveSocket(SocketHandle &aSocket); + bool IsMlePort(uint16_t aPort) const; + + uint16_t mEphemeralPort; + LinkedList mReceivers; + LinkedList mSockets; #if OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE void * mUdpForwarderContext; otUdpForwarder mUdpForwarder; diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 219197562..afc72e826 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -89,7 +89,7 @@ Mle::Mle(Instance &aInstance) , mParentLinkMargin(0) , mParentIsSingleton(false) , mReceivedResponseFromParent(false) - , mSocket(aInstance.Get()) + , mSocket(aInstance) , mTimeout(kMleEndDeviceTimeout) #if OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH , mPreviousParentRloc(Mac::kShortAddrInvalid)