blob: 033b85c71a2d350f1d3dae80e0df45ee649b3d2b [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 "socket_channel.hpp"
Tom Joseph89481cf2017-04-03 02:11:34 +053021#include "sol_module.hpp"
Tom Josephc35524e2016-08-29 08:17:59 -050022
23// Tuple of Global Singletons
24session::Manager manager;
25command::Table table;
Tom Joseph52f53d72017-03-14 15:20:19 +053026eventloop::EventLoop loop;
27sol::Manager solManager;
28
29std::tuple<session::Manager&, command::Table&, eventloop::EventLoop&,
30 sol::Manager&> singletonPool(manager, table, loop, solManager);
Tom Josephc35524e2016-08-29 08:17:59 -050031
32sd_bus* bus = nullptr;
Tom069f01e2016-12-02 14:11:37 +053033FILE* ipmidbus = nullptr;
34unsigned short g_sel_reserve = 0xFFFF;
35sd_bus_slot* ipmid_slot = nullptr;
Tom Josephc35524e2016-08-29 08:17:59 -050036
37/*
38 * @brief Required by apphandler IPMI Provider Library
39 */
40sd_bus* ipmid_get_sd_bus_connection()
41{
42 return bus;
43}
44
45/*
Tom069f01e2016-12-02 14:11:37 +053046 * @brief Required by apphandler IPMI Provider Library
47 */
48unsigned short get_sel_reserve_id()
49{
50 return g_sel_reserve;
51}
52
53/*
Tom Josephc35524e2016-08-29 08:17:59 -050054 * TODO : The plan is to refactor the event loop to support adding multiple
55 * file descriptors and event handlers for implementing the Serial Over LAN.
56 *
57 * A class would abstract the features provided by the sd_event_loop
58 */
59
60namespace eventloop
61{
62
63static int io_handler(sd_event_source* es, int fd, uint32_t revents,
64 void* userdata)
65{
66 std::shared_ptr<udpsocket::Channel> channelPtr;
67 struct timeval timeout;
68 timeout.tv_sec = SELECT_CALL_TIMEOUT;
69 timeout.tv_usec = 0;
70
71 channelPtr.reset(new udpsocket::Channel(fd, timeout));
72
73 // Initialize the Message Handler with the socket channel
74 message::Handler msgHandler(channelPtr);
75
76 // Read the incoming IPMI packet
77 std::unique_ptr<message::Message> inMessage;
78 try
79 {
80 inMessage = msgHandler.receive();
81 }
82 catch (std::exception& e)
83 {
84 std::cerr << "Reading & Parsing the incoming IPMI message failed\n";
85 std::cerr << e.what() << "\n";
86 return 0;
87 }
88
89 // Execute the Command
Tom069f01e2016-12-02 14:11:37 +053090 auto outMessage = msgHandler.executeCommand(*(inMessage.get()));
Tom Josephc35524e2016-08-29 08:17:59 -050091 if (outMessage == nullptr)
92 {
93 std::cerr << "Execution of IPMI command failed\n";
94 return 0;
95 }
96
Tom Joseph73a3d962017-01-24 16:45:28 +053097 try
98 {
99 // Send the response IPMI Message
100 msgHandler.send(*(outMessage.get()));
101 }
102 catch (std::exception& e)
103 {
104 std::cerr << "Flattening & Sending the outgoing IPMI message failed\n";
105 std::cerr << e.what() << "\n";
106 }
Tom Josephc35524e2016-08-29 08:17:59 -0500107
108 return 0;
109}
110
111int startEventLoop()
112{
Tom Josephc35524e2016-08-29 08:17:59 -0500113 sd_event_source* event_source = nullptr;
114 sd_event* event = nullptr;
115 int fd = -1, r;
116 sigset_t ss;
117
118 r = sd_event_default(&event);
119 if (r < 0)
120 {
121 goto finish;
122 }
123
124 if (sigemptyset(&ss) < 0 || sigaddset(&ss, SIGTERM) < 0 ||
125 sigaddset(&ss, SIGINT) < 0)
126 {
127 r = -errno;
128 goto finish;
129 }
130
131 /* Block SIGTERM first, so that the event loop can handle it */
132 if (sigprocmask(SIG_BLOCK, &ss, nullptr) < 0)
133 {
134 r = -errno;
135 goto finish;
136 }
137
138 /* Let's make use of the default handler and "floating" reference features
139 * of sd_event_add_signal() */
140 r = sd_event_add_signal(event, nullptr, SIGTERM, nullptr, nullptr);
141 if (r < 0)
142 {
143 goto finish;
144 }
145
146 r = sd_event_add_signal(event, nullptr, SIGINT, nullptr, nullptr);
147 if (r < 0)
148 {
149 goto finish;
150 }
151
Tom Joseph76931bf2017-01-27 08:40:42 +0530152 if (sd_listen_fds(0) != 1)
Tom Josephc35524e2016-08-29 08:17:59 -0500153 {
Tom Joseph76931bf2017-01-27 08:40:42 +0530154 fprintf(stderr, "No or too many file descriptors received.\n");
Tom Josephc35524e2016-08-29 08:17:59 -0500155 goto finish;
156 }
157
Tom Joseph76931bf2017-01-27 08:40:42 +0530158 fd = SD_LISTEN_FDS_START;
Tom Josephc35524e2016-08-29 08:17:59 -0500159
160 r = sd_event_add_io(event, &event_source, fd, EPOLLIN, io_handler, nullptr);
161 if (r < 0)
162 {
163 goto finish;
164 }
165
166 r = sd_event_loop(event);
167
168finish:
169 event_source = sd_event_source_unref(event_source);
170 event = sd_event_unref(event);
171
172 if (fd >= 0)
173 {
174 (void) close(fd);
175 }
176
177 if (r < 0)
178 {
179 fprintf(stderr, "Failure: %s\n", strerror(-r));
180 }
181
182 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
183}
184
185} // namespace eventloop
186
187int main(int i_argc, char* i_argv[])
188{
Tom069f01e2016-12-02 14:11:37 +0530189 /*
190 * Required by apphandler IPMI Provider Library for logging.
191 */
192 ipmidbus = fopen("/dev/null", "w");
193
Tom Josephc35524e2016-08-29 08:17:59 -0500194 // Connect to system bus
195 auto rc = sd_bus_open_system(&bus);
196 if (rc < 0)
197 {
198 std::cerr << "Failed to connect to system bus:" << strerror(-rc) <<"\n";
199 goto finish;
200 }
201
Tom485038e2016-12-02 13:44:45 +0530202 // Register all the IPMI provider libraries applicable for net-ipmid
203 provider::registerCallbackHandlers(NET_IPMID_LIB_PATH);
204
Tom Josephc35524e2016-08-29 08:17:59 -0500205 // Register the phosphor-net-ipmid session setup commands
206 command::sessionSetupCommands();
207
Tom Joseph89481cf2017-04-03 02:11:34 +0530208 // Register the phosphor-net-ipmid SOL commands
209 sol::command::registerCommands();
210
Tom Josephc35524e2016-08-29 08:17:59 -0500211 // Start Event Loop
212 return eventloop::startEventLoop();
213
214finish:
215 sd_bus_unref(bus);
216
217 return 0;
218}