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