1 #include "sd_event_loop.hpp"
2 
3 #include "main.hpp"
4 #include "message_handler.hpp"
5 
6 #include <netinet/in.h>
7 #include <sys/ioctl.h>
8 #include <sys/socket.h>
9 #include <systemd/sd-daemon.h>
10 
11 #include <boost/asio/io_context.hpp>
12 #include <phosphor-logging/log.hpp>
13 #include <sdbusplus/asio/sd_event.hpp>
14 
15 namespace eventloop
16 {
17 using namespace phosphor::logging;
18 
19 void EventLoop::handleRmcpPacket()
20 {
21     try
22     {
23         auto channelPtr = std::make_shared<udpsocket::Channel>(udpSocket);
24 
25         // Initialize the Message Handler with the socket channel
26         auto msgHandler = std::make_shared<message::Handler>(channelPtr, io);
27 
28         msgHandler->processIncoming();
29     }
30     catch (const std::exception& e)
31     {
32         log<level::ERR>("Executing the IPMI message failed",
33                         entry("EXCEPTION=%s", e.what()));
34     }
35 }
36 
37 void EventLoop::startRmcpReceive()
38 {
39     udpSocket->async_wait(boost::asio::socket_base::wait_read,
40                           [this](const boost::system::error_code& ec) {
41                               if (!ec)
42                               {
43                                   io->post([this]() { startRmcpReceive(); });
44                                   handleRmcpPacket();
45                               }
46                           });
47 }
48 
49 int EventLoop::startEventLoop()
50 {
51     // set up boost::asio signal handling
52     boost::asio::signal_set signals(*io, SIGINT, SIGTERM);
53     signals.async_wait(
54         [this](const boost::system::error_code& error, int signalNumber) {
55             udpSocket->cancel();
56             udpSocket->close();
57             io->stop();
58         });
59 
60     // Create our own socket if SysD did not supply one.
61     int listensFdCount = sd_listen_fds(0);
62     if (listensFdCount == 1)
63     {
64         if (sd_is_socket(SD_LISTEN_FDS_START, AF_UNSPEC, SOCK_DGRAM, -1))
65         {
66             udpSocket = std::make_shared<boost::asio::ip::udp::socket>(
67                 *io, boost::asio::ip::udp::v6(), SD_LISTEN_FDS_START);
68         }
69     }
70     else if (listensFdCount > 1)
71     {
72         log<level::ERR>("Too many file descriptors received");
73         return EXIT_FAILURE;
74     }
75     if (!udpSocket)
76     {
77         udpSocket = std::make_shared<boost::asio::ip::udp::socket>(
78             *io, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v6(),
79                                                 IPMI_STD_PORT));
80         if (!udpSocket)
81         {
82             log<level::ERR>("Failed to start listening on RMCP socket");
83             return EXIT_FAILURE;
84         }
85     }
86     startRmcpReceive();
87 
88     io->run();
89 
90     return EXIT_SUCCESS;
91 }
92 
93 } // namespace eventloop
94