1 #pragma once
2 
3 #include "main.hpp"
4 #include "sol/sol_manager.hpp"
5 
6 #include <systemd/sd-event.h>
7 
8 #include <boost/asio/io_context.hpp>
9 #include <sdbusplus/asio/connection.hpp>
10 
11 #include <chrono>
12 #include <map>
13 #include <string>
14 
15 namespace ipmi
16 {
17 namespace rmcpp
18 {
19 constexpr uint16_t defaultPort = 623;
20 } // namespace rmcpp
21 } // namespace ipmi
22 
23 namespace eventloop
24 {
25 using DbusObjectPath = std::string;
26 using DbusService = std::string;
27 using DbusInterface = std::string;
28 using ObjectTree =
29     std::map<DbusObjectPath, std::map<DbusService, std::vector<DbusInterface>>>;
30 using Value = std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
31                            int64_t, uint64_t, double, std::string>;
32 // VLANs are a 12-bit value
33 constexpr uint16_t VLAN_VALUE_MASK = 0x0fff;
34 constexpr auto MAPPER_BUS_NAME = "xyz.openbmc_project.ObjectMapper";
35 constexpr auto MAPPER_OBJ = "/xyz/openbmc_project/object_mapper";
36 constexpr auto MAPPER_INTF = "xyz.openbmc_project.ObjectMapper";
37 constexpr auto PATH_ROOT = "/xyz/openbmc_project/network";
38 constexpr auto INTF_VLAN = "xyz.openbmc_project.Network.VLAN";
39 constexpr auto INTF_ETHERNET = "xyz.openbmc_project.Network.EthernetInterface";
40 constexpr auto METHOD_GET = "Get";
41 constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";
42 
43 class EventLoop
44 {
45   private:
46     struct Private
47     {};
48 
49   public:
EventLoop(std::shared_ptr<boost::asio::io_context> & io,const Private &)50     EventLoop(std::shared_ptr<boost::asio::io_context>& io, const Private&) :
51         io(io)
52     {}
53     EventLoop() = delete;
54     ~EventLoop() = default;
55     EventLoop(const EventLoop&) = delete;
56     EventLoop& operator=(const EventLoop&) = delete;
57     EventLoop(EventLoop&&) = delete;
58     EventLoop& operator=(EventLoop&&) = delete;
59 
60     /**
61      * @brief Get a reference to the singleton EventLoop
62      *
63      * @return EventLoop reference
64      */
get()65     static EventLoop& get()
66     {
67         static std::shared_ptr<EventLoop> ptr = nullptr;
68         if (!ptr)
69         {
70             std::shared_ptr<boost::asio::io_context> io = getIo();
71             ptr = std::make_shared<EventLoop>(io, Private());
72         }
73         return *ptr;
74     }
75 
76     /** @brief Initialise the event loop and add the handler for incoming
77      *         IPMI packets.
78      *
79      *  @return EXIT_SUCCESS on success and EXIT_FAILURE on failure.
80      */
81     int startEventLoop();
82 
83     /** @brief Set up the socket (if systemd has not already) and
84      *         make sure that the bus name matches the specified channel
85      */
86     int setupSocket(std::shared_ptr<sdbusplus::asio::connection>& bus,
87                     std::string iface,
88                     uint16_t reqPort = ipmi::rmcpp::defaultPort);
89 
90     /** @brief set up boost::asio signal handling */
91     void setupSignal();
92 
93   private:
94     /** @brief async handler for incoming udp packets */
95     void handleRmcpPacket();
96 
97     /** @brief register the async handler for incoming udp packets */
98     void startRmcpReceive();
99 
100     /** @brief get vlanid  */
101     int getVLANID(const std::string channel);
102 
103     /** @brief boost::asio io context to run with
104      */
105     std::shared_ptr<boost::asio::io_context> io;
106 
107     /** @brief boost::asio udp socket
108      */
109     std::shared_ptr<boost::asio::ip::udp::socket> udpSocket = nullptr;
110 };
111 
112 } // namespace eventloop
113