summaryrefslogtreecommitdiff
path: root/include/CommonAPI
diff options
context:
space:
mode:
Diffstat (limited to 'include/CommonAPI')
-rw-r--r--include/CommonAPI/DBus/DBusAddress.hpp53
-rw-r--r--include/CommonAPI/DBus/DBusAddressTranslator.hpp61
-rw-r--r--include/CommonAPI/DBus/DBusAttribute.hpp156
-rw-r--r--include/CommonAPI/DBus/DBusClientId.hpp48
-rw-r--r--include/CommonAPI/DBus/DBusConfig.hpp24
-rw-r--r--include/CommonAPI/DBus/DBusConnection.hpp246
-rw-r--r--include/CommonAPI/DBus/DBusDaemonProxy.hpp94
-rw-r--r--include/CommonAPI/DBus/DBusDeployment.hpp37
-rw-r--r--include/CommonAPI/DBus/DBusError.hpp45
-rw-r--r--include/CommonAPI/DBus/DBusEvent.hpp91
-rw-r--r--include/CommonAPI/DBus/DBusFactory.hpp114
-rw-r--r--include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp451
-rw-r--r--include/CommonAPI/DBus/DBusFreedesktopPropertiesStub.hpp59
-rw-r--r--include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp194
-rw-r--r--include/CommonAPI/DBus/DBusFreedesktopVariant.hpp74
-rw-r--r--include/CommonAPI/DBus/DBusFunctionalHash.hpp81
-rw-r--r--include/CommonAPI/DBus/DBusHelper.hpp55
-rw-r--r--include/CommonAPI/DBus/DBusInputStream.hpp426
-rw-r--r--include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp135
-rw-r--r--include/CommonAPI/DBus/DBusInterfaceHandler.hpp31
-rw-r--r--include/CommonAPI/DBus/DBusMainLoopContext.hpp87
-rw-r--r--include/CommonAPI/DBus/DBusMessage.hpp101
-rw-r--r--include/CommonAPI/DBus/DBusMultiEvent.hpp118
-rw-r--r--include/CommonAPI/DBus/DBusObjectManager.hpp69
-rw-r--r--include/CommonAPI/DBus/DBusObjectManagerStub.hpp125
-rw-r--r--include/CommonAPI/DBus/DBusOutputStream.hpp398
-rw-r--r--include/CommonAPI/DBus/DBusProxy.hpp84
-rw-r--r--include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp78
-rw-r--r--include/CommonAPI/DBus/DBusProxyBase.hpp72
-rw-r--r--include/CommonAPI/DBus/DBusProxyConnection.hpp127
-rw-r--r--include/CommonAPI/DBus/DBusProxyHelper.hpp258
-rw-r--r--include/CommonAPI/DBus/DBusProxyManager.hpp72
-rw-r--r--include/CommonAPI/DBus/DBusSelectiveEvent.hpp56
-rw-r--r--include/CommonAPI/DBus/DBusSerializableArguments.hpp30
-rw-r--r--include/CommonAPI/DBus/DBusServiceRegistry.hpp315
-rw-r--r--include/CommonAPI/DBus/DBusStubAdapter.hpp59
-rw-r--r--include/CommonAPI/DBus/DBusStubAdapterHelper.hpp674
-rw-r--r--include/CommonAPI/DBus/DBusTypeOutputStream.hpp153
-rw-r--r--include/CommonAPI/DBus/DBusTypes.hpp37
-rw-r--r--include/CommonAPI/DBus/DBusUtils.hpp37
40 files changed, 5425 insertions, 0 deletions
diff --git a/include/CommonAPI/DBus/DBusAddress.hpp b/include/CommonAPI/DBus/DBusAddress.hpp
new file mode 100644
index 0000000..926b11b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusAddress.hpp
@@ -0,0 +1,53 @@
+// Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_ADDRESS_HPP_
+#define COMMONAPI_DBUS_ADDRESS_HPP_
+
+#include <iostream>
+#include <map>
+
+#include <CommonAPI/Export.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusAddress {
+public:
+ COMMONAPI_EXPORT DBusAddress(const std::string &_service = "",
+ const std::string &_objectPath = "",
+ const std::string &_interface = "");
+ COMMONAPI_EXPORT DBusAddress(const DBusAddress &_source);
+ COMMONAPI_EXPORT virtual ~DBusAddress();
+
+ COMMONAPI_EXPORT bool operator==(const DBusAddress &_other) const;
+ COMMONAPI_EXPORT bool operator!=(const DBusAddress &_other) const;
+ COMMONAPI_EXPORT bool operator<(const DBusAddress &_other) const;
+
+ COMMONAPI_EXPORT const std::string &getInterface() const;
+ COMMONAPI_EXPORT void setInterface(const std::string &_interface);
+
+ COMMONAPI_EXPORT const std::string &getObjectPath() const;
+ COMMONAPI_EXPORT void setObjectPath(const std::string &_objectPath);
+
+ COMMONAPI_EXPORT const std::string &getService() const;
+ COMMONAPI_EXPORT void setService(const std::string &_service);
+
+private:
+ std::string service_;
+ std::string objectPath_;
+ std::string interface_;
+
+friend std::ostream &operator<<(std::ostream &_out, const DBusAddress &_dbusAddress);
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_ADDRESS_HPP_
diff --git a/include/CommonAPI/DBus/DBusAddressTranslator.hpp b/include/CommonAPI/DBus/DBusAddressTranslator.hpp
new file mode 100644
index 0000000..6d950e9
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusAddressTranslator.hpp
@@ -0,0 +1,61 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_ADDRESSTRANSLATOR_HPP_
+#define COMMONAPI_DBUS_ADDRESSTRANSLATOR_HPP_
+
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include <CommonAPI/Address.hpp>
+#include <CommonAPI/DBus/DBusAddress.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusAddressTranslator {
+public:
+ COMMONAPI_EXPORT static std::shared_ptr<DBusAddressTranslator> get();
+
+ COMMONAPI_EXPORT DBusAddressTranslator();
+
+ COMMONAPI_EXPORT void init();
+
+ COMMONAPI_EXPORT bool translate(const std::string &_key, DBusAddress &_value);
+ COMMONAPI_EXPORT bool translate(const CommonAPI::Address &_key, DBusAddress &_value);
+
+ COMMONAPI_EXPORT bool translate(const DBusAddress &_key, std::string &_value);
+ COMMONAPI_EXPORT bool translate(const DBusAddress &_key, CommonAPI::Address &_value);
+
+ COMMONAPI_EXPORT void insert(const std::string &_address,
+ const std::string &_service, const std::string &_path, const std::string &_interface);
+
+private:
+ COMMONAPI_EXPORT bool readConfiguration();
+
+ COMMONAPI_EXPORT bool isValid(const std::string &, const char,
+ bool = false, bool = false, bool = false) const;
+
+private:
+ bool isDefault_;
+
+ std::string defaultConfig_;
+ std::string defaultDomain_;
+
+ std::map<CommonAPI::Address, DBusAddress> forwards_;
+ std::map<DBusAddress, CommonAPI::Address> backwards_;
+
+ std::mutex mutex_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_ADDRESSTRANSLATOR_HPP_
diff --git a/include/CommonAPI/DBus/DBusAttribute.hpp b/include/CommonAPI/DBus/DBusAttribute.hpp
new file mode 100644
index 0000000..3d9170d
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusAttribute.hpp
@@ -0,0 +1,156 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_ATTRIBUTE_HPP_
+#define COMMONAPI_DBUS_DBUS_ATTRIBUTE_HPP_
+
+#include <cassert>
+#include <cstdint>
+#include <tuple>
+
+#include <CommonAPI/DBus/DBusConfig.hpp>
+#include <CommonAPI/DBus/DBusEvent.hpp>
+#include <CommonAPI/DBus/DBusProxyHelper.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename _AttributeType, typename _AttributeDepl = EmptyDeployment>
+class DBusReadonlyAttribute: public _AttributeType {
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef _AttributeDepl ValueTypeDepl;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusReadonlyAttribute(DBusProxy &_proxy,
+ const char *setMethodSignature, const char *getMethodName,
+ _AttributeDepl *_depl = nullptr)
+ : proxy_(_proxy),
+ getMethodName_(getMethodName),
+ setMethodSignature_(setMethodSignature),
+ depl_(_depl) {
+ assert(getMethodName);
+ }
+
+ void getValue(CommonAPI::CallStatus &_status, ValueType &_value, const CommonAPI::CallInfo *_info) const {
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedValue(depl_);
+ DBusProxyHelper<
+ DBusSerializableArguments<
+ >,
+ DBusSerializableArguments<
+ CommonAPI::Deployable<
+ ValueType,
+ _AttributeDepl
+ >
+ >
+ >::callMethodWithReply(proxy_, getMethodName_, "", (_info ? _info : &defaultCallInfo), _status, deployedValue);
+ _value = deployedValue.getValue();
+ }
+
+ std::future<CallStatus> getValueAsync(AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedValue(depl_);
+ return DBusProxyHelper<
+ DBusSerializableArguments<>,
+ DBusSerializableArguments<CommonAPI::Deployable<ValueType, _AttributeDepl>>
+ >::callMethodAsync(proxy_, getMethodName_, "", (_info ? _info : &defaultCallInfo),
+ [_callback](CommonAPI::CallStatus _status, CommonAPI::Deployable<ValueType, _AttributeDepl> _response) {
+ _callback(_status, _response.getValue());
+ },
+ std::make_tuple(deployedValue));
+ }
+
+ protected:
+ DBusProxy &proxy_;
+ const char *getMethodName_;
+ const char *setMethodSignature_;
+ _AttributeDepl *depl_;
+};
+
+template <typename _AttributeType, typename _AttributeDepl = EmptyDeployment>
+class DBusAttribute: public DBusReadonlyAttribute<_AttributeType, _AttributeDepl> {
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusAttribute(DBusProxy &_proxy,
+ const char *_setMethodName, const char *_setMethodSignature, const char *_getMethodName,
+ _AttributeDepl *_depl = nullptr)
+ : DBusReadonlyAttribute<_AttributeType, _AttributeDepl>(_proxy, _setMethodSignature, _getMethodName, _depl),
+ setMethodName_(_setMethodName),
+ setMethodSignature_(_setMethodSignature) {
+ assert(_setMethodName);
+ assert(_setMethodSignature);
+ }
+
+ void setValue(const ValueType &_request, CommonAPI::CallStatus &_status, ValueType &_response, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedRequest(_request, this->depl_);
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedResponse(this->depl_);
+ DBusProxyHelper<DBusSerializableArguments<CommonAPI::Deployable<ValueType, _AttributeDepl>>,
+ DBusSerializableArguments<CommonAPI::Deployable<ValueType, _AttributeDepl>> >::callMethodWithReply(
+ this->proxy_,
+ setMethodName_,
+ setMethodSignature_,
+ (_info ? _info : &defaultCallInfo),
+ deployedRequest,
+ _status,
+ deployedResponse);
+ _response = deployedResponse.getValue();
+ }
+
+
+ std::future<CallStatus> setValueAsync(const ValueType &_request, AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedRequest(_request, this->depl_);
+ CommonAPI::Deployable<ValueType, _AttributeDepl> deployedResponse(this->depl_);
+ return DBusProxyHelper<DBusSerializableArguments<CommonAPI::Deployable<ValueType, _AttributeDepl>>,
+ DBusSerializableArguments<CommonAPI::Deployable<ValueType, _AttributeDepl>> >::callMethodAsync(
+ this->proxy_,
+ setMethodName_,
+ setMethodSignature_,
+ (_info ? _info : &defaultCallInfo),
+ deployedRequest,
+ [_callback](CommonAPI::CallStatus _status, CommonAPI::Deployable<ValueType, _AttributeDepl> _response) {
+ _callback(_status, _response.getValue());
+ },
+ std::make_tuple(deployedResponse));
+ }
+
+ protected:
+ const char* setMethodName_;
+ const char* setMethodSignature_;
+};
+
+template <typename _AttributeType>
+class DBusObservableAttribute: public _AttributeType {
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::ValueTypeDepl ValueTypeDepl;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+ typedef typename _AttributeType::ChangedEvent ChangedEvent;
+
+ template <typename... _AttributeTypeArguments>
+ DBusObservableAttribute(DBusProxy &_proxy,
+ const char *_changedEventName,
+ _AttributeTypeArguments... arguments)
+ : _AttributeType(_proxy, arguments...),
+ changedEvent_(_proxy, _changedEventName, this->setMethodSignature_,
+ std::make_tuple(CommonAPI::Deployable<ValueType, ValueTypeDepl>(this->depl_))) {
+ }
+
+ ChangedEvent &getChangedEvent() {
+ return changedEvent_;
+ }
+
+ protected:
+ DBusEvent<ChangedEvent, CommonAPI::Deployable<ValueType, ValueTypeDepl> > changedEvent_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_ATTRIBUTE_HPP_
diff --git a/include/CommonAPI/DBus/DBusClientId.hpp b/include/CommonAPI/DBus/DBusClientId.hpp
new file mode 100644
index 0000000..72dc1c5
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusClientId.hpp
@@ -0,0 +1,48 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSCLIENTID_HPP_
+#define COMMONAPI_DBUS_DBUSCLIENTID_HPP_
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/Types.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusMessage;
+
+/**
+ * \brief Implementation of CommonAPI::ClientId for DBus
+ *
+ * This class represents the DBus specific implementation of CommonAPI::ClientId.
+ * It internally uses a string to identify clients. This string is the unique sender id used by dbus.
+ */
+class DBusClientId
+ : public CommonAPI::ClientId {
+ friend struct std::hash<DBusClientId>;
+
+public:
+ COMMONAPI_EXPORT DBusClientId(std::string dbusId);
+
+ COMMONAPI_EXPORT bool operator==(CommonAPI::ClientId& clientIdToCompare);
+ COMMONAPI_EXPORT bool operator==(DBusClientId& clientIdToCompare);
+ COMMONAPI_EXPORT size_t hashCode();
+
+ COMMONAPI_EXPORT const char * getDBusId();
+
+ COMMONAPI_EXPORT DBusMessage createMessage(const std::string objectPath, const std::string interfaceName, const std::string signalName) const;
+protected:
+ std::string dbusId_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // DBUSCLIENTID_HPP_
diff --git a/include/CommonAPI/DBus/DBusConfig.hpp b/include/CommonAPI/DBus/DBusConfig.hpp
new file mode 100644
index 0000000..dae6b7a
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusConfig.hpp
@@ -0,0 +1,24 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSCONFIG_HPP_
+#define COMMONAPI_DBUS_DBUSCONFIG_HPP_
+
+#include <CommonAPI/CallInfo.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+static const Timeout_t DEFAULT_SEND_TIMEOUT_MS = 5000;
+static CommonAPI::CallInfo defaultCallInfo(DEFAULT_SEND_TIMEOUT_MS);
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSCONFIG_HPP_
diff --git a/include/CommonAPI/DBus/DBusConnection.hpp b/include/CommonAPI/DBus/DBusConnection.hpp
new file mode 100644
index 0000000..436cfab
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusConnection.hpp
@@ -0,0 +1,246 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_CONNECTION_HPP_
+#define COMMONAPI_DBUS_DBUS_CONNECTION_HPP_
+
+#include <atomic>
+
+#include <dbus/dbus.h>
+
+#include <CommonAPI/DBus/DBusConfig.hpp>
+#include <CommonAPI/DBus/DBusDaemonProxy.hpp>
+#include <CommonAPI/DBus/DBusMainLoopContext.hpp>
+#include <CommonAPI/DBus/DBusObjectManager.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusServiceRegistry.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusObjectManager;
+
+class DBusConnectionStatusEvent
+ : public DBusProxyConnection::ConnectionStatusEvent {
+public:
+ DBusConnectionStatusEvent(DBusConnection* dbusConnection);
+ virtual ~DBusConnectionStatusEvent() {}
+
+ protected:
+ virtual void onListenerAdded(const Listener& listener);
+
+ // TODO: change to std::weak_ptr<DBusConnection> connection_;
+ DBusConnection* dbusConnection_;
+
+friend class DBusConnection;
+};
+
+struct WatchContext {
+ WatchContext(std::weak_ptr<MainLoopContext> mainLoopContext, DispatchSource* dispatchSource) :
+ mainLoopContext_(mainLoopContext), dispatchSource_(dispatchSource) {
+ }
+
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+ DispatchSource* dispatchSource_;
+};
+
+class DBusConnection
+ : public DBusProxyConnection,
+ public std::enable_shared_from_this<DBusConnection> {
+public:
+ COMMONAPI_EXPORT static std::shared_ptr<DBusConnection> getBus(const DBusType_t &_type);
+ COMMONAPI_EXPORT static std::shared_ptr<DBusConnection> wrap(::DBusConnection *_connection);
+
+ COMMONAPI_EXPORT DBusConnection(DBusType_t _type);
+ COMMONAPI_EXPORT DBusConnection(const DBusConnection&) = delete;
+ COMMONAPI_EXPORT DBusConnection(::DBusConnection* libDbusConnection);
+ COMMONAPI_EXPORT virtual ~DBusConnection();
+
+ COMMONAPI_EXPORT DBusConnection& operator=(const DBusConnection&) = delete;
+
+ COMMONAPI_EXPORT DBusType_t getBusType() const;
+
+ COMMONAPI_EXPORT bool connect(bool startDispatchThread = true);
+ COMMONAPI_EXPORT bool connect(DBusError& dbusError, bool startDispatchThread = true);
+ COMMONAPI_EXPORT void disconnect();
+
+ COMMONAPI_EXPORT virtual bool isConnected() const;
+
+ COMMONAPI_EXPORT virtual ConnectionStatusEvent& getConnectionStatusEvent();
+
+ COMMONAPI_EXPORT virtual bool requestServiceNameAndBlock(const std::string& serviceName) const;
+ COMMONAPI_EXPORT virtual bool releaseServiceName(const std::string& serviceName) const;
+
+ COMMONAPI_EXPORT bool sendDBusMessage(const DBusMessage& dbusMessage/*, uint32_t* allocatedSerial = NULL*/) const;
+
+ COMMONAPI_EXPORT std::future<CallStatus> sendDBusMessageWithReplyAsync(
+ const DBusMessage& dbusMessage,
+ std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler,
+ const CommonAPI::CallInfo *_info) const;
+
+ COMMONAPI_EXPORT DBusMessage sendDBusMessageWithReplyAndBlock(const DBusMessage& dbusMessage,
+ DBusError& dbusError,
+ const CommonAPI::CallInfo *_info) const;
+
+ COMMONAPI_EXPORT virtual bool addObjectManagerSignalMemberHandler(const std::string& dbusBusName,
+ DBusSignalHandler* dbusSignalHandler);
+ COMMONAPI_EXPORT virtual bool removeObjectManagerSignalMemberHandler(const std::string& dbusBusName,
+ DBusSignalHandler* dbusSignalHandler);
+
+ COMMONAPI_EXPORT DBusSignalHandlerToken addSignalMemberHandler(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& inuint32_tterfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler,
+ const bool justAddFilter = false);
+
+ COMMONAPI_EXPORT DBusProxyConnection::DBusSignalHandlerToken subscribeForSelectiveBroadcast(bool& subscriptionAccepted,
+ const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler,
+ DBusProxy* callingProxy);
+
+ COMMONAPI_EXPORT void unsubscribeFromSelectiveBroadcast(const std::string& eventName,
+ DBusProxyConnection::DBusSignalHandlerToken subscription,
+ DBusProxy* callingProxy,
+ const DBusSignalHandler* dbusSignalHandler);
+
+ COMMONAPI_EXPORT void registerObjectPath(const std::string& objectPath);
+ COMMONAPI_EXPORT void unregisterObjectPath(const std::string& objectPath);
+
+ COMMONAPI_EXPORT bool removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken,
+ const DBusSignalHandler* dbusSignalHandler = NULL);
+ COMMONAPI_EXPORT bool readWriteDispatch(int timeoutMilliseconds = -1);
+
+ COMMONAPI_EXPORT virtual const std::shared_ptr<DBusObjectManager> getDBusObjectManager();
+
+ COMMONAPI_EXPORT void setObjectPathMessageHandler(DBusObjectPathMessageHandler);
+ COMMONAPI_EXPORT bool isObjectPathMessageHandlerSet();
+
+ COMMONAPI_EXPORT virtual bool attachMainLoopContext(std::weak_ptr<MainLoopContext>);
+
+ COMMONAPI_EXPORT bool isDispatchReady();
+ COMMONAPI_EXPORT bool singleDispatch();
+
+ typedef std::tuple<std::string, std::string, std::string> DBusSignalMatchRuleTuple;
+ typedef std::pair<uint32_t, std::string> DBusSignalMatchRuleMapping;
+ typedef std::unordered_map<DBusSignalMatchRuleTuple, DBusSignalMatchRuleMapping> DBusSignalMatchRulesMap;
+ private:
+ COMMONAPI_EXPORT void dispatch();
+ COMMONAPI_EXPORT void suspendDispatching() const;
+ COMMONAPI_EXPORT void resumeDispatching() const;
+
+ std::thread* dispatchThread_;
+ bool stopDispatching_;
+
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+ DispatchSource* dispatchSource_;
+ WatchContext* watchContext_;
+
+ mutable std::recursive_mutex sendLock_;
+ mutable bool pauseDispatching_;
+ mutable std::mutex dispatchSuspendLock_;
+
+ COMMONAPI_EXPORT void addLibdbusSignalMatchRule(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const bool justAddFilter = false);
+
+ COMMONAPI_EXPORT void removeLibdbusSignalMatchRule(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName);
+
+ COMMONAPI_EXPORT void initLibdbusSignalFilterAfterConnect();
+ ::DBusHandlerResult onLibdbusSignalFilter(::DBusMessage* libdbusMessage);
+
+ COMMONAPI_EXPORT void initLibdbusObjectPathHandlerAfterConnect();
+ ::DBusHandlerResult onLibdbusObjectPathMessage(::DBusMessage* libdbusMessage);
+
+ COMMONAPI_EXPORT static void onLibdbusPendingCallNotifyThunk(::DBusPendingCall* libdbusPendingCall, void* userData);
+ COMMONAPI_EXPORT static void onLibdbusDataCleanup(void* userData);
+
+ COMMONAPI_EXPORT static ::DBusHandlerResult onLibdbusObjectPathMessageThunk(::DBusConnection* libdbusConnection,
+ ::DBusMessage* libdbusMessage,
+ void* userData);
+
+ COMMONAPI_EXPORT static ::DBusHandlerResult onLibdbusSignalFilterThunk(::DBusConnection* libdbusConnection,
+ ::DBusMessage* libdbusMessage,
+ void* userData);
+
+ COMMONAPI_EXPORT static dbus_bool_t onAddWatch(::DBusWatch* libdbusWatch, void* data);
+ COMMONAPI_EXPORT static void onRemoveWatch(::DBusWatch* libdbusWatch, void* data);
+ COMMONAPI_EXPORT static void onToggleWatch(::DBusWatch* libdbusWatch, void* data);
+
+ COMMONAPI_EXPORT static dbus_bool_t onAddTimeout(::DBusTimeout* dbus_timeout, void* data);
+ COMMONAPI_EXPORT static void onRemoveTimeout(::DBusTimeout* dbus_timeout, void* data);
+ COMMONAPI_EXPORT static void onToggleTimeout(::DBusTimeout* dbus_timeout, void* data);
+
+ COMMONAPI_EXPORT static void onWakeupMainContext(void* data);
+
+ COMMONAPI_EXPORT void enforceAsynchronousTimeouts() const;
+ COMMONAPI_EXPORT static const DBusObjectPathVTable* getDBusObjectPathVTable();
+
+ ::DBusConnection* connection_;
+ mutable std::mutex connectionGuard_;
+
+ std::mutex signalGuard_;
+ std::mutex objectManagerGuard_;
+ std::mutex serviceRegistryGuard_;
+
+ DBusType_t busType_;
+
+ std::shared_ptr<DBusObjectManager> dbusObjectManager_;
+
+ DBusConnectionStatusEvent dbusConnectionStatusEvent_;
+
+ DBusSignalMatchRulesMap dbusSignalMatchRulesMap_;
+
+ DBusSignalHandlerTable dbusSignalHandlerTable_;
+
+ std::unordered_map<std::string, size_t> dbusObjectManagerSignalMatchRulesMap_;
+ std::unordered_multimap<std::string, DBusSignalHandler*> dbusObjectManagerSignalHandlerTable_;
+ std::mutex dbusObjectManagerSignalGuard_;
+
+ COMMONAPI_EXPORT bool addObjectManagerSignalMatchRule(const std::string& dbusBusName);
+ COMMONAPI_EXPORT bool removeObjectManagerSignalMatchRule(const std::string& dbusBusName);
+
+ COMMONAPI_EXPORT bool addLibdbusSignalMatchRule(const std::string& dbusMatchRule);
+ COMMONAPI_EXPORT bool removeLibdbusSignalMatchRule(const std::string& dbusMatchRule);
+
+ std::atomic_size_t libdbusSignalMatchRulesCount_;
+
+ // objectPath, referenceCount
+ typedef std::unordered_map<std::string, uint32_t> LibdbusRegisteredObjectPathHandlersTable;
+ LibdbusRegisteredObjectPathHandlersTable libdbusRegisteredObjectPaths_;
+
+ DBusObjectPathMessageHandler dbusObjectMessageHandler_;
+
+ mutable std::unordered_map<std::string, uint16_t> connectionNameCount_;
+
+ typedef std::pair<DBusPendingCall*, std::tuple<int, DBusMessageReplyAsyncHandler*, DBusMessage> > TimeoutMapElement;
+ mutable std::map<DBusPendingCall*, std::tuple<int, DBusMessageReplyAsyncHandler*, DBusMessage>> timeoutMap_;
+
+ typedef std::pair<DBusMessageReplyAsyncHandler *, DBusMessage> MainloopTimeout_t;
+ mutable std::list<MainloopTimeout_t> mainloopTimeouts_;
+
+ mutable std::mutex enforceTimeoutMutex_;
+ mutable std::condition_variable enforceTimeoutCondition_;
+
+ mutable std::shared_ptr<std::thread> enforcerThread_;
+ mutable std::mutex enforcerThreadMutex_;
+ bool enforcerThreadCancelled_;
+};
+
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_CONNECTION_HPP_
diff --git a/include/CommonAPI/DBus/DBusDaemonProxy.hpp b/include/CommonAPI/DBus/DBusDaemonProxy.hpp
new file mode 100644
index 0000000..1333548
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusDaemonProxy.hpp
@@ -0,0 +1,94 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_DAEMON_PROXY_HPP_
+#define COMMONAPI_DBUS_DBUS_DAEMON_PROXY_HPP_
+
+#include <functional>
+#include <string>
+#include <vector>
+
+#include <CommonAPI/Address.hpp>
+
+#include <CommonAPI/DBus/DBusAttribute.hpp>
+#include <CommonAPI/DBus/DBusEvent.hpp>
+#include <CommonAPI/DBus/DBusProxyBase.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class StaticInterfaceVersionAttribute: public InterfaceVersionAttribute {
+ public:
+ StaticInterfaceVersionAttribute(const uint32_t& majorValue, const uint32_t& minorValue);
+
+ void getValue(CommonAPI::CallStatus& callStatus, Version &_version, const CommonAPI::CallInfo *_info) const;
+ std::future<CommonAPI::CallStatus> getValueAsync(AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info);
+
+ private:
+ Version version_;
+};
+
+
+class DBusDaemonProxy : public DBusProxyBase {
+ public:
+ typedef Event<std::string, std::string, std::string> NameOwnerChangedEvent;
+
+ typedef std::unordered_map<std::string, int> PropertyDictStub;
+ typedef std::unordered_map<std::string, PropertyDictStub> InterfaceToPropertyDict;
+ typedef std::unordered_map<std::string, InterfaceToPropertyDict> DBusObjectToInterfaceDict;
+
+ typedef std::function<void(const CommonAPI::CallStatus&, std::vector<std::string>)> ListNamesAsyncCallback;
+ typedef std::function<void(const CommonAPI::CallStatus&, bool)> NameHasOwnerAsyncCallback;
+ typedef std::function<void(const CommonAPI::CallStatus&, DBusObjectToInterfaceDict)> GetManagedObjectsAsyncCallback;
+ typedef std::function<void(const CommonAPI::CallStatus&, std::string)> GetNameOwnerAsyncCallback;
+
+ COMMONAPI_EXPORT DBusDaemonProxy(const std::shared_ptr<DBusProxyConnection>& dbusConnection);
+ COMMONAPI_EXPORT virtual ~DBusDaemonProxy() {}
+
+ COMMONAPI_EXPORT virtual bool isAvailable() const;
+ COMMONAPI_EXPORT virtual bool isAvailableBlocking() const;
+ COMMONAPI_EXPORT virtual ProxyStatusEvent& getProxyStatusEvent();
+
+ COMMONAPI_EXPORT virtual InterfaceVersionAttribute& getInterfaceVersionAttribute();
+
+ COMMONAPI_EXPORT void init();
+
+ COMMONAPI_EXPORT static const char* getInterfaceId();
+
+ COMMONAPI_EXPORT NameOwnerChangedEvent& getNameOwnerChangedEvent();
+
+ COMMONAPI_EXPORT void listNames(CommonAPI::CallStatus& callStatus, std::vector<std::string>& busNames) const;
+ COMMONAPI_EXPORT std::future<CallStatus> listNamesAsync(ListNamesAsyncCallback listNamesAsyncCallback) const;
+
+ COMMONAPI_EXPORT void nameHasOwner(const std::string& busName, CommonAPI::CallStatus& callStatus, bool& hasOwner) const;
+ COMMONAPI_EXPORT std::future<CallStatus> nameHasOwnerAsync(const std::string& busName,
+ NameHasOwnerAsyncCallback nameHasOwnerAsyncCallback) const;
+
+ COMMONAPI_EXPORT std::future<CallStatus> getManagedObjectsAsync(const std::string& forDBusServiceName,
+ GetManagedObjectsAsyncCallback) const;
+
+ /**
+ * Get the unique connection/bus name of the primary owner of the name given
+ *
+ * @param busName Name to get the owner of
+ * @param getNameOwnerAsyncCallback callback functor
+ *
+ * @return CallStatus::REMOTE_ERROR if the name is unknown, otherwise CallStatus::SUCCESS and the uniq name of the owner
+ */
+ std::future<CallStatus> getNameOwnerAsync(const std::string& busName, GetNameOwnerAsyncCallback getNameOwnerAsyncCallback) const;
+
+ private:
+ DBusEvent<NameOwnerChangedEvent, std::string, std::string, std::string> nameOwnerChangedEvent_;
+ StaticInterfaceVersionAttribute interfaceVersionAttribute_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_DAEMON_PROXY_HPP_
diff --git a/include/CommonAPI/DBus/DBusDeployment.hpp b/include/CommonAPI/DBus/DBusDeployment.hpp
new file mode 100644
index 0000000..21ad78a
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusDeployment.hpp
@@ -0,0 +1,37 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSDEPLOYMENTS_HPP_
+#define COMMONAPI_DBUS_DBUSDEPLOYMENTS_HPP_
+
+#include <string>
+#include <unordered_map>
+
+#include <CommonAPI/Deployment.hpp>
+#include <CommonAPI/Export.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template<typename... _Types>
+struct VariantDeployment : CommonAPI::Deployment<_Types...> {
+ VariantDeployment(bool _isFreeDesktop, _Types*... _t)
+ : CommonAPI::Deployment<_Types...>(_t...),
+ isFreeDesktop_(_isFreeDesktop) {
+ }
+
+ bool isFreeDesktop_;
+};
+
+extern COMMONAPI_IMPORT_EXPORT VariantDeployment<> freedesktopVariant;
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSDEPLOYMENTS_HPP_
diff --git a/include/CommonAPI/DBus/DBusError.hpp b/include/CommonAPI/DBus/DBusError.hpp
new file mode 100644
index 0000000..6e8f170
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusError.hpp
@@ -0,0 +1,45 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_ERROR_HPP_
+#define COMMONAPI_DBUS_DBUS_ERROR_HPP_
+
+#include <string>
+#include <dbus/dbus.h>
+
+#include <CommonAPI/Export.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusConnection;
+
+
+class COMMONAPI_EXPORT DBusError {
+ public:
+ DBusError();
+ ~DBusError();
+
+ operator bool() const;
+
+ void clear();
+
+ std::string getName() const;
+ std::string getMessage() const;
+
+ private:
+ ::DBusError libdbusError_;
+
+ friend class DBusConnection;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_ERROR_HPP_
diff --git a/include/CommonAPI/DBus/DBusEvent.hpp b/include/CommonAPI/DBus/DBusEvent.hpp
new file mode 100644
index 0000000..a3bfe01
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusEvent.hpp
@@ -0,0 +1,91 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_EVENT_HPP_
+#define COMMONAPI_DBUS_DBUS_EVENT_HPP_
+
+#include <CommonAPI/Event.hpp>
+#include <CommonAPI/DBus/DBusAddress.hpp>
+#include <CommonAPI/DBus/DBusHelper.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusProxyBase.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusSerializableArguments.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename _Event, typename... _Arguments>
+class DBusEvent: public _Event, public DBusProxyConnection::DBusSignalHandler {
+public:
+ typedef typename _Event::Listener Listener;
+
+ DBusEvent(DBusProxyBase &_proxy,
+ const std::string &_name, const std::string &_signature,
+ std::tuple<_Arguments...> _arguments)
+ : proxy_(_proxy),
+ name_(_name), signature_(_signature),
+ arguments_(_arguments) {
+
+ interface_ = proxy_.getDBusAddress().getInterface();
+ path_ = proxy_.getDBusAddress().getObjectPath();
+ }
+
+ DBusEvent(DBusProxyBase &_proxy,
+ const std::string &_name, const std::string &_signature,
+ const std::string &_path, const std::string &_interface,
+ std::tuple<_Arguments...> _arguments)
+ : proxy_(_proxy),
+ name_(_name), signature_(_signature),
+ path_(_path), interface_(_interface),
+ arguments_(_arguments) {
+ }
+
+ virtual ~DBusEvent() {
+ proxy_.removeSignalMemberHandler(subscription_, this);
+ }
+
+ virtual void onSignalDBusMessage(const DBusMessage &_message) {
+ handleSignalDBusMessage(_message, typename make_sequence<sizeof...(_Arguments)>::type());
+ }
+ protected:
+ virtual void onFirstListenerAdded(const Listener&) {
+ subscription_ = proxy_.addSignalMemberHandler(
+ path_, interface_, name_, signature_, this);
+ }
+
+ virtual void onLastListenerRemoved(const Listener&) {
+ proxy_.removeSignalMemberHandler(subscription_, this);
+ }
+
+ template<int ... _Indices>
+ inline void handleSignalDBusMessage(const DBusMessage &_message, index_sequence<_Indices...>) {
+ DBusInputStream input(_message);
+ if (DBusSerializableArguments<
+ _Arguments...
+ >::deserialize(input, std::get<_Indices>(arguments_)...)) {
+ this->notifyListeners(std::get<_Indices>(arguments_)...);
+ }
+ }
+
+ DBusProxyBase &proxy_;
+
+ std::string name_;
+ std::string signature_;
+ std::string path_;
+ std::string interface_;
+
+ DBusProxyConnection::DBusSignalHandlerToken subscription_;
+ std::tuple<_Arguments...> arguments_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_EVENT_HPP_
diff --git a/include/CommonAPI/DBus/DBusFactory.hpp b/include/CommonAPI/DBus/DBusFactory.hpp
new file mode 100644
index 0000000..fa0808b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFactory.hpp
@@ -0,0 +1,114 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_FACTORY_HPP_
+#define COMMONAPI_DBUS_FACTORY_HPP_
+
+#include <map>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/Factory.hpp>
+#include <CommonAPI/DBus/DBusTypes.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusAddress;
+class DBusProxy;
+class DBusProxyConnection;
+class DBusStubAdapter;
+
+typedef std::shared_ptr<DBusProxy>
+(*ProxyCreateFunction)(const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection);
+
+typedef std::shared_ptr<DBusStubAdapter>
+(*StubAdapterCreateFunction) (const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection,
+ const std::shared_ptr<StubBase> &_stub);
+
+class Factory : public CommonAPI::Factory {
+public:
+ COMMONAPI_EXPORT static std::shared_ptr<Factory> get();
+
+ COMMONAPI_EXPORT Factory();
+ COMMONAPI_EXPORT virtual ~Factory();
+
+ COMMONAPI_EXPORT void registerProxyCreateMethod(const std::string &_address,
+ ProxyCreateFunction _function);
+
+ COMMONAPI_EXPORT void registerStubAdapterCreateMethod(const std::string &_address,
+ StubAdapterCreateFunction _function);
+
+
+ COMMONAPI_EXPORT std::shared_ptr<Proxy> createProxy(const std::string &_domain,
+ const std::string &_interface,
+ const std::string &_instance,
+ const ConnectionId_t &_connectionId);
+
+ COMMONAPI_EXPORT std::shared_ptr<Proxy> createProxy(const std::string &_domain,
+ const std::string &_interface,
+ const std::string &_instance,
+ std::shared_ptr<MainLoopContext> _context);
+
+ COMMONAPI_EXPORT bool registerStub(const std::string &_domain,
+ const std::string &_interface,
+ const std::string &_instance,
+ std::shared_ptr<StubBase> _stub,
+ const ConnectionId_t &_connectionId);
+
+ COMMONAPI_EXPORT bool registerStub(const std::string &_domain,
+ const std::string &_interface,
+ const std::string &_instance,
+ std::shared_ptr<StubBase> _stub,
+ std::shared_ptr<MainLoopContext> _context);
+
+ COMMONAPI_EXPORT bool unregisterStub(const std::string &_domain,
+ const std::string &_interface,
+ const std::string &_instance);
+
+ // Services
+ COMMONAPI_EXPORT std::shared_ptr<DBusStubAdapter> getRegisteredService(const std::string &_address);
+
+ // Managed services
+ COMMONAPI_EXPORT std::shared_ptr<DBusStubAdapter> createDBusStubAdapter(const std::shared_ptr<StubBase> &_stub,
+ const std::string &_interface,
+ const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection);
+ COMMONAPI_EXPORT bool registerManagedService(const std::shared_ptr<DBusStubAdapter> &_adapter);
+ COMMONAPI_EXPORT bool unregisterManagedService(const std::string &_address);
+
+private:
+ COMMONAPI_EXPORT std::shared_ptr<DBusConnection> getConnection(const ConnectionId_t &);
+ COMMONAPI_EXPORT std::shared_ptr<DBusConnection> getConnection(std::shared_ptr<MainLoopContext>);
+ COMMONAPI_EXPORT bool registerStubAdapter(std::shared_ptr<DBusStubAdapter>);
+ COMMONAPI_EXPORT bool unregisterStubAdapter(std::shared_ptr<DBusStubAdapter>);
+
+ // Managed services
+ typedef std::unordered_map<std::string, std::shared_ptr<DBusStubAdapter>> ServicesMap;
+ COMMONAPI_EXPORT bool unregisterManagedService(const ServicesMap::iterator &);
+
+private:
+ static std::shared_ptr<Factory> theFactory;
+
+ std::map<ConnectionId_t, std::shared_ptr<DBusConnection>> connections_;
+ std::map<MainLoopContext *, std::shared_ptr<DBusConnection>> contextConnections_;
+
+ std::map<std::string, ProxyCreateFunction> proxyCreateFunctions_;
+ std::map<std::string, StubAdapterCreateFunction> stubAdapterCreateFunctions_;
+
+ ServicesMap services_;
+
+ DBusType_t defaultBusType_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_FACTORY_HPP_
diff --git a/include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp b/include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp
new file mode 100644
index 0000000..dc485cb
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp
@@ -0,0 +1,451 @@
+// Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_FREEDESKTOPATTRIBUTE_HPP_
+#define COMMONAPI_DBUS_DBUS_FREEDESKTOPATTRIBUTE_HPP_
+
+#include <CommonAPI/DBus/DBusDeployment.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename _AttributeType>
+class DBusFreedesktopReadonlyAttribute: public _AttributeType {
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusFreedesktopReadonlyAttribute(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : proxy_(_proxy),
+ interfaceName_(_interfaceName),
+ propertyName_(_propertyName) {
+ }
+
+ void getValue(CommonAPI::CallStatus &_status, ValueType &_value, const CommonAPI::CallInfo *_info) const {
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>> deployedValue(&freedesktopVariant);
+ DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string
+ >,
+ DBusSerializableArguments<
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>>
+ >
+ >::callMethodWithReply(
+ proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ "ss",
+ (_info ? _info : &defaultCallInfo),
+ interfaceName_,
+ propertyName_,
+ _status,
+ deployedValue);
+
+ _value = deployedValue.getValue().template get<ValueType>();
+ }
+
+ std::future<CallStatus> getValueAsync(AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>> deployedValue(&freedesktopVariant);
+ return DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string
+ >,
+ DBusSerializableArguments<
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>>
+ >
+ >::callMethodAsync(
+ proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ "ss",
+ (_info ? _info : &defaultCallInfo),
+ interfaceName_,
+ propertyName_,
+ [_callback](CommonAPI::CallStatus _status, CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>> _value) {
+ _callback(_status, _value.getValue().template get<ValueType>());
+ },
+ std::make_tuple(deployedValue)
+ );
+ }
+
+protected:
+ DBusProxy &proxy_;
+ std::string interfaceName_;
+ std::string propertyName_;
+};
+
+template <typename _AttributeType>
+class DBusFreedesktopUnionReadonlyAttribute: public _AttributeType {
+public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusFreedesktopUnionReadonlyAttribute(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : proxy_(_proxy),
+ interfaceName_(_interfaceName),
+ propertyName_(_propertyName) {
+ }
+
+ void getValue(CommonAPI::CallStatus &_status, ValueType &_value, const CommonAPI::CallInfo *_info) const {
+ CommonAPI::Deployable<ValueType, VariantDeployment<>> deployedValue(&freedesktopVariant);
+ DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string
+ >,
+ DBusSerializableArguments<
+ CommonAPI::Deployable<ValueType, VariantDeployment<>>
+ >
+ >::callMethodWithReply(
+ proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ "ss",
+ (_info ? _info : &defaultCallInfo),
+ interfaceName_,
+ propertyName_,
+ _status,
+ deployedValue);
+
+ _value = deployedValue.getValue().template get<ValueType>();
+ }
+
+ std::future<CommonAPI::CallStatus> getValueAsync(AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, VariantDeployment<>> deployedValue(&freedesktopVariant);
+ return DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string
+ >,
+ DBusSerializableArguments<
+ CommonAPI::Deployable<ValueType, VariantDeployment<>>
+ >
+ >::callMethodAsync(
+ proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ "ss",
+ (_info ? _info : &defaultCallInfo),
+ interfaceName_,
+ propertyName_,
+ [_callback](CommonAPI::CallStatus _status, CommonAPI::Deployable<ValueType, VariantDeployment<>> _value) {
+ _callback(_status, _value.getValue().template get<ValueType>());
+ },
+ std::make_tuple(deployedValue)
+ );
+ }
+
+protected:
+ DBusProxy &proxy_;
+ std::string interfaceName_;
+ std::string propertyName_;
+};
+
+template <typename _AttributeType>
+class DBusFreedesktopAttribute
+ : public DBusFreedesktopReadonlyAttribute<_AttributeType> {
+ public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+ typedef typename _AttributeType::ChangedEvent ChangedEvent;
+
+ DBusFreedesktopAttribute(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : DBusFreedesktopReadonlyAttribute<_AttributeType>(_proxy, _interfaceName, _propertyName) {
+ }
+
+ void setValue(const ValueType &_request, CommonAPI::CallStatus &_status, ValueType &_response, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>> deployedVariant(_request, &freedesktopVariant);
+ DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string, CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>>
+ >,
+ DBusSerializableArguments<
+ >
+ >::callMethodWithReply(
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ "ssv",
+ (_info ? _info : &defaultCallInfo),
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_,
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_,
+ deployedVariant,
+ _status);
+ _response = _request;
+ }
+
+ std::future<CommonAPI::CallStatus> setValueAsync(const ValueType &_request, AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>> deployedVariant(_request, &freedesktopVariant);
+ return DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string, CommonAPI::Deployable<Variant<ValueType>, VariantDeployment<>>
+ >,
+ DBusSerializableArguments<
+ >
+ >::callMethodAsync(
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ "ssv",
+ (_info ? _info : &defaultCallInfo),
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_,
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_,
+ deployedVariant,
+ [_callback, deployedVariant](CommonAPI::CallStatus _status) {
+ _callback(_status, deployedVariant.getValue().template get<ValueType>());
+ },
+ std::tuple<>());
+ }
+};
+
+template <typename _AttributeType>
+class DBusFreedesktopUnionAttribute
+ : public DBusFreedesktopReadonlyAttribute<_AttributeType> {
+ public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+
+ DBusFreedesktopUnionAttribute(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : DBusFreedesktopUnionReadonlyAttribute<_AttributeType>(_proxy, _interfaceName, _propertyName) {
+ }
+
+ void setValue(const ValueType &_request, CommonAPI::CallStatus &_status, ValueType &_response, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, VariantDeployment<>> deployedVariant(_request, &freedesktopVariant);
+ DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string, CommonAPI::Deployable<ValueType, VariantDeployment<>>
+ >,
+ DBusSerializableArguments<
+ >
+ >::callMethodWithReply(
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ "ssv",
+ (_info ? _info : &defaultCallInfo),
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_,
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_,
+ deployedVariant,
+ _status);
+ _response = _request;
+ }
+
+ std::future<CallStatus> setValueAsync(const ValueType &_request, AttributeAsyncCallback _callback, const CommonAPI::CallInfo *_info) {
+ CommonAPI::Deployable<ValueType, VariantDeployment<>> deployedVariant(_request, &freedesktopVariant);
+ return DBusProxyHelper<
+ DBusSerializableArguments<
+ std::string, std::string, CommonAPI::Deployable<ValueType, VariantDeployment<>>
+ >,
+ DBusSerializableArguments<
+ >
+ >::callMethodAsync(
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::proxy_,
+ "org.freedesktop.DBus.Properties",
+ "Set",
+ "ssv",
+ (_info ? _info : &defaultCallInfo),
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_,
+ DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_,
+ deployedVariant,
+ [_callback](CommonAPI::CallStatus _status, CommonAPI::Deployable<ValueType, VariantDeployment<>> _value) {
+ _callback(_status, _value.getValue().template get<ValueType>());
+ },
+ std::make_tuple(deployedVariant));
+ }
+};
+
+template<class, class>
+class LegacyEvent;
+
+template <template <class...> class _Type, class _Types, class _Variant>
+class LegacyEvent<_Type<_Types>, _Variant>: public _Type<_Types> {
+public:
+ typedef _Types ValueType;
+ typedef typename _Type<ValueType>::Listener Listener;
+ typedef std::unordered_map<std::string, _Variant> PropertyMap;
+ typedef MapDeployment<EmptyDeployment, VariantDeployment<>> PropertyMapDeployment;
+ typedef Deployable<PropertyMap, PropertyMapDeployment> DeployedPropertyMap;
+ typedef std::vector<std::string> InvalidArray;
+ typedef Event<std::string, DeployedPropertyMap, InvalidArray> SignalEvent;
+
+ LegacyEvent(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : interfaceName_(_interfaceName),
+ propertyName_(_propertyName),
+ isSubcriptionSet_(false),
+ internalEvent_(_proxy,
+ "PropertiesChanged",
+ "sa{sv}as",
+ _proxy.getDBusAddress().getObjectPath(),
+ "org.freedesktop.DBus.Properties",
+ std::make_tuple("", getDeployedMap(), InvalidArray())) {
+ }
+
+protected:
+ void onFirstListenerAdded(const Listener &) {
+ if (!isSubcriptionSet_) {
+ subscription_ = internalEvent_.subscribe(
+ [this](const std::string &_interfaceName,
+ const PropertyMap &_properties,
+ const InvalidArray &_invalid) {
+ if (interfaceName_ == _interfaceName) {
+ auto iter = _properties.find(propertyName_);
+ if (iter != _properties.end()) {
+ const ValueType &value = iter->second.template get<ValueType>();
+ this->notifyListeners(value);
+ }
+ }
+ });
+
+ isSubcriptionSet_ = true;
+ }
+ }
+
+ void onLastListenerRemoved(const Listener &) {
+ if (isSubcriptionSet_) {
+ internalEvent_.unsubscribe(subscription_);
+ isSubcriptionSet_ = false;
+ }
+ }
+
+ std::string interfaceName_;
+ std::string propertyName_;
+
+ typename DBusEvent<SignalEvent, std::string, DeployedPropertyMap, InvalidArray>::Subscription subscription_;
+ bool isSubcriptionSet_;
+
+ DBusEvent<SignalEvent, std::string, DeployedPropertyMap, InvalidArray> internalEvent_;
+
+private:
+ static DeployedPropertyMap &getDeployedMap() {
+ static PropertyMapDeployment itsDeployment(nullptr, &freedesktopVariant);
+ static DeployedPropertyMap itsDeployedMap(&itsDeployment);
+ return itsDeployedMap;
+ }
+};
+
+template <typename _AttributeType, typename _Variant>
+class DBusFreedesktopObservableAttribute: public _AttributeType {
+ public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+ typedef typename _AttributeType::ChangedEvent ChangedEvent;
+
+ template <typename... _AttributeTypeArguments>
+ DBusFreedesktopObservableAttribute(DBusProxy &_proxy,
+ const std::string &_interfaceName,
+ const std::string &_propertyName,
+ _AttributeTypeArguments... _arguments)
+ : _AttributeType(_proxy, _interfaceName, _propertyName, _arguments...),
+ interfaceName_(_interfaceName),
+ propertyName_(_propertyName),
+ externalChangedEvent_(_proxy, _interfaceName, _propertyName) {
+ }
+
+ ChangedEvent &getChangedEvent() {
+ return externalChangedEvent_;
+ }
+
+ protected:
+ std::string interfaceName_;
+ std::string propertyName_;
+ LegacyEvent<ChangedEvent, _Variant> externalChangedEvent_;
+};
+
+template<class, class>
+class LegacyUnionEvent;
+
+template <template <class...> class _Type, class _Types, class _Variant>
+class LegacyUnionEvent<_Type<_Types>, _Variant>: public _Type<_Types> {
+public:
+ typedef _Types ValueType;
+ typedef typename _Type<ValueType>::Listener Listener;
+ typedef std::unordered_map<std::string, _Variant> PropertyMap;
+ typedef MapDeployment<EmptyDeployment, VariantDeployment<>> PropertyMapDeployment;
+ typedef CommonAPI::Deployable<PropertyMap, PropertyMapDeployment> DeployedPropertyMap;
+ typedef std::vector<std::string> InvalidArray;
+ typedef Event<std::string, DeployedPropertyMap, InvalidArray> SignalEvent;
+
+ LegacyUnionEvent(DBusProxy &_proxy, const std::string &_interfaceName, const std::string &_propertyName)
+ : interfaceName_(_interfaceName),
+ propertyName_(_propertyName),
+ isSubcriptionSet_(false),
+ internalEvent_(_proxy,
+ "PropertiesChanged",
+ "sa{sv}as",
+ _proxy.getDBusAddress().getObjectPath(),
+ "org.freedesktop.DBus.Properties",
+ std::make_tuple("", getDeployedMap(), InvalidArray())) {
+ }
+
+protected:
+ void onFirstListenerAdded(const Listener &) {
+ if (isSubcriptionSet_) {
+ subscription_ = internalEvent_.subscribe(
+ [this](const std::string &_interfaceName,
+ const PropertyMap &_properties,
+ const std::vector<std::string> &_invalid) {
+ if (interfaceName_ == _interfaceName) {
+ auto iter = _properties.find(propertyName_);
+ if (iter != _properties.end()) {
+ this->notifyListeners(iter->second.template get<ValueType>());
+ }
+ }
+ });
+ isSubcriptionSet_ = true;
+ }
+ }
+
+ void onLastListenerRemoved(const Listener &) {
+ if (isSubcriptionSet_) {
+ internalEvent_.unsubscribe(subscription_);
+ isSubcriptionSet_ = false;
+ }
+ }
+
+ DBusEvent<SignalEvent, ValueType> internalEvent_;
+ std::string interfaceName_;
+ std::string propertyName_;
+
+ typename DBusEvent<SignalEvent>::Subscription subscription_;
+ bool isSubcriptionSet_;
+
+private:
+ static DeployedPropertyMap &getDeployedMap() {
+ static PropertyMapDeployment itsDeployment(nullptr, &freedesktopVariant);
+ static DeployedPropertyMap itsDeployedMap(&itsDeployment);
+ return itsDeployedMap;
+ }
+};
+
+template <typename _AttributeType, typename _Variant>
+class DBusFreedesktopUnionObservableAttribute: public _AttributeType {
+ public:
+ typedef typename _AttributeType::ValueType ValueType;
+ typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback;
+ typedef typename _AttributeType::ChangedEvent ChangedEvent;
+
+ template <typename... _AttributeTypeArguments>
+ DBusFreedesktopUnionObservableAttribute(DBusProxy &_proxy,
+ const std::string &_interfaceName,
+ const std::string &_propertyName,
+ _AttributeTypeArguments... _arguments)
+ : _AttributeType(_proxy, _interfaceName, _propertyName, _arguments...),
+ externalChangedEvent_(_proxy, _interfaceName, _propertyName) {
+ }
+
+ ChangedEvent &getChangedEvent() {
+ return externalChangedEvent_;
+ }
+
+ protected:
+ LegacyUnionEvent<ChangedEvent, _Variant> externalChangedEvent_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_FREEDESKTOPATTRIBUTE_HPP_
diff --git a/include/CommonAPI/DBus/DBusFreedesktopPropertiesStub.hpp b/include/CommonAPI/DBus/DBusFreedesktopPropertiesStub.hpp
new file mode 100644
index 0000000..f7e2cdf
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFreedesktopPropertiesStub.hpp
@@ -0,0 +1,59 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_FREEDESKTOPPROPERTIESSTUB_HPP_
+#define COMMONAPI_DBUS_DBUS_FREEDESKTOPPROPERTIESSTUB_HPP_
+
+#include <memory>
+#include <mutex>
+#include <string>
+
+#include <CommonAPI/DBus/DBusInterfaceHandler.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusStubAdapter;
+
+/**
+ * Stub for standard <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties">org.freedesktop.dbus.Properties</a> interface.
+ *
+ * DBusFreedesktopPropertiesStub gets the DBusStubAdapter for handling the actual properties with instantiation.
+ */
+class DBusFreedesktopPropertiesStub: public DBusInterfaceHandler {
+public:
+ DBusFreedesktopPropertiesStub(const std::string &_path,
+ const std::string &_interface,
+ const std::shared_ptr<DBusProxyConnection> &_connection,
+ const std::shared_ptr<DBusStubAdapter> &_adapter);
+
+ virtual ~DBusFreedesktopPropertiesStub();
+
+ const std::string &getObjectPath() const;
+ static const std::string &getInterface();
+
+ virtual const char* getMethodsDBusIntrospectionXmlData() const;
+ virtual bool onInterfaceDBusMessage(const DBusMessage &_message);
+ virtual const bool hasFreedesktopProperties();
+
+private:
+ std::string path_;
+ std::weak_ptr<DBusProxyConnection> connection_;
+ std::shared_ptr<DBusStubAdapter> adapter_;
+
+ typedef std::unordered_map<std::string, std::shared_ptr<DBusStubAdapter>> DBusInterfacesMap;
+ DBusInterfacesMap managedInterfaces_;
+
+ std::mutex dbusInterfacesLock_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_FREEDESKTOPPROPERTIESSTUB_HPP_
diff --git a/include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp b/include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp
new file mode 100644
index 0000000..5c0bffa
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp
@@ -0,0 +1,194 @@
+// Copyright (C) 2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSFREEDESKTOPSTUBADAPTERHELPER_HPP_
+#define COMMONAPI_DBUS_DBUSFREEDESKTOPSTUBADAPTERHELPER_HPP_
+
+#include <CommonAPI/Struct.hpp>
+#include <CommonAPI/DBus/DBusStubAdapterHelper.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename _StubClass>
+class DBusGetFreedesktopAttributeStubDispatcherBase {
+public:
+ virtual ~DBusGetFreedesktopAttributeStubDispatcherBase() {}
+ virtual void dispatchDBusMessageAndAppendReply(const DBusMessage &_message,
+ const std::shared_ptr<_StubClass> &_stub,
+ DBusOutputStream &_output,
+ const std::shared_ptr<DBusClientId> &_clientId) = 0;
+};
+
+template <typename _StubClass, typename _AttributeType>
+class DBusGetFreedesktopAttributeStubDispatcher
+ : public virtual DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>,
+ public virtual DBusGetFreedesktopAttributeStubDispatcherBase<_StubClass> {
+public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
+
+ DBusGetFreedesktopAttributeStubDispatcher(GetStubFunctor _getStubFunctor)
+ : DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, "v") {
+ }
+
+ virtual ~DBusGetFreedesktopAttributeStubDispatcher() {};
+
+ void dispatchDBusMessageAndAppendReply(const DBusMessage &_message,
+ const std::shared_ptr<_StubClass> &_stub,
+ DBusOutputStream &_output,
+ const std::shared_ptr<DBusClientId> &_clientId) {
+ CommonAPI::Deployable<CommonAPI::Variant<_AttributeType>, VariantDeployment<>> deployedVariant(
+ (_stub.get()->*(DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::getStubFunctor_))(_clientId), &freedesktopVariant);
+
+ _output << deployedVariant;
+ }
+
+protected:
+ virtual bool sendAttributeValueReply(const DBusMessage &_message, const std::shared_ptr<_StubClass> &_stub, DBusStubAdapterHelperType &_helper) {
+ DBusMessage reply = _message.createMethodReturn(DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::signature_);
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(_message.getSender()));
+ CommonAPI::Deployable<CommonAPI::Variant<_AttributeType>, VariantDeployment<>> deployedVariant(
+ (_stub.get()->*(DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::getStubFunctor_))(clientId), &freedesktopVariant);
+
+ DBusOutputStream output(reply);
+ output << deployedVariant;
+ output.flush();
+
+ return _helper.getDBusConnection()->sendDBusMessage(reply);
+ }
+};
+
+template <typename _StubClass, typename _AttributeType>
+class DBusSetFreedesktopAttributeStubDispatcher
+ : public virtual DBusGetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>,
+ public virtual DBusSetAttributeStubDispatcher<_StubClass, _AttributeType> {
+public:
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
+ typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType;
+ typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(std::shared_ptr<CommonAPI::ClientId>, _AttributeType);
+ typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)();
+
+ DBusSetFreedesktopAttributeStubDispatcher(
+ GetStubFunctor _getStubFunctor,
+ OnRemoteSetFunctor _onRemoteSetFunctor,
+ OnRemoteChangedFunctor _onRemoteChangedFunctor)
+ : DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, "v"),
+ DBusGetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor),
+ DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor, "v") {
+ }
+
+ virtual ~DBusSetFreedesktopAttributeStubDispatcher() {};
+
+protected:
+ virtual _AttributeType retreiveAttributeValue(const DBusMessage &_message, bool &_error) {
+ std::string interfaceName, attributeName;
+ DBusInputStream input(_message);
+ CommonAPI::Deployable<CommonAPI::Variant<_AttributeType>, VariantDeployment<>> deployedVariant(&freedesktopVariant);
+ input >> interfaceName; // skip over interface and attribute name
+ input >> attributeName;
+ input >> deployedVariant;
+ _error = input.hasError();
+ _AttributeType attributeValue = deployedVariant.getValue().template get<_AttributeType>() ;
+ return attributeValue;
+ }
+};
+
+template <typename _StubClass, typename _AttributeType>
+class DBusSetFreedesktopObservableAttributeStubDispatcher
+ : public virtual DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>,
+ public virtual DBusSetObservableAttributeStubDispatcher<_StubClass, _AttributeType> {
+public:
+ typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
+ typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType;
+ typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
+ typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteSetFunctor OnRemoteSetFunctor;
+ typedef typename DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteChangedFunctor OnRemoteChangedFunctor;
+ typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&);
+
+ DBusSetFreedesktopObservableAttributeStubDispatcher(
+ GetStubFunctor _getStubFunctor,
+ OnRemoteSetFunctor _onRemoteSetFunctor,
+ OnRemoteChangedFunctor _onRemoteChangedFunctor,
+ FireChangedFunctor _fireChangedFunctor)
+ : DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, "v"),
+ DBusGetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor),
+ DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor, "v"),
+ DBusSetFreedesktopAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor),
+ DBusSetObservableAttributeStubDispatcher<_StubClass, _AttributeType>(_getStubFunctor, _onRemoteSetFunctor, _onRemoteChangedFunctor, _fireChangedFunctor, "v") {
+ }
+};
+
+template<class>
+struct DBusStubFreedesktopPropertiesSignalHelper;
+
+template<template<class ...> class _In, class _InArg>
+struct DBusStubFreedesktopPropertiesSignalHelper<_In<DBusInputStream, DBusOutputStream, _InArg>> {
+
+ template <typename _ValueType>
+ struct DBusPropertiesEntry
+ : public CommonAPI::Struct<std::string, CommonAPI::Variant<_ValueType>> {
+
+ DBusPropertiesEntry() = default;
+ DBusPropertiesEntry(const std::string &_propertyName,
+ const _ValueType &_propertyValue) {
+ std::get<0>(this->values_) = _propertyName;
+ std::get<1>(this->values_) = _propertyValue;
+ };
+
+ const std::string &getPropertyName() const { return std::get<0>(this->values_); }
+ void setPropertyName(const std::string &_value) { std::get<0>(this->values_) = _value; }
+
+ const _ValueType getPropertyValue() const { return std::get<1>(this->values_); }
+ void setPropertyValue(const _ValueType &_value) { std::get<1>(this->values_) = _value; }
+ };
+
+ typedef std::vector<DBusPropertiesEntry<_InArg>> PropertiesArray;
+ typedef CommonAPI::Deployment<CommonAPI::EmptyDeployment, VariantDeployment<>> PropertyDeployment;
+ typedef CommonAPI::ArrayDeployment<PropertyDeployment> PropertiesDeployment;
+ typedef CommonAPI::Deployable<PropertiesArray, PropertiesDeployment> DeployedPropertiesArray;
+
+ template <typename _StubClass>
+ static bool sendPropertiesChangedSignal(const _StubClass &_stub, const std::string &_propertyName, const _InArg &_inArg) {
+ const std::vector<std::string> invalidatedProperties;
+ PropertiesArray changedProperties;
+ DBusPropertiesEntry<_InArg> entry(_propertyName, _inArg);
+ changedProperties.push_back(entry);
+
+ PropertyDeployment propertyDeployment(nullptr, &freedesktopVariant);
+ PropertiesDeployment changedPropertiesDeployment(&propertyDeployment);
+
+ DeployedPropertiesArray deployedChangedProperties(changedProperties, &changedPropertiesDeployment);
+
+ return DBusStubSignalHelper<
+ _In<
+ DBusInputStream,
+ DBusOutputStream,
+ const std::string,
+ DeployedPropertiesArray,
+ std::vector<std::string>
+ >
+ >::sendSignal(
+ _stub.getDBusAddress().getObjectPath().c_str(),
+ "org.freedesktop.DBus.Properties",
+ "PropertiesChanged",
+ "sa{sv}as",
+ _stub.getDBusConnection(),
+ _stub.getInterface(),
+ deployedChangedProperties,
+ invalidatedProperties);
+ }
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSFREEDESKTOPSTUBADAPTERHELPER_HPP_
diff --git a/include/CommonAPI/DBus/DBusFreedesktopVariant.hpp b/include/CommonAPI/DBus/DBusFreedesktopVariant.hpp
new file mode 100644
index 0000000..31490d2
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFreedesktopVariant.hpp
@@ -0,0 +1,74 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.h> can be included directly, this file may disappear or change contents."
+#endif
+
+#include <CommonAPI/DBus/DBusTypeOutputStream.hpp>
+
+#ifndef COMMONAPI_DBUS_FREEDESKTOPVARIANT_HPP_
+#define COMMONAPI_DBUS_FREEDESKTOPVARIANT_HPP_
+
+namespace CommonAPI {
+namespace DBus {
+
+template<class Visitor, class Variant, typename ... _Types>
+struct ApplyTypeCompareVisitor;
+
+template<class Visitor, class Variant>
+struct ApplyTypeCompareVisitor<Visitor, Variant> {
+ static const uint8_t index = 0;
+
+ static uint8_t visit(Visitor&, const Variant&) {
+ // won't be called if the variant contains the requested type
+ assert(false);
+ return 0;
+ }
+};
+
+template<class Visitor, class Variant, typename _Type, typename ... _Types>
+struct ApplyTypeCompareVisitor<Visitor, Variant, _Type, _Types...> {
+ static const uint8_t index
+ = ApplyTypeCompareVisitor<Visitor, Variant, _Types...>::index + 1;
+
+ static uint8_t visit(Visitor &_visitor, const Variant &_variant) {
+ DBusTypeOutputStream output;
+ _Type current;
+ output.writeType(current);
+#ifdef WIN32
+ if (_visitor.operator()<_Type>(output.getSignature())) {
+#else
+ if (_visitor.template operator()<_Type>(output.getSignature())) {
+#endif
+ return index;
+ } else {
+ return ApplyTypeCompareVisitor<
+ Visitor, Variant, _Types...
+ >::visit(_visitor, _variant);
+ }
+ }
+};
+
+template<typename ... _Types>
+struct TypeCompareVisitor {
+public:
+ TypeCompareVisitor(const std::string &_type)
+ : type_(_type) {
+ }
+
+ template<typename _Type>
+ bool operator()(const std::string &_type) const {
+ return (_type == type_);
+ }
+
+private:
+ const std::string type_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_FREEDESKTOPVARIANT_HPP_
diff --git a/include/CommonAPI/DBus/DBusFunctionalHash.hpp b/include/CommonAPI/DBus/DBusFunctionalHash.hpp
new file mode 100644
index 0000000..78848c7
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusFunctionalHash.hpp
@@ -0,0 +1,81 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_HPP_
+#define COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_HPP_
+
+#include <functional>
+#include <string>
+#include <tuple>
+
+#include <CommonAPI/Export.hpp>
+
+namespace std {
+
+template<>
+struct COMMONAPI_EXPORT hash<pair<const char*, const char*> >
+ : public unary_function<pair<const char*, const char*>, size_t> {
+
+ size_t operator()(const pair<const char*, const char*>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<const char*>
+ : public unary_function<const char*, size_t> {
+
+ size_t operator()(const char* const t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<pair<string, string> >
+ : public unary_function<pair<string, string>, size_t> {
+
+ size_t operator()(const pair<string, string>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<tuple<string, string, string> >
+ : public unary_function<tuple<string, string, string>, size_t> {
+
+ size_t operator()(const tuple<string, string, string>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<tuple<string, string, string, bool> >
+ : public unary_function<tuple<string, string, string, bool>, size_t> {
+
+ size_t operator()(const tuple<string, string, string, bool>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<tuple<string, string, string, int> >
+ : public unary_function<tuple<string, string, string, int>, size_t> {
+
+ size_t operator()(const tuple<string, string, string, int>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT hash<tuple<string, string, string, string> >
+ : public std::unary_function<tuple<string, string, string, string>, size_t> {
+
+ size_t operator()(const tuple<string, string, string, string>& t) const;
+};
+
+template<>
+struct COMMONAPI_EXPORT equal_to<pair<const char*, const char*> >
+ : public binary_function<pair<const char*, const char*>,
+ pair<const char*, const char*>,
+ bool> {
+
+ bool operator()(const pair<const char*, const char*>& a, const pair<const char*, const char*>& b) const;
+};
+
+} // namespace std
+
+#endif // COMMONAPI_DBUS_DBUS_FUNCTIONAL_HASH_HPP_
diff --git a/include/CommonAPI/DBus/DBusHelper.hpp b/include/CommonAPI/DBus/DBusHelper.hpp
new file mode 100644
index 0000000..53a5625
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusHelper.hpp
@@ -0,0 +1,55 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_HELPER_HPP_
+#define COMMONAPI_DBUS_DBUS_HELPER_HPP_
+
+#include <unordered_map>
+#include <vector>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <int ...>
+struct index_sequence {};
+
+
+template <int N, int ...S>
+struct make_sequence : make_sequence<N-1, N-1, S...> {};
+
+template <int ...S>
+struct make_sequence<0, S...> {
+ typedef index_sequence<S...> type;
+};
+
+
+template <int N, int _Offset, int ...S>
+struct make_sequence_range : make_sequence_range<N-1, _Offset, N-1+_Offset, S...> {};
+
+template <int _Offset, int ...S>
+struct make_sequence_range<0, _Offset, S...> {
+ typedef index_sequence<S...> type;
+};
+
+template<typename _Type>
+struct is_std_vector { static const bool value = false; };
+
+template<typename _Type>
+struct is_std_vector<std::vector<_Type> > { static const bool value = true; };
+
+template<typename _Type>
+struct is_std_unordered_map { static const bool value = false; };
+
+template<typename _Key, typename _Value, typename _Hash>
+struct is_std_unordered_map<std::unordered_map<_Key, _Value, _Hash>> { static const bool value = true; };
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_HELPER_HPP_
diff --git a/include/CommonAPI/DBus/DBusInputStream.hpp b/include/CommonAPI/DBus/DBusInputStream.hpp
new file mode 100644
index 0000000..389cb68
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusInputStream.hpp
@@ -0,0 +1,426 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSINPUTSTREAM_HPP_
+#define COMMONAPI_DBUS_DBUSINPUTSTREAM_HPP_
+
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+
+#include <cassert>
+#include <cstdint>
+#include <stack>
+#include <string>
+#include <vector>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/InputStream.hpp>
+#include <CommonAPI/Struct.hpp>
+#include <CommonAPI/DBus/DBusDeployment.hpp>
+#include <CommonAPI/DBus/DBusError.hpp>
+#include <CommonAPI/DBus/DBusFreedesktopVariant.hpp>
+#include <CommonAPI/DBus/DBusHelper.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+// Used to mark the position of a pointer within an array of bytes.
+typedef uint32_t position_t;
+
+/**
+ * @class DBusInputMessageStream
+ *
+ * Used to deserialize and read data from a #DBusMessage. For all data types that can be read from a #DBusMessage, a ">>"-operator should be defined to handle the reading
+ * (this operator is predefined for all basic data types and for vectors).
+ */
+class DBusInputStream
+ : public InputStream<DBusInputStream> {
+public:
+ COMMONAPI_EXPORT bool hasError() const {
+ return isErrorSet();
+ }
+
+ COMMONAPI_EXPORT InputStream &readValue(bool &_value, const EmptyDeployment *_depl);
+
+ COMMONAPI_EXPORT InputStream &readValue(int8_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(int16_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(int32_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(int64_t &_value, const EmptyDeployment *_depl);
+
+ COMMONAPI_EXPORT InputStream &readValue(uint8_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(uint16_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(uint32_t &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(uint64_t &_value, const EmptyDeployment *_depl);
+
+ COMMONAPI_EXPORT InputStream &readValue(float &_value, const EmptyDeployment *_depl);
+ COMMONAPI_EXPORT InputStream &readValue(double &_value, const EmptyDeployment *_depl);
+
+ COMMONAPI_EXPORT InputStream &readValue(std::string &_value, const EmptyDeployment *_depl);
+
+ COMMONAPI_EXPORT InputStream &readValue(Version &_value, const EmptyDeployment *_depl);
+
+ template<class _Deployment, typename _Base>
+ COMMONAPI_EXPORT InputStream &readValue(Enumeration<_Base> &_value, const _Deployment *_depl) {
+ _Base tmpValue;
+ readValue(tmpValue, _depl);
+ _value = tmpValue;
+ return (*this);
+ }
+
+ template<class _Deployment, typename... _Types>
+ COMMONAPI_EXPORT InputStream &readValue(Struct<_Types...> &_value, const _Deployment *_depl) {
+ align(8);
+ const auto itsSize(std::tuple_size<std::tuple<_Types...>>::value);
+ StructReader<itsSize-1, DBusInputStream, Struct<_Types...>, _Deployment>{}(
+ (*this), _value, _depl);
+ return (*this);
+ }
+
+ template<class _Deployment, class _PolymorphicStruct>
+ COMMONAPI_EXPORT InputStream &readValue(std::shared_ptr<_PolymorphicStruct> &_value,
+ const _Deployment *_depl) {
+ uint32_t serial;
+ align(8);
+ _readValue(serial);
+ skipSignature();
+ align(8);
+ if (!hasError()) {
+ _value = _PolymorphicStruct::create(serial);
+ _value->template readValue<>(*this, _depl);
+ }
+
+ return (*this);
+ }
+
+ template<typename... _Types>
+ COMMONAPI_EXPORT InputStream &readValue(Variant<_Types...> &_value, const CommonAPI::EmptyDeployment *_depl = nullptr) {
+ if(_value.hasValue()) {
+ DeleteVisitor<_value.maxSize> visitor(_value.valueStorage_);
+ ApplyVoidVisitor<DeleteVisitor<_value.maxSize>,
+ Variant<_Types...>, _Types... >::visit(visitor, _value);
+ }
+
+ align(8);
+ readValue(_value.valueType_, static_cast<EmptyDeployment *>(nullptr));
+ skipSignature();
+
+ InputStreamReadVisitor<DBusInputStream, _Types...> visitor((*this), _value);
+ ApplyVoidVisitor<InputStreamReadVisitor<DBusInputStream, _Types... >,
+ Variant<_Types...>, _Types...>::visit(visitor, _value);
+
+ return (*this);
+ }
+
+ template<typename _Deployment, typename... _Types>
+ COMMONAPI_EXPORT InputStream &readValue(Variant<_Types...> &_value, const _Deployment *_depl) {
+ if(_value.hasValue()) {
+ DeleteVisitor<_value.maxSize> visitor(_value.valueStorage_);
+ ApplyVoidVisitor<DeleteVisitor<_value.maxSize>,
+ Variant<_Types...>, _Types... >::visit(visitor, _value);
+ }
+
+ if (_depl != nullptr && _depl->isFreeDesktop_) {
+ // Read signature
+ uint8_t signatureLength;
+ readValue(signatureLength, static_cast<EmptyDeployment *>(nullptr));
+ std::string signature(_readRaw(signatureLength+1), signatureLength);
+
+ // Determine index (value type) from signature
+ TypeCompareVisitor<_Types...> visitor(signature);
+ _value.valueType_ = ApplyTypeCompareVisitor<
+ TypeCompareVisitor<_Types...>,
+ Variant<_Types...>,
+ _Types...
+ >::visit(visitor, _value);
+ } else {
+ align(8);
+ readValue(_value.valueType_, static_cast<EmptyDeployment *>(nullptr));
+ skipSignature();
+ }
+
+
+ InputStreamReadVisitor<DBusInputStream, _Types...> visitor((*this), _value);
+ ApplyVoidVisitor<InputStreamReadVisitor<DBusInputStream, _Types... >,
+ Variant<_Types...>, _Types...>::visit(visitor, _value);
+
+ return (*this);
+ }
+
+ template<typename _ElementType>
+ COMMONAPI_EXPORT InputStream &readValue(std::vector<_ElementType> &_value, const EmptyDeployment *_depl) {
+ uint32_t itsSize;
+ _readValue(itsSize);
+ pushSize(itsSize);
+
+ alignVector<_ElementType>();
+
+ pushPosition();
+
+ _value.clear();
+ while (sizes_.top() > current_ - positions_.top()) {
+ _ElementType itsElement;
+ readValue(itsElement, static_cast<EmptyDeployment *>(nullptr));
+
+ if (hasError()) {
+ break;
+ }
+
+ _value.push_back(std::move(itsElement));
+ }
+
+ popSize();
+ popPosition();
+
+ return (*this);
+ }
+
+ template<class _Deployment, typename _ElementType>
+ COMMONAPI_EXPORT InputStream &readValue(std::vector<_ElementType> &_value, const _Deployment *_depl) {
+ uint32_t itsSize;
+ _readValue(itsSize);
+ pushSize(itsSize);
+
+ alignVector<_ElementType>();
+
+ pushPosition();
+
+ _value.clear();
+ while (sizes_.top() > current_ - positions_.top()) {
+ _ElementType itsElement;
+ readValue(itsElement, _depl->elementDepl_);
+
+ if (hasError()) {
+ break;
+ }
+
+ _value.push_back(std::move(itsElement));
+ }
+
+ popSize();
+ popPosition();
+
+ return (*this);
+ }
+
+ template<typename _KeyType, typename _ValueType, typename _HasherType>
+ COMMONAPI_EXPORT InputStream &readValue(std::unordered_map<_KeyType, _ValueType, _HasherType> &_value,
+ const EmptyDeployment *_depl) {
+
+ typedef typename std::unordered_map<_KeyType, _ValueType, _HasherType>::value_type MapElement;
+
+ uint32_t itsSize;
+ _readValue(itsSize);
+ pushSize(itsSize);
+
+ align(8);
+ pushPosition();
+
+ _value.clear();
+ while (sizes_.top() > current_ - positions_.top()) {
+ _KeyType itsKey;
+ _ValueType itsValue;
+
+ align(8);
+ readValue(itsKey, _depl);
+ readValue(itsValue, _depl);
+
+ if (hasError()) {
+ break;
+ }
+
+ _value.insert(MapElement(std::move(itsKey), std::move(itsValue)));
+ }
+
+ (void)popSize();
+ (void)popPosition();
+
+ return (*this);
+ }
+
+ template<class _Deployment, typename _KeyType, typename _ValueType, typename _HasherType>
+ COMMONAPI_EXPORT InputStream &readValue(std::unordered_map<_KeyType, _ValueType, _HasherType> &_value,
+ const _Deployment *_depl) {
+
+ typedef typename std::unordered_map<_KeyType, _ValueType, _HasherType>::value_type MapElement;
+
+ uint32_t itsSize;
+ _readValue(itsSize);
+ pushSize(itsSize);
+
+ align(8);
+ pushPosition();
+
+ _value.clear();
+ while (sizes_.top() > current_ - positions_.top()) {
+ _KeyType itsKey;
+ _ValueType itsValue;
+
+ align(8);
+ readValue(itsKey, _depl->key_);
+ readValue(itsValue, _depl->value_);
+
+ if (hasError()) {
+ break;
+ }
+
+ _value.insert(MapElement(std::move(itsKey), std::move(itsValue)));
+ }
+
+ (void)popSize();
+ (void)popPosition();
+
+ return (*this);
+ }
+
+ /**
+ * Creates a #DBusInputMessageStream which can be used to deserialize and read data from the given #DBusMessage.
+ * As no message-signature is checked, the user is responsible to ensure that the correct data types are read in the correct order.
+ *
+ * @param message the #DBusMessage from which data should be read.
+ */
+ COMMONAPI_EXPORT DBusInputStream(const CommonAPI::DBus::DBusMessage &_message);
+ COMMONAPI_EXPORT DBusInputStream(const DBusInputStream &_stream) = delete;
+
+ /**
+ * Destructor; does not call the destructor of the referred #DBusMessage. Make sure to maintain a reference to the
+ * #DBusMessage outside of the stream if you intend to make further use of the message.
+ */
+ COMMONAPI_EXPORT ~DBusInputStream();
+
+ // Marks the stream as erroneous.
+ COMMONAPI_EXPORT void setError();
+
+ /**
+ * @return An instance of #DBusError if this stream is in an erroneous state, NULL otherwise
+ */
+ COMMONAPI_EXPORT const DBusError &getError() const;
+
+ /**
+ * @return true if this stream is in an erroneous state, false otherwise.
+ */
+ COMMONAPI_EXPORT bool isErrorSet() const;
+
+ // Marks the state of the stream as cleared from all errors. Further reading is possible afterwards.
+ // The stream will have maintained the last valid position from before its state became erroneous.
+ COMMONAPI_EXPORT void clearError();
+
+ /**
+ * Aligns the stream to the given byte boundary, i.e. the stream skips as many bytes as are necessary to execute the next read
+ * starting from the given boundary.
+ *
+ * @param _boundary the byte boundary to which the stream needs to be aligned.
+ */
+ COMMONAPI_EXPORT void align(const size_t _boundary);
+
+ /**
+ * Reads the given number of bytes and returns them as an array of characters.
+ *
+ * Actually, for performance reasons this command only returns a pointer to the current position in the stream,
+ * and then increases the position of this pointer by the number of bytes indicated by the given parameter.
+ * It is the user's responsibility to actually use only the number of bytes he indicated he would use.
+ * It is assumed the user knows what kind of value is stored next in the #DBusMessage the data is streamed from.
+ * Using a reinterpret_cast on the returned pointer should then restore the original value.
+ *
+ * Example use case:
+ * @code
+ * ...
+ * inputMessageStream.alignForBasicType(sizeof(int32_t));
+ * char* const dataPtr = inputMessageStream.read(sizeof(int32_t));
+ * int32_t val = *(reinterpret_cast<int32_t*>(dataPtr));
+ * ...
+ * @endcode
+ */
+ COMMONAPI_EXPORT char *_readRaw(const size_t _size);
+
+ /**
+ * Handles all reading of basic types from a given #DBusInputMessageStream.
+ * Basic types in this context are: uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t, float, double.
+ * Any types not listed here (especially all complex types, e.g. structs, unions etc.) need to provide a
+ * specialized implementation of this operator.
+ *
+ * @tparam _Type The type of the value that is to be read from the given stream.
+ * @param _value The variable in which the retrieved value is to be stored
+ * @return The given inputMessageStream to allow for successive reading
+ */
+ template<typename _Type>
+ COMMONAPI_EXPORT DBusInputStream &_readValue(_Type &_value) {
+ if (sizeof(_value) > 1)
+ align(sizeof(_Type));
+
+ _value = *(reinterpret_cast<_Type *>(_readRaw(sizeof(_Type))));
+
+ return (*this);
+ }
+
+ COMMONAPI_EXPORT DBusInputStream &_readValue(float &_value) {
+ align(sizeof(double));
+
+ _value = (float) (*(reinterpret_cast<double*>(_readRaw(sizeof(double)))));
+ return (*this);
+ }
+
+private:
+ COMMONAPI_EXPORT void pushPosition();
+ COMMONAPI_EXPORT size_t popPosition();
+
+ COMMONAPI_EXPORT void pushSize(size_t _size);
+ COMMONAPI_EXPORT size_t popSize();
+
+ inline void skipSignature() {
+ uint8_t length;
+ _readValue(length);
+ _readRaw(length + 1);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<!std::is_class<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_vector<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ if (4 < sizeof(_Type)) align(8);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<!std::is_same<_Type, std::string>::value>::type * = nullptr,
+ typename std::enable_if<std::is_class<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_vector<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ align(8);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<std::is_same<_Type, std::string>::value>::type * = nullptr) {
+ // Intentionally do nothing
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<is_std_vector<_Type>::value>::type * = nullptr) {
+ // Intentionally do nothing
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ align(4);
+ }
+
+ char *begin_;
+ size_t current_;
+ size_t size_;
+ CommonAPI::DBus::DBusError* exception_;
+ CommonAPI::DBus::DBusMessage message_;
+
+ std::stack<uint32_t> sizes_;
+ std::stack<size_t> positions_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUS_INPUTSTREAM_HPP_
diff --git a/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp b/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp
new file mode 100644
index 0000000..d520034
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp
@@ -0,0 +1,135 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSINSTANCEAVAILABILITYSTATUSCHANGED_EVENT_HPP_
+#define COMMONAPI_DBUS_DBUSINSTANCEAVAILABILITYSTATUSCHANGED_EVENT_HPP_
+
+#include <functional>
+#include <future>
+#include <string>
+#include <vector>
+
+#include <CommonAPI/ProxyManager.hpp>
+#include <CommonAPI/DBus/DBusAddressTranslator.hpp>
+#include <CommonAPI/DBus/DBusProxy.hpp>
+#include <CommonAPI/DBus/DBusObjectManagerStub.hpp>
+#include <CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp>
+#include <CommonAPI/DBus/DBusTypes.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+// TODO Check to move logic to DBusServiceRegistry, now every proxy will deserialize the messages!
+class DBusInstanceAvailabilityStatusChangedEvent:
+ public ProxyManager::InstanceAvailabilityStatusChangedEvent,
+ public DBusProxyConnection::DBusSignalHandler {
+ public:
+ DBusInstanceAvailabilityStatusChangedEvent(DBusProxy &_proxy, const std::string &_interfaceName) :
+ proxy_(_proxy),
+ observedInterfaceName_(_interfaceName) {
+ }
+
+ virtual ~DBusInstanceAvailabilityStatusChangedEvent() {
+ proxy_.removeSignalMemberHandler(interfacesAddedSubscription_);
+ proxy_.removeSignalMemberHandler(interfacesRemovedSubscription_);
+ }
+
+ virtual void onSignalDBusMessage(const DBusMessage& dbusMessage) {
+ if (dbusMessage.hasMemberName("InterfacesAdded")) {
+ onInterfacesAddedSignal(dbusMessage);
+ } else if (dbusMessage.hasMemberName("InterfacesRemoved")) {
+ onInterfacesRemovedSignal(dbusMessage);
+ }
+ }
+
+ protected:
+ virtual void onFirstListenerAdded(const Listener&) {
+ interfacesAddedSubscription_ = proxy_.addSignalMemberHandler(
+ proxy_.getDBusAddress().getObjectPath(),
+ DBusObjectManagerStub::getInterfaceName(),
+ "InterfacesAdded",
+ "oa{sa{sv}}",
+ this);
+
+ interfacesRemovedSubscription_ = proxy_.addSignalMemberHandler(
+ proxy_.getDBusAddress().getObjectPath(),
+ DBusObjectManagerStub::getInterfaceName(),
+ "InterfacesRemoved",
+ "oas",
+ this);
+ }
+
+ virtual void onLastListenerRemoved(const Listener&) {
+ proxy_.removeSignalMemberHandler(interfacesAddedSubscription_);
+ proxy_.removeSignalMemberHandler(interfacesRemovedSubscription_);
+ }
+
+ private:
+ inline void onInterfacesAddedSignal(const DBusMessage &_message) {
+ DBusInputStream dbusInputStream(_message);
+ std::string dbusObjectPath;
+ DBusInterfacesAndPropertiesDict dbusInterfacesAndPropertiesDict;
+
+ dbusInputStream >> dbusObjectPath;
+ assert(!dbusInputStream.hasError());
+
+ dbusInputStream >> dbusInterfacesAndPropertiesDict;
+ assert(!dbusInputStream.hasError());
+
+ for (const auto& dbusInterfaceIterator : dbusInterfacesAndPropertiesDict) {
+ const std::string& dbusInterfaceName = dbusInterfaceIterator.first;
+
+ if(dbusInterfaceName == observedInterfaceName_) {
+ notifyInterfaceStatusChanged(dbusObjectPath, dbusInterfaceName, AvailabilityStatus::AVAILABLE);
+ }
+ }
+ }
+
+ inline void onInterfacesRemovedSignal(const DBusMessage &_message) {
+ DBusInputStream dbusInputStream(_message);
+ std::string dbusObjectPath;
+ std::vector<std::string> dbusInterfaceNames;
+
+ dbusInputStream >> dbusObjectPath;
+ assert(!dbusInputStream.hasError());
+
+ dbusInputStream >> dbusInterfaceNames;
+ assert(!dbusInputStream.hasError());
+
+ for (const auto& dbusInterfaceName : dbusInterfaceNames) {
+ if(dbusInterfaceName == observedInterfaceName_) {
+ notifyInterfaceStatusChanged(dbusObjectPath, dbusInterfaceName, AvailabilityStatus::NOT_AVAILABLE);
+ }
+ }
+ }
+
+ void notifyInterfaceStatusChanged(const std::string &_objectPath,
+ const std::string &_interfaceName,
+ const AvailabilityStatus &_availability) {
+ CommonAPI::Address itsAddress;
+ DBusAddress itsDBusAddress(proxy_.getDBusAddress().getService(),
+ _objectPath,
+ _interfaceName);
+
+ DBusAddressTranslator::get()->translate(itsDBusAddress, itsAddress);
+
+ notifyListeners(itsAddress.getAddress(), _availability);
+ }
+
+
+ DBusProxy &proxy_;
+ std::string observedInterfaceName_;
+ DBusProxyConnection::DBusSignalHandlerToken interfacesAddedSubscription_;
+ DBusProxyConnection::DBusSignalHandlerToken interfacesRemovedSubscription_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSINSTANCEAVAILABILITYSTATUSCHANGEDEVENT_HPP_
diff --git a/include/CommonAPI/DBus/DBusInterfaceHandler.hpp b/include/CommonAPI/DBus/DBusInterfaceHandler.hpp
new file mode 100644
index 0000000..c570975
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusInterfaceHandler.hpp
@@ -0,0 +1,31 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef COMMONAPI_DBUS_DBUSINTERFACEHANDLER_HPP_
+#define COMMONAPI_DBUS_DBUSINTERFACEHANDLER_HPP_
+
+#include <memory>
+
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusInterfaceHandler {
+ public:
+ virtual ~DBusInterfaceHandler() {}
+
+ virtual const char* getMethodsDBusIntrospectionXmlData() const = 0;
+
+ virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) = 0;
+
+ virtual const bool hasFreedesktopProperties() = 0;
+};
+
+} // namespace dbus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSINTERFACEHANDLER_HPP_
diff --git a/include/CommonAPI/DBus/DBusMainLoopContext.hpp b/include/CommonAPI/DBus/DBusMainLoopContext.hpp
new file mode 100644
index 0000000..9230cd2
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusMainLoopContext.hpp
@@ -0,0 +1,87 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSMAINLOOPCONTEXT_HPP_
+#define COMMONAPI_DBUS_DBUSMAINLOOPCONTEXT_HPP_
+
+#include <list>
+#include <memory>
+
+#include <dbus/dbus.h>
+
+#include <CommonAPI/MainLoopContext.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusConnection;
+
+class DBusDispatchSource: public DispatchSource {
+ public:
+ DBusDispatchSource(DBusConnection* dbusConnection);
+ ~DBusDispatchSource();
+
+ bool prepare(int64_t& timeout);
+ bool check();
+ bool dispatch();
+
+ private:
+ DBusConnection* dbusConnection_;
+};
+
+class DBusWatch: public Watch {
+ public:
+ DBusWatch(::DBusWatch* libdbusWatch, std::weak_ptr<MainLoopContext>& mainLoopContext);
+
+ bool isReadyToBeWatched();
+ void startWatching();
+ void stopWatching();
+
+ void dispatch(unsigned int eventFlags);
+
+ const pollfd& getAssociatedFileDescriptor();
+
+ const std::vector<DispatchSource*>& getDependentDispatchSources();
+ void addDependentDispatchSource(DispatchSource* dispatchSource);
+ private:
+ bool isReady();
+
+ ::DBusWatch* libdbusWatch_;
+ pollfd pollFileDescriptor_;
+ std::vector<DispatchSource*> dependentDispatchSources_;
+
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+};
+
+
+class DBusTimeout: public Timeout {
+ public:
+ DBusTimeout(::DBusTimeout* libdbusTimeout, std::weak_ptr<MainLoopContext>& mainLoopContext);
+
+ bool isReadyToBeMonitored();
+ void startMonitoring();
+ void stopMonitoring();
+
+ bool dispatch();
+
+ int64_t getTimeoutInterval() const;
+ int64_t getReadyTime() const;
+ private:
+ void recalculateDueTime();
+
+ int64_t dueTimeInMs_;
+ ::DBusTimeout* libdbusTimeout_;
+ std::weak_ptr<MainLoopContext> mainLoopContext_;
+};
+
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSMAINLOOPCONTEXT_HPP_
diff --git a/include/CommonAPI/DBus/DBusMessage.hpp b/include/CommonAPI/DBus/DBusMessage.hpp
new file mode 100644
index 0000000..dc5d72e
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusMessage.hpp
@@ -0,0 +1,101 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSMESSAGE_HPP_
+#define COMMONAPI_DBUS_DBUSMESSAGE_HPP_
+
+#include <string>
+
+#include <dbus/dbus.h>
+
+#include <CommonAPI/Export.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusAddress;
+class DBusConnection;
+
+class COMMONAPI_EXPORT DBusMessage {
+public:
+ enum class Type: int {
+ Invalid = DBUS_MESSAGE_TYPE_INVALID,
+ MethodCall = DBUS_MESSAGE_TYPE_METHOD_CALL,
+ MethodReturn = DBUS_MESSAGE_TYPE_METHOD_RETURN,
+ Error = DBUS_MESSAGE_TYPE_ERROR,
+ Signal = DBUS_MESSAGE_TYPE_SIGNAL
+ };
+
+ DBusMessage();
+ DBusMessage(::DBusMessage* libdbusMessage);
+ DBusMessage(::DBusMessage* libdbusMessage, bool _reference);
+ DBusMessage(const DBusMessage &_source);
+ DBusMessage(DBusMessage &&_source);
+
+ ~DBusMessage();
+
+ DBusMessage &operator=(const DBusMessage &_source);
+ DBusMessage &operator=(DBusMessage &&_source);
+ operator bool() const;
+
+ static DBusMessage createOrgFreedesktopOrgMethodCall(const std::string &_method,
+ const std::string &_signature = "");
+
+ static DBusMessage createMethodCall(const DBusAddress &_address,
+ const std::string &_method, const std::string &_signature = "");
+
+ DBusMessage createMethodReturn(const std::string &_signature) const;
+
+ DBusMessage createMethodError(const std::string &_name, const std::string &_reason = "") const;
+
+ static DBusMessage createSignal(const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& signalName,
+ const std::string& signature = "");
+
+ const char* getSender() const;
+ const char* getObjectPath() const;
+ const char* getInterface() const;
+ const char* getMember() const;
+ const char* getSignature() const;
+ const char* getError() const;
+ const char* getDestination() const;
+ const uint32_t getSerial() const;
+
+ bool hasObjectPath(const std::string& objectPath) const;
+
+ bool hasObjectPath(const char* objectPath) const;
+ bool hasInterfaceName(const char* interfaceName) const;
+ bool hasMemberName(const char* memberName) const;
+ bool hasSignature(const char* signature) const;
+
+ const Type getType() const;
+ bool isInvalidType() const;
+ bool isMethodCallType() const;
+ bool isMethodReturnType() const;
+ bool isErrorType() const;
+ bool isSignalType() const;
+
+ char* getBodyData() const;
+ int getBodyLength() const;
+ int getBodySize() const;
+
+ bool setBodyLength(const int bodyLength);
+ bool setDestination(const char* destination);
+
+private:
+ ::DBusMessage *message_;
+
+ friend class DBusConnection;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSMESSAGE_HPP_
diff --git a/include/CommonAPI/DBus/DBusMultiEvent.hpp b/include/CommonAPI/DBus/DBusMultiEvent.hpp
new file mode 100644
index 0000000..8215d4f
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusMultiEvent.hpp
@@ -0,0 +1,118 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSMULTIEVENT_HPP_
+#define COMMONAPI_DBUS_DBUSMULTIEVENT_HPP_
+
+#include <string>
+#include <unordered_map>
+
+#include <CommonAPI/Event.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template <typename... _Arguments>
+class DBusMultiEvent {
+ public:
+ typedef std::function<SubscriptionStatus(const std::string&, const _Arguments&...)> Listener;
+ typedef std::unordered_multimap<std::string, Listener> ListenersMap;
+ typedef typename ListenersMap::iterator Subscription;
+
+ virtual ~DBusMultiEvent() {}
+
+ Subscription subscribeAll(const Listener& listener);
+ Subscription subscribe(const std::string& eventName, const Listener& listener);
+
+ void unsubscribe(Subscription listenerSubscription);
+
+ protected:
+ SubscriptionStatus notifyListeners(const std::string& name, const _Arguments&... eventArguments);
+
+ virtual void onFirstListenerAdded(const std::string& name, const Listener& listener) { }
+ virtual void onListenerAdded(const std::string& name, const Listener& listener) { }
+
+ virtual void onListenerRemoved(const std::string& name, const Listener& listener) { }
+ virtual void onLastListenerRemoved(const std::string& name, const Listener& listener) { }
+
+ private:
+ typedef std::pair<typename ListenersMap::iterator, typename ListenersMap::iterator> IteratorRange;
+ SubscriptionStatus notifyListenersRange(const std::string& name, IteratorRange listenersRange, const _Arguments&... eventArguments);
+
+ ListenersMap listenersMap_;
+};
+
+template <typename... _Arguments>
+typename DBusMultiEvent<_Arguments...>::Subscription
+DBusMultiEvent<_Arguments...>::subscribeAll(const Listener& listener) {
+ return subscribe(std::string(), listener);
+}
+
+template <typename... _Arguments>
+typename DBusMultiEvent<_Arguments...>::Subscription
+DBusMultiEvent<_Arguments...>::subscribe(const std::string& eventName, const Listener& listener) {
+ const bool firstListenerAdded = listenersMap_.empty();
+
+ auto listenerSubscription = listenersMap_.insert({eventName, listener});
+
+ if (firstListenerAdded) {
+ onFirstListenerAdded(eventName, listener);
+ }
+
+ onListenerAdded(eventName, listener);
+
+ return listenerSubscription;
+}
+
+template <typename... _Arguments>
+void DBusMultiEvent<_Arguments...>::unsubscribe(Subscription listenerSubscription) {
+ const std::string name = listenerSubscription->first;
+ const Listener listener = listenerSubscription->second;
+
+ listenersMap_.erase(listenerSubscription);
+
+ onListenerRemoved(name, listener);
+
+ const bool lastListenerRemoved = listenersMap_.empty();
+ if (lastListenerRemoved)
+ onLastListenerRemoved(name, listener);
+}
+
+template <typename... _Arguments>
+SubscriptionStatus DBusMultiEvent<_Arguments...>::notifyListeners(const std::string& name, const _Arguments&... eventArguments) {
+ const SubscriptionStatus subscriptionStatus = notifyListenersRange(name, listenersMap_.equal_range(name), eventArguments...);
+
+ if (subscriptionStatus == SubscriptionStatus::CANCEL)
+ return SubscriptionStatus::CANCEL;
+
+ return notifyListenersRange(name, listenersMap_.equal_range(std::string()), eventArguments...);
+}
+
+template <typename... _Arguments>
+SubscriptionStatus DBusMultiEvent<_Arguments...>::notifyListenersRange(
+ const std::string& name,
+ IteratorRange listenersRange,
+ const _Arguments&... eventArguments) {
+ for (auto iterator = listenersRange.first; iterator != listenersRange.second; iterator++) {
+ const Listener& listener = iterator->second;
+ const SubscriptionStatus listenerSubcriptionStatus = listener(name, eventArguments...);
+
+ if (listenerSubcriptionStatus == SubscriptionStatus::CANCEL) {
+ auto listenerIterator = iterator;
+ listenersMap_.erase(listenerIterator);
+ }
+ }
+
+ return listenersMap_.empty() ? SubscriptionStatus::CANCEL : SubscriptionStatus::RETAIN;
+}
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSMULTIEVENT_HPP_
diff --git a/include/CommonAPI/DBus/DBusObjectManager.hpp b/include/CommonAPI/DBus/DBusObjectManager.hpp
new file mode 100644
index 0000000..8c7225b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusObjectManager.hpp
@@ -0,0 +1,69 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSOBJECTMANAGER_HPP_
+#define COMMONAPI_DBUS_DBUSOBJECTMANAGER_HPP_
+
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusObjectManagerStub.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusStubAdapter;
+class DBusInterfaceHandler;
+
+class DBusObjectManager {
+ public:
+ COMMONAPI_EXPORT DBusObjectManager(const std::shared_ptr<DBusProxyConnection>&);
+ COMMONAPI_EXPORT ~DBusObjectManager();
+
+ COMMONAPI_EXPORT bool registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+ COMMONAPI_EXPORT bool unregisterDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ //Zusammenfassbar mit "registerDBusStubAdapter"?
+ COMMONAPI_EXPORT bool exportManagedDBusStubAdapter(const std::string& parentObjectPath, std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+ COMMONAPI_EXPORT bool unexportManagedDBusStubAdapter(const std::string& parentObjectPath, std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ COMMONAPI_EXPORT bool handleMessage(const DBusMessage&);
+
+ COMMONAPI_EXPORT std::shared_ptr<DBusObjectManagerStub> getRootDBusObjectManagerStub();
+
+ private:
+ // objectPath, interfaceName
+ typedef std::pair<std::string, std::string> DBusInterfaceHandlerPath;
+
+ COMMONAPI_EXPORT bool addDBusInterfaceHandler(const DBusInterfaceHandlerPath& dbusInterfaceHandlerPath,
+ std::shared_ptr<DBusInterfaceHandler> dbusInterfaceHandler);
+
+ COMMONAPI_EXPORT bool removeDBusInterfaceHandler(const DBusInterfaceHandlerPath& dbusInterfaceHandlerPath,
+ std::shared_ptr<DBusInterfaceHandler> dbusInterfaceHandler);
+
+ COMMONAPI_EXPORT bool onIntrospectableInterfaceDBusMessage(const DBusMessage& callMessage);
+ COMMONAPI_EXPORT bool onFreedesktopPropertiesDBusMessage(const DBusMessage& callMessage);
+
+
+ typedef std::unordered_map<DBusInterfaceHandlerPath, std::shared_ptr<DBusInterfaceHandler>> DBusRegisteredObjectsTable;
+ DBusRegisteredObjectsTable dbusRegisteredObjectsTable_;
+
+ std::shared_ptr<DBusObjectManagerStub> rootDBusObjectManagerStub_;
+
+ typedef std::pair<std::shared_ptr<DBusObjectManagerStub>, uint32_t> ReferenceCountedDBusObjectManagerStub;
+ typedef std::unordered_map<std::string, ReferenceCountedDBusObjectManagerStub> RegisteredObjectManagersTable;
+ RegisteredObjectManagersTable managerStubs_;
+
+ std::weak_ptr<DBusProxyConnection> dbusConnection_;
+ std::recursive_mutex objectPathLock_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSOBJECTMANAGER_HPP_
diff --git a/include/CommonAPI/DBus/DBusObjectManagerStub.hpp b/include/CommonAPI/DBus/DBusObjectManagerStub.hpp
new file mode 100644
index 0000000..a16578b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusObjectManagerStub.hpp
@@ -0,0 +1,125 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef COMMONAPI_DBUS_DBUSFREEDESKTOPOBJECTMANAGERSTUB_HPP_
+#define COMMONAPI_DBUS_DBUSFREEDESKTOPOBJECTMANAGERSTUB_HPP_
+
+#include <memory>
+#include <mutex>
+#include <string>
+
+#include <CommonAPI/DBus/DBusInterfaceHandler.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusStubAdapter;
+
+/**
+ * Stub for standard <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">org.freedesktop.dbus.ObjectManager</a> interface.
+ *
+ * Instantiated within a manager stub and it must hold reference to all registered objects.
+ * Whenever the manager gets destroyed all references to registered objects are lost too.
+ * This duplicates the semantic of the CommonAPI::ServicePublisher class.
+ *
+ * Only one DBusStubAdapter instance could be registered per DBusObjectManagerStub instance.
+ *
+ * The owner of the DBusObjectManagerStub instance must take care of registering and unregistering it.
+ *
+ * Example stub life cycle:
+ * - create CommonAPI::ServicePublisher
+ * - create stub A
+ * - register stub A to CommonAPI::ServicePublisher
+ * - create stub B
+ * - register stub B with stub A as object manager
+ * - drop all references to stub B, stub A keeps a reference to stub B
+ * - drop all references to stub A, CommonAPI::ServicePublisher keeps a reference to stub A
+ * - reference overview: Application > CommonAPI::ServicePublisher > Stub A > Stub B
+ * - drop all references to CommonAPI::ServicePublisher causes all object references to be dropped
+ */
+class DBusObjectManagerStub : public DBusInterfaceHandler {
+public:
+ // serialization trick: use bool instead of variant since we never serialize it
+ typedef std::unordered_map<std::string, bool> DBusPropertiesChangedDict;
+ typedef std::unordered_map<std::string, DBusPropertiesChangedDict> DBusInterfacesAndPropertiesDict;
+ typedef std::unordered_map<std::string, DBusInterfacesAndPropertiesDict> DBusObjectPathAndInterfacesDict;
+
+public:
+ COMMONAPI_EXPORT DBusObjectManagerStub(const std::string& dbusObjectPath, const std::shared_ptr<DBusProxyConnection>&);
+
+ /**
+ * Unregisters all currently registered DBusStubAdapter instances from the DBusServicePublisher
+ */
+ COMMONAPI_EXPORT virtual ~DBusObjectManagerStub();
+
+ /**
+ * Export DBusStubAdapter instance with the current DBusObjectManagerStub instance.
+ *
+ * The DBusStubAdapter must be registered with the DBusServicePublisher!
+ *
+ * On registering a
+ * <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">InsterfaceAdded</a>
+ * signal will be emitted with the DBusObjectManagerStub instance's current D-Bus object path.
+ *
+ * @param dbusStubAdapter a refernce to DBusStubAdapter instance
+ *
+ * @return false if the @a dbusStubAdapter instance was already registered
+ * @return false if sending the InterfaceAdded signal fails
+ *
+ * @see ~DBusObjectManagerStub()
+ * @see CommonAPI::ServicePublisher
+ * @see DBusObjectManager
+ */
+ COMMONAPI_EXPORT bool exportManagedDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ /**
+ * Unexport DBusStubAdapter instance from this DBusObjectManagerStub instance.
+ *
+ * On unregistering a
+ * <a href="http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager">InsterfaceRemoved</a>
+ * signal will be emitted with the DBusObjectManagerStub instance's current D-Bus object path.
+ *
+ * @param dbusStubAdapter
+ *
+ * @return false if @a dbusStubAdapter wasn't registered
+ * @return true even if sending the InterfaceRemoved signal fails
+ *
+ * @see exportDBusStubAdapter()
+ */
+ COMMONAPI_EXPORT bool unexportManagedDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ COMMONAPI_EXPORT bool isDBusStubAdapterExported(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ COMMONAPI_EXPORT const std::string& getDBusObjectPath() const;
+ COMMONAPI_EXPORT static const char* getInterfaceName();
+
+ COMMONAPI_EXPORT virtual const char* getMethodsDBusIntrospectionXmlData() const;
+ COMMONAPI_EXPORT virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage);
+ COMMONAPI_EXPORT virtual const bool hasFreedesktopProperties();
+
+ private:
+ COMMONAPI_EXPORT bool registerDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+ COMMONAPI_EXPORT bool unregisterDBusStubAdapter(std::shared_ptr<DBusStubAdapter> dbusStubAdapter);
+
+ COMMONAPI_EXPORT bool emitInterfacesAddedSignal(std::shared_ptr<DBusStubAdapter> dbusStubAdapter,
+ const std::shared_ptr<DBusProxyConnection>& dbusConnection) const;
+
+ COMMONAPI_EXPORT bool emitInterfacesRemovedSignal(std::shared_ptr<DBusStubAdapter> dbusStubAdapter,
+ const std::shared_ptr<DBusProxyConnection>& dbusConnection) const;
+
+ std::string dbusObjectPath_;
+ std::weak_ptr<DBusProxyConnection> dbusConnection_;
+
+ typedef std::unordered_map<std::string, std::shared_ptr<DBusStubAdapter>> DBusInterfacesMap;
+ typedef std::unordered_map<std::string, DBusInterfacesMap> DBusObjectPathsMap;
+ DBusObjectPathsMap registeredDBusObjectPathsMap_;
+
+ std::mutex dbusObjectManagerStubLock_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSFREEDESKTOPOBJECTMANAGERSTUB_HPP_
diff --git a/include/CommonAPI/DBus/DBusOutputStream.hpp b/include/CommonAPI/DBus/DBusOutputStream.hpp
new file mode 100644
index 0000000..1148f3e
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusOutputStream.hpp
@@ -0,0 +1,398 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSOUTPUTSTREAM_HPP_
+#define COMMONAPI_DBUS_DBUSOUTPUTSTREAM_HPP_
+
+#include <cassert>
+#include <cstring>
+#include <memory>
+#include <stack>
+#include <string>
+#include <vector>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/Logger.hpp>
+#include <CommonAPI/OutputStream.hpp>
+#include <CommonAPI/DBus/DBusDeployment.hpp>
+#include <CommonAPI/DBus/DBusError.hpp>
+#include <CommonAPI/DBus/DBusHelper.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusTypeOutputStream.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+/**
+ * @class DBusOutputMessageStream
+ *
+ * Used to serialize and write data into a #DBusMessage. For all data types that may be written to a #DBusMessage, a "<<"-operator should be defined to handle the writing
+ * (this operator is predefined for all basic data types and for vectors). The signature that has to be written to the #DBusMessage separately is assumed
+ * to match the actual data that is inserted via the #DBusOutputMessageStream.
+ */
+class DBusOutputStream: public OutputStream<DBusOutputStream> {
+public:
+
+ /**
+ * Creates a #DBusOutputMessageStream which can be used to serialize and write data into the given #DBusMessage. Any data written is buffered within the stream.
+ * Remember to call flush() when you are done with writing: Only then the data actually is written to the #DBusMessage.
+ *
+ * @param dbusMessage The #DBusMessage any data pushed into this stream should be written to.
+ */
+ COMMONAPI_EXPORT DBusOutputStream(DBusMessage dbusMessage);
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const bool &_value, const EmptyDeployment *_depl) {
+ uint32_t tmp = (_value ? 1 : 0);
+ return _writeValue(tmp);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const int8_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const int16_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const int32_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const int64_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const uint8_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const uint16_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const uint32_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const uint64_t &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const float &_value, const EmptyDeployment *_depl) {
+ return _writeValue(static_cast<double>(_value));
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const double &_value, const EmptyDeployment *_depl) {
+ return _writeValue(_value);
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::string &_value, const EmptyDeployment * = nullptr) {
+ return writeString(_value.c_str(), _value.length());
+ }
+
+ COMMONAPI_EXPORT OutputStream &writeValue(const Version &_value, const EmptyDeployment *_depl = nullptr) {
+ align(8);
+ writeValue(_value.Major, _depl);
+ writeValue(_value.Minor, _depl);
+ return (*this);
+ }
+
+ template<class _Deployment, typename _Base>
+ COMMONAPI_EXPORT OutputStream &writeValue(const Enumeration<_Base> &_value, const _Deployment *_depl = nullptr) {
+ return writeValue(static_cast<_Base>(_value), _depl);
+ }
+
+ template<class _Deployment, typename... _Types>
+ COMMONAPI_EXPORT OutputStream &writeValue(const Struct<_Types...> &_value, const _Deployment *_depl = nullptr) {
+ align(8);
+
+ const auto itsSize(std::tuple_size<std::tuple<_Types...>>::value);
+ StructWriter<itsSize-1, DBusOutputStream, Struct<_Types...>, _Deployment>{}((*this), _value, _depl);
+
+ return (*this);
+ }
+
+ template<class _Deployment, class _PolymorphicStruct>
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::shared_ptr<_PolymorphicStruct> &_value, const _Deployment *_depl = nullptr) {
+ align(8);
+ _writeValue(_value->getSerial());
+
+ DBusTypeOutputStream typeOutput;
+ typeOutput.writeType(_value);
+ writeSignature(typeOutput.getSignature());
+
+ align(8);
+ _value->template writeValue<>((*this), _depl);
+
+ return (*this);
+ }
+
+ template<typename... _Types>
+ COMMONAPI_EXPORT OutputStream &writeValue(const Variant<_Types...> &_value, const CommonAPI::EmptyDeployment *_depl = nullptr) {
+ align(8);
+ writeValue(_value.getValueType(), static_cast<EmptyDeployment *>(nullptr));
+
+ DBusTypeOutputStream typeOutput;
+ TypeOutputStreamWriteVisitor<DBusTypeOutputStream> typeVisitor(typeOutput);
+ ApplyVoidVisitor<TypeOutputStreamWriteVisitor<DBusTypeOutputStream>,
+ Variant<_Types...>, _Types...>::visit(typeVisitor, _value);
+ writeSignature(typeOutput.getSignature());
+
+ OutputStreamWriteVisitor<DBusOutputStream> valueVisitor(*this);
+ ApplyVoidVisitor<OutputStreamWriteVisitor<DBusOutputStream>,
+ Variant<_Types...>, _Types...>::visit(valueVisitor, _value);
+
+ return (*this);
+ }
+
+ template<typename _Deployment, typename... _Types>
+ COMMONAPI_EXPORT OutputStream &writeValue(const Variant<_Types...> &_value, const _Deployment *_depl = nullptr) {
+ if (_depl != nullptr && _depl->isFreeDesktop_) {
+ align(1);
+ } else {
+ align(8);
+ writeValue(_value.getValueType(), static_cast<EmptyDeployment *>(nullptr));
+ }
+
+ DBusTypeOutputStream typeOutput;
+ TypeOutputStreamWriteVisitor<DBusTypeOutputStream> typeVisitor(typeOutput);
+ ApplyVoidVisitor<TypeOutputStreamWriteVisitor<DBusTypeOutputStream>,
+ Variant<_Types...>, _Types...>::visit(typeVisitor, _value);
+ writeSignature(typeOutput.getSignature());
+
+ OutputStreamWriteVisitor<DBusOutputStream> valueVisitor(*this);
+ ApplyVoidVisitor<OutputStreamWriteVisitor<DBusOutputStream>,
+ Variant<_Types...>, _Types...>::visit(valueVisitor, _value);
+
+ return (*this);
+ }
+
+ template<typename _ElementType>
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::vector<_ElementType> &_value,
+ const EmptyDeployment *_depl) {
+ align(sizeof(uint32_t));
+ pushPosition();
+ _writeValue(static_cast<uint32_t>(0)); // Placeholder
+
+ alignVector<_ElementType>();
+ pushPosition(); // Start of vector data
+
+ for (auto i : _value) {
+ writeValue(i, _depl);
+ if (hasError()) {
+ break;
+ }
+ }
+
+ // Write number of written bytes to placeholder position
+ uint32_t length = getPosition() - popPosition();
+ _writeValueAt(popPosition(), length);
+
+ return (*this);
+ }
+
+ template<class _Deployment, typename _ElementType>
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::vector<_ElementType> &_value,
+ const _Deployment *_depl) {
+ align(sizeof(uint32_t));
+ pushPosition();
+ _writeValue(static_cast<uint32_t>(0)); // Placeholder
+
+ alignVector<_ElementType>();
+ pushPosition(); // Start of vector data
+
+ for (auto i : _value) {
+ writeValue(i, _depl->elementDepl_);
+ if (hasError()) {
+ break;
+ }
+ }
+
+ // Write number of written bytes to placeholder position
+ uint32_t length = getPosition() - popPosition();
+ _writeValueAt(popPosition(), length);
+
+ return (*this);
+ }
+
+ template<typename _KeyType, typename _ValueType, typename _HasherType>
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::unordered_map<_KeyType, _ValueType, _HasherType> &_value,
+ const EmptyDeployment *_depl) {
+ align(sizeof(uint32_t));
+ pushPosition();
+ _writeValue(static_cast<uint32_t>(0)); // Placeholder
+
+ align(8);
+ pushPosition(); // Start of map data
+
+ for (auto v : _value) {
+ align(8);
+ writeValue(v.first, static_cast<EmptyDeployment *>(nullptr));
+ writeValue(v.second, static_cast<EmptyDeployment *>(nullptr));
+
+ if (hasError()) {
+ return (*this);
+ }
+ }
+
+ // Write number of written bytes to placeholder position
+ uint32_t length = getPosition() - popPosition();
+ _writeValueAt(popPosition(), length);
+ return (*this);
+ }
+
+ template<class _Deployment, typename _KeyType, typename _ValueType, typename _HasherType>
+ COMMONAPI_EXPORT OutputStream &writeValue(const std::unordered_map<_KeyType, _ValueType, _HasherType> &_value,
+ const _Deployment *_depl) {
+ align(sizeof(uint32_t));
+ pushPosition();
+ _writeValue(static_cast<uint32_t>(0)); // Placeholder
+
+ align(8);
+ pushPosition(); // Start of map data
+
+ for (auto v : _value) {
+ align(8);
+ writeValue(v.first, _depl->key_);
+ writeValue(v.second, _depl->value_);
+
+ if (hasError()) {
+ return (*this);
+ }
+ }
+
+ // Write number of written bytes to placeholder position
+ uint32_t length = getPosition() - popPosition();
+ _writeValueAt(popPosition(), length);
+ return (*this);
+ }
+
+ /**
+ * Writes the data that was buffered within this #DBusOutputMessageStream to the #DBusMessage that was given to the constructor. Each call to flush()
+ * will completely override the data that currently is contained in the #DBusMessage. The data that is buffered in this #DBusOutputMessageStream is
+ * not deleted by calling flush().
+ */
+ COMMONAPI_EXPORT void flush();
+
+ COMMONAPI_EXPORT bool hasError() const;
+
+private:
+ COMMONAPI_EXPORT size_t getPosition();
+ COMMONAPI_EXPORT void pushPosition();
+ COMMONAPI_EXPORT size_t popPosition();
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<!std::is_class<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_vector<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ if (4 < sizeof(_Type)) align(8);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<!std::is_same<_Type, std::string>::value>::type * = nullptr,
+ typename std::enable_if<std::is_class<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_vector<_Type>::value>::type * = nullptr,
+ typename std::enable_if<!is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ align(8);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<std::is_same<_Type, std::string>::value>::type * = nullptr) {
+ // Intentionally do nothing
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<is_std_vector<_Type>::value>::type * = nullptr) {
+ // Intentionally do nothing
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void alignVector(typename std::enable_if<is_std_unordered_map<_Type>::value>::type * = nullptr) {
+ align(4);
+ }
+
+ COMMONAPI_EXPORT void setError();
+
+ /**
+ * Reserves the given number of bytes for writing, thereby negating the need to dynamically allocate memory while writing.
+ * Use this method for optimization: If possible, reserve as many bytes as you need for your data before doing any writing.
+ *
+ * @param numOfBytes The number of bytes that should be reserved for writing.
+ */
+ COMMONAPI_EXPORT void reserveMemory(size_t numOfBytes);
+
+ template<typename _Type>
+ COMMONAPI_EXPORT DBusOutputStream &_writeValue(const _Type &_value) {
+ if (sizeof(_Type) > 1)
+ align(sizeof(_Type));
+
+ _writeRaw(reinterpret_cast<const char*>(&_value), sizeof(_Type));
+ return (*this);
+ }
+
+ template<typename _Type>
+ COMMONAPI_EXPORT void _writeValueAt(size_t _position, const _Type &_value) {
+ assert(_position + sizeof(_Type) <= payload_.size());
+ _writeRawAt(reinterpret_cast<const char *>(&_value),
+ sizeof(_Type), _position);
+ }
+
+ COMMONAPI_EXPORT DBusOutputStream &writeString(const char *_data, const uint32_t &_length);
+
+ /**
+ * Fills the stream with 0-bytes to make the next value be aligned to the boundary given.
+ * This means that as many 0-bytes are written to the buffer as are necessary
+ * to make the next value start with the given alignment.
+ *
+ * @param alignBoundary The byte-boundary to which the next value should be aligned.
+ */
+ COMMONAPI_EXPORT void align(const size_t _boundary);
+
+ /**
+ * Takes sizeInByte characters, starting from the character which val points to, and stores them for later writing.
+ * When calling flush(), all values that were written to this stream are copied into the payload of the #DBusMessage.
+ *
+ * The array of characters might be created from a pointer to a given value by using a reinterpret_cast. Example:
+ * @code
+ * ...
+ * int32_t val = 15;
+ * outputMessageStream.alignForBasicType(sizeof(int32_t));
+ * const char* const reinterpreted = reinterpret_cast<const char*>(&val);
+ * outputMessageStream.writeValue(reinterpreted, sizeof(int32_t));
+ * ...
+ * @endcode
+ *
+ * @param _data The array of chars that should serve as input
+ * @param _size The number of bytes that should be written
+ * @return true if writing was successful, false otherwise.
+ *
+ * @see DBusOutputMessageStream()
+ * @see flush()
+ */
+ COMMONAPI_EXPORT void _writeRaw(const char *_data, const size_t _size);
+ COMMONAPI_EXPORT void _writeRawAt(const char *_data, const size_t _size, size_t _position);
+
+protected:
+ std::string payload_;
+
+private:
+ COMMONAPI_EXPORT void writeSignature(const std::string& signature);
+
+ COMMONAPI_EXPORT size_t getCurrentStreamPosition();
+
+ DBusError dbusError_;
+ DBusMessage dbusMessage_;
+
+ std::stack<size_t> positions_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSOUTPUTSTREAM_PPH_
diff --git a/include/CommonAPI/DBus/DBusProxy.hpp b/include/CommonAPI/DBus/DBusProxy.hpp
new file mode 100644
index 0000000..af40863
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxy.hpp
@@ -0,0 +1,84 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSPROXY_HPP_
+#define COMMONAPI_DBUS_DBUSPROXY_HPP_
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/DBus/DBusAttribute.hpp>
+#include <CommonAPI/DBus/DBusServiceRegistry.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusProxyStatusEvent
+ : public ProxyStatusEvent {
+ friend class DBusProxy;
+
+ public:
+ DBusProxyStatusEvent(DBusProxy* dbusProxy);
+ virtual ~DBusProxyStatusEvent() {}
+
+ protected:
+ virtual void onListenerAdded(const Listener& listener);
+
+ DBusProxy* dbusProxy_;
+};
+
+
+class DBusProxy
+ : public DBusProxyBase {
+public:
+ COMMONAPI_EXPORT DBusProxy(const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection);
+ COMMONAPI_EXPORT virtual ~DBusProxy();
+
+ COMMONAPI_EXPORT virtual ProxyStatusEvent& getProxyStatusEvent();
+ COMMONAPI_EXPORT virtual InterfaceVersionAttribute& getInterfaceVersionAttribute();
+
+ COMMONAPI_EXPORT virtual bool isAvailable() const;
+ COMMONAPI_EXPORT virtual bool isAvailableBlocking() const;
+
+ COMMONAPI_EXPORT DBusProxyConnection::DBusSignalHandlerToken subscribeForSelectiveBroadcastOnConnection(
+ bool& subscriptionAccepted,
+ const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusProxyConnection::DBusSignalHandler* dbusSignalHandler);
+ COMMONAPI_EXPORT void unsubscribeFromSelectiveBroadcast(const std::string& eventName,
+ DBusProxyConnection::DBusSignalHandlerToken subscription,
+ const DBusProxyConnection::DBusSignalHandler* dbusSignalHandler);
+
+ COMMONAPI_EXPORT void init();
+
+private:
+ COMMONAPI_EXPORT DBusProxy(const DBusProxy &) = delete;
+
+ COMMONAPI_EXPORT void onDBusServiceInstanceStatus(const AvailabilityStatus& availabilityStatus);
+
+ DBusProxyStatusEvent dbusProxyStatusEvent_;
+ DBusServiceRegistry::DBusServiceSubscription dbusServiceRegistrySubscription_;
+ AvailabilityStatus availabilityStatus_;
+
+ DBusReadonlyAttribute<InterfaceVersionAttribute> interfaceVersionAttribute_;
+
+ std::shared_ptr<DBusServiceRegistry> dbusServiceRegistry_;
+};
+
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSPROXY_HPP_
+
diff --git a/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp b/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp
new file mode 100644
index 0000000..eac96d2
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp
@@ -0,0 +1,78 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSPROXYASYNCCALLBACKHANDLER_HPP_
+#define COMMONAPI_DBUS_DBUSPROXYASYNCCALLBACKHANDLER_HPP_
+
+#include <functional>
+#include <future>
+#include <memory>
+
+#include <CommonAPI/DBus/DBusHelper.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusSerializableArguments.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template<typename ... _ArgTypes>
+class DBusProxyAsyncCallbackHandler: public DBusProxyConnection::DBusMessageReplyAsyncHandler {
+ public:
+ typedef std::function<void(CallStatus, _ArgTypes...)> FunctionType;
+
+ static std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler> create(
+ FunctionType&& callback, std::tuple<_ArgTypes...> args) {
+ return std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler>(
+ new DBusProxyAsyncCallbackHandler(std::move(callback), args));
+ }
+
+ DBusProxyAsyncCallbackHandler() = delete;
+ DBusProxyAsyncCallbackHandler(FunctionType&& callback, std::tuple<_ArgTypes...> args):
+ callback_(std::move(callback)), args_(args) {
+ }
+ virtual ~DBusProxyAsyncCallbackHandler() {}
+
+ virtual std::future<CallStatus> getFuture() {
+ return promise_.get_future();
+ }
+
+ virtual void onDBusMessageReply(const CallStatus& dbusMessageCallStatus, const DBusMessage& dbusMessage) {
+ promise_.set_value(handleDBusMessageReply(dbusMessageCallStatus, dbusMessage, typename make_sequence<sizeof...(_ArgTypes)>::type(), args_));
+ }
+
+ private:
+ template <int... _ArgIndices>
+ inline CallStatus handleDBusMessageReply(const CallStatus dbusMessageCallStatus, const DBusMessage& dbusMessage, index_sequence<_ArgIndices...>, std::tuple<_ArgTypes...> argTuple) const {
+ CallStatus callStatus = dbusMessageCallStatus;
+
+ if (dbusMessageCallStatus == CallStatus::SUCCESS) {
+ if (!dbusMessage.isErrorType()) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_ArgTypes...>::deserialize(dbusInputStream, std::get<_ArgIndices>(argTuple)...);
+ if (!success)
+ callStatus = CallStatus::REMOTE_ERROR;
+ } else {
+ callStatus = CallStatus::REMOTE_ERROR;
+ }
+ }
+
+ callback_(callStatus, std::move(std::get<_ArgIndices>(argTuple))...);
+ return callStatus;
+ }
+
+ std::promise<CallStatus> promise_;
+ const FunctionType callback_;
+ std::tuple<_ArgTypes...> args_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSPROXYASYNCCALLBACKHANDLER_HPP_
diff --git a/include/CommonAPI/DBus/DBusProxyBase.hpp b/include/CommonAPI/DBus/DBusProxyBase.hpp
new file mode 100644
index 0000000..85c746c
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxyBase.hpp
@@ -0,0 +1,72 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSPROXYBASE_HPP_
+#define COMMONAPI_DBUS_DBUSPROXYBASE_HPP_
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/Proxy.hpp>
+#include <CommonAPI/Types.hpp>
+
+#include <CommonAPI/DBus/DBusAddress.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusAddress;
+
+class DBusProxyBase
+ : public virtual CommonAPI::Proxy {
+public:
+ COMMONAPI_EXPORT DBusProxyBase(const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection);
+ COMMONAPI_EXPORT virtual ~DBusProxyBase() {}
+
+ COMMONAPI_EXPORT const DBusAddress &getDBusAddress() const;
+ COMMONAPI_EXPORT const std::shared_ptr<DBusProxyConnection> &getDBusConnection() const;
+
+ COMMONAPI_EXPORT DBusMessage createMethodCall(const std::string &_method,
+ const std::string &_signature = "") const;
+
+ COMMONAPI_EXPORT DBusProxyConnection::DBusSignalHandlerToken addSignalMemberHandler(
+ const std::string& signalName,
+ const std::string& signalSignature,
+ DBusProxyConnection::DBusSignalHandler* dbusSignalHandler,
+ const bool justAddFilter = false);
+
+ COMMONAPI_EXPORT DBusProxyConnection::DBusSignalHandlerToken addSignalMemberHandler(
+ const std::string &objectPath,
+ const std::string &interfaceName,
+ const std::string &signalName,
+ const std::string &signalSignature,
+ DBusProxyConnection::DBusSignalHandler *dbusSignalHandler,
+ const bool justAddFilter = false);
+
+ COMMONAPI_EXPORT bool removeSignalMemberHandler(
+ const DBusProxyConnection::DBusSignalHandlerToken &_token,
+ const DBusProxyConnection::DBusSignalHandler *_handler = NULL);
+
+ COMMONAPI_EXPORT virtual void init() = 0;
+
+ private:
+ COMMONAPI_EXPORT DBusProxyBase(const DBusProxyBase &) = delete;
+
+ DBusAddress dbusAddress_;
+ std::shared_ptr<DBusProxyConnection> connection_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSPROXYBASE_HPP_
diff --git a/include/CommonAPI/DBus/DBusProxyConnection.hpp b/include/CommonAPI/DBus/DBusProxyConnection.hpp
new file mode 100644
index 0000000..cbef54d
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxyConnection.hpp
@@ -0,0 +1,127 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSPROXYCONNECTION_HPP_
+#define COMMONAPI_DBUS_DBUSPROXYCONNECTION_HPP_
+
+#include <cstdint>
+#include <functional>
+#include <future>
+#include <memory>
+#include <set>
+#include <tuple>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include <CommonAPI/Attribute.hpp>
+#include <CommonAPI/Event.hpp>
+#include <CommonAPI/Types.hpp>
+#include <CommonAPI/DBus/DBusConfig.hpp>
+#include <CommonAPI/DBus/DBusError.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusFunctionalHash.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+typedef std::function<void(const DBusMessage&)> DBusMessageHandler;
+
+class DBusDaemonProxy;
+class DBusServiceRegistry;
+class DBusObjectManager;
+class DBusProxy;
+
+class DBusProxyConnection {
+ public:
+ class DBusMessageReplyAsyncHandler {
+ public:
+ virtual ~DBusMessageReplyAsyncHandler() {}
+ virtual std::future<CallStatus> getFuture() = 0;
+ virtual void onDBusMessageReply(const CallStatus&, const DBusMessage&) = 0;
+ };
+
+ class DBusSignalHandler {
+ public:
+ virtual ~DBusSignalHandler() {}
+ virtual void onSignalDBusMessage(const DBusMessage&) = 0;
+ };
+
+ // objectPath, interfaceName, interfaceMemberName, interfaceMemberSignature
+ typedef std::tuple<std::string, std::string, std::string, std::string> DBusSignalHandlerPath;
+ typedef std::unordered_map<DBusSignalHandlerPath, std::pair<std::shared_ptr<std::recursive_mutex>, std::set<DBusSignalHandler* >>> DBusSignalHandlerTable;
+ typedef DBusSignalHandlerPath DBusSignalHandlerToken;
+
+ typedef Event<AvailabilityStatus> ConnectionStatusEvent;
+
+ virtual ~DBusProxyConnection() {}
+
+ virtual bool isConnected() const = 0;
+
+ virtual ConnectionStatusEvent& getConnectionStatusEvent() = 0;
+
+ virtual bool sendDBusMessage(const DBusMessage& dbusMessage) const = 0;
+
+ virtual std::future<CallStatus> sendDBusMessageWithReplyAsync(
+ const DBusMessage& dbusMessage,
+ std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler,
+ const CommonAPI::CallInfo *_info) const = 0;
+
+ virtual DBusMessage sendDBusMessageWithReplyAndBlock(
+ const DBusMessage& dbusMessage,
+ DBusError& dbusError,
+ const CommonAPI::CallInfo *_info) const = 0;
+
+ virtual DBusSignalHandlerToken addSignalMemberHandler(
+ const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler,
+ const bool justAddFilter = false) = 0;
+
+ virtual DBusSignalHandlerToken subscribeForSelectiveBroadcast(bool& subscriptionAccepted,
+ const std::string& objectPath,
+ const std::string& interfaceName,
+ const std::string& interfaceMemberName,
+ const std::string& interfaceMemberSignature,
+ DBusSignalHandler* dbusSignalHandler,
+ DBusProxy* callingProxy) = 0;
+
+ virtual void unsubscribeFromSelectiveBroadcast(const std::string& eventName,
+ DBusProxyConnection::DBusSignalHandlerToken subscription,
+ DBusProxy* callingProxy,
+ const DBusSignalHandler* dbusSignalHandler) = 0;
+
+ virtual bool removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken,
+ const DBusSignalHandler* dbusSignalHandler = NULL) = 0;
+
+ virtual bool addObjectManagerSignalMemberHandler(const std::string& dbusBusName,
+ DBusSignalHandler* dbusSignalHandler) = 0;
+ virtual bool removeObjectManagerSignalMemberHandler(const std::string& dbusBusName,
+ DBusSignalHandler* dbusSignalHandler) = 0;
+
+ virtual const std::shared_ptr<DBusObjectManager> getDBusObjectManager() = 0;
+
+ virtual void registerObjectPath(const std::string& objectPath) = 0;
+ virtual void unregisterObjectPath(const std::string& objectPath) = 0;
+
+ virtual bool requestServiceNameAndBlock(const std::string& serviceName) const = 0;
+ virtual bool releaseServiceName(const std::string& serviceName) const = 0;
+
+ typedef std::function<bool(const DBusMessage&)> DBusObjectPathMessageHandler;
+
+ virtual void setObjectPathMessageHandler(DBusObjectPathMessageHandler) = 0;
+ virtual bool isObjectPathMessageHandlerSet() = 0;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSPROXYCONNECTION_HPP_
diff --git a/include/CommonAPI/DBus/DBusProxyHelper.hpp b/include/CommonAPI/DBus/DBusProxyHelper.hpp
new file mode 100644
index 0000000..516d923
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxyHelper.hpp
@@ -0,0 +1,258 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSPROXYHELPER_HPP_
+#define COMMONAPI_DBUS_DBUSPROXYHELPER_HPP_
+
+#include <functional>
+#include <future>
+#include <memory>
+#include <string>
+
+#include <CommonAPI/DBus/DBusAddress.hpp>
+#include <CommonAPI/DBus/DBusConfig.hpp>
+#include <CommonAPI/DBus/DBusMessage.hpp>
+#include <CommonAPI/DBus/DBusSerializableArguments.hpp>
+#include <CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusProxy;
+
+template< class, class >
+struct DBusProxyHelper;
+
+template<
+ template<class ...> class _In, class... _InArgs,
+ template <class...> class _Out, class... _OutArgs>
+struct DBusProxyHelper<_In<DBusInputStream, DBusOutputStream, _InArgs...>,
+ _Out<DBusInputStream, DBusOutputStream, _OutArgs...>> {
+
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethod(const _DBusProxy &_proxy,
+ const std::string &_method,
+ const std::string &_signature,
+ const _InArgs&... _in,
+ CommonAPI::CallStatus &_status) {
+
+ if (_proxy.isAvailableBlocking()) {
+ DBusMessage message = _proxy.createMethodCall(_method, _signature);
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream output(message);
+ if (DBusSerializableArguments<_InArgs...>::serialize(output, _in...)) {
+ _status = CallStatus::OUT_OF_MEMORY;
+ return;
+ }
+ output.flush();
+ }
+
+ const bool isSent = _proxy.getDBusConnection()->sendDBusMessage(message);
+ _status = (isSent ? CallStatus::SUCCESS : CallStatus::OUT_OF_MEMORY);
+ } else {
+ _status = CallStatus::NOT_AVAILABLE;
+ }
+ }
+
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethodWithReply(
+ const _DBusProxy &_proxy,
+ DBusMessage &_message,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ CommonAPI::CallStatus &_status,
+ _OutArgs&... _out) {
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream output(_message);
+ if (!DBusSerializableArguments<_InArgs...>::serialize(output, _in...)) {
+ _status = CallStatus::OUT_OF_MEMORY;
+ return;
+ }
+ output.flush();
+ }
+
+ DBusError error;
+ DBusMessage reply = _proxy.getDBusConnection()->sendDBusMessageWithReplyAndBlock(_message, error, _info);
+ if (error || !reply.isMethodReturnType()) {
+ _status = CallStatus::REMOTE_ERROR;
+ return;
+ }
+
+ if (sizeof...(_OutArgs) > 0) {
+ DBusInputStream input(reply);
+ if (!DBusSerializableArguments<_OutArgs...>::deserialize(input, _out...)) {
+ _status = CallStatus::REMOTE_ERROR;
+ return;
+ }
+ }
+ _status = CallStatus::SUCCESS;
+ }
+
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethodWithReply(
+ const _DBusProxy &_proxy,
+ const DBusAddress &_address,
+ const char *_method,
+ const char *_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ CommonAPI::CallStatus &_status,
+ _OutArgs&... _out) {
+ if (_proxy.isAvailableBlocking()) {
+ DBusMessage message = DBusMessage::createMethodCall(_address, _method, _signature);
+ callMethodWithReply(_proxy, message, _info, _in..., _status, _out...);
+ } else {
+ _status = CallStatus::NOT_AVAILABLE;
+ }
+ }
+
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethodWithReply(
+ const _DBusProxy &_proxy,
+ const std::string &_interface,
+ const std::string &_method,
+ const std::string &_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ CommonAPI::CallStatus &_status,
+ _OutArgs&... _out) {
+ DBusAddress itsAddress(_proxy.getDBusAddress());
+ itsAddress.setInterface(_interface);
+ callMethodWithReply(
+ _proxy, itsAddress,
+ _method.c_str(), _signature.c_str(),
+ _info,
+ _in..., _status, _out...);
+ }
+
+ template <typename _DBusProxy = DBusProxy>
+ static void callMethodWithReply(
+ const _DBusProxy &_proxy,
+ const std::string &_method,
+ const std::string &_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ CommonAPI::CallStatus &_status,
+ _OutArgs&... _out) {
+ if (_proxy.isAvailableBlocking()) {
+ DBusMessage message = _proxy.createMethodCall(_method, _signature);
+ callMethodWithReply(_proxy, message, _info, _in..., _status, _out...);
+ } else {
+ _status = CallStatus::NOT_AVAILABLE;
+ }
+ }
+
+ template <typename _DBusProxy = DBusProxy, typename _AsyncCallback>
+ static std::future<CallStatus> callMethodAsync(
+ const _DBusProxy &_proxy,
+ DBusMessage &_message,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ _AsyncCallback _callback,
+ std::tuple<_OutArgs...> _out) {
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream output(_message);
+ const bool success = DBusSerializableArguments<
+ _InArgs...
+ >::serialize(output, _in...);
+ if (!success) {
+ std::promise<CallStatus> promise;
+ promise.set_value(CallStatus::OUT_OF_MEMORY);
+ return promise.get_future();
+ }
+ output.flush();
+ }
+
+ return _proxy.getDBusConnection()->sendDBusMessageWithReplyAsync(
+ _message,
+ DBusProxyAsyncCallbackHandler<
+ _OutArgs...
+ >::create(std::move(_callback), _out),
+ _info);
+ }
+
+ template <typename _DBusProxy = DBusProxy, typename _AsyncCallback>
+ static std::future<CallStatus> callMethodAsync(
+ const _DBusProxy &_proxy,
+ const DBusAddress &_address,
+ const std::string &_method,
+ const std::string &_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ _AsyncCallback _callback,
+ std::tuple<_OutArgs...> _out) {
+ if (_proxy.isAvailable()) {
+ DBusMessage message = DBusMessage::createMethodCall(_address, _method, _signature);
+ return callMethodAsync(_proxy, message, _info, _in..., _callback, _out);
+ } else {
+ CallStatus status = CallStatus::NOT_AVAILABLE;
+ callCallbackOnNotAvailable(_callback, typename make_sequence<sizeof...(_OutArgs)>::type(), _out);
+
+ std::promise<CallStatus> promise;
+ promise.set_value(status);
+ return promise.get_future();
+ }
+ }
+
+ template <typename _DBusProxy = DBusProxy, typename _AsyncCallback>
+ static std::future<CallStatus> callMethodAsync(
+ const _DBusProxy &_proxy,
+ const std::string &_interface,
+ const std::string &_method,
+ const std::string &_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ _AsyncCallback _callback,
+ std::tuple<_OutArgs...> _out) {
+ DBusAddress itsAddress(_proxy.getDBusAddress());
+ itsAddress.setInterface(_interface);
+ return callMethodAsync(
+ _proxy, itsAddress,
+ _method, _signature,
+ _info,
+ _in..., _callback, _out);
+ }
+
+ template <typename _DBusProxy = DBusProxy, typename _AsyncCallback>
+ static std::future<CallStatus> callMethodAsync(
+ const _DBusProxy &_proxy,
+ const std::string &_method,
+ const std::string &_signature,
+ const CommonAPI::CallInfo *_info,
+ const _InArgs&... _in,
+ _AsyncCallback _callback,
+ std::tuple<_OutArgs...> _out) {
+ if (_proxy.isAvailable()) {
+ DBusMessage message = _proxy.createMethodCall(_method, _signature);
+ return callMethodAsync(_proxy, message, _info, _in..., _callback, _out);
+ } else {
+ callCallbackOnNotAvailable(
+ _callback, typename make_sequence<sizeof...(_OutArgs)>::type(), _out);
+
+ CallStatus status = CallStatus::NOT_AVAILABLE;
+ std::promise<CallStatus> promise;
+ promise.set_value(status);
+ return promise.get_future();
+ }
+ }
+
+ template <int... _ArgIndices>
+ static void callCallbackOnNotAvailable(std::function<void(CallStatus, _OutArgs&...)> _callback,
+ index_sequence<_ArgIndices...>, std::tuple<_OutArgs...> _out) {
+ const CallStatus status(CallStatus::NOT_AVAILABLE);
+ _callback(status, std::get<_ArgIndices>(_out)...);
+ }
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSPROXYHELPER_HPP_
diff --git a/include/CommonAPI/DBus/DBusProxyManager.hpp b/include/CommonAPI/DBus/DBusProxyManager.hpp
new file mode 100644
index 0000000..a28527a
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusProxyManager.hpp
@@ -0,0 +1,72 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_PROXYMANAGER_HPP_
+#define COMMONAPI_DBUS_PROXYMANAGER_HPP_
+
+#include <functional>
+#include <future>
+#include <string>
+#include <vector>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/ProxyManager.hpp>
+#include <CommonAPI/DBus/DBusProxy.hpp>
+#include <CommonAPI/DBus/DBusFactory.hpp>
+#include <CommonAPI/DBus/DBusObjectManagerStub.hpp>
+#include <CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusProxyManager: public ProxyManager {
+public:
+ COMMONAPI_EXPORT DBusProxyManager(DBusProxy &_proxy,
+ const std::string &_interfaceName);
+
+ COMMONAPI_EXPORT const std::string &getDomain() const;
+ COMMONAPI_EXPORT const std::string &getInterface() const;
+ COMMONAPI_EXPORT const ConnectionId_t &getConnectionId() const;
+
+ COMMONAPI_EXPORT virtual void getAvailableInstances(CommonAPI::CallStatus &, std::vector<std::string> &_instances);
+ COMMONAPI_EXPORT virtual std::future<CallStatus> getAvailableInstancesAsync(GetAvailableInstancesCallback _callback);
+
+ COMMONAPI_EXPORT virtual void getInstanceAvailabilityStatus(const std::string &_address,
+ CallStatus &_callStatus,
+ AvailabilityStatus &_availabilityStatus);
+
+ COMMONAPI_EXPORT virtual std::future<CallStatus> getInstanceAvailabilityStatusAsync(
+ const std::string&,
+ GetInstanceAvailabilityStatusCallback callback);
+
+ COMMONAPI_EXPORT virtual InstanceAvailabilityStatusChangedEvent& getInstanceAvailabilityStatusChangedEvent();
+
+private:
+ COMMONAPI_EXPORT void instancesAsyncCallback(const CommonAPI::CallStatus& status,
+ const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict& dict,
+ GetAvailableInstancesCallback& call);
+
+ COMMONAPI_EXPORT void instanceAliveAsyncCallback(const AvailabilityStatus &_alive,
+ GetInstanceAvailabilityStatusCallback &_call,
+ std::shared_ptr<std::promise<CallStatus>> &_status);
+
+ COMMONAPI_EXPORT void translateCommonApiAddresses(const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict &_dict,
+ std::vector<std::string> &_instances);
+
+ DBusProxy &proxy_;
+ DBusInstanceAvailabilityStatusChangedEvent instanceAvailabilityStatusEvent_;
+ const std::string interfaceId_;
+ const std::shared_ptr<DBusServiceRegistry> registry_;
+ ConnectionId_t connectionId_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_PROXYMANAGER_HPP_
diff --git a/include/CommonAPI/DBus/DBusSelectiveEvent.hpp b/include/CommonAPI/DBus/DBusSelectiveEvent.hpp
new file mode 100644
index 0000000..65c61f9
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusSelectiveEvent.hpp
@@ -0,0 +1,56 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSSELECTIVEEVENT_HPP_
+#define COMMONAPI_DBUS_DBUSSELECTIVEEVENT_HPP_
+
+#include <CommonAPI/DBus/DBusEvent.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template<typename _EventType, typename... _Arguments>
+class DBusSelectiveEvent: public DBusEvent<_EventType, _Arguments...> {
+public:
+ typedef typename DBusEvent<_EventType, _Arguments...>::Listener Listener;
+ typedef DBusEvent<_EventType, _Arguments...> DBusEventBase;
+
+ DBusSelectiveEvent(DBusProxy &_proxy,
+ const char *_name, const char *_signature,
+ std::tuple<_Arguments...> _arguments)
+ : DBusEventBase(_proxy, _name, _signature, _arguments) {
+ }
+
+ DBusSelectiveEvent(DBusProxy &_proxy,
+ const char *_name, const char *_signature,
+ const char *_path, const char *_interface,
+ std::tuple<_Arguments...> _arguments)
+ : DBusEventBase(_proxy, _name, _signature, _path, _interface, _arguments) {
+ }
+
+ virtual ~DBusSelectiveEvent() {}
+
+protected:
+ void onFirstListenerAdded(const Listener &) {
+ bool success;
+ this->subscription_
+ = static_cast<DBusProxy&>(this->proxy_).subscribeForSelectiveBroadcastOnConnection(
+ success, this->path_, this->interface_, this->name_, this->signature_, this);
+ }
+
+ void onLastListenerRemoved(const Listener &) {
+ static_cast<DBusProxy&>(this->proxy_).unsubscribeFromSelectiveBroadcast(
+ this->name_, this->subscription_, this);
+ }
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSSELECTIVEEVENT_HPP_
diff --git a/include/CommonAPI/DBus/DBusSerializableArguments.hpp b/include/CommonAPI/DBus/DBusSerializableArguments.hpp
new file mode 100644
index 0000000..f763ce5
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusSerializableArguments.hpp
@@ -0,0 +1,30 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUS_SERIALIZABLEARGUMENTS_HPP_
+#define COMMONAPI_DBUS_DBUS_SERIALIZABLEARGUMENTS_HPP_
+
+#include <CommonAPI/SerializableArguments.hpp>
+#include <CommonAPI/DBus/DBusInputStream.hpp>
+#include <CommonAPI/DBus/DBusOutputStream.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+template<typename... _Arguments>
+using DBusSerializableArguments = CommonAPI::SerializableArguments<
+ DBusInputStream,
+ DBusOutputStream,
+ _Arguments...
+ >;
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSSERIALIZABLEARGUMENTS_HPP_
diff --git a/include/CommonAPI/DBus/DBusServiceRegistry.hpp b/include/CommonAPI/DBus/DBusServiceRegistry.hpp
new file mode 100644
index 0000000..3dbcf1b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusServiceRegistry.hpp
@@ -0,0 +1,315 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSSERVICEREGISTRY_HPP_
+#define COMMONAPI_DBUS_DBUSSERVICEREGISTRY_HPP_
+
+#include <algorithm>
+#include <condition_variable>
+#include <future>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+#include <list>
+
+#include <pugixml/pugixml.hpp>
+
+#include <CommonAPI/Attribute.hpp>
+#include <CommonAPI/Proxy.hpp>
+#include <CommonAPI/Types.hpp>
+#include <CommonAPI/DBus/DBusProxyConnection.hpp>
+#include <CommonAPI/DBus/DBusFactory.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+typedef Event<std::string, std::string, std::string> NameOwnerChangedEvent;
+typedef Event<std::string, std::string, std::string>::Subscription NameOwnerChangedEventSubscription;
+
+// Connection name, Object path
+typedef std::pair<std::string, std::string> DBusInstanceId;
+
+class DBusAddress;
+class DBusAddressTranslator;
+class DBusDaemonProxy;
+
+class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegistry>,
+ public DBusProxyConnection::DBusSignalHandler {
+ public:
+ enum class DBusRecordState {
+ UNKNOWN,
+ AVAILABLE,
+ RESOLVING,
+ RESOLVED,
+ NOT_AVAILABLE
+ };
+
+ // template class DBusServiceListener<> { typedef functor; typedef list; typedef subscription }
+ typedef std::function<void(const AvailabilityStatus& availabilityStatus)> DBusServiceListener;
+ typedef std::list<DBusServiceListener> DBusServiceListenerList;
+ typedef DBusServiceListenerList::iterator DBusServiceSubscription;
+
+ typedef std::function<void(const std::vector<std::string>& interfaces,
+ const AvailabilityStatus& availabilityStatus)> DBusManagedInterfaceListener;
+ typedef std::list<DBusManagedInterfaceListener> DBusManagedInterfaceListenerList;
+ typedef DBusManagedInterfaceListenerList::iterator DBusManagedInterfaceSubscription;
+
+ static std::shared_ptr<DBusServiceRegistry> get(std::shared_ptr<DBusProxyConnection> _connection);
+
+ DBusServiceRegistry(std::shared_ptr<DBusProxyConnection> dbusProxyConnection);
+
+ DBusServiceRegistry(const DBusServiceRegistry&) = delete;
+ DBusServiceRegistry& operator=(const DBusServiceRegistry&) = delete;
+
+ virtual ~DBusServiceRegistry();
+
+ void init();
+
+ DBusServiceSubscription subscribeAvailabilityListener(const std::string &_address,
+ DBusServiceListener _listener);
+
+ void unsubscribeAvailabilityListener(const std::string &_address,
+ DBusServiceSubscription &_listener);
+
+
+ bool isServiceInstanceAlive(const std::string &_dbusInterfaceName,
+ const std::string &_dbusConnectionName,
+ const std::string &_dbusObjectPath);
+
+
+ virtual std::vector<std::string> getAvailableServiceInstances(const std::string &_interface,
+ const std::string &_domain = "local");
+
+ virtual void getAvailableServiceInstancesAsync(CommonAPI::Factory::AvailableInstancesCbk_t _cbk,
+ const std::string &_interface,
+ const std::string &_domain = "local");
+
+ virtual void onSignalDBusMessage(const DBusMessage&);
+
+ private:
+ struct DBusInterfaceNameListenersRecord {
+ DBusInterfaceNameListenersRecord()
+ : state(DBusRecordState::UNKNOWN) {
+ }
+
+ DBusInterfaceNameListenersRecord(DBusInterfaceNameListenersRecord &&_other)
+ : state(_other.state),
+ listenerList(std::move(_other.listenerList)) {
+ }
+
+ DBusRecordState state;
+ DBusServiceListenerList listenerList;
+ };
+
+ typedef std::unordered_map<std::string, DBusInterfaceNameListenersRecord> DBusInterfaceNameListenersMap;
+
+ struct DBusServiceListenersRecord {
+ DBusServiceListenersRecord()
+ : uniqueBusNameState(DBusRecordState::UNKNOWN),
+ mutexOnResolve() {
+ }
+
+ DBusServiceListenersRecord(DBusServiceListenersRecord&& other)
+ : uniqueBusNameState(other.uniqueBusNameState),
+ uniqueBusName(std::move(other.uniqueBusName)),
+ promiseOnResolve(std::move(other.promiseOnResolve)),
+ futureOnResolve(std::move(other.futureOnResolve)),
+ mutexOnResolve(std::move(other.mutexOnResolve)),
+ dbusObjectPathListenersMap(std::move(other.dbusObjectPathListenersMap)) {
+ }
+
+ ~DBusServiceListenersRecord() {};
+
+ DBusRecordState uniqueBusNameState;
+ std::string uniqueBusName;
+
+ std::promise<DBusRecordState> promiseOnResolve;
+ std::shared_future<DBusRecordState> futureOnResolve;
+ std::unique_lock<std::mutex>* mutexOnResolve;
+
+ std::unordered_map<std::string, DBusInterfaceNameListenersMap> dbusObjectPathListenersMap;
+ };
+
+ std::unordered_map<std::string, DBusServiceListenersRecord> dbusServiceListenersMap;
+
+
+ struct DBusObjectPathCache {
+ DBusObjectPathCache()
+ : referenceCount(0),
+ state(DBusRecordState::UNKNOWN) {
+ }
+
+ DBusObjectPathCache(DBusObjectPathCache&& other)
+ : referenceCount(other.referenceCount),
+ state(other.state),
+ promiseOnResolve(std::move(other.promiseOnResolve)),
+ dbusInterfaceNamesCache(std::move(other.dbusInterfaceNamesCache)) {
+ }
+
+ ~DBusObjectPathCache() {}
+
+ size_t referenceCount;
+ DBusRecordState state;
+ std::promise<DBusRecordState> promiseOnResolve;
+
+ std::unordered_set<std::string> dbusInterfaceNamesCache;
+ };
+
+ struct DBusUniqueNameRecord {
+ DBusUniqueNameRecord()
+ : objectPathsState(DBusRecordState::UNKNOWN) {
+ }
+
+ DBusUniqueNameRecord(DBusUniqueNameRecord&& other)
+ : uniqueName(std::move(other.uniqueName)),
+ objectPathsState(other.objectPathsState),
+ ownedBusNames(std::move(other.ownedBusNames)),
+ dbusObjectPathsCache(std::move(other.dbusObjectPathsCache)) {
+ }
+
+ std::string uniqueName;
+ DBusRecordState objectPathsState;
+ std::unordered_set<std::string> ownedBusNames;
+ std::unordered_map<std::string, DBusObjectPathCache> dbusObjectPathsCache;
+ };
+
+ std::unordered_map<std::string, DBusUniqueNameRecord> dbusUniqueNamesMap_;
+ typedef std::unordered_map<std::string, DBusUniqueNameRecord>::iterator DBusUniqueNamesMapIterator;
+
+ // mapping service names (well-known names) to service instances
+ std::unordered_map<std::string, DBusUniqueNameRecord*> dbusServiceNameMap_;
+
+ // protects the dbus service maps
+ std::mutex dbusServicesMutex_;
+
+ void resolveDBusServiceName(const std::string& dbusServiceName,
+ DBusServiceListenersRecord& dbusServiceListenersRecord);
+
+ void onGetNameOwnerCallback(const CallStatus& status,
+ std::string dbusServiceUniqueName,
+ const std::string& dbusServiceName);
+
+
+ DBusRecordState resolveDBusInterfaceNameState(const DBusAddress &_address,
+ DBusServiceListenersRecord &_record);
+
+
+ DBusObjectPathCache& getDBusObjectPathCacheReference(const std::string& dbusObjectPath,
+ const std::string& dbusServiceUniqueName,
+ DBusUniqueNameRecord& dbusUniqueNameRecord);
+
+ void releaseDBusObjectPathCacheReference(const std::string& dbusObjectPath,
+ const DBusServiceListenersRecord& dbusServiceListenersRecord);
+
+
+ bool introspectDBusObjectPath(const std::string& dbusServiceUniqueName, const std::string& dbusObjectPath);
+
+ void onIntrospectCallback(const CallStatus& status,
+ std::string xmlData,
+ const std::string& dbusServiceName,
+ const std::string& dbusObjectPath);
+
+ void parseIntrospectionData(const std::string& xmlData,
+ const std::string& rootObjectPath,
+ const std::string& dbusServiceUniqueName);
+
+ void parseIntrospectionNode(const pugi::xml_node& node,
+ const std::string& rootObjectPath,
+ const std::string& fullObjectPath,
+ const std::string& dbusServiceUniqueName);
+
+ void processIntrospectionObjectPath(const pugi::xml_node& node,
+ const std::string& rootObjectPath,
+ const std::string& dbusServiceUniqueName);
+
+ void processIntrospectionInterface(const pugi::xml_node& node,
+ const std::string& rootObjectPath,
+ const std::string& fullObjectPath,
+ const std::string& dbusServiceUniqueName);
+
+ void onDBusDaemonProxyStatusEvent(const AvailabilityStatus& availabilityStatus);
+
+ void onDBusDaemonProxyNameOwnerChangedEvent(const std::string& name,
+ const std::string& oldOwner,
+ const std::string& newOwner);
+
+ std::shared_ptr<DBusDaemonProxy> dbusDaemonProxy_;
+ bool initialized_;
+
+ ProxyStatusEvent::Subscription dbusDaemonProxyStatusEventSubscription_;
+ NameOwnerChangedEvent::Subscription dbusDaemonProxyNameOwnerChangedEventSubscription_;
+
+
+ void checkDBusServiceWasAvailable(const std::string& dbusServiceName, const std::string& dbusServiceUniqueName);
+
+ void onDBusServiceAvailable(const std::string& dbusServiceName, const std::string& dbusServiceUniqueName);
+
+ void onDBusServiceNotAvailable(DBusServiceListenersRecord& dbusServiceListenersRecord, const std::string &_serviceName = "");
+
+
+ void notifyDBusServiceListeners(const DBusUniqueNameRecord& dbusUniqueNameRecord,
+ const std::string& dbusObjectPath,
+ const std::unordered_set<std::string>& dbusInterfaceNames,
+ const DBusRecordState& dbusInterfaceNamesState);
+
+ void notifyDBusObjectPathResolved(DBusInterfaceNameListenersMap& dbusInterfaceNameListenersMap,
+ const std::unordered_set<std::string>& dbusInterfaceNames);
+
+ void notifyDBusObjectPathChanged(DBusInterfaceNameListenersMap& dbusInterfaceNameListenersMap,
+ const std::unordered_set<std::string>& dbusInterfaceNames,
+ const DBusRecordState& dbusInterfaceNamesState);
+
+ void notifyDBusInterfaceNameListeners(DBusInterfaceNameListenersRecord& dbusInterfaceNameListenersRecord,
+ const bool& isDBusInterfaceNameAvailable);
+
+
+ void removeUniqueName(const DBusUniqueNamesMapIterator &_dbusUniqueName, const std::string &_serviceName);
+ DBusUniqueNameRecord* insertServiceNameMapping(const std::string& dbusUniqueName, const std::string& dbusServiceName);
+ bool findCachedDbusService(const std::string& dbusServiceName, DBusUniqueNameRecord** uniqueNameRecord);
+ bool findCachedObjectPath(const std::string& dbusObjectPathName, const DBusUniqueNameRecord* uniqueNameRecord, DBusObjectPathCache* objectPathCache);
+
+ std::condition_variable monitorResolveAllServices_;
+ std::mutex mutexServiceResolveCount;
+ int servicesToResolve;
+
+ std::condition_variable monitorResolveAllObjectPaths_;
+ std::mutex mutexObjectPathsResolveCount;
+ int objectPathsToResolve;
+
+ void fetchAllServiceNames();
+
+ inline const bool isDBusServiceName(const std::string &_name) {
+ return (_name.length() > 0 && _name[0] != ':');
+ };
+
+
+ inline const bool isOrgFreedesktopDBusInterface(const std::string& dbusInterfaceName) {
+ return dbusInterfaceName.find("org.freedesktop.DBus.") == 0;
+ }
+
+ std::thread::id notificationThread_;
+
+private:
+ typedef std::map<std::shared_ptr<DBusProxyConnection>, std::shared_ptr<DBusServiceRegistry>> RegistryMap_t;
+ static RegistryMap_t registries_;
+ static std::mutex registriesMutex_;
+ std::shared_ptr<DBusAddressTranslator> translator_;
+};
+
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSSERVICEREGISTRY_HPP_
diff --git a/include/CommonAPI/DBus/DBusStubAdapter.hpp b/include/CommonAPI/DBus/DBusStubAdapter.hpp
new file mode 100644
index 0000000..5d1657b
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusStubAdapter.hpp
@@ -0,0 +1,59 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSSTUBADAPTER_HPP_
+#define COMMONAPI_DBUS_DBUSSTUBADAPTER_HPP_
+
+#include <memory>
+
+#include <CommonAPI/Export.hpp>
+#include <CommonAPI/Stub.hpp>
+#include <CommonAPI/DBus/DBusAddress.hpp>
+#include <CommonAPI/DBus/DBusInterfaceHandler.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusProxyConnection;
+
+class DBusStubAdapter
+ : virtual public CommonAPI::StubAdapter,
+ public DBusInterfaceHandler {
+ public:
+ COMMONAPI_EXPORT DBusStubAdapter(const DBusAddress &_dbusAddress,
+ const std::shared_ptr<DBusProxyConnection> &_connection,
+ const bool isManagingInterface);
+
+ COMMONAPI_EXPORT virtual ~DBusStubAdapter();
+
+ COMMONAPI_EXPORT virtual void init(std::shared_ptr<DBusStubAdapter> _instance);
+ COMMONAPI_EXPORT virtual void deinit();
+
+ COMMONAPI_EXPORT const DBusAddress &getDBusAddress() const;
+ COMMONAPI_EXPORT const std::shared_ptr<DBusProxyConnection> &getDBusConnection() const;
+
+ COMMONAPI_EXPORT const bool isManaging() const;
+
+ COMMONAPI_EXPORT virtual const char* getMethodsDBusIntrospectionXmlData() const = 0;
+ COMMONAPI_EXPORT virtual bool onInterfaceDBusMessage(const DBusMessage &_message) = 0;
+
+ COMMONAPI_EXPORT virtual void deactivateManagedInstances() = 0;
+ COMMONAPI_EXPORT virtual const bool hasFreedesktopProperties();
+ COMMONAPI_EXPORT virtual bool onInterfaceDBusFreedesktopPropertiesMessage(const DBusMessage &_message) = 0;
+
+ protected:
+ DBusAddress dbusAddress_;
+ const std::shared_ptr<DBusProxyConnection> connection_;
+ const bool isManaging_;
+};
+
+} // namespace dbus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSSTUBADAPTER_HPP_
diff --git a/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp b/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp
new file mode 100644
index 0000000..56e5021
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp
@@ -0,0 +1,674 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSSTUBADAPTERHELPER_HPP_
+#define COMMONAPI_DBUS_DBUSSTUBADAPTERHELPER_HPP_
+
+#include <initializer_list>
+#include <memory>
+#include <tuple>
+#include <unordered_map>
+#include <map>
+
+#include <CommonAPI/Variant.hpp>
+#include <CommonAPI/DBus/DBusStubAdapter.hpp>
+#include <CommonAPI/DBus/DBusInputStream.hpp>
+#include <CommonAPI/DBus/DBusOutputStream.hpp>
+#include <CommonAPI/DBus/DBusHelper.hpp>
+#include <CommonAPI/DBus/DBusSerializableArguments.hpp>
+#include <CommonAPI/DBus/DBusClientId.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class StubDispatcherBase {
+public:
+ virtual ~StubDispatcherBase() { }
+};
+
+struct DBusAttributeDispatcherStruct {
+ StubDispatcherBase* getter;
+ StubDispatcherBase* setter;
+
+ DBusAttributeDispatcherStruct(StubDispatcherBase* g, StubDispatcherBase* s) {
+ getter = g;
+ setter = s;
+ }
+};
+
+typedef std::unordered_map<std::string, DBusAttributeDispatcherStruct> StubAttributeTable;
+
+template <typename _StubClass>
+class DBusStubAdapterHelper: public virtual DBusStubAdapter {
+ public:
+ typedef typename _StubClass::StubAdapterType StubAdapterType;
+ typedef typename _StubClass::RemoteEventHandlerType RemoteEventHandlerType;
+
+ class StubDispatcher: public StubDispatcherBase {
+ public:
+ virtual ~StubDispatcher() {}
+ virtual bool dispatchDBusMessage(const DBusMessage& dbusMessage,
+ const std::shared_ptr<_StubClass>& stub,
+ DBusStubAdapterHelper<_StubClass>& dbusStubAdapterHelper) = 0;
+ };
+ // interfaceMemberName, interfaceMemberSignature
+ typedef std::pair<const char*, const char*> DBusInterfaceMemberPath;
+ typedef std::unordered_map<DBusInterfaceMemberPath, StubDispatcherBase*> StubDispatcherTable;
+
+ DBusStubAdapterHelper(const DBusAddress &_address,
+ const std::shared_ptr<DBusProxyConnection> &_connection,
+ const std::shared_ptr<_StubClass> &_stub,
+ const bool _isManaging):
+ DBusStubAdapter(_address, _connection, _isManaging),
+ stub_(_stub),
+ remoteEventHandler_(nullptr) {
+ }
+
+ virtual ~DBusStubAdapterHelper() {
+ DBusStubAdapter::deinit();
+ stub_.reset();
+ }
+
+ virtual void init(std::shared_ptr<DBusStubAdapter> instance) {
+ DBusStubAdapter::init(instance);
+ std::shared_ptr<StubAdapterType> stubAdapter = std::dynamic_pointer_cast<StubAdapterType>(instance);
+ remoteEventHandler_ = stub_->initStubAdapter(stubAdapter);
+ }
+
+ virtual void deinit() {
+ DBusStubAdapter::deinit();
+ stub_.reset();
+ }
+
+ inline RemoteEventHandlerType* getRemoteEventHandler() {
+ return remoteEventHandler_;
+ }
+
+ protected:
+
+ virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) {
+ const char* interfaceMemberName = dbusMessage.getMember();
+ const char* interfaceMemberSignature = dbusMessage.getSignature();
+
+ assert(interfaceMemberName);
+ assert(interfaceMemberSignature);
+
+ DBusInterfaceMemberPath dbusInterfaceMemberPath(interfaceMemberName, interfaceMemberSignature);
+ auto findIterator = getStubDispatcherTable().find(dbusInterfaceMemberPath);
+ const bool foundInterfaceMemberHandler = (findIterator != getStubDispatcherTable().end());
+ bool dbusMessageHandled = false;
+ if (foundInterfaceMemberHandler) {
+ StubDispatcher* stubDispatcher = static_cast<StubDispatcher*>(findIterator->second);
+ dbusMessageHandled = stubDispatcher->dispatchDBusMessage(dbusMessage, stub_, *this);
+ }
+
+ return dbusMessageHandled;
+ }
+
+ virtual bool onInterfaceDBusFreedesktopPropertiesMessage(const DBusMessage &_message) {
+ DBusInputStream input(_message);
+
+ if (_message.hasMemberName("Get")) {
+ return handleFreedesktopGet(_message, input);
+ } else if (_message.hasMemberName("Set")) {
+ return handleFreedesktopSet(_message, input);
+ } else if (_message.hasMemberName("GetAll")) {
+ return handleFreedesktopGetAll(_message, input);
+ }
+
+ return false;
+ }
+
+ virtual const StubDispatcherTable& getStubDispatcherTable() = 0;
+ virtual const StubAttributeTable& getStubAttributeTable() = 0;
+
+ std::shared_ptr<_StubClass> stub_;
+ RemoteEventHandlerType* remoteEventHandler_;
+
+ private:
+ bool handleFreedesktopGet(const DBusMessage &_message, DBusInputStream &_input) {
+ std::string interfaceName;
+ std::string attributeName;
+ _input >> interfaceName;
+ _input >> attributeName;
+
+ if (_input.hasError()) {
+ return false;
+ }
+
+ auto attributeDispatcherIterator = getStubAttributeTable().find(attributeName);
+ if (attributeDispatcherIterator == getStubAttributeTable().end()) {
+ return false;
+ }
+
+ StubDispatcher* getterDispatcher = static_cast<StubDispatcher*>(attributeDispatcherIterator->second.getter);
+ assert(getterDispatcher != NULL); // all attributes have at least a getter
+ return (getterDispatcher->dispatchDBusMessage(_message, stub_, *this));
+ }
+
+ bool handleFreedesktopSet(const DBusMessage& dbusMessage, DBusInputStream& dbusInputStream) {
+ std::string interfaceName;
+ std::string attributeName;
+ dbusInputStream >> interfaceName;
+ dbusInputStream >> attributeName;
+
+ if(dbusInputStream.hasError()) {
+ return false;
+ }
+
+ auto attributeDispatcherIterator = getStubAttributeTable().find(attributeName);
+ if(attributeDispatcherIterator == getStubAttributeTable().end()) {
+ return false;
+ }
+
+ StubDispatcher *setterDispatcher = static_cast<StubDispatcher*>(attributeDispatcherIterator->second.setter);
+ if (setterDispatcher == NULL) { // readonly attributes do not have a setter
+ return false;
+ }
+
+ return setterDispatcher->dispatchDBusMessage(dbusMessage, stub_, *this);
+ }
+
+ bool handleFreedesktopGetAll(const DBusMessage& dbusMessage, DBusInputStream& dbusInputStream) {
+ std::string interfaceName;
+ dbusInputStream >> interfaceName;
+
+ if(dbusInputStream.hasError()) {
+ return false;
+ }
+
+ DBusMessage dbusMessageReply = dbusMessage.createMethodReturn("a{sv}");
+ DBusOutputStream dbusOutputStream(dbusMessageReply);
+ /*
+ dbusOutputStream.beginWriteVectorOfSerializableStructs(getStubAttributeTable().size());
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSenderName()));
+
+ for(auto attributeDispatcherIterator = getStubAttributeTable().begin(); attributeDispatcherIterator != getStubAttributeTable().end(); attributeDispatcherIterator++) {
+ //To prevent the destruction of the stub whilst still handling a message
+ if (stub_) {
+ DBusGetFreedesktopAttributeStubDispatcherBase<_StubClass>* const getterDispatcher = dynamic_cast<DBusGetFreedesktopAttributeStubDispatcherBase<_StubClass>*>(attributeDispatcherIterator->second.getter);
+
+ if(getterDispatcher == NULL) { // readonly attributes do not have a setter
+ return false;
+ }
+
+ dbusOutputStream << attributeDispatcherIterator->first;
+ getterDispatcher->dispatchDBusMessageAndAppendReply(dbusMessage, stub_, dbusOutputStream, clientId);
+ }
+ }
+
+ dbusOutputStream.endWriteVector();
+ */
+ dbusOutputStream.flush();
+ return getDBusConnection()->sendDBusMessage(dbusMessageReply);
+ }
+};
+
+template< class >
+struct DBusStubSignalHelper;
+
+template<template<class ...> class _In, class... _InArgs>
+struct DBusStubSignalHelper<_In<DBusInputStream, DBusOutputStream, _InArgs...>> {
+
+ static inline bool sendSignal(const char* objectPath,
+ const char* interfaceName,
+ const char* signalName,
+ const char* signalSignature,
+ const std::shared_ptr<DBusProxyConnection>& dbusConnection,
+ const _InArgs&... inArgs) {
+ DBusMessage dbusMessage = DBusMessage::createSignal(
+ objectPath,
+ interfaceName,
+ signalName,
+ signalSignature);
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream outputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
+ if (!success) {
+ return false;
+ }
+ outputStream.flush();
+ }
+
+ const bool dbusMessageSent = dbusConnection->sendDBusMessage(dbusMessage);
+ return dbusMessageSent;
+ }
+
+ template <typename _DBusStub = DBusStubAdapter>
+ static bool sendSignal(const _DBusStub &_stub,
+ const char *_name,
+ const char *_signature,
+ const _InArgs&... inArgs) {
+ return(sendSignal(_stub.getDBusAddress().getObjectPath().c_str(),
+ _stub.getDBusAddress().getInterface().c_str(),
+ _name,
+ _signature,
+ _stub.getDBusConnection(),
+ inArgs...));
+ }
+
+
+ template <typename _DBusStub = DBusStubAdapter>
+ static bool sendSignal(const char *_target,
+ const _DBusStub &_stub,
+ const char *_name,
+ const char *_signature,
+ const _InArgs&... inArgs) {
+ DBusMessage dbusMessage
+ = DBusMessage::createSignal(
+ _stub.getDBusAddress().getObjectPath().c_str(),
+ _stub.getDBusAddress().getInterface().c_str(),
+ _name,
+ _signature);
+
+ dbusMessage.setDestination(_target);
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusOutputStream outputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
+ if (!success) {
+ return false;
+ }
+ outputStream.flush();
+ }
+
+ return _stub.getDBusConnection()->sendDBusMessage(dbusMessage);
+ }
+};
+
+template< class, class >
+class DBusMethodStubDispatcher;
+
+template <
+ typename _StubClass,
+ template <class...> class _In, class... _InArgs>
+class DBusMethodStubDispatcher<_StubClass, _In<_InArgs...> >: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
+ public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef void (_StubClass::*_StubFunctor)(std::shared_ptr<CommonAPI::ClientId>, _InArgs...);
+
+ DBusMethodStubDispatcher(_StubFunctor stubFunctor):
+ stubFunctor_(stubFunctor) {
+ }
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ return handleDBusMessage(dbusMessage, stub, dbusStubAdapterHelper, typename make_sequence<sizeof...(_InArgs)>::type());
+ }
+
+ private:
+ template <int... _InArgIndices>
+ inline bool handleDBusMessage(const DBusMessage& dbusMessage,
+ const std::shared_ptr<_StubClass>& stub,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ index_sequence<_InArgIndices...>) const {
+ std::tuple<_InArgs...> argTuple;
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
+ if (!success)
+ return false;
+ }
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+
+ (stub.get()->*stubFunctor_)(clientId, std::move(std::get<_InArgIndices>(argTuple))...);
+
+ return true;
+ }
+
+ _StubFunctor stubFunctor_;
+};
+
+
+template< class, class, class>
+class DBusMethodWithReplyStubDispatcher;
+
+template <
+ typename _StubClass,
+ template <class...> class _In, class... _InArgs,
+ template <class...> class _Out, class... _OutArgs>
+class DBusMethodWithReplyStubDispatcher<_StubClass, _In<_InArgs...>, _Out<_OutArgs...> >:
+ public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
+ public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef std::function<void (_OutArgs...)> ReplyType_t;
+ typedef void (_StubClass::*_StubFunctor)(
+ std::shared_ptr<CommonAPI::ClientId>, _InArgs..., ReplyType_t);
+
+ DBusMethodWithReplyStubDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature, std::tuple<_InArgs..., _OutArgs...> _args):
+ stubFunctor_(stubFunctor),
+ dbusReplySignature_(dbusReplySignature),
+ args_(_args),
+ currentCall_(0) {
+ }
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ connection_ = dbusStubAdapterHelper.getDBusConnection();
+ return handleDBusMessage(
+ dbusMessage,
+ stub,
+ dbusStubAdapterHelper,
+ typename make_sequence_range<sizeof...(_InArgs), 0>::type(),
+ typename make_sequence_range<sizeof...(_OutArgs), sizeof...(_InArgs)>::type(), args_);
+ }
+
+ bool sendReply(CommonAPI::CallId_t _call, std::tuple<_OutArgs...> args = std::make_tuple()) {
+ return sendReplyInternal(_call, typename make_sequence_range<sizeof...(_OutArgs), 0>::type(), args);
+ }
+
+private:
+ template <int... _InArgIndices, int... _OutArgIndices>
+ inline bool handleDBusMessage(const DBusMessage& dbusMessage,
+ const std::shared_ptr<_StubClass>& stub,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ index_sequence<_InArgIndices...>,
+ index_sequence<_OutArgIndices...>,
+ std::tuple<_InArgs..., _OutArgs...> argTuple) {
+ if (sizeof...(_InArgs) > 0) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
+ if (!success)
+ return false;
+ }
+
+ std::shared_ptr<DBusClientId> clientId
+ = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+ DBusMessage reply = dbusMessage.createMethodReturn(dbusReplySignature_);
+
+ CommonAPI::CallId_t call;
+ {
+ std::lock_guard<std::mutex> lock(mutex_);
+ call = currentCall_++;
+ pending_[call] = reply;
+ }
+
+ (stub.get()->*stubFunctor_)(
+ clientId,
+ std::move(std::get<_InArgIndices>(argTuple))...,
+ [call, this](_OutArgs... _args){
+ this->sendReply(call, std::make_tuple(_args...));
+ }
+ );
+
+ return true;
+ }
+
+ template<int... _OutArgIndices>
+ bool sendReplyInternal(CommonAPI::CallId_t _call,
+ index_sequence<_OutArgIndices...>,
+ std::tuple<_OutArgs...> args) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ auto reply = pending_.find(_call);
+ if (reply != pending_.end()) {
+ if (sizeof...(_OutArgs) > 0) {
+ DBusOutputStream output(reply->second);
+ if (!DBusSerializableArguments<_OutArgs...>::serialize(
+ output, std::get<_OutArgIndices>(args)...)) {
+ pending_.erase(_call);
+ return false;
+ }
+ output.flush();
+ }
+ bool isSuccessful = connection_->sendDBusMessage(reply->second);
+ pending_.erase(_call);
+ return isSuccessful;
+ }
+ return false;
+ }
+
+ _StubFunctor stubFunctor_;
+ const char* dbusReplySignature_;
+ std::tuple<_InArgs..., _OutArgs...> args_;
+
+ CommonAPI::CallId_t currentCall_;
+ std::map<CommonAPI::CallId_t, DBusMessage> pending_;
+ std::mutex mutex_; // protects pending_
+
+ std::shared_ptr<DBusProxyConnection> connection_;
+};
+
+template< class, class, class, class >
+class DBusMethodWithReplyAdapterDispatcher;
+
+template <
+ typename _StubClass,
+ typename _StubAdapterClass,
+ template <class...> class _In, class... _InArgs,
+ template <class...> class _Out, class... _OutArgs>
+class DBusMethodWithReplyAdapterDispatcher<_StubClass, _StubAdapterClass, _In<_InArgs...>, _Out<_OutArgs...> >:
+ public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
+ public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef void (_StubAdapterClass::*_StubFunctor)(std::shared_ptr<CommonAPI::ClientId>, _InArgs..., _OutArgs&...);
+ typedef typename CommonAPI::Stub<typename DBusStubAdapterHelperType::StubAdapterType, typename _StubClass::RemoteEventType> StubType;
+
+ DBusMethodWithReplyAdapterDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature):
+ stubFunctor_(stubFunctor),
+ dbusReplySignature_(dbusReplySignature) {
+ }
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ std::tuple<_InArgs..., _OutArgs...> argTuple;
+ return handleDBusMessage(
+ dbusMessage,
+ stub,
+ dbusStubAdapterHelper,
+ typename make_sequence_range<sizeof...(_InArgs), 0>::type(),
+ typename make_sequence_range<sizeof...(_OutArgs), sizeof...(_InArgs)>::type(),argTuple);
+ }
+
+ private:
+ template <int... _InArgIndices, int... _OutArgIndices>
+ inline bool handleDBusMessage(const DBusMessage& dbusMessage,
+ const std::shared_ptr<_StubClass>& stub,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ index_sequence<_InArgIndices...>,
+ index_sequence<_OutArgIndices...>,
+ std::tuple<_InArgs..., _OutArgs...> argTuple) const {
+
+ if (sizeof...(_InArgs) > 0) {
+ DBusInputStream dbusInputStream(dbusMessage);
+ const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
+ if (!success)
+ return false;
+ }
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+
+ (stub->StubType::getStubAdapter().get()->*stubFunctor_)(clientId, std::move(std::get<_InArgIndices>(argTuple))..., std::get<_OutArgIndices>(argTuple)...);
+ DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusReplySignature_);
+
+ if (sizeof...(_OutArgs) > 0) {
+ DBusOutputStream dbusOutputStream(dbusMessageReply);
+ const bool success = DBusSerializableArguments<_OutArgs...>::serialize(dbusOutputStream, std::get<_OutArgIndices>(argTuple)...);
+ if (!success)
+ return false;
+
+ dbusOutputStream.flush();
+ }
+
+ return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
+ }
+
+ _StubFunctor stubFunctor_;
+ const char* dbusReplySignature_;
+};
+
+
+template <typename _StubClass, typename _AttributeType, typename _AttributeDepl = EmptyDeployment>
+class DBusGetAttributeStubDispatcher: public virtual DBusStubAdapterHelper<_StubClass>::StubDispatcher {
+ public:
+ typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
+ typedef const _AttributeType& (_StubClass::*GetStubFunctor)(std::shared_ptr<CommonAPI::ClientId>);
+
+ DBusGetAttributeStubDispatcher(GetStubFunctor _getStubFunctor, const char *_signature, _AttributeDepl *_depl = nullptr):
+ getStubFunctor_(_getStubFunctor),
+ signature_(_signature),
+ depl_(_depl) {
+ }
+
+ virtual ~DBusGetAttributeStubDispatcher() {};
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ return sendAttributeValueReply(dbusMessage, stub, dbusStubAdapterHelper);
+ }
+ protected:
+ virtual bool sendAttributeValueReply(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(signature_);
+ DBusOutputStream dbusOutputStream(dbusMessageReply);
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+
+ dbusOutputStream << CommonAPI::Deployable<_AttributeType, _AttributeDepl>((stub.get()->*getStubFunctor_)(clientId), depl_);
+ dbusOutputStream.flush();
+
+ return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
+ }
+
+
+ GetStubFunctor getStubFunctor_;
+ const char* signature_;
+ _AttributeDepl *depl_;
+};
+
+template <typename _StubClass, typename _AttributeType, typename _AttributeDepl = EmptyDeployment>
+class DBusSetAttributeStubDispatcher: public virtual DBusGetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl> {
+ public:
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
+ typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType;
+
+ typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::GetStubFunctor GetStubFunctor;
+ typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(std::shared_ptr<CommonAPI::ClientId>, _AttributeType);
+ typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)();
+
+ DBusSetAttributeStubDispatcher(GetStubFunctor getStubFunctor,
+ OnRemoteSetFunctor onRemoteSetFunctor,
+ OnRemoteChangedFunctor onRemoteChangedFunctor,
+ const char* dbusSignature,
+ _AttributeDepl *_depl = nullptr) :
+ DBusGetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>(getStubFunctor, dbusSignature, _depl),
+ onRemoteSetFunctor_(onRemoteSetFunctor),
+ onRemoteChangedFunctor_(onRemoteChangedFunctor) {
+ }
+
+ virtual ~DBusSetAttributeStubDispatcher() {};
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ bool attributeValueChanged;
+
+ if (!setAttributeValue(dbusMessage, stub, dbusStubAdapterHelper, attributeValueChanged))
+ return false;
+
+ if (attributeValueChanged)
+ notifyOnRemoteChanged(dbusStubAdapterHelper);
+
+ return true;
+ }
+
+ protected:
+ virtual _AttributeType retrieveAttributeValue(const DBusMessage& dbusMessage, bool& errorOccured) {
+ errorOccured = false;
+
+ DBusInputStream dbusInputStream(dbusMessage);
+ CommonAPI::Deployable<_AttributeType, _AttributeDepl> attributeValue(this->depl_);
+ dbusInputStream >> attributeValue;
+
+ if (dbusInputStream.hasError()) {
+ errorOccured = true;
+ }
+
+ return attributeValue.getValue();
+ }
+
+ inline bool setAttributeValue(const DBusMessage& dbusMessage,
+ const std::shared_ptr<_StubClass>& stub,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ bool& attributeValueChanged) {
+ bool errorOccured;
+ CommonAPI::Deployable<_AttributeType, _AttributeDepl> attributeValue(
+ retrieveAttributeValue(dbusMessage, errorOccured), this->depl_);
+
+ if(errorOccured) {
+ return false;
+ }
+
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+
+ attributeValueChanged = (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteSetFunctor_)(clientId, std::move(attributeValue.getValue()));
+
+ return this->sendAttributeValueReply(dbusMessage, stub, dbusStubAdapterHelper);
+ }
+
+ inline void notifyOnRemoteChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteChangedFunctor_)();
+ }
+
+ inline const _AttributeType& getAttributeValue(std::shared_ptr<CommonAPI::ClientId> clientId, const std::shared_ptr<_StubClass>& stub) {
+ return (stub.get()->*(this->getStubFunctor_))(clientId);
+ }
+
+ const OnRemoteSetFunctor onRemoteSetFunctor_;
+ const OnRemoteChangedFunctor onRemoteChangedFunctor_;
+};
+
+template <typename _StubClass, typename _AttributeType, typename _AttributeDepl = EmptyDeployment>
+class DBusSetObservableAttributeStubDispatcher: public virtual DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl> {
+ public:
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
+ typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType;
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::GetStubFunctor GetStubFunctor;
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::OnRemoteSetFunctor OnRemoteSetFunctor;
+ typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>::OnRemoteChangedFunctor OnRemoteChangedFunctor;
+ typedef typename CommonAPI::Stub<StubAdapterType, typename _StubClass::RemoteEventType> StubType;
+ typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&);
+
+ DBusSetObservableAttributeStubDispatcher(GetStubFunctor getStubFunctor,
+ OnRemoteSetFunctor onRemoteSetFunctor,
+ OnRemoteChangedFunctor onRemoteChangedFunctor,
+ FireChangedFunctor fireChangedFunctor,
+ const char* dbusSignature,
+ _AttributeDepl *_depl = nullptr)
+ : DBusGetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>(
+ getStubFunctor, dbusSignature, _depl),
+ DBusSetAttributeStubDispatcher<_StubClass, _AttributeType, _AttributeDepl>(
+ getStubFunctor, onRemoteSetFunctor, onRemoteChangedFunctor, dbusSignature, _depl),
+ fireChangedFunctor_(fireChangedFunctor) {
+ }
+
+ virtual ~DBusSetObservableAttributeStubDispatcher() {};
+
+ bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<_StubClass>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
+ bool attributeValueChanged;
+ if (!this->setAttributeValue(dbusMessage, stub, dbusStubAdapterHelper, attributeValueChanged))
+ return false;
+
+ if (attributeValueChanged) {
+ std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender()));
+ fireAttributeValueChanged(clientId, dbusStubAdapterHelper, stub);
+ this->notifyOnRemoteChanged(dbusStubAdapterHelper);
+ }
+ return true;
+ }
+protected:
+ virtual void fireAttributeValueChanged(std::shared_ptr<CommonAPI::ClientId> clientId,
+ DBusStubAdapterHelperType& dbusStubAdapterHelper,
+ const std::shared_ptr<_StubClass> stub) {
+ (stub->StubType::getStubAdapter().get()->*fireChangedFunctor_)(this->getAttributeValue(clientId, stub));
+ }
+
+ const FireChangedFunctor fireChangedFunctor_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSSTUBADAPTERHELPER_HPP_
diff --git a/include/CommonAPI/DBus/DBusTypeOutputStream.hpp b/include/CommonAPI/DBus/DBusTypeOutputStream.hpp
new file mode 100644
index 0000000..3ba7cf7
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusTypeOutputStream.hpp
@@ -0,0 +1,153 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef COMMONAPI_DBUS_DBUSTYPEOUTPUTSTREAM_H_
+#define COMMONAPI_DBUS_DBUSTYPEOUTPUTSTREAM_H_
+
+#include <CommonAPI/TypeOutputStream.hpp>
+
+namespace CommonAPI {
+namespace DBus {
+
+class DBusTypeOutputStream: public TypeOutputStream<DBusTypeOutputStream> {
+public:
+ DBusTypeOutputStream() : signature_("") {}
+
+ TypeOutputStream &writeType(const bool &_type) {
+ signature_.append("b");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const int8_t &) {
+ signature_.append("y");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const int16_t &) {
+ signature_.append("n");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const int32_t &) {
+ signature_.append("i");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const int64_t &) {
+ signature_.append("x");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const uint8_t &) {
+ signature_.append("y");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const uint16_t &) {
+ signature_.append("q");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const uint32_t &) {
+ signature_.append("u");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const uint64_t &) {
+ signature_.append("t");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const float &) {
+ signature_.append("d");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const double &) {
+ signature_.append("d");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType(const std::string &) {
+ signature_.append("s");
+ return (*this);
+ }
+
+ TypeOutputStream &writeType() {
+ signature_.append("ay");
+ return (*this);
+ }
+
+ TypeOutputStream &writeVersionType() {
+ signature_.append("(uu)");
+ return (*this);
+ }
+
+ template<typename... _Types>
+ TypeOutputStream &writeType(const Struct<_Types...> &_value) {
+ signature_.append("(");
+ const auto itsSize(std::tuple_size<std::tuple<_Types...>>::value);
+ StructTypeWriter<itsSize-1, DBusTypeOutputStream, Struct<_Types...>>{}
+ (*this, _value);
+ signature_.append(")");
+ return (*this);
+ }
+
+ template<class _PolymorphicStruct>
+ TypeOutputStream &writeType(const std::shared_ptr<_PolymorphicStruct> &_value) {
+ signature_.append("(");
+ _value->writeType(*this);
+ signature_.append(")");
+ return (*this);
+ }
+
+ template<typename... _Types>
+ TypeOutputStream &writeType(const Variant<_Types...> &_value) {
+ signature_.append("(yv)");
+ return (*this);
+ }
+
+ template<typename _Deployment, typename... _Types>
+ TypeOutputStream &writeType(const Variant<_Types...> &_value, const _Deployment *_depl) {
+ if (_depl != nullptr && _depl->isFreeDesktop_) {
+ signature_.append("v");
+ } else {
+ signature_.append("(yv)");
+ }
+ TypeOutputStreamWriteVisitor<DBusTypeOutputStream> typeVisitor(*this);
+ ApplyVoidVisitor<TypeOutputStreamWriteVisitor<DBusTypeOutputStream>,
+ Variant<_Types...>, _Types...>::visit(typeVisitor, _value);
+ return (*this);
+ }
+
+ template<typename _ElementType>
+ TypeOutputStream &writeType(const std::vector<_ElementType> &_value) {
+ signature_.append("a");
+ return (*this);
+ }
+
+ template<typename _KeyType, typename _ValueType, typename _HasherType>
+ TypeOutputStream &writeType(const std::unordered_map<_KeyType, _ValueType, _HasherType> &_value) {
+ signature_.append("a{");
+ _KeyType dummyKey;
+ writeType(dummyKey);
+ _ValueType dummyValue;
+ writeType(dummyValue);
+ signature_.append("}");
+ return (*this);
+ }
+
+ inline std::string getSignature() {
+ return std::move(signature_);
+ }
+
+private:
+ std::string signature_;
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSTYPEOUTPUTSTREAM_HPP_
diff --git a/include/CommonAPI/DBus/DBusTypes.hpp b/include/CommonAPI/DBus/DBusTypes.hpp
new file mode 100644
index 0000000..4c723c4
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusTypes.hpp
@@ -0,0 +1,37 @@
+// Copyright (C) 2014-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSTYPES_HPP_
+#define COMMONAPI_DBUS_DBUSTYPES_HPP_
+
+#include <string>
+#include <unordered_map>
+
+#include <dbus/dbus.h>
+
+namespace CommonAPI {
+namespace DBus {
+
+typedef std::unordered_map<std::string, bool> DBusPropertiesChangedDict;
+typedef std::unordered_map<std::string,
+ DBusPropertiesChangedDict> DBusInterfacesAndPropertiesDict;
+typedef std::unordered_map<std::string,
+ DBusInterfacesAndPropertiesDict> DBusObjectPathAndInterfacesDict;
+
+enum class DBusType_t {
+ SESSION = DBUS_BUS_SESSION,
+ SYSTEM = DBUS_BUS_SYSTEM,
+ STARTER = DBUS_BUS_STARTER,
+ WRAPPED
+};
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSTYPES_HPP_
diff --git a/include/CommonAPI/DBus/DBusUtils.hpp b/include/CommonAPI/DBus/DBusUtils.hpp
new file mode 100644
index 0000000..ba8826d
--- /dev/null
+++ b/include/CommonAPI/DBus/DBusUtils.hpp
@@ -0,0 +1,37 @@
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#if !defined (COMMONAPI_INTERNAL_COMPILATION)
+#error "Only <CommonAPI/CommonAPI.hpp> can be included directly, this file may disappear or change contents."
+#endif
+
+#ifndef COMMONAPI_DBUS_DBUSUTILS_HPP_
+#define COMMONAPI_DBUS_DBUSUTILS_HPP_
+
+#include <future>
+
+namespace CommonAPI {
+namespace DBus {
+
+//In gcc 4.4.1, the enumeration "std::future_status" is defined, but the return values of some functions
+//are bool where the same functions in gcc 4.6. return a value from this enum. This template is a way
+//to ensure compatibility for this issue.
+template<typename _FutureWaitType>
+inline bool checkReady(_FutureWaitType&);
+
+template<>
+inline bool checkReady<bool>(bool& returnedValue) {
+ return returnedValue;
+}
+
+template<>
+inline bool checkReady<std::future_status>(std::future_status& returnedValue) {
+ return returnedValue == std::future_status::ready;
+}
+
+} // namespace DBus
+} // namespace CommonAPI
+
+#endif // COMMONAPI_DBUS_DBUSUTILS_HPP_