summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorNinad Palsule <ninadpalsule@us.ibm.com>2023-04-11 00:40:00 +0300
committerEd Tanous <ed@tanous.net>2023-05-25 06:32:31 +0300
commita8d4b8e62e2c718e1be83aefefd0cd7175043e7f (patch)
tree9452c27e11e440c999da9ddcbe1d9976e037fdf8 /include
parentdfbf7de5d2bc404bd9ce60f113d3acb98bf8db5b (diff)
downloadbmcweb-a8d4b8e62e2c718e1be83aefefd0cd7175043e7f.tar.xz
Use console information from DBUS
This drop is a preparation of supporting multiple consoles in bmcweb. In this drop we will hook up the new DBUS interface to get the unix socket file descriptor for existing host console. At this time bmcweb only allows host console. This drop includes following bmcweb changes: - The default console leaf node is set to "default" by the obmc-console - Currently the URL is still maintained to /console0 for GUI compatibility. In future, it will be changed to /console/<str> where <str> could be any string which represents the console id. - In the obmc routing function, query the console DBUS interface for all available consoles. If the object leaf matches with the target string, then create socket and assign the file descriptor returned by the DBUS console. [INFO "http_connection.hpp":209] Request: 0x1b8c608 HTTP/1.1 GET /console0 ::ffff:x.xxx.xx.xxx | [DEBUG "routing.hpp":1440] Matched rule (upgrade) '/console0' 1 / 2 | [DEBUG "obmc_console.hpp":247] Connection 0x13e3c8c opened [DEBUG "obmc_console.hpp":268] Console Object path = \ /xyz/openbmc_project/console/default Request target = /console0 [DEBUG "obmc_console.hpp":230] Looking up unixFD for Service \ xyz.openbmc_project.Console.default Path /xyz/openbmc_project/console/default [DEBUG "obmc_console.hpp":157] Console web socket path: /console0 Console\ unix FD: 12 duped FD: 13 Testing: Make sure that console open is working for /console0 on rainier machine Related commits: 1) phosphor-dbus-interface: https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/61486 2) obmc-console: https://gerrit.openbmc.org/c/openbmc/obmc-console/+/62496 3) bmcweb: https://gerrit.openbmc.org/c/openbmc/bmcweb/+/62525 Change-Id: I476f1bb3e3be384ab09802340a59ffa036ca0278 Signed-off-by: Ninad Palsule <ninadpalsule@us.ibm.com>
Diffstat (limited to 'include')
-rw-r--r--include/obmc_console.hpp153
1 files changed, 122 insertions, 31 deletions
diff --git a/include/obmc_console.hpp b/include/obmc_console.hpp
index cf90c0ed94..ae8143a9df 100644
--- a/include/obmc_console.hpp
+++ b/include/obmc_console.hpp
@@ -64,7 +64,7 @@ inline void doWrite()
}
if (ec)
{
- BMCWEB_LOG_ERROR << "Error in host serial write " << ec;
+ BMCWEB_LOG_ERROR << "Error in host serial write " << ec.message();
return;
}
doWrite();
@@ -86,7 +86,8 @@ inline void doRead()
BMCWEB_LOG_DEBUG << "read done. Read " << bytesRead << " bytes";
if (ec)
{
- BMCWEB_LOG_ERROR << "Couldn't read from host serial port: " << ec;
+ BMCWEB_LOG_ERROR << "Couldn't read from host serial port: "
+ << ec.message();
for (crow::websocket::Connection* session : sessions)
{
session->close("Error in connecting to host port");
@@ -102,20 +103,131 @@ inline void doRead()
});
}
-inline void connectHandler(const boost::system::error_code& ec)
+// If connection is active then remove it from the connection map
+inline bool removeConnection(crow::websocket::Connection& conn)
{
+ bool ret = false;
+
+ if (sessions.erase(&conn) != 0U)
+ {
+ ret = true;
+ }
+
+ if (sessions.empty())
+ {
+ hostSocket = nullptr;
+ inputBuffer.clear();
+ inputBuffer.shrink_to_fit();
+ }
+ return ret;
+}
+
+inline void connectConsoleSocket(crow::websocket::Connection& conn,
+ const boost::system::error_code& ec,
+ const sdbusplus::message::unix_fd& unixfd)
+{
+ int fd = -1;
+
if (ec)
{
- BMCWEB_LOG_ERROR << "Couldn't connect to host serial port: " << ec;
- for (crow::websocket::Connection* session : sessions)
+ BMCWEB_LOG_ERROR << "Failed to call console Connect() method"
+ << " DBUS error: " << ec.message();
+ if (removeConnection(conn))
{
- session->close("Error in connecting to host port");
+ conn.close("Failed to call console Connect() method");
}
return;
}
- doWrite();
- doRead();
+ // Make sure that connection is still open.
+ if (!sessions.contains(&conn))
+ {
+ return;
+ }
+
+ fd = dup(unixfd);
+ if (fd == -1)
+ {
+ BMCWEB_LOG_ERROR << "Failed to dup the DBUS unixfd"
+ << " error: " << strerror(errno);
+ if (removeConnection(conn))
+ {
+ conn.close("Failed to dup the DBUS unixfd");
+ }
+ return;
+ }
+
+ BMCWEB_LOG_DEBUG << "Console web socket path: " << conn.req.target()
+ << " Console unix FD: " << unixfd << " duped FD: " << fd;
+
+ if (hostSocket == nullptr)
+ {
+ boost::system::error_code ec1;
+ boost::asio::local::stream_protocol proto;
+ hostSocket =
+ std::make_unique<boost::asio::local::stream_protocol::socket>(
+ conn.getIoContext());
+
+ hostSocket->assign(proto, fd, ec1);
+
+ if (ec1)
+ {
+ close(fd);
+ BMCWEB_LOG_ERROR << "Failed to assign the DBUS socket"
+ << " Socket assign error: " << ec1.message();
+ if (removeConnection(conn))
+ {
+ conn.close("Failed to assign the DBUS socket");
+ }
+ }
+ else
+ {
+ conn.resumeRead();
+ doWrite();
+ doRead();
+ }
+ }
+ else
+ {
+ BMCWEB_LOG_DEBUG << "Socket already exist so close the new fd: " << fd;
+ close(fd);
+ }
+}
+
+// Query consoles from DBUS and find the matching to the
+// rules string.
+inline void onOpen(crow::websocket::Connection& conn)
+{
+ BMCWEB_LOG_DEBUG << "Connection " << &conn << " opened";
+
+ // Save the connection in the map
+ sessions.insert(&conn);
+
+ // We need to wait for dbus and the websockets to hook up before data is
+ // sent/received. Tell the core to hold off messages until the sockets are
+ // up
+ if (hostSocket == nullptr)
+ {
+ conn.deferRead();
+ }
+
+ // The console id 'default' is used for the console0
+ // We need to change it when we provide full multi-console support.
+ const std::string consolePath = "/xyz/openbmc_project/console/default";
+ const std::string consoleService = "xyz.openbmc_project.Console.default";
+
+ BMCWEB_LOG_DEBUG << "Console Object path = " << consolePath
+ << " service = " << consoleService
+ << " Request target = " << conn.req.target();
+
+ // Call Connect() method to get the unix FD
+ crow::connections::systemBus->async_method_call(
+ [&conn](const boost::system::error_code& ec,
+ const sdbusplus::message::unix_fd& unixfd) {
+ connectConsoleSocket(conn, ec, unixfd);
+ },
+ consoleService, consolePath, "xyz.openbmc_project.Console.Access",
+ "Connect");
}
inline void requestRoutes(App& app)
@@ -123,33 +235,12 @@ inline void requestRoutes(App& app)
BMCWEB_ROUTE(app, "/console0")
.privileges({{"OpenBMCHostConsole"}})
.websocket()
- .onopen(
- [](crow::websocket::Connection& conn) {
- BMCWEB_LOG_DEBUG << "Connection " << &conn << " opened";
-
- sessions.insert(&conn);
- if (hostSocket == nullptr)
- {
- const std::string consoleName("\0obmc-console", 13);
- boost::asio::local::stream_protocol::endpoint ep(consoleName);
-
- hostSocket =
- std::make_unique<boost::asio::local::stream_protocol::socket>(
- conn.getIoContext());
- hostSocket->async_connect(ep, connectHandler);
- }
- })
+ .onopen(onOpen)
.onclose([](crow::websocket::Connection& conn,
[[maybe_unused]] const std::string& reason) {
BMCWEB_LOG_INFO << "Closing websocket. Reason: " << reason;
- sessions.erase(&conn);
- if (sessions.empty())
- {
- hostSocket = nullptr;
- inputBuffer.clear();
- inputBuffer.shrink_to_fit();
- }
+ removeConnection(conn);
})
.onmessage([]([[maybe_unused]] crow::websocket::Connection& conn,
const std::string& data, [[maybe_unused]] bool isBinary) {