| Tom Joseph | 7fd26dd | 2017-03-14 15:26:26 +0530 | [diff] [blame] | 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 |  | 
| Tom Joseph | 56f24e9 | 2017-03-14 16:06:31 +0530 | [diff] [blame] | 56 | static int consoleInputHandler(sd_event_source* es, int fd, uint32_t revents, | 
 | 57 |                                void* userdata) | 
 | 58 | { | 
 | 59 |     try | 
 | 60 |     { | 
 | 61 |         int readSize = 0; | 
 | 62 |  | 
 | 63 |         if (ioctl(fd, FIONREAD, &readSize) < 0) | 
 | 64 |         { | 
 | 65 |             log<level::ERR>("ioctl failed for FIONREAD:", | 
 | 66 |                     entry("errno = %d", errno)); | 
 | 67 |             return 0; | 
 | 68 |         } | 
 | 69 |  | 
 | 70 |         std::vector<uint8_t> buffer(readSize); | 
 | 71 |         auto bufferSize = buffer.size(); | 
 | 72 |         ssize_t readDataLen = 0; | 
 | 73 |  | 
 | 74 |         readDataLen = read(fd, buffer.data(), bufferSize); | 
 | 75 |  | 
 | 76 |         // Update the Console buffer with data read from the socket | 
 | 77 |         if (readDataLen > 0) | 
 | 78 |         { | 
 | 79 |             buffer.resize(readDataLen); | 
 | 80 |             std::get<sol::Manager&>(singletonPool).dataBuffer.write(buffer); | 
 | 81 |         } | 
 | 82 |         else if (readDataLen == 0) | 
 | 83 |         { | 
 | 84 |             log<level::ERR>("Connection Closed for host console socket"); | 
 | 85 |         } | 
 | 86 |         else if (readDataLen < 0) // Error | 
 | 87 |         { | 
 | 88 |             log<level::ERR>("Reading from host console socket failed:", | 
 | 89 |                     entry("ERRNO=%d", errno)); | 
 | 90 |         } | 
 | 91 |     } | 
 | 92 |     catch (std::exception& e) | 
 | 93 |     { | 
 | 94 |         log<level::ERR>(e.what()); | 
 | 95 |     } | 
 | 96 |  | 
 | 97 |     return 0; | 
 | 98 | } | 
 | 99 |  | 
| Tom Joseph | 7fd26dd | 2017-03-14 15:26:26 +0530 | [diff] [blame] | 100 | int EventLoop::startEventLoop() | 
 | 101 | { | 
 | 102 |     int fd = -1; | 
 | 103 |     int r = 0; | 
 | 104 |     sigset_t ss; | 
 | 105 |     sd_event_source* source = nullptr; | 
 | 106 |  | 
 | 107 |     r = sd_event_default(&event); | 
 | 108 |     if (r < 0) | 
 | 109 |     { | 
 | 110 |         goto finish; | 
 | 111 |     } | 
 | 112 |  | 
 | 113 |     if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 || | 
 | 114 |         sigaddset(&ss, SIGINT) < 0) | 
 | 115 |     { | 
 | 116 |         r = -errno; | 
 | 117 |         goto finish; | 
 | 118 |     } | 
 | 119 |  | 
 | 120 |     /* Block SIGTERM first, so that the event loop can handle it */ | 
 | 121 |     if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0) | 
 | 122 |     { | 
 | 123 |         r = -errno; | 
 | 124 |         goto finish; | 
 | 125 |     } | 
 | 126 |  | 
 | 127 |     /* Let's make use of the default handler and "floating" reference features | 
 | 128 |      * of sd_event_add_signal() */ | 
 | 129 |     r = sd_event_add_signal(event, nullptr, SIGTERM, nullptr, nullptr); | 
 | 130 |     if (r < 0) | 
 | 131 |     { | 
 | 132 |         goto finish; | 
 | 133 |     } | 
 | 134 |  | 
 | 135 |     r = sd_event_add_signal(event, nullptr, SIGINT, nullptr, nullptr); | 
 | 136 |     if (r < 0) | 
 | 137 |     { | 
 | 138 |         goto finish; | 
 | 139 |     } | 
 | 140 |  | 
 | 141 |     if (sd_listen_fds(0) != 1) | 
 | 142 |     { | 
 | 143 |         log<level::ERR>("No or too many file descriptors received"); | 
 | 144 |         goto finish; | 
 | 145 |     } | 
 | 146 |  | 
 | 147 |     fd = SD_LISTEN_FDS_START; | 
 | 148 |  | 
 | 149 |     r = sd_event_add_io(event, &source, fd, EPOLLIN, udp623Handler, nullptr); | 
 | 150 |     if (r < 0) | 
 | 151 |     { | 
 | 152 |         goto finish; | 
 | 153 |     } | 
 | 154 |  | 
 | 155 |     udpIPMI.reset(source); | 
 | 156 |     source = nullptr; | 
 | 157 |  | 
 | 158 |     r = sd_event_loop(event); | 
 | 159 |  | 
 | 160 | finish: | 
 | 161 |     event = sd_event_unref(event); | 
 | 162 |  | 
 | 163 |     if (fd >= 0) | 
 | 164 |     { | 
 | 165 |         (void) close(fd); | 
 | 166 |     } | 
 | 167 |  | 
 | 168 |     if (r < 0) | 
 | 169 |     { | 
 | 170 |         log<level::ERR>("Event Loop Failure:", | 
 | 171 |                 entry("FAILURE=%s", strerror(-r))); | 
 | 172 |     } | 
 | 173 |  | 
 | 174 |     return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; | 
 | 175 | } | 
 | 176 |  | 
| Tom Joseph | 56f24e9 | 2017-03-14 16:06:31 +0530 | [diff] [blame] | 177 | void EventLoop::startHostConsole(const sol::CustomFD& fd) | 
 | 178 | { | 
 | 179 |     int rc = 0; | 
 | 180 |  | 
 | 181 |     if((fd() == -1) || hostConsole.get()) | 
 | 182 |     { | 
 | 183 |         throw std::runtime_error("Console descriptor already added"); | 
 | 184 |     } | 
 | 185 |  | 
 | 186 |     sd_event_source* source = nullptr; | 
 | 187 |  | 
 | 188 |     // Add the fd to the event loop for EPOLLIN | 
 | 189 |     rc = sd_event_add_io( | 
 | 190 |             event, &source, fd(), EPOLLIN, consoleInputHandler, nullptr); | 
 | 191 |     if (rc < 0) | 
 | 192 |     { | 
 | 193 |         throw std::runtime_error("Failed to add socket descriptor"); | 
 | 194 |     } | 
 | 195 |  | 
 | 196 |     hostConsole.reset(source); | 
 | 197 |     source=nullptr; | 
 | 198 | } | 
 | 199 |  | 
| Tom Joseph | 7fd26dd | 2017-03-14 15:26:26 +0530 | [diff] [blame] | 200 | } // namespace eventloop |