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