2cc6e619e956635738c0acdfd35cb81a4d860aff
[platform/upstream/connman.git] / client / dbus_helpers.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2013  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 #include <stdio.h>
24 #include <errno.h>
25 #include <glib.h>
26
27 #include "input.h"
28 #include "dbus_helpers.h"
29
30 #define TIMEOUT         60000
31
32 void __connmanctl_dbus_print(DBusMessageIter *iter, const char *pre,
33                 const char *dict, const char *sep)
34 {
35         int arg_type;
36         dbus_bool_t b;
37         unsigned char c;
38         unsigned int i;
39         double d;
40
41         char *str;
42         DBusMessageIter entry;
43
44         if (pre == NULL)
45                 pre = "";
46
47         while ((arg_type = dbus_message_iter_get_arg_type(iter))
48                         != DBUS_TYPE_INVALID) {
49
50                 fprintf(stdout, "%s", pre);
51
52                 switch (arg_type) {
53                 case DBUS_TYPE_STRUCT:
54                         fprintf(stdout, "{ ");
55                         dbus_message_iter_recurse(iter, &entry);
56                         __connmanctl_dbus_print(&entry, "", "=", " ");
57                         fprintf(stdout, " }");
58                         break;
59
60                 case DBUS_TYPE_ARRAY:
61                         fprintf(stdout, "[ ");
62
63                         dbus_message_iter_recurse(iter, &entry);
64                         __connmanctl_dbus_print(&entry, "", "=", ", ");
65
66                         fprintf(stdout, " ]");
67                         break;
68
69                 case DBUS_TYPE_DICT_ENTRY:
70
71                         dbus_message_iter_recurse(iter, &entry);
72                         __connmanctl_dbus_print(&entry, "", dict, dict);
73                         break;
74
75                 case DBUS_TYPE_STRING:
76                 case DBUS_TYPE_OBJECT_PATH:
77                         dbus_message_iter_get_basic(iter, &str);
78                         fprintf(stdout, "%s", str);
79                         break;
80
81                 case DBUS_TYPE_VARIANT:
82                         dbus_message_iter_recurse(iter, &entry);
83                         __connmanctl_dbus_print(&entry, pre, dict, sep);
84                         break;
85
86                 case DBUS_TYPE_BOOLEAN:
87                         dbus_message_iter_get_basic(iter, &b);
88                         if (b == FALSE)
89                                 fprintf(stdout, "False");
90                         else
91                                 fprintf(stdout, "True");
92                         break;
93
94                 case DBUS_TYPE_BYTE:
95                         dbus_message_iter_get_basic(iter, &c);
96                         fprintf(stdout, "%d", c);
97                         break;
98
99                 case DBUS_TYPE_UINT16:
100                 case DBUS_TYPE_UINT32:
101                         dbus_message_iter_get_basic(iter, &i);
102                         fprintf(stdout, "%d", i);
103                         break;
104
105                 case DBUS_TYPE_DOUBLE:
106                         dbus_message_iter_get_basic(iter, &d);
107                         fprintf(stdout, "%f", d);
108                         break;
109
110                 default:
111                         fprintf(stdout, "<type %c>", arg_type);
112                         break;
113                 }
114
115                 if (dbus_message_iter_has_next(iter) == TRUE)
116                         fprintf(stdout, "%s", sep);
117
118                 dbus_message_iter_next(iter);
119         }
120 }
121
122 struct dbus_callback {
123         connmanctl_dbus_method_return_func_t cb;
124         void *user_data;
125 };
126
127 static void dbus_method_reply(DBusPendingCall *call, void *user_data)
128 {
129         struct dbus_callback *callback = user_data;
130         DBusMessage *reply;
131         DBusMessageIter iter;
132
133         __connmanctl_save_rl();
134
135         reply = dbus_pending_call_steal_reply(call);
136         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
137                 DBusError err;
138
139                 dbus_error_init(&err);
140                 dbus_set_error_from_message(&err, reply);
141
142                 callback->cb(NULL, err.message, callback->user_data);
143
144                 dbus_error_free(&err);
145                 goto end;
146         }
147
148         dbus_message_iter_init(reply, &iter);
149         callback->cb(&iter, NULL, callback->user_data);
150
151 end:
152         __connmanctl_redraw_rl();
153         if (__connmanctl_is_interactive() == false)
154                 __connmanctl_quit();
155
156         g_free(callback);
157         dbus_message_unref(reply);
158 }
159
160 static int send_method_call(DBusConnection *connection,
161                 DBusMessage *message, connmanctl_dbus_method_return_func_t cb,
162                 void *user_data)
163 {
164         int res = -ENXIO;
165         DBusPendingCall *call;
166         struct dbus_callback *callback;
167
168         if (dbus_connection_send_with_reply(connection, message, &call,
169                                         TIMEOUT) == FALSE)
170                 goto end;
171
172         if (call == NULL)
173                 goto end;
174
175         if (cb != NULL) {
176                 callback = g_new0(struct dbus_callback, 1);
177                 callback->cb = cb;
178                 callback->user_data = user_data;
179                 dbus_pending_call_set_notify(call, dbus_method_reply,
180                                 callback, NULL);
181                 res = -EINPROGRESS;
182         }
183
184 end:
185         dbus_message_unref(message);
186         return res;
187 }
188
189 static int append_variant(DBusMessageIter *iter, const char *property,
190                 int type, void *value)
191 {
192         DBusMessageIter variant;
193         char *type_str;
194
195         switch(type) {
196         case DBUS_TYPE_BOOLEAN:
197                 type_str = DBUS_TYPE_BOOLEAN_AS_STRING;
198                 break;
199         case DBUS_TYPE_BYTE:
200                 type_str = DBUS_TYPE_BYTE_AS_STRING;
201                 break;
202         case DBUS_TYPE_STRING:
203                 type_str = DBUS_TYPE_STRING_AS_STRING;
204                 break;
205         default:
206                 return -EOPNOTSUPP;
207         }
208
209         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
210         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, type_str,
211                         &variant);
212         dbus_message_iter_append_basic(&variant, type, value);
213         dbus_message_iter_close_container(iter, &variant);
214
215         return 0;
216 }
217
218 int __connmanctl_dbus_method_call(DBusConnection *connection, const char *path,
219                 const char *interface, const char *method,
220                 connmanctl_dbus_method_return_func_t cb, void *user_data,
221                 int arg1, ...)
222 {
223         DBusMessage *message;
224         va_list args;
225
226         message = dbus_message_new_method_call("net.connman", path,
227                         interface, method);
228
229         if (message == NULL)
230                 return -ENOMEM;
231
232         va_start(args, arg1);
233         dbus_message_append_args_valist(message, arg1, args);
234         va_end(args);
235
236         return send_method_call(connection, message, cb, user_data);
237 }
238
239 int __connmanctl_dbus_set_property(DBusConnection *connection,
240                 const char *path, const char *interface,
241                 connmanctl_dbus_method_return_func_t cb, void * user_data,
242                 const char *property, int type, void *value)
243 {
244         DBusMessage *message;
245         DBusMessageIter iter;
246
247         message = dbus_message_new_method_call("net.connman", path,
248                         interface, "SetProperty");
249
250         if (message == NULL)
251                 return -ENOMEM;
252
253         dbus_message_iter_init_append(message, &iter);
254
255         if (append_variant(&iter, property, type, value) < 0) {
256                 dbus_message_unref(message);
257                 return -EINVAL;
258         }
259
260         return send_method_call(connection, message, cb, user_data);
261 }
262
263 void __connmanctl_dbus_append_dict_entry(DBusMessageIter *iter, char *property,
264                 int type, void *value)
265 {
266         DBusMessageIter dict_entry;
267
268         dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL,
269                         &dict_entry);
270
271         append_variant(&dict_entry, property, type, value);
272
273         dbus_message_iter_close_container(iter, &dict_entry);
274 }
275
276 int __connmanctl_dbus_set_property_dict(DBusConnection *connection,
277                 const char *path, const char *interface,
278                 connmanctl_dbus_method_return_func_t cb, void *user_data,
279                 const char *property, int type,
280                 connman_dbus_append_cb_t append_fn, void *append_user_data)
281 {
282         DBusMessage *message;
283         DBusMessageIter iter, variant, dict;
284
285         message = dbus_message_new_method_call("net.connman", path,
286                         interface, "SetProperty");
287
288         if (message == NULL)
289                 return -ENOMEM;
290
291         dbus_message_iter_init_append(message, &iter);
292         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
293         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
294                         DBUS_TYPE_ARRAY_AS_STRING
295                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
296                                         DBUS_TYPE_STRING_AS_STRING
297                                         DBUS_TYPE_VARIANT_AS_STRING
298                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
299                         &variant);
300
301         dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
302                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
303                                 DBUS_TYPE_STRING_AS_STRING
304                                 DBUS_TYPE_VARIANT_AS_STRING
305                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
306                         &dict);
307
308         append_fn(&dict, append_user_data);
309
310         dbus_message_iter_close_container(&variant, &dict);
311         dbus_message_iter_close_container(&iter, &variant);
312
313         return send_method_call(connection, message, cb, user_data);
314 }
315
316 static void append_variant_array(DBusMessageIter *iter, const char *property,
317                 connman_dbus_append_cb_t append_fn, void *append_user_data)
318 {
319         DBusMessageIter variant, array;
320
321         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
322         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
323                         DBUS_TYPE_ARRAY_AS_STRING
324                                 DBUS_TYPE_STRING_AS_STRING,
325                         &variant);
326
327         dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
328                         DBUS_TYPE_STRING_AS_STRING, &array);
329
330         append_fn(&array, append_user_data);
331
332         dbus_message_iter_close_container(&variant, &array);
333         dbus_message_iter_close_container(iter, &variant);
334 }
335
336 void __connmanctl_dbus_append_dict_string_array(DBusMessageIter *iter,
337                 const char *property, connman_dbus_append_cb_t append_fn,
338                 void *append_user_data)
339 {
340         DBusMessageIter dict_entry;
341
342         dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL,
343                         &dict_entry);
344
345         append_variant_array(&dict_entry, property, append_fn,
346                         append_user_data);
347
348         dbus_message_iter_close_container(iter, &dict_entry);
349 }
350
351 int __connmanctl_dbus_set_property_array(DBusConnection *connection,
352                 const char *path, const char *interface,
353                 connmanctl_dbus_method_return_func_t cb, void *user_data,
354                 const char *property, int type,
355                 connman_dbus_append_cb_t append_fn, void *append_user_data)
356 {
357         DBusMessage *message;
358         DBusMessageIter iter;
359
360         if (type != DBUS_TYPE_STRING)
361                 return -EOPNOTSUPP;
362
363         message = dbus_message_new_method_call("net.connman", path,
364                         interface, "SetProperty");
365
366         if (message == NULL)
367                 return -ENOMEM;
368
369         dbus_message_iter_init_append(message, &iter);
370
371         append_variant_array(&iter, property, append_fn, append_user_data);
372
373         return send_method_call(connection, message, cb, user_data);
374 }