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