[connman] Added Tizen Wi-Fi Mesh
[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 <inttypes.h>
26 #include <glib.h>
27
28 #include "input.h"
29 #include "dbus_helpers.h"
30
31 #define TIMEOUT         120000
32
33 void __connmanctl_dbus_print(DBusMessageIter *iter, const char *pre,
34                 const char *dict, const char *sep)
35 {
36         int arg_type;
37         dbus_bool_t b;
38         unsigned char c;
39         dbus_uint16_t u16;
40         dbus_uint32_t u;
41         dbus_int32_t i;
42         dbus_uint64_t u64;
43         double d;
44
45         char *str;
46         DBusMessageIter entry;
47
48         if (!pre)
49                 pre = "";
50
51         while ((arg_type = dbus_message_iter_get_arg_type(iter))
52                         != DBUS_TYPE_INVALID) {
53
54                 fprintf(stdout, "%s", pre);
55
56                 switch (arg_type) {
57                 case DBUS_TYPE_STRUCT:
58                         fprintf(stdout, "{ ");
59                         dbus_message_iter_recurse(iter, &entry);
60                         __connmanctl_dbus_print(&entry, "", "=", " ");
61                         fprintf(stdout, " }");
62                         break;
63
64                 case DBUS_TYPE_ARRAY:
65                         fprintf(stdout, "[ ");
66
67                         dbus_message_iter_recurse(iter, &entry);
68                         __connmanctl_dbus_print(&entry, "", "=", ", ");
69
70                         fprintf(stdout, " ]");
71                         break;
72
73                 case DBUS_TYPE_DICT_ENTRY:
74
75                         dbus_message_iter_recurse(iter, &entry);
76                         __connmanctl_dbus_print(&entry, "", dict, dict);
77                         break;
78
79                 case DBUS_TYPE_STRING:
80                 case DBUS_TYPE_OBJECT_PATH:
81                         dbus_message_iter_get_basic(iter, &str);
82                         fprintf(stdout, "%s", str);
83                         break;
84
85                 case DBUS_TYPE_VARIANT:
86                         dbus_message_iter_recurse(iter, &entry);
87                         __connmanctl_dbus_print(&entry, pre, dict, sep);
88                         break;
89
90                 case DBUS_TYPE_BOOLEAN:
91                         dbus_message_iter_get_basic(iter, &b);
92                         if (!b)
93                                 fprintf(stdout, "False");
94                         else
95                                 fprintf(stdout, "True");
96                         break;
97
98                 case DBUS_TYPE_BYTE:
99                         dbus_message_iter_get_basic(iter, &c);
100                         fprintf(stdout, "%d", c);
101                         break;
102
103                 case DBUS_TYPE_UINT16:
104                         dbus_message_iter_get_basic(iter, &u16);
105                         fprintf(stdout, "%u", u16);
106                         break;
107
108                 case DBUS_TYPE_UINT32:
109                         dbus_message_iter_get_basic(iter, &u);
110                         fprintf(stdout, "%d", u);
111                         break;
112
113                 case DBUS_TYPE_INT32:
114                         dbus_message_iter_get_basic(iter, &i);
115                         fprintf(stdout, "%d", i);
116                         break;
117
118                 case DBUS_TYPE_UINT64:
119                         dbus_message_iter_get_basic(iter, &u64);
120                         fprintf(stdout, "%"PRIu64, u64);
121                         break;
122
123                 case DBUS_TYPE_DOUBLE:
124                         dbus_message_iter_get_basic(iter, &d);
125                         fprintf(stdout, "%f", d);
126                         break;
127
128                 default:
129                         fprintf(stdout, "<type %c>", arg_type);
130                         break;
131                 }
132
133                 if (dbus_message_iter_has_next(iter))
134                         fprintf(stdout, "%s", sep);
135
136                 dbus_message_iter_next(iter);
137         }
138 }
139
140 struct dbus_callback {
141         connmanctl_dbus_method_return_func_t cb;
142         void *user_data;
143 };
144
145 static void dbus_method_reply(DBusPendingCall *call, void *user_data)
146 {
147         struct dbus_callback *callback = user_data;
148         int res = 0;
149         DBusMessage *reply;
150         DBusMessageIter iter;
151
152         __connmanctl_save_rl();
153
154         reply = dbus_pending_call_steal_reply(call);
155         dbus_pending_call_unref(call);
156         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
157                 DBusError err;
158
159                 dbus_error_init(&err);
160                 dbus_set_error_from_message(&err, reply);
161
162                 callback->cb(NULL, err.message, callback->user_data);
163
164                 dbus_error_free(&err);
165                 goto end;
166         }
167
168         dbus_message_iter_init(reply, &iter);
169         res = callback->cb(&iter, NULL, callback->user_data);
170
171 end:
172         __connmanctl_redraw_rl();
173         if (__connmanctl_is_interactive() == false && res != -EINPROGRESS)
174                 __connmanctl_quit();
175
176         g_free(callback);
177         dbus_message_unref(reply);
178 }
179
180 static int send_method_call(DBusConnection *connection,
181                 DBusMessage *message, connmanctl_dbus_method_return_func_t cb,
182                 void *user_data)
183 {
184         int res = -ENXIO;
185         DBusPendingCall *call;
186         struct dbus_callback *callback;
187
188         if (!dbus_connection_send_with_reply(connection, message, &call, TIMEOUT))
189                 goto end;
190
191         if (!call)
192                 goto end;
193
194         if (cb) {
195                 callback = g_new0(struct dbus_callback, 1);
196                 callback->cb = cb;
197                 callback->user_data = user_data;
198                 dbus_pending_call_set_notify(call, dbus_method_reply,
199                                 callback, NULL);
200                 res = -EINPROGRESS;
201         }
202
203 end:
204         dbus_message_unref(message);
205         return res;
206 }
207
208 static int append_variant(DBusMessageIter *iter, const char *property,
209                 int type, void *value)
210 {
211         DBusMessageIter variant;
212         char *type_str;
213
214         switch(type) {
215         case DBUS_TYPE_BOOLEAN:
216                 type_str = DBUS_TYPE_BOOLEAN_AS_STRING;
217                 break;
218         case DBUS_TYPE_BYTE:
219                 type_str = DBUS_TYPE_BYTE_AS_STRING;
220                 break;
221         case DBUS_TYPE_STRING:
222                 type_str = DBUS_TYPE_STRING_AS_STRING;
223                 break;
224         case DBUS_TYPE_INT32:
225                 type_str = DBUS_TYPE_INT32_AS_STRING;
226                 break;
227 #if defined TIZEN_EXT_WIFI_MESH
228         case DBUS_TYPE_UINT16:
229                 type_str = DBUS_TYPE_UINT16_AS_STRING;
230                 break;
231 #endif
232         default:
233                 return -EOPNOTSUPP;
234         }
235
236         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
237         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, type_str,
238                         &variant);
239         dbus_message_iter_append_basic(&variant, type, value);
240         dbus_message_iter_close_container(iter, &variant);
241
242         return 0;
243 }
244
245 int __connmanctl_dbus_method_call(DBusConnection *connection,
246                 const char *service, const char *path, const char *interface,
247                 const char *method, connmanctl_dbus_method_return_func_t cb,
248                 void *user_data, connmanctl_dbus_append_func_t append_func,
249                 void *append_data)
250 {
251         DBusMessage *message;
252         DBusMessageIter iter;
253
254         message = dbus_message_new_method_call(service, path, interface,
255                         method);
256
257         if (!message)
258                 return -ENOMEM;
259
260         if (append_func) {
261                 dbus_message_iter_init_append(message, &iter);
262                 append_func(&iter, append_data);
263         }
264
265         return send_method_call(connection, message, cb, user_data);
266 }
267
268 int __connmanctl_dbus_set_property(DBusConnection *connection,
269                 const char *path, const char *interface,
270                 connmanctl_dbus_method_return_func_t cb, void * user_data,
271                 const char *property, int type, void *value)
272 {
273         DBusMessage *message;
274         DBusMessageIter iter;
275
276         message = dbus_message_new_method_call("net.connman", path,
277                         interface, "SetProperty");
278
279         if (!message)
280                 return -ENOMEM;
281
282         dbus_message_iter_init_append(message, &iter);
283
284         if (append_variant(&iter, property, type, value) < 0) {
285                 dbus_message_unref(message);
286                 return -EINVAL;
287         }
288
289         return send_method_call(connection, message, cb, user_data);
290 }
291
292 void __connmanctl_dbus_append_dict(DBusMessageIter *iter,
293                 connmanctl_dbus_append_func_t append_fn, void *append_data)
294 {
295         DBusMessageIter dict;
296
297         dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
298                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
299                         DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
300                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
301
302         if (append_fn)
303                 append_fn(&dict, append_data);
304
305         dbus_message_iter_close_container(iter, &dict);
306 }
307
308 void __connmanctl_dbus_append_dict_entry(DBusMessageIter *iter,
309                 const char *property, int type, void *value)
310 {
311         DBusMessageIter dict_entry;
312
313         dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL,
314                         &dict_entry);
315
316         append_variant(&dict_entry, property, type, value);
317
318         dbus_message_iter_close_container(iter, &dict_entry);
319 }
320
321 int __connmanctl_dbus_set_property_dict(DBusConnection *connection,
322                 const char *path, const char *interface,
323                 connmanctl_dbus_method_return_func_t cb, void *user_data,
324                 const char *property, int type,
325                 connmanctl_dbus_append_func_t append_fn,
326                 void *append_user_data)
327 {
328         DBusMessage *message;
329         DBusMessageIter iter, variant, dict;
330
331         message = dbus_message_new_method_call("net.connman", path,
332                         interface, "SetProperty");
333
334         if (!message)
335                 return -ENOMEM;
336
337         dbus_message_iter_init_append(message, &iter);
338         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
339         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
340                         DBUS_TYPE_ARRAY_AS_STRING
341                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
342                                         DBUS_TYPE_STRING_AS_STRING
343                                         DBUS_TYPE_VARIANT_AS_STRING
344                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
345                         &variant);
346
347         dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
348                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
349                                 DBUS_TYPE_STRING_AS_STRING
350                                 DBUS_TYPE_VARIANT_AS_STRING
351                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
352                         &dict);
353
354         append_fn(&dict, append_user_data);
355
356         dbus_message_iter_close_container(&variant, &dict);
357         dbus_message_iter_close_container(&iter, &variant);
358
359         return send_method_call(connection, message, cb, user_data);
360 }
361
362 #if defined TIZEN_EXT_WIFI_MESH
363 int __connmanctl_dbus_mesh_dict(DBusConnection *connection,
364                 const char *path, const char *interface,
365                 connmanctl_dbus_method_return_func_t cb, void *user_data,
366                 const char *property, int type,
367                 connmanctl_dbus_append_func_t append_fn,
368                 void *append_user_data)
369 {
370         DBusMessage *message;
371         DBusMessageIter iter, variant, dict;
372
373         message = dbus_message_new_method_call(CONNMAN_SERVICE, path,
374                         interface, "MeshCommands");
375
376         if (!message)
377                 return -ENOMEM;
378
379         dbus_message_iter_init_append(message, &iter);
380         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
381         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
382                         DBUS_TYPE_ARRAY_AS_STRING
383                                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
384                                         DBUS_TYPE_STRING_AS_STRING
385                                         DBUS_TYPE_VARIANT_AS_STRING
386                                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
387                         &variant);
388
389         dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
390                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
391                                 DBUS_TYPE_STRING_AS_STRING
392                                 DBUS_TYPE_VARIANT_AS_STRING
393                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
394                         &dict);
395
396         if (append_fn)
397                 append_fn(&dict, append_user_data);
398
399         dbus_message_iter_close_container(&variant, &dict);
400         dbus_message_iter_close_container(&iter, &variant);
401
402         return send_method_call(connection, message, cb, user_data);
403 }
404 #endif
405
406 static void append_variant_array(DBusMessageIter *iter, const char *property,
407                 connmanctl_dbus_append_func_t append_fn,
408                 void *append_user_data)
409 {
410         DBusMessageIter variant, array;
411
412         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
413         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
414                         DBUS_TYPE_ARRAY_AS_STRING
415                                 DBUS_TYPE_STRING_AS_STRING,
416                         &variant);
417
418         dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
419                         DBUS_TYPE_STRING_AS_STRING, &array);
420
421         append_fn(&array, append_user_data);
422
423         dbus_message_iter_close_container(&variant, &array);
424         dbus_message_iter_close_container(iter, &variant);
425 }
426
427 void __connmanctl_dbus_append_dict_string_array(DBusMessageIter *iter,
428                 const char *property, connmanctl_dbus_append_func_t append_fn,
429                 void *append_user_data)
430 {
431         DBusMessageIter dict_entry;
432
433         dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL,
434                         &dict_entry);
435
436         append_variant_array(&dict_entry, property, append_fn,
437                         append_user_data);
438
439         dbus_message_iter_close_container(iter, &dict_entry);
440 }
441
442 int __connmanctl_dbus_set_property_array(DBusConnection *connection,
443                 const char *path, const char *interface,
444                 connmanctl_dbus_method_return_func_t cb, void *user_data,
445                 const char *property, int type,
446                 connmanctl_dbus_append_func_t append_fn,
447                 void *append_user_data)
448 {
449         DBusMessage *message;
450         DBusMessageIter iter;
451
452         if (type != DBUS_TYPE_STRING)
453                 return -EOPNOTSUPP;
454
455         message = dbus_message_new_method_call("net.connman", path,
456                         interface, "SetProperty");
457
458         if (!message)
459                 return -ENOMEM;
460
461         dbus_message_iter_init_append(message, &iter);
462
463         append_variant_array(&iter, property, append_fn, append_user_data);
464
465         return send_method_call(connection, message, cb, user_data);
466 }
467
468 int __connmanctl_dbus_session_change(DBusConnection *connection,
469                 const char *session_path,
470                 connmanctl_dbus_method_return_func_t cb, void * user_data,
471                 const char *property, int type, void *value)
472 {
473         DBusMessage *message;
474         DBusMessageIter iter;
475
476         message = dbus_message_new_method_call("net.connman", session_path,
477                         "net.connman.Session", "Change");
478
479         if (!message)
480                 return -ENOMEM;
481
482         dbus_message_iter_init_append(message, &iter);
483
484         if (append_variant(&iter, property, type, value) < 0) {
485                 dbus_message_unref(message);
486                 return -EINVAL;
487         }
488
489         return send_method_call(connection, message, cb, user_data);
490 }
491
492 int __connmanctl_dbus_session_change_array(DBusConnection *connection,
493                 const char *session_path,
494                 connmanctl_dbus_method_return_func_t cb, void *user_data,
495                 const char *property,
496                 connmanctl_dbus_append_func_t append_fn,
497                 void *append_user_data)
498 {
499         DBusMessage *message;
500         DBusMessageIter iter;
501
502         message = dbus_message_new_method_call("net.connman", session_path,
503                         "net.connman.Session", "Change");
504
505         if (!message)
506                 return -ENOMEM;
507
508         dbus_message_iter_init_append(message, &iter);
509
510         append_variant_array(&iter, property, append_fn, append_user_data);
511
512         return send_method_call(connection, message, cb, user_data);
513 }