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 <chrono> 10 #include <cmath> 11 #include <phosphor-logging/log.hpp> 12 13 namespace sol 14 { 15 16 using namespace phosphor::logging; 17 18 CustomFD::~CustomFD() 19 { 20 if (fd >= 0) 21 { 22 // Remove the host console descriptor from the sd_event_loop 23 std::get<eventloop::EventLoop&>(singletonPool).stopHostConsole(); 24 close(fd); 25 } 26 } 27 28 void Manager::initHostConsoleFd() 29 { 30 struct sockaddr_un addr; 31 int rc = 0; 32 int fd = 0; 33 34 fd = socket(AF_UNIX, SOCK_STREAM, 0); 35 if (fd < 0) 36 { 37 log<level::ERR>("Failed to open the host console socket", 38 entry("ERRNO=%d", errno)); 39 throw std::runtime_error("Failed to open the host console socket"); 40 } 41 42 memset(&addr, 0, sizeof(addr)); 43 addr.sun_family = AF_UNIX; 44 memcpy(&addr.sun_path, &CONSOLE_SOCKET_PATH, CONSOLE_SOCKET_PATH_LEN); 45 consoleFD = std::make_unique<CustomFD>(fd); 46 auto& conFD = *(consoleFD.get()); 47 48 rc = 49 connect(conFD(), (struct sockaddr*)&addr, 50 sizeof(addr) - sizeof(addr.sun_path) + CONSOLE_SOCKET_PATH_LEN); 51 if (rc < 0) 52 { 53 log<level::ERR>("Failed to connect to host console socket address", 54 entry("ERRNO=%d", errno)); 55 consoleFD.reset(); 56 throw std::runtime_error("Failed to connect to console server"); 57 } 58 } 59 60 int Manager::writeConsoleSocket(const std::vector<uint8_t>& input) const 61 { 62 auto inBuffer = input.data(); 63 auto inBufferSize = input.size(); 64 size_t pos = 0; 65 ssize_t rc = 0; 66 int errVal = 0; 67 auto& conFD = *(consoleFD.get()); 68 69 for (pos = 0; pos < inBufferSize; pos += rc) 70 { 71 rc = write(conFD(), inBuffer + pos, inBufferSize - pos); 72 if (rc <= 0) 73 { 74 if (errno == EINTR) 75 { 76 log<level::INFO>(" Retrying to handle EINTR", 77 entry("ERRNO=%d", errno)); 78 rc = 0; 79 continue; 80 } 81 else 82 { 83 errVal = errno; 84 log<level::ERR>("Failed to write to host console socket", 85 entry("ERRNO=%d", errno)); 86 return -errVal; 87 } 88 } 89 } 90 91 return 0; 92 } 93 94 void Manager::startPayloadInstance(uint8_t payloadInstance, 95 session::SessionID sessionID) 96 { 97 if (payloadMap.empty()) 98 { 99 initHostConsoleFd(); 100 101 // Register the fd in the sd_event_loop 102 std::get<eventloop::EventLoop&>(singletonPool) 103 .startHostConsole(*(consoleFD.get())); 104 } 105 106 // Create the SOL Context data for payload instance 107 auto context = std::make_unique<Context>(retryCount, sendThreshold, 108 payloadInstance, sessionID); 109 110 std::get<eventloop::EventLoop&>(singletonPool) 111 .startSOLPayloadInstance( 112 payloadInstance, 113 std::chrono::duration_cast<eventloop::IntervalType>( 114 accumulateInterval), 115 std::chrono::duration_cast<eventloop::IntervalType>(retryInterval)); 116 117 payloadMap.emplace(payloadInstance, std::move(context)); 118 } 119 120 void Manager::stopPayloadInstance(uint8_t payloadInstance) 121 { 122 auto iter = payloadMap.find(payloadInstance); 123 if (iter == payloadMap.end()) 124 { 125 throw std::runtime_error("SOL Payload instance not found "); 126 } 127 128 payloadMap.erase(iter); 129 130 std::get<eventloop::EventLoop&>(singletonPool) 131 .stopSOLPayloadInstance(payloadInstance); 132 133 if (payloadMap.empty()) 134 { 135 consoleFD.reset(); 136 137 dataBuffer.erase(dataBuffer.size()); 138 } 139 } 140 141 } // namespace sol 142