kcsbridge: Daemon rewrite

This focuses on improving compile time, output size, and correctness
of command handling. Notably, it adds the ability for the host to cancel
outstanding IPMI calls when the host decides they should time out. It
ensures that canceled calls do not end up writing over the response for
an incoming request. Since the host can now cancel calls, we remove
internal DBus timeouts and instead require the host to drive any timeout
logic it desires for communications. This gives the host more control
and better adheres to the wishes of the specification.

Change-Id: I526169253931b9bcc4910afa0b54b304d4a9bef3
Signed-off-by: William A. Kennington III <wak@google.com>
diff --git a/src/server.cpp b/src/server.cpp
new file mode 100644
index 0000000..836ac43
--- /dev/null
+++ b/src/server.cpp
@@ -0,0 +1,72 @@
+#include "server.hpp"
+
+#include <fmt/format.h>
+#include <linux/ipmi_bmc.h>
+
+#include <sdbusplus/exception.hpp>
+#include <sdbusplus/server/interface.hpp>
+#include <sdbusplus/vtable.hpp>
+#include <stdplus/fd/ops.hpp>
+
+#include <stdexcept>
+
+namespace kcsbridge
+{
+
+void setAttention(sdbusplus::message::message& m, stdplus::Fd& kcs)
+{
+    stdplus::fd::ioctl(kcs, IPMI_BMC_IOCTL_SET_SMS_ATN, nullptr);
+    m.new_method_return().method_return();
+}
+
+void clearAttention(sdbusplus::message::message& m, stdplus::Fd& kcs)
+{
+    stdplus::fd::ioctl(kcs, IPMI_BMC_IOCTL_CLEAR_SMS_ATN, nullptr);
+    m.new_method_return().method_return();
+}
+
+void forceAbort(sdbusplus::message::message& m, stdplus::Fd& kcs)
+{
+    stdplus::fd::ioctl(kcs, IPMI_BMC_IOCTL_FORCE_ABORT, nullptr);
+    m.new_method_return().method_return();
+}
+
+template <auto func, typename Data>
+int methodRsp(sd_bus_message* mptr, void* dataptr, sd_bus_error* error) noexcept
+{
+    sdbusplus::message::message m(mptr);
+    try
+    {
+        func(m, *reinterpret_cast<Data*>(dataptr));
+    }
+    catch (const std::exception& e)
+    {
+        fmt::print(stderr, "Method response failed: {}\n", e.what());
+        sd_bus_error_set(error,
+                         "xyz.openbmc_project.Common.Error.InternalFailure",
+                         "The operation failed internally.");
+    }
+    return 1;
+}
+
+template <typename Data>
+constexpr sdbusplus::vtable::vtable_t dbusMethods[] = {
+    sdbusplus::vtable::start(),
+    sdbusplus::vtable::method("setAttention", "", "",
+                              methodRsp<setAttention, Data>),
+    sdbusplus::vtable::method("clearAttention", "", "",
+                              methodRsp<clearAttention, Data>),
+    sdbusplus::vtable::method("forceAbort", "", "",
+                              methodRsp<forceAbort, Data>),
+    sdbusplus::vtable::end(),
+};
+
+sdbusplus::server::interface::interface createSMSHandler(
+    sdbusplus::bus::bus& bus, const char* obj, stdplus::Fd& kcs)
+{
+    return sdbusplus::server::interface::interface(
+        bus, obj, "xyz.openbmc_project.Ipmi.Channel.SMS",
+        dbusMethods<stdplus::Fd>, reinterpret_cast<stdplus::Fd*>(&kcs));
+}
+
+} // namespace kcsbridge