summaryrefslogtreecommitdiffstats
path: root/sd_event_loop.hpp
blob: 5218b2735c900fb8cb98285bb4584e56c1a8a11f (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#pragma once

#include "sol/sol_manager.hpp"

#include <systemd/sd-event.h>

#include <boost/asio/io_context.hpp>
#include <chrono>
#include <map>

namespace eventloop
{

/** @struct EventSourceDeleter
 *
 *  Custom deleter for the sd_event_source*.
 */
struct EventSourceDeleter
{
    void operator()(sd_event_source* event) const
    {
        event = sd_event_source_unref(event);
    }
};

using EventSource = std::unique_ptr<sd_event_source, EventSourceDeleter>;
using IntervalType = std::chrono::microseconds;

/** @enum Timers
 *
 *  For SOL functioning, there are two timers involved. The character accumulate
 *  interval timer is the amount of time that the BMC will wait before
 *  transmitting a partial SOL packet. The retry interval timer is the time that
 *  BMC will wait before the first retry and the time between retries when
 *  sending SOL packets to the remote console.
 */
enum class Timers
{
    ACCUMULATE, /**< Character Accumulate Timer */
    RETRY,      /**< Retry Interval Timer */
};

class EventLoop
{
  public:
    explicit EventLoop(std::shared_ptr<boost::asio::io_context> io) : io(io)
    {
    }
    EventLoop() = delete;
    ~EventLoop() = default;
    EventLoop(const EventLoop&) = delete;
    EventLoop& operator=(const EventLoop&) = delete;
    EventLoop(EventLoop&&) = delete;
    EventLoop& operator=(EventLoop&&) = delete;

    /** @brief Timer Map
     *
     *  The key for the timer map is the timer type. There are two types of
     *  timers, character accumulate timer and retry interval timer. The
     *  entries in the values is the event source for the timer and the
     *  interval.
     */
    using TimerMap = std::map<Timers, std::tuple<EventSource, IntervalType>>;

    /** @brief SOL Payload Map.
     *
     *  The key for the payload map is the payload instance, the entries in
     *  the value are a map of timers.
     */
    using PayloadMap = std::map<uint8_t, TimerMap>;

    /** @brief Initialise the event loop and add the handler for incoming
     *         IPMI packets.
     *
     *  @return EXIT_SUCCESS on success and EXIT_FAILURE on failure.
     */
    int startEventLoop();

    /** @brief Add host console I/O event source to the event loop.
     *
     *  @param[in] fd - File descriptor for host console socket.
     */
    void startHostConsole(const sol::CustomFD& fd);

    /** @brief Remove host console I/O event source. */
    void stopHostConsole();

    /** @brief Initialize the timers for the SOL payload instance
     *
     *  This API would add the Character accumulate interval timer event
     *  source and the retry interval timer event source for the SOL payload
     *  instance to the event loop.
     *
     *  @param[in] payloadInst - SOL payload instance.
     *  @param[in] accumulateInterval - Character accumulate interval.
     *  @param[in] retryInterval - Retry interval.
     */
    void startSOLPayloadInstance(uint8_t payloadInst,
                                 IntervalType accumulateInterval,
                                 IntervalType retryInterval);

    /** @brief Stop the timers for the SOL payload instance.
     *
     *  This would remove the character accumulate interval timer event
     *  source and the retry interval timer event source from the event
     *  loop.
     *
     *  @param[in] payloadInst - SOL payload instance
     */
    void stopSOLPayloadInstance(uint8_t payloadInst);

    /** @brief Modify the timer event source to enable/disable.
     *
     *  When the timer is enabled, the timer it set to fire again at
     *  timer's interval for the instance added to the event loop iteration
     *  timestamp. When the timer is disabled, the event source for the
     *  timer is disabled.
     *
     *  @param[in] payloadInst - SOL payload instance.
     *  @param[in] type -  Timer type.
     *  @param[in] status - on/off the event source.
     */
    void switchTimer(uint8_t payloadInst, Timers type, bool status);

    /** @brief Modify the retry interval timer event source to enable/
     *         disable
     *
     *  When the timer is enabled, the timer it set to fire again at
     *  retry interval for the instance added to the event loop iteration
     *  timestamp. When the timer is disabled the event source for the
     *  retry interval timer is disabled.
     *
     *  @param[in] payloadInst - SOL payload instance.
     *  @param[in] status - on/off the event source.
     */
    void switchRetryTimer(uint8_t payloadInst, bool status);

    /** @brief Event loop object. */
    sd_event* event = nullptr;

  private:
    /** @brief Event source object for host console. */
    EventSource hostConsole = nullptr;

    /** @brief boost::asio io context to run with
     */
    std::shared_ptr<boost::asio::io_context> io;

    /** @brief Event source for the UDP socket listening on IPMI standard
     *         port.
     */
    EventSource udpIPMI = nullptr;

    /** @brief Map to keep information regarding IPMI payload instance and
     *         timers for character accumulate interval and retry interval.
     */
    PayloadMap payloadInfo;
};

} // namespace eventloop
OpenPOWER on IntegriCloud