1 #pragma once
2 
3 #include "../manager.hpp"
4 #include "../utils/flight_recorder.hpp"
5 
6 #include <fmt/format.h>
7 
8 #include <sdbusplus/message.hpp>
9 
10 #include <algorithm>
11 #include <map>
12 #include <tuple>
13 #include <vector>
14 
15 namespace phosphor::fan::control::json::trigger::signal
16 {
17 
18 using namespace sdbusplus::message;
19 
20 struct Handlers
21 {
22 
23   public:
24     /**
25      * @brief Processes a properties changed signal and updates the property's
26      * value in the manager's object cache
27      *
28      * @param[in] msg - The sdbusplus signal message
29      * @param[in] obj - Object data associated with the signal
30      * @param[in] mgr - Manager that stores the object cache
31      */
32     static bool propertiesChanged(message& msg, const SignalObject& obj,
33                                   Manager& mgr)
34     {
35         std::string intf;
36         msg.read(intf);
37         if (intf != std::get<Intf>(obj))
38         {
39             // Interface name does not match object's interface
40             return false;
41         }
42 
43         std::map<std::string, PropertyVariantType> props;
44         msg.read(props);
45         auto itProp = props.find(std::get<Prop>(obj));
46         if (itProp == props.cend())
47         {
48             // Object's property not in dictionary of properties changed
49             return false;
50         }
51 
52         mgr.setProperty(std::get<Path>(obj), std::get<Intf>(obj),
53                         std::get<Prop>(obj), itProp->second);
54         return true;
55     }
56 
57     /**
58      * @brief Processes an interfaces added signal and adds the interface
59      * (including property & property value) to the manager's object cache
60      *
61      * @param[in] msg - The sdbusplus signal message
62      * @param[in] obj - Object data associated with the signal
63      * @param[in] mgr - Manager that stores the object cache
64      */
65     static bool interfacesAdded(message& msg, const SignalObject& obj,
66                                 Manager& mgr)
67     {
68         sdbusplus::message::object_path op;
69         msg.read(op);
70         if (static_cast<const std::string&>(op) != std::get<Path>(obj))
71         {
72             // Path name does not match object's path
73             return false;
74         }
75 
76         std::map<std::string, std::map<std::string, PropertyVariantType>>
77             intfProps;
78         msg.read(intfProps);
79         auto itIntf = intfProps.find(std::get<Intf>(obj));
80         if (itIntf == intfProps.cend())
81         {
82             // Object's interface not in dictionary of interfaces added
83             return false;
84         }
85 
86         auto itProp = itIntf->second.find(std::get<Prop>(obj));
87         if (itProp == itIntf->second.cend())
88         {
89             // Object's property not in dictionary of properties of interface
90             return false;
91         }
92 
93         mgr.setProperty(std::get<Path>(obj), std::get<Intf>(obj),
94                         std::get<Prop>(obj), itProp->second);
95         return true;
96     }
97 
98     /**
99      * @brief Processes an interfaces removed signal and removes the interface
100      * (including its properties) from the object cache on the manager
101      *
102      * @param[in] msg - The sdbusplus signal message
103      * @param[in] obj - Object data associated with the signal
104      * @param[in] mgr - Manager that stores the object cache
105      */
106     static bool interfacesRemoved(message& msg, const SignalObject& obj,
107                                   Manager& mgr)
108     {
109         sdbusplus::message::object_path op;
110         msg.read(op);
111         if (static_cast<const std::string&>(op) != std::get<Path>(obj))
112         {
113             // Path name does not match object's path
114             return false;
115         }
116 
117         std::vector<std::string> intfs;
118         msg.read(intfs);
119         auto itIntf =
120             std::find(intfs.begin(), intfs.end(), std::get<Intf>(obj));
121         if (itIntf == intfs.cend())
122         {
123             // Object's interface not in list of interfaces removed
124             return false;
125         }
126 
127         mgr.removeInterface(std::get<Path>(obj), std::get<Intf>(obj));
128         return true;
129     }
130 
131     /**
132      * @brief Processes a name owner changed signal and updates the service's
133      * owner state for all objects/interfaces associated in the cache
134      *
135      * @param[in] msg - The sdbusplus signal message
136      * @param[in] mgr - Manager that stores the service's owner state
137      */
138     static bool nameOwnerChanged(message& msg, const SignalObject&,
139                                  Manager& mgr)
140     {
141         bool hasOwner = false;
142 
143         std::string serv;
144         msg.read(serv);
145 
146         std::string oldOwner;
147         msg.read(oldOwner);
148 
149         std::string newOwner;
150         msg.read(newOwner);
151         if (!newOwner.empty())
152         {
153             hasOwner = true;
154         }
155         FlightRecorder::instance().log(
156             "nameOwnerChanged", fmt::format("Service: {}, Owned: {}", serv,
157                                             hasOwner ? "true" : "false"));
158         mgr.setOwner(serv, hasOwner);
159         return true;
160     }
161 
162     /**
163      * @brief Processes a dbus member signal, there is nothing associated or
164      * any cache to update when this signal is received
165      */
166     static bool member(message&, const SignalObject&, Manager&)
167     {
168         return true;
169     }
170 };
171 
172 } // namespace phosphor::fan::control::json::trigger::signal
173