1 #pragma once
2 
3 #include <systemd/sd-bus.h>
4 
5 #include <sdbusplus/bus.hpp>
6 #include <sdbusplus/sdbus.hpp>
7 #include <sdbusplus/slot.hpp>
8 #include <sdbusplus/vtable.hpp>
9 
10 #include <string>
11 
12 namespace sdbusplus
13 {
14 
15 namespace server
16 {
17 
18 namespace interface
19 {
20 
21 /** @class interface
22  *  @brief Provide a C++ holder for dbus interface instances.
23  *
24  *  Wraps sd_bus_add_object_vtable so that the interface is registered
25  *  on construction and deregistered on destruction.
26  *
27  *  @note This class is 'final' because it is expected to be used by an
28  *  implementation of a class representing a dbus interface, which will be
29  *  composed through multiple-inheritence to create a single dbus 'object'.
30  *  Marking it 'final' prevents users from using an 'is-a' relationship via
31  *  inheritance, which might be a natural option.  Instead, a dbus interface
32  *  implementation should 'has-a' server::interface with a name sufficiently
33  *  unique to prevent name collisions in multiple-inheritence situations.
34  */
35 struct interface final : private sdbusplus::bus::details::bus_friend
36 {
37     /* Define all of the basic class operations:
38      *     Not allowed:
39      *         - Default constructor to avoid nullptrs.
40      *         - Copy operations due to internal unique_ptr.
41      *         - Move operations.
42      *     Allowed:
43      *         - Destructor.
44      */
45     interface() = delete;
46     interface(const interface&) = delete;
47     interface& operator=(const interface&) = delete;
48     interface(interface&&) = delete;
49     interface& operator=(interface&&) = delete;
50 
51     /** @brief Register the (path, interface, vtable) as a dbus object.
52      *
53      *  @param[in] bus - The bus to register on.
54      *  @param[in] path - The path to register as.
55      *  @param[in] interf - The interface to register as.
56      *  @param[in] vtable - The vtable to register.
57      *  @param[in] context - User-defined context, which is often 'this' from
58      *                       the interface implementation class.
59      */
60     interface(sdbusplus::bus_t& bus, const char* path, const char* interf,
61               const sdbusplus::vtable_t* vtable, void* context);
62 
63     ~interface();
64 
65     /** @brief Create a new signal message.
66      *
67      *  @param[in] member - The signal name to create.
68      */
new_signalsdbusplus::server::interface::interface69     auto new_signal(const char* member)
70     {
71         return _bus.new_signal(_path.c_str(), _interf.c_str(), member);
72     }
73 
74     /** @brief Broadcast a property changed signal.
75      *
76      *  @param[in] property - The property which changed.
77      */
78     void property_changed(const char* property);
79 
80     /** @brief Emit the interface is added on D-Bus */
emit_addedsdbusplus::server::interface::interface81     void emit_added()
82     {
83         if (!_interface_added)
84         {
85             _bus.emit_interfaces_added(_path.c_str(), {_interf});
86             _interface_added = true;
87         }
88     }
89 
90     /** @brief Emit the interface is removed on D-Bus */
emit_removedsdbusplus::server::interface::interface91     void emit_removed()
92     {
93         if (_interface_added)
94         {
95             _bus.emit_interfaces_removed(_path.c_str(), {_interf});
96             _interface_added = false;
97         }
98     }
99 
bussdbusplus::server::interface::interface100     bus_t& bus()
101     {
102         return _bus;
103     }
pathsdbusplus::server::interface::interface104     const std::string& path()
105     {
106         return _path;
107     }
108 
109   private:
110     bus_t _bus;
111     std::string _path;
112     std::string _interf;
113     bool _interface_added;
114     slot_t _slot;
115 };
116 
117 } // namespace interface
118 
119 using interface_t = interface::interface;
120 
121 } // namespace server
122 } // namespace sdbusplus
123