1 #include "crow/app.h" 2 #include "crow/ci_map.h" 3 #include "crow/common.h" 4 #include "crow/dumb_timer_queue.h" 5 #include "crow/http_connection.h" 6 #include "crow/http_parser_merged.h" 7 #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" 16 #include "crow/query_string.h" 17 #include "crow/routing.h" 18 #include "crow/settings.h" 19 #include "crow/socket_adaptors.h" 20 #include "crow/utility.h" 21 #include "crow/websocket.h" 22 23 #include "security_headers_middleware.hpp" 24 #include "ssl_key_handler.hpp" 25 #include "token_authorization_middleware.hpp" 26 #include "web_kvm.hpp" 27 #include "webassets.hpp" 28 29 #include <boost/asio.hpp> 30 #include <boost/endian/arithmetic.hpp> 31 32 #include <dbus/connection.hpp> 33 #include <dbus/endpoint.hpp> 34 #include <dbus/filter.hpp> 35 #include <dbus/match.hpp> 36 #include <dbus/message.hpp> 37 #include <dbus/utility.hpp> 38 39 #include <iostream> 40 #include <memory> 41 #include <string> 42 #include <unordered_set> 43 44 static std::shared_ptr<dbus::connection> system_bus; 45 static std::shared_ptr<dbus::match> sensor_match; 46 static std::shared_ptr<dbus::filter> sensor_filter; 47 static std::shared_ptr<dbus::filter> sensor_callback; 48 49 std::unordered_set<crow::websocket::connection*> users; 50 51 void on_sensor_update(boost::system::error_code ec, dbus::message s) { 52 std::string object_name; 53 std::vector<std::pair<std::string, dbus::dbus_variant>> values; 54 s.unpack(object_name).unpack(values); 55 crow::json::wvalue j; 56 for (auto& value : values) { 57 //std::cout << "Got sensor value for " << s.get_path() << "\n"; 58 boost::apply_visitor([&](auto val) { j[s.get_path()] = val; }, 59 value.second); 60 } 61 for (auto conn : users) { 62 conn->send_text(crow::json::dump(j)); 63 } 64 sensor_filter->async_dispatch(on_sensor_update); 65 }; 66 67 int main(int argc, char** argv) { 68 bool enable_ssl = true; 69 std::string ssl_pem_file("server.pem"); 70 71 if (enable_ssl) { 72 ensuressl::ensure_openssl_key_present_and_valid(ssl_pem_file); 73 } 74 75 crow::App<crow::TokenAuthorizationMiddleware, crow::SecurityHeadersMiddleware> 76 app; 77 78 crow::webassets::request_routes(app); 79 crow::kvm::request_routes(app); 80 81 crow::logger::setLogLevel(crow::LogLevel::INFO); 82 CROW_ROUTE(app, "/systeminfo") 83 ([]() { 84 85 crow::json::wvalue j; 86 j["device_id"] = 0x7B; 87 j["device_provides_sdrs"] = true; 88 j["device_revision"] = true; 89 j["device_available"] = true; 90 j["firmware_revision"] = "0.68"; 91 92 j["ipmi_revision"] = "2.0"; 93 j["supports_chassis_device"] = true; 94 j["supports_bridge"] = true; 95 j["supports_ipmb_event_generator"] = true; 96 j["supports_ipmb_event_receiver"] = true; 97 j["supports_fru_inventory_device"] = true; 98 j["supports_sel_device"] = true; 99 j["supports_sdr_repository_device"] = true; 100 j["supports_sensor_device"] = true; 101 102 j["firmware_aux_revision"] = "0.60.foobar"; 103 104 return j; 105 }); 106 107 CROW_ROUTE(app, "/sensorws") 108 .websocket() 109 .onopen([&](crow::websocket::connection& conn) { 110 system_bus = std::make_shared<dbus::connection>(conn.get_io_service(), 111 dbus::bus::system); 112 sensor_match = std::make_shared<dbus::match>( 113 *system_bus, 114 "type='signal',path_namespace='/xyz/openbmc_project/sensors'"); 115 116 sensor_filter = 117 std::make_shared<dbus::filter>(*system_bus, [](dbus::message& m) { 118 auto member = m.get_member(); 119 return member == "PropertiesChanged"; 120 }); 121 /* 122 std::function<void(boost::system::error_code, dbus::message)> 123 sensor_callback = [&conn, sensor_callback]( 124 boost::system::error_code ec, dbus::message s) { 125 std::string object_name; 126 std::vector<std::pair<std::string, dbus::dbus_variant>> values; 127 s.unpack(object_name).unpack(values); 128 crow::json::wvalue j; 129 for (auto& value : values) { 130 std::cout << "Got sensor value for " << s.get_path() << "\n"; 131 boost::apply_visitor([&](auto val) { j[s.get_path()] = val; }, 132 value.second); 133 } 134 for (auto conn : users) { 135 conn.send_text(crow::json::dump(j)); 136 } 137 sensor_filter->async_dispatch(sensor_callback); 138 }; 139 */ 140 sensor_filter->async_dispatch(on_sensor_update); 141 users.insert(&conn); 142 ; 143 }) 144 .onclose( 145 [&](crow::websocket::connection& conn, const std::string& reason) { 146 // TODO(ed) needs lock 147 users.erase(&conn); 148 }) 149 .onmessage([&](crow::websocket::connection& conn, const std::string& data, 150 bool is_binary) { 151 CROW_LOG_ERROR << "Got unexpected message from client on sensorws"; 152 }); 153 154 CROW_ROUTE(app, "/sensortest") 155 ([](const crow::request& req, crow::response& res) { 156 crow::json::wvalue j; 157 158 dbus::connection system_bus(*req.io_service, dbus::bus::system); 159 dbus::endpoint test_daemon("org.openbmc.Sensors", 160 "/org/openbmc/sensors/tach", 161 "org.freedesktop.DBus.Introspectable"); 162 dbus::message m = dbus::message::new_call(test_daemon, "Introspect"); 163 system_bus.async_send( 164 m, 165 [&j, &system_bus](const boost::system::error_code ec, dbus::message r) { 166 std::string xml; 167 r.unpack(xml); 168 std::vector<std::string> dbus_objects; 169 dbus::read_dbus_xml_names(xml, dbus_objects); 170 171 for (auto& object : dbus_objects) { 172 dbus::endpoint test_daemon("org.openbmc.Sensors", 173 "/org/openbmc/sensors/tach/" + object, 174 "org.openbmc.SensorValue"); 175 dbus::message m2 = dbus::message::new_call(test_daemon, "getValue"); 176 177 system_bus.async_send( 178 m2, [&](const boost::system::error_code ec, dbus::message r) { 179 int32_t value; 180 r.unpack(value); 181 // TODO(ed) if we ever go multithread, j needs a lock 182 j[object] = value; 183 }); 184 } 185 186 }); 187 188 }); 189 190 CROW_ROUTE(app, "/intel/firmwareupload") 191 .methods("POST"_method)([](const crow::request& req) { 192 // TODO(ed) handle errors here (file exists already and is locked, ect) 193 std::ofstream out( 194 "/tmp/fw_update_image", 195 std::ofstream::out | std::ofstream::binary | std::ofstream::trunc); 196 out << req.body; 197 out.close(); 198 199 crow::json::wvalue j; 200 j["status"] = "Upload Successfull"; 201 202 return j; 203 }); 204 205 std::cout << "Building SSL context\n"; 206 207 int port = 18080; 208 209 std::cout << "Starting webserver on port " << port << "\n"; 210 app.port(port); 211 if (enable_ssl) { 212 std::cout << "SSL Enabled\n"; 213 auto ssl_context = ensuressl::get_ssl_context(ssl_pem_file); 214 app.ssl(std::move(ssl_context)); 215 } 216 // app.concurrency(4); 217 app.run(); 218 } 219