1 #include <sys/ioctl.h> 2 #include <systemd/sd-daemon.h> 3 #include <phosphor-logging/log.hpp> 4 #include "main.hpp" 5 #include "message_handler.hpp" 6 #include "sd_event_loop.hpp" 7 8 namespace eventloop 9 { 10 using namespace phosphor::logging; 11 12 static int udp623Handler(sd_event_source* es, int fd, uint32_t revents, 13 void* userdata) 14 { 15 std::shared_ptr<udpsocket::Channel> channelPtr; 16 struct timeval timeout; 17 timeout.tv_sec = SELECT_CALL_TIMEOUT; 18 timeout.tv_usec = 0; 19 20 try 21 { 22 channelPtr.reset(new udpsocket::Channel(fd, timeout)); 23 24 // Initialize the Message Handler with the socket channel 25 message::Handler msgHandler(channelPtr); 26 27 28 std::unique_ptr<message::Message> inMessage; 29 30 // Read the incoming IPMI packet 31 inMessage = msgHandler.receive(); 32 if (inMessage == nullptr) 33 { 34 return 0; 35 } 36 37 // Execute the Command 38 auto outMessage = msgHandler.executeCommand(*(inMessage.get())); 39 if (outMessage == nullptr) 40 { 41 return 0; 42 } 43 44 // Send the response IPMI Message 45 msgHandler.send(*(outMessage.get())); 46 } 47 catch (std::exception& e) 48 { 49 log<level::ERR>("Executing the IPMI message failed"); 50 log<level::ERR>(e.what()); 51 } 52 53 return 0; 54 } 55 56 int EventLoop::startEventLoop() 57 { 58 int fd = -1; 59 int r = 0; 60 sigset_t ss; 61 sd_event_source* source = nullptr; 62 63 r = sd_event_default(&event); 64 if (r < 0) 65 { 66 goto finish; 67 } 68 69 if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 || 70 sigaddset(&ss, SIGINT) < 0) 71 { 72 r = -errno; 73 goto finish; 74 } 75 76 /* Block SIGTERM first, so that the event loop can handle it */ 77 if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0) 78 { 79 r = -errno; 80 goto finish; 81 } 82 83 /* Let's make use of the default handler and "floating" reference features 84 * of sd_event_add_signal() */ 85 r = sd_event_add_signal(event, nullptr, SIGTERM, nullptr, nullptr); 86 if (r < 0) 87 { 88 goto finish; 89 } 90 91 r = sd_event_add_signal(event, nullptr, SIGINT, nullptr, nullptr); 92 if (r < 0) 93 { 94 goto finish; 95 } 96 97 if (sd_listen_fds(0) != 1) 98 { 99 log<level::ERR>("No or too many file descriptors received"); 100 goto finish; 101 } 102 103 fd = SD_LISTEN_FDS_START; 104 105 r = sd_event_add_io(event, &source, fd, EPOLLIN, udp623Handler, nullptr); 106 if (r < 0) 107 { 108 goto finish; 109 } 110 111 udpIPMI.reset(source); 112 source = nullptr; 113 114 r = sd_event_loop(event); 115 116 finish: 117 event = sd_event_unref(event); 118 119 if (fd >= 0) 120 { 121 (void) close(fd); 122 } 123 124 if (r < 0) 125 { 126 log<level::ERR>("Event Loop Failure:", 127 entry("FAILURE=%s", strerror(-r))); 128 } 129 130 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; 131 } 132 133 } // namespace eventloop 134