rtnetlink_server: Use netlink parser code

Change-Id: I97a8fd1c692973a8ac97171dfaf309cfc9cfceb1
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/netlink.cpp b/src/netlink.cpp
index 5bc876f..ed1278f 100644
--- a/src/netlink.cpp
+++ b/src/netlink.cpp
@@ -78,53 +78,6 @@
     }
 }
 
-static void receive(int sock, ReceiveCallback cb)
-{
-    // We need to make sure we have enough room for an entire packet otherwise
-    // it gets truncated. The netlink docs guarantee packets will not exceed 8K
-    std::array<char, 8192> buf;
-
-    iovec iov{};
-    iov.iov_base = buf.data();
-    iov.iov_len = buf.size();
-
-    sockaddr_nl from{};
-    from.nl_family = AF_NETLINK;
-
-    msghdr hdr{};
-    hdr.msg_name = &from;
-    hdr.msg_namelen = sizeof(from);
-    hdr.msg_iov = &iov;
-    hdr.msg_iovlen = 1;
-
-    // We only do multiple recvs if we have a MULTI type message
-    bool done = true;
-    do
-    {
-        ssize_t recvd = recvmsg(sock, &hdr, 0);
-        if (recvd < 0)
-        {
-            throw std::system_error(errno, std::generic_category(),
-                                    "netlink recvmsg");
-        }
-        if (recvd == 0)
-        {
-            throw std::runtime_error("netlink recvmsg: Got empty payload");
-        }
-
-        std::string_view msgs(buf.data(), recvd);
-        do
-        {
-            processMsg(msgs, done, cb);
-        } while (!done && !msgs.empty());
-
-        if (done && !msgs.empty())
-        {
-            throw std::runtime_error("Extra unprocessed netlink messages");
-        }
-    } while (!done);
-}
-
 static void requestSend(int sock, void* data, size_t size)
 {
     sockaddr_nl dst{};
@@ -170,6 +123,57 @@
 
 } // namespace detail
 
+void receive(int sock, ReceiveCallback cb)
+{
+    // We need to make sure we have enough room for an entire packet otherwise
+    // it gets truncated. The netlink docs guarantee packets will not exceed 8K
+    std::array<char, 8192> buf;
+
+    iovec iov{};
+    iov.iov_base = buf.data();
+    iov.iov_len = buf.size();
+
+    sockaddr_nl from{};
+    from.nl_family = AF_NETLINK;
+
+    msghdr hdr{};
+    hdr.msg_name = &from;
+    hdr.msg_namelen = sizeof(from);
+    hdr.msg_iov = &iov;
+    hdr.msg_iovlen = 1;
+
+    // We only do multiple recvs if we have a MULTI type message
+    bool done = true;
+    do
+    {
+        ssize_t recvd = recvmsg(sock, &hdr, 0);
+        if (recvd < 0)
+        {
+            throw std::system_error(errno, std::generic_category(),
+                                    "netlink recvmsg");
+        }
+        if (recvd == 0)
+        {
+            if (!done)
+            {
+                throw std::runtime_error("netlink recvmsg: Got empty payload");
+            }
+            return;
+        }
+
+        std::string_view msgs(buf.data(), recvd);
+        do
+        {
+            detail::processMsg(msgs, done, cb);
+        } while (!done && !msgs.empty());
+
+        if (done && !msgs.empty())
+        {
+            throw std::runtime_error("Extra unprocessed netlink messages");
+        }
+    } while (!done);
+}
+
 std::tuple<rtattr, std::string_view> extractRtAttr(std::string_view& data)
 {
     auto hdr = stdplus::raw::copyFrom<rtattr>(data);
diff --git a/src/netlink.hpp b/src/netlink.hpp
index 2168972..1260f8e 100644
--- a/src/netlink.hpp
+++ b/src/netlink.hpp
@@ -28,6 +28,13 @@
 
 } // namespace detail
 
+/** @brief Receives all outstanding messages on a netlink socket
+ *
+ *  @param[in] sock - The socket to receive the messages on
+ *  @param[in] cb   - Called for each response message payload
+ */
+void receive(int sock, ReceiveCallback cb);
+
 /* @brief Call on a block of rtattrs to parse a single one out
  *        Updates the input to remove the attr parsed out.
  *
diff --git a/src/network_manager_main.cpp b/src/network_manager_main.cpp
index 876ed0a..8f8a89e 100644
--- a/src/network_manager_main.cpp
+++ b/src/network_manager_main.cpp
@@ -289,7 +289,7 @@
     manager = std::make_unique<Manager>(bus, DEFAULT_OBJPATH, NETWORK_CONF_DIR);
 
     // RTNETLINK event handler
-    rtnetlink::Server svr(event);
+    netlink::Server svr(event);
 
 #ifdef SYNC_MAC_FROM_INVENTORY
     std::ifstream in(configFile);
diff --git a/src/rtnetlink_server.cpp b/src/rtnetlink_server.cpp
index d14b28e..cf68340 100644
--- a/src/rtnetlink_server.cpp
+++ b/src/rtnetlink_server.cpp
@@ -1,5 +1,6 @@
 #include "rtnetlink_server.hpp"
 
+#include "netlink.hpp"
 #include "types.hpp"
 
 #include <linux/netlink.h>
@@ -18,10 +19,11 @@
 
 extern std::unique_ptr<Timer> refreshObjectTimer;
 
-namespace rtnetlink
+namespace netlink
 {
 
-static bool shouldRefresh(const struct nlmsghdr& hdr, std::string_view data)
+static bool shouldRefresh(const struct nlmsghdr& hdr,
+                          std::string_view data) noexcept
 {
     switch (hdr.nlmsg_type)
     {
@@ -49,41 +51,17 @@
     return false;
 }
 
-/* Call Back for the sd event loop */
+static void handler(const nlmsghdr& hdr, std::string_view data)
+{
+    if (shouldRefresh(hdr, data) && !refreshObjectTimer->isEnabled())
+    {
+        refreshObjectTimer->restartOnce(refreshTimeout);
+    }
+}
+
 static void eventHandler(sdeventplus::source::IO&, int fd, uint32_t)
 {
-    std::array<char, BUFSIZE> buffer = {};
-    int len{};
-
-    auto netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer.data());
-
-    while ((len = recv(fd, netLinkHeader, buffer.size(), 0)) > 0)
-    {
-        for (; (NLMSG_OK(netLinkHeader, len)) &&
-               (netLinkHeader->nlmsg_type != NLMSG_DONE);
-             netLinkHeader = NLMSG_NEXT(netLinkHeader, len))
-        {
-            std::string_view data(
-                reinterpret_cast<const char*>(NLMSG_DATA(netLinkHeader)),
-                netLinkHeader->nlmsg_len - NLMSG_HDRLEN);
-            if (shouldRefresh(*netLinkHeader, data))
-            {
-                // starting the timer here to make sure that we don't want
-                // create the child objects multiple times.
-                if (!refreshObjectTimer->isEnabled())
-                {
-                    // if start timer throws exception then let the application
-                    // crash
-                    refreshObjectTimer->restartOnce(refreshTimeout);
-                } // end if
-            }     // end if
-
-        } // end for
-
-        buffer.fill('\0');
-
-        netLinkHeader = reinterpret_cast<struct nlmsghdr*>(buffer.data());
-    } // end while
+    receive(fd, handler);
 }
 
 static stdplus::ManagedFd makeSock()
@@ -109,6 +87,6 @@
 {
 }
 
-} // namespace rtnetlink
+} // namespace netlink
 } // namespace network
 } // namespace phosphor
diff --git a/src/rtnetlink_server.hpp b/src/rtnetlink_server.hpp
index 1e849ee..066f19c 100644
--- a/src/rtnetlink_server.hpp
+++ b/src/rtnetlink_server.hpp
@@ -3,16 +3,11 @@
 #include <sdeventplus/source/io.hpp>
 #include <stdplus/fd/managed.hpp>
 
-namespace sdeventplus
-{
-class Event;
-}
-
 namespace phosphor
 {
 namespace network
 {
-namespace rtnetlink
+namespace netlink
 {
 
 constexpr auto BUFSIZE = 4096;
@@ -22,7 +17,6 @@
     Usage would be create the server with the  call back
     and call the run method.
  */
-
 class Server
 {
 
@@ -47,6 +41,6 @@
     sdeventplus::source::IO io;
 };
 
-} // namespace rtnetlink
+} // namespace netlink
 } // namespace network
 } // namespace phosphor