[udp6] use newly added linked-list to search for a matching socket (#5180)

This commit adds `UdpSocket::Matches()` to match a UDP socket with a
given `MessageInfo`. This is then used alongw with the newly added
linked-list `FindMatching()` method to find a matching socket from the
list of UDP sockets in `Udp::HandlePayload()`.
diff --git a/src/core/net/udp6.cpp b/src/core/net/udp6.cpp
index 0e9e498..9b74765 100644
--- a/src/core/net/udp6.cpp
+++ b/src/core/net/udp6.cpp
@@ -202,6 +202,32 @@
     return error;
 }
 
+bool UdpSocket::Matches(const MessageInfo &aMessageInfo) const
+{
+    bool matches = false;
+
+    VerifyOrExit(GetSockName().mPort == aMessageInfo.GetSockPort(), OT_NOOP);
+
+    VerifyOrExit(aMessageInfo.GetSockAddr().IsMulticast() || GetSockName().GetAddress().IsUnspecified() ||
+                     GetSockName().GetAddress() == aMessageInfo.GetSockAddr(),
+                 OT_NOOP);
+
+    // Verify source if connected socket
+    if (GetPeerName().mPort != 0)
+    {
+        VerifyOrExit(GetPeerName().mPort == aMessageInfo.GetPeerPort(), OT_NOOP);
+
+        VerifyOrExit(GetPeerName().GetAddress().IsUnspecified() ||
+                         GetPeerName().GetAddress() == aMessageInfo.GetPeerAddr(),
+                     OT_NOOP);
+    }
+
+    matches = true;
+
+exit:
+    return matches;
+}
+
 Udp::Udp(Instance &aInstance)
     : InstanceLocator(aInstance)
     , mEphemeralPort(kDynamicPortMin)
@@ -341,40 +367,18 @@
 
 void Udp::HandlePayload(Message &aMessage, MessageInfo &aMessageInfo)
 {
-    // find socket
-    for (UdpSocket *socket = mSockets.GetHead(); socket; socket = socket->GetNext())
-    {
-        if (socket->GetSockName().mPort != aMessageInfo.GetSockPort())
-        {
-            continue;
-        }
+    UdpSocket *socket;
+    UdpSocket *prev;
 
-        if (!aMessageInfo.GetSockAddr().IsMulticast() && !socket->GetSockName().GetAddress().IsUnspecified() &&
-            socket->GetSockName().GetAddress() != aMessageInfo.GetSockAddr())
-        {
-            continue;
-        }
+    socket = mSockets.FindMatching(aMessageInfo, prev);
+    VerifyOrExit(socket != nullptr, OT_NOOP);
 
-        // verify source if connected socket
-        if (socket->GetPeerName().mPort != 0)
-        {
-            if (socket->GetPeerName().mPort != aMessageInfo.GetPeerPort())
-            {
-                continue;
-            }
+    aMessage.RemoveHeader(aMessage.GetOffset());
+    OT_ASSERT(aMessage.GetOffset() == 0);
+    socket->HandleUdpReceive(aMessage, aMessageInfo);
 
-            if (!socket->GetPeerName().GetAddress().IsUnspecified() &&
-                socket->GetPeerName().GetAddress() != aMessageInfo.GetPeerAddr())
-            {
-                continue;
-            }
-        }
-
-        aMessage.RemoveHeader(aMessage.GetOffset());
-        OT_ASSERT(aMessage.GetOffset() == 0);
-        socket->HandleUdpReceive(aMessage, aMessageInfo);
-        break;
-    }
+exit:
+    return;
 }
 
 void Udp::UpdateChecksum(Message &aMessage, uint16_t aChecksum)
diff --git a/src/core/net/udp6.hpp b/src/core/net/udp6.hpp
index b56a7ea..cca7cbe 100644
--- a/src/core/net/udp6.hpp
+++ b/src/core/net/udp6.hpp
@@ -94,6 +94,7 @@
 class UdpSocket : public otUdpSocket, public InstanceLocator, public LinkedListEntry<UdpSocket>
 {
     friend class Udp;
+    friend class LinkedList<UdpSocket>;
 
 public:
     /**
@@ -189,6 +190,14 @@
     SockAddr &GetSockName(void) { return *static_cast<SockAddr *>(&mSockName); }
 
     /**
+     * This method returns the local socket address.
+     *
+     * @returns A reference to the local socket address.
+     *
+     */
+    const SockAddr &GetSockName(void) const { return *static_cast<const SockAddr *>(&mSockName); }
+
+    /**
      * This method returns the peer's socket address.
      *
      * @returns A reference to the peer's socket address.
@@ -196,7 +205,17 @@
      */
     SockAddr &GetPeerName(void) { return *static_cast<SockAddr *>(&mPeerName); }
 
+    /**
+     * This method returns the peer's socket address.
+     *
+     * @returns A reference to the peer's socket address.
+     *
+     */
+    const SockAddr &GetPeerName(void) const { return *static_cast<const SockAddr *>(&mPeerName); }
+
 private:
+    bool Matches(const MessageInfo &aMessageInfo) const;
+
     void HandleUdpReceive(Message &aMessage, const MessageInfo &aMessageInfo)
     {
         mHandler(mContext, &aMessage, &aMessageInfo);