blob: 89ef15ceecc0298bb491929411ecbf29da56af27 [file] [log] [blame]
Tom Josephc35524e2016-08-29 08:17:59 -05001#include "main.hpp"
2#include <assert.h>
3#include <dlfcn.h>
4#include <dirent.h>
5#include <unistd.h>
6
7#include <iostream>
8#include <tuple>
9
10#include <systemd/sd-bus.h>
11#include <systemd/sd-daemon.h>
12#include <systemd/sd-event.h>
13
14#include <host-ipmid/ipmid-api.h>
15#include "comm_module.hpp"
16#include "command_table.hpp"
17#include "message.hpp"
18#include "message_handler.hpp"
Tom485038e2016-12-02 13:44:45 +053019#include "provider_registration.hpp"
Tom Josephc35524e2016-08-29 08:17:59 -050020#include "sessions_manager.hpp"
21#include "socket_channel.hpp"
22
23// Tuple of Global Singletons
24session::Manager manager;
25command::Table table;
26std::tuple<session::Manager&, command::Table&> singletonPool(manager, table);
27
28sd_bus* bus = nullptr;
Tom069f01e2016-12-02 14:11:37 +053029FILE* ipmidbus = nullptr;
30unsigned short g_sel_reserve = 0xFFFF;
31sd_bus_slot* ipmid_slot = nullptr;
Tom Josephc35524e2016-08-29 08:17:59 -050032
33/*
34 * @brief Required by apphandler IPMI Provider Library
35 */
36sd_bus* ipmid_get_sd_bus_connection()
37{
38 return bus;
39}
40
41/*
Tom069f01e2016-12-02 14:11:37 +053042 * @brief Required by apphandler IPMI Provider Library
43 */
44unsigned short get_sel_reserve_id()
45{
46 return g_sel_reserve;
47}
48
49/*
Tom Josephc35524e2016-08-29 08:17:59 -050050 * TODO : The plan is to refactor the event loop to support adding multiple
51 * file descriptors and event handlers for implementing the Serial Over LAN.
52 *
53 * A class would abstract the features provided by the sd_event_loop
54 */
55
56namespace eventloop
57{
58
59static int io_handler(sd_event_source* es, int fd, uint32_t revents,
60 void* userdata)
61{
62 std::shared_ptr<udpsocket::Channel> channelPtr;
63 struct timeval timeout;
64 timeout.tv_sec = SELECT_CALL_TIMEOUT;
65 timeout.tv_usec = 0;
66
67 channelPtr.reset(new udpsocket::Channel(fd, timeout));
68
69 // Initialize the Message Handler with the socket channel
70 message::Handler msgHandler(channelPtr);
71
72 // Read the incoming IPMI packet
73 std::unique_ptr<message::Message> inMessage;
74 try
75 {
76 inMessage = msgHandler.receive();
77 }
78 catch (std::exception& e)
79 {
80 std::cerr << "Reading & Parsing the incoming IPMI message failed\n";
81 std::cerr << e.what() << "\n";
82 return 0;
83 }
84
85 // Execute the Command
Tom069f01e2016-12-02 14:11:37 +053086 auto outMessage = msgHandler.executeCommand(*(inMessage.get()));
Tom Josephc35524e2016-08-29 08:17:59 -050087 if (outMessage == nullptr)
88 {
89 std::cerr << "Execution of IPMI command failed\n";
90 return 0;
91 }
92
93 // Send the response IPMI Message
Tom069f01e2016-12-02 14:11:37 +053094 msgHandler.send(*(outMessage.get()));
Tom Josephc35524e2016-08-29 08:17:59 -050095
96 return 0;
97}
98
99int startEventLoop()
100{
Tom Josephc35524e2016-08-29 08:17:59 -0500101 sd_event_source* event_source = nullptr;
102 sd_event* event = nullptr;
103 int fd = -1, r;
104 sigset_t ss;
105
106 r = sd_event_default(&event);
107 if (r < 0)
108 {
109 goto finish;
110 }
111
112 if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
113 sigaddset(&ss, SIGINT) < 0)
114 {
115 r = -errno;
116 goto finish;
117 }
118
119 /* Block SIGTERM first, so that the event loop can handle it */
120 if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0)
121 {
122 r = -errno;
123 goto finish;
124 }
125
126 /* Let's make use of the default handler and "floating" reference features
127 * of sd_event_add_signal() */
128 r = sd_event_add_signal(event, nullptr, SIGTERM, nullptr, nullptr);
129 if (r < 0)
130 {
131 goto finish;
132 }
133
134 r = sd_event_add_signal(event, nullptr, SIGINT, nullptr, nullptr);
135 if (r < 0)
136 {
137 goto finish;
138 }
139
Tom Joseph76931bf2017-01-27 08:40:42 +0530140 if (sd_listen_fds(0) != 1)
Tom Josephc35524e2016-08-29 08:17:59 -0500141 {
Tom Joseph76931bf2017-01-27 08:40:42 +0530142 fprintf(stderr, "No or too many file descriptors received.\n");
Tom Josephc35524e2016-08-29 08:17:59 -0500143 goto finish;
144 }
145
Tom Joseph76931bf2017-01-27 08:40:42 +0530146 fd = SD_LISTEN_FDS_START;
Tom Josephc35524e2016-08-29 08:17:59 -0500147
148 r = sd_event_add_io(event, &event_source, fd, EPOLLIN, io_handler, nullptr);
149 if (r < 0)
150 {
151 goto finish;
152 }
153
154 r = sd_event_loop(event);
155
156finish:
157 event_source = sd_event_source_unref(event_source);
158 event = sd_event_unref(event);
159
160 if (fd >= 0)
161 {
162 (void) close(fd);
163 }
164
165 if (r < 0)
166 {
167 fprintf(stderr, "Failure: %s\n", strerror(-r));
168 }
169
170 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
171}
172
173} // namespace eventloop
174
175int main(int i_argc, char* i_argv[])
176{
Tom069f01e2016-12-02 14:11:37 +0530177
178 /*
179 * Required by apphandler IPMI Provider Library for logging.
180 */
181 ipmidbus = fopen("/dev/null", "w");
182
Tom Josephc35524e2016-08-29 08:17:59 -0500183 // Connect to system bus
184 auto rc = sd_bus_open_system(&bus);
185 if (rc < 0)
186 {
187 std::cerr << "Failed to connect to system bus:" << strerror(-rc) <<"\n";
188 goto finish;
189 }
190
Tom485038e2016-12-02 13:44:45 +0530191 // Register all the IPMI provider libraries applicable for net-ipmid
192 provider::registerCallbackHandlers(NET_IPMID_LIB_PATH);
193
Tom Josephc35524e2016-08-29 08:17:59 -0500194 // Register the phosphor-net-ipmid session setup commands
195 command::sessionSetupCommands();
196
197 // Start Event Loop
198 return eventloop::startEventLoop();
199
200finish:
201 sd_bus_unref(bus);
202
203 return 0;
204}