diff options
author | Jürgen Gehring <Juergen.Gehring@bmw.de> | 2016-10-11 03:33:43 -0700 |
---|---|---|
committer | Jürgen Gehring <Juergen.Gehring@bmw.de> | 2016-10-11 03:33:43 -0700 |
commit | 8518d74e952ff0dbbb430e944fc3bee1b879f881 (patch) | |
tree | b9eca882899e33663ccf8c127050fcc4746d5957 /include/CommonAPI | |
parent | bdf7ab8cf3243619f0b8bc526f07e5b03624b94c (diff) | |
download | genivi-common-api-dbus-runtime-8518d74e952ff0dbbb430e944fc3bee1b879f881.tar.gz |
CommonAPI-D-Bus 3.1.93.1.9
Diffstat (limited to 'include/CommonAPI')
-rw-r--r-- | include/CommonAPI/DBus/DBusConnection.hpp | 107 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusDaemonProxy.hpp | 61 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusFactory.hpp | 9 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp | 18 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusInputStream.hpp | 2 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp | 139 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusMainLoopContext.hpp | 68 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusProxy.hpp | 26 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp | 7 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusProxyConnection.hpp | 15 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusProxyHelper.hpp | 46 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusProxyManager.hpp | 28 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusSelectiveEvent.hpp | 2 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusServiceRegistry.hpp | 73 | ||||
-rw-r--r-- | include/CommonAPI/DBus/DBusStubAdapterHelper.hpp | 399 |
15 files changed, 616 insertions, 384 deletions
diff --git a/include/CommonAPI/DBus/DBusConnection.hpp b/include/CommonAPI/DBus/DBusConnection.hpp index f79dc27..b32274f 100644 --- a/include/CommonAPI/DBus/DBusConnection.hpp +++ b/include/CommonAPI/DBus/DBusConnection.hpp @@ -26,6 +26,54 @@ namespace CommonAPI { namespace DBus { +class DBusConnection; + +struct QueueEntry { + QueueEntry() { } + virtual ~QueueEntry() { } + + virtual void process(std::shared_ptr<DBusConnection> _connection) = 0; + virtual void clear() = 0; +}; + +struct MsgQueueEntry : QueueEntry { + MsgQueueEntry(DBusMessage _message) : + message_(_message) { } + virtual ~MsgQueueEntry() { } + DBusMessage message_; + + virtual void process(std::shared_ptr<DBusConnection> _connection); + virtual void clear(); + }; + +struct MsgReplyQueueEntry : MsgQueueEntry { + MsgReplyQueueEntry(DBusProxyConnection::DBusMessageReplyAsyncHandler* _replyAsyncHandler, + DBusMessage _reply) : + MsgQueueEntry(_reply), + replyAsyncHandler_(_replyAsyncHandler) { } + virtual ~MsgReplyQueueEntry() { } + + DBusProxyConnection::DBusMessageReplyAsyncHandler* replyAsyncHandler_; + + void process(std::shared_ptr<DBusConnection> _connection); + void clear(); +}; + +template<class Function, class... Arguments> +struct FunctionQueueEntry : QueueEntry { + + using bindType = decltype(std::bind(std::declval<Function>(),std::declval<Arguments>()...)); + + FunctionQueueEntry(Function&& _function, + Arguments&& ... _args): + bind_(std::forward<Function>(_function), std::forward<Arguments>(_args)...) { } + + bindType bind_; + + void process(std::shared_ptr<DBusConnection> _connection); + void clear(); +}; + class DBusMainLoop; class DBusObjectManager; @@ -55,6 +103,16 @@ struct WatchContext { std::weak_ptr<DBusConnection> dbusConnection_; }; +struct TimeoutContext { + TimeoutContext(std::weak_ptr<MainLoopContext> mainLoopContext, + std::weak_ptr<DBusConnection> dbusConnection) : + mainLoopContext_(mainLoopContext), dbusConnection_(dbusConnection) { + } + + std::weak_ptr<MainLoopContext> mainLoopContext_; + std::weak_ptr<DBusConnection> dbusConnection_; +}; + class DBusConnection : public DBusProxyConnection, public std::enable_shared_from_this<DBusConnection> { @@ -88,7 +146,7 @@ public: COMMONAPI_EXPORT bool sendDBusMessage(const DBusMessage& dbusMessage/*, uint32_t* allocatedSerial = NULL*/) const; - COMMONAPI_EXPORT std::future<CallStatus> sendDBusMessageWithReplyAsync( + COMMONAPI_EXPORT bool sendDBusMessageWithReplyAsync( const DBusMessage& dbusMessage, std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler, const CommonAPI::CallInfo *_info) const; @@ -150,9 +208,17 @@ public: COMMONAPI_EXPORT bool setDispatching(bool isDispatching); - COMMONAPI_EXPORT void pushDBusMessageReply(const DBusMessage& _reply, + template<class Function, class... Arguments> + COMMONAPI_EXPORT void processFunctionQueueEntry(FunctionQueueEntry<Function, Arguments ...> &_functionQueueEntry); + + COMMONAPI_EXPORT void pushDBusMessageReplyToMainLoop(const DBusMessage& _reply, std::unique_ptr<DBusMessageReplyAsyncHandler> _dbusMessageReplyAsyncHandler); + template<class Function, class... Arguments> + COMMONAPI_EXPORT void proxyPushFunctionToMainLoop(Function&& _function, Arguments&& ... _args); + + COMMONAPI_EXPORT void setPendingCallTimedOut(DBusPendingCall* _pendingCall, ::DBusTimeout* _timeout) const; + #ifdef COMMONAPI_DBUS_TEST inline std::weak_ptr<DBusMainloop> getLoop() { return loop_; } #endif @@ -179,10 +245,11 @@ public: std::thread* dispatchThread_; std::weak_ptr<MainLoopContext> mainLoopContext_; - DBusMessageWatch* msgWatch_; - DBusMessageDispatchSource* msgDispatchSource_; + DBusQueueWatch* queueWatch_; + DBusQueueDispatchSource* queueDispatchSource_; DispatchSource* dispatchSource_; WatchContext* watchContext_; + TimeoutContext* timeoutContext_; COMMONAPI_EXPORT void addLibdbusSignalMatchRule(const std::string& objectPath, const std::string& interfaceName, @@ -227,8 +294,8 @@ public: COMMONAPI_EXPORT void enforceAsynchronousTimeouts() const; COMMONAPI_EXPORT static const DBusObjectPathVTable* getDBusObjectPathVTable(); - COMMONAPI_EXPORT void sendPendingSelectiveSubscription(DBusProxy* proxy, std::string methodName, - DBusSignalHandler* dbusSignalHandler, uint32_t tag); + COMMONAPI_EXPORT void sendPendingSelectiveSubscription(DBusProxy* proxy, std::string interfaceMemberName, + DBusSignalHandler* dbusSignalHandler, uint32_t tag, std::string interfaceMemberSignature); ::DBusConnection* connection_; mutable std::mutex connectionGuard_; @@ -270,7 +337,7 @@ public: typedef std::pair< DBusPendingCall*, std::tuple< - std::chrono::time_point<std::chrono::high_resolution_clock>, + std::chrono::steady_clock::time_point, DBusMessageReplyAsyncHandler*, DBusMessage > @@ -278,7 +345,7 @@ public: mutable std::map< DBusPendingCall*, std::tuple< - std::chrono::time_point<std::chrono::high_resolution_clock>, + std::chrono::steady_clock::time_point, DBusMessageReplyAsyncHandler*, DBusMessage > @@ -320,6 +387,30 @@ public: }; +template<class Function, class... Arguments> +void FunctionQueueEntry<Function, Arguments ...>::process(std::shared_ptr<DBusConnection> _connection) { + _connection->processFunctionQueueEntry(*this); +} + +template<class Function, class... Arguments> +void FunctionQueueEntry<Function, Arguments ...>::clear() { +} + +template<class Function, class... Arguments> +void DBusConnection::processFunctionQueueEntry(FunctionQueueEntry<Function, Arguments ...> &_functionQueueEntry) { + _functionQueueEntry.bind_(); +} + +template<class Function, class... Arguments> +void DBusConnection::proxyPushFunctionToMainLoop(Function&& _function, Arguments&& ... _args) { + if (auto lockedContext = mainLoopContext_.lock()) { + std::shared_ptr<FunctionQueueEntry<Function, Arguments ...>> functionQueueEntry = std::make_shared<FunctionQueueEntry<Function, Arguments ...>>( + std::forward<Function>(_function), std::forward<Arguments>(_args) ...); + queueWatch_->pushQueue(functionQueueEntry); + } +} + + } // namespace DBus } // namespace CommonAPI diff --git a/include/CommonAPI/DBus/DBusDaemonProxy.hpp b/include/CommonAPI/DBus/DBusDaemonProxy.hpp index 0652654..44b882b 100644 --- a/include/CommonAPI/DBus/DBusDaemonProxy.hpp +++ b/include/CommonAPI/DBus/DBusDaemonProxy.hpp @@ -79,10 +79,25 @@ class DBusDaemonProxy : public DBusProxyBase, COMMONAPI_EXPORT std::future<CallStatus> listNamesAsync(typename DBusProxyAsyncCallbackHandler<DelegateObjectType, std::vector<std::string>>::Delegate& delegate) const { DBusMessage dbusMessage = createMethodCall("ListNames", ""); - return getDBusConnection()->sendDBusMessageWithReplyAsync( + + auto dbusMessageReplyAsyncHandler = std::move(DBusProxyAsyncCallbackHandler< + DelegateObjectType, std::vector< std::string > >::create(delegate, std::tuple<std::vector<std::string>>())); + + std::future<CallStatus> callStatusFuture; + try { + callStatusFuture = dbusMessageReplyAsyncHandler->getFuture(); + } catch (std::exception& e) { + COMMONAPI_ERROR("getNameOwnerAsync: messageReplyAsyncHandler future failed(", e.what(), ")"); + } + + if(getDBusConnection()->sendDBusMessageWithReplyAsync( dbusMessage, - DBusProxyAsyncCallbackHandler<DelegateObjectType, std::vector<std::string>>::create(delegate, std::tuple<std::vector<std::string>>()), - &daemonProxyInfo); + std::move(dbusMessageReplyAsyncHandler), + &daemonProxyInfo)) { + return callStatusFuture; + } else { + return std::future<CallStatus>(); + } } COMMONAPI_EXPORT void nameHasOwner(const std::string& busName, CommonAPI::CallStatus& callStatus, bool& hasOwner) const; @@ -102,10 +117,24 @@ class DBusDaemonProxy : public DBusProxyBase, } outputStream.flush(); - return getDBusConnection()->sendDBusMessageWithReplyAsync( + auto dbusMessageReplyAsyncHandler = std::move(DBusProxyAsyncCallbackHandler< + DelegateObjectType, bool >::create(delegate, std::tuple< bool >())); + + std::future<CallStatus> callStatusFuture; + try { + callStatusFuture = dbusMessageReplyAsyncHandler->getFuture(); + } catch (std::exception& e) { + COMMONAPI_ERROR("getNameOwnerAsync: messageReplyAsyncHandler future failed(", e.what(), ")"); + } + + if (getDBusConnection()->sendDBusMessageWithReplyAsync( dbusMessage, - DBusProxyAsyncCallbackHandler<DelegateObjectType, bool>::create(delegate, std::tuple<bool>()), - &daemonProxyInfo); + std::move(dbusMessageReplyAsyncHandler), + &daemonProxyInfo)) { + return callStatusFuture; + } else { + return std::future<CallStatus>(); + } } template <typename DelegateObjectType> @@ -146,10 +175,24 @@ class DBusDaemonProxy : public DBusProxyBase, } outputStream.flush(); - return getDBusConnection()->sendDBusMessageWithReplyAsync( + auto dbusMessageReplyAsyncHandler = std::move(DBusProxyAsyncCallbackHandler< + DelegateObjectType, std::string>::create(delegate, std::tuple<std::string>())); + + std::future<CallStatus> callStatusFuture; + try { + callStatusFuture = dbusMessageReplyAsyncHandler->getFuture(); + } catch (std::exception& e) { + COMMONAPI_ERROR("getNameOwnerAsync: messageReplyAsyncHandler future failed(", e.what(), ")"); + } + + if (getDBusConnection()->sendDBusMessageWithReplyAsync( dbusMessage, - DBusProxyAsyncCallbackHandler<DelegateObjectType, std::string>::create(delegate, std::tuple<std::string>()), - &daemonProxyInfo); + std::move(dbusMessageReplyAsyncHandler), + &daemonProxyInfo)) { + return callStatusFuture; + } else { + return std::future<CallStatus>(); + } } private: diff --git a/include/CommonAPI/DBus/DBusFactory.hpp b/include/CommonAPI/DBus/DBusFactory.hpp index 6ce0c7e..51ec476 100644 --- a/include/CommonAPI/DBus/DBusFactory.hpp +++ b/include/CommonAPI/DBus/DBusFactory.hpp @@ -89,14 +89,14 @@ public: COMMONAPI_EXPORT bool registerManagedService(const std::shared_ptr<DBusStubAdapter> &_adapter); COMMONAPI_EXPORT bool unregisterManagedService(const std::string &_address); - COMMONAPI_EXPORT void incrementConnection(std::shared_ptr<DBusProxyConnection>); COMMONAPI_EXPORT void decrementConnection(std::shared_ptr<DBusProxyConnection>); - COMMONAPI_EXPORT void releaseConnection(const ConnectionId_t&, MainLoopContext*); + COMMONAPI_EXPORT void releaseConnection(const ConnectionId_t&); // Initialization COMMONAPI_EXPORT void registerInterface(InterfaceInitFunction _function); private: + COMMONAPI_EXPORT void incrementConnection(std::shared_ptr<DBusProxyConnection>); COMMONAPI_EXPORT std::shared_ptr<DBusConnection> getConnection(const ConnectionId_t &); COMMONAPI_EXPORT std::shared_ptr<DBusConnection> getConnection(std::shared_ptr<MainLoopContext>); COMMONAPI_EXPORT bool registerStubAdapter(std::shared_ptr<DBusStubAdapter>); @@ -109,12 +109,9 @@ private: private: static std::shared_ptr<Factory> theFactory; - std::mutex connectionsMutex_; + std::recursive_mutex connectionsMutex_; std::map<ConnectionId_t, std::shared_ptr<DBusConnection>> connections_; - std::mutex contextConnectionsMutex_; - std::map<MainLoopContext *, std::shared_ptr<DBusConnection>> contextConnections_; - std::map<std::string, ProxyCreateFunction> proxyCreateFunctions_; std::map<std::string, StubAdapterCreateFunction> stubAdapterCreateFunctions_; diff --git a/include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp b/include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp index ec55f4e..d5abcca 100644 --- a/include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp +++ b/include/CommonAPI/DBus/DBusFreedesktopStubAdapterHelper.hpp @@ -41,7 +41,6 @@ class DBusGetFreedesktopAttributeStubDispatcher : public virtual DBusGetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>, public virtual DBusGetFreedesktopAttributeStubDispatcherBase<StubClass_> { public: - typedef DBusStubAdapterHelper<StubClass_> DBusStubAdapterHelperType; typedef typename DBusGetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::GetStubFunctor GetStubFunctor; DBusGetFreedesktopAttributeStubDispatcher(GetStubFunctor _getStubFunctor, AttributeDepl_ *_depl = nullptr) @@ -63,7 +62,7 @@ public: } protected: - virtual bool sendAttributeValueReply(const DBusMessage &_message, const std::shared_ptr<StubClass_> &_stub, DBusStubAdapterHelperType &_helper) { + virtual bool sendAttributeValueReply(const DBusMessage &_message, const std::shared_ptr<StubClass_> &_stub, std::weak_ptr<DBusProxyConnection> connection_) { DBusMessage reply = _message.createMethodReturn(DBusGetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::signature_); VariantDeployment<AttributeDepl_> actualDepl(true, DBusGetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::depl_); @@ -74,8 +73,11 @@ protected: DBusOutputStream output(reply); output << deployedVariant; output.flush(); - - return _helper.getDBusConnection()->sendDBusMessage(reply); + if (std::shared_ptr<DBusProxyConnection> connection = connection_.lock()) { + return connection->sendDBusMessage(reply); + } else { + return false; + } } }; @@ -85,8 +87,7 @@ class DBusSetFreedesktopAttributeStubDispatcher public virtual DBusSetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_> { public: typedef typename DBusGetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::GetStubFunctor GetStubFunctor; - typedef typename DBusGetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::DBusStubAdapterHelperType DBusStubAdapterHelperType; - typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType; + typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(std::shared_ptr<CommonAPI::ClientId>, AttributeType_); typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)(); @@ -122,11 +123,10 @@ class DBusSetFreedesktopObservableAttributeStubDispatcher : public virtual DBusSetFreedesktopAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>, public virtual DBusSetObservableAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_> { public: - typedef typename DBusSetFreedesktopAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::DBusStubAdapterHelperType DBusStubAdapterHelperType; - typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType; typedef typename DBusSetFreedesktopAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::GetStubFunctor GetStubFunctor; typedef typename DBusSetFreedesktopAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::OnRemoteSetFunctor OnRemoteSetFunctor; typedef typename DBusSetFreedesktopAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::OnRemoteChangedFunctor OnRemoteChangedFunctor; + typedef typename StubClass_::StubAdapterType StubAdapterType; typedef void (StubAdapterType::*FireChangedFunctor)(const AttributeType_&); DBusSetFreedesktopObservableAttributeStubDispatcher( @@ -177,7 +177,7 @@ struct DBusStubFreedesktopPropertiesSignalHelper { "PropertiesChanged", "sa{sv}as", _stub.getDBusConnection(), - _stub.getInterface(), + _stub.getDBusAddress().getInterface(), deployedChangedProperties, invalidatedProperties); } diff --git a/include/CommonAPI/DBus/DBusInputStream.hpp b/include/CommonAPI/DBus/DBusInputStream.hpp index ec6c7d0..61e4133 100644 --- a/include/CommonAPI/DBus/DBusInputStream.hpp +++ b/include/CommonAPI/DBus/DBusInputStream.hpp @@ -454,7 +454,7 @@ public: char * raw = _readRaw(sizeof(double)); if (!hasError()) { - _value = (float) (*(reinterpret_cast<double*>(raw))); + _value = float(*(reinterpret_cast<double*>(raw))); } return (*this); } diff --git a/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp b/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp index ec2d70f..1f5bcc2 100644 --- a/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp +++ b/include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp @@ -15,11 +15,10 @@ #include <string> #include <vector> +#include <CommonAPI/Export.hpp> #include <CommonAPI/ProxyManager.hpp> -#include <CommonAPI/DBus/DBusAddressTranslator.hpp> #include <CommonAPI/DBus/DBusProxy.hpp> #include <CommonAPI/DBus/DBusObjectManagerStub.hpp> -#include <CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp> #include <CommonAPI/DBus/DBusTypes.hpp> namespace CommonAPI { @@ -30,115 +29,61 @@ class DBusInstanceAvailabilityStatusChangedEvent: public ProxyManager::InstanceAvailabilityStatusChangedEvent, public DBusProxyConnection::DBusSignalHandler { public: - DBusInstanceAvailabilityStatusChangedEvent(DBusProxy &_proxy, const std::string &_interfaceName) : - proxy_(_proxy), - observedInterfaceName_(_interfaceName) { - } - - virtual ~DBusInstanceAvailabilityStatusChangedEvent() { - proxy_.removeSignalMemberHandler(interfacesAddedSubscription_, this); - proxy_.removeSignalMemberHandler(interfacesRemovedSubscription_, this); - } - - virtual void onSignalDBusMessage(const DBusMessage& dbusMessage) { - if (dbusMessage.hasMemberName("InterfacesAdded")) { - onInterfacesAddedSignal(dbusMessage); - } else if (dbusMessage.hasMemberName("InterfacesRemoved")) { - onInterfacesRemovedSignal(dbusMessage); - } - } + + typedef std::function<void(const CallStatus &, const std::vector<DBusAddress> &)> GetAvailableServiceInstancesCallback; + + COMMONAPI_EXPORT DBusInstanceAvailabilityStatusChangedEvent(DBusProxy &_proxy, + const std::string &_dbusInterfaceName, + const std::string &_capiInterfaceName); + + 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); + + COMMONAPI_EXPORT void getServiceInstanceAvailabilityStatus(const std::string &_instance, + CallStatus &_callStatus, + AvailabilityStatus &_availabilityStatus); + COMMONAPI_EXPORT std::future<CallStatus> getServiceInstanceAvailabilityStatusAsync(const std::string& _instance, + ProxyManager::GetInstanceAvailabilityStatusCallback _callback); protected: - virtual void onFirstListenerAdded(const Listener&) { - interfacesAddedSubscription_ = proxy_.addSignalMemberHandler( - proxy_.getDBusAddress().getObjectPath(), - DBusObjectManagerStub::getInterfaceName(), - "InterfacesAdded", - "oa{sa{sv}}", - this, - false); - - interfacesRemovedSubscription_ = proxy_.addSignalMemberHandler( - proxy_.getDBusAddress().getObjectPath(), - DBusObjectManagerStub::getInterfaceName(), - "InterfacesRemoved", - "oas", - this, - false); - } - - virtual void onLastListenerRemoved(const Listener&) { - proxy_.removeSignalMemberHandler(interfacesAddedSubscription_, this); - proxy_.removeSignalMemberHandler(interfacesRemovedSubscription_, this); - } + virtual void onFirstListenerAdded(const Listener&); + virtual void onLastListenerRemoved(const Listener&); private: - inline void onInterfacesAddedSignal(const DBusMessage &_message) { - DBusInputStream dbusInputStream(_message); - std::string dbusObjectPath; - std::string dbusInterfaceName; - DBusInterfacesAndPropertiesDict dbusInterfacesAndPropertiesDict; - - dbusInputStream >> dbusObjectPath; - if (dbusInputStream.hasError()) { - COMMONAPI_ERROR(std::string(__FUNCTION__) + " failed to read object path"); - } - - dbusInputStream.beginReadMapOfSerializableStructs(); - while (!dbusInputStream.readMapCompleted()) { - dbusInputStream.align(8); - dbusInputStream >> dbusInterfaceName; - dbusInputStream.skipMap(); - if (dbusInputStream.hasError()) { - COMMONAPI_ERROR(std::string(__FUNCTION__) + " failed to read interface name"); - } - if(dbusInterfaceName == observedInterfaceName_) { - notifyInterfaceStatusChanged(dbusObjectPath, dbusInterfaceName, AvailabilityStatus::AVAILABLE); - } - } - dbusInputStream.endReadMapOfSerializableStructs(); - } - - inline void onInterfacesRemovedSignal(const DBusMessage &_message) { - DBusInputStream dbusInputStream(_message); - std::string dbusObjectPath; - std::vector<std::string> dbusInterfaceNames; - - dbusInputStream >> dbusObjectPath; - if (dbusInputStream.hasError()) { - COMMONAPI_ERROR(std::string(__FUNCTION__) + " failed to read object path"); - } - - dbusInputStream >> dbusInterfaceNames; - if (dbusInputStream.hasError()) { - COMMONAPI_ERROR(std::string(__FUNCTION__) + " failed to read interface names"); - } - - for (const auto& dbusInterfaceName : dbusInterfaceNames) { - if(dbusInterfaceName == observedInterfaceName_) { - notifyInterfaceStatusChanged(dbusObjectPath, dbusInterfaceName, AvailabilityStatus::NOT_AVAILABLE); - } - } - } + + void onInterfacesAddedSignal(const DBusMessage &_message); + + void onInterfacesRemovedSignal(const DBusMessage &_message); void notifyInterfaceStatusChanged(const std::string &_objectPath, const std::string &_interfaceName, - const AvailabilityStatus &_availability) { - CommonAPI::Address itsAddress; - DBusAddress itsDBusAddress(proxy_.getDBusAddress().getService(), - _objectPath, - _interfaceName); + const AvailabilityStatus &_availability); - DBusAddressTranslator::get()->translate(itsDBusAddress, itsAddress); + bool addInterface(const std::string &_dbusObjectPath, + const std::string &_dbusInterfaceName); + bool removeInterface(const std::string &_dbusObjectPath, + const std::string &_dbusInterfaceName); - notifyListeners(itsAddress.getAddress(), _availability); - } + void serviceInstancesAsyncCallback(std::shared_ptr<Proxy> _proxy, + const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict _dict, + GetAvailableServiceInstancesCallback &_call, + std::shared_ptr<std::promise<CallStatus> > &_promise); + void translate(const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict &_dict, + std::vector<DBusAddress> &_serviceInstances); DBusProxy &proxy_; - std::string observedInterfaceName_; + std::string observedDbusInterfaceName_; + std::string observedCapiInterfaceName_; DBusProxyConnection::DBusSignalHandlerToken interfacesAddedSubscription_; DBusProxyConnection::DBusSignalHandlerToken interfacesRemovedSubscription_; + std::mutex interfacesMutex_; + std::map<std::string, std::set<std::string>> interfaces_; + const std::shared_ptr<DBusServiceRegistry> registry_; }; } // namespace DBus diff --git a/include/CommonAPI/DBus/DBusMainLoopContext.hpp b/include/CommonAPI/DBus/DBusMainLoopContext.hpp index c048c90..6de84f8 100644 --- a/include/CommonAPI/DBus/DBusMainLoopContext.hpp +++ b/include/CommonAPI/DBus/DBusMainLoopContext.hpp @@ -38,18 +38,18 @@ class DBusDispatchSource: public DispatchSource { DBusConnection* dbusConnection_; }; -class DBusMessageWatch; -class DBusMessageDispatchSource: public DispatchSource { +class DBusQueueWatch; +class DBusQueueDispatchSource: public DispatchSource { public: - DBusMessageDispatchSource(DBusMessageWatch* watch); - virtual ~DBusMessageDispatchSource(); + DBusQueueDispatchSource(DBusQueueWatch* watch); + virtual ~DBusQueueDispatchSource(); bool prepare(int64_t& timeout); bool check(); bool dispatch(); private: - DBusMessageWatch* watch_; + DBusQueueWatch* watch_; std::mutex watchMutex_; }; @@ -88,32 +88,13 @@ class DBusWatch: public Watch { #endif }; -class DBusMessageWatch : public Watch { -public: - - struct MsgQueueEntry { - MsgQueueEntry(DBusMessage _message) : - message_(_message) { } - DBusMessage message_; - - virtual void process(std::shared_ptr<DBusConnection> _connection) = 0; - virtual void clear(); - }; +struct QueueEntry; - struct MsgReplyQueueEntry : MsgQueueEntry { - MsgReplyQueueEntry(DBusProxyConnection::DBusMessageReplyAsyncHandler* _replyAsyncHandler, - DBusMessage _reply) : - MsgQueueEntry(_reply), - replyAsyncHandler_(_replyAsyncHandler) { } - - DBusProxyConnection::DBusMessageReplyAsyncHandler* replyAsyncHandler_; - - void process(std::shared_ptr<DBusConnection> _connection); - void clear(); - }; +class DBusQueueWatch : public Watch { +public: - DBusMessageWatch(std::shared_ptr<DBusConnection> _connection); - virtual ~DBusMessageWatch(); + DBusQueueWatch(std::shared_ptr<DBusConnection> _connection); + virtual ~DBusQueueWatch(); void dispatch(unsigned int eventFlags); @@ -129,24 +110,24 @@ public: void removeDependentDispatchSource(CommonAPI::DispatchSource* _dispatchSource); - void pushMsgQueue(std::shared_ptr<MsgQueueEntry> _queueEntry); + void pushQueue(std::shared_ptr<QueueEntry> _queueEntry); - void popMsgQueue(); + void popQueue(); - std::shared_ptr<MsgQueueEntry> frontMsgQueue(); + std::shared_ptr<QueueEntry> frontQueue(); - bool emptyMsgQueue(); + bool emptyQueue(); - void processMsgQueueEntry(std::shared_ptr<MsgQueueEntry> _queueEntry); + void processQueueEntry(std::shared_ptr<QueueEntry> _queueEntry); private: int pipeFileDescriptors_[2]; pollfd pollFileDescriptor_; std::vector<CommonAPI::DispatchSource*> dependentDispatchSources_; - std::queue<std::shared_ptr<MsgQueueEntry>> msgQueue_; + std::queue<std::shared_ptr<QueueEntry>> queue_; - std::mutex msgQueueMutex_; + std::mutex queueMutex_; std::weak_ptr<DBusConnection> connection_; @@ -161,7 +142,9 @@ private: class DBusTimeout: public Timeout { public: - DBusTimeout(::DBusTimeout* libdbusTimeout, std::weak_ptr<MainLoopContext>& mainLoopContext); + DBusTimeout(::DBusTimeout* libdbusTimeout, + std::weak_ptr<MainLoopContext>& mainLoopContext, + std::weak_ptr<DBusConnection>& dbusConnection); bool isReadyToBeMonitored(); void startMonitoring(); @@ -171,12 +154,23 @@ class DBusTimeout: public Timeout { int64_t getTimeoutInterval() const; int64_t getReadyTime() const; + + void setPendingCall(DBusPendingCall* _pendingCall); + +#ifdef WIN32 + __declspec(thread) static DBusTimeout *currentTimeout_; +#else + thread_local static DBusTimeout *currentTimeout_; +#endif + private: void recalculateDueTime(); int64_t dueTimeInMs_; ::DBusTimeout* libdbusTimeout_; std::weak_ptr<MainLoopContext> mainLoopContext_; + std::weak_ptr<DBusConnection> dbusConnection_; + DBusPendingCall *pendingCall_; }; diff --git a/include/CommonAPI/DBus/DBusProxy.hpp b/include/CommonAPI/DBus/DBusProxy.hpp index c8a57bc..072e356 100644 --- a/include/CommonAPI/DBus/DBusProxy.hpp +++ b/include/CommonAPI/DBus/DBusProxy.hpp @@ -30,9 +30,13 @@ class DBusProxyStatusEvent virtual ~DBusProxyStatusEvent() {} protected: - virtual void onListenerAdded(const Listener& listener, const Subscription subscription); + virtual void onListenerAdded(const Listener& _listener, const Subscription _subscription); + virtual void onListenerRemoved(const Listener &_listener, const Subscription _subscription); DBusProxy* dbusProxy_; + + std::recursive_mutex listenersMutex_; + std::vector<std::pair<ProxyStatusEvent::Subscription, ProxyStatusEvent::Listener>> listeners_; }; @@ -44,6 +48,8 @@ public: const std::shared_ptr<DBusProxyConnection> &_connection); COMMONAPI_EXPORT virtual ~DBusProxy(); + COMMONAPI_EXPORT AvailabilityStatus getAvailabilityStatus() const; + COMMONAPI_EXPORT virtual ProxyStatusEvent& getProxyStatusEvent(); COMMONAPI_EXPORT virtual InterfaceVersionAttribute& getInterfaceVersionAttribute(); @@ -61,8 +67,10 @@ public: DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, uint32_t tag); - COMMONAPI_EXPORT void insertSelectiveSubscription(const std::string& interfaceMemberName, - DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, uint32_t tag); + COMMONAPI_EXPORT void insertSelectiveSubscription( + const std::string& interfaceMemberName, + DBusProxyConnection::DBusSignalHandler* dbusSignalHandler, + uint32_t tag, std::string interfaceMemberSignature); COMMONAPI_EXPORT void unsubscribeFromSelectiveBroadcast(const std::string& eventName, DBusProxyConnection::DBusSignalHandlerToken subscription, const DBusProxyConnection::DBusSignalHandler* dbusSignalHandler); @@ -101,6 +109,10 @@ public: const std::string &interfaceName, const std::string &propertyName); + COMMONAPI_EXPORT virtual void notifySpecificListener(std::weak_ptr<DBusProxy> _dbusProxy, + const ProxyStatusEvent::Listener &_listener, + const ProxyStatusEvent::Subscription _subscription); + private: typedef std::tuple< const std::string, @@ -142,7 +154,9 @@ private: std::list<SignalMemberHandlerTuple> signalMemberHandlerQueue_; mutable std::mutex signalMemberHandlerQueueMutex_; - std::map<std::string, std::pair<DBusProxyConnection::DBusSignalHandler*, uint32_t>> selectiveBroadcastHandlers; + std::map<std::string, + std::tuple<DBusProxyConnection::DBusSignalHandler*, uint32_t, + std::string>> selectiveBroadcastHandlers; mutable std::mutex selectiveBroadcastHandlersMutex_; mutable std::shared_ptr<std::thread> availabilityTimeoutThread_; @@ -151,11 +165,13 @@ private: mutable std::condition_variable availabilityTimeoutCondition_; typedef std::tuple< - std::chrono::time_point<std::chrono::high_resolution_clock>, + std::chrono::steady_clock::time_point, isAvailableAsyncCallback, 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 c36ccb1..1a00adc 100644 --- a/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp +++ b/include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp @@ -53,7 +53,10 @@ class DBusProxyAsyncCallbackHandler: timeoutOccurred_(false), hasToBeDeleted_(false) { } - virtual ~DBusProxyAsyncCallbackHandler() {} + virtual ~DBusProxyAsyncCallbackHandler() { + // free assigned std::function<> immediately + delegate_.function_ = [](CallStatus, ArgTypes_...) {}; + } virtual std::future<CallStatus> getFuture() { return promise_.get_future(); @@ -76,8 +79,6 @@ class DBusProxyAsyncCallbackHandler: virtual void setExecutionFinished() { executionFinished_ = true; - // free assigned std::function<> immediately - delegate_.function_ = [](CallStatus, ArgTypes_...) {}; } virtual bool getExecutionFinished() { diff --git a/include/CommonAPI/DBus/DBusProxyConnection.hpp b/include/CommonAPI/DBus/DBusProxyConnection.hpp index 8f7a1c8..6065a8b 100644 --- a/include/CommonAPI/DBus/DBusProxyConnection.hpp +++ b/include/CommonAPI/DBus/DBusProxyConnection.hpp @@ -83,7 +83,7 @@ class DBusProxyConnection { virtual bool sendDBusMessage(const DBusMessage& dbusMessage) const = 0; - virtual std::future<CallStatus> sendDBusMessageWithReplyAsync( + virtual bool sendDBusMessageWithReplyAsync( const DBusMessage& dbusMessage, std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler, const CommonAPI::CallInfo *_info) const = 0; @@ -137,11 +137,18 @@ class DBusProxyConnection { virtual bool hasDispatchThread() = 0; - virtual void sendPendingSelectiveSubscription(DBusProxy* proxy, std::string methodName, - DBusSignalHandler* dbusSignalHandler, uint32_t tag) = 0; + virtual void sendPendingSelectiveSubscription( + DBusProxy* proxy, std::string interfaceMemberName, + DBusSignalHandler* dbusSignalHandler, uint32_t tag, + std::string interfaceMemberSignature) = 0; - virtual void pushDBusMessageReply(const DBusMessage& reply, + virtual void pushDBusMessageReplyToMainLoop(const DBusMessage& reply, std::unique_ptr<DBusMessageReplyAsyncHandler> dbusMessageReplyAsyncHandler) = 0; + + template<class DBusConnection, class Function, class... Arguments> + void proxyPushFunctionToMainLoop(Function&& _function, Arguments&& ... _args) { + static_cast<DBusConnection*>(this)->proxyPushFunctionToMainLoop(std::forward<Function>(_function), std::forward<Arguments>(_args) ...); + } }; } // namespace DBus diff --git a/include/CommonAPI/DBus/DBusProxyHelper.hpp b/include/CommonAPI/DBus/DBusProxyHelper.hpp index cb5b942..8bd0154 100644 --- a/include/CommonAPI/DBus/DBusProxyHelper.hpp +++ b/include/CommonAPI/DBus/DBusProxyHelper.hpp @@ -196,19 +196,33 @@ struct DBusProxyHelper<In_<DBusInputStream, DBusOutputStream, InArgs_...>, typename DBusProxyAsyncCallbackHandler< DBusProxy, OutArgs_... >::Delegate delegate(_proxy.shared_from_this(), _function); - auto dbusMessageReplyAsyncHandler = DBusProxyAsyncCallbackHandler< + auto dbusMessageReplyAsyncHandler = std::move(DBusProxyAsyncCallbackHandler< DBusProxy, OutArgs_... - >::create(delegate, _out).release(); + >::create(delegate, _out)); + + std::future<CallStatus> callStatusFuture; + try { + callStatusFuture = dbusMessageReplyAsyncHandler->getFuture(); + } catch (std::exception& e) { + COMMONAPI_ERROR("MethodAsync(dbus): messageReplyAsyncHandler future failed(", e.what(), ")"); + } if(_proxy.isAvailable()) { - return _proxy.getDBusConnection()->sendDBusMessageWithReplyAsync( + if (_proxy.getDBusConnection()->sendDBusMessageWithReplyAsync( _message, - std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler>(dbusMessageReplyAsyncHandler), - _info); + 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 - _proxy.isAvailableAsync([&_proxy, _message, _info, - _out, dbusMessageReplyAsyncHandler, _function]( + COMMONAPI_VERBOSE("MethodAsync(dbus): Proxy not available -> register calback"); + _proxy.isAvailableAsync([&_proxy, _message, sharedDbusMessageReplyAsyncHandler]( const AvailabilityStatus _status, const Timeout_t remaining) { if(_status == AvailabilityStatus::AVAILABLE) { @@ -217,20 +231,30 @@ struct DBusProxyHelper<In_<DBusInputStream, DBusOutputStream, InArgs_...>, if(remaining < 100) newTimeout = 100; CallInfo newInfo(newTimeout); + if(*sharedDbusMessageReplyAsyncHandler) { _proxy.getDBusConnection()->sendDBusMessageWithReplyAsync( _message, - std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler>(dbusMessageReplyAsyncHandler), + 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()->pushDBusMessageReply(errorMessage, - std::unique_ptr<DBusProxyConnection::DBusMessageReplyAsyncHandler>(dbusMessageReplyAsyncHandler)); + _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 dbusMessageReplyAsyncHandler->getFuture(); + return callStatusFuture; } } diff --git a/include/CommonAPI/DBus/DBusProxyManager.hpp b/include/CommonAPI/DBus/DBusProxyManager.hpp index ff28a26..1dd8dbe 100644 --- a/include/CommonAPI/DBus/DBusProxyManager.hpp +++ b/include/CommonAPI/DBus/DBusProxyManager.hpp @@ -29,41 +29,39 @@ namespace DBus { class COMMONAPI_EXPORT_CLASS_EXPLICIT DBusProxyManager: public ProxyManager { public: COMMONAPI_EXPORT DBusProxyManager(DBusProxy &_proxy, - const std::string &_interfaceName); + const std::string &_dbusInterfaceName, + const std::string &_capiInterfaceName); COMMONAPI_EXPORT const std::string &getDomain() const; COMMONAPI_EXPORT const std::string &getInterface() const; COMMONAPI_EXPORT const ConnectionId_t &getConnectionId() const; - COMMONAPI_EXPORT virtual void getAvailableInstances(CommonAPI::CallStatus &, std::vector<std::string> &_instances); + COMMONAPI_EXPORT virtual void getAvailableInstances(CommonAPI::CallStatus &_status, std::vector<std::string> &_instances); COMMONAPI_EXPORT virtual std::future<CallStatus> getAvailableInstancesAsync(GetAvailableInstancesCallback _callback); - COMMONAPI_EXPORT virtual void getInstanceAvailabilityStatus(const std::string &_address, + COMMONAPI_EXPORT virtual void getInstanceAvailabilityStatus(const std::string &_instance, CallStatus &_callStatus, AvailabilityStatus &_availabilityStatus); COMMONAPI_EXPORT virtual std::future<CallStatus> getInstanceAvailabilityStatusAsync( - const std::string&, - GetInstanceAvailabilityStatusCallback callback); + const std::string& _instance, + GetInstanceAvailabilityStatusCallback _callback); COMMONAPI_EXPORT virtual InstanceAvailabilityStatusChangedEvent& getInstanceAvailabilityStatusChangedEvent(); private: - COMMONAPI_EXPORT void instancesAsyncCallback(const CommonAPI::CallStatus& status, - const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict& dict, - GetAvailableInstancesCallback& call); + COMMONAPI_EXPORT void instancesAsyncCallback(std::shared_ptr<Proxy> _proxy, + const CommonAPI::CallStatus &_status, + const std::vector<DBusAddress> &_availableServiceInstances, + GetAvailableInstancesCallback &_call); - COMMONAPI_EXPORT void instanceAliveAsyncCallback(const AvailabilityStatus &_alive, - GetInstanceAvailabilityStatusCallback &_call, - std::shared_ptr<std::promise<CallStatus>> &_status); - - COMMONAPI_EXPORT void translateCommonApiAddresses(const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict &_dict, + COMMONAPI_EXPORT void translate(const std::vector<DBusAddress> &_serviceInstances, std::vector<std::string> &_instances); DBusProxy &proxy_; DBusInstanceAvailabilityStatusChangedEvent instanceAvailabilityStatusEvent_; - const std::string interfaceId_; - const std::shared_ptr<DBusServiceRegistry> registry_; + const std::string dbusInterfaceId_; + const std::string capiInterfaceId_; ConnectionId_t connectionId_; }; diff --git a/include/CommonAPI/DBus/DBusSelectiveEvent.hpp b/include/CommonAPI/DBus/DBusSelectiveEvent.hpp index 627a17b..1c1ce85 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); + static_cast<DBusProxy&>(this->proxy_).insertSelectiveSubscription(this->name_, this, tag, this->signature_); } protected: diff --git a/include/CommonAPI/DBus/DBusServiceRegistry.hpp b/include/CommonAPI/DBus/DBusServiceRegistry.hpp index 17e7139..00dd355 100644 --- a/include/CommonAPI/DBus/DBusServiceRegistry.hpp +++ b/include/CommonAPI/DBus/DBusServiceRegistry.hpp @@ -67,6 +67,8 @@ class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegist typedef std::list<DBusManagedInterfaceListener> DBusManagedInterfaceListenerList; typedef DBusManagedInterfaceListenerList::iterator DBusManagedInterfaceSubscription; + typedef std::function<void(const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict)> GetAvailableServiceInstancesCallback; + static std::shared_ptr<DBusServiceRegistry> get(std::shared_ptr<DBusProxyConnection> _connection); static void remove(std::shared_ptr<DBusProxyConnection> _connection); @@ -91,12 +93,13 @@ class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegist const std::string &_dbusObjectPath); - virtual std::vector<std::string> getAvailableServiceInstances(const std::string &_interface, - const std::string &_domain = "local"); + virtual void getAvailableServiceInstances(const std::string& dbusServiceName, + const std::string& dbusObjectPath, + DBusObjectManagerStub::DBusObjectPathAndInterfacesDict& availableServiceInstances); - virtual void getAvailableServiceInstancesAsync(CommonAPI::Factory::AvailableInstancesCbk_t _cbk, - const std::string &_interface, - const std::string &_domain = "local"); + virtual void getAvailableServiceInstancesAsync(GetAvailableServiceInstancesCallback callback, + const std::string& dbusServiceName, + const std::string& dbusObjectPath); virtual void onSignalDBusMessage(const DBusMessage&); @@ -110,11 +113,13 @@ class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegist DBusInterfaceNameListenersRecord(DBusInterfaceNameListenersRecord &&_other) : state(_other.state), - listenerList(std::move(_other.listenerList)) { + listenerList(std::move(_other.listenerList)), + listenersToRemove(std::move(_other.listenersToRemove)) { } DBusRecordState state; DBusServiceListenerList listenerList; + std::list<DBusServiceSubscription> listenersToRemove; }; typedef std::unordered_map<std::string, DBusInterfaceNameListenersRecord> DBusInterfaceNameListenersMap; @@ -200,7 +205,7 @@ class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegist std::unordered_map<std::string, DBusUniqueNameRecord*> dbusServiceNameMap_; // protects the dbus service maps - std::mutex dbusServicesMutex_; + std::recursive_mutex dbusServicesMutex_; void resolveDBusServiceName(const std::string& dbusServiceName, DBusServiceListenersRecord& dbusServiceListenersRecord); @@ -222,24 +227,23 @@ class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegist void releaseDBusObjectPathCacheReference(const std::string& dbusObjectPath, const DBusServiceListenersRecord& dbusServiceListenersRecord); + bool resolveObjectPathWithObjectManager(const std::string& dbusServiceUniqueName, const std::string& dbusObjectPath); + typedef std::function<void(const CallStatus&, const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict, const std::string&, const std::string&)> GetManagedObjectsCallback; - bool resolveObjectPathWithObjectManager(const std::string& dbusServiceUniqueName, const std::string& dbusObjectPath); - - bool getManagedObjects(const std::string& dbusServiceUniqueName, + bool getManagedObjects(const std::string& dbusServiceName, const std::string& dbusObjectPath, - GetManagedObjectsCallback callback); + DBusObjectManagerStub::DBusObjectPathAndInterfacesDict& availableServiceInstances); - void onGetManagedObjectsCallbackResolve(const CallStatus& callStatus, - const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict dbusObjectPathAndInterfacesDict, - const std::string& dbusServiceUniqueName, - const std::string& dbusObjectPath); + bool getManagedObjectsAsync(const std::string& dbusServiceName, + const std::string& dbusObjectPath, + GetManagedObjectsCallback callback); - void onGetManagedObjectsCallbackResolveFurther(const CallStatus& callStatus, - const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict dbusObjectPathAndInterfacesDict, + void onGetManagedObjectsCallbackResolve(const CallStatus& callStatus, + const DBusObjectManagerStub::DBusObjectPathAndInterfacesDict availableServiceInstances, const std::string& dbusServiceUniqueName, const std::string& dbusObjectPath); @@ -247,33 +251,6 @@ class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegist const std::string& dbusServiceUniqueName, const std::string& interfaceName); - bool introspectDBusObjectPath(const std::string& dbusServiceUniqueName, const std::string& dbusObjectPath); - - void onIntrospectCallback(const CallStatus& status, - std::string xmlData, - const std::string& dbusServiceName, - const std::string& dbusObjectPath); - - void parseIntrospectionData(const std::string& xmlData, - const std::string& rootObjectPath, - const std::string& dbusServiceUniqueName); - - void parseIntrospectionNode(const pugi::xml_node& node, - const std::string& rootObjectPath, - const std::string& fullObjectPath, - const std::string& dbusServiceUniqueName); - - void processIntrospectionObjectPath(const pugi::xml_node& node, - const std::string& rootObjectPath, - const std::string& dbusServiceUniqueName); - - void processIntrospectionInterface(const pugi::xml_node& node, - const std::string& rootObjectPath, - const std::string& fullObjectPath, - const std::string& dbusServiceUniqueName); - - void onDBusDaemonProxyStatusEvent(const AvailabilityStatus& availabilityStatus); - void onDBusDaemonProxyNameOwnerChangedEvent(const std::string& name, const std::string& oldOwner, const std::string& newOwner); @@ -313,14 +290,6 @@ class DBusServiceRegistry: public std::enable_shared_from_this<DBusServiceRegist bool findCachedDbusService(const std::string& dbusServiceName, DBusUniqueNameRecord** uniqueNameRecord); bool findCachedObjectPath(const std::string& dbusObjectPathName, const DBusUniqueNameRecord* uniqueNameRecord, DBusObjectPathCache* objectPathCache); - std::condition_variable monitorResolveAllServices_; - std::mutex mutexServiceResolveCount; - int servicesToResolve; - - std::condition_variable monitorResolveAllObjectPaths_; - std::mutex mutexObjectPathsResolveCount; - int objectPathsToResolve; - void fetchAllServiceNames(); inline bool isDBusServiceName(const std::string &_name) { diff --git a/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp b/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp index 42d7301..59d33bc 100644 --- a/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp +++ b/include/CommonAPI/DBus/DBusStubAdapterHelper.hpp @@ -27,59 +27,112 @@ namespace CommonAPI { namespace DBus { -class StubDispatcherBase { +template <typename StubClass_> +class StubDispatcher { public: - virtual ~StubDispatcherBase() { } -}; - + typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; + virtual ~StubDispatcher() {} + virtual bool dispatchDBusMessage(const DBusMessage &_message, + const std::shared_ptr<StubClass_> &_stub, + RemoteEventHandlerType* _remoteEventHandler, + std::weak_ptr<DBusProxyConnection> _connection_) = 0; + virtual void appendGetAllReply(const DBusMessage &_message, + const std::shared_ptr<StubClass_> &_stub, + DBusOutputStream &_output) { + (void)_message; + (void)_stub; + (void)_output; + } +}; +template <typename StubClass_> struct DBusAttributeDispatcherStruct { - StubDispatcherBase* getter; - StubDispatcherBase* setter; + StubDispatcher<StubClass_>* getter; + StubDispatcher<StubClass_>* setter; - DBusAttributeDispatcherStruct(StubDispatcherBase* g, StubDispatcherBase* s) { + DBusAttributeDispatcherStruct(StubDispatcher<StubClass_>* g, StubDispatcher<StubClass_>* s) { getter = g; setter = s; } }; -typedef std::unordered_map<std::string, DBusAttributeDispatcherStruct> StubAttributeTable; +template <typename T> +struct identity { typedef T type; }; -template <typename StubClass_> -class DBusStubAdapterHelper: public virtual DBusStubAdapter { +// interfaceMemberName, interfaceMemberSignature +typedef std::pair<const char*, const char*> DBusInterfaceMemberPath; + +template <typename... Stubs_> +class DBusStubAdapterHelper { +public: + DBusStubAdapterHelper(const DBusAddress &_address, + const std::shared_ptr<DBusProxyConnection> &_connection, + const bool _isManaging, + const std::shared_ptr<StubBase> &_stub) { + (void)_address; + (void)_connection; + (void) _isManaging; + (void) _stub; + } +protected: + bool findDispatcherAndHandle(const DBusMessage& dbusMessage, DBusInterfaceMemberPath& dbusInterfaceMemberPath) { + (void) dbusMessage; + (void) dbusInterfaceMemberPath; + return false; + } + bool findAttributeGetDispatcherAndHandle(std::string interfaceName, std::string attributeName, const DBusMessage &_message) { + (void) interfaceName; + (void) attributeName; + (void) _message; + return false; + } + bool findAttributeSetDispatcherAndHandle(std::string interfaceName, std::string attributeName, const DBusMessage &_message) { + (void) interfaceName; + (void) attributeName; + (void) _message; + return false; + } + bool appendGetAllReply(const DBusMessage& dbusMessage, DBusOutputStream& dbusOutputStream) { + (void) dbusMessage; + (void) dbusOutputStream; + return true; + } +public: + template <typename Stub_> + void addStubDispatcher(DBusInterfaceMemberPath _dbusInterfaceMemberPath, + StubDispatcher<Stub_>* _stubDispatcher) { + (void) _dbusInterfaceMemberPath; + (void) _stubDispatcher; + } + template <typename RemoteEventHandlerType> + void setRemoteEventHandler(RemoteEventHandlerType * _remoteEventHandler) { + (void) _remoteEventHandler; + } + +}; + +template <typename StubClass_, typename... Stubs_> +class DBusStubAdapterHelper<StubClass_, Stubs_...>: + public virtual DBusStubAdapter, + public DBusStubAdapterHelper<Stubs_...> { public: typedef typename StubClass_::StubAdapterType StubAdapterType; typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; - class StubDispatcher: public StubDispatcherBase { - public: - virtual ~StubDispatcher() {} - virtual bool dispatchDBusMessage(const DBusMessage &_message, - const std::shared_ptr<StubClass_> &_stub, - DBusStubAdapterHelper<StubClass_> &_helper) = 0; - virtual void appendGetAllReply(const DBusMessage &_message, - const std::shared_ptr<StubClass_> &_stub, - DBusStubAdapterHelper<StubClass_> &_helper, - DBusOutputStream &_output) { - (void)_message; - (void)_stub; - (void)_helper; - (void)_output; - } - }; - // interfaceMemberName, interfaceMemberSignature - typedef std::pair<const char*, const char*> DBusInterfaceMemberPath; - typedef std::unordered_map<DBusInterfaceMemberPath, StubDispatcherBase*> StubDispatcherTable; + typedef std::unordered_map<DBusInterfaceMemberPath, StubDispatcher<StubClass_>*> StubDispatcherTable; + typedef std::unordered_map<std::string, DBusAttributeDispatcherStruct<StubClass_>> StubAttributeTable; DBusStubAdapterHelper(const DBusAddress &_address, const std::shared_ptr<DBusProxyConnection> &_connection, - const std::shared_ptr<StubClass_> &_stub, - const bool _isManaging): + const bool _isManaging, + const std::shared_ptr<StubBase> &_stub) : + DBusStubAdapter(_address, _connection, _isManaging), - stub_(_stub), + DBusStubAdapterHelper<Stubs_...>(_address, _connection, _isManaging, _stub), remoteEventHandler_(nullptr) { + stub_ = std::dynamic_pointer_cast<StubClass_>(_stub); } virtual ~DBusStubAdapterHelper() { @@ -91,6 +144,12 @@ class DBusStubAdapterHelper: public virtual DBusStubAdapter { DBusStubAdapter::init(instance); std::shared_ptr<StubAdapterType> stubAdapter = std::dynamic_pointer_cast<StubAdapterType>(instance); remoteEventHandler_ = stub_->initStubAdapter(stubAdapter); + DBusStubAdapterHelper<Stubs_...>::setRemoteEventHandler(remoteEventHandler_); + } + + void setRemoteEventHandler(RemoteEventHandlerType* _remoteEventHandler) { + remoteEventHandler_ = _remoteEventHandler; + DBusStubAdapterHelper<Stubs_...>::setRemoteEventHandler(remoteEventHandler_); } virtual void deinit() { @@ -115,16 +174,21 @@ class DBusStubAdapterHelper: public virtual DBusStubAdapter { COMMONAPI_ERROR(std::string(__FUNCTION__), " signature empty"); } - DBusInterfaceMemberPath dbusInterfaceMemberPath(interfaceMemberName, interfaceMemberSignature); - auto findIterator = getStubDispatcherTable().find(dbusInterfaceMemberPath); - const bool foundInterfaceMemberHandler = (findIterator != getStubDispatcherTable().end()); + DBusInterfaceMemberPath dbusInterfaceMemberPath = {interfaceMemberName, interfaceMemberSignature}; + return findDispatcherAndHandle(dbusMessage, dbusInterfaceMemberPath); + } + + bool findDispatcherAndHandle(const DBusMessage& dbusMessage, DBusInterfaceMemberPath& dbusInterfaceMemberPath) { + auto findIterator = stubDispatcherTable_.find(dbusInterfaceMemberPath); + const bool foundInterfaceMemberHandler = (findIterator != stubDispatcherTable_.end()); bool dbusMessageHandled = false; if (foundInterfaceMemberHandler) { - StubDispatcher* stubDispatcher = static_cast<StubDispatcher*>(findIterator->second); - dbusMessageHandled = stubDispatcher->dispatchDBusMessage(dbusMessage, stub_, *this); + StubDispatcher<StubClass_>* stubDispatcher = findIterator->second; + dbusMessageHandled = stubDispatcher->dispatchDBusMessage(dbusMessage, stub_, getRemoteEventHandler(), getDBusConnection()); + return dbusMessageHandled; } - return dbusMessageHandled; + return DBusStubAdapterHelper<Stubs_...>::findDispatcherAndHandle(dbusMessage, dbusInterfaceMemberPath); } virtual bool onInterfaceDBusFreedesktopPropertiesMessage(const DBusMessage &_message) { @@ -141,13 +205,26 @@ class DBusStubAdapterHelper: public virtual DBusStubAdapter { return false; } - virtual const StubDispatcherTable& getStubDispatcherTable() = 0; - virtual const StubAttributeTable& getStubAttributeTable() = 0; + template <typename Stub_> + void addStubDispatcher(DBusInterfaceMemberPath _dbusInterfaceMemberPath, + StubDispatcher<Stub_>* _stubDispatcher) { + addStubDispatcher(_dbusInterfaceMemberPath, _stubDispatcher, identity<Stub_>()); + } + + template <typename Stub_> + void addAttributeDispatcher(std::string _key, + StubDispatcher<Stub_>* _stubDispatcherGetter, + StubDispatcher<Stub_>* _stubDispatcherSetter) { + addAttributeDispatcher(_key, _stubDispatcherGetter, _stubDispatcherSetter, identity<Stub_>()); + } std::shared_ptr<StubClass_> stub_; RemoteEventHandlerType* remoteEventHandler_; + StubDispatcherTable stubDispatcherTable_; + StubAttributeTable stubAttributeTable_; + +protected: - private: bool handleFreedesktopGet(const DBusMessage &_message, DBusInputStream &_input) { std::string interfaceName; std::string attributeName; @@ -157,18 +234,23 @@ class DBusStubAdapterHelper: public virtual DBusStubAdapter { if (_input.hasError()) { return false; } + return findAttributeGetDispatcherAndHandle(interfaceName, attributeName, _message); + } - auto attributeDispatcherIterator = getStubAttributeTable().find(attributeName); - if (attributeDispatcherIterator == getStubAttributeTable().end()) { - return false; + bool findAttributeGetDispatcherAndHandle(std::string interfaceName, std::string attributeName, const DBusMessage &_message) { + + auto attributeDispatcherIterator = stubAttributeTable_.find(attributeName); + if (attributeDispatcherIterator == stubAttributeTable_.end()) { + // not found, try parent + return DBusStubAdapterHelper<Stubs_...>::findAttributeGetDispatcherAndHandle(interfaceName, attributeName, _message); } - StubDispatcher* getterDispatcher = static_cast<StubDispatcher*>(attributeDispatcherIterator->second.getter); + StubDispatcher<StubClass_>* getterDispatcher = attributeDispatcherIterator->second.getter; if (NULL == getterDispatcher) { // all attributes have at least a getter COMMONAPI_ERROR(std::string(__FUNCTION__), "getterDispatcher == NULL"); return false; } else { - return (getterDispatcher->dispatchDBusMessage(_message, stub_, *this)); + return getterDispatcher->dispatchDBusMessage(_message, stub_, getRemoteEventHandler(), getDBusConnection()); } } @@ -182,54 +264,98 @@ class DBusStubAdapterHelper: public virtual DBusStubAdapter { return false; } - auto attributeDispatcherIterator = getStubAttributeTable().find(attributeName); - if(attributeDispatcherIterator == getStubAttributeTable().end()) { - return false; - } + return findAttributeSetDispatcherAndHandle(interfaceName, attributeName, dbusMessage); + } - StubDispatcher *setterDispatcher = static_cast<StubDispatcher*>(attributeDispatcherIterator->second.setter); - if (setterDispatcher == NULL) { // readonly attributes do not have a setter - return false; - } + bool findAttributeSetDispatcherAndHandle(std::string interfaceName, std::string attributeName, const DBusMessage& dbusMessage) { - return setterDispatcher->dispatchDBusMessage(dbusMessage, stub_, *this); - } + auto attributeDispatcherIterator = stubAttributeTable_.find(attributeName); + if(attributeDispatcherIterator == stubAttributeTable_.end()) { + // not found, try parent + return DBusStubAdapterHelper<Stubs_...>::findAttributeSetDispatcherAndHandle(interfaceName, attributeName, dbusMessage); - bool handleFreedesktopGetAll(const DBusMessage& dbusMessage, DBusInputStream& dbusInputStream) { - std::string interfaceName; - dbusInputStream >> interfaceName; + } - if(dbusInputStream.hasError()) { + StubDispatcher<StubClass_> *setterDispatcher = attributeDispatcherIterator->second.setter; + if (setterDispatcher == NULL) { // readonly attributes do not have a setter return false; } - DBusMessage dbusMessageReply = dbusMessage.createMethodReturn("a{sv}"); - DBusOutputStream dbusOutputStream(dbusMessageReply); - - dbusOutputStream.beginWriteMap(); + return setterDispatcher->dispatchDBusMessage(dbusMessage, stub_, getRemoteEventHandler(), getDBusConnection()); + } - std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender())); - for(auto attributeDispatcherIterator = getStubAttributeTable().begin(); attributeDispatcherIterator != getStubAttributeTable().end(); attributeDispatcherIterator++) { + bool appendGetAllReply(const DBusMessage& dbusMessage, DBusOutputStream& dbusOutputStream) + { + for(auto attributeDispatcherIterator = stubAttributeTable_.begin(); attributeDispatcherIterator != stubAttributeTable_.end(); attributeDispatcherIterator++) { //To prevent the destruction of the stub whilst still handling a message if (stub_) { - StubDispatcher* getterDispatcher = static_cast<StubDispatcher*>(attributeDispatcherIterator->second.getter); + StubDispatcher<StubClass_>* getterDispatcher = attributeDispatcherIterator->second.getter; if (NULL == getterDispatcher) { // all attributes have at least a getter COMMONAPI_ERROR(std::string(__FUNCTION__), "getterDispatcher == NULL"); - break; + return false; } else { dbusOutputStream.align(8); dbusOutputStream << attributeDispatcherIterator->first; - getterDispatcher->appendGetAllReply(dbusMessage, stub_, *this, dbusOutputStream); + getterDispatcher->appendGetAllReply(dbusMessage, stub_, dbusOutputStream); } } } + return DBusStubAdapterHelper<Stubs_...>::appendGetAllReply(dbusMessage, dbusOutputStream); + } - dbusOutputStream.endWriteMap(); - dbusOutputStream.flush(); + private: + + template <typename Stub_> + void addStubDispatcher(DBusInterfaceMemberPath _dbusInterfaceMemberPath, + StubDispatcher<Stub_>* _stubDispatcher, + identity<Stub_>) { + DBusStubAdapterHelper<Stubs_...>::addStubDispatcher(_dbusInterfaceMemberPath, _stubDispatcher); + + } + + void addStubDispatcher(DBusInterfaceMemberPath _dbusInterfaceMemberPath, + StubDispatcher<StubClass_>* _stubDispatcher, + identity<StubClass_>) { + stubDispatcherTable_.insert({_dbusInterfaceMemberPath, _stubDispatcher}); + + } + + template <typename Stub_> + void addAttributeDispatcher(std::string _key, + StubDispatcher<Stub_>* _stubDispatcherGetter, + StubDispatcher<Stub_>* _stubDispatcherSetter, + identity<Stub_>) { + DBusStubAdapterHelper<Stubs_...>::addAttributeDispatcher(_key, _stubDispatcherGetter, _stubDispatcherSetter); + + } + + void addAttributeDispatcher(std::string _key, + StubDispatcher<StubClass_>* _stubDispatcherGetter, + StubDispatcher<StubClass_>* _stubDispatcherSetter, + identity<StubClass_>) { + stubAttributeTable_.insert({_key, {_stubDispatcherGetter, _stubDispatcherSetter}}); + } + + bool handleFreedesktopGetAll(const DBusMessage& dbusMessage, DBusInputStream& dbusInputStream) { + std::string interfaceName; + dbusInputStream >> interfaceName; + + if(dbusInputStream.hasError()) { + return false; + } + + DBusMessage dbusMessageReply = dbusMessage.createMethodReturn("a{sv}"); + DBusOutputStream dbusOutputStream(dbusMessageReply); + + dbusOutputStream.beginWriteMap(); + appendGetAllReply(dbusMessage, dbusOutputStream); + dbusOutputStream.endWriteMap(); + dbusOutputStream.flush(); + + return getDBusConnection()->sendDBusMessage(dbusMessageReply); + } - return getDBusConnection()->sendDBusMessage(dbusMessageReply); - } }; template< class > @@ -313,9 +439,10 @@ template < template <class...> class In_, class... InArgs_, template <class...> class DeplIn_, class... DeplIn_Args> -class DBusMethodStubDispatcher<StubClass_, In_<InArgs_...>, DeplIn_<DeplIn_Args...> >: public DBusStubAdapterHelper<StubClass_>::StubDispatcher { +class DBusMethodStubDispatcher<StubClass_, In_<InArgs_...>, DeplIn_<DeplIn_Args...> >: public StubDispatcher<StubClass_> { public: - typedef DBusStubAdapterHelper<StubClass_> DBusStubAdapterHelperType; + + typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; typedef void (StubClass_::*StubFunctor_)(std::shared_ptr<CommonAPI::ClientId>, InArgs_...); DBusMethodStubDispatcher(StubFunctor_ stubFunctor, std::tuple<DeplIn_Args*...> _in): @@ -323,8 +450,12 @@ class DBusMethodStubDispatcher<StubClass_, In_<InArgs_...>, DeplIn_<DeplIn_Args. initialize(typename make_sequence_range<sizeof...(DeplIn_Args), 0>::type(), _in); } - bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { - return handleDBusMessage(dbusMessage, stub, dbusStubAdapterHelper, typename make_sequence_range<sizeof...(InArgs_), 0>::type()); + bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, + RemoteEventHandlerType* _remoteEventHandler, + std::weak_ptr<DBusProxyConnection> _connection) { + (void) _remoteEventHandler; + (void) _connection; + return handleDBusMessage(dbusMessage, stub, typename make_sequence_range<sizeof...(InArgs_), 0>::type()); } private: @@ -336,9 +467,7 @@ class DBusMethodStubDispatcher<StubClass_, In_<InArgs_...>, DeplIn_<DeplIn_Args. template <int... InArgIndices_> inline bool handleDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, - DBusStubAdapterHelperType& dbusStubAdapterHelper, index_sequence<InArgIndices_...>) { - (void)dbusStubAdapterHelper; if (sizeof...(InArgs_) > 0) { DBusInputStream dbusInputStream(dbusMessage); @@ -375,15 +504,15 @@ class DBusMethodWithReplyStubDispatcher< Out_<OutArgs_...>, DeplIn_<DeplIn_Args...>, DeplOut_<DeplOutArgs_...> >: - public DBusStubAdapterHelper<StubClass_>::StubDispatcher { + public StubDispatcher<StubClass_> { public: - typedef DBusStubAdapterHelper<StubClass_> DBusStubAdapterHelperType; + 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, + const char* dbusReplySignature, std::tuple<DeplIn_Args*...> _inDepArgs, std::tuple<DeplOutArgs_*...> _outDepArgs): stubFunctor_(stubFunctor), @@ -395,19 +524,20 @@ class DBusMethodWithReplyStubDispatcher< } - bool dispatchDBusMessage(const DBusMessage& dbusMessage, + bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, - DBusStubAdapterHelperType& dbusStubAdapterHelper) { - connection_ = dbusStubAdapterHelper.getDBusConnection(); + RemoteEventHandlerType* _remoteEventHandler, + std::weak_ptr<DBusProxyConnection> _connection) { + (void) _remoteEventHandler; + connection_ = _connection; return handleDBusMessage( dbusMessage, stub, - dbusStubAdapterHelper, typename make_sequence_range<sizeof...(InArgs_), 0>::type(), typename make_sequence_range<sizeof...(OutArgs_), 0>::type()); } - bool sendReply(CommonAPI::CallId_t _call, + bool sendReply(CommonAPI::CallId_t _call, std::tuple<CommonAPI::Deployable<OutArgs_, DeplOutArgs_>...> args = std::make_tuple()) { return sendReplyInternal(_call, typename make_sequence_range<sizeof...(OutArgs_), 0>::type(), args); } @@ -419,14 +549,11 @@ private: 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, - DBusStubAdapterHelperType& dbusStubAdapterHelper, index_sequence<InArgIndices_...>, index_sequence<OutArgIndices_...>) { - (void)dbusStubAdapterHelper; if (sizeof...(DeplIn_Args) > 0) { DBusInputStream dbusInputStream(dbusMessage); const bool success = DBusSerializableArguments<CommonAPI::Deployable<InArgs_, DeplIn_Args>...>::deserialize(dbusInputStream, std::get<InArgIndices_>(in_)...); @@ -508,23 +635,28 @@ template < template <class...> class In_, class... InArgs_, template <class...> class Out_, class... OutArgs_> class DBusMethodWithReplyAdapterDispatcher<StubClass_, StubAdapterClass_, In_<InArgs_...>, Out_<OutArgs_...> >: - public DBusStubAdapterHelper<StubClass_>::StubDispatcher { + public StubDispatcher<StubClass_> { public: - typedef DBusStubAdapterHelper<StubClass_> DBusStubAdapterHelperType; + typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; typedef void (StubAdapterClass_::*StubFunctor_)(std::shared_ptr<CommonAPI::ClientId>, InArgs_..., OutArgs_&...); - typedef typename CommonAPI::Stub<typename DBusStubAdapterHelperType::StubAdapterType, typename StubClass_::RemoteEventType> StubType; + typedef typename CommonAPI::Stub<typename StubClass_::StubAdapterType, typename StubClass_::RemoteEventType> StubType; DBusMethodWithReplyAdapterDispatcher(StubFunctor_ stubFunctor, const char* dbusReplySignature): stubFunctor_(stubFunctor), dbusReplySignature_(dbusReplySignature) { } - bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { + bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, + RemoteEventHandlerType* _remoteEventHandler, + std::weak_ptr<DBusProxyConnection> _connection) { + + (void)_remoteEventHandler; + std::tuple<InArgs_..., OutArgs_...> argTuple; return handleDBusMessage( dbusMessage, stub, - dbusStubAdapterHelper, + _connection, typename make_sequence_range<sizeof...(InArgs_), 0>::type(), typename make_sequence_range<sizeof...(OutArgs_), sizeof...(InArgs_)>::type(),argTuple); } @@ -533,7 +665,7 @@ class DBusMethodWithReplyAdapterDispatcher<StubClass_, StubAdapterClass_, In_<In template <int... InArgIndices_, int... OutArgIndices_> inline bool handleDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, - DBusStubAdapterHelperType& dbusStubAdapterHelper, + std::weak_ptr<DBusProxyConnection> _connection, index_sequence<InArgIndices_...>, index_sequence<OutArgIndices_...>, std::tuple<InArgs_..., OutArgs_...> argTuple) const { @@ -559,8 +691,13 @@ class DBusMethodWithReplyAdapterDispatcher<StubClass_, StubAdapterClass_, In_<In dbusOutputStream.flush(); } - - return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply); + if (std::shared_ptr<DBusProxyConnection> connection = _connection.lock()) { + bool isSuccessful = connection->sendDBusMessage(dbusMessageReply); + return isSuccessful; + } + else { + return false; + } } StubFunctor_ stubFunctor_; @@ -569,9 +706,9 @@ class DBusMethodWithReplyAdapterDispatcher<StubClass_, StubAdapterClass_, In_<In template <typename StubClass_, typename AttributeType_, typename AttributeDepl_ = EmptyDeployment> -class DBusGetAttributeStubDispatcher: public virtual DBusStubAdapterHelper<StubClass_>::StubDispatcher { +class DBusGetAttributeStubDispatcher: public virtual StubDispatcher<StubClass_> { public: - typedef DBusStubAdapterHelper<StubClass_> DBusStubAdapterHelperType; + typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; typedef const AttributeType_& (StubClass_::*GetStubFunctor)(std::shared_ptr<CommonAPI::ClientId>); DBusGetAttributeStubDispatcher(GetStubFunctor _getStubFunctor, const char *_signature, AttributeDepl_ *_depl = nullptr): @@ -582,12 +719,14 @@ class DBusGetAttributeStubDispatcher: public virtual DBusStubAdapterHelper<StubC virtual ~DBusGetAttributeStubDispatcher() {}; - bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { - return sendAttributeValueReply(dbusMessage, stub, dbusStubAdapterHelper); + bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, + RemoteEventHandlerType* _remoteEventHandler, + std::weak_ptr<DBusProxyConnection> _connection) { + (void) _remoteEventHandler; + return sendAttributeValueReply(dbusMessage, stub, _connection); } - void appendGetAllReply(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper, DBusOutputStream &_output) { - (void)dbusStubAdapterHelper; + void appendGetAllReply(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, DBusOutputStream &_output) { std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender())); auto varDepl = CommonAPI::DBus::VariantDeployment<AttributeDepl_>(true, depl_); // presuming FreeDesktop variant deployment, as support for "legacy" service only @@ -596,7 +735,7 @@ class DBusGetAttributeStubDispatcher: public virtual DBusStubAdapterHelper<StubC } protected: - virtual bool sendAttributeValueReply(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { + virtual bool sendAttributeValueReply(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, std::weak_ptr<DBusProxyConnection> connection_) { DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(signature_); DBusOutputStream dbusOutputStream(dbusMessageReply); @@ -604,8 +743,13 @@ class DBusGetAttributeStubDispatcher: public virtual DBusStubAdapterHelper<StubC dbusOutputStream << CommonAPI::Deployable<AttributeType_, AttributeDepl_>((stub.get()->*getStubFunctor_)(clientId), depl_); dbusOutputStream.flush(); - - return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply); + if (std::shared_ptr<DBusProxyConnection> connection = connection_.lock()) { + bool isSuccessful = connection->sendDBusMessage(dbusMessageReply); + return isSuccessful; + } + else { + return false; + } } @@ -617,8 +761,7 @@ class DBusGetAttributeStubDispatcher: public virtual DBusStubAdapterHelper<StubC template <typename StubClass_, typename AttributeType_, typename AttributeDepl_ = EmptyDeployment> class DBusSetAttributeStubDispatcher: public virtual DBusGetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_> { public: - typedef typename DBusGetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::DBusStubAdapterHelperType DBusStubAdapterHelperType; - typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType; + typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; typedef typename DBusGetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::GetStubFunctor GetStubFunctor; typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(std::shared_ptr<CommonAPI::ClientId>, AttributeType_); @@ -636,14 +779,16 @@ class DBusSetAttributeStubDispatcher: public virtual DBusGetAttributeStubDispatc virtual ~DBusSetAttributeStubDispatcher() {}; - bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { + bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, + RemoteEventHandlerType* _remoteEventHandler, + std::weak_ptr<DBusProxyConnection> _connection) { bool attributeValueChanged; - if (!setAttributeValue(dbusMessage, stub, dbusStubAdapterHelper, attributeValueChanged)) + if (!setAttributeValue(dbusMessage, stub, _remoteEventHandler, _connection, attributeValueChanged)) return false; if (attributeValueChanged) - notifyOnRemoteChanged(dbusStubAdapterHelper); + notifyOnRemoteChanged(_remoteEventHandler); return true; } @@ -665,7 +810,8 @@ class DBusSetAttributeStubDispatcher: public virtual DBusGetAttributeStubDispatc inline bool setAttributeValue(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, - DBusStubAdapterHelperType& dbusStubAdapterHelper, + RemoteEventHandlerType* _remoteEventHandler, + std::weak_ptr<DBusProxyConnection> _connection, bool& attributeValueChanged) { bool errorOccured; CommonAPI::Deployable<AttributeType_, AttributeDepl_> attributeValue( @@ -677,13 +823,13 @@ class DBusSetAttributeStubDispatcher: public virtual DBusGetAttributeStubDispatc std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender())); - attributeValueChanged = (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteSetFunctor_)(clientId, std::move(attributeValue.getValue())); + attributeValueChanged = (_remoteEventHandler->*onRemoteSetFunctor_)(clientId, std::move(attributeValue.getValue())); - return this->sendAttributeValueReply(dbusMessage, stub, dbusStubAdapterHelper); + return this->sendAttributeValueReply(dbusMessage, stub, _connection); } - inline void notifyOnRemoteChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) { - (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteChangedFunctor_)(); + inline void notifyOnRemoteChanged(RemoteEventHandlerType* _remoteEventHandler) { + (_remoteEventHandler->*onRemoteChangedFunctor_)(); } inline const AttributeType_& getAttributeValue(std::shared_ptr<CommonAPI::ClientId> clientId, const std::shared_ptr<StubClass_>& stub) { @@ -697,8 +843,8 @@ class DBusSetAttributeStubDispatcher: public virtual DBusGetAttributeStubDispatc template <typename StubClass_, typename AttributeType_, typename AttributeDepl_ = EmptyDeployment> class DBusSetObservableAttributeStubDispatcher: public virtual DBusSetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_> { public: - typedef typename DBusSetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::DBusStubAdapterHelperType DBusStubAdapterHelperType; - typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType; + typedef typename StubClass_::RemoteEventHandlerType RemoteEventHandlerType; + typedef typename StubClass_::StubAdapterType StubAdapterType; typedef typename DBusSetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::GetStubFunctor GetStubFunctor; typedef typename DBusSetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::OnRemoteSetFunctor OnRemoteSetFunctor; typedef typename DBusSetAttributeStubDispatcher<StubClass_, AttributeType_, AttributeDepl_>::OnRemoteChangedFunctor OnRemoteChangedFunctor; @@ -720,23 +866,25 @@ class DBusSetObservableAttributeStubDispatcher: public virtual DBusSetAttributeS virtual ~DBusSetObservableAttributeStubDispatcher() {}; - bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, DBusStubAdapterHelperType& dbusStubAdapterHelper) { + bool dispatchDBusMessage(const DBusMessage& dbusMessage, const std::shared_ptr<StubClass_>& stub, + RemoteEventHandlerType* _remoteEventHandler, + std::weak_ptr<DBusProxyConnection> _connection) { bool attributeValueChanged; - if (!this->setAttributeValue(dbusMessage, stub, dbusStubAdapterHelper, attributeValueChanged)) + if (!this->setAttributeValue(dbusMessage, stub, _remoteEventHandler, _connection, attributeValueChanged)) return false; if (attributeValueChanged) { std::shared_ptr<DBusClientId> clientId = std::make_shared<DBusClientId>(std::string(dbusMessage.getSender())); - fireAttributeValueChanged(clientId, dbusStubAdapterHelper, stub); - this->notifyOnRemoteChanged(dbusStubAdapterHelper); + fireAttributeValueChanged(clientId, _remoteEventHandler, stub); + this->notifyOnRemoteChanged(_remoteEventHandler); } return true; } protected: virtual void fireAttributeValueChanged(std::shared_ptr<CommonAPI::ClientId> _client, - DBusStubAdapterHelperType &_helper, + RemoteEventHandlerType* _remoteEventHandler, const std::shared_ptr<StubClass_> _stub) { - (void)_helper; + (void)_remoteEventHandler; (_stub->StubType::getStubAdapter().get()->*fireChangedFunctor_)(this->getAttributeValue(_client, _stub)); } @@ -747,4 +895,3 @@ protected: } // namespace CommonAPI #endif // COMMONAPI_DBUS_DBUSSTUBADAPTERHELPER_HPP_ - |