Add service types for system and VPN connections
[framework/connectivity/connman.git] / src / notifier.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2009  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 version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <gdbus.h>
27
28 #include "connman.h"
29
30 static DBusConnection *connection = NULL;
31
32 static GSList *notifier_list = NULL;
33
34 static gint compare_priority(gconstpointer a, gconstpointer b)
35 {
36         const struct connman_notifier *notifier1 = a;
37         const struct connman_notifier *notifier2 = b;
38
39         return notifier2->priority - notifier1->priority;
40 }
41
42 /**
43  * connman_notifier_register:
44  * @notifier: notifier module
45  *
46  * Register a new notifier module
47  *
48  * Returns: %0 on success
49  */
50 int connman_notifier_register(struct connman_notifier *notifier)
51 {
52         DBG("notifier %p name %s", notifier, notifier->name);
53
54         notifier_list = g_slist_insert_sorted(notifier_list, notifier,
55                                                         compare_priority);
56
57         return 0;
58 }
59
60 /**
61  * connman_notifier_unregister:
62  * @notifier: notifier module
63  *
64  * Remove a previously registered notifier module
65  */
66 void connman_notifier_unregister(struct connman_notifier *notifier)
67 {
68         DBG("notifier %p name %s", notifier, notifier->name);
69
70         notifier_list = g_slist_remove(notifier_list, notifier);
71 }
72
73 #define MAX_TECHNOLOGIES 10
74
75 static volatile gint registered[MAX_TECHNOLOGIES];
76 static volatile gint enabled[MAX_TECHNOLOGIES];
77 static volatile gint connected[MAX_TECHNOLOGIES];
78
79 void __connman_notifier_list_registered(DBusMessageIter *iter)
80 {
81         int i;
82
83         for (i = 0; i < 10; i++) {
84                 const char *type = __connman_service_type2string(i);
85
86                 if (type == NULL)
87                         continue;
88
89                 if (g_atomic_int_get(&registered[i]) > 0)
90                         dbus_message_iter_append_basic(iter,
91                                                 DBUS_TYPE_STRING, &type);
92         }
93 }
94
95 void __connman_notifier_list_enabled(DBusMessageIter *iter)
96 {
97         int i;
98
99         for (i = 0; i < 10; i++) {
100                 const char *type = __connman_service_type2string(i);
101
102                 if (type == NULL)
103                         continue;
104
105                 if (g_atomic_int_get(&enabled[i]) > 0)
106                         dbus_message_iter_append_basic(iter,
107                                                 DBUS_TYPE_STRING, &type);
108         }
109 }
110
111 void __connman_notifier_list_connected(DBusMessageIter *iter)
112 {
113         int i;
114
115         for (i = 0; i < 10; i++) {
116                 const char *type = __connman_service_type2string(i);
117
118                 if (type == NULL)
119                         continue;
120
121                 if (g_atomic_int_get(&connected[i]) > 0)
122                         dbus_message_iter_append_basic(iter,
123                                                 DBUS_TYPE_STRING, &type);
124         }
125 }
126
127 static void technology_registered(enum connman_service_type type,
128                                                 connman_bool_t registered)
129 {
130         DBusMessage *signal;
131         DBusMessageIter entry, value, iter;
132         const char *key = "AvailableTechnologies";
133
134         DBG("type %d registered %d", type, registered);
135
136         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
137                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
138         if (signal == NULL)
139                 return;
140
141         dbus_message_iter_init_append(signal, &entry);
142
143         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
144
145         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
146                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
147                                                                 &value);
148
149         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
150                                         DBUS_TYPE_STRING_AS_STRING, &iter);
151         __connman_notifier_list_registered(&iter);
152         dbus_message_iter_close_container(&value, &iter);
153
154         dbus_message_iter_close_container(&entry, &value);
155
156         g_dbus_send_message(connection, signal);
157 }
158
159 static void technology_enabled(enum connman_service_type type,
160                                                 connman_bool_t enabled)
161 {
162         GSList *list;
163         DBusMessage *signal;
164         DBusMessageIter entry, value, iter;
165         const char *key = "EnabledTechnologies";
166
167         DBG("type %d enabled %d", type, enabled);
168
169         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
170                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
171         if (signal == NULL)
172                 goto done;
173
174         dbus_message_iter_init_append(signal, &entry);
175
176         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
177
178         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
179                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
180                                                                 &value);
181
182         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
183                                         DBUS_TYPE_STRING_AS_STRING, &iter);
184         __connman_notifier_list_enabled(&iter);
185         dbus_message_iter_close_container(&value, &iter);
186
187         dbus_message_iter_close_container(&entry, &value);
188
189         g_dbus_send_message(connection, signal);
190
191 done:
192         for (list = notifier_list; list; list = list->next) {
193                 struct connman_notifier *notifier = list->data;
194
195                 if (notifier->service_enabled)
196                         notifier->service_enabled(type, enabled);
197         }
198 }
199
200 static void technology_connected(enum connman_service_type type,
201                                                 connman_bool_t connected)
202 {
203         DBusMessage *signal;
204         DBusMessageIter entry, value, iter;
205         const char *key = "ConnectedTechnologies";
206
207         DBG("type %d connected %d", type, connected);
208
209         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
210                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
211         if (signal == NULL)
212                 return;
213
214         dbus_message_iter_init_append(signal, &entry);
215
216         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
217
218         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
219                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
220                                                                 &value);
221
222         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
223                                         DBUS_TYPE_STRING_AS_STRING, &iter);
224         __connman_notifier_list_connected(&iter);
225         dbus_message_iter_close_container(&value, &iter);
226
227         dbus_message_iter_close_container(&entry, &value);
228
229         g_dbus_send_message(connection, signal);
230 }
231
232 void __connman_notifier_register(enum connman_service_type type)
233 {
234         DBG("type %d", type);
235
236         switch (type) {
237         case CONNMAN_SERVICE_TYPE_UNKNOWN:
238         case CONNMAN_SERVICE_TYPE_SYSTEM:
239         case CONNMAN_SERVICE_TYPE_VPN:
240                 return;
241         case CONNMAN_SERVICE_TYPE_ETHERNET:
242         case CONNMAN_SERVICE_TYPE_WIFI:
243         case CONNMAN_SERVICE_TYPE_WIMAX:
244         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
245         case CONNMAN_SERVICE_TYPE_CELLULAR:
246                 break;
247         }
248
249         if (g_atomic_int_exchange_and_add(&registered[type], 1) == 0)
250                 technology_registered(type, TRUE);
251 }
252
253 void __connman_notifier_unregister(enum connman_service_type type)
254 {
255         DBG("type %d", type);
256
257         switch (type) {
258         case CONNMAN_SERVICE_TYPE_UNKNOWN:
259         case CONNMAN_SERVICE_TYPE_SYSTEM:
260         case CONNMAN_SERVICE_TYPE_VPN:
261                 return;
262         case CONNMAN_SERVICE_TYPE_ETHERNET:
263         case CONNMAN_SERVICE_TYPE_WIFI:
264         case CONNMAN_SERVICE_TYPE_WIMAX:
265         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
266         case CONNMAN_SERVICE_TYPE_CELLULAR:
267                 break;
268         }
269
270         if (g_atomic_int_dec_and_test(&registered[type]) == TRUE)
271                 technology_registered(type, FALSE);
272 }
273
274 void __connman_notifier_enable(enum connman_service_type type)
275 {
276         DBG("type %d", type);
277
278         switch (type) {
279         case CONNMAN_SERVICE_TYPE_UNKNOWN:
280         case CONNMAN_SERVICE_TYPE_SYSTEM:
281         case CONNMAN_SERVICE_TYPE_VPN:
282                 return;
283         case CONNMAN_SERVICE_TYPE_ETHERNET:
284         case CONNMAN_SERVICE_TYPE_WIFI:
285         case CONNMAN_SERVICE_TYPE_WIMAX:
286         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
287         case CONNMAN_SERVICE_TYPE_CELLULAR:
288                 break;
289         }
290
291         if (g_atomic_int_exchange_and_add(&enabled[type], 1) == 0)
292                 technology_enabled(type, TRUE);
293 }
294
295 void __connman_notifier_disable(enum connman_service_type type)
296 {
297         DBG("type %d", type);
298
299         switch (type) {
300         case CONNMAN_SERVICE_TYPE_UNKNOWN:
301         case CONNMAN_SERVICE_TYPE_SYSTEM:
302         case CONNMAN_SERVICE_TYPE_VPN:
303                 return;
304         case CONNMAN_SERVICE_TYPE_ETHERNET:
305         case CONNMAN_SERVICE_TYPE_WIFI:
306         case CONNMAN_SERVICE_TYPE_WIMAX:
307         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
308         case CONNMAN_SERVICE_TYPE_CELLULAR:
309                 break;
310         }
311
312         if (g_atomic_int_dec_and_test(&enabled[type]) == TRUE)
313                 technology_enabled(type, FALSE);
314 }
315
316 void __connman_notifier_connect(enum connman_service_type type)
317 {
318         DBG("type %d", type);
319
320         switch (type) {
321         case CONNMAN_SERVICE_TYPE_UNKNOWN:
322         case CONNMAN_SERVICE_TYPE_SYSTEM:
323         case CONNMAN_SERVICE_TYPE_VPN:
324                 return;
325         case CONNMAN_SERVICE_TYPE_ETHERNET:
326         case CONNMAN_SERVICE_TYPE_WIFI:
327         case CONNMAN_SERVICE_TYPE_WIMAX:
328         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
329         case CONNMAN_SERVICE_TYPE_CELLULAR:
330                 break;
331         }
332
333         if (g_atomic_int_exchange_and_add(&connected[type], 1) == 0)
334                 technology_connected(type, TRUE);
335 }
336
337 void __connman_notifier_disconnect(enum connman_service_type type)
338 {
339         DBG("type %d", type);
340
341         switch (type) {
342         case CONNMAN_SERVICE_TYPE_UNKNOWN:
343         case CONNMAN_SERVICE_TYPE_SYSTEM:
344         case CONNMAN_SERVICE_TYPE_VPN:
345                 return;
346         case CONNMAN_SERVICE_TYPE_ETHERNET:
347         case CONNMAN_SERVICE_TYPE_WIFI:
348         case CONNMAN_SERVICE_TYPE_WIMAX:
349         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
350         case CONNMAN_SERVICE_TYPE_CELLULAR:
351                 break;
352         }
353
354         if (g_atomic_int_dec_and_test(&connected[type]) == TRUE)
355                 technology_connected(type, FALSE);
356 }
357
358 static void technology_default(enum connman_service_type type)
359 {
360         DBusMessage *signal;
361         DBusMessageIter entry, value;
362         const char *str, *key = "DefaultTechnology";
363
364         str = __connman_service_type2string(type);
365         if (str == NULL)
366                 str = "";
367
368         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
369                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
370         if (signal == NULL)
371                 return;
372
373         dbus_message_iter_init_append(signal, &entry);
374
375         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
376
377         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
378                                         DBUS_TYPE_STRING_AS_STRING, &value);
379         dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &str);
380         dbus_message_iter_close_container(&entry, &value);
381
382         g_dbus_send_message(connection, signal);
383 }
384
385 void __connman_notifier_default_changed(struct connman_service *service)
386 {
387         enum connman_service_type type = connman_service_get_type(service);
388         GSList *list;
389
390         technology_default(type);
391
392         for (list = notifier_list; list; list = list->next) {
393                 struct connman_notifier *notifier = list->data;
394
395                 if (notifier->default_changed)
396                         notifier->default_changed(service);
397         }
398 }
399
400 static void offlinemode_changed(dbus_bool_t enabled)
401 {
402         DBusMessage *signal;
403         DBusMessageIter entry, value;
404         const char *key = "OfflineMode";
405
406         DBG("enabled %d", enabled);
407
408         signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
409                                 CONNMAN_MANAGER_INTERFACE, "PropertyChanged");
410         if (signal == NULL)
411                 return;
412
413         dbus_message_iter_init_append(signal, &entry);
414
415         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
416
417         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
418                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
419         dbus_message_iter_append_basic(&value, DBUS_TYPE_BOOLEAN, &enabled);
420         dbus_message_iter_close_container(&entry, &value);
421
422         g_dbus_send_message(connection, signal);
423 }
424
425 void __connman_notifier_offlinemode(connman_bool_t enabled)
426 {
427         GSList *list;
428
429         DBG("enabled %d", enabled);
430
431         __connman_profile_changed(FALSE);
432
433         offlinemode_changed(enabled);
434
435         for (list = notifier_list; list; list = list->next) {
436                 struct connman_notifier *notifier = list->data;
437
438                 if (notifier->offline_mode)
439                         notifier->offline_mode(enabled);
440         }
441 }
442
443 connman_bool_t __connman_notifier_is_enabled(enum connman_service_type type)
444 {
445         DBG("type %d", type);
446
447         switch (type) {
448         case CONNMAN_SERVICE_TYPE_UNKNOWN:
449         case CONNMAN_SERVICE_TYPE_SYSTEM:
450         case CONNMAN_SERVICE_TYPE_VPN:
451                 return FALSE;
452         case CONNMAN_SERVICE_TYPE_ETHERNET:
453         case CONNMAN_SERVICE_TYPE_WIFI:
454         case CONNMAN_SERVICE_TYPE_WIMAX:
455         case CONNMAN_SERVICE_TYPE_BLUETOOTH:
456         case CONNMAN_SERVICE_TYPE_CELLULAR:
457                 break;
458         }
459
460         if (g_atomic_int_get(&enabled[type]) > 0)
461                 return TRUE;
462
463         return FALSE;
464 }
465
466 int __connman_notifier_init(void)
467 {
468         DBG("");
469
470         connection = connman_dbus_get_connection();
471
472         return 0;
473 }
474
475 void __connman_notifier_cleanup(void)
476 {
477         DBG("");
478
479         dbus_connection_unref(connection);
480 }