client: Reimplement monitor command
[platform/upstream/connman.git] / client / monitor.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2012  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 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <stdint.h>
32 #include <errno.h>
33
34 #include <glib.h>
35 #include <gdbus.h>
36
37 #include "monitor.h"
38 #include "services.h"
39 #include "technology.h"
40 #include "data_manager.h"
41
42 static const char *get_service_name(DBusMessage *message, char *dbus_path)
43 {
44         DBusMessageIter iter, array;
45
46         dbus_message_iter_init(message, &iter);
47         dbus_message_iter_recurse(&iter, &array);
48
49         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
50                 DBusMessageIter entry, dict;
51                 struct service_data service;
52                 char *path;
53
54                 dbus_message_iter_recurse(&array, &entry);
55                 dbus_message_iter_get_basic(&entry, &path);
56
57                 if (g_strcmp0(path, dbus_path) == 0) {
58                         dbus_message_iter_next(&entry);
59                         dbus_message_iter_recurse(&entry, &dict);
60                         extract_service_name(&dict, &service);
61                         return service.name;
62                 } else {
63                         dbus_message_iter_next(&array);
64                 }
65         }
66         return NULL;
67 }
68
69 static void extract_tech_signal(DBusMessage *message)
70 {
71         DBusMessageIter iter, dict;
72         char *path;
73
74         dbus_message_iter_init(message, &iter);
75
76         if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_OBJECT_PATH) {
77                 dbus_message_iter_get_basic(&iter, &path);
78                 printf(" { %s }\n", path);
79         }
80         dbus_message_iter_next(&iter);
81
82         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
83                 dbus_message_iter_recurse(&iter, &dict);
84                 extract_properties(&dict);
85         }
86 }
87
88 static void extract_signal_args(DBusMessage *message)
89 {
90         DBusMessageIter iter, array, dict;
91         char *string, *value;
92         uint16_t key_int;
93         dbus_bool_t bvalue;
94
95         value = NULL;
96         key_int = 0;
97
98         dbus_message_iter_init(message, &iter);
99
100         while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) {
101                 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) {
102                         dbus_message_iter_get_basic(&iter, &string);
103                         printf("\n[%s] = ",
104                         string);
105                 }
106                 dbus_message_iter_next(&iter);
107                 if (dbus_message_iter_get_arg_type(&iter) !=
108                                                         DBUS_TYPE_INVALID) {
109                         dbus_message_iter_recurse(&iter, &array);
110                         if (dbus_message_iter_get_arg_type(&array) ==
111                                                         DBUS_TYPE_STRING) {
112                                 dbus_message_iter_get_basic(&array, &value);
113                                 printf("%s\n", value);
114                                 continue;
115                         } else if (dbus_message_iter_get_arg_type(&array) ==
116                                                         DBUS_TYPE_BOOLEAN) {
117                                 dbus_message_iter_get_basic(&array, &bvalue);
118                                 printf("%s\n", bvalue == TRUE ?
119                                                         "True" : "False");
120                                 continue;
121                         } else if (dbus_message_iter_get_arg_type(&array) ==
122                                                         DBUS_TYPE_ARRAY)
123                                 dbus_message_iter_recurse(&array, &dict);
124                         if (dbus_message_iter_get_arg_type(&dict) ==
125                                                 DBUS_TYPE_DICT_ENTRY) {
126                                 iterate_dict(&dict, value, key_int);
127                                 printf("\n");
128                         } else {
129                                 iterate_array(&array);
130                                 printf("\n");
131                         }
132                         dbus_message_iter_next(&iter);
133                 }
134         }
135 }
136
137 int monitor_connman(DBusConnection *connection, char *interface,
138                                 char *signal_name)
139 {
140         char *rule = g_strdup_printf("type='signal',interface='net.connman.%s',"
141                                         "member='%s'", interface, signal_name);
142         DBusError err;
143
144         dbus_error_init(&err);
145         g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, &err);
146         if (dbus_error_is_set(&err)) {
147                 fprintf(stderr, "Bus setup error:%s\n", err.message);
148                 return -1;
149         }
150         dbus_bus_add_match(connection, rule, &err);
151
152         if (dbus_error_is_set(&err)) {
153                 fprintf(stderr, "Match Error: %s\n", err.message);
154                 return -1;
155         }
156         return 0;
157 }
158
159 static void monitor_clear(DBusConnection *connection, char *interface)
160 {
161         char *rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
162                         interface);
163
164         dbus_bus_remove_match(connection, rule, NULL);
165 }
166
167 static int monitor_add(DBusConnection *connection, char *interface)
168 {
169         char *rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
170                         interface);
171         DBusError err;
172
173         dbus_error_init(&err);
174         g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, &err);
175         if (dbus_error_is_set(&err)) {
176                 fprintf(stderr, "Bus setup error:%s\n", err.message);
177                 return -1;
178         }
179         dbus_bus_add_match(connection, rule, &err);
180
181         if (dbus_error_is_set(&err)) {
182                 fprintf(stderr, "Match Error: %s\n", err.message);
183                 return -1;
184         }
185         return 0;
186 }
187
188 int monitor_connman_service(DBusConnection *connection)
189 {
190         int err;
191
192         err = monitor_add(connection, "Service");
193         if (err < 0)
194                 return err;
195
196         if (dbus_connection_add_filter(connection,
197                                         service_property_changed,
198                                         NULL, NULL) == FALSE) {
199                 monitor_clear(connection, "Service");
200                 return -ENXIO;
201         }
202
203         return 0;
204 }
205
206 int monitor_connman_technology(DBusConnection *connection)
207 {
208         int err;
209
210         err = monitor_add(connection, "Technology");
211         if (err < 0)
212                 return err;
213
214         if (dbus_connection_add_filter(connection,
215                                         tech_property_changed,
216                                         NULL, NULL) == FALSE) {
217                 monitor_clear(connection, "Technology");
218                 return -ENXIO;
219         }
220
221         return 0;
222 }
223
224 int monitor_connman_manager(DBusConnection *connection)
225 {
226         int err;
227
228         err = monitor_add(connection, "Manager");
229         if (err < 0)
230                 return err;
231
232         if (dbus_connection_add_filter(connection, manager_property_changed,
233                                         NULL, NULL) == FALSE) {
234                 monitor_clear(connection, "Manager");
235                 return -ENXIO;
236         }
237
238         if (dbus_connection_add_filter(connection, manager_services_changed,
239                                         NULL, NULL) == FALSE) {
240                 dbus_connection_remove_filter(connection,
241                                 manager_property_changed, NULL);
242                 monitor_clear(connection, "Manager");
243                 return -ENXIO;
244         }
245
246         return 0;
247 }
248
249 DBusHandlerResult service_property_changed(DBusConnection *connection,
250                                                 DBusMessage *message,
251                                                 void *user_data)
252 {
253         DBusMessage *service_message;
254         struct service_data service;
255
256         if (dbus_message_is_signal(message, "net.connman.Service",
257                                             "PropertyChanged")) {
258                 service_message = get_message(connection, "GetServices");
259                 if (service_message == NULL)
260                         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
261
262                 service.name = get_service_name(service_message,
263                                 (char *) dbus_message_get_path(message));
264                 printf("\n");
265                 g_message("Path = %s, Interface = %s\nService = %s",
266                                 dbus_message_get_path(message),
267                                 dbus_message_get_interface(message),
268                                 service.name);
269                 extract_signal_args(message);
270
271                 dbus_message_unref(service_message);
272         }
273
274         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
275 }
276
277 DBusHandlerResult tech_property_changed(DBusConnection *connection,
278                                         DBusMessage *message, void *user_data)
279 {
280         if (dbus_message_is_signal(message, "net.connman.Technology",
281                                             "PropertyChanged")) {
282                 printf("\n");
283                 g_message("Path = %s, Interface = %s",
284                                 dbus_message_get_path(message),
285                                 dbus_message_get_interface(message));
286                 extract_signal_args(message);
287         }
288         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
289 }
290
291 DBusHandlerResult tech_added_removed(DBusConnection *connection,
292                                         DBusMessage *message, void *user_data)
293 {
294         if (dbus_message_is_signal(message, "net.connman.Manager",
295                                             "TechnologyAdded")) {
296                 printf("\n");
297                 g_message("Path = %s, Interface = %s",
298                                 dbus_message_get_path(message),
299                                 dbus_message_get_interface(message));
300                 printf("New technology added:\n");
301                 extract_tech_signal(message);
302         } else if (dbus_message_is_signal(message, "net.connman.Manager",
303                                                    "TechnologyRemoved")) {
304                 printf("\n");
305                 g_message("Path = %s, Interface = %s",
306                                 dbus_message_get_path(message),
307                                 dbus_message_get_interface(message));
308                 printf("Technology was removed:\n");
309                 extract_tech_signal(message);
310         }
311
312         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
313 }
314
315 DBusHandlerResult manager_services_changed(DBusConnection *connection,
316                                 DBusMessage *message, void *user_data)
317 {
318         if (dbus_message_is_signal(message, "net.connman.Manager",
319                                                 "ServicesChanged")) {
320                 printf("\n");
321                 g_message("Path = %s, Interface = %s",
322                                 dbus_message_get_path(message),
323                                 dbus_message_get_interface(message));
324                 printf("Services Changed, displaying updated "
325                                                         "list of services:\n");
326                 list_properties(connection, "GetServices", NULL);
327         }
328
329         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
330 }
331
332 DBusHandlerResult manager_property_changed(DBusConnection *connection,
333                                 DBusMessage *message, void *user_data)
334 {
335         if (dbus_message_is_signal(message, "net.connman.Manager",
336                                             "PropertyChanged")) {
337                 printf("\n");
338                 g_message("Path = %s, Interface = %s",
339                                 dbus_message_get_path(message),
340                                 dbus_message_get_interface(message));
341                 extract_signal_args(message);
342         }
343
344         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
345 }