blob: a118457e63dfacff785de59d7ec665beb5531050 [file] [log] [blame]
Vernon Mauery9e801a22018-10-12 13:20:49 -07001#include "sol_manager.hpp"
2
3#include "main.hpp"
4#include "sol_context.hpp"
5
Tom Joseph22c5ad32017-03-14 18:04:22 +05306#include <sys/socket.h>
7#include <sys/un.h>
Vernon Mauery9e801a22018-10-12 13:20:49 -07008
Vernon Mauery7e4a6512018-11-09 08:43:36 -08009#include <boost/asio/basic_stream_socket.hpp>
10#include <boost/asio/io_context.hpp>
11#include <boost/asio/local/stream_protocol.hpp>
12#include <boost/asio/write.hpp>
Tom Joseph2e44e0e2017-03-14 18:09:11 +053013#include <chrono>
Tom Joseph22c5ad32017-03-14 18:04:22 +053014#include <cmath>
srikanta mondalf6e72302020-06-08 12:46:28 +000015#include <ipmid/utils.hpp>
Tom Joseph22c5ad32017-03-14 18:04:22 +053016#include <phosphor-logging/log.hpp>
Tom Joseph22c5ad32017-03-14 18:04:22 +053017
18namespace sol
19{
20
21using namespace phosphor::logging;
22
srikanta mondalf6e72302020-06-08 12:46:28 +000023std::unique_ptr<sdbusplus::bus::match_t> matchPtrSOL(nullptr);
24
Vernon Mauery7e4a6512018-11-09 08:43:36 -080025void Manager::initConsoleSocket()
Tom Josephb81f7612017-04-25 17:59:02 +053026{
Vernon Mauery7e4a6512018-11-09 08:43:36 -080027 // explicit length constructor for NUL-prefixed abstract path
28 std::string path(CONSOLE_SOCKET_PATH, CONSOLE_SOCKET_PATH_LEN);
29 boost::asio::local::stream_protocol::endpoint ep(path);
30 consoleSocket =
31 std::make_unique<boost::asio::local::stream_protocol::socket>(*io);
32 consoleSocket->connect(ep);
Tom Josephb81f7612017-04-25 17:59:02 +053033}
34
Vernon Mauery7e4a6512018-11-09 08:43:36 -080035void Manager::consoleInputHandler()
Tom Joseph22c5ad32017-03-14 18:04:22 +053036{
Vernon Mauery7e4a6512018-11-09 08:43:36 -080037 boost::system::error_code ec;
38 boost::asio::socket_base::bytes_readable cmd(true);
39 consoleSocket->io_control(cmd, ec);
40 size_t readSize;
41 if (!ec)
Tom Joseph22c5ad32017-03-14 18:04:22 +053042 {
Vernon Mauery7e4a6512018-11-09 08:43:36 -080043 readSize = cmd.get();
44 }
45 else
46 {
47 log<level::ERR>("Reading ready count from host console socket failed:",
48 entry("EXCEPTION=%s", ec.message().c_str()));
49 return;
50 }
51 std::vector<uint8_t> buffer(readSize);
52 ec.clear();
53 size_t readDataLen =
54 consoleSocket->read_some(boost::asio::buffer(buffer), ec);
55 if (ec)
56 {
57 log<level::ERR>("Reading from host console socket failed:",
58 entry("EXCEPTION=%s", ec.message().c_str()));
59 return;
Tom Joseph22c5ad32017-03-14 18:04:22 +053060 }
61
Vernon Mauery7e4a6512018-11-09 08:43:36 -080062 // Update the Console buffer with data read from the socket
63 buffer.resize(readDataLen);
64 dataBuffer.write(buffer);
Tom Joseph22c5ad32017-03-14 18:04:22 +053065}
66
Vernon Mauery70fd29c2017-11-30 13:11:43 -080067int Manager::writeConsoleSocket(const std::vector<uint8_t>& input) const
Tom Josephb51f6412017-03-14 18:08:14 +053068{
Vernon Mauery7e4a6512018-11-09 08:43:36 -080069 boost::system::error_code ec;
70 boost::asio::write(*consoleSocket, boost::asio::buffer(input), ec);
71 return ec.value();
72}
Tom Josephb51f6412017-03-14 18:08:14 +053073
Vernon Mauery7e4a6512018-11-09 08:43:36 -080074void Manager::startHostConsole()
75{
76 if (!consoleSocket)
Tom Josephb51f6412017-03-14 18:08:14 +053077 {
Vernon Mauery7e4a6512018-11-09 08:43:36 -080078 initConsoleSocket();
Tom Josephb51f6412017-03-14 18:08:14 +053079 }
srikanta mondalf6e72302020-06-08 12:46:28 +000080
81 // Register callback to close SOL session for disable SSH SOL
82 if (matchPtrSOL == nullptr)
83 {
84 registerSOLServiceChangeCallback();
85 }
86
Vernon Mauery7e4a6512018-11-09 08:43:36 -080087 consoleSocket->async_wait(boost::asio::socket_base::wait_read,
88 [this](const boost::system::error_code& ec) {
89 if (!ec)
90 {
91 consoleInputHandler();
92 startHostConsole();
93 }
94 });
Rashmi RV0f63e012019-11-21 15:38:50 +053095} // namespace sol
Tom Josephb51f6412017-03-14 18:08:14 +053096
Vernon Mauery7e4a6512018-11-09 08:43:36 -080097void Manager::stopHostConsole()
98{
99 if (consoleSocket)
100 {
101 consoleSocket->cancel();
102 consoleSocket.reset();
103 }
Tom Josephb51f6412017-03-14 18:08:14 +0530104}
105
Tom Joseph2e44e0e2017-03-14 18:09:11 +0530106void Manager::startPayloadInstance(uint8_t payloadInstance,
107 session::SessionID sessionID)
108{
109 if (payloadMap.empty())
110 {
Rashmi RV0f63e012019-11-21 15:38:50 +0530111 try
112 {
113 startHostConsole();
114 }
115 catch (const std::exception& e)
116 {
117 log<level::ERR>("Encountered exception when starting host console. "
118 "Hence stopping host console.",
119 entry("EXCEPTION=%s", e.what()));
120 stopHostConsole();
121 throw;
122 }
Tom Joseph2e44e0e2017-03-14 18:09:11 +0530123 }
124
125 // Create the SOL Context data for payload instance
Vernon Mauerya6ad5e12020-02-21 14:54:24 -0800126 std::shared_ptr<Context> context = Context::makeContext(
127 io, retryCount, sendThreshold, payloadInstance, sessionID);
Tom Joseph2e44e0e2017-03-14 18:09:11 +0530128
Tom Joseph2e44e0e2017-03-14 18:09:11 +0530129 payloadMap.emplace(payloadInstance, std::move(context));
130}
131
Tom Joseph4ff14b52017-03-14 18:10:52 +0530132void Manager::stopPayloadInstance(uint8_t payloadInstance)
133{
134 auto iter = payloadMap.find(payloadInstance);
135 if (iter == payloadMap.end())
136 {
137 throw std::runtime_error("SOL Payload instance not found ");
138 }
139
140 payloadMap.erase(iter);
141
Tom Joseph4ff14b52017-03-14 18:10:52 +0530142 if (payloadMap.empty())
143 {
Vernon Mauery7e4a6512018-11-09 08:43:36 -0800144 stopHostConsole();
Tom Josephde203ce2017-08-01 16:48:06 +0530145
146 dataBuffer.erase(dataBuffer.size());
Tom Joseph4ff14b52017-03-14 18:10:52 +0530147 }
148}
149
srikanta mondalf6e72302020-06-08 12:46:28 +0000150void Manager::stopAllPayloadInstance()
151{
152 // Erase all payload instance
153 payloadMap.erase(payloadMap.begin(), payloadMap.end());
154
155 stopHostConsole();
156
157 dataBuffer.erase(dataBuffer.size());
158}
159
160void registerSOLServiceChangeCallback()
161{
162 using namespace sdbusplus::bus::match::rules;
163 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
164 try
165 {
166 auto servicePath = ipmi::getDbusObject(
167 bus, "xyz.openbmc_project.Control.Service.Attributes",
168 "/xyz/openbmc_project/control/service", "obmc_2dconsole");
169
170 if (!std::empty(servicePath.first))
171 {
172 matchPtrSOL = std::make_unique<sdbusplus::bus::match_t>(
173 bus,
174 path_namespace(servicePath.first) +
175 "arg0namespace='xyz.openbmc_project.Control.Service."
176 "Attributes'"
177 ", " +
178 type::signal() + member("PropertiesChanged") +
179 interface("org.freedesktop.DBus.Properties"),
180 [](sdbusplus::message::message& msg) {
181 std::string intfName;
182 std::map<std::string, std::variant<bool>> properties;
183 msg.read(intfName, properties);
184
185 const auto it = properties.find("Enabled");
186 if (it != properties.end())
187 {
188 const bool* state = std::get_if<bool>(&it->second);
189
190 if (state != nullptr && *state == false)
191 {
192 // Stop all the payload session.
193 std::get<sol::Manager&>(singletonPool)
194 .stopAllPayloadInstance();
195 }
196 }
197 });
198 }
199 }
200 catch (sdbusplus::exception_t& e)
201 {
202 log<level::ERR>(
203 "Failed to get service path in registerSOLServiceChangeCallback");
204 }
205}
206
Tom Joseph22c5ad32017-03-14 18:04:22 +0530207} // namespace sol