xref: /openbmc/phosphor-power/dbus_interfaces_finder.hpp (revision f54021972b91be5058b50e9046bb0dd5a3b22a80)
1 /**
2  * Copyright © 2024 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "utility.hpp"
19 
20 #include <sdbusplus/bus.hpp>
21 #include <sdbusplus/bus/match.hpp>
22 
23 #include <functional>
24 #include <string>
25 #include <vector>
26 
27 namespace phosphor::power::util
28 {
29 
30 /**
31  * @class DBusInterfacesFinder
32  *
33  * Class that finds instances of one or more D-Bus interfaces.
34  *
35  * A D-Bus service name and one or more D-Bus interfaces are specified in the
36  * constructor.  The class finds instances of those interfaces that are owned by
37  * the service.
38  *
39  * The class finds the instances using two different methods:
40  * - Registers an InterfacesAdded listener for the specified service.  Class is
41  *   notified when a new interface instance is created on D-Bus.
42  * - Queries the ObjectMapper to find interface instances that already exist.
43  *
44  * Utilizing both methods allows this class to be used before, during, or after
45  * the service has created the interface instances.
46  *
47  * When an interface instance is found, the callback function specified in the
48  * constructor is called.  This function will be called multiple times if
49  * multiple instances are found.
50  */
51 class DBusInterfacesFinder
52 {
53   public:
54     // Specify which compiler-generated methods we want
55     DBusInterfacesFinder() = delete;
56     DBusInterfacesFinder(const DBusInterfacesFinder&) = delete;
57     DBusInterfacesFinder(DBusInterfacesFinder&&) = delete;
58     DBusInterfacesFinder& operator=(const DBusInterfacesFinder&) = delete;
59     DBusInterfacesFinder& operator=(DBusInterfacesFinder&&) = delete;
60     ~DBusInterfacesFinder() = default;
61 
62     /**
63      * Callback function that is called when an interface instance is found.
64      *
65      * @param path D-Bus object path that implements the interface
66      * @param interface D-Bus interface that was found
67      * @param properties Properties of the D-Bus interface
68      */
69     using Callback = std::function<void(const std::string& path,
70                                         const std::string& interface,
71                                         const DbusPropertyMap& properties)>;
72 
73     /**
74      * Constructor.
75      *
76      * Note: The callback function may be called immediately by this
77      * constructor.  For this reason, do not use this constructor in the
78      * initialization list of constructors in other classes.  Otherwise the
79      * callback may be called before the other class is fully initialized,
80      * leading to unpredictable behavior.
81      *
82      * @param bus D-Bus bus object
83      * @param service D-Bus service that owns the object paths implementing
84      *                the specified interfaces
85      * @param interfaces D-Bus interfaces to find
86      * @param callback Callback function that is called each time an interface
87      *                 instance is found
88      */
89     explicit DBusInterfacesFinder(
90         sdbusplus::bus_t& bus, const std::string& service,
91         const std::vector<std::string>& interfaces, Callback callback);
92 
93     /**
94      * Refind all instances of the interfaces specified in the constructor.
95      *
96      * The callback specified in the constructor will be called for each
97      * instance found.
98      *
99      * This method normally does not need to be called.  New instances are
100      * automatically detected using an InterfacesAdded listener.  However, this
101      * method may be useful if the caller is not currently receiving D-Bus
102      * signals (such as within a loop).
103      */
refind()104     void refind()
105     {
106         findInterfaces();
107     }
108 
109     /**
110      * Callback function to handle InterfacesAdded D-Bus signals
111      *
112      * @param message Expanded sdbusplus message data
113      */
114     void interfacesAddedCallback(sdbusplus::message_t& message);
115 
116   private:
117     /**
118      * Finds any interface instances that already exist on D-Bus.
119      */
120     void findInterfaces();
121 
122     /**
123      * D-Bus bus object.
124      */
125     sdbusplus::bus_t& bus;
126 
127     /**
128      * D-Bus service that owns the object paths implementing the interfaces.
129      */
130     std::string service;
131 
132     /**
133      * D-Bus interfaces to find.
134      */
135     std::vector<std::string> interfaces;
136 
137     /**
138      * Callback function that is called each time an interface instance is
139      * found.
140      */
141     Callback callback;
142 
143     /**
144      * Match object for InterfacesAdded signals.
145      */
146     sdbusplus::bus::match_t match;
147 };
148 
149 } // namespace phosphor::power::util
150