netipmid: move event loop to boost::asio::io_context

Replacing the event loop with asio provides for more flexibility and
less code than the sd_event model. Intially, this will require the loop
to handle both sd_events with a wrapper, but after all the sd_event
sources are replaced with asio event sources the wrapper can be removed.

Change-Id: Icf020c6c26a214bb1239641733c89603501c0c49
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/Makefile.am b/Makefile.am
index 352a20c..297aa9c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,3 +1,10 @@
+BOOST_CXX = \
+	-DBOOST_ERROR_CODE_HEADER_ONLY \
+	-DBOOST_SYSTEM_NO_DEPRECATED \
+	-DBOOST_COROUTINES_NO_DEPRECATION_WARNING \
+	-DBOOST_ASIO_DISABLE_THREADS \
+	-DBOOST_ALL_NO_LIB
+
 sbin_PROGRAMS = \
 	netipmid
 
@@ -71,6 +78,7 @@
 netipmid_CXXFLAGS = \
 	-flto \
 	$(SYSTEMD_CFLAGS) \
+	$(BOOST_CXX) \
 	$(libmapper_CFLAGS) \
 	$(PHOSPHOR_LOGGING_CFLAGS) \
 	$(PHOSPHOR_DBUS_INTERFACES_CFLAGS)
diff --git a/main.cpp b/main.cpp
index b142ed7..c3f3dfd 100644
--- a/main.cpp
+++ b/main.cpp
@@ -13,19 +13,20 @@
 #include <dirent.h>
 #include <dlfcn.h>
 #include <host-ipmid/ipmid-api.h>
-#include <systemd/sd-bus.h>
 #include <systemd/sd-daemon.h>
 #include <systemd/sd-event.h>
 #include <unistd.h>
 
 #include <iostream>
+#include <sdbusplus/asio/connection.hpp>
 #include <sdbusplus/timer.hpp>
 #include <tuple>
 
 // Tuple of Global Singletons
+static auto io = std::make_shared<boost::asio::io_context>();
 session::Manager manager;
 command::Table table;
-eventloop::EventLoop loop;
+eventloop::EventLoop loop(io);
 sol::Manager solManager;
 
 std::tuple<session::Manager&, command::Table&, eventloop::EventLoop&,
@@ -118,9 +119,8 @@
     {
         std::cerr << "Failed to connect to system bus:" << strerror(-rc)
                   << "\n";
-        goto finish;
+        return rc;
     }
-    sdbusp = std::make_shared<sdbusplus::bus::bus>(bus);
 
     /* Get an sd event handler */
     rc = sd_event_default(&events);
@@ -129,6 +129,7 @@
         std::cerr << "Failure to create sd_event" << strerror(-rc) << "\n";
         return EXIT_FAILURE;
     }
+    sdbusp = std::make_shared<sdbusplus::asio::connection>(*io, bus);
 
     // Register callback to update cache for a GUID change and cache the GUID
     command::registerGUIDChangeCallback();
@@ -144,11 +145,5 @@
     sol::command::registerCommands();
 
     // Start Event Loop
-    return std::get<eventloop::EventLoop&>(singletonPool)
-        .startEventLoop(events);
-
-finish:
-    sd_event_unref(events);
-
-    return 0;
+    return std::get<eventloop::EventLoop&>(singletonPool).startEventLoop();
 }
diff --git a/sd_event_loop.cpp b/sd_event_loop.cpp
index aa5224a..c6ad063 100644
--- a/sd_event_loop.cpp
+++ b/sd_event_loop.cpp
@@ -8,7 +8,9 @@
 #include <sys/socket.h>
 #include <systemd/sd-daemon.h>
 
+#include <boost/asio/io_context.hpp>
 #include <phosphor-logging/log.hpp>
+#include <sdbusplus/asio/sd_event.hpp>
 
 namespace eventloop
 {
@@ -170,35 +172,29 @@
     return 0;
 }
 
-int EventLoop::startEventLoop(sd_event* events)
+int EventLoop::startEventLoop()
 {
     int fd = -1;
     int r = 0;
     int listen_fd;
     sigset_t ss;
     sd_event_source* source = nullptr;
-    auto bus = ipmid_get_sd_bus_connection();
 
-    event = events;
-    // Attach the bus to sd_event to service user requests
-    r = sd_bus_attach_event(bus, event, SD_EVENT_PRIORITY_NORMAL);
-    if (r < 0)
-    {
-        goto finish;
-    }
+    sdbusplus::asio::sd_event_wrapper sdEvents(*io);
+    event = sdEvents.get();
 
     if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
         sigaddset(&ss, SIGINT) < 0)
     {
         r = -errno;
-        goto finish;
+        return EXIT_FAILURE;
     }
 
     /* Block SIGTERM first, so that the event loop can handle it */
     if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0)
     {
         r = -errno;
-        goto finish;
+        return EXIT_FAILURE;
     }
 
     /* Let's make use of the default handler and "floating" reference features
@@ -206,13 +202,13 @@
     r = sd_event_add_signal(event, nullptr, SIGTERM, nullptr, nullptr);
     if (r < 0)
     {
-        goto finish;
+        return EXIT_FAILURE;
     }
 
     r = sd_event_add_signal(event, nullptr, SIGINT, nullptr, nullptr);
     if (r < 0)
     {
-        goto finish;
+        return EXIT_FAILURE;
     }
 
     // Create our own socket if SysD did not supply one.
@@ -224,7 +220,7 @@
     else if (listen_fd > 1)
     {
         log<level::ERR>("Too many file descriptors received");
-        goto finish;
+        return 1;
     }
     else
     {
@@ -233,7 +229,7 @@
         {
             r = -errno;
             log<level::ERR>("Unable to manually open socket");
-            goto finish;
+            return EXIT_FAILURE;
         }
 
         address.sin_family = AF_INET;
@@ -244,35 +240,24 @@
         {
             r = -errno;
             log<level::ERR>("Unable to bind socket");
-            goto finish;
+            close(fd);
+            return EXIT_FAILURE;
         }
     }
 
     r = sd_event_add_io(event, &source, fd, EPOLLIN, udp623Handler, nullptr);
     if (r < 0)
     {
-        goto finish;
+        close(fd);
+        return EXIT_FAILURE;
     }
 
     udpIPMI.reset(source);
     source = nullptr;
 
-    r = sd_event_loop(event);
+    io->run();
 
-finish:
-
-    if (fd >= 0)
-    {
-        (void)close(fd);
-    }
-
-    if (r < 0)
-    {
-        log<level::ERR>("Event Loop Failure:",
-                        entry("FAILURE=%s", strerror(-r)));
-    }
-
-    return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+    return EXIT_SUCCESS;
 }
 
 void EventLoop::startHostConsole(const sol::CustomFD& fd)
diff --git a/sd_event_loop.hpp b/sd_event_loop.hpp
index 2faa7ad..5218b27 100644
--- a/sd_event_loop.hpp
+++ b/sd_event_loop.hpp
@@ -4,6 +4,7 @@
 
 #include <systemd/sd-event.h>
 
+#include <boost/asio/io_context.hpp>
 #include <chrono>
 #include <map>
 
@@ -42,7 +43,10 @@
 class EventLoop
 {
   public:
-    EventLoop() = default;
+    explicit EventLoop(std::shared_ptr<boost::asio::io_context> io) : io(io)
+    {
+    }
+    EventLoop() = delete;
     ~EventLoop() = default;
     EventLoop(const EventLoop&) = delete;
     EventLoop& operator=(const EventLoop&) = delete;
@@ -67,11 +71,10 @@
 
     /** @brief Initialise the event loop and add the handler for incoming
      *         IPMI packets.
-     *  @param[in] events- sd bus event;
      *
      *  @return EXIT_SUCCESS on success and EXIT_FAILURE on failure.
      */
-    int startEventLoop(sd_event* events);
+    int startEventLoop();
 
     /** @brief Add host console I/O event source to the event loop.
      *
@@ -139,6 +142,10 @@
     /** @brief Event source object for host console. */
     EventSource hostConsole = nullptr;
 
+    /** @brief boost::asio io context to run with
+     */
+    std::shared_ptr<boost::asio::io_context> io;
+
     /** @brief Event source for the UDP socket listening on IPMI standard
      *         port.
      */
diff --git a/test/Makefile.am b/test/Makefile.am
index b4996d0..49d96d4 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,3 +1,8 @@
+BOOST_CXX = -DBOOST_ERROR_CODE_HEADER_ONLY \
+            -DBOOST_SYSTEM_NO_DEPRECATED \
+            -DBOOST_COROUTINES_NO_DEPRECATION_WARNING \
+            -DBOOST_ALL_NO_LIB
+
 AM_CPPFLAGS = -I$(top_srcdir)
 
 # Run all 'check' test programs
@@ -6,7 +11,7 @@
 # # Build/add utest to test suite
 check_PROGRAMS = utest
 utest_CPPFLAGS = -Igtest $(GTEST_CPPFLAGS) $(AM_CPPFLAGS)
-utest_CXXFLAGS = $(PTHREAD_CFLAGS)
+utest_CXXFLAGS = $(PTHREAD_CFLAGS) $(BOOST_CXX)
 utest_LDFLAGS = -lgtest_main -lgtest $(PTHREAD_LIBS) $(OESDK_TESTCASE_FLAGS) $(CRYPTO_LIBS)
 utest_SOURCES = cipher.cpp
 utest_LDADD = \