Added a way to deinitialize running services
[profile/ivi/common-api-dbus-runtime.git] / src / CommonAPI / DBus / DBusStubAdapterHelper.h
1 /* Copyright (C) 2013 BMW Group
2  * Author: Manfred Bathelt (manfred.bathelt@bmw.de)
3  * Author: Juergen Gehring (juergen.gehring@bmw.de)
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_
8 #define COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_
9
10 #include "DBusStubAdapter.h"
11 #include "DBusInputStream.h"
12 #include "DBusOutputStream.h"
13 #include "DBusHelper.h"
14
15 #include <memory>
16 #include <initializer_list>
17 #include <tuple>
18 #include <unordered_map>
19
20 namespace CommonAPI {
21 namespace DBus {
22
23 template <typename _StubClass>
24 class DBusStubAdapterHelper: public DBusStubAdapter, public std::enable_shared_from_this<typename _StubClass::StubAdapterType> {
25  public:
26     typedef typename _StubClass::StubAdapterType StubAdapterType;
27     typedef typename _StubClass::RemoteEventHandlerType RemoteEventHandlerType;
28
29     class StubDispatcher {
30      public:
31         virtual ~StubDispatcher() { }
32         virtual bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelper<_StubClass>& dbusStubAdapterHelper) = 0;
33     };
34
35  public:
36     DBusStubAdapterHelper(const std::string& commonApiAddress,
37                           const std::string& dbusInterfaceName,
38                           const std::string& dbusBusName,
39                           const std::string& dbusObjectPath,
40                           const std::shared_ptr<DBusProxyConnection>& dbusConnection,
41                           const std::shared_ptr<_StubClass>& stub):
42                     DBusStubAdapter(commonApiAddress, dbusInterfaceName, dbusBusName, dbusObjectPath, dbusConnection),
43                     stub_(stub) {
44     }
45
46     virtual ~DBusStubAdapterHelper() {
47         stub_->deinitStubAdapter();
48     }
49
50     virtual void init() {
51         DBusStubAdapter::init();
52         remoteEventHandler_ = stub_->initStubAdapter(getStubAdapter());
53     }
54
55     virtual void deinit() {
56         DBusStubAdapter::deinit();
57         stub_->deinitStubAdapter();
58     }
59
60     inline std::shared_ptr<StubAdapterType> getStubAdapter() {
61         return this->shared_from_this();
62     }
63
64     inline const std::shared_ptr<_StubClass>& getStub() {
65         return stub_;
66     }
67
68     inline RemoteEventHandlerType* getRemoteEventHandler() {
69         return remoteEventHandler_;
70     }
71
72  protected:
73     // interfaceMemberName, interfaceMemberSignature
74     typedef std::pair<const char*, const char*> DBusInterfaceMemberPath;
75     typedef std::unordered_map<DBusInterfaceMemberPath, StubDispatcher*> StubDispatcherTable;
76
77     virtual bool onInterfaceDBusMessage(const DBusMessage& dbusMessage) {
78         const char* interfaceMemberName = dbusMessage.getMemberName();
79         const char* interfaceMemberSignature = dbusMessage.getSignatureString();
80
81         assert(interfaceMemberName);
82         assert(interfaceMemberSignature);
83
84         DBusInterfaceMemberPath dbusInterfaceMemberPath(interfaceMemberName, interfaceMemberSignature);
85         auto findIterator = this->stubDispatcherTable_.find(dbusInterfaceMemberPath);
86         const bool foundInterfaceMemberHandler = (findIterator != this->stubDispatcherTable_.end());
87         bool dbusMessageHandled = false;
88
89         if (foundInterfaceMemberHandler) {
90             StubDispatcher* stubDispatcher = findIterator->second;
91             dbusMessageHandled = stubDispatcher->dispatchDBusMessage(dbusMessage, *this);
92         }
93
94         return dbusMessageHandled;
95     }
96
97     std::shared_ptr<_StubClass> stub_;
98     RemoteEventHandlerType* remoteEventHandler_;
99     static const StubDispatcherTable stubDispatcherTable_;
100 };
101
102 template< class >
103 struct DBusStubSignalHelper;
104
105 template<template<class ...> class _In, class... _InArgs>
106 struct DBusStubSignalHelper<_In<_InArgs...>> {
107     template <typename _DBusStub = DBusStubAdapter>
108     static bool sendSignal(const _DBusStub& dbusStub,
109                     const char* signalName,
110                     const char* signalSignature,
111                     const _InArgs&... inArgs) {
112         DBusMessage dbusMessage = DBusMessage::createSignal(
113                         dbusStub.getObjectPath().c_str(),
114                         dbusStub.getInterfaceName(),
115                         signalName,
116                         signalSignature);
117
118         if (sizeof...(_InArgs) > 0) {
119             DBusOutputStream outputStream(dbusMessage);
120             const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
121             if (!success) {
122                 return false;
123             }
124             outputStream.flush();
125         }
126
127         const bool dbusMessageSent = dbusStub.getDBusConnection()->sendDBusMessage(dbusMessage);
128         return dbusMessageSent;
129     }
130 };
131
132
133
134 template< class, class >
135 class DBusMethodStubDispatcher;
136
137 template <
138     typename _StubClass,
139     template <class...> class _In, class... _InArgs>
140 class DBusMethodStubDispatcher<_StubClass, _In<_InArgs...> >: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
141  public:
142     typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
143     typedef void (_StubClass::*_StubFunctor)(_InArgs...);
144
145     DBusMethodStubDispatcher(_StubFunctor stubFunctor):
146             stubFunctor_(stubFunctor) {
147     }
148
149     bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
150         return handleDBusMessage(dbusMessage, dbusStubAdapterHelper, typename make_sequence<sizeof...(_InArgs)>::type());
151     }
152
153  private:
154     template <int... _InArgIndices, int... _OutArgIndices>
155     inline bool handleDBusMessage(const DBusMessage& dbusMessage,
156                                   DBusStubAdapterHelperType& dbusStubAdapterHelper,
157                                   index_sequence<_InArgIndices...>) const {
158         std::tuple<_InArgs...> argTuple;
159
160         if (sizeof...(_InArgs) > 0) {
161             DBusInputStream dbusInputStream(dbusMessage);
162             const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
163             if (!success)
164                 return false;
165         }
166
167         (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))...);
168
169         return true;
170     }
171
172     _StubFunctor stubFunctor_;
173 };
174
175
176 template< class, class, class >
177 class DBusMethodWithReplyStubDispatcher;
178
179 template <
180     typename _StubClass,
181     template <class...> class _In, class... _InArgs,
182     template <class...> class _Out, class... _OutArgs>
183 class DBusMethodWithReplyStubDispatcher<_StubClass, _In<_InArgs...>, _Out<_OutArgs...> >:
184             public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
185  public:
186     typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
187     typedef void (_StubClass::*_StubFunctor)(_InArgs..., _OutArgs&...);
188
189     DBusMethodWithReplyStubDispatcher(_StubFunctor stubFunctor, const char* dbusReplySignature):
190             stubFunctor_(stubFunctor),
191             dbusReplySignature_(dbusReplySignature) {
192     }
193
194     bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
195         return handleDBusMessage(
196                         dbusMessage,
197                         dbusStubAdapterHelper,
198                         typename make_sequence_range<sizeof...(_InArgs), 0>::type(),
199                         typename make_sequence_range<sizeof...(_OutArgs), sizeof...(_InArgs)>::type());
200     }
201
202  private:
203     template <int... _InArgIndices, int... _OutArgIndices>
204     inline bool handleDBusMessage(const DBusMessage& dbusMessage,
205                                   DBusStubAdapterHelperType& dbusStubAdapterHelper,
206                                   index_sequence<_InArgIndices...>,
207                                   index_sequence<_OutArgIndices...>) const {
208         std::tuple<_InArgs..., _OutArgs...> argTuple;
209
210         if (sizeof...(_InArgs) > 0) {
211             DBusInputStream dbusInputStream(dbusMessage);
212             const bool success = DBusSerializableArguments<_InArgs...>::deserialize(dbusInputStream, std::get<_InArgIndices>(argTuple)...);
213             if (!success)
214                 return false;
215         }
216
217         (dbusStubAdapterHelper.getStub().get()->*stubFunctor_)(std::move(std::get<_InArgIndices>(argTuple))..., std::get<_OutArgIndices>(argTuple)...);
218
219         DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusReplySignature_);
220
221         if (sizeof...(_OutArgs) > 0) {
222             DBusOutputStream dbusOutputStream(dbusMessageReply);
223             const bool success = DBusSerializableArguments<_OutArgs...>::serialize(dbusOutputStream, std::get<_OutArgIndices>(argTuple)...);
224             if (!success)
225                 return false;
226
227             dbusOutputStream.flush();
228         }
229
230         return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
231     }
232
233     _StubFunctor stubFunctor_;
234     const char* dbusReplySignature_;
235 };
236
237
238 template <typename _StubClass, typename _AttributeType>
239 class DBusGetAttributeStubDispatcher: public DBusStubAdapterHelper<_StubClass>::StubDispatcher {
240  public:
241     typedef DBusStubAdapterHelper<_StubClass> DBusStubAdapterHelperType;
242     typedef const _AttributeType& (_StubClass::*GetStubFunctor)();
243
244     DBusGetAttributeStubDispatcher(GetStubFunctor getStubFunctor, const char* dbusSignature):
245         getStubFunctor_(getStubFunctor),
246         dbusSignature_(dbusSignature) {
247     }
248
249     bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
250         return sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper);
251     }
252
253  protected:
254     inline bool sendAttributeValueReply(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
255         DBusMessage dbusMessageReply = dbusMessage.createMethodReturn(dbusSignature_);
256         DBusOutputStream dbusOutputStream(dbusMessageReply);
257
258         dbusOutputStream << (dbusStubAdapterHelper.getStub().get()->*getStubFunctor_)();
259         dbusOutputStream.flush();
260
261         return dbusStubAdapterHelper.getDBusConnection()->sendDBusMessage(dbusMessageReply);
262     }
263
264     GetStubFunctor getStubFunctor_;
265     const char* dbusSignature_;
266 };
267
268
269 template <typename _StubClass, typename _AttributeType>
270 class DBusSetAttributeStubDispatcher: public DBusGetAttributeStubDispatcher<_StubClass, _AttributeType> {
271  public:
272     typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
273     typedef typename DBusStubAdapterHelperType::RemoteEventHandlerType RemoteEventHandlerType;
274
275     typedef typename DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
276     typedef bool (RemoteEventHandlerType::*OnRemoteSetFunctor)(_AttributeType);
277     typedef void (RemoteEventHandlerType::*OnRemoteChangedFunctor)();
278
279     DBusSetAttributeStubDispatcher(GetStubFunctor getStubFunctor,
280                                    OnRemoteSetFunctor onRemoteSetFunctor,
281                                    OnRemoteChangedFunctor onRemoteChangedFunctor,
282                                    const char* dbusSignature) :
283                     DBusGetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor, dbusSignature),
284                     onRemoteSetFunctor_(onRemoteSetFunctor),
285                     onRemoteChangedFunctor_(onRemoteChangedFunctor) {
286     }
287
288     bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
289         bool attributeValueChanged;
290
291         if (!setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged))
292             return false;
293
294         if (attributeValueChanged)
295             notifyOnRemoteChanged(dbusStubAdapterHelper);
296
297         return true;
298     }
299
300  protected:
301     inline bool setAttributeValue(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper, bool& attributeValueChanged) {
302         DBusInputStream dbusInputStream(dbusMessage);
303         _AttributeType attributeValue;
304         dbusInputStream >> attributeValue;
305         if (dbusInputStream.hasError())
306             return false;
307
308         attributeValueChanged = (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteSetFunctor_)(std::move(attributeValue));
309
310         return this->sendAttributeValueReply(dbusMessage, dbusStubAdapterHelper);
311     }
312
313     inline void notifyOnRemoteChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
314         (dbusStubAdapterHelper.getRemoteEventHandler()->*onRemoteChangedFunctor_)();
315     }
316
317     inline const _AttributeType& getAttributeValue(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
318         return (dbusStubAdapterHelper.getStub().get()->*(this->getStubFunctor_))();
319     }
320
321     const OnRemoteSetFunctor onRemoteSetFunctor_;
322     const OnRemoteChangedFunctor onRemoteChangedFunctor_;
323 };
324
325
326 template <typename _StubClass, typename _AttributeType>
327 class DBusSetObservableAttributeStubDispatcher: public DBusSetAttributeStubDispatcher<_StubClass, _AttributeType> {
328  public:
329     typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::DBusStubAdapterHelperType DBusStubAdapterHelperType;
330     typedef typename DBusStubAdapterHelperType::StubAdapterType StubAdapterType;
331
332     typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::GetStubFunctor GetStubFunctor;
333     typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteSetFunctor OnRemoteSetFunctor;
334     typedef typename DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>::OnRemoteChangedFunctor OnRemoteChangedFunctor;
335     typedef void (StubAdapterType::*FireChangedFunctor)(const _AttributeType&);
336
337     DBusSetObservableAttributeStubDispatcher(GetStubFunctor getStubFunctor,
338                                              OnRemoteSetFunctor onRemoteSetFunctor,
339                                              OnRemoteChangedFunctor onRemoteChangedFunctor,
340                                              FireChangedFunctor fireChangedFunctor,
341                                              const char* dbusSignature) :
342                     DBusSetAttributeStubDispatcher<_StubClass, _AttributeType>(getStubFunctor,
343                                                                                onRemoteSetFunctor,
344                                                                                onRemoteChangedFunctor,
345                                                                                dbusSignature),
346                     fireChangedFunctor_(fireChangedFunctor) {
347     }
348
349     bool dispatchDBusMessage(const DBusMessage& dbusMessage, DBusStubAdapterHelperType& dbusStubAdapterHelper) {
350         bool attributeValueChanged;
351         if (!this->setAttributeValue(dbusMessage, dbusStubAdapterHelper, attributeValueChanged))
352             return false;
353
354         if (attributeValueChanged) {
355             fireAttributeValueChanged(dbusStubAdapterHelper);
356             this->notifyOnRemoteChanged(dbusStubAdapterHelper);
357         }
358         return true;
359     }
360
361  private:
362     inline void fireAttributeValueChanged(DBusStubAdapterHelperType& dbusStubAdapterHelper) {
363         (dbusStubAdapterHelper.getStubAdapter().get()->*fireChangedFunctor_)(this->getAttributeValue(dbusStubAdapterHelper));
364     }
365
366     const FireChangedFunctor fireChangedFunctor_;
367 };
368
369 } // namespace DBus
370 } // namespace CommonAPI
371
372 #endif // COMMONAPI_DBUS_DBUS_STUB_ADAPTER_HELPER_H_