[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`.
diff --git a/include/openthread/instance.h b/include/openthread/instance.h
index af9f2d9..e0e4010 100644
--- a/include/openthread/instance.h
+++ b/include/openthread/instance.h
@@ -53,7 +53,7 @@
* @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 6e925ff..f11d5d7 100644
--- a/include/openthread/udp.h
+++ b/include/openthread/udp.h
@@ -126,7 +126,7 @@
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 @@
* 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 @@
* @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 @@
* 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);
/**
* @}
@@ -303,16 +290,6 @@
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 24bdbe5..1454908 100644
--- a/src/cli/cli_udp.cpp
+++ b/src/cli/cli_udp.cpp
@@ -86,7 +86,7 @@
sockaddr.mPort = static_cast<uint16_t>(value);
- error = otUdpBind(&mSocket, &sockaddr);
+ error = otUdpBind(mInterpreter.mInstance, &mSocket, &sockaddr);
exit:
return error;
@@ -110,7 +110,7 @@
sockaddr.mPort = static_cast<uint16_t>(value);
- error = otUdpConnect(&mSocket, &sockaddr);
+ error = otUdpConnect(mInterpreter.mInstance, &mSocket, &sockaddr);
exit:
return error;
@@ -121,7 +121,7 @@
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 @@
}
}
- 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 2cd17a7..bd907e7 100644
--- a/src/core/api/udp_api.cpp
+++ b/src/core/api/udp_api.cpp
@@ -51,41 +51,48 @@
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 @@
}
#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);
diff --git a/src/core/coap/coap.cpp b/src/core/coap/coap.cpp
index 9f7e271..5e34539 100644
--- a/src/core/coap/coap.cpp
+++ b/src/core/coap/coap.cpp
@@ -1014,7 +1014,7 @@
Coap::Coap(Instance &aInstance)
: CoapBase(aInstance, &Coap::Send)
- , mSocket(aInstance.Get<Ip6::Udp>())
+ , mSocket(aInstance)
{
}
diff --git a/src/core/meshcop/dtls.cpp b/src/core/meshcop/dtls.cpp
index 9364f15..a97d79a 100644
--- a/src/core/meshcop/dtls.cpp
+++ b/src/core/meshcop/dtls.cpp
@@ -73,7 +73,7 @@
, mConnectedHandler(nullptr)
, mReceiveHandler(nullptr)
, mContext(nullptr)
- , mSocket(Get<Ip6::Udp>())
+ , 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 1d4b69e..5107562 100644
--- a/src/core/meshcop/joiner_router.cpp
+++ b/src/core/meshcop/joiner_router.cpp
@@ -56,7 +56,7 @@
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)
diff --git a/src/core/net/dhcp6_client.cpp b/src/core/net/dhcp6_client.cpp
index 45841fa..63faa1c 100644
--- a/src/core/net/dhcp6_client.cpp
+++ b/src/core/net/dhcp6_client.cpp
@@ -53,7 +53,7 @@
Dhcp6Client::Dhcp6Client(Instance &aInstance)
: InstanceLocator(aInstance)
- , mSocket(Get<Ip6::Udp>())
+ , 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 bf99652..6bf2368 100644
--- a/src/core/net/dhcp6_server.cpp
+++ b/src/core/net/dhcp6_server.cpp
@@ -48,7 +48,7 @@
Dhcp6Server::Dhcp6Server(Instance &aInstance)
: InstanceLocator(aInstance)
- , mSocket(Get<Ip6::Udp>())
+ , mSocket(aInstance)
, mPrefixAgentsCount(0)
, mPrefixAgentsMask(0)
{
diff --git a/src/core/net/dns_client.cpp b/src/core/net/dns_client.cpp
index a8afec9..0919d62 100644
--- a/src/core/net/dns_client.cpp
+++ b/src/core/net/dns_client.cpp
@@ -73,7 +73,7 @@
}
Client::Client(Ip6::Netif &aNetif)
- : mSocket(aNetif.Get<Ip6::Udp>())
+ : 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 d7f7a41..a8bc0e4 100644
--- a/src/core/net/sntp_client.cpp
+++ b/src/core/net/sntp_client.cpp
@@ -90,7 +90,7 @@
}
Client::Client(Ip6::Netif &aNetif)
- : mSocket(aNetif.Get<Ip6::Udp>())
+ : 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 9174eec..f0743a8 100644
--- a/src/core/net/udp6.cpp
+++ b/src/core/net/udp6.cpp
@@ -48,168 +48,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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
diff --git a/src/core/net/udp6.hpp b/src/core/net/udp6.hpp
index 35abc51..5cc29fe 100644
--- a/src/core/net/udp6.hpp
+++ b/src/core/net/udp6.hpp
@@ -68,55 +68,13 @@
* 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.
*
* @retval TRUE if the socket is bound (i.e. source port is non-zero).
@@ -126,39 +84,6 @@
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.
*
* @returns A reference to the local socket address.
@@ -200,6 +125,91 @@
};
/**
+ * 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 @@
/**
* 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 @@
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 @@
* @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 @@
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;
diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp
index 2191975..afc72e8 100644
--- a/src/core/thread/mle.cpp
+++ b/src/core/thread/mle.cpp
@@ -89,7 +89,7 @@
, 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)