diff options
Diffstat (limited to 'include/CommonAPI/DBus')
-rw-r--r-- | include/CommonAPI/DBus/DBusConnection.hpp | 24 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusErrorEvent.hpp | 131 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusEvent.hpp | 60 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp | 64 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp | 16 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusMainLoopContext.hpp | 2 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusMessage.hpp | 2 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusProxy.hpp | 29 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp | 152 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusProxyAsyncSignalMemberCallbackHandler.hpp | 10 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusProxyBase.hpp | 8 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusProxyConnection.hpp | 13 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusProxyHelper.hpp | 194 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusSelectiveEvent.hpp | 6 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusServiceRegistry.hpp | 16 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusStubAdapterHelper.hpp | 237 |
16 files changed, 801 insertions, 163 deletions
diff --git a/include/CommonAPI/DBus/DBusConnection.hpp b/include/CommonAPI/DBus/DBusConnection.hpp index b32274f..acb163f 100644 --- a/include/CommonAPI/DBus/DBusConnection.hpp +++ b/include/CommonAPI/DBus/DBusConnection.hpp @@ -156,27 +156,27 @@ public: const CommonAPI::CallInfo *_info) const; COMMONAPI_EXPORT virtual bool addObjectManagerSignalMemberHandler(const std::string& dbusBusName, - DBusSignalHandler* dbusSignalHandler); + std::weak_ptr<DBusSignalHandler> dbusSignalHandler); COMMONAPI_EXPORT virtual bool removeObjectManagerSignalMemberHandler(const std::string& dbusBusName, - DBusSignalHandler* dbusSignalHandler); + 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, + std::weak_ptr<DBusSignalHandler> dbusSignalHandler, const bool justAddFilter = false); COMMONAPI_EXPORT void subscribeForSelectiveBroadcast(const std::string& objectPath, const std::string& interfaceName, const std::string& interfaceMemberName, const std::string& interfaceMemberSignature, - DBusSignalHandler* dbusSignalHandler, + std::weak_ptr<DBusSignalHandler> dbusSignalHandler, DBusProxy* callingProxy, uint32_t tag); COMMONAPI_EXPORT void unsubscribeFromSelectiveBroadcast(const std::string& eventName, - DBusProxyConnection::DBusSignalHandlerToken subscription, + DBusSignalHandlerToken subscription, DBusProxy* callingProxy, const DBusSignalHandler* dbusSignalHandler); @@ -184,7 +184,7 @@ public: COMMONAPI_EXPORT void unregisterObjectPath(const std::string& objectPath); COMMONAPI_EXPORT bool removeSignalMemberHandler(const DBusSignalHandlerToken& dbusSignalHandlerToken, - const DBusSignalHandler* dbusSignalHandler = NULL); + const DBusSignalHandler* dbusSignalHandler = NULL); COMMONAPI_EXPORT bool readWriteDispatch(int timeoutMilliseconds = -1); COMMONAPI_EXPORT virtual const std::shared_ptr<DBusObjectManager> getDBusObjectManager(); @@ -294,8 +294,11 @@ public: COMMONAPI_EXPORT void enforceAsynchronousTimeouts() const; COMMONAPI_EXPORT static const DBusObjectPathVTable* getDBusObjectPathVTable(); - COMMONAPI_EXPORT void sendPendingSelectiveSubscription(DBusProxy* proxy, std::string interfaceMemberName, - DBusSignalHandler* dbusSignalHandler, uint32_t tag, std::string interfaceMemberSignature); + COMMONAPI_EXPORT void sendPendingSelectiveSubscription(DBusProxy* proxy, + std::string interfaceMemberName, + std::weak_ptr<DBusSignalHandler> dbusSignalHandler, + uint32_t tag, + std::string interfaceMemberSignature); ::DBusConnection* connection_; mutable std::mutex connectionGuard_; @@ -315,7 +318,8 @@ public: DBusSignalHandlerTable dbusSignalHandlerTable_; std::unordered_map<std::string, size_t> dbusObjectManagerSignalMatchRulesMap_; - std::unordered_multimap<std::string, DBusSignalHandler*> dbusObjectManagerSignalHandlerTable_; + std::unordered_multimap<std::string, std::pair<DBusSignalHandler*, + std::weak_ptr<DBusSignalHandler>>> dbusObjectManagerSignalHandlerTable_; std::mutex dbusObjectManagerSignalGuard_; COMMONAPI_EXPORT bool addObjectManagerSignalMatchRule(const std::string& dbusBusName); @@ -374,7 +378,7 @@ public: mutable std::set<DBusMessageReplyAsyncHandler*> timeoutInfiniteAsyncHandlers_; mutable std::mutex timeoutInfiniteAsyncHandlersMutex_; - uint32_t activeConnections_; + int activeConnections_; mutable std::mutex activeConnectionsMutex_; bool isDisconnecting_; diff --git a/include/CommonAPI/DBus/DBusErrorEvent.hpp b/include/CommonAPI/DBus/DBusErrorEvent.hpp new file mode 100644 index 0000000..2256d33 --- /dev/null +++ b/include/CommonAPI/DBus/DBusErrorEvent.hpp @@ -0,0 +1,131 @@ +// 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_DBUSERROREVENT_HPP_ +#define COMMONAPI_DBUS_DBUSERROREVENT_HPP_ + +#include <CommonAPI/Event.hpp> + +#include <CommonAPI/DBus/DBusInputStream.hpp> + +namespace CommonAPI { +namespace DBus { + +template <class...> +class DBusErrorEvent; + +template<> +class DBusErrorEvent<> : public Event<std::string> { +public: + DBusErrorEvent(const std::string &_errorName) : + errorName_(_errorName) {} + + DBusErrorEvent(const DBusErrorEvent &_source) : + errorName_(_source.errorName_) {} + + virtual ~DBusErrorEvent() {} + + inline const std::string & getErrorName() const { + return errorName_; + } + + void notifyErrorEventListeners(const DBusMessage &_reply) { + (void)_reply; + this->notifyListeners(errorName_); + } + +private: + std::string errorName_; +}; + +template < + template <class...> class In_, class... InArgs_, + template <class...> class DeplIn_, class... DeplIn_Args> +class DBusErrorEvent< + In_<InArgs_...>, + DeplIn_<DeplIn_Args...>> : public Event<std::string, InArgs_...> { +public: + DBusErrorEvent(const std::string &_errorName, + const std::tuple<DeplIn_Args*...> &_in) : + errorName_(_errorName) { + initialize(typename make_sequence_range<sizeof...(DeplIn_Args), 0>::type(), _in); + } + + DBusErrorEvent(const DBusErrorEvent &_source) : + errorName_(_source.errorName_), + in_(_source.in_) {} + + virtual ~DBusErrorEvent() {} + + inline const std::string & getErrorName() const { + return errorName_; + } + + void notifyErrorEventListeners(const DBusMessage &_reply) { + deserialize(_reply, typename make_sequence_range<sizeof...(InArgs_), 0>::type()); + } + +private: + + template <int... DeplIn_ArgIndices> + inline void initialize(index_sequence<DeplIn_ArgIndices...>, const std::tuple<DeplIn_Args*...> &_in) { + in_ = std::make_tuple(std::get<DeplIn_ArgIndices>(_in)...); + } + + template <int... InArgIndices_> + void deserialize(const DBusMessage &_reply, + index_sequence<InArgIndices_...>) { + if (sizeof...(InArgs_) > 0) { + DBusInputStream dbusInputStream(_reply); + const bool success = DBusSerializableArguments<CommonAPI::Deployable<InArgs_, DeplIn_Args>...>::deserialize(dbusInputStream, std::get<InArgIndices_>(in_)...); + if (!success) + return; + this->notifyListeners(errorName_, std::move(std::get<InArgIndices_>(in_).getValue())...); + } + } + + std::string errorName_; + std::tuple<CommonAPI::Deployable<InArgs_, DeplIn_Args>...> in_; +}; + +class DBusErrorEventHelper { +public: + template <int... ErrorEventsIndices_, class... ErrorEvents_> + static void notifyListeners(const DBusMessage &_reply, + const std::string &_errorName, + index_sequence<ErrorEventsIndices_...>, + const std::tuple<ErrorEvents_*...> &_errorEvents) { + + notifyListeners(_reply, _errorName, std::get<ErrorEventsIndices_>(_errorEvents)...); + } + + template <class ErrorEvent_> + static void notifyListeners(const DBusMessage &_reply, + const std::string &_errorName, + ErrorEvent_ *_errorEvent) { + if(_errorEvent->getErrorName() == _errorName) + _errorEvent->notifyErrorEventListeners(_reply); + + } + + template <class ErrorEvent_, class... Rest_> + static void notifyListeners(const DBusMessage &_reply, + const std::string &_errorName, + ErrorEvent_ *_errorEvent, + Rest_&... _rest) { + if(_errorEvent->getErrorName() == _errorName) + _errorEvent->notifyErrorEventListeners(_reply); + notifyListeners(_reply, _errorName, _rest...); + } +}; + +} // namespace DBus +} // namespace CommonAPI + +#endif /* COMMONAPI_DBUS_DBUSERROREVENT_HPP_ */ diff --git a/include/CommonAPI/DBus/DBusEvent.hpp b/include/CommonAPI/DBus/DBusEvent.hpp index 2637acf..945988d 100644 --- a/include/CommonAPI/DBus/DBusEvent.hpp +++ b/include/CommonAPI/DBus/DBusEvent.hpp @@ -22,7 +22,7 @@ namespace CommonAPI { namespace DBus { template <typename Event_, typename... Arguments_> -class DBusEvent: public Event_, public DBusProxyConnection::DBusSignalHandler { +class DBusEvent: public Event_ { public: typedef typename Event_::Subscription Subscription; typedef typename Event_::Listener Listener; @@ -31,6 +31,7 @@ public: const std::string &_name, const std::string &_signature, std::tuple<Arguments_...> _arguments) : proxy_(_proxy), + signalHandler_(std::make_shared<SignalHandler>(_proxy, this)), name_(_name), signature_(_signature), getMethodName_(""), arguments_(_arguments) { @@ -44,6 +45,7 @@ public: const std::string &_path, const std::string &_interface, std::tuple<Arguments_...> _arguments) : proxy_(_proxy), + signalHandler_(std::make_shared<SignalHandler>(_proxy, this)), name_(_name), signature_(_signature), path_(_path), interface_(_interface), getMethodName_(""), @@ -56,6 +58,7 @@ public: const std::string &_getMethodName, std::tuple<Arguments_...> _arguments) : proxy_(_proxy), + signalHandler_(std::make_shared<SignalHandler>(_proxy, this)), name_(_name), signature_(_signature), getMethodName_(_getMethodName), @@ -66,37 +69,71 @@ public: } virtual ~DBusEvent() { - proxy_.removeSignalMemberHandler(subscription_, this); + proxy_.removeSignalMemberHandler(subscription_, signalHandler_.get()); } - virtual void onSignalDBusMessage(const DBusMessage &_message) { - handleSignalDBusMessage(_message, typename make_sequence<sizeof...(Arguments_)>::type()); + virtual void onError(const CommonAPI::CallStatus status) { + (void)status; } - virtual void onInitialValueSignalDBusMessage(const DBusMessage&_message, const uint32_t tag) { - handleSignalDBusMessage(tag, _message, typename make_sequence<sizeof...(Arguments_)>::type()); + virtual void onSpecificError(const CommonAPI::CallStatus status, const uint32_t tag) { + (void)status; + (void)tag; } - virtual void onError(const CommonAPI::CallStatus status) { - (void) status; + virtual void setSubscriptionToken(const DBusProxyConnection::DBusSignalHandlerToken token, const uint32_t tag) { + (void)token; + (void)tag; } protected: + + class SignalHandler : public DBusProxyConnection::DBusSignalHandler, + public std::enable_shared_from_this<SignalHandler> { + public: + SignalHandler(DBusProxyBase&_proxy, + DBusEvent<Event_, Arguments_ ...>* _dbusEvent) : + proxy_(_proxy), + dbusEvent_(_dbusEvent) { + + } + + virtual void onSignalDBusMessage(const DBusMessage &_message) { + dbusEvent_->handleSignalDBusMessage(_message, typename make_sequence<sizeof...(Arguments_)>::type()); + } + + virtual void onInitialValueSignalDBusMessage(const DBusMessage&_message, const uint32_t tag) { + dbusEvent_->handleSignalDBusMessage(tag, _message, typename make_sequence<sizeof...(Arguments_)>::type()); + } + + virtual void onSpecificError(const CommonAPI::CallStatus status, const uint32_t tag) { + dbusEvent_->onSpecificError(status, tag); + } + + virtual void setSubscriptionToken(const DBusProxyConnection::DBusSignalHandlerToken token, const uint32_t tag) { + dbusEvent_->setSubscriptionToken(token, tag); + } + + private : + DBusProxyBase& proxy_; + DBusEvent<Event_, Arguments_ ...>* dbusEvent_; + }; + virtual void onFirstListenerAdded(const Listener &_listener) { (void)_listener; subscription_ = proxy_.addSignalMemberHandler( - path_, interface_, name_, signature_, getMethodName_, this, false); + path_, interface_, name_, signature_, getMethodName_, signalHandler_, false); } virtual void onListenerAdded(const Listener &_listener, const Subscription subscription) { (void)_listener; if ("" != getMethodName_) { - proxy_.getCurrentValueForSignalListener(getMethodName_, this, subscription); + proxy_.getCurrentValueForSignalListener(getMethodName_, signalHandler_, subscription); } } virtual void onLastListenerRemoved(const Listener&) { - proxy_.removeSignalMemberHandler(subscription_, this); + proxy_.removeSignalMemberHandler(subscription_, signalHandler_.get()); std::get<0>(subscription_) = ""; std::get<1>(subscription_) = ""; std::get<2>(subscription_) = ""; @@ -124,6 +161,7 @@ public: } DBusProxyBase &proxy_; + std::shared_ptr<SignalHandler> signalHandler_; std::string name_; std::string signature_; diff --git a/include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp b/include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp index 4f78f5c..8f35928 100644 --- a/include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp +++ b/include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp @@ -151,8 +151,7 @@ class DBusFreedesktopAttribute template<class, class, class> class LegacyEvent; template <template <class...> class Type_, class Types_, class DataType_, class DataDeplType_> -class LegacyEvent<Type_<Types_>, DataType_, DataDeplType_>: public Type_<Types_>, - public DBusProxyConnection::DBusSignalHandler { +class LegacyEvent<Type_<Types_>, DataType_, DataDeplType_>: public Type_<Types_> { public: typedef Types_ ValueType; typedef typename Type_<ValueType>::Listener Listener; @@ -170,6 +169,7 @@ public: mapDepl_(nullptr, &variantDepl_), deployedMap_(&mapDepl_), proxy_(_proxy), + signalHandler_(std::make_shared<SignalHandler>(_proxy, this, &variantDepl_)), isSubcriptionSet_(false), internalEvent_(_proxy, "PropertiesChanged", @@ -179,7 +179,47 @@ public: std::make_tuple("", deployedMap_, InvalidArray())) { } + virtual ~LegacyEvent() {} + protected: + + class SignalHandler : public DBusProxyConnection::DBusSignalHandler, + public std::enable_shared_from_this<SignalHandler> { + public: + SignalHandler(DBusProxy& _proxy, + LegacyEvent<Type_<Types_>, DataType_, DataDeplType_>* _legacyEvent, + VariantDeployment<DataDeplType_>* _variantDepl) : + proxy_(_proxy), + legacyEvent_(_legacyEvent), + variantDepl_(_variantDepl) { + + } + + virtual void onInitialValueSignalDBusMessage(const DBusMessage&_message, const uint32_t tag) { + CommonAPI::Deployable<Variant<DataType_>, VariantDeployment<DataDeplType_>> deployedValue(variantDepl_); + DBusInputStream input(_message); + if (DBusSerializableArguments< + CommonAPI::Deployable< + Variant<DataType_>, + VariantDeployment<DataDeplType_> + > + >::deserialize(input, deployedValue)) { + Variant<DataType_> v = deployedValue.getValue(); + const DataType_ &value = v.template get<DataType_>(); + legacyEvent_->notifySpecificListener(tag, value); + } + } + + virtual void onSignalDBusMessage(const DBusMessage&) { + // ignore + } + + private: + DBusProxy& proxy_; + LegacyEvent<Type_<Types_>, DataType_, DataDeplType_>* legacyEvent_; + VariantDeployment<DataDeplType_>* variantDepl_; + }; + void onFirstListenerAdded(const Listener &) { if (!isSubcriptionSet_) { subscription_ = internalEvent_.subscribe( @@ -202,26 +242,9 @@ protected: virtual void onListenerAdded(const Listener& listener, const Subscription subscription) { (void)listener; - proxy_.freeDesktopGetCurrentValueForSignalListener(this, subscription, interfaceName_, propertyName_); + proxy_.freeDesktopGetCurrentValueForSignalListener(signalHandler_, subscription, interfaceName_, propertyName_); } - virtual void onInitialValueSignalDBusMessage(const DBusMessage&_message, const uint32_t tag) { - CommonAPI::Deployable<Variant<DataType_>, VariantDeployment<DataDeplType_>> deployedValue(&variantDepl_); - DBusInputStream input(_message); - if (DBusSerializableArguments< - CommonAPI::Deployable< - Variant<DataType_>, - VariantDeployment<DataDeplType_> - > - >::deserialize(input, deployedValue)) { - Variant<DataType_> v = deployedValue.getValue(); - const DataType_ &value = v.template get<DataType_>(); - this->notifySpecificListener(tag, value); - } - } - virtual void onSignalDBusMessage(const DBusMessage&) { - // ignore - } void onLastListenerRemoved(const Listener &) { if (isSubcriptionSet_) { internalEvent_.unsubscribe(subscription_); @@ -235,6 +258,7 @@ protected: PropertyMapDeployment mapDepl_; DeployedPropertyMap deployedMap_; DBusProxy &proxy_; + std::shared_ptr<SignalHandler> signalHandler_; typename DBusEvent<SignalEvent, std::string, DeployedPropertyMap, InvalidArray>::Subscription subscription_; bool isSubcriptionSet_; diff --git a/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp b/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp index 1f5bcc2..9be2e9a 100644 --- a/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp +++ b/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp @@ -26,8 +26,7 @@ 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 ProxyManager::InstanceAvailabilityStatusChangedEvent { public: typedef std::function<void(const CallStatus &, const std::vector<DBusAddress> &)> GetAvailableServiceInstancesCallback; @@ -38,8 +37,6 @@ class DBusInstanceAvailabilityStatusChangedEvent: COMMONAPI_EXPORT virtual ~DBusInstanceAvailabilityStatusChangedEvent(); - COMMONAPI_EXPORT virtual void onSignalDBusMessage(const DBusMessage& dbusMessage); - COMMONAPI_EXPORT void getAvailableServiceInstances(CommonAPI::CallStatus &_status, std::vector<DBusAddress> &_availableServiceInstances); COMMONAPI_EXPORT std::future<CallStatus> getAvailableServiceInstancesAsync(GetAvailableServiceInstancesCallback _callback); @@ -50,6 +47,15 @@ class DBusInstanceAvailabilityStatusChangedEvent: ProxyManager::GetInstanceAvailabilityStatusCallback _callback); protected: + + class SignalHandler : public DBusProxyConnection::DBusSignalHandler { + public: + COMMONAPI_EXPORT SignalHandler(DBusInstanceAvailabilityStatusChangedEvent* _instanceAvblStatusEvent); + COMMONAPI_EXPORT virtual void onSignalDBusMessage(const DBusMessage& dbusMessage); + private: + DBusInstanceAvailabilityStatusChangedEvent* instanceAvblStatusEvent_; + }; + virtual void onFirstListenerAdded(const Listener&); virtual void onLastListenerRemoved(const Listener&); @@ -76,7 +82,9 @@ class DBusInstanceAvailabilityStatusChangedEvent: void translate(const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict &_dict, std::vector<DBusAddress> &_serviceInstances); + std::shared_ptr<SignalHandler> signalHandler_; DBusProxy &proxy_; + std::weak_ptr<DBusProxy> proxyWeakPtr_; std::string observedDbusInterfaceName_; std::string observedCapiInterfaceName_; DBusProxyConnection::DBusSignalHandlerToken interfacesAddedSubscription_; diff --git a/include/CommonAPI/DBus/DBusMainLoopContext.hpp b/include/CommonAPI/DBus/DBusMainLoopContext.hpp index 6de84f8..708cfa3 100644 --- a/include/CommonAPI/DBus/DBusMainLoopContext.hpp +++ b/include/CommonAPI/DBus/DBusMainLoopContext.hpp @@ -124,6 +124,7 @@ private: int pipeFileDescriptors_[2]; pollfd pollFileDescriptor_; + std::vector<CommonAPI::DispatchSource*> dependentDispatchSources_; std::queue<std::shared_ptr<QueueEntry>> queue_; @@ -134,7 +135,6 @@ private: const int pipeValue_; #ifdef WIN32 HANDLE wsaEvent_; - OVERLAPPED ov; #endif }; diff --git a/include/CommonAPI/DBus/DBusMessage.hpp b/include/CommonAPI/DBus/DBusMessage.hpp index b005904..ece0b21 100644 --- a/include/CommonAPI/DBus/DBusMessage.hpp +++ b/include/CommonAPI/DBus/DBusMessage.hpp @@ -56,7 +56,7 @@ public: DBusMessage createMethodReturn(const std::string &_signature) const; - DBusMessage createMethodError(const std::string &_name, const std::string &_reason = "") const; + DBusMessage createMethodError(const std::string &_name, const std::string &_signature = "s", const std::string &_reason = "") const; static DBusMessage createSignal(const std::string& objectPath, const std::string& interfaceName, diff --git a/include/CommonAPI/DBus/DBusProxy.hpp b/include/CommonAPI/DBus/DBusProxy.hpp index 072e356..cc9bd06 100644 --- a/include/CommonAPI/DBus/DBusProxy.hpp +++ b/include/CommonAPI/DBus/DBusProxy.hpp @@ -64,12 +64,12 @@ public: const std::string& interfaceName, const std::string& interfaceMemberName, const std::string& interfaceMemberSignature, - DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler, uint32_t tag); COMMONAPI_EXPORT void insertSelectiveSubscription( const std::string& interfaceMemberName, - DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler, uint32_t tag, std::string interfaceMemberSignature); COMMONAPI_EXPORT void unsubscribeFromSelectiveBroadcast(const std::string& eventName, DBusProxyConnection::DBusSignalHandlerToken subscription, @@ -82,7 +82,7 @@ public: const std::string &interfaceName, const std::string &signalName, const std::string &signalSignature, - DBusProxyConnection::DBusSignalHandler *dbusSignalHandler, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler, const bool justAddFilter); COMMONAPI_EXPORT virtual DBusProxyConnection::DBusSignalHandlerToken addSignalMemberHandler( @@ -91,25 +91,25 @@ public: const std::string &signalName, const std::string &signalSignature, const std::string &getMethodName, - DBusProxyConnection::DBusSignalHandler *dbusSignalHandler, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler, const bool justAddFilter); COMMONAPI_EXPORT virtual bool removeSignalMemberHandler( const DBusProxyConnection::DBusSignalHandlerToken &_dbusSignalHandlerToken, - const DBusProxyConnection::DBusSignalHandler *_dbusSignalHandler = NULL); + const DBusProxyConnection::DBusSignalHandler* _dbusSignalHandler = NULL); COMMONAPI_EXPORT virtual void getCurrentValueForSignalListener( const std::string &getMethodName, - DBusProxyConnection::DBusSignalHandler *dbusSignalHandler, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler, const uint32_t subscription); COMMONAPI_EXPORT virtual void freeDesktopGetCurrentValueForSignalListener( - DBusProxyConnection::DBusSignalHandler *dbusSignalHandler, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler, const uint32_t subscription, const std::string &interfaceName, const std::string &propertyName); - COMMONAPI_EXPORT virtual void notifySpecificListener(std::weak_ptr<DBusProxy> _dbusProxy, + COMMONAPI_EXPORT static void notifySpecificListener(std::weak_ptr<DBusProxy> _dbusProxy, const ProxyStatusEvent::Listener &_listener, const ProxyStatusEvent::Subscription _subscription); @@ -120,21 +120,22 @@ private: const std::string, const std::string, const std::string, - DBusProxyConnection::DBusSignalHandler*, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler>, const bool, bool > SignalMemberHandlerTuple; COMMONAPI_EXPORT DBusProxy(const DBusProxy &) = delete; - COMMONAPI_EXPORT void onDBusServiceInstanceStatus(const AvailabilityStatus& availabilityStatus); + COMMONAPI_EXPORT void onDBusServiceInstanceStatus(std::shared_ptr<DBusProxy> _proxy, + const AvailabilityStatus& availabilityStatus); COMMONAPI_EXPORT void signalMemberCallback(const CallStatus dbusMessageCallStatus, const DBusMessage& dbusMessage, - DBusProxyConnection::DBusSignalHandler* dbusSignalHandlers, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandlers, const uint32_t tag); COMMONAPI_EXPORT void signalInitialValueCallback(const CallStatus dbusMessageCallStatus, const DBusMessage& dbusMessage, - DBusProxyConnection::DBusSignalHandler* dbusSignalHandlers, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandlers, const uint32_t tag); COMMONAPI_EXPORT void addSignalMemberHandlerToQueue(SignalMemberHandlerTuple& _signalMemberHandler); @@ -155,7 +156,7 @@ private: mutable std::mutex signalMemberHandlerQueueMutex_; std::map<std::string, - std::tuple<DBusProxyConnection::DBusSignalHandler*, uint32_t, + std::tuple<std::weak_ptr<DBusProxyConnection::DBusSignalHandler>, uint32_t, std::string>> selectiveBroadcastHandlers; mutable std::mutex selectiveBroadcastHandlersMutex_; @@ -170,8 +171,6 @@ private: std::promise<AvailabilityStatus> > AvailabilityTimeout_t; mutable std::list<AvailabilityTimeout_t> timeouts_; - - std::weak_ptr<DBusProxy> selfReference_; }; diff --git a/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp b/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp index 1a00adc..d21807d 100644 --- a/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp +++ b/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp @@ -18,36 +18,40 @@ #include <CommonAPI/DBus/DBusMessage.hpp> #include <CommonAPI/DBus/DBusProxyConnection.hpp> #include <CommonAPI/DBus/DBusSerializableArguments.hpp> +#include <CommonAPI/DBus/DBusErrorEvent.hpp> namespace CommonAPI { namespace DBus { -template<typename DelegateObjectType_, typename ... ArgTypes_> -class DBusProxyAsyncCallbackHandler: +template <class, class...> +class DBusProxyAsyncCallbackHandler; + +template <class DelegateObjectType_, class ... ArgTypes_> +class DBusProxyAsyncCallbackHandler : public DBusProxyConnection::DBusMessageReplyAsyncHandler { public: struct Delegate { typedef std::function<void(CallStatus, ArgTypes_...)> FunctionType; - Delegate(std::shared_ptr<DelegateObjectType_> object, FunctionType function) : - function_(std::move(function)) { - object_ = object; + Delegate(std::shared_ptr<DelegateObjectType_> _object, FunctionType _function) : + function_(std::move(_function)) { + object_ = _object; } std::weak_ptr<DelegateObjectType_> object_; FunctionType function_; }; static std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler> create( - Delegate& delegate, std::tuple<ArgTypes_...> args) { + Delegate& _delegate, const std::tuple<ArgTypes_...>& _args) { return std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler>( - new DBusProxyAsyncCallbackHandler<DelegateObjectType_, ArgTypes_...>(std::move(delegate), args)); + new DBusProxyAsyncCallbackHandler<DelegateObjectType_, ArgTypes_...>(std::move(_delegate), _args)); } DBusProxyAsyncCallbackHandler() = delete; - DBusProxyAsyncCallbackHandler(Delegate&& delegate, std::tuple<ArgTypes_...> args) - : delegate_(std::move(delegate)), - args_(args), + DBusProxyAsyncCallbackHandler(Delegate&& _delegate, const std::tuple<ArgTypes_...>& _args) + : delegate_(std::move(_delegate)), + args_(_args), executionStarted_(false), executionFinished_(false), timeoutOccurred_(false), @@ -62,10 +66,10 @@ class DBusProxyAsyncCallbackHandler: return promise_.get_future(); } - virtual void onDBusMessageReply(const CallStatus& dbusMessageCallStatus, - const DBusMessage& dbusMessage) { - promise_.set_value(handleDBusMessageReply(dbusMessageCallStatus, - dbusMessage, + virtual void onDBusMessageReply(const CallStatus& _dbusMessageCallStatus, + const DBusMessage& _dbusMessage) { + promise_.set_value(handleDBusMessageReply(_dbusMessageCallStatus, + _dbusMessage, typename make_sequence<sizeof...(ArgTypes_)>::type(), args_)); } @@ -109,42 +113,39 @@ class DBusProxyAsyncCallbackHandler: asyncHandlerMutex_.unlock(); } + protected: + Delegate delegate_; + std::promise<CallStatus> promise_; + std::tuple<ArgTypes_...> args_; + private: template <int... ArgIndices_> inline CallStatus handleDBusMessageReply( - const CallStatus dbusMessageCallStatus, - const DBusMessage& dbusMessage, + const CallStatus _dbusMessageCallStatus, + const DBusMessage& _dbusMessage, index_sequence<ArgIndices_...>, - std::tuple<ArgTypes_...> argTuple) const { - (void)argTuple; // this suppresses warning "set but not used" in case of empty _ArgTypes + std::tuple<ArgTypes_...>& _argTuple) const { + (void)_argTuple; // this suppresses warning "set but not used" in case of empty _ArgTypes // Looks like: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57560 - Bug 57650 - 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; + CallStatus callStatus = _dbusMessageCallStatus; + + if (_dbusMessageCallStatus == CallStatus::SUCCESS) { + DBusInputStream dbusInputStream(_dbusMessage); + if(DBusSerializableArguments<ArgTypes_...>::deserialize(dbusInputStream, + std::get<ArgIndices_>(_argTuple)...)) { } else { callStatus = CallStatus::REMOTE_ERROR; } } - //check if object is expired - if(!delegate_.object_.expired()) - delegate_.function_(callStatus, std::move(std::get<ArgIndices_>(argTuple))...); + //ensure that delegate object (e.g. Proxy) survives + if(auto itsDelegateObject = delegate_.object_.lock()) + delegate_.function_(callStatus, std::move(std::get<ArgIndices_>(_argTuple))...); return callStatus; } - std::promise<CallStatus> promise_; - Delegate delegate_; - std::tuple<ArgTypes_...> args_; bool executionStarted_; bool executionFinished_; bool timeoutOccurred_; @@ -153,6 +154,87 @@ class DBusProxyAsyncCallbackHandler: std::mutex asyncHandlerMutex_; }; +template< + template <class...> class ErrorEventsTuple_, class... ErrorEvents_, + class DelegateObjectType_, class... ArgTypes_> +class DBusProxyAsyncCallbackHandler< + ErrorEventsTuple_<ErrorEvents_...>, + DelegateObjectType_, + ArgTypes_...>: + public DBusProxyAsyncCallbackHandler<DelegateObjectType_, ArgTypes_...> { + +public: + + static std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler> create( + typename DBusProxyAsyncCallbackHandler<DelegateObjectType_, ArgTypes_...>::Delegate& _delegate, + const std::tuple<ArgTypes_...>& _args, + const ErrorEventsTuple_<ErrorEvents_...> &_errorEvents) { + return std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler>( + new DBusProxyAsyncCallbackHandler<ErrorEventsTuple_<ErrorEvents_...>, DelegateObjectType_, ArgTypes_...>(std::move(_delegate), _args, _errorEvents)); + } + + DBusProxyAsyncCallbackHandler() = delete; + DBusProxyAsyncCallbackHandler(typename DBusProxyAsyncCallbackHandler<DelegateObjectType_, ArgTypes_...>::Delegate&& _delegate, + const std::tuple<ArgTypes_...>& _args, + const ErrorEventsTuple_<ErrorEvents_...> &_errorEvents) : + DBusProxyAsyncCallbackHandler<DelegateObjectType_, ArgTypes_...>(std::move(_delegate), _args), + errorEvents_(_errorEvents) {} + + virtual ~DBusProxyAsyncCallbackHandler() { + // free assigned std::function<> immediately + this->delegate_.function_ = [](CallStatus, ArgTypes_...) {}; + } + + virtual void onDBusMessageReply(const CallStatus& _dbusMessageCallStatus, + const DBusMessage& _dbusMessage) { + this->promise_.set_value(handleDBusMessageReply( + _dbusMessageCallStatus, + _dbusMessage, + typename make_sequence<sizeof...(ArgTypes_)>::type(), this->args_)); + } + +private: + + template <int... ArgIndices_> + inline CallStatus handleDBusMessageReply( + const CallStatus _dbusMessageCallStatus, + const DBusMessage& _dbusMessage, + index_sequence<ArgIndices_...>, + std::tuple<ArgTypes_...>& _argTuple) const { + (void)_argTuple; // this suppresses warning "set but not used" in case of empty _ArgTypes + // Looks like: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57560 - Bug 57650 + + CallStatus callStatus = _dbusMessageCallStatus; + + if (_dbusMessageCallStatus == CallStatus::SUCCESS) { + DBusInputStream dbusInputStream(_dbusMessage); + if(DBusSerializableArguments<ArgTypes_...>::deserialize(dbusInputStream, + std::get<ArgIndices_>(_argTuple)...)) { + } else { + callStatus = CallStatus::REMOTE_ERROR; + } + } else { + if(_dbusMessage.isErrorType()) { + //ensure that delegate object (e.g. Proxy and its error events) survives + if(auto itsDelegateObject = this->delegate_.object_.lock()) { + DBusErrorEventHelper::notifyListeners(_dbusMessage, + _dbusMessage.getError(), + typename make_sequence_range<sizeof...(ErrorEvents_), 0>::type(), + errorEvents_); + } + } + } + + //ensure that delegate object (e.g. Proxy) survives + if(auto itsDelegateObject = this->delegate_.object_.lock()) + this->delegate_.function_(callStatus, std::move(std::get<ArgIndices_>(_argTuple))...); + + return callStatus; + } + + ErrorEventsTuple_<ErrorEvents_...> errorEvents_; +}; + } // namespace DBus } // namespace CommonAPI diff --git a/include/CommonAPI/DBus/DBusProxyAsyncSignalMemberCallbackHandler.hpp b/include/CommonAPI/DBus/DBusProxyAsyncSignalMemberCallbackHandler.hpp index 11cb354..788c1ff 100644 --- a/include/CommonAPI/DBus/DBusProxyAsyncSignalMemberCallbackHandler.hpp +++ b/include/CommonAPI/DBus/DBusProxyAsyncSignalMemberCallbackHandler.hpp @@ -26,7 +26,7 @@ class DBusProxyAsyncSignalMemberCallbackHandler: public DBusProxyConnection::DBu public: struct Delegate { - typedef std::function<void(CallStatus, DBusMessage, DBusProxyConnection::DBusSignalHandler*, uint32_t)> FunctionType; + typedef std::function<void(CallStatus, DBusMessage, std::weak_ptr<DBusProxyConnection::DBusSignalHandler>, uint32_t)> FunctionType; Delegate(std::shared_ptr<DelegateObjectType_> object, FunctionType function) : function_(std::move(function)) { @@ -37,7 +37,7 @@ class DBusProxyAsyncSignalMemberCallbackHandler: public DBusProxyConnection::DBu }; static std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler> create( - Delegate& delegate, DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, + Delegate& delegate, std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler, const uint32_t tag) { return std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler>( new DBusProxyAsyncSignalMemberCallbackHandler<DelegateObjectType_>(std::move(delegate), dbusSignalHandler, tag)); @@ -45,8 +45,8 @@ class DBusProxyAsyncSignalMemberCallbackHandler: public DBusProxyConnection::DBu DBusProxyAsyncSignalMemberCallbackHandler() = delete; DBusProxyAsyncSignalMemberCallbackHandler(Delegate&& delegate, - DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, - const uint32_t tag): + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler, + const uint32_t tag): delegate_(std::move(delegate)), dbusSignalHandler_(dbusSignalHandler), tag_(tag), executionStarted_(false), executionFinished_(false), timeoutOccurred_(false), hasToBeDeleted_(false) { @@ -114,7 +114,7 @@ class DBusProxyAsyncSignalMemberCallbackHandler: public DBusProxyConnection::DBu std::promise<CallStatus> promise_; const Delegate delegate_; - DBusProxyConnection::DBusSignalHandler* dbusSignalHandler_; + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler_; const uint32_t tag_; bool executionStarted_; bool executionFinished_; diff --git a/include/CommonAPI/DBus/DBusProxyBase.hpp b/include/CommonAPI/DBus/DBusProxyBase.hpp index 2193ca7..e0fbaec 100644 --- a/include/CommonAPI/DBus/DBusProxyBase.hpp +++ b/include/CommonAPI/DBus/DBusProxyBase.hpp @@ -49,7 +49,7 @@ public: const std::string &interfaceName, const std::string &signalName, const std::string &signalSignature, - DBusProxyConnection::DBusSignalHandler *dbusSignalHandler, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler, const bool justAddFilter); COMMONAPI_EXPORT virtual DBusProxyConnection::DBusSignalHandlerToken addSignalMemberHandler( @@ -58,16 +58,16 @@ public: const std::string &signalName, const std::string &signalSignature, const std::string &getMethodName, - DBusProxyConnection::DBusSignalHandler *dbusSignalHandler, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> dbusSignalHandler, const bool justAddFilter); COMMONAPI_EXPORT virtual bool removeSignalMemberHandler( const DBusProxyConnection::DBusSignalHandlerToken &_dbusSignalHandlerToken, - const DBusProxyConnection::DBusSignalHandler *_dbusSignalHandler = NULL); + const DBusProxyConnection::DBusSignalHandler* dbusSignalHandler = NULL); COMMONAPI_EXPORT virtual void getCurrentValueForSignalListener( const std::string &_getMethodName, - DBusProxyConnection::DBusSignalHandler *_handler, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler> _handler, const uint32_t _subscription) { (void)_getMethodName; (void)_handler; diff --git a/include/CommonAPI/DBus/DBusProxyConnection.hpp b/include/CommonAPI/DBus/DBusProxyConnection.hpp index 6065a8b..d0db2ba 100644 --- a/include/CommonAPI/DBus/DBusProxyConnection.hpp +++ b/include/CommonAPI/DBus/DBusProxyConnection.hpp @@ -61,7 +61,10 @@ class DBusProxyConnection { // 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 std::unordered_map<DBusSignalHandlerPath, + std::pair<std::shared_ptr<std::recursive_mutex>, + std::map<DBusSignalHandler*, + std::weak_ptr<DBusProxyConnection::DBusSignalHandler>>>> DBusSignalHandlerTable; typedef DBusSignalHandlerPath DBusSignalHandlerToken; class DBusSignalHandler { @@ -98,14 +101,14 @@ class DBusProxyConnection { const std::string& interfaceName, const std::string& interfaceMemberName, const std::string& interfaceMemberSignature, - DBusSignalHandler* dbusSignalHandler, + std::weak_ptr<DBusSignalHandler> dbusSignalHandler, const bool justAddFilter = false) = 0; virtual void subscribeForSelectiveBroadcast(const std::string& objectPath, const std::string& interfaceName, const std::string& interfaceMemberName, const std::string& interfaceMemberSignature, - DBusSignalHandler* dbusSignalHandler, + std::weak_ptr<DBusSignalHandler> dbusSignalHandler, DBusProxy* callingProxy, uint32_t tag) = 0; @@ -118,7 +121,7 @@ class DBusProxyConnection { const DBusSignalHandler* dbusSignalHandler = NULL) = 0; virtual bool addObjectManagerSignalMemberHandler(const std::string& dbusBusName, - DBusSignalHandler* dbusSignalHandler) = 0; + std::weak_ptr<DBusSignalHandler> dbusSignalHandler) = 0; virtual bool removeObjectManagerSignalMemberHandler(const std::string& dbusBusName, DBusSignalHandler* dbusSignalHandler) = 0; @@ -139,7 +142,7 @@ class DBusProxyConnection { virtual void sendPendingSelectiveSubscription( DBusProxy* proxy, std::string interfaceMemberName, - DBusSignalHandler* dbusSignalHandler, uint32_t tag, + std::weak_ptr<DBusSignalHandler> dbusSignalHandler, uint32_t tag, std::string interfaceMemberSignature) = 0; virtual void pushDBusMessageReplyToMainLoop(const DBusMessage& reply, diff --git a/include/CommonAPI/DBus/DBusProxyHelper.hpp b/include/CommonAPI/DBus/DBusProxyHelper.hpp index 8bd0154..3f9e175 100644 --- a/include/CommonAPI/DBus/DBusProxyHelper.hpp +++ b/include/CommonAPI/DBus/DBusProxyHelper.hpp @@ -21,13 +21,14 @@ #include <CommonAPI/DBus/DBusSerializableArguments.hpp> #include <CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp> #include <CommonAPI/DBus/DBusProxyConnection.hpp> +#include <CommonAPI/DBus/DBusErrorEvent.hpp> namespace CommonAPI { namespace DBus { class DBusProxy; -template< class, class > +template< class, class... > struct DBusProxyHelper; #ifdef WIN32 @@ -76,7 +77,7 @@ struct DBusProxyHelper<In_<DBusInputStream, DBusOutputStream, InArgs_...>, template <typename DBusProxy_ = DBusProxy> static void callMethodWithReply( const DBusProxy_ &_proxy, - DBusMessage &_message, + const DBusMessage &_message, const CommonAPI::CallInfo *_info, const InArgs_&... _in, CommonAPI::CallStatus &_status, @@ -175,7 +176,7 @@ struct DBusProxyHelper<In_<DBusInputStream, DBusOutputStream, InArgs_...>, template <typename DBusProxy_ = DBusProxy, typename DelegateFunction_> static std::future<CallStatus> callMethodAsync( DBusProxy_ &_proxy, - DBusMessage &_message, + const DBusMessage &_message, const CommonAPI::CallInfo *_info, const InArgs_&... _in, DelegateFunction_ _function, @@ -221,7 +222,7 @@ struct DBusProxyHelper<In_<DBusInputStream, DBusOutputStream, InArgs_...>, std::shared_ptr< std::unique_ptr< DBusProxyConnection::DBusMessageReplyAsyncHandler > > sharedDbusMessageReplyAsyncHandler( new std::unique_ptr< DBusProxyConnection::DBusMessageReplyAsyncHandler >(std::move(dbusMessageReplyAsyncHandler))); //async isAvailable call with timeout - COMMONAPI_VERBOSE("MethodAsync(dbus): Proxy not available -> register calback"); + COMMONAPI_VERBOSE("MethodAsync(dbus): Proxy not available -> register callback"); _proxy.isAvailableAsync([&_proxy, _message, sharedDbusMessageReplyAsyncHandler]( const AvailabilityStatus _status, const Timeout_t remaining) { @@ -245,9 +246,9 @@ struct DBusProxyHelper<In_<DBusInputStream, DBusOutputStream, InArgs_...>, unsigned int dummySerial = 999; _message.setSerial(dummySerial); //set dummy serial if (*sharedDbusMessageReplyAsyncHandler) { - DBusMessage errorMessage = _message.createMethodError(DBUS_ERROR_UNKNOWN_METHOD); - _proxy.getDBusConnection()->pushDBusMessageReplyToMainLoop(errorMessage, - std::move(*sharedDbusMessageReplyAsyncHandler)); + DBusMessage errorMessage = _message.createMethodError(DBUS_ERROR_UNKNOWN_METHOD); + _proxy.getDBusConnection()->pushDBusMessageReplyToMainLoop(errorMessage, + std::move(*sharedDbusMessageReplyAsyncHandler)); COMMONAPI_VERBOSE("MethodAsync(dbus): Proxy callback not reachable -> sendMessageWithReplyAsync"); } else { COMMONAPI_ERROR("MethodAsync(dbus): Proxy callback not reachable but callback taken"); @@ -324,6 +325,185 @@ struct DBusProxyHelper<In_<DBusInputStream, DBusOutputStream, InArgs_...>, } }; +template< + template <class ...> class In_, class... InArgs_, + template <class...> class Out_, class... OutArgs_, + class... ErrorEvents_> +struct DBusProxyHelper<In_<DBusInputStream, DBusOutputStream, InArgs_...>, + Out_<DBusInputStream, DBusOutputStream, OutArgs_...>, + ErrorEvents_...> { + + template <typename DBusProxy_ = DBusProxy> + static void callMethodWithReply( + const DBusProxy_ &_proxy, + const DBusMessage &_message, + const CommonAPI::CallInfo *_info, + const InArgs_&... _in, + CommonAPI::CallStatus &_status, + OutArgs_&... _out, + const std::tuple<ErrorEvents_*...> &_errorEvents) { + + 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) { + DBusErrorEventHelper::notifyListeners(reply, + error.getName(), + typename make_sequence_range<sizeof...(ErrorEvents_), 0>::type(), + _errorEvents); + _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 std::string &_method, + const std::string &_signature, + const CommonAPI::CallInfo *_info, + const InArgs_&... _in, + CommonAPI::CallStatus &_status, + OutArgs_&... _out, + const std::tuple<ErrorEvents_*...> &_errorEvents){ +#ifndef WIN32 + static std::mutex callMethodWithReply_mutex_; +#endif + std::lock_guard<std::mutex> lock(callMethodWithReply_mutex_); + + if (_proxy.isAvailable()) { + DBusMessage message = _proxy.createMethodCall(_method, _signature); + callMethodWithReply(_proxy, message, _info, _in..., _status, _out..., _errorEvents); + } else { + _status = CallStatus::NOT_AVAILABLE; + } + } + + template <typename DBusProxy_ = DBusProxy, typename DelegateFunction_> + static std::future<CallStatus> callMethodAsync( + DBusProxy_ &_proxy, + const DBusMessage &_message, + const CommonAPI::CallInfo *_info, + const InArgs_&... _in, + DelegateFunction_ _function, + std::tuple<OutArgs_...> _out, + const std::tuple<ErrorEvents_*...> &_errorEvents) { + 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(); + } + + typename DBusProxyAsyncCallbackHandler<DBusProxy, OutArgs_...>::Delegate delegate( + _proxy.shared_from_this(), _function); + auto dbusMessageReplyAsyncHandler = std::move(DBusProxyAsyncCallbackHandler< + std::tuple<ErrorEvents_*...>, + DBusProxy, + OutArgs_...>::create(delegate, _out, _errorEvents)); + + std::future<CallStatus> callStatusFuture; + try { + callStatusFuture = dbusMessageReplyAsyncHandler->getFuture(); + } catch (std::exception& e) { + COMMONAPI_ERROR("MethodAsync(dbus): messageReplyAsyncHandler future failed(", e.what(), ")"); + } + + if(_proxy.isAvailable()) { + if (_proxy.getDBusConnection()->sendDBusMessageWithReplyAsync( + _message, + std::move(dbusMessageReplyAsyncHandler), + _info)){ + COMMONAPI_VERBOSE("MethodAsync(dbus): Proxy available -> sendMessageWithReplyAsync"); + return callStatusFuture; + } else { + return std::future<CallStatus>(); + } + } else { + std::shared_ptr< std::unique_ptr< DBusProxyConnection::DBusMessageReplyAsyncHandler > > sharedDbusMessageReplyAsyncHandler( + new std::unique_ptr< DBusProxyConnection::DBusMessageReplyAsyncHandler >(std::move(dbusMessageReplyAsyncHandler))); + //async isAvailable call with timeout + COMMONAPI_VERBOSE("MethodAsync(dbus): Proxy not available -> register callback"); + _proxy.isAvailableAsync([&_proxy, _message, sharedDbusMessageReplyAsyncHandler]( + const AvailabilityStatus _status, + const Timeout_t remaining) { + if(_status == AvailabilityStatus::AVAILABLE) { + //create new call info with remaining timeout. Minimal timeout is 100 ms. + Timeout_t newTimeout = remaining; + if(remaining < 100) + newTimeout = 100; + CallInfo newInfo(newTimeout); + if(*sharedDbusMessageReplyAsyncHandler) { + _proxy.getDBusConnection()->sendDBusMessageWithReplyAsync( + _message, + std::move(*sharedDbusMessageReplyAsyncHandler), + &newInfo); + COMMONAPI_VERBOSE("MethodAsync(dbus): Proxy callback available -> sendMessageWithReplyAsync"); + } else { + COMMONAPI_ERROR("MethodAsync(dbus): Proxy callback available but callback taken"); + } + } else { + //create error message and push it directly to the connection + unsigned int dummySerial = 999; + _message.setSerial(dummySerial); //set dummy serial + if (*sharedDbusMessageReplyAsyncHandler) { + DBusMessage errorMessage = _message.createMethodError(DBUS_ERROR_UNKNOWN_METHOD); + _proxy.getDBusConnection()->pushDBusMessageReplyToMainLoop(errorMessage, + std::move(*sharedDbusMessageReplyAsyncHandler)); + COMMONAPI_VERBOSE("MethodAsync(dbus): Proxy callback not reachable -> sendMessageWithReplyAsync"); + } else { + COMMONAPI_ERROR("MethodAsync(dbus): Proxy callback not reachable but callback taken"); + } + } + }, _info); + return callStatusFuture; + } + } + + template <typename DBusProxy_ = DBusProxy, typename DelegateFunction_> + static std::future<CallStatus> callMethodAsync( + DBusProxy_ &_proxy, + const std::string &_method, + const std::string &_signature, + const CommonAPI::CallInfo *_info, + const InArgs_&... _in, + DelegateFunction_ _function, + std::tuple<OutArgs_...> _out, + const std::tuple<ErrorEvents_*...> &_errorEvents) { +#ifndef WIN32 + static std::mutex callMethodAsync_mutex_; +#endif + std::lock_guard<std::mutex> lock(callMethodAsync_mutex_); + + DBusMessage message = _proxy.createMethodCall(_method, _signature); + return callMethodAsync(_proxy, message, _info, _in..., _function, _out, _errorEvents); + } +}; + } // namespace DBus } // namespace CommonAPI diff --git a/include/CommonAPI/DBus/DBusSelectiveEvent.hpp b/include/CommonAPI/DBus/DBusSelectiveEvent.hpp index 1c1ce85..93bb5ea 100644 --- a/include/CommonAPI/DBus/DBusSelectiveEvent.hpp +++ b/include/CommonAPI/DBus/DBusSelectiveEvent.hpp @@ -42,7 +42,7 @@ public: virtual void setSubscriptionToken(const DBusProxyConnection::DBusSignalHandlerToken _subscriptionToken, uint32_t tag) { this->subscription_ = _subscriptionToken; - static_cast<DBusProxy&>(this->proxy_).insertSelectiveSubscription(this->name_, this, tag, this->signature_); + static_cast<DBusProxy&>(this->proxy_).insertSelectiveSubscription(this->name_, this->signalHandler_, tag, this->signature_); } protected: @@ -53,12 +53,12 @@ protected: void onListenerAdded(const Listener &_listener, const uint32_t subscription) { (void) _listener; static_cast<DBusProxy&>(this->proxy_).subscribeForSelectiveBroadcastOnConnection( - this->path_, this->interface_, this->name_, this->signature_, this, subscription); + this->path_, this->interface_, this->name_, this->signature_, this->signalHandler_, subscription); } void onLastListenerRemoved(const Listener &) { static_cast<DBusProxy&>(this->proxy_).unsubscribeFromSelectiveBroadcast( - this->name_, this->subscription_, this); + this->name_, this->subscription_, this->signalHandler_.get()); } }; diff --git a/include/CommonAPI/DBus/DBusServiceRegistry.hpp b/include/CommonAPI/DBus/DBusServiceRegistry.hpp index 00dd355..8a56a91 100644 --- a/include/CommonAPI/DBus/DBusServiceRegistry.hpp +++ b/include/CommonAPI/DBus/DBusServiceRegistry.hpp @@ -58,7 +58,7 @@ class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegist }; // template class DBusServiceListener<> { typedef functor; typedef list; typedef subscription } - typedef std::function<void(const AvailabilityStatus& availabilityStatus)> DBusServiceListener; + typedef std::function<void(std::shared_ptr<DBusProxy>, const AvailabilityStatus& availabilityStatus)> DBusServiceListener; typedef std::list<DBusServiceListener> DBusServiceListenerList; typedef DBusServiceListenerList::iterator DBusServiceSubscription; @@ -82,7 +82,8 @@ class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegist void init(); DBusServiceSubscription subscribeAvailabilityListener(const std::string &_address, - DBusServiceListener _listener); + DBusServiceListener _listener, + std::weak_ptr<DBusProxy> _proxy); void unsubscribeAvailabilityListener(const std::string &_address, DBusServiceSubscription &_listener); @@ -114,12 +115,14 @@ class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegist DBusInterfaceNameListenersRecord(DBusInterfaceNameListenersRecord &&_other) : state(_other.state), listenerList(std::move(_other.listenerList)), - listenersToRemove(std::move(_other.listenersToRemove)) { + listenersToRemove(std::move(_other.listenersToRemove)), + proxy(_other.proxy){ } DBusRecordState state; DBusServiceListenerList listenerList; std::list<DBusServiceSubscription> listenersToRemove; + std::weak_ptr<DBusProxy> proxy; }; typedef std::unordered_map<std::string, DBusInterfaceNameListenersRecord> DBusInterfaceNameListenersMap; @@ -307,9 +310,14 @@ class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegist private: typedef std::map<std::shared_ptr<DBusProxyConnection>, std::shared_ptr<DBusServiceRegistry>> RegistryMap_t; - static RegistryMap_t registries_; + static std::shared_ptr<RegistryMap_t> getRegistryMap() { + static std::shared_ptr<RegistryMap_t> registries(new RegistryMap_t); + return registries; + } static std::mutex registriesMutex_; + std::shared_ptr<RegistryMap_t> registries_; std::shared_ptr<DBusAddressTranslator> translator_; + std::weak_ptr<DBusServiceRegistry> selfReference_; }; diff --git a/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp b/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp index 59d33bc..3a9b7e8 100644 --- a/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp +++ b/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp @@ -487,8 +487,7 @@ class DBusMethodStubDispatcher<StubClass_, In_<InArgs_...>, DeplIn_<DeplIn_Args. std::tuple<CommonAPI::Deployable<InArgs_, DeplIn_Args>...> in_; }; - -template< class, class, class, class, class> +template< class, class, class, class, class...> class DBusMethodWithReplyStubDispatcher; template < @@ -503,76 +502,95 @@ class DBusMethodWithReplyStubDispatcher< In_<InArgs_...>, Out_<OutArgs_...>, DeplIn_<DeplIn_Args...>, - DeplOut_<DeplOutArgs_...> >: + DeplOut_<DeplOutArgs_...>>: public StubDispatcher<StubClass_> { public: typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; 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<DeplIn_Args*...> _inDepArgs, - std::tuple<DeplOutArgs_*...> _outDepArgs): - stubFunctor_(stubFunctor), - dbusReplySignature_(dbusReplySignature), + DBusMethodWithReplyStubDispatcher(StubFunctor_ _stubFunctor, + const char* _dbusReplySignature, + const std::tuple<DeplIn_Args*...>& _inDepArgs, + const std::tuple<DeplOutArgs_*...>& _outDepArgs): out_(_outDepArgs), - currentCall_(0) { + currentCall_(0), + stubFunctor_(_stubFunctor), + dbusReplySignature_(_dbusReplySignature) { initialize(typename make_sequence_range<sizeof...(DeplIn_Args), 0>::type(), _inDepArgs); - } - bool dispatchDBusMessage(const DBusMessage& dbusMessage, - const std::shared_ptr<StubClass_>& stub, + bool dispatchDBusMessage(const DBusMessage& _dbusMessage, + const std::shared_ptr<StubClass_>& _stub, RemoteEventHandlerType* _remoteEventHandler, std::weak_ptr<DBusProxyConnection> _connection) { (void) _remoteEventHandler; connection_ = _connection; return handleDBusMessage( - dbusMessage, - stub, - typename make_sequence_range<sizeof...(InArgs_), 0>::type(), - typename make_sequence_range<sizeof...(OutArgs_), 0>::type()); + _dbusMessage, + _stub, + typename make_sequence_range<sizeof...(InArgs_), 0>::type(), + typename make_sequence_range<sizeof...(OutArgs_), 0>::type()); } - bool sendReply(CommonAPI::CallId_t _call, - std::tuple<CommonAPI::Deployable<OutArgs_, DeplOutArgs_>...> args = std::make_tuple()) { + bool sendReply(const CommonAPI::CallId_t _call, + const std::tuple<CommonAPI::Deployable<OutArgs_, DeplOutArgs_>...> args = std::make_tuple()) { + { + std::lock_guard<std::mutex> lock(mutex_); + auto dbusMessage = pending_.find(_call); + if(dbusMessage != pending_.end()) { + DBusMessage reply = dbusMessage->second.createMethodReturn(dbusReplySignature_); + pending_[_call] = reply; + } else { + return false; + } + } return sendReplyInternal(_call, typename make_sequence_range<sizeof...(OutArgs_), 0>::type(), args); } +protected: + + std::tuple<CommonAPI::Deployable<InArgs_, DeplIn_Args>...> in_; + std::tuple<DeplOutArgs_*...> out_; + CommonAPI::CallId_t currentCall_; + std::map<CommonAPI::CallId_t, DBusMessage> pending_; + std::mutex mutex_; // protects pending_ + + std::weak_ptr<DBusProxyConnection> connection_; + private: template <int... DeplIn_ArgIndices> - inline void initialize(index_sequence<DeplIn_ArgIndices...>, std::tuple<DeplIn_Args*...> &_in) { + inline void initialize(index_sequence<DeplIn_ArgIndices...>, const std::tuple<DeplIn_Args*...>& _in) { in_ = std::make_tuple(std::get<DeplIn_ArgIndices>(_in)...); } template <int... InArgIndices_, int... OutArgIndices_> - inline bool handleDBusMessage(const DBusMessage& dbusMessage, - const std::shared_ptr<StubClass_>& stub, + inline bool handleDBusMessage(const DBusMessage& _dbusMessage, + const std::shared_ptr<StubClass_>& _stub, index_sequence<InArgIndices_...>, index_sequence<OutArgIndices_...>) { if (sizeof...(DeplIn_Args) > 0) { - DBusInputStream dbusInputStream(dbusMessage); + DBusInputStream dbusInputStream(_dbusMessage); const bool success = DBusSerializableArguments<CommonAPI::Deployable<InArgs_, DeplIn_Args>...>::deserialize(dbusInputStream, std::get<InArgIndices_>(in_)...); if (!success) return false; } std::shared_ptr<DBusClientId> clientId - = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender())); - DBusMessage reply = dbusMessage.createMethodReturn(dbusReplySignature_); + = std::make_shared<DBusClientId>(std::string(_dbusMessage.getSender())); CommonAPI::CallId_t call; { std::lock_guard<std::mutex> lock(mutex_); call = currentCall_++; - pending_[call] = reply; + pending_[call] = _dbusMessage; } - (stub.get()->*stubFunctor_)( + (_stub.get()->*stubFunctor_)( clientId, std::move(std::get<InArgIndices_>(in_).getValue())..., [call, this](OutArgs_... _args){ @@ -582,21 +600,21 @@ private: } ); - return true; + return true; } template<int... OutArgIndices_> - bool sendReplyInternal(CommonAPI::CallId_t _call, + bool sendReplyInternal(const CommonAPI::CallId_t _call, index_sequence<OutArgIndices_...>, - std::tuple<CommonAPI::Deployable<OutArgs_, DeplOutArgs_>...> args) { + const std::tuple<CommonAPI::Deployable<OutArgs_, DeplOutArgs_>...>& _args) { std::lock_guard<std::mutex> lock(mutex_); auto reply = pending_.find(_call); if (reply != pending_.end()) { if (sizeof...(DeplOutArgs_) > 0) { DBusOutputStream output(reply->second); if (!DBusSerializableArguments<CommonAPI::Deployable<OutArgs_, DeplOutArgs_>...>::serialize( - output, std::get<OutArgIndices_>(args)...)) { - (void)args; + output, std::get<OutArgIndices_>(_args)...)) { + (void)_args; pending_.erase(_call); return false; } @@ -616,14 +634,157 @@ private: StubFunctor_ stubFunctor_; const char* dbusReplySignature_; +}; - std::tuple<CommonAPI::Deployable<InArgs_, DeplIn_Args>...> in_; - std::tuple<DeplOutArgs_*...> out_; - CommonAPI::CallId_t currentCall_; - std::map<CommonAPI::CallId_t, DBusMessage> pending_; - std::mutex mutex_; // protects pending_ +template < + typename StubClass_, + template <class...> class In_, class... InArgs_, + template <class...> class Out_, class... OutArgs_, + template <class...> class DeplIn_, class... DeplIn_Args, + template <class...> class DeplOut_, class... DeplOutArgs_, + class... ErrorReplies_> - std::weak_ptr<DBusProxyConnection> connection_; +class DBusMethodWithReplyStubDispatcher< + StubClass_, + In_<InArgs_...>, + Out_<OutArgs_...>, + DeplIn_<DeplIn_Args...>, + DeplOut_<DeplOutArgs_...>, + ErrorReplies_...> : + public DBusMethodWithReplyStubDispatcher< + StubClass_, + In_<InArgs_...>, + Out_<OutArgs_...>, + DeplIn_<DeplIn_Args...>, + DeplOut_<DeplOutArgs_...>> { + public: + typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; + typedef std::function<void (OutArgs_...)> ReplyType_t; + + typedef void (StubClass_::*StubFunctor_)( + std::shared_ptr<CommonAPI::ClientId>, CommonAPI::CallId_t, InArgs_..., ReplyType_t, ErrorReplies_...); + + DBusMethodWithReplyStubDispatcher(StubFunctor_ _stubFunctor, + const char* _dbusReplySignature, + const std::tuple<DeplIn_Args*...>& _inDepArgs, + const std::tuple<DeplOutArgs_*...>& _outDepArgs, + const ErrorReplies_... _errorReplies) : + DBusMethodWithReplyStubDispatcher< + StubClass_, + In_<InArgs_...>, + Out_<OutArgs_...>, + DeplIn_<DeplIn_Args...>, + DeplOut_<DeplOutArgs_...>>( + NULL, + _dbusReplySignature, + _inDepArgs, + _outDepArgs), + stubFunctor_(_stubFunctor), + errorReplies_(std::make_tuple(_errorReplies...)) { } + + bool dispatchDBusMessage(const DBusMessage& _dbusMessage, + const std::shared_ptr<StubClass_>& _stub, + RemoteEventHandlerType* _remoteEventHandler, + std::weak_ptr<DBusProxyConnection> _connection) { + (void) _remoteEventHandler; + this->connection_ = _connection; + return handleDBusMessage( + _dbusMessage, + _stub, + typename make_sequence_range<sizeof...(InArgs_), 0>::type(), + typename make_sequence_range<sizeof...(OutArgs_), 0>::type(), + typename make_sequence_range<sizeof...(ErrorReplies_), 0>::type()); + } + + template <class... ErrorReplyOutArgs_, class... ErrorReplyDeplOutArgs_> + bool sendErrorReply(const CommonAPI::CallId_t _call, + const std::string &_signature, + const std::string &_errorName, + const std::tuple<CommonAPI::Deployable<ErrorReplyOutArgs_, ErrorReplyDeplOutArgs_>...>& _args) { + { + std::lock_guard<std::mutex> lock(this->mutex_); + auto dbusMessage = this->pending_.find(_call); + if(dbusMessage != this->pending_.end()) { + DBusMessage reply = dbusMessage->second.createMethodError(_errorName, _signature); + this->pending_[_call] = reply; + } else { + return false; + } + } + return sendErrorReplyInternal(_call, typename make_sequence_range<sizeof...(ErrorReplyOutArgs_), 0>::type(), _args); + } + +private: + + template <int... InArgIndices_, int... OutArgIndices_, int... ErrorRepliesIndices_> + inline bool handleDBusMessage(const DBusMessage& _dbusMessage, + const std::shared_ptr<StubClass_>& _stub, + index_sequence<InArgIndices_...>, + index_sequence<OutArgIndices_...>, + index_sequence<ErrorRepliesIndices_...>) { + if (sizeof...(DeplIn_Args) > 0) { + DBusInputStream dbusInputStream(_dbusMessage); + const bool success = DBusSerializableArguments<CommonAPI::Deployable<InArgs_, DeplIn_Args>...>::deserialize(dbusInputStream, std::get<InArgIndices_>(this->in_)...); + if (!success) + return false; + } + + std::shared_ptr<DBusClientId> clientId + = std::make_shared<DBusClientId>(std::string(_dbusMessage.getSender())); + + CommonAPI::CallId_t call; + { + std::lock_guard<std::mutex> lock(this->mutex_); + call = this->currentCall_++; + this->pending_[call] = _dbusMessage; + } + + (_stub.get()->*stubFunctor_)( + clientId, + call, + std::move(std::get<InArgIndices_>(this->in_).getValue())..., + [call, this](OutArgs_... _args){ + this->sendReply(call, std::make_tuple(CommonAPI::Deployable<OutArgs_, DeplOutArgs_>( + _args, std::get<OutArgIndices_>(this->out_) + )...)); + }, + std::get<ErrorRepliesIndices_>(errorReplies_)... + ); + + return true; + } + + template<int... ErrorReplyOutArgIndices_, class... ErrorReplyOutArgs_, class ...ErrorReplyDeplOutArgs_> + bool sendErrorReplyInternal(CommonAPI::CallId_t _call, + index_sequence<ErrorReplyOutArgIndices_...>, + const std::tuple<CommonAPI::Deployable<ErrorReplyOutArgs_, ErrorReplyDeplOutArgs_>...>& _args) { + std::lock_guard<std::mutex> lock(this->mutex_); + auto reply = this->pending_.find(_call); + if (reply != this->pending_.end()) { + if (sizeof...(ErrorReplyDeplOutArgs_) > 0) { + DBusOutputStream output(reply->second); + if (!DBusSerializableArguments<CommonAPI::Deployable<ErrorReplyOutArgs_, ErrorReplyDeplOutArgs_>...>::serialize( + output, std::get<ErrorReplyOutArgIndices_>(_args)...)) { + (void)_args; + this->pending_.erase(_call); + return false; + } + output.flush(); + } + if (std::shared_ptr<DBusProxyConnection> connection = this->connection_.lock()) { + bool isSuccessful = connection->sendDBusMessage(reply->second); + this->pending_.erase(_call); + return isSuccessful; + } + else { + return false; + } + } + return false; + } + + StubFunctor_ stubFunctor_; + std::tuple<ErrorReplies_...> errorReplies_; }; template< class, class, class, class > |