summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
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) {