diff options
author | Johannes Schanda <schanda@itestra.de> | 2013-06-06 11:26:02 +0200 |
---|---|---|
committer | Johannes Schanda <schanda@itestra.de> | 2013-06-06 11:26:02 +0200 |
commit | 4ada91c04f494ecbce0f910f0008a94262d845f2 (patch) | |
tree | 020cf01ef9c85fe09b74f8ebf183c11ec98ed02e | |
parent | fd34f6f90819ed1e9ac3e8525b155d06ce947805 (diff) | |
download | genivi-common-api-dbus-runtime-4ada91c04f494ecbce0f910f0008a94262d845f2.tar.gz |
Working client side for legacy dbus attributes as fixed types and unions
in franca
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | src/CommonAPI/DBus/DBusAttribute.h | 461 | ||||
-rw-r--r-- | src/CommonAPI/DBus/DBusEvent.h | 45 | ||||
-rw-r--r-- | src/CommonAPI/DBus/DBusLegacyVariant.h | 130 | ||||
-rw-r--r-- | src/CommonAPI/DBus/DBusProxyBase.h | 23 | ||||
-rw-r--r-- | src/CommonAPI/DBus/DBusProxyHelper.h | 157 | ||||
-rw-r--r-- | src/test/DBusTestUtils.h | 5 |
7 files changed, 759 insertions, 65 deletions
diff --git a/Makefile.am b/Makefile.am index df4a358..f0af9f9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -89,7 +89,8 @@ CommonAPI_DBus_include_HEADERS = \ src/CommonAPI/DBus/DBusServiceStatusEvent.h \ src/CommonAPI/DBus/DBusStubAdapter.h \ src/CommonAPI/DBus/DBusStubAdapterHelper.h \ - src/CommonAPI/DBus/DBusUtils.h + src/CommonAPI/DBus/DBusUtils.h \ + src/CommonAPI/DBus/DBusLegacyVariant.h pkgconfigdir = ${libdir}/pkgconfig pkgconfig_DATA = CommonAPI-DBus.pc diff --git a/src/CommonAPI/DBus/DBusAttribute.h b/src/CommonAPI/DBus/DBusAttribute.h index 4844b87..89cc61a 100644 --- a/src/CommonAPI/DBus/DBusAttribute.h +++ b/src/CommonAPI/DBus/DBusAttribute.h @@ -9,6 +9,8 @@ #include "DBusProxyHelper.h" #include "DBusEvent.h" +#include <stdint.h> +#include "DBusLegacyVariant.h" #include <cassert> @@ -32,7 +34,8 @@ class DBusReadonlyAttribute: public _AttributeType { } void getValue(CallStatus& callStatus, ValueType& value) const { - DBusProxyHelper<DBusSerializableArguments<>, + + DBusProxyHelper<DBusSerializableArguments<>, DBusSerializableArguments<ValueType> >::callMethodWithReply(dbusProxy_, getMethodName_, "", callStatus, value); } @@ -46,6 +49,132 @@ class DBusReadonlyAttribute: public _AttributeType { const char* getMethodName_; }; +template <typename _AttributeType, typename _DBusProxyType = DBusProxy> +class DBusFreedesktopReadonlyAttribute: public _AttributeType { + public: + typedef typename _AttributeType::ValueType ValueType; + typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; + + DBusFreedesktopReadonlyAttribute(_DBusProxyType& dbusProxy, const char* interfaceName, const char* propertyName): + dbusProxy_(dbusProxy), + interfaceName_(interfaceName), + propertyName_(propertyName) + { + assert(interfaceName); + assert(propertyName); + } + + void getValue(CallStatus& callStatus, ValueType& value) const { + DBusLegacyVariantWrapper<Variant<ValueType> > variantVal; + DBusProxyHelper<DBusSerializableArguments<std::string, std::string>, + DBusSerializableArguments<DBusLegacyVariantWrapper<Variant<ValueType> > > >::callMethodWithReply( + dbusProxy_, + dbusProxy_.getDBusBusName().c_str(), + dbusProxy_.getDBusObjectPath().c_str(), + "org.freedesktop.DBus.Properties", + "Get", + "ss", + std::string(interfaceName_), + std::string(propertyName_), + callStatus, + variantVal); + value = variantVal.contained_.template get<ValueType>(); + + } + + std::future<CallStatus> getValueAsync(AttributeAsyncCallback attributeAsyncCallback) { + return DBusProxyHelper<DBusSerializableArguments<std::string, std::string>, + DBusSerializableArguments<DBusLegacyVariantWrapper<Variant<ValueType> > > >::callMethodAsync( + dbusProxy_, + dbusProxy_.getDBusBusName().c_str(), + dbusProxy_.getDBusObjectPath().c_str(), + "org.freedesktop.DBus.Properties", + "Get", + "ss", + std::string(interfaceName_), + std::string(propertyName_), + std::bind( + &CommonAPI::DBus::DBusFreedesktopReadonlyAttribute<_AttributeType>::AsyncVariantStripper, + this, + std::placeholders::_1, + std::placeholders::_2, + std::move(attributeAsyncCallback))); + } + + void AsyncVariantStripper(const CommonAPI::CallStatus& status, + const DBusLegacyVariantWrapper<Variant<ValueType> >& value, + AttributeAsyncCallback attributeAsyncCallback) { + attributeAsyncCallback(status, value.contained_.template get<ValueType>()); + } + + protected: + _DBusProxyType& dbusProxy_; + const char* interfaceName_; + const char* propertyName_; +}; + +template <typename _AttributeType, typename _DBusProxyType = DBusProxy> +class DBusFreedesktopUnionReadonlyAttribute: public _AttributeType { + public: + typedef typename _AttributeType::ValueType ValueType; + typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; + + DBusFreedesktopUnionReadonlyAttribute(_DBusProxyType& dbusProxy, const char* interfaceName, const char* propertyName): + dbusProxy_(dbusProxy), + interfaceName_(interfaceName), + propertyName_(propertyName) + { + assert(interfaceName); + assert(propertyName); + } + + void getValue(CallStatus& callStatus, ValueType& value) const { + DBusLegacyVariantWrapper<ValueType> variantVal(value); + DBusProxyHelper<DBusSerializableArguments<std::string, std::string>, + DBusSerializableArguments<DBusLegacyVariantWrapper<ValueType> > >::callMethodWithReply( + dbusProxy_, + dbusProxy_.getDBusBusName().c_str(), + dbusProxy_.getDBusObjectPath().c_str(), + "org.freedesktop.DBus.Properties", + "Get", + "ss", + std::string(interfaceName_), + std::string(propertyName_), + callStatus, + variantVal); + value = variantVal.contained_; + } + + std::future<CallStatus> getValueAsync(AttributeAsyncCallback attributeAsyncCallback) { + return DBusProxyHelper<DBusSerializableArguments<std::string, std::string>, + DBusSerializableArguments<DBusLegacyVariantWrapper<ValueType> > >::callMethodAsync( + dbusProxy_, + dbusProxy_.getDBusBusName().c_str(), + dbusProxy_.getDBusObjectPath().c_str(), + "org.freedesktop.DBus.Properties", + "Get", + "ss", + std::string(interfaceName_), + std::string(propertyName_), + std::bind( + &CommonAPI::DBus::DBusFreedesktopUnionReadonlyAttribute<_AttributeType>::AsyncVariantStripper, + this, + std::placeholders::_1, + std::placeholders::_2, + std::move(attributeAsyncCallback))); + } + + void AsyncVariantStripper(const CommonAPI::CallStatus& status, + const DBusLegacyVariantWrapper<ValueType>& value, + AttributeAsyncCallback attributeAsyncCallback) { + attributeAsyncCallback(status, value.contained_); + } + + protected: + _DBusProxyType& dbusProxy_; + const char* interfaceName_; + const char* propertyName_; +}; template <typename _AttributeType, typename _DBusProxyType = DBusProxy> class DBusAttribute: public DBusReadonlyAttribute<_AttributeType> { @@ -61,16 +190,17 @@ class DBusAttribute: public DBusReadonlyAttribute<_AttributeType> { assert(setMethodSignature); } - void setValue(const ValueType& requestValue, CallStatus& callStatus, ValueType& responseValue) { - DBusProxyHelper<DBusSerializableArguments<ValueType>, - DBusSerializableArguments<ValueType> >::callMethodWithReply( - this->dbusProxy_, - setMethodName_, - setMethodSignature_, - requestValue, - callStatus, - responseValue); - } + void setValue(const ValueType& requestValue, CallStatus& callStatus, ValueType& responseValue) { + DBusProxyHelper<DBusSerializableArguments<ValueType>, + DBusSerializableArguments<ValueType> >::callMethodWithReply( + this->dbusProxy_, + setMethodName_, + setMethodSignature_, + requestValue, + callStatus, + responseValue); + } + std::future<CallStatus> setValueAsync(const ValueType& requestValue, AttributeAsyncCallback attributeAsyncCallback) { return DBusProxyHelper<DBusSerializableArguments<ValueType>, @@ -87,6 +217,131 @@ class DBusAttribute: public DBusReadonlyAttribute<_AttributeType> { const char* setMethodSignature_; }; +template <typename _AttributeType, typename _DBusProxyType = DBusProxy> +class DBusFreedesktopAttribute: public DBusFreedesktopReadonlyAttribute<_AttributeType, _DBusProxyType> { + public: + typedef typename _AttributeType::ValueType ValueType; + typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; + + DBusFreedesktopAttribute(_DBusProxyType& dbusProxy, + const char* interfaceName, + const char* propertyName) : + DBusFreedesktopReadonlyAttribute<_AttributeType>(dbusProxy, interfaceName, propertyName) + { + assert(interfaceName); + assert(propertyName); + } + + + void setValue(const ValueType& requestValue, CallStatus& callStatus, ValueType& responseValue) { + DBusLegacyVariantWrapper<Variant<ValueType> > variantVal; + variantVal.contained_ = Variant<ValueType>(requestValue); + DBusProxyHelper<DBusSerializableArguments<std::string, std::string, DBusLegacyVariantWrapper<Variant<ValueType> > >, + DBusSerializableArguments<> >::callMethodWithReply( + DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_, + DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_.getDBusBusName().c_str(), + DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_.getDBusObjectPath().c_str(), + "org.freedesktop.DBus.Properties", + "Set", + "ssv", + std::string(DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_), + std::string(DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_), + variantVal, + callStatus); + responseValue = requestValue; + } + + std::future<CallStatus> setValueAsync(const ValueType& requestValue, AttributeAsyncCallback attributeAsyncCallback) { + DBusLegacyVariantWrapper<Variant<ValueType> > variantVal; + variantVal.contained_ = Variant<ValueType>(requestValue); + return DBusProxyHelper<DBusSerializableArguments<std::string, std::string, DBusLegacyVariantWrapper<Variant<ValueType> > >, + DBusSerializableArguments<> >::callMethodAsync( + DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_, + DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_.getDBusBusName().c_str(), + DBusFreedesktopReadonlyAttribute<_AttributeType>::dbusProxy_.getDBusObjectPath().c_str(), + "org.freedesktop.DBus.Properties", + "Set", + "ssv", + std::string(DBusFreedesktopReadonlyAttribute<_AttributeType>::interfaceName_), + std::string(DBusFreedesktopReadonlyAttribute<_AttributeType>::propertyName_), + variantVal, + std::bind( + &CommonAPI::DBus::DBusFreedesktopAttribute<_AttributeType>::AsyncVariantStripper, + this, + std::placeholders::_1, + variantVal, + std::move(attributeAsyncCallback))); + } + + void AsyncVariantStripper(const CommonAPI::CallStatus& status, + const DBusLegacyVariantWrapper<Variant<ValueType> >& value, + AttributeAsyncCallback attributeAsyncCallback) { + attributeAsyncCallback(status, value.contained_.template get<ValueType>()); + } +}; + +template <typename _AttributeType, typename _DBusProxyType = DBusProxy> +class DBusFreedesktopUnionAttribute: public DBusFreedesktopUnionReadonlyAttribute<_AttributeType, _DBusProxyType> { + public: + typedef typename _AttributeType::ValueType ValueType; + typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; + + DBusFreedesktopUnionAttribute(_DBusProxyType& dbusProxy, + const char* interfaceName, + const char* propertyName) : + DBusFreedesktopUnionReadonlyAttribute<_AttributeType>(dbusProxy, interfaceName, propertyName) + { + assert(interfaceName); + assert(propertyName); + } + + + void setValue(const ValueType& requestValue, CallStatus& callStatus, ValueType& responseValue) { + DBusLegacyVariantWrapper<ValueType> variantVal; + variantVal.contained_ = requestValue; + DBusProxyHelper<DBusSerializableArguments<std::string, std::string, DBusLegacyVariantWrapper<ValueType> >, + DBusSerializableArguments<> >::callMethodWithReply( + DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_, + DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_.getDBusBusName().c_str(), + DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_.getDBusObjectPath().c_str(), + "org.freedesktop.DBus.Properties", + "Set", + "ssv", + std::string(DBusFreedesktopUnionReadonlyAttribute<_AttributeType>::interfaceName_), + std::string(DBusFreedesktopUnionReadonlyAttribute<_AttributeType>::propertyName_), + variantVal, + callStatus); + responseValue = requestValue; + } + + std::future<CallStatus> setValueAsync(const ValueType& requestValue, AttributeAsyncCallback attributeAsyncCallback) { + DBusLegacyVariantWrapper<ValueType> variantVal; + variantVal.contained_ = requestValue; + return DBusProxyHelper<DBusSerializableArguments<std::string, std::string, DBusLegacyVariantWrapper<ValueType> >, + DBusSerializableArguments<> >::callMethodAsync( + DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_, + DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_.getDBusBusName().c_str(), + DBusFreedesktopUnionAttribute<_AttributeType>::dbusProxy_.getDBusObjectPath().c_str(), + "org.freedesktop.DBus.Properties", + "Set", + "ssv", + std::string(DBusFreedesktopUnionReadonlyAttribute<_AttributeType>::interfaceName_), + std::string(DBusFreedesktopUnionReadonlyAttribute<_AttributeType>::propertyName_), + variantVal, + std::bind( + &CommonAPI::DBus::DBusFreedesktopUnionAttribute<_AttributeType>::AsyncVariantStripper, + this, + std::placeholders::_1, + variantVal, + std::move(attributeAsyncCallback))); + } + + void AsyncVariantStripper(const CommonAPI::CallStatus& status, + const DBusLegacyVariantWrapper<ValueType>& value, + AttributeAsyncCallback attributeAsyncCallback) { + attributeAsyncCallback(status, value.contained_); + } +}; template <typename _AttributeType, typename _DBusProxyType = DBusProxy> class DBusObservableAttribute: public _AttributeType { @@ -109,6 +364,190 @@ class DBusObservableAttribute: public _AttributeType { DBusEvent<ChangedEvent> changedEvent_; }; +template< class, class > +class LegacyEvent; + +template <template <class...> class _Type, class _Types, typename _DBusProxy> +class LegacyEvent<_Type<_Types>, _DBusProxy> : public _Type<_Types> { +public: + typedef _Types ValueType; + typedef _Type<ValueType> CommonAPIEvent; + typedef typename CommonAPIEvent::CancellableListener CancellableListener; + + LegacyEvent(_DBusProxy& dbusProxy, const char* interfaceName, const char* propName) : + interfaceName_(interfaceName), + propertyName_(propName), + subSet_(false), + internalEvent_(dbusProxy, "PropertiesChanged", "sa{sv}as", dbusProxy.getDBusObjectPath().c_str(), "org.freedesktop.DBus.Properties") { + } + +protected: + void onInternalEvent(const std::string& interface, + const std::unordered_map<std::string, DBusLegacyVariantWrapper<Variant<_Types> > >& props, + const std::vector<std::string>& invalid) { + if (std::string(interfaceName_) == interface) { + auto mapIter = props.find(std::string(propertyName_)); + if (mapIter != props.end()) { + notifyListeners(mapIter->second.contained_.template get<ValueType>()); + } + } + } + + void onFirstListenerAdded(const CancellableListener& listener) { + sub = internalEvent_.subscribe( + std::bind( + &LegacyEvent<_Type<_Types>, _DBusProxy>::onInternalEvent, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3)); + subSet_ = true; + } + + void onLastListenerRemoved(const CancellableListener& listener) { + if (subSet_) { + internalEvent_.unsubscribe(sub); + subSet_ = false; + } + } + + typedef DBusLegacyVariantWrapper<Variant<_Types> > ContainedVariant; + typedef std::unordered_map<std::string, ContainedVariant> PropertyMap; + typedef std::vector<std::string> InvalidArray; + typedef Event<std::string, PropertyMap, InvalidArray> SignalEvent; + + DBusEvent<SignalEvent> internalEvent_; + + typename DBusEvent<SignalEvent>::Subscription sub; + + const char* interfaceName_; + const char* propertyName_; + + bool subSet_; + +}; + +template <typename _AttributeType, typename _DBusProxyType = DBusProxy> +class DBusFreedesktopObservableAttribute: public _AttributeType { + public: + typedef typename _AttributeType::ValueType ValueType; + typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; + typedef typename _AttributeType::ChangedEvent ChangedEvent; + + template <typename... _AttributeTypeArguments> + DBusFreedesktopObservableAttribute(_DBusProxyType& dbusProxy, + const char* interfaceName, + const char* propertyName, + _AttributeTypeArguments... arguments): + _AttributeType(dbusProxy, interfaceName, propertyName, arguments...), + propertyName_(propertyName), + interfaceName_(interfaceName), + externalChangedEvent_(dbusProxy, interfaceName, propertyName) { + + } + + ChangedEvent& getChangedEvent() { + return externalChangedEvent_; + } + + protected: + LegacyEvent<ChangedEvent, _DBusProxyType> externalChangedEvent_; + const char * propertyName_; + const char * interfaceName_; +}; + +template< class, class > +class LegacyUnionEvent; + +template <template <class...> class _Type, class _Types, typename _DBusProxy> +class LegacyUnionEvent<_Type<_Types>, _DBusProxy> : public _Type<_Types> { +public: + typedef _Types ValueType; + typedef _Type<ValueType> CommonAPIEvent; + typedef typename CommonAPIEvent::CancellableListener CancellableListener; + + LegacyUnionEvent(_DBusProxy& dbusProxy, const char* interfaceName, const char* propName) : + interfaceName_(interfaceName), + propertyName_(propName), + subSet_(false), + internalEvent_(dbusProxy, "PropertiesChanged", "sa{sv}as", dbusProxy.getDBusObjectPath().c_str(), "org.freedesktop.DBus.Properties") { + } + +protected: + void onInternalEvent(const std::string& interface, + const std::unordered_map<std::string, DBusLegacyVariantWrapper<ValueType> >& props, + const std::vector<std::string>& invalid) { + if (std::string(interfaceName_) == interface) { + auto mapIter = props.find(std::string(propertyName_)); + if (mapIter != props.end()) { + notifyListeners(mapIter->second.contained_); + } + } + } + + void onFirstListenerAdded(const CancellableListener& listener) { + sub = internalEvent_.subscribe( + std::bind( + &LegacyUnionEvent<_Type<_Types>, _DBusProxy>::onInternalEvent, + this, + std::placeholders::_1, + std::placeholders::_2, + std::placeholders::_3)); + subSet_ = true; + } + + void onLastListenerRemoved(const CancellableListener& listener) { + if (subSet_) { + internalEvent_.unsubscribe(sub); + subSet_ = false; + } + } + + typedef DBusLegacyVariantWrapper<ValueType> ContainedVariant; + typedef std::unordered_map<std::string, ContainedVariant> PropertyMap; + typedef std::vector<std::string> InvalidArray; + typedef Event<std::string, PropertyMap, InvalidArray> SignalEvent; + + DBusEvent<SignalEvent> internalEvent_; + + typename DBusEvent<SignalEvent>::Subscription sub; + + const char* interfaceName_; + const char* propertyName_; + + bool subSet_; + +}; + +template <typename _AttributeType, typename _DBusProxyType = DBusProxy> +class DBusFreedesktopUnionObservableAttribute: public _AttributeType { + public: + typedef typename _AttributeType::ValueType ValueType; + typedef typename _AttributeType::AttributeAsyncCallback AttributeAsyncCallback; + typedef typename _AttributeType::ChangedEvent ChangedEvent; + + template <typename... _AttributeTypeArguments> + DBusFreedesktopUnionObservableAttribute(_DBusProxyType& dbusProxy, + const char* interfaceName, + const char* propertyName, + _AttributeTypeArguments... arguments): + _AttributeType(dbusProxy, interfaceName, propertyName, arguments...), + propertyName_(propertyName), + interfaceName_(interfaceName), + externalChangedEvent_(dbusProxy, interfaceName, propertyName) { + + } + + ChangedEvent& getChangedEvent() { + return externalChangedEvent_; + } + + protected: + LegacyUnionEvent<ChangedEvent, _DBusProxyType> externalChangedEvent_; + const char * propertyName_; + const char * interfaceName_; +}; + } // namespace DBus } // namespace CommonAPI diff --git a/src/CommonAPI/DBus/DBusEvent.h b/src/CommonAPI/DBus/DBusEvent.h index 46ba4ab..561fa04 100644 --- a/src/CommonAPI/DBus/DBusEvent.h +++ b/src/CommonAPI/DBus/DBusEvent.h @@ -30,10 +30,26 @@ class DBusEvent: public _EventType, public DBusProxyConnection::DBusSignalHandle dbusProxy_(dbusProxy), eventName_(eventName), eventSignature_(eventSignature) { - assert(eventName); - assert(eventSignature); + interfaceName_ = dbusProxy.getInterfaceName().c_str(); + objectPath_ = dbusProxy_.getDBusObjectPath().c_str(); + assert(eventName_); + assert(eventSignature_); + assert(objectPath_); + assert(interfaceName_); } + DBusEvent(_DBusProxy& dbusProxy, const char* eventName, const char* eventSignature, const char* objPath, const char* interfaceName) : + dbusProxy_(dbusProxy), + eventName_(eventName), + eventSignature_(eventSignature), + objectPath_(objPath), + interfaceName_(interfaceName) { + assert(eventName); + assert(eventSignature); + assert(objPath); + assert(interfaceName); + } + virtual ~DBusEvent() { if (this->hasListeners()) dbusProxy_.removeSignalMemberHandler(subscription_); @@ -45,30 +61,36 @@ class DBusEvent: public _EventType, public DBusProxyConnection::DBusSignalHandle protected: virtual void onFirstListenerAdded(const CancellableListener&) { - subscription_ = dbusProxy_.addSignalMemberHandler(eventName_, eventSignature_, this); + subscription_ = dbusProxy_.addSignalMemberHandler(objectPath_, interfaceName_, + eventName_, eventSignature_, this); } virtual void onLastListenerRemoved(const CancellableListener&) { dbusProxy_.removeSignalMemberHandler(subscription_); } - private: template <typename ... _Arguments> inline SubscriptionStatus unpackArgumentsAndHandleSignalDBusMessage(const DBusMessage& dbusMessage, std::tuple<_Arguments...> argTuple) { return handleSignalDBusMessage(dbusMessage, std::move(argTuple), typename make_sequence<sizeof...(_Arguments)>::type()); } - template <typename ... _Arguments, int... _ArgIndices> - inline SubscriptionStatus handleSignalDBusMessage(const DBusMessage& dbusMessage, std::tuple<_Arguments...> argTuple, index_sequence<_ArgIndices...>) { - DBusInputStream dbusInputStream(dbusMessage); - const bool success = DBusSerializableArguments<_Arguments...>::deserialize(dbusInputStream, std::get<_ArgIndices>(argTuple)...); - // Continue subscription if deserialization failed - return success ? this->notifyListeners(std::get<_ArgIndices>(argTuple)...) : SubscriptionStatus::RETAIN; - } + template<typename ... _Arguments, int ... _ArgIndices> + inline SubscriptionStatus handleSignalDBusMessage(const DBusMessage& dbusMessage, + std::tuple<_Arguments...> argTuple, + index_sequence<_ArgIndices...>) { + DBusInputStream dbusInputStream(dbusMessage); + const bool success = DBusSerializableArguments<_Arguments...>::deserialize( + dbusInputStream, + std::get<_ArgIndices>(argTuple)...); + // Continue subscription if deserialization failed + return success ? this->notifyListeners(std::get<_ArgIndices>(argTuple)...) : SubscriptionStatus::RETAIN; + } _DBusProxy& dbusProxy_; const char* eventName_; const char* eventSignature_; + const char* interfaceName_; + const char* objectPath_; DBusProxyConnection::DBusSignalHandlerToken subscription_; }; @@ -76,3 +98,4 @@ class DBusEvent: public _EventType, public DBusProxyConnection::DBusSignalHandle } // namespace CommonAPI #endif // COMMONAPI_DBUS_DBUS_EVENT_H_ + diff --git a/src/CommonAPI/DBus/DBusLegacyVariant.h b/src/CommonAPI/DBus/DBusLegacyVariant.h new file mode 100644 index 0000000..1403dea --- /dev/null +++ b/src/CommonAPI/DBus/DBusLegacyVariant.h @@ -0,0 +1,130 @@ +/* Copyright (C) 2013 BMW Group + * Author: Manfred Bathelt (manfred.bathelt@bmw.de) + * Author: Juergen Gehring (juergen.gehring@bmw.de) + * 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 DBUSLEGACYVARIANT_H_ +#define DBUSLEGACYVARIANT_H_ + +#include <CommonAPI/SerializableVariant.h> +#include "DBusOutputStream.h" +#include "DBusInputStream.h" + +namespace CommonAPI { +namespace DBus { + +template<class Visitor, class Variant, typename ... _Types> +struct ApplyIndexForStringVisitor +; + +template<class Visitor, class Variant> +struct ApplyIndexForStringVisitor<Visitor, Variant> { + static const uint8_t index = 0; + + static uint8_t visit(Visitor&, const Variant&) { + //won't be called + assert(false); + return 0; + } +}; + +template<class Visitor, class Variant, typename _Type, typename ... _Types> +struct ApplyIndexForStringVisitor<Visitor, Variant, _Type, _Types...> { + static const uint8_t index = ApplyIndexForStringVisitor<Visitor, Variant, + _Types...>::index + 1; + + static uint8_t visit(Visitor& visitor, const Variant& var) { + DBusTypeOutputStream typeStream_; + TypeWriter<_Type>::writeType(typeStream_); + const std::string sig = typeStream_.retrieveSignature(); + if (visitor.template operator()<_Type>(sig)) { + return index; + } else { + return ApplyIndexForStringVisitor<Visitor, Variant, _Types...>::visit(visitor, + var); + } + } +}; + +template<typename ... _Types> +struct TypeOutputStreamCompareVisitor { +public: + TypeOutputStreamCompareVisitor(const std::string& type) : + type_(type) { + } + + template<typename _Type> + bool operator()(const std::string& ntype) const { + int comp = type_.compare(0, type_.size(), ntype); + if (comp == 0) { + return true; + } else { + return false; + } + } +private: + const std::string type_; + +}; + +template< class > +class DBusLegacyVariantWrapper; + +template < + template <class...> class _Type, class... _Types> +class DBusLegacyVariantWrapper<_Type<_Types...>> { +public: + + DBusLegacyVariantWrapper() : + contained_() { + } + + DBusLegacyVariantWrapper(CommonAPI::Variant<_Types...>& cont) : + contained_(cont) { + } + + + uint8_t getIndexForType(const std::string& type) const { + TypeOutputStreamCompareVisitor<_Types...> visitor(type); + return ApplyIndexForStringVisitor<TypeOutputStreamCompareVisitor<_Types...>, Variant<_Types...>, _Types...>::visit( + visitor, contained_); + } + + CommonAPI::Variant<_Types...> contained_; +}; + +} /* namespace DBus */ + +//template <template <class...> class _Type, class... _Types> +template <typename ... _Types> +inline OutputStream& operator<<(OutputStream& outputStream, const DBus::DBusLegacyVariantWrapper<Variant<_Types...> >& serializableVariant) { + DBus::DBusTypeOutputStream typeOutputStream; + serializableVariant.contained_.writeToTypeOutputStream(typeOutputStream); + std::string sigStr = typeOutputStream.retrieveSignature(); + uint8_t length = (uint8_t) sigStr.length(); + assert(length < 256); + outputStream << length; + outputStream.writeRawData(sigStr.c_str(), length + 1); + serializableVariant.contained_.writeToOutputStream(outputStream); + return outputStream; +} + +//template <template <class...> class _Type, class... _Types> +template <typename ... _Types> +inline InputStream& operator>>(InputStream& inputStream, DBus::DBusLegacyVariantWrapper<Variant<_Types...> >& serializableVariant) { + uint8_t signatureLength; + inputStream.readValue(signatureLength); + assert(signatureLength < 256); + char * buf = inputStream.readRawData(signatureLength + 1); + std::string sigString; + sigString.assign(buf, buf + signatureLength); + uint8_t containedTypeIndex = serializableVariant.getIndexForType(sigString); + serializableVariant.contained_.readFromInputStream(containedTypeIndex, inputStream); + return inputStream; +} + +} /* namespace CommonAPI */ + +#endif /* DBUSLEGACYVARIANT_H_ */ diff --git a/src/CommonAPI/DBus/DBusProxyBase.h b/src/CommonAPI/DBus/DBusProxyBase.h index 686c878..454d03f 100644 --- a/src/CommonAPI/DBus/DBusProxyBase.h +++ b/src/CommonAPI/DBus/DBusProxyBase.h @@ -41,6 +41,13 @@ class DBusProxyBase: public virtual CommonAPI::Proxy { const std::string& signalSignature, DBusProxyConnection::DBusSignalHandler* dbusSignalHandler); + inline DBusProxyConnection::DBusSignalHandlerToken addSignalMemberHandler( + const std::string& objectPath, + const std::string& interfaceName, + const std::string& signalName, + const std::string& signalSignature, + DBusProxyConnection::DBusSignalHandler* dbusSignalHandler); + inline void removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& dbusSignalHandlerToken); protected: @@ -60,7 +67,7 @@ DBusProxyConnection::DBusSignalHandlerToken DBusProxyBase::addSignalMemberHandle const std::string& signalName, const std::string& signalSignature, DBusProxyConnection::DBusSignalHandler* dbusSignalHandler) { - return dbusConnection_->addSignalMemberHandler( + return addSignalMemberHandler( getDBusObjectPath(), getInterfaceName(), signalName, @@ -68,6 +75,20 @@ DBusProxyConnection::DBusSignalHandlerToken DBusProxyBase::addSignalMemberHandle dbusSignalHandler); } +DBusProxyConnection::DBusSignalHandlerToken DBusProxyBase::addSignalMemberHandler( + const std::string& objectPath, + const std::string& interfaceName, + const std::string& signalName, + const std::string& signalSignature, + DBusProxyConnection::DBusSignalHandler* dbusSignalHandler) { + return dbusConnection_->addSignalMemberHandler( + objectPath, + interfaceName, + signalName, + signalSignature, + dbusSignalHandler); +} + void DBusProxyBase::removeSignalMemberHandler(const DBusProxyConnection::DBusSignalHandlerToken& dbusSignalHandlerToken) { return dbusConnection_->removeSignalMemberHandler(dbusSignalHandlerToken); } diff --git a/src/CommonAPI/DBus/DBusProxyHelper.h b/src/CommonAPI/DBus/DBusProxyHelper.h index 5483d2b..48433d7 100644 --- a/src/CommonAPI/DBus/DBusProxyHelper.h +++ b/src/CommonAPI/DBus/DBusProxyHelper.h @@ -59,6 +59,66 @@ struct DBusProxyHelper<_In<_InArgs...>, _Out<_OutArgs...>> { } template <typename _DBusProxy = DBusProxy> + static void callMethodWithReply( + const _DBusProxy& dbusProxy, + DBusMessage& dbusMethodCall, + const _InArgs&... inArgs, + CommonAPI::CallStatus& callStatus, + _OutArgs&... outArgs) { + + if (sizeof...(_InArgs) > 0) { + DBusOutputStream outputStream(dbusMethodCall); + const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...); + if (!success) { + callStatus = CallStatus::OUT_OF_MEMORY; + return; + } + outputStream.flush(); + } + + DBusError dbusError; + DBusMessage dbusMessageReply = dbusProxy.getDBusConnection()->sendDBusMessageWithReplyAndBlock(dbusMethodCall, dbusError); + if (dbusError || !dbusMessageReply.isMethodReturnType()) { + callStatus = CallStatus::REMOTE_ERROR; + return; + } + + if (sizeof...(_OutArgs) > 0) { + DBusInputStream inputStream(dbusMessageReply); + const bool success = DBusSerializableArguments<_OutArgs...>::deserialize(inputStream, outArgs...); + if (!success) { + callStatus = CallStatus::REMOTE_ERROR; + return; + } + } + callStatus = CallStatus::SUCCESS; + } + + template <typename _DBusProxy = DBusProxy> + static void callMethodWithReply( + const _DBusProxy& dbusProxy, + const char* busName, + const char* objPath, + const char* interfaceName, + const char* methodName, + const char* methodSignature, + const _InArgs&... inArgs, + CommonAPI::CallStatus& callStatus, + _OutArgs&... outArgs) { + if (dbusProxy.isAvailableBlocking()) { + DBusMessage dbusMethodCall = DBusMessage::createMethodCall( + busName, + objPath, + interfaceName, + methodName, + methodSignature); + callMethodWithReply(dbusProxy, dbusMethodCall, inArgs..., callStatus, outArgs...); + } else { + callStatus = CallStatus::NOT_AVAILABLE; + } + } + + template <typename _DBusProxy = DBusProxy> static void callMethodWithReply( const _DBusProxy& dbusProxy, const char* methodName, @@ -71,50 +131,76 @@ struct DBusProxyHelper<_In<_InArgs...>, _Out<_OutArgs...>> { DBusMessage dbusMethodCall = dbusProxy.createMethodCall(methodName, methodSignature); - if (sizeof...(_InArgs) > 0) { - DBusOutputStream outputStream(dbusMethodCall); - const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...); - if (!success) { - callStatus = CallStatus::OUT_OF_MEMORY; - return; - } - outputStream.flush(); - } + callMethodWithReply(dbusProxy, dbusMethodCall, inArgs..., callStatus, outArgs...); - DBusError dbusError; - DBusMessage dbusMessageReply = dbusProxy.getDBusConnection()->sendDBusMessageWithReplyAndBlock(dbusMethodCall, dbusError); - if (dbusError || !dbusMessageReply.isMethodReturnType()) { - callStatus = CallStatus::REMOTE_ERROR; - return; - } + } else { + callStatus = CallStatus::NOT_AVAILABLE; + } + } - if (sizeof...(_OutArgs) > 0) { - DBusInputStream inputStream(dbusMessageReply); - const bool success = DBusSerializableArguments<_OutArgs...>::deserialize(inputStream, outArgs...); - if (!success) { - callStatus = CallStatus::REMOTE_ERROR; - return; - } - } + template <typename _DBusProxy = DBusProxy, typename _AsyncCallback> + static std::future<CallStatus> callMethodAsync( + const _DBusProxy& dbusProxy, + const char* methodName, + const char* methodSignature, + const _InArgs&... inArgs, + _AsyncCallback asyncCallback) { + if (dbusProxy.isAvailable()) { + DBusMessage dbusMethodCall = dbusProxy.createMethodCall(methodName, methodSignature); + + return callMethodAsync(dbusProxy, dbusMethodCall, inArgs..., asyncCallback); - callStatus = CallStatus::SUCCESS; } else { - callStatus = CallStatus::NOT_AVAILABLE; + + CallStatus callStatus = CallStatus::NOT_AVAILABLE; + + callCallbackOnNotAvailable(asyncCallback, typename make_sequence<sizeof...(_OutArgs)>::type()); + + std::promise<CallStatus> promise; + promise.set_value(callStatus); + return promise.get_future(); } + } + template <typename _DBusProxy = DBusProxy, typename _AsyncCallback> + static std::future<CallStatus> callMethodAsync( + const _DBusProxy& dbusProxy, + const char* busName, + const char* objPath, + const char* interfaceName, + const char* methodName, + const char* methodSignature, + const _InArgs&... inArgs, + _AsyncCallback asyncCallback) { + if (dbusProxy.isAvailable()) { + DBusMessage dbusMethodCall = DBusMessage::createMethodCall( + busName, + objPath, + interfaceName, + methodName, + methodSignature); + return callMethodAsync(dbusProxy, dbusMethodCall, inArgs..., asyncCallback); + } else { + + CallStatus callStatus = CallStatus::NOT_AVAILABLE; + + callCallbackOnNotAvailable(asyncCallback, typename make_sequence<sizeof...(_OutArgs)>::type()); + + std::promise<CallStatus> promise; + promise.set_value(callStatus); + return promise.get_future(); + } + } + + template <typename _DBusProxy = DBusProxy, typename _AsyncCallback> static std::future<CallStatus> callMethodAsync( const _DBusProxy& dbusProxy, - const char* methodName, - const char* methodSignature, + DBusMessage& dbusMessage, const _InArgs&... inArgs, _AsyncCallback asyncCallback) { - if (dbusProxy.isAvailable()) { - - DBusMessage dbusMessage = dbusProxy.createMethodCall(methodName, methodSignature); - if (sizeof...(_InArgs) > 0) { DBusOutputStream outputStream(dbusMessage); const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...); @@ -129,16 +215,7 @@ struct DBusProxyHelper<_In<_InArgs...>, _Out<_OutArgs...>> { return dbusProxy.getDBusConnection()->sendDBusMessageWithReplyAsync( dbusMessage, DBusProxyAsyncCallbackHandler<_OutArgs...>::create(std::move(asyncCallback))); - } else { - - CallStatus callStatus = CallStatus::NOT_AVAILABLE; - callCallbackOnNotAvailable(asyncCallback, typename make_sequence<sizeof...(_OutArgs)>::type()); - - std::promise<CallStatus> promise; - promise.set_value(callStatus); - return promise.get_future(); - } } template <int... _ArgIndices> diff --git a/src/test/DBusTestUtils.h b/src/test/DBusTestUtils.h index a1140e4..476840b 100644 --- a/src/test/DBusTestUtils.h +++ b/src/test/DBusTestUtils.h @@ -5,10 +5,12 @@ * 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 __DBUS_TEST_UTILS__ +#define __DBUS_TEST_UTILS__ + #include <dbus/dbus.h> #include <CommonAPI/DBus/DBusServiceRegistry.h> - inline char eliminateZeroes(char val) { return !val ? '0' : val; } @@ -73,3 +75,4 @@ inline std::string toString(CommonAPI::CallStatus state) { return "SUCCESS"; } } +#endif //__DBUS_TEST_UTILS__ |