1 #include "sol_manager.hpp"
2 
3 #include "main.hpp"
4 #include "sol_context.hpp"
5 
6 #include <sys/socket.h>
7 #include <sys/un.h>
8 
9 #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>
13 #include <chrono>
14 #include <cmath>
15 #include <phosphor-logging/log.hpp>
16 
17 namespace sol
18 {
19 
20 using namespace phosphor::logging;
21 
22 void Manager::initConsoleSocket()
23 {
24     // explicit length constructor for NUL-prefixed abstract path
25     std::string path(CONSOLE_SOCKET_PATH, CONSOLE_SOCKET_PATH_LEN);
26     boost::asio::local::stream_protocol::endpoint ep(path);
27     consoleSocket =
28         std::make_unique<boost::asio::local::stream_protocol::socket>(*io);
29     consoleSocket->connect(ep);
30 }
31 
32 void Manager::consoleInputHandler()
33 {
34     boost::system::error_code ec;
35     boost::asio::socket_base::bytes_readable cmd(true);
36     consoleSocket->io_control(cmd, ec);
37     size_t readSize;
38     if (!ec)
39     {
40         readSize = cmd.get();
41     }
42     else
43     {
44         log<level::ERR>("Reading ready count from host console socket failed:",
45                         entry("EXCEPTION=%s", ec.message().c_str()));
46         return;
47     }
48     std::vector<uint8_t> buffer(readSize);
49     ec.clear();
50     size_t readDataLen =
51         consoleSocket->read_some(boost::asio::buffer(buffer), ec);
52     if (ec)
53     {
54         log<level::ERR>("Reading from host console socket failed:",
55                         entry("EXCEPTION=%s", ec.message().c_str()));
56         return;
57     }
58 
59     // Update the Console buffer with data read from the socket
60     buffer.resize(readDataLen);
61     dataBuffer.write(buffer);
62 }
63 
64 int Manager::writeConsoleSocket(const std::vector<uint8_t>& input) const
65 {
66     boost::system::error_code ec;
67     boost::asio::write(*consoleSocket, boost::asio::buffer(input), ec);
68     return ec.value();
69 }
70 
71 void Manager::startHostConsole()
72 {
73     if (!consoleSocket)
74     {
75         initConsoleSocket();
76     }
77     consoleSocket->async_wait(boost::asio::socket_base::wait_read,
78                               [this](const boost::system::error_code& ec) {
79                                   if (!ec)
80                                   {
81                                       consoleInputHandler();
82                                       startHostConsole();
83                                   }
84                               });
85 } // namespace sol
86 
87 void Manager::stopHostConsole()
88 {
89     if (consoleSocket)
90     {
91         consoleSocket->cancel();
92         consoleSocket.reset();
93     }
94 }
95 
96 void Manager::startPayloadInstance(uint8_t payloadInstance,
97                                    session::SessionID sessionID)
98 {
99     if (payloadMap.empty())
100     {
101         try
102         {
103             startHostConsole();
104         }
105         catch (const std::exception& e)
106         {
107             log<level::ERR>("Encountered exception when starting host console. "
108                             "Hence stopping host console.",
109                             entry("EXCEPTION=%s", e.what()));
110             stopHostConsole();
111             throw;
112         }
113     }
114 
115     // Create the SOL Context data for payload instance
116     std::shared_ptr<Context> context = Context::makeContext(
117         io, retryCount, sendThreshold, payloadInstance, sessionID);
118 
119     payloadMap.emplace(payloadInstance, std::move(context));
120 }
121 
122 void Manager::stopPayloadInstance(uint8_t payloadInstance)
123 {
124     auto iter = payloadMap.find(payloadInstance);
125     if (iter == payloadMap.end())
126     {
127         throw std::runtime_error("SOL Payload instance not found ");
128     }
129 
130     payloadMap.erase(iter);
131 
132     if (payloadMap.empty())
133     {
134         stopHostConsole();
135 
136         dataBuffer.erase(dataBuffer.size());
137     }
138 }
139 
140 } // namespace sol
141