Add support for ObjectManager and other standard D-Bus interfaces (#55)

Fixes #50
This commit is contained in:
Stanislav Angelovič
2019-05-29 22:28:15 +02:00
committed by GitHub
parent 4b0c23204d
commit 91fa35140b
36 changed files with 541 additions and 235 deletions
+24
View File
@@ -130,6 +130,30 @@ namespace sdbus {
getObject().unregister();
}
/*!
* @brief Adds an ObjectManager interface at the path of this D-Bus object
*
* Creates an ObjectManager interface at the specified object path on
* the connection. This is a convenient way to interrogate a connection
* to see what objects it has.
*
* @throws sdbus::Error in case of failure
*/
void addObjectManager()
{
getObject().addObjectManager();
}
/*!
* @brief Removes an ObjectManager interface from the path of this D-Bus object
*
* @throws sdbus::Error in case of failure
*/
void removeObjectManager()
{
getObject().removeObjectManager();
}
protected:
using base_type = AdaptorInterfaces;
};
@@ -220,6 +220,7 @@ namespace sdbus {
PropertySetter(IProxy& proxy, const std::string& propertyName);
PropertySetter& onInterface(const std::string& interfaceName);
template <typename _Value> void toValue(const _Value& value);
void toValue(const sdbus::Variant& value);
private:
IProxy& proxy_;
+6 -1
View File
@@ -596,13 +596,18 @@ namespace sdbus {
template <typename _Value>
inline void PropertySetter::toValue(const _Value& value)
{
PropertySetter::toValue(sdbus::Variant{value});
}
inline void PropertySetter::toValue(const sdbus::Variant& value)
{
SDBUS_THROW_ERROR_IF(interfaceName_.empty(), "DBus interface not specified when setting a property", EINVAL);
proxy_
.callMethod("Set")
.onInterface("org.freedesktop.DBus.Properties")
.withArguments(interfaceName_, propertyName_, sdbus::Variant{value});
.withArguments(interfaceName_, propertyName_, value);
}
}
+4 -6
View File
@@ -45,6 +45,8 @@ namespace sdbus {
class IConnection
{
public:
virtual ~IConnection() = default;
/*!
* @brief Requests D-Bus name on the connection
*
@@ -91,7 +93,7 @@ namespace sdbus {
virtual void leaveProcessingLoop() = 0;
/*!
* @brief Add an ObjectManager at the specified D-Bus object path
* @brief Adds an ObjectManager at the specified D-Bus object path
*
* Creates an ObjectManager interface at the specified object path on
* the connection. This is a convenient way to interrogate a connection
@@ -99,13 +101,9 @@ namespace sdbus {
*
* @throws sdbus::Error in case of failure
*/
virtual void addObjectManager( const std::string& objectPath ) = 0;
inline virtual ~IConnection() = 0;
virtual void addObjectManager(const std::string& objectPath) = 0;
};
IConnection::~IConnection() {}
/*!
* @brief Creates/opens D-Bus system connection
*
+26 -4
View File
@@ -57,6 +57,8 @@ namespace sdbus {
class IObject
{
public:
virtual ~IObject() = default;
/*!
* @brief Registers method that the object will provide on D-Bus
*
@@ -192,6 +194,30 @@ namespace sdbus {
*/
virtual sdbus::IConnection& getConnection() const = 0;
/*!
* @brief Adds an ObjectManager interface at the path of this D-Bus object
*
* Creates an ObjectManager interface at the specified object path on
* the connection. This is a convenient way to interrogate a connection
* to see what objects it has.
*
* @throws sdbus::Error in case of failure
*/
virtual void addObjectManager() = 0;
/*!
* @brief Removes an ObjectManager interface from the path of this D-Bus object
*
* @throws sdbus::Error in case of failure
*/
virtual void removeObjectManager() = 0;
/*!
* @brief Tests whether ObjectManager interface is added at the path of this D-Bus object
* @return True if ObjectManager interface is there, false otherwise
*/
virtual bool hasObjectManager() const = 0;
/*!
* @brief Registers method that the object will provide on D-Bus
*
@@ -287,8 +313,6 @@ namespace sdbus {
* @throws sdbus::Error in case of failure
*/
SignalEmitter emitSignal(const std::string& signalName);
virtual ~IObject() = 0;
};
inline MethodRegistrator IObject::registerMethod(const std::string& methodName)
@@ -316,8 +340,6 @@ namespace sdbus {
return SignalEmitter(*this, signalName);
}
inline IObject::~IObject() {}
/*!
* @brief Creates instance representing a D-Bus object
*
+2 -2
View File
@@ -58,6 +58,8 @@ namespace sdbus {
class IProxy
{
public:
virtual ~IProxy() = default;
/*!
* @brief Creates a method call message
*
@@ -259,8 +261,6 @@ namespace sdbus {
* @throws sdbus::Error in case of failure
*/
PropertySetter setProperty(const std::string& propertyName);
virtual ~IProxy() = default;
};
inline MethodInvoker IProxy::callMethod(const std::string& methodName)
-84
View File
@@ -1,84 +0,0 @@
/**
* (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
*
* @file Introspection.h
*
* Created on: Dec 13, 2016
* Project: sdbus-c++
* Description: High-level D-Bus IPC C++ library based on sd-bus
*
* This file is part of sdbus-c++.
*
* sdbus-c++ is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* sdbus-c++ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with sdbus-c++. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SDBUS_CXX_INTROSPECTION_H_
#define SDBUS_CXX_INTROSPECTION_H_
#include <sdbus-c++/IObject.h>
#include <sdbus-c++/IProxy.h>
#include <string>
namespace sdbus {
// Proxy for introspection
class introspectable_proxy
{
static constexpr const char* interfaceName = "org.freedesktop.DBus.Introspectable";
protected:
introspectable_proxy(sdbus::IProxy& object)
: object_(object)
{
}
public:
std::string Introspect()
{
std::string xml;
object_.callMethod("Introspect").onInterface(interfaceName).storeResultsTo(xml);
return xml;
}
private:
sdbus::IProxy& object_;
};
// Adaptor is not necessary if we want to rely on sdbus-provided introspection
// class introspectable_adaptor
// {
// static constexpr const char* interfaceName = "org.freedesktop.DBus.Introspectable";
//
// protected:
// introspectable_adaptor(sdbus::IObject& object)
// : object_(object)
// {
// object_.registerMethod("Introspect").onInterface(interfaceName).implementedAs([this](){ return object_.introspect(); });
// }
//
// public:
// std::string introspect()
// {
// std::string xml;
// object_.callMethod("Introspect").onInterface(interfaceName).storeResultsTo(xml);
// return xml;
// }
//
// private:
// sdbus::IObject& object_;
// };
}
#endif /* SDBUS_CXX_INTROSPECTION_H_ */
+185
View File
@@ -0,0 +1,185 @@
/**
* (C) 2017 KISTLER INSTRUMENTE AG, Winterthur, Switzerland
*
* @file StandardInterfaces.h
*
* Created on: Dec 13, 2016
* Project: sdbus-c++
* Description: High-level D-Bus IPC C++ library based on sd-bus
*
* This file is part of sdbus-c++.
*
* sdbus-c++ is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* sdbus-c++ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with sdbus-c++. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SDBUS_CXX_STANDARDINTERFACES_H_
#define SDBUS_CXX_STANDARDINTERFACES_H_
#include <sdbus-c++/IObject.h>
#include <sdbus-c++/IProxy.h>
#include <sdbus-c++/Types.h>
#include <string>
#include <map>
#include <vector>
namespace sdbus {
// Proxy for peer
class Peer_proxy
{
static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Peer";
protected:
Peer_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
}
public:
void Ping()
{
proxy_.callMethod("Ping").onInterface(INTERFACE_NAME);
}
std::string GetMachineId()
{
std::string machineUUID;
proxy_.callMethod("GetMachineId").onInterface(INTERFACE_NAME).storeResultsTo(machineUUID);
return machineUUID;
}
private:
sdbus::IProxy& proxy_;
};
// Proxy for introspection
class Introspectable_proxy
{
static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Introspectable";
protected:
Introspectable_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
}
public:
std::string Introspect()
{
std::string xml;
proxy_.callMethod("Introspect").onInterface(INTERFACE_NAME).storeResultsTo(xml);
return xml;
}
private:
sdbus::IProxy& proxy_;
};
// Proxy for properties
class Properties_proxy
{
static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.Properties";
protected:
Properties_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
proxy_
.uponSignal("PropertiesChanged")
.onInterface(INTERFACE_NAME)
.call([this]( const std::string& interfaceName
, const std::map<std::string, sdbus::Variant>& changedProperties
, const std::vector<std::string>& invalidatedProperties )
{
this->onPropertiesChanged(interfaceName, changedProperties, invalidatedProperties);
});
}
virtual void onPropertiesChanged( const std::string& interfaceName
, const std::map<std::string, sdbus::Variant>& changedProperties
, const std::vector<std::string>& invalidatedProperties ) = 0;
public:
sdbus::Variant Get(const std::string& interfaceName, const std::string& propertyName)
{
return proxy_.getProperty(propertyName).onInterface(interfaceName);
}
void Set(const std::string& interfaceName, const std::string& propertyName, const sdbus::Variant& value)
{
proxy_.setProperty(propertyName).onInterface(interfaceName).toValue(value);
}
std::map<std::string, sdbus::Variant> GetAll(const std::string& interfaceName)
{
std::map<std::string, sdbus::Variant> props;
proxy_.callMethod("GetAll").onInterface(INTERFACE_NAME).withArguments(interfaceName).storeResultsTo(props);
return props;
}
private:
sdbus::IProxy& proxy_;
};
// Proxy for object manager
class ObjectManager_proxy
{
static constexpr const char* INTERFACE_NAME = "org.freedesktop.DBus.ObjectManager";
protected:
ObjectManager_proxy(sdbus::IProxy& proxy)
: proxy_(proxy)
{
proxy_
.uponSignal("InterfacesAdded")
.onInterface(INTERFACE_NAME)
.call([this]( const sdbus::ObjectPath& objectPath
, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties )
{
this->onInterfacesAdded(objectPath, interfacesAndProperties);
});
proxy_
.uponSignal("InterfacesRemoved")
.onInterface(INTERFACE_NAME)
.call([this]( const sdbus::ObjectPath& objectPath
, const std::vector<std::string>& interfaces )
{
this->onInterfacesRemoved(objectPath, interfaces);
});
}
virtual void onInterfacesAdded( const sdbus::ObjectPath& objectPath
, const std::map<std::string, std::map<std::string, sdbus::Variant>>& interfacesAndProperties) = 0;
virtual void onInterfacesRemoved( const sdbus::ObjectPath& objectPath
, const std::vector<std::string>& interfaces) = 0;
public:
std::map<sdbus::ObjectPath, std::map<std::string, std::map<std::string, sdbus::Variant>>> GetManagedObjects()
{
std::map<sdbus::ObjectPath, std::map<std::string, std::map<std::string, sdbus::Variant>>> objectsInterfacesAndProperties;
proxy_.callMethod("GetManagedObjects").onInterface(INTERFACE_NAME).storeResultsTo(objectsInterfacesAndProperties);
return objectsInterfacesAndProperties;
}
private:
sdbus::IProxy& proxy_;
};
// Adaptors for the above-listed standard D-Bus interfaces are not necessary because the functionality
// is provided automatically for each D-Bus object by underlying libsystemd (with the exception of
// object manager which is provided but needs to be added explicitly, see IObject::addObjectManager).
}
#endif /* SDBUS_CXX_STANDARDINTERFACES_H_ */
+2 -1
View File
@@ -28,9 +28,10 @@
#include <sdbus-c++/IProxy.h>
#include <sdbus-c++/AdaptorInterfaces.h>
#include <sdbus-c++/ProxyInterfaces.h>
#include <sdbus-c++/StandardInterfaces.h>
#include <sdbus-c++/Message.h>
#include <sdbus-c++/MethodResult.h>
#include <sdbus-c++/Types.h>
#include <sdbus-c++/TypeTraits.h>
#include <sdbus-c++/Introspection.h>
#include <sdbus-c++/Error.h>
#include <sdbus-c++/Flags.h>