Initial import to Git
[profile/ivi/common-api-dbus-runtime.git] / src / CommonAPI / DBus / DBusProxyHelper.h
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_PROXY_HELPER_H_
5 #define COMMONAPI_DBUS_DBUS_PROXY_HELPER_H_
6
7 #include "DBusMessage.h"
8 #include "DBusSerializableArguments.h"
9 #include "DBusProxyAsyncCallbackHandler.h"
10
11 #include <functional>
12 #include <future>
13 #include <memory>
14 #include <string>
15
16 namespace CommonAPI {
17 namespace DBus {
18
19
20 class DBusProxy;
21
22
23 template< class, class >
24 struct DBusProxyHelper;
25
26 template <
27         template <class...> class _In, class... _InArgs,
28         template <class...> class _Out, class... _OutArgs>
29 struct DBusProxyHelper<_In<_InArgs...>, _Out<_OutArgs...>> {
30         template <typename _DBusProxy = DBusProxy>
31         static void callMethod(const _DBusProxy& dbusProxy,
32                         const char* methodName,
33                         const char* methodSignature,
34                         const _InArgs&... inArgs,
35                         CommonAPI::CallStatus& callStatus) {
36             if (dbusProxy.isAvailableBlocking()) {
37
38                 DBusMessage dbusMessage = dbusProxy.createMethodCall(methodName, methodSignature);
39
40                 if (sizeof...(_InArgs) > 0) {
41                     DBusOutputStream outputStream(dbusMessage);
42                     const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
43                     if (!success) {
44                         callStatus = CallStatus::OUT_OF_MEMORY;
45                         return;
46                     }
47                     outputStream.flush();
48                 }
49
50                 const bool dbusMessageSent = dbusProxy.getDBusConnection()->sendDBusMessage(dbusMessage);
51                 callStatus = dbusMessageSent ? CallStatus::SUCCESS : CallStatus::OUT_OF_MEMORY;
52             } else {
53                 callStatus = CallStatus::NOT_AVAILABLE;
54             }
55         }
56
57         template <typename _DBusProxy = DBusProxy>
58         static void callMethodWithReply(
59                         const _DBusProxy& dbusProxy,
60                         const char* methodName,
61                         const char* methodSignature,
62                         const _InArgs&... inArgs,
63                         CommonAPI::CallStatus& callStatus,
64                         _OutArgs&... outArgs) {
65
66             if (dbusProxy.isAvailableBlocking()) {
67
68                 DBusMessage dbusMethodCall = dbusProxy.createMethodCall(methodName, methodSignature);
69
70                 if (sizeof...(_InArgs) > 0) {
71                     DBusOutputStream outputStream(dbusMethodCall);
72                     const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
73                     if (!success) {
74                         callStatus = CallStatus::OUT_OF_MEMORY;
75                         return;
76                     }
77                     outputStream.flush();
78                 }
79
80                 DBusError dbusError;
81                 DBusMessage dbusMessageReply = dbusProxy.getDBusConnection()->sendDBusMessageWithReplyAndBlock(dbusMethodCall, dbusError);
82                 if (dbusError || !dbusMessageReply.isMethodReturnType()) {
83                     callStatus = CallStatus::REMOTE_ERROR;
84                     return;
85                 }
86
87                 if (sizeof...(_OutArgs) > 0) {
88                     DBusInputStream inputStream(dbusMessageReply);
89                     const bool success = DBusSerializableArguments<_OutArgs...>::deserialize(inputStream, outArgs...);
90                     if (!success) {
91                         callStatus = CallStatus::REMOTE_ERROR;
92                         return;
93                     }
94                 }
95
96                 callStatus = CallStatus::SUCCESS;
97             } else {
98                 callStatus = CallStatus::NOT_AVAILABLE;
99             }
100         }
101
102         template <typename _DBusProxy = DBusProxy, typename _AsyncCallback>
103         static std::future<CallStatus> callMethodAsync(
104                         const _DBusProxy& dbusProxy,
105                         const char* methodName,
106                         const char* methodSignature,
107                         const _InArgs&... inArgs,
108                         _AsyncCallback asyncCallback) {
109
110             if (dbusProxy.isAvailable()) {
111
112                 DBusMessage dbusMessage = dbusProxy.createMethodCall(methodName, methodSignature);
113
114                 if (sizeof...(_InArgs) > 0) {
115                     DBusOutputStream outputStream(dbusMessage);
116                             const bool success = DBusSerializableArguments<_InArgs...>::serialize(outputStream, inArgs...);
117                             if (!success) {
118                                 std::promise<CallStatus> promise;
119                                 promise.set_value(CallStatus::OUT_OF_MEMORY);
120                                 return promise.get_future();
121                             }
122                             outputStream.flush();
123                 }
124
125                 return dbusProxy.getDBusConnection()->sendDBusMessageWithReplyAsync(
126                                 dbusMessage,
127                                 DBusProxyAsyncCallbackHandler<_OutArgs...>::create(std::move(asyncCallback)));
128                 } else {
129                     std::promise<CallStatus> promise;
130                     promise.set_value(CallStatus::NOT_AVAILABLE);
131                     return promise.get_future();
132                 }
133            }
134 };
135
136 } // namespace DBus
137 } // namespace CommonAPI
138
139 #endif // COMMONAPI_DBUS_DBUS_PROXY_HELPER_H_