blob: 3baf388a2465bd49ddbc540c6db6b26165de401f [file] [log] [blame]
Ed Tanousf9273472017-02-28 16:05:13 -08001#include "crow/app.h"
Ed Tanousc4771fb2017-03-13 13:39:49 -07002#include "crow/ci_map.h"
Ed Tanousf9273472017-02-28 16:05:13 -08003#include "crow/common.h"
4#include "crow/dumb_timer_queue.h"
5#include "crow/http_connection.h"
Ed Tanousc4771fb2017-03-13 13:39:49 -07006#include "crow/http_parser_merged.h"
Ed Tanousf9273472017-02-28 16:05:13 -08007#include "crow/http_request.h"
8#include "crow/http_response.h"
9#include "crow/http_server.h"
10#include "crow/json.h"
11#include "crow/logging.h"
12#include "crow/middleware.h"
13#include "crow/middleware_context.h"
14#include "crow/mustache.h"
15#include "crow/parser.h"
Ed Tanousc4771fb2017-03-13 13:39:49 -070016#include "crow/query_string.h"
Ed Tanousf9273472017-02-28 16:05:13 -080017#include "crow/routing.h"
Ed Tanous0fdddb12017-02-28 11:06:34 -080018#include "crow/settings.h"
19#include "crow/socket_adaptors.h"
Ed Tanous0fdddb12017-02-28 11:06:34 -080020#include "crow/utility.h"
Ed Tanous0fdddb12017-02-28 11:06:34 -080021#include "crow/websocket.h"
Ed Tanous0fdddb12017-02-28 11:06:34 -080022
Ed Tanous5f34a9c2017-02-28 12:35:13 -080023#include "color_cout_g3_sink.hpp"
Ed Tanous7d3dba42017-04-05 13:04:39 -070024#include "security_headers_middleware.hpp"
Ed Tanous9140a672017-04-24 17:01:32 -070025#include "ssl_key_handler.hpp"
Ed Tanous7d3dba42017-04-05 13:04:39 -070026#include "token_authorization_middleware.hpp"
Ed Tanous9140a672017-04-24 17:01:32 -070027#include "web_kvm.hpp"
28#include "webassets.hpp"
Ed Tanousb4d29f42017-03-24 16:39:25 -070029
30#include <boost/asio.hpp>
31#include <boost/endian/arithmetic.hpp>
32
Ed Tanousc9b55212017-06-12 13:25:51 -070033#include <dbus/connection.hpp>
34#include <dbus/endpoint.hpp>
35#include <dbus/filter.hpp>
36#include <dbus/match.hpp>
37#include <dbus/message.hpp>
38#include <dbus/utility.hpp>
Ed Tanouscc5a37f2017-05-11 10:27:23 -070039
Ed Tanous0fdddb12017-02-28 11:06:34 -080040#include <iostream>
Ed Tanousc4771fb2017-03-13 13:39:49 -070041#include <memory>
Ed Tanous0fdddb12017-02-28 11:06:34 -080042#include <string>
Ed Tanousc4771fb2017-03-13 13:39:49 -070043#include <unordered_set>
Ed Tanous9b65f1f2017-03-07 15:17:13 -080044
Ed Tanouscc5a37f2017-05-11 10:27:23 -070045using sensor_values = std::vector<std::pair<std::string, int32_t>>;
46
Ed Tanouscc5a37f2017-05-11 10:27:23 -070047sensor_values read_sensor_values() {
48 sensor_values values;
49 DBusError err;
50
51 int ret;
52 bool stat;
53 dbus_uint32_t level;
54
55 // initialiset the errors
56 dbus_error_init(&err);
57
58 // connect to the system bus and check for errors
59 DBusConnection* conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
60 if (dbus_error_is_set(&err)) {
61 fprintf(stderr, "Connection Error (%s)\n", err.message);
62 dbus_error_free(&err);
63 }
64 if (NULL == conn) {
65 exit(1);
66 }
67
68 // create a new method call and check for errors
69 DBusMessage* msg = dbus_message_new_method_call(
70 "org.openbmc.Sensors", // target for the method call
71 "/org/openbmc/sensors/tach", // object to call on
72 "org.freedesktop.DBus.Introspectable", // interface to call on
73 "Introspect"); // method name
74 if (NULL == msg) {
75 fprintf(stderr, "Message Null\n");
76 exit(1);
77 }
78
79 DBusPendingCall* pending;
80 // send message and get a handle for a reply
81 if (!dbus_connection_send_with_reply(conn, msg, &pending,
82 -1)) { // -1 is default timeout
83 fprintf(stderr, "Out Of Memory!\n");
84 exit(1);
85 }
86 if (NULL == pending) {
87 fprintf(stderr, "Pending Call Null\n");
88 exit(1);
89 }
90 dbus_connection_flush(conn);
91
92 // free message
93 dbus_message_unref(msg);
94
95 // block until we recieve a reply
96 dbus_pending_call_block(pending);
97
98 // get the reply message
99 msg = dbus_pending_call_steal_reply(pending);
100 if (NULL == msg) {
101 fprintf(stderr, "Reply Null\n");
102 exit(1);
103 }
104 // free the pending message handle
105 dbus_pending_call_unref(pending);
106
107 // read the parameters
108 DBusMessageIter args;
109 char* xml_struct = NULL;
110 if (!dbus_message_iter_init(msg, &args)) {
111 fprintf(stderr, "Message has no arguments!\n");
112 }
113
114 // read the arguments
115 if (!dbus_message_iter_init(msg, &args)) {
116 fprintf(stderr, "Message has no arguments!\n");
117 } else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) {
118 fprintf(stderr, "Argument is not string!\n");
119 } else {
120 dbus_message_iter_get_basic(&args, &xml_struct);
121 }
122 std::vector<std::string> methods;
123 if (xml_struct != NULL) {
124 std::string xml_data(xml_struct);
Ed Tanousc9b55212017-06-12 13:25:51 -0700125 std::vector<std::string> names;
126 dbus::read_dbus_xml_names(xml_data, methods);
Ed Tanouscc5a37f2017-05-11 10:27:23 -0700127 }
128
Ed Tanousf0226cd2017-05-16 12:35:38 -0700129 fprintf(stdout, "Found %zd sensors \n", methods.size());
Ed Tanouscc5a37f2017-05-11 10:27:23 -0700130
131 for (auto& method : methods) {
132 // TODO(Ed) make sure sensor exposes SensorValue interface
133 // create a new method call and check for errors
134 DBusMessage* msg = dbus_message_new_method_call(
135 "org.openbmc.Sensors", // target for the method call
136 ("/org/openbmc/sensors/tach/" + method).c_str(), // object to call on
137 "org.openbmc.SensorValue", // interface to call on
138 "getValue"); // method name
139 if (NULL == msg) {
140 fprintf(stderr, "Message Null\n");
141 exit(1);
142 }
143
144 DBusPendingCall* pending;
145 // send message and get a handle for a reply
146 if (!dbus_connection_send_with_reply(conn, msg, &pending,
147 -1)) { // -1 is default timeout
148 fprintf(stderr, "Out Of Memory!\n");
149 exit(1);
150 }
151 if (NULL == pending) {
152 fprintf(stderr, "Pending Call Null\n");
153 exit(1);
154 }
155 dbus_connection_flush(conn);
156
157 // free message
158 dbus_message_unref(msg);
159
160 // block until we recieve a reply
161 dbus_pending_call_block(pending);
162
163 // get the reply message
164 msg = dbus_pending_call_steal_reply(pending);
165 if (NULL == msg) {
166 fprintf(stderr, "Reply Null\n");
167 exit(1);
168 }
169 // free the pending message handle
170 dbus_pending_call_unref(pending);
171
172 // read the parameters
173 DBusMessageIter args;
174 int32_t value;
175 if (!dbus_message_iter_init(msg, &args)) {
176 fprintf(stderr, "Message has no arguments!\n");
177 }
178
179 // read the arguments
180 if (!dbus_message_iter_init(msg, &args)) {
181 fprintf(stderr, "Message has no arguments!\n");
182 } else if (DBUS_TYPE_VARIANT != dbus_message_iter_get_arg_type(&args)) {
183 fprintf(stderr, "Argument is not string!\n");
184 } else {
185 DBusMessageIter sub;
186 dbus_message_iter_recurse(&args, &sub);
187 auto type = dbus_message_iter_get_arg_type(&sub);
188 if (DBUS_TYPE_INT32 != type) {
189 fprintf(stderr, "Variant subType is not int32 it is %d\n", type);
190 } else {
191 dbus_message_iter_get_basic(&sub, &value);
192 values.emplace_back(method.c_str(), value);
193 }
194 }
195 }
196
197 // free reply and close connection
198 dbus_message_unref(msg);
199 return values;
200}
201
Ed Tanous99923322017-03-03 14:21:24 -0800202int main(int argc, char** argv) {
Ed Tanous9b65f1f2017-03-07 15:17:13 -0800203 auto worker(g3::LogWorker::createLogWorker());
Ed Tanouscfbe25d2017-05-23 16:34:35 -0700204 if (false) {
205 auto handle = worker->addDefaultLogger("bmcweb", "/tmp/");
206 }
Ed Tanous99923322017-03-03 14:21:24 -0800207 g3::initializeLogging(worker.get());
Ed Tanous1ccd57c2017-03-21 13:15:58 -0700208 auto sink_handle = worker->addSink(std::make_unique<crow::ColorCoutSink>(),
209 &crow::ColorCoutSink::ReceiveLogMessage);
Ed Tanous4758d5b2017-06-06 15:28:13 -0700210 bool enable_ssl = true;
Ed Tanous99923322017-03-03 14:21:24 -0800211 std::string ssl_pem_file("server.pem");
Ed Tanous0fdddb12017-02-28 11:06:34 -0800212
Ed Tanous4758d5b2017-06-06 15:28:13 -0700213 if (enable_ssl) {
214 ensuressl::ensure_openssl_key_present_and_valid(ssl_pem_file);
215 }
216
Ed Tanousc9b55212017-06-12 13:25:51 -0700217 crow::App<crow::TokenAuthorizationMiddleware, crow::SecurityHeadersMiddleware>
Ed Tanous7d3dba42017-04-05 13:04:39 -0700218 app;
Ed Tanousb4d29f42017-03-24 16:39:25 -0700219
Ed Tanous99923322017-03-03 14:21:24 -0800220 crow::webassets::request_routes(app);
Ed Tanousc81ca422017-03-21 16:18:49 -0700221 crow::kvm::request_routes(app);
Ed Tanous0fdddb12017-02-28 11:06:34 -0800222
Ed Tanous9b65f1f2017-03-07 15:17:13 -0800223 crow::logger::setLogLevel(crow::LogLevel::INFO);
Ed Tanousc4771fb2017-03-13 13:39:49 -0700224 CROW_ROUTE(app, "/systeminfo")
225 ([]() {
226
227 crow::json::wvalue j;
228 j["device_id"] = 0x7B;
229 j["device_provides_sdrs"] = true;
230 j["device_revision"] = true;
231 j["device_available"] = true;
232 j["firmware_revision"] = "0.68";
233
234 j["ipmi_revision"] = "2.0";
235 j["supports_chassis_device"] = true;
236 j["supports_bridge"] = true;
237 j["supports_ipmb_event_generator"] = true;
238 j["supports_ipmb_event_receiver"] = true;
239 j["supports_fru_inventory_device"] = true;
240 j["supports_sel_device"] = true;
241 j["supports_sdr_repository_device"] = true;
242 j["supports_sensor_device"] = true;
243
244 j["firmware_aux_revision"] = "0.60.foobar";
245
246 return j;
247 });
248
Ed Tanousf3d847c2017-06-12 16:01:42 -0700249 CROW_ROUTE(app, "/sensorws")
Ed Tanousc4771fb2017-03-13 13:39:49 -0700250 .websocket()
251 .onopen([&](crow::websocket::connection& conn) {
Ed Tanousf3d847c2017-06-12 16:01:42 -0700252 dbus::connection system_bus(conn.get_io_service(), dbus::bus::system);
253 dbus::match ma(system_bus,
254 "type='signal',sender='org.freedesktop.DBus', "
255 "interface='org.freedesktop.DBus.Properties',member="
256 "'PropertiesChanged'");
257 dbus::filter f(system_bus, [](dbus::message& m) { return true; });
258
259 f.async_dispatch([&](boost::system::error_code ec, dbus::message s) {
260 std::cout << "got event\n";
261 //f.async_dispatch(event_handler);
262 });
Ed Tanousc4771fb2017-03-13 13:39:49 -0700263
264 })
Ed Tanous1ccd57c2017-03-21 13:15:58 -0700265 .onclose(
266 [&](crow::websocket::connection& conn, const std::string& reason) {
Ed Tanousc4771fb2017-03-13 13:39:49 -0700267
Ed Tanous1ccd57c2017-03-21 13:15:58 -0700268 })
269 .onmessage([&](crow::websocket::connection& conn, const std::string& data,
270 bool is_binary) {
Ed Tanous1ccd57c2017-03-21 13:15:58 -0700271
Ed Tanousc4771fb2017-03-13 13:39:49 -0700272 });
Ed Tanouscc5a37f2017-05-11 10:27:23 -0700273
274 CROW_ROUTE(app, "/sensortest")
Ed Tanousc9b55212017-06-12 13:25:51 -0700275 ([](const crow::request& req, crow::response& res) {
Ed Tanousf3d847c2017-06-12 16:01:42 -0700276 crow::json::wvalue j;
277 auto values = read_sensor_values();
278
Ed Tanousc9b55212017-06-12 13:25:51 -0700279 dbus::connection system_bus(*req.io_service, dbus::bus::system);
Ed Tanousf3d847c2017-06-12 16:01:42 -0700280 dbus::endpoint test_daemon("org.openbmc.Sensors",
281 "/org/openbmc/sensors/tach",
282 "org.freedesktop.DBus.Introspectable");
283 dbus::message m = dbus::message::new_call(test_daemon, "Introspect");
284 system_bus.async_send(
285 m,
286 [&j, &system_bus](const boost::system::error_code ec, dbus::message r) {
287 std::string xml;
288 r.unpack(xml);
289 std::vector<std::string> dbus_objects;
290 dbus::read_dbus_xml_names(xml, dbus_objects);
Ed Tanouscc5a37f2017-05-11 10:27:23 -0700291
Ed Tanousf3d847c2017-06-12 16:01:42 -0700292 for (auto& object : dbus_objects) {
293 dbus::endpoint test_daemon("org.openbmc.Sensors",
294 "/org/openbmc/sensors/tach/" + object,
295 "org.openbmc.SensorValue");
296 dbus::message m2 = dbus::message::new_call(test_daemon, "getValue");
297
298 system_bus.async_send(
299 m2, [&](const boost::system::error_code ec, dbus::message r) {
300 int32_t value;
301 r.unpack(value);
302 // TODO(ed) if we ever go multithread, j needs a lock
303 j[object] = value;
304 });
305 }
Ed Tanousc9b55212017-06-12 13:25:51 -0700306
Ed Tanousf3d847c2017-06-12 16:01:42 -0700307 });
Ed Tanousc9b55212017-06-12 13:25:51 -0700308
Ed Tanouscc5a37f2017-05-11 10:27:23 -0700309 });
Ed Tanous4758d5b2017-06-06 15:28:13 -0700310
311 CROW_ROUTE(app, "/intel/firmwareupload")
312 .methods("POST"_method)([](const crow::request& req) {
313 // TODO(ed) handle errors here (file exists already and is locked, ect)
Ed Tanousc9b55212017-06-12 13:25:51 -0700314 std::ofstream out("/tmp/fw_update_image", std::ofstream::out |
315 std::ofstream::binary |
316 std::ofstream::trunc);
Ed Tanous4758d5b2017-06-06 15:28:13 -0700317 out << req.body;
318 out.close();
319
320 crow::json::wvalue j;
321 j["status"] = "Upload Successfull";
322
323 return j;
324 });
325
Ed Tanous4c3cbc62017-05-16 09:17:42 -0700326 LOG(DEBUG) << "Building SSL context";
Ed Tanous4758d5b2017-06-06 15:28:13 -0700327
Ed Tanous4c3cbc62017-05-16 09:17:42 -0700328 int port = 18080;
Ed Tanousf0226cd2017-05-16 12:35:38 -0700329
Ed Tanous4c3cbc62017-05-16 09:17:42 -0700330 LOG(DEBUG) << "Starting webserver on port " << port;
Ed Tanous4758d5b2017-06-06 15:28:13 -0700331 app.port(port);
332 if (enable_ssl) {
333 LOG(DEBUG) << "SSL Enabled";
334 auto ssl_context = ensuressl::get_ssl_context(ssl_pem_file);
335 app.ssl(std::move(ssl_context));
336 }
Ed Tanousf3d847c2017-06-12 16:01:42 -0700337 //app.concurrency(4);
Ed Tanous4758d5b2017-06-06 15:28:13 -0700338 app.run();
Ed Tanous0fdddb12017-02-28 11:06:34 -0800339}