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