From 7fd26ddbf61f0ba4958e9ee61f342a8859deb79b Mon Sep 17 00:00:00 2001 From: Tom Joseph Date: Tue, 14 Mar 2017 15:26:26 +0530 Subject: Implement startEventLoop and handler function for IPMI packets The startEventLoop would start the sd_event_loop and register the handler for IPMI incoming packets on UDP standard port 623. Change-Id: Ia8ff44961686c1bf715413ff58bd60d7c71f1be1 Signed-off-by: Tom Joseph --- sd_event_loop.cpp | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 sd_event_loop.cpp (limited to 'sd_event_loop.cpp') diff --git a/sd_event_loop.cpp b/sd_event_loop.cpp new file mode 100644 index 0000000..a99cf56 --- /dev/null +++ b/sd_event_loop.cpp @@ -0,0 +1,133 @@ +#include +#include +#include +#include "main.hpp" +#include "message_handler.hpp" +#include "sd_event_loop.hpp" + +namespace eventloop +{ +using namespace phosphor::logging; + +static int udp623Handler(sd_event_source* es, int fd, uint32_t revents, + void* userdata) +{ + std::shared_ptr channelPtr; + struct timeval timeout; + timeout.tv_sec = SELECT_CALL_TIMEOUT; + timeout.tv_usec = 0; + + try + { + channelPtr.reset(new udpsocket::Channel(fd, timeout)); + + // Initialize the Message Handler with the socket channel + message::Handler msgHandler(channelPtr); + + + std::unique_ptr inMessage; + + // Read the incoming IPMI packet + inMessage = msgHandler.receive(); + if (inMessage == nullptr) + { + return 0; + } + + // Execute the Command + auto outMessage = msgHandler.executeCommand(*(inMessage.get())); + if (outMessage == nullptr) + { + return 0; + } + + // Send the response IPMI Message + msgHandler.send(*(outMessage.get())); + } + catch (std::exception& e) + { + log("Executing the IPMI message failed"); + log(e.what()); + } + + return 0; +} + +int EventLoop::startEventLoop() +{ + int fd = -1; + int r = 0; + sigset_t ss; + sd_event_source* source = nullptr; + + r = sd_event_default(&event); + if (r < 0) + { + goto finish; + } + + if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 || + sigaddset(&ss, SIGINT) < 0) + { + r = -errno; + goto finish; + } + + /* Block SIGTERM first, so that the event loop can handle it */ + if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0) + { + r = -errno; + goto finish; + } + + /* Let's make use of the default handler and "floating" reference features + * of sd_event_add_signal() */ + r = sd_event_add_signal(event, nullptr, SIGTERM, nullptr, nullptr); + if (r < 0) + { + goto finish; + } + + r = sd_event_add_signal(event, nullptr, SIGINT, nullptr, nullptr); + if (r < 0) + { + goto finish; + } + + if (sd_listen_fds(0) != 1) + { + log("No or too many file descriptors received"); + goto finish; + } + + fd = SD_LISTEN_FDS_START; + + r = sd_event_add_io(event, &source, fd, EPOLLIN, udp623Handler, nullptr); + if (r < 0) + { + goto finish; + } + + udpIPMI.reset(source); + source = nullptr; + + r = sd_event_loop(event); + +finish: + event = sd_event_unref(event); + + if (fd >= 0) + { + (void) close(fd); + } + + if (r < 0) + { + log("Event Loop Failure:", + entry("FAILURE=%s", strerror(-r))); + } + + return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; +} + +} // namespace eventloop -- cgit v1.2.1