client: Add connmanctl D-Bus helper functions
[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 "dbus_helpers.h"
28
29 #define TIMEOUT         60000
30
31 void __connmanctl_dbus_print(DBusMessageIter *iter, const char *pre,
32                 const char *dict, const char *sep)
33 {
34         int arg_type;
35         dbus_bool_t b;
36         unsigned char c;
37         unsigned int i;
38         double d;
39
40         char *str;
41         DBusMessageIter entry;
42
43         if (pre == NULL)
44                 pre = "";
45
46         while ((arg_type = dbus_message_iter_get_arg_type(iter))
47                         != DBUS_TYPE_INVALID) {
48
49                 fprintf(stdout, "%s", pre);
50
51                 switch (arg_type) {
52                 case DBUS_TYPE_STRUCT:
53                         fprintf(stdout, "{ ");
54                         dbus_message_iter_recurse(iter, &entry);
55                         __connmanctl_dbus_print(&entry, "", "=", " ");
56                         fprintf(stdout, " }");
57                         break;
58
59                 case DBUS_TYPE_ARRAY:
60                         fprintf(stdout, "[ ");
61
62                         dbus_message_iter_recurse(iter, &entry);
63                         __connmanctl_dbus_print(&entry, "", "=", ", ");
64
65                         fprintf(stdout, " ]");
66                         break;
67
68                 case DBUS_TYPE_DICT_ENTRY:
69
70                         dbus_message_iter_recurse(iter, &entry);
71                         __connmanctl_dbus_print(&entry, "", dict, dict);
72                         break;
73
74                 case DBUS_TYPE_STRING:
75                 case DBUS_TYPE_OBJECT_PATH:
76                         dbus_message_iter_get_basic(iter, &str);
77                         fprintf(stdout, "%s", str);
78                         break;
79
80                 case DBUS_TYPE_VARIANT:
81                         dbus_message_iter_recurse(iter, &entry);
82                         __connmanctl_dbus_print(&entry, pre, dict, sep);
83                         break;
84
85                 case DBUS_TYPE_BOOLEAN:
86                         dbus_message_iter_get_basic(iter, &b);
87                         if (b == FALSE)
88                                 fprintf(stdout, "False");
89                         else
90                                 fprintf(stdout, "True");
91                         break;
92
93                 case DBUS_TYPE_BYTE:
94                         dbus_message_iter_get_basic(iter, &c);
95                         fprintf(stdout, "%d", c);
96                         break;
97
98                 case DBUS_TYPE_UINT16:
99                 case DBUS_TYPE_UINT32:
100                         dbus_message_iter_get_basic(iter, &i);
101                         fprintf(stdout, "%d", i);
102                         break;
103
104                 case DBUS_TYPE_DOUBLE:
105                         dbus_message_iter_get_basic(iter, &d);
106                         fprintf(stdout, "%f", d);
107                         break;
108
109                 default:
110                         fprintf(stdout, "<type %c>", arg_type);
111                         break;
112                 }
113
114                 if (dbus_message_iter_has_next(iter) == TRUE)
115                         fprintf(stdout, "%s", sep);
116
117                 dbus_message_iter_next(iter);
118         }
119 }
120
121 struct dbus_callback {
122         connmanctl_dbus_method_return_func_t cb;
123         void *user_data;
124 };
125
126 static void dbus_method_reply(DBusPendingCall *call, void *user_data)
127 {
128         struct dbus_callback *callback = user_data;
129         DBusMessage *reply;
130         DBusMessageIter iter;
131
132         reply = dbus_pending_call_steal_reply(call);
133         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
134                 DBusError err;
135
136                 dbus_error_init(&err);
137                 dbus_set_error_from_message(&err, reply);
138
139                 callback->cb(NULL, err.message, callback->user_data);
140
141                 dbus_error_free(&err);
142                 goto end;
143         }
144
145         dbus_message_iter_init(reply, &iter);
146         callback->cb(&iter, NULL, callback->user_data);
147
148 end:
149         g_free(callback);
150         dbus_message_unref(reply);
151 }
152
153 int __connmanctl_dbus_method_call(DBusConnection *connection, const char *path,
154                 const char *interface, const char *method,
155                 connmanctl_dbus_method_return_func_t cb, void * user_data,
156                 int arg1, ...)
157 {
158         int res = -ENXIO;
159         DBusMessage *message;
160         va_list args;
161         DBusPendingCall *call;
162         struct dbus_callback *callback;
163
164         message = dbus_message_new_method_call("net.connman", path,
165                         interface, method);
166
167         if (message == NULL)
168                 return -ENOMEM;
169
170         va_start(args, arg1);
171         dbus_message_append_args_valist(message, arg1, args);
172         va_end(args);
173
174         if (dbus_connection_send_with_reply(connection, message, &call,
175                                         TIMEOUT) == FALSE)
176                 goto end;
177
178         if (call == NULL)
179                 goto end;
180
181         if (cb != NULL) {
182                 callback = g_new0(struct dbus_callback, 1);
183                 callback->cb = cb;
184                 callback->user_data = user_data;
185                 dbus_pending_call_set_notify(call, dbus_method_reply,
186                                 callback, NULL);
187                 res = -EINPROGRESS;
188         }
189
190 end:
191         dbus_message_unref(message);
192         return res;
193 }