1 #include <boost/asio.hpp> 2 #include <boost/container/flat_map.hpp> 3 #include <boost/container/stable_vector.hpp> 4 5 #include "crow/app.h" 6 #include "crow/ci_map.h" 7 #include "crow/common.h" 8 #include "crow/dumb_timer_queue.h" 9 #include "crow/http_connection.h" 10 #include "crow/http_parser_merged.h" 11 #include "crow/http_request.h" 12 #include "crow/http_response.h" 13 #include "crow/http_server.h" 14 #include "crow/logging.h" 15 #include "crow/middleware.h" 16 #include "crow/middleware_context.h" 17 #include "crow/mustache.h" 18 #include "crow/parser.h" 19 #include "crow/query_string.h" 20 #include "crow/routing.h" 21 #include "crow/settings.h" 22 #include "crow/socket_adaptors.h" 23 #include "crow/utility.h" 24 #include "crow/websocket.h" 25 26 #include "redfish_v1.hpp" 27 #include "security_headers_middleware.hpp" 28 #include "ssl_key_handler.hpp" 29 #include "token_authorization_middleware.hpp" 30 #include "web_kvm.hpp" 31 #include "webassets.hpp" 32 33 #include "nlohmann/json.hpp" 34 35 #include <dbus/connection.hpp> 36 #include <dbus/endpoint.hpp> 37 #include <dbus/filter.hpp> 38 #include <dbus/match.hpp> 39 #include <dbus/message.hpp> 40 41 #include <chrono> 42 #include <iostream> 43 #include <memory> 44 #include <string> 45 #include <unordered_set> 46 47 static std::shared_ptr<dbus::connection> system_bus; 48 static std::vector<dbus::match> dbus_matches; 49 static std::shared_ptr<dbus::filter> sensor_filter; 50 51 struct DbusWebsocketSession { 52 std::vector<dbus::match> matches; 53 std::vector<dbus::filter> filters; 54 }; 55 56 static boost::container::flat_map<crow::websocket::connection*, 57 DbusWebsocketSession> 58 sessions; 59 60 void on_property_update(dbus::filter& filter, boost::system::error_code ec, 61 dbus::message s) { 62 std::string object_name; 63 std::vector<std::pair<std::string, dbus::dbus_variant>> values; 64 s.unpack(object_name).unpack(values); 65 nlohmann::json j; 66 for (auto& value : values) { 67 boost::apply_visitor([&](auto val) { j[s.get_path()] = val; }, 68 value.second); 69 } 70 auto data_to_send = j.dump(); 71 72 for (auto& session : sessions) { 73 session.first->send_text(data_to_send); 74 } 75 filter.async_dispatch([&](boost::system::error_code ec, dbus::message s) { 76 on_property_update(filter, ec, s);; 77 }); 78 }; 79 80 int main(int argc, char** argv) { 81 // Build an io_service (there should only be 1) 82 auto io = std::make_shared<boost::asio::io_service>(); 83 84 bool enable_ssl = true; 85 std::string ssl_pem_file("server.pem"); 86 87 if (enable_ssl) { 88 ensuressl::ensure_openssl_key_present_and_valid(ssl_pem_file); 89 } 90 91 crow::App< 92 /*crow::TokenAuthorizationMiddleware, */ crow::SecurityHeadersMiddleware> 93 app(io); 94 95 crow::webassets::request_routes(app); 96 crow::kvm::request_routes(app); 97 crow::redfish::request_routes(app); 98 99 crow::logger::setLogLevel(crow::LogLevel::INFO); 100 101 CROW_ROUTE(app, "/dbus_monitor") 102 .websocket() 103 .onopen([&](crow::websocket::connection& conn) { 104 sessions[&conn] = DbusWebsocketSession(); 105 106 sessions[&conn].matches.emplace_back( 107 system_bus, 108 "type='signal',path_namespace='/xyz/openbmc_project/sensors'"); 109 110 sessions[&conn].filters.emplace_back(system_bus, [](dbus::message m) { 111 auto member = m.get_member(); 112 return member == "PropertiesChanged"; 113 }); 114 auto& this_filter = sessions[&conn].filters.back(); 115 this_filter.async_dispatch( 116 [&](boost::system::error_code ec, dbus::message s) { 117 on_property_update(this_filter, ec, s);; 118 }); 119 120 }) 121 .onclose( 122 [&](crow::websocket::connection& conn, const std::string& reason) { 123 sessions.erase(&conn); 124 125 }) 126 .onmessage([&](crow::websocket::connection& conn, const std::string& data, 127 bool is_binary) { 128 CROW_LOG_ERROR << "Got unexpected message from client on sensorws"; 129 }); 130 131 CROW_ROUTE(app, "/intel/firmwareupload") 132 .methods("POST"_method)([](const crow::request& req) { 133 auto filepath = "/tmp/fw_update_image"; 134 std::ofstream out(filepath, std::ofstream::out | std::ofstream::binary | 135 std::ofstream::trunc); 136 out << req.body; 137 out.close(); 138 139 nlohmann::json j; 140 j["status"] = "Upload Successfull"; 141 142 dbus::endpoint fw_update_endpoint( 143 "xyz.openbmc_project.fwupdate1.server", 144 "/xyz/openbmc_project/fwupdate1", "xyz.openbmc_project.fwupdate1"); 145 146 auto m = dbus::message::new_call(fw_update_endpoint, "start"); 147 148 m.pack(std::string("file://") + filepath); 149 system_bus->send(m); 150 151 return j; 152 }); 153 154 crow::logger::setLogLevel(crow::LogLevel::DEBUG); 155 auto test = app.get_routes(); 156 app.debug_print(); 157 std::cout << "Building SSL context\n"; 158 159 int port = 18080; 160 161 std::cout << "Starting webserver on port " << port << "\n"; 162 app.port(port); 163 if (enable_ssl) { 164 std::cout << "SSL Enabled\n"; 165 auto ssl_context = ensuressl::get_ssl_context(ssl_pem_file); 166 app.ssl(std::move(ssl_context)); 167 } 168 // app.concurrency(4); 169 170 // Start dbus connection 171 system_bus = std::make_shared<dbus::connection>(*io, dbus::bus::system); 172 173 app.run(); 174 } 175