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(sdbusplus::bus_t& bus,
90                                   const std::string& service,
91                                   const std::vector<std::string>& interfaces,
92                                   Callback callback);
93 
94     /**
95      * Callback function to handle InterfacesAdded D-Bus signals
96      *
97      * @param message Expanded sdbusplus message data
98      */
99     void interfacesAddedCallback(sdbusplus::message_t& message);
100 
101   private:
102     /**
103      * Finds any interface instances that already exist on D-Bus.
104      */
105     void findInterfaces();
106 
107     /**
108      * D-Bus bus object.
109      */
110     sdbusplus::bus_t& bus;
111 
112     /**
113      * D-Bus service that owns the object paths implementing the interfaces.
114      */
115     std::string service;
116 
117     /**
118      * D-Bus interfaces to find.
119      */
120     std::vector<std::string> interfaces;
121 
122     /**
123      * Callback function that is called each time an interface instance is
124      * found.
125      */
126     Callback callback;
127 
128     /**
129      * Match object for InterfacesAdded signals.
130      */
131     sdbusplus::bus::match_t match;
132 };
133 
134 } // namespace phosphor::power::util
135