summaryrefslogtreecommitdiffstats
path: root/sol/sol_manager.cpp
blob: 889065f779b75bad76650765f2d2fc2759c88565 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <sys/socket.h>
#include <sys/un.h>
#include <chrono>
#include <cmath>
#include <phosphor-logging/log.hpp>
#include "main.hpp"
#include "sol_context.hpp"
#include "sol_manager.hpp"

namespace sol
{

using namespace phosphor::logging;

CustomFD::~CustomFD()
{
    if(fd >= 0)
    {
        // Remove the host console descriptor from the sd_event_loop
        std::get<eventloop::EventLoop&>(singletonPool).stopHostConsole();
        close(fd);
    }
}

void Manager::initHostConsoleFd()
{
    struct sockaddr_un addr;
    int rc = 0;
    int fd = 0;

    fd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (fd < 0)
    {
        log<level::ERR>("Failed to open the host console socket",
                entry("ERRNO=%d", errno));
        throw std::runtime_error("Failed to open the host console socket");
    }

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    memcpy(&addr.sun_path, &CONSOLE_SOCKET_PATH, CONSOLE_SOCKET_PATH_LEN);
    consoleFD = std::make_unique<CustomFD>(fd);
    auto& conFD = *(consoleFD.get());

    rc = connect(conFD(), (struct sockaddr *)&addr, sizeof(addr));
    if (rc < 0)
    {
        log<level::ERR>("Failed to connect to host console socket address",
                entry("ERRNO=%d", errno));
        consoleFD.reset();
        throw std::runtime_error("Failed to connect to console server");
    }
}

int Manager::writeConsoleSocket(const Buffer& input) const
{
    auto inBuffer = input.data();
    auto inBufferSize = input.size();
    size_t pos = 0;
    ssize_t rc = 0;
    int errVal = 0;
    auto& conFD = *(consoleFD.get());

    for (pos = 0; pos < inBufferSize; pos += rc)
    {
        rc = write(conFD(), inBuffer + pos, inBufferSize - pos);
        if (rc <= 0)
        {
            if (errno == EINTR)
            {
                log<level::INFO>(" Retrying to handle EINTR",
                        entry("ERRNO=%d", errno));
                rc = 0;
                continue;
            }
            else
            {
                errVal = errno;
                log<level::ERR>("Failed to write to host console socket",
                        entry("ERRNO=%d", errno));
                return -errVal;
            }
        }
    }

    return 0;
}

void Manager::startPayloadInstance(uint8_t payloadInstance,
                                   session::SessionID sessionID)
{
    if (payloadMap.empty())
    {
        initHostConsoleFd();

        // Register the fd in the sd_event_loop
        std::get<eventloop::EventLoop&>(singletonPool).startHostConsole(
            *(consoleFD.get()));
    }

    // Create the SOL Context data for payload instance
    auto context = std::make_unique<Context>(
            retryCount, sendThreshold, payloadInstance, sessionID);

    std::get<eventloop::EventLoop&>(singletonPool).startSOLPayloadInstance(
            payloadInstance,
            std::chrono::duration_cast<eventloop::IntervalType>
                    (accumulateInterval),
            std::chrono::duration_cast<eventloop::IntervalType>(retryInterval));

    payloadMap.emplace(payloadInstance, std::move(context));
}

void Manager::stopPayloadInstance(uint8_t payloadInstance)
{
    auto iter = payloadMap.find(payloadInstance);
    if (iter == payloadMap.end())
    {
        throw std::runtime_error("SOL Payload instance not found ");
    }

    payloadMap.erase(iter);

    std::get<eventloop::EventLoop&>(singletonPool).stopSOLPayloadInstance(
            payloadInstance);

    if (payloadMap.empty())
    {
        consoleFD.reset();

        dataBuffer.erase(dataBuffer.size());
    }
}

} // namespace sol
OpenPOWER on IntegriCloud