1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 #ifndef COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_
5 #define COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_
7 #include "DBusStubAdapter.h"
8 #include "DBusInputStream.h"
9 #include "DBusOutputStream.h"
10 #include "DBusHelper.h"
14 #include <initializer_list>
16 #include <unordered_map>
21 template <typename _StubClass>
22 class DBusStubAdapterHelper: public DBusStubAdapter, public std::enable_shared_from_this<typename _StubClass::StubAdapterType> {
24 typedef typename _StubClass::StubAdapterType StubAdapterType;
25 typedef typename _StubClass::RemoteEventHandlerType RemoteEventHandlerType;
27 class StubDispatcher {
29 virtual ~StubDispatcher() { }
30 virtual bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelper<_StubClass>& dbusStubAdapterHelper) = 0;
34 DBusStubAdapterHelper(const std::string& dbusBusName,
35 const std::string& dbusObjectPath,
36 const std::string& interfaceName,
37 const std::shared_ptr<DBusProxyConnection>& dbusConnection,
38 std::shared_ptr<_StubClass> stub):
39 DBusStubAdapter(dbusBusName, dbusObjectPath, interfaceName, dbusConnection),
43 virtual ~DBusStubAdapterHelper() { }
46 DBusStubAdapter::init();
47 remoteEventHandler_ = stub_->initStubAdapter(getStubAdapter());
50 inline std::shared_ptr<StubAdapterType> getStubAdapter() {
51 return this->shared_from_this();
54 inline const std::shared_ptr<_StubClass>& getStub() {
58 inline RemoteEventHandlerType* getRemoteEventHandler() {
59 return remoteEventHandler_;
63 // interfaceMemberName, interfaceMemberSignature
64 typedef std::pair<const char*, const char*> DBusInterfaceMemberPath;
65 typedef std::unordered_map<DBusInterfaceMemberPath, StubDispatcher*> StubDispatcherTable;
67 virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) {
68 const char* interfaceMemberName = dbusMessage.getMemberName();
69 const char* interfaceMemberSignature = dbusMessage.getSignatureString();
71 assert(interfaceMemberName);
72 assert(interfaceMemberSignature);
74 DBusInterfaceMemberPath dbusInterfaceMemberPath(interfaceMemberName, interfaceMemberSignature);
75 auto findIterator = this->stubDispatcherTable_.find(dbusInterfaceMemberPath);
76 const bool foundInterfaceMemberHandler = (findIterator != this->stubDispatcherTable_.end());
77 bool dbusMessageHandled = false;
79 if (foundInterfaceMemberHandler) {
80 StubDispatcher* stubDispatcher = findIterator->second;
81 dbusMessageHandled = stubDispatcher->dispatchDBusMessage(dbusMessage, *this);
84 return dbusMessageHandled;
87 std::shared_ptr<_StubClass> stub_;
88 RemoteEventHandlerType* remoteEventHandler_;
89 static const StubDispatcherTable stubDispatcherTable_;
93 struct DBusStubSignalHelper;
95 template<template<class ...> class _In, class... _InArgs>
96 struct DBusStubSignalHelper<_In<_InArgs...>> {
97 template <typename _DBusStub = DBusStubAdapter>
98 static bool sendSignal(const _DBusStub& dbusStub,
99 const char* signalName,
100 const char* signalSignature,
101 const _InArgs&... inArgs) {
102 DBusMessage dbusMessage = DBusMessage::createSignal(
103 dbusStub.getObjectPath().c_str(),
104 dbusStub.getInterfaceName(),
108 if (sizeof...(_InArgs) > 0) {
109 DBusOutputStream outputStream(dbusMessage);
110 const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
114 outputStream.flush();
117 const bool dbusMessageSent = dbusStub.getDBusConnection()->sendDBusMessage(dbusMessage);
118 return dbusMessageSent;
124 template< class, class >
125 class DBusMethodStubDispatcher;
129 template <class...> class _In, class... _InArgs>
130 class DBusMethodStubDispatcher<_StubClass, _In<_InArgs...> >: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
132 typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
133 typedef void (_StubClass::*_StubFunctor)(_InArgs...);
135 DBusMethodStubDispatcher(_StubFunctor stubFunctor):
136 stubFunctor_(stubFunctor) {
139 bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
140 return handleDBusMessage(dbusMessage, dbusStubAdapterHelper, typename make_sequence<sizeof...(_InArgs)>::type());
144 template <int... _InArgIndices, int... _OutArgIndices>
145 inline bool handleDBusMessage(const DBusMessage& dbusMessage,
146 DBusStubAdapterHelperType& dbusStubAdapterHelper,
147 index_sequence<_InArgIndices...>) const {
148 std::tuple<_InArgs...> argTuple;
150 if (sizeof...(_InArgs) > 0) {
151 DBusInputStream dbusInputStream(dbusMessage);
152 const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
157 (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))...);
162 _StubFunctor stubFunctor_;
166 template< class, class, class >
167 class DBusMethodWithReplyStubDispatcher;
171 template <class...> class _In, class... _InArgs,
172 template <class...> class _Out, class... _OutArgs>
173 class DBusMethodWithReplyStubDispatcher<_StubClass, _In<_InArgs...>, _Out<_OutArgs...> >:
174 public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
176 typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
177 typedef void (_StubClass::*_StubFunctor)(_InArgs..., _OutArgs&...);
179 DBusMethodWithReplyStubDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature):
180 stubFunctor_(stubFunctor),
181 dbusReplySignature_(dbusReplySignature) {
184 bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
185 return handleDBusMessage(
187 dbusStubAdapterHelper,
188 typename make_sequence_range<sizeof...(_InArgs), 0>::type(),
189 typename make_sequence_range<sizeof...(_OutArgs), sizeof...(_InArgs)>::type());
193 template <int... _InArgIndices, int... _OutArgIndices>
194 inline bool handleDBusMessage(const DBusMessage& dbusMessage,
195 DBusStubAdapterHelperType& dbusStubAdapterHelper,
196 index_sequence<_InArgIndices...>,
197 index_sequence<_OutArgIndices...>) const {
198 std::tuple<_InArgs..., _OutArgs...> argTuple;
200 if (sizeof...(_InArgs) > 0) {
201 DBusInputStream dbusInputStream(dbusMessage);
202 const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
207 (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))..., std::get<_OutArgIndices>(argTuple)...);
209 DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusReplySignature_);
211 if (sizeof...(_OutArgs) > 0) {
212 DBusOutputStream dbusOutputStream(dbusMessageReply);
213 const bool success = DBusSerializableArguments<_OutArgs...>::serialize(dbusOutputStream, std::get<_OutArgIndices>(argTuple)...);
217 dbusOutputStream.flush();
220 return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
223 _StubFunctor stubFunctor_;
224 const char* dbusReplySignature_;
228 template <typename _StubClass, typename _AttributeType>
229 class DBusGetAttributeStubDispatcher: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
231 typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
232 typedef const _AttributeType& (_StubClass::*GetStubFunctor)();
234 DBusGetAttributeStubDispatcher(GetStubFunctor getStubFunctor, const char* dbusSignature):
235 getStubFunctor_(getStubFunctor),
236 dbusSignature_(dbusSignature) {
239 bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
240 return sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper);
244 inline bool sendAttributeValueReply(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
245 DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusSignature_);
246 DBusOutputStream dbusOutputStream(dbusMessageReply);
248 dbusOutputStream << (dbusStubAdapterHelper.getStub().get()->*getStubFunctor_)();
249 dbusOutputStream.flush();
251 return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
254 GetStubFunctor getStubFunctor_;
255 const char* dbusSignature_;
259 template <typename _StubClass, typename _AttributeType>
260 class DBusSetAttributeStubDispatcher: public DBusGetAttributeStubDispatcher<_StubClass, _AttributeType> {
262 typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
263 typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType;
265 typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
266 typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(_AttributeType);
267 typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)();
269 DBusSetAttributeStubDispatcher(GetStubFunctor getStubFunctor,
270 OnRemoteSetFunctor onRemoteSetFunctor,
271 OnRemoteChangedFunctor onRemoteChangedFunctor,
272 const char* dbusSignature) :
273 DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, dbusSignature),
274 onRemoteSetFunctor_(onRemoteSetFunctor),
275 onRemoteChangedFunctor_(onRemoteChangedFunctor) {
278 bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
279 bool attributeValueChanged;
281 if (!setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged))
284 if (attributeValueChanged)
285 notifyOnRemoteChanged(dbusStubAdapterHelper);
291 inline bool setAttributeValue(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper, bool& attributeValueChanged) {
292 DBusInputStream dbusInputStream(dbusMessage);
293 _AttributeType attributeValue;
294 dbusInputStream >> attributeValue;
295 if (dbusInputStream.hasError())
298 attributeValueChanged = (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteSetFunctor_)(std::move(attributeValue));
300 return this->sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper);
303 inline void notifyOnRemoteChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
304 (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteChangedFunctor_)();
307 inline const _AttributeType& getAttributeValue(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
308 return (dbusStubAdapterHelper.getStub().get()->*(this->getStubFunctor_))();
311 const OnRemoteSetFunctor onRemoteSetFunctor_;
312 const OnRemoteChangedFunctor onRemoteChangedFunctor_;
316 template <typename _StubClass, typename _AttributeType>
317 class DBusSetObservableAttributeStubDispatcher: public DBusSetAttributeStubDispatcher<_StubClass, _AttributeType> {
319 typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
320 typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType;
322 typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
323 typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteSetFunctor OnRemoteSetFunctor;
324 typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteChangedFunctor OnRemoteChangedFunctor;
325 typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&);
327 DBusSetObservableAttributeStubDispatcher(GetStubFunctor getStubFunctor,
328 OnRemoteSetFunctor onRemoteSetFunctor,
329 OnRemoteChangedFunctor onRemoteChangedFunctor,
330 FireChangedFunctor fireChangedFunctor,
331 const char* dbusSignature) :
332 DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor,
334 onRemoteChangedFunctor,
336 fireChangedFunctor_(fireChangedFunctor) {
339 bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
340 bool attributeValueChanged;
341 if (!this->setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged))
344 if (attributeValueChanged) {
345 fireAttributeValueChanged(dbusStubAdapterHelper);
346 this->notifyOnRemoteChanged(dbusStubAdapterHelper);
352 inline void fireAttributeValueChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
353 (dbusStubAdapterHelper.getStubAdapter().get()->*fireChangedFunctor_)(this->getAttributeValue(dbusStubAdapterHelper));
356 const FireChangedFunctor fireChangedFunctor_;
360 } // namespace CommonAPI
362 #endif // COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_