summaryrefslogtreecommitdiff
path: root/include/CommonAPI
diff options
context:
space:
mode:
Diffstat (limited to 'include/CommonAPI')
-rw-r--r--include/CommonAPI/DBus/DBusConnection.hpp24
-rw-r--r--include/CommonAPI/DBus/DBusErrorEvent.hpp131
-rw-r--r--include/CommonAPI/DBus/DBusEvent.hpp60
-rw-r--r--include/CommonAPI/DBus/DBusFreedesktopAttribute.hpp64
-rw-r--r--include/CommonAPI/DBus/DBusInstanceAvailabilityStatusChangedEvent.hpp16
-rw-r--r--include/CommonAPI/DBus/DBusMainLoopContext.hpp2
-rw-r--r--include/CommonAPI/DBus/DBusMessage.hpp2
-rw-r--r--include/CommonAPI/DBus/DBusProxy.hpp29
-rw-r--r--include/CommonAPI/DBus/DBusProxyAsyncCallbackHandler.hpp152
-rw-r--r--include/CommonAPI/DBus/DBusProxyAsyncSignalMemberCallbackHandler.hpp10
-rw-r--r--include/CommonAPI/DBus/DBusProxyBase.hpp8
-rw-r--r--include/CommonAPI/DBus/DBusProxyConnection.hpp13
-rw-r--r--include/CommonAPI/DBus/DBusProxyHelper.hpp194
-rw-r--r--include/CommonAPI/DBus/DBusSelectiveEvent.hpp6
-rw-r--r--include/CommonAPI/DBus/DBusServiceRegistry.hpp16
-rw-r--r--include/CommonAPI/DBus/DBusStubAdapterHelper.hpp237
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 >