1 #pragma once
2 
3 #include <systemd/sd-event.h>
4 #include <chrono>
5 #include <map>
6 
7 namespace eventloop
8 {
9 
10 /** @struct EventSourceDeleter
11  *
12  *  Custom deleter for the sd_event_source*.
13  */
14 struct EventSourceDeleter
15 {
16     void operator()(sd_event_source* event) const
17     {
18         event = sd_event_source_unref(event);
19     }
20 };
21 
22 using EventSource = std::unique_ptr<sd_event_source, EventSourceDeleter>;
23 using IntervalType = std::chrono::microseconds;
24 
25 /** @enum Timers
26  *
27  *  For SOL functioning, there are two timers involved. The character accumulate
28  *  interval timer is the amount of time that the BMC will wait before
29  *  transmitting a partial SOL packet. The retry interval timer is the time that
30  *  BMC will wait before the first retry and the time between retries when
31  *  sending SOL packets to the remote console.
32  */
33 enum class Timers
34 {
35     ACCUMULATE,   /**< Character Accumulate Timer */
36     RETRY,        /**< Retry Interval Timer */
37 };
38 
39 class EventLoop
40 {
41     public:
42 
43         EventLoop() = default;
44         ~EventLoop() = default;
45         EventLoop(const EventLoop&) = delete;
46         EventLoop& operator=(const EventLoop&) = delete;
47         EventLoop(EventLoop&&) = delete;
48         EventLoop& operator=(EventLoop&&) = delete;
49 
50         /** @brief Timer Map
51          *
52          *  The key for the timer map is the timer type. There are two types of
53          *  timers, character accumulate timer and retry interval timer. The
54          *  entries in the values is the event source for the timer and the
55          *  interval.
56          */
57         using TimerMap = std::map<Timers, std::tuple<EventSource,
58                                                      IntervalType>>;
59 
60         /** @brief SOL Payload Map.
61          *
62          *  The key for the payload map is the payload instance, the entries in
63          *  the value are a map of timers.
64          */
65         using PayloadMap = std::map<uint8_t, TimerMap>;
66 
67         /** @brief Initialise the event loop and add the handler for incoming
68          *         IPMI packets.
69          *
70          *  @return EXIT_SUCCESS on success and EXIT_FAILURE on failure.
71          */
72         int startEventLoop();
73 
74         /** @brief Add host console I/O event source to the event loop.
75          *
76          *  @param[in] fd - File descriptor for host console socket.
77          */
78         void startHostConsole(const sol::CustomFD& fd);
79 
80         /** @brief Remove host console I/O event source. */
81         void stopHostConsole();
82 
83         /** @brief Initialize the timers for the SOL payload instance
84          *
85          *  This API would add the Character accumulate interval timer event
86          *  source and the retry interval timer event source for the SOL payload
87          *  instance to the event loop.
88          *
89          *  @param[in] payloadInst - SOL payload instance.
90          *  @param[in] accumulateInterval - Character accumulate interval.
91          *  @param[in] retryInterval - Retry interval.
92          */
93         void startSOLPayloadInstance(uint8_t payloadInst,
94                                      IntervalType accumulateInterval,
95                                      IntervalType retryInterval);
96 
97         /** @brief Stop the timers for the SOL payload instance.
98          *
99          *  This would remove the character accumulate interval timer event
100          *  source and the retry interval timer event source from the event
101          *  loop.
102          *
103          *  @param[in] payloadInst - SOL payload instance
104          */
105         void stopSOLPayloadInstance(uint8_t payloadInst);
106 
107         /** @brief Modify the timer event source to enable/disable.
108          *
109          *  When the timer is enabled, the timer it set to fire again at
110          *  timer's interval for the instance added to the event loop iteration
111          *  timestamp. When the timer is disabled, the event source for the
112          *  timer is disabled.
113          *
114          *  @param[in] payloadInst - SOL payload instance.
115          *  @param[in] type -  Timer type.
116          *  @param[in] status - on/off the event source.
117          */
118         void switchTimer(uint8_t payloadInst,
119                          Timers type,
120                          bool status);
121 
122         /** @brief Modify the retry interval timer event source to enable/
123          *         disable
124          *
125          *  When the timer is enabled, the timer it set to fire again at
126          *  retry interval for the instance added to the event loop iteration
127          *  timestamp. When the timer is disabled the event source for the
128          *  retry interval timer is disabled.
129          *
130          *  @param[in] payloadInst - SOL payload instance.
131          *  @param[in] status - on/off the event source.
132          */
133         void switchRetryTimer(uint8_t payloadInst, bool status);
134 
135     private:
136         /** @brief Event source object for host console. */
137         EventSource hostConsole = nullptr;
138 
139         /** @brief Event source for the UDP socket listening on IPMI standard
140          *         port.
141          */
142         EventSource udpIPMI = nullptr;
143 
144         /** @brief Map to keep information regarding IPMI payload instance and
145          *         timers for character accumulate interval and retry interval.
146          */
147         PayloadMap payloadInfo;
148 
149         /** @brief Event loop object. */
150         sd_event* event = nullptr;
151 };
152 
153 } // namespace eventloop
154