Initialize Tizen 2.3
[framework/connectivity/net-config.git] / wearable / src / signal-handler.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <dbus/dbus-glib-lowlevel.h>
23
24 #include <vconf.h>
25 #include <vconf-keys.h>
26
27 #include "log.h"
28 #include "util.h"
29 #include "netdbus.h"
30 #include "neterror.h"
31 #include "wifi-wps.h"
32 #include "wifi-agent.h"
33 #include "wifi-power.h"
34 #include "wifi-state.h"
35 #include "netsupplicant.h"
36 #include "network-state.h"
37 #include "cellular-state.h"
38 #include "signal-handler.h"
39 #include "wifi-ssid-scan.h"
40 #include "wifi-background-scan.h"
41
42 #define SIGNAL_INTERFACE_REMOVED                        "InterfaceRemoved"
43 #define SIGNAL_SCAN_DONE                                        "ScanDone"
44 #define SIGNAL_BSS_ADDED                                        "BSSAdded"
45 #define SIGNAL_PROPERTIES_CHANGED                       "PropertiesChanged"
46 #define SIGNAL_PROPERTIES_DRIVER_HANGED         "DriverHanged"
47
48 #define CONNMAN_SIGNAL_SERVICES_CHANGED         "ServicesChanged"
49 #define CONNMAN_SIGNAL_PROPERTY_CHANGED         "PropertyChanged"
50
51 #define CONNMAN_TECHNOLOGY_SIGNAL_FILTER \
52         "type='signal',interface='"CONNMAN_TECHNOLOGY_INTERFACE"'"
53
54 #define CONNMAN_SERVICE_STATE_SIGNAL_FILTER \
55         "type='signal',interface='"CONNMAN_SERVICE_INTERFACE \
56         "',member='PropertyChanged',arg0='State'"
57
58 #define CONNMAN_SERVICE_PROXY_SIGNAL_FILTER \
59         "type='signal',interface='"CONNMAN_SERVICE_INTERFACE \
60         "',member='PropertyChanged',arg0='Proxy'"
61
62 #define SUPPLICANT_INTERFACE_REMOVED_SIGNAL_FILTER \
63         "type='signal',interface='"SUPPLICANT_INTERFACE \
64         "',member='"SIGNAL_INTERFACE_REMOVED"'"
65
66 #define SUPPLICANT_INTERFACE_PROPERTIESCHANGED_SIGNAL_FILTER \
67         "type='signal',interface='"SUPPLICANT_IFACE_INTERFACE \
68         "',member='"SIGNAL_PROPERTIES_CHANGED"'"
69
70 #define SUPPLICANT_INTERFACE_BSSADDED_SIGNAL_FILTER \
71         "type='signal',interface='"SUPPLICANT_IFACE_INTERFACE \
72         "',member='"SIGNAL_BSS_ADDED"'"
73
74 #define SUPPLICANT_INTERFACE_SCANDONE_SIGNAL_FILTER \
75         "type='signal',interface='"SUPPLICANT_IFACE_INTERFACE \
76         "',member='"SIGNAL_SCAN_DONE"'"
77
78 #define SUPPLICANT_INTERFACE_DRIVERHANGED_SIGNAL_FILTER \
79         "type='signal',interface='"SUPPLICANT_IFACE_INTERFACE \
80         "',member='"SIGNAL_PROPERTIES_DRIVER_HANGED"'"
81
82 #define CONNMAN_SERVICE_NAMECHANGED_SIGNAL_FILTER \
83         "type='signal',sender='"DBUS_SERVICE_DBUS \
84         "',interface='"DBUS_INTERFACE_DBUS \
85         "',member='NameOwnerChanged',path='/org/freedesktop/DBus'" \
86         ",arg0='"CONNMAN_SERVICE"'"
87
88
89 static DBusConnection *signal_connection = NULL;
90
91 static void __netconfig_technology_signal_handler(DBusMessage *msg)
92 {
93         char *key = NULL;
94         const char *tech = NULL;
95         dbus_bool_t value = FALSE;
96
97         if (netconfig_dbus_get_basic_params_string(msg,
98                         &key, DBUS_TYPE_BOOLEAN, &value) != TRUE)
99                 return;
100
101         tech = dbus_message_get_path(msg);
102         if (key == NULL || tech == NULL)
103                 return;
104
105         if (g_str_has_prefix(tech, CONNMAN_WIFI_TECHNOLOGY_PREFIX) == TRUE) {
106                 if (g_strcmp0(key, "Powered") == 0) {
107                         /* Power state */
108                         if (value == TRUE) {
109                                 netconfig_wifi_update_power_state(TRUE);
110                         } else {
111                                 netconfig_wifi_update_power_state(FALSE);
112                         }
113                 } else if (g_strcmp0(key, "Connected") == 0) {
114                         /* Connection state */
115                         netconfig_wifi_state_set_technology_state(
116                                                                 NETCONFIG_WIFI_TECH_CONNECTED);
117                 } else if (g_strcmp0(key, "Tethering") == 0) {
118                         /* Tethering state */
119                         netconfig_wifi_state_set_technology_state(
120                                                                 NETCONFIG_WIFI_TECH_TETHERED);
121                 }
122         } else if (g_str_has_prefix(tech,
123                         CONNMAN_CELLULAR_TECHNOLOGY_PREFIX) == TRUE) {
124                 /* Cellular technology state */
125         }
126 }
127
128 static void __netconfig_service_signal_handler(DBusMessage *msg)
129 {
130         char *sigvalue = NULL;
131         char *property = NULL;
132         char *service_profile = NULL;
133         DBusMessageIter args, variant, iter1, iter2, iter3, iter4;
134         const char *value = NULL;
135
136         service_profile = (char *)dbus_message_get_path(msg);
137         if (service_profile == NULL)
138                 return;
139
140         dbus_message_iter_init(msg, &args);
141         dbus_message_iter_get_basic(&args, &sigvalue);
142         if (sigvalue == NULL)
143                 return;
144
145         if (g_str_equal(sigvalue, "State") == TRUE) {
146                 dbus_message_iter_next(&args);
147                 dbus_message_iter_recurse(&args, &variant);
148                 dbus_message_iter_get_basic(&variant, &property);
149
150                 DBG("[%s] %s", property, service_profile);
151                 if (netconfig_is_wifi_profile(service_profile) == TRUE) {
152                         int wifi_state = 0;
153
154                         vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
155                         if (wifi_state == VCONFKEY_WIFI_OFF)
156                                 return;
157
158                         if (g_str_equal(property, "ready") == TRUE ||
159                                         g_str_equal(property, "online") == TRUE) {
160                                 if (wifi_state >= VCONFKEY_WIFI_CONNECTED)
161                                         return;
162
163                                 netconfig_update_default_profile(service_profile);
164
165                                 netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTED);
166
167                         } else if (g_str_equal(property, "failure") == TRUE ||
168                                         g_str_equal(property, "disconnect") == TRUE ||
169                                         g_str_equal(property, "idle") == TRUE) {
170                                 if (netconfig_get_default_profile() == NULL ||
171                                                 netconfig_is_wifi_profile(netconfig_get_default_profile())
172                                                 != TRUE) {
173                                         if (g_str_equal(property, "failure") == TRUE)
174                                                 netconfig_wifi_state_set_service_state(
175                                                                                         NETCONFIG_WIFI_FAILURE);
176                                         else
177                                                 netconfig_wifi_state_set_service_state(
178                                                                                         NETCONFIG_WIFI_IDLE);
179                                         return;
180                                 }
181
182                                 if (g_str_equal(service_profile, netconfig_get_default_profile())
183                                                 != TRUE)
184                                         return;
185
186                                 netconfig_update_default_profile(NULL);
187
188                                 if (g_str_equal(property, "failure") == TRUE)
189                                         netconfig_wifi_state_set_service_state(
190                                                                                 NETCONFIG_WIFI_FAILURE);
191                                 else
192                                         netconfig_wifi_state_set_service_state(
193                                                                                 NETCONFIG_WIFI_IDLE);
194
195                         } else if (g_str_equal(property, "association") == TRUE ||
196                                         g_str_equal(property, "configuration") == TRUE) {
197                                 if (netconfig_get_default_profile() == NULL ||
198                                                 netconfig_is_wifi_profile(netconfig_get_default_profile())
199                                                 != TRUE) {
200                                         netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTING);
201                                         return;
202                                 }
203
204                                 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
205                                         return;
206
207                                 netconfig_update_default_profile(NULL);
208
209                                 netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTING);
210
211                         }
212                 } else {
213                         if (g_str_equal(property, "ready") == TRUE ||
214                                         g_str_equal(property, "online") == TRUE) {
215                                 if (netconfig_get_default_profile() == NULL)
216                                         netconfig_update_default_profile(service_profile);
217
218                                 if (netconfig_is_cellular_profile(service_profile) == TRUE)
219                                         netconfig_cellular_state_set_service_state(NETCONFIG_CELLULAR_ONLINE);
220                         } else if (g_str_equal(property, "failure") == TRUE ||
221                                         g_str_equal(property, "disconnect") == TRUE ||
222                                         g_str_equal(property, "idle") == TRUE) {
223                                 if (netconfig_get_default_profile() == NULL)
224                                         return;
225
226                                 if (netconfig_is_cellular_profile(service_profile) == TRUE)
227                                         netconfig_cellular_state_set_service_state(NETCONFIG_CELLULAR_IDLE);
228
229                                 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
230                                         return;
231
232                                 netconfig_update_default_profile(NULL);
233                         } else if (g_str_equal(property, "association") == TRUE ||
234                                         g_str_equal(property, "configuration") == TRUE) {
235                                 if (netconfig_get_default_profile() == NULL)
236                                         return;
237
238                                 if (netconfig_is_cellular_profile(service_profile) == TRUE)
239                                         netconfig_cellular_state_set_service_state(NETCONFIG_CELLULAR_IDLE);
240
241                                 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
242                                         return;
243
244                                 netconfig_update_default_profile(NULL);
245                         }
246                 }
247         } else if (g_str_equal(sigvalue, "Proxy") == TRUE) {
248                 dbus_message_iter_next(&args);
249                 dbus_message_iter_recurse(&args, &variant);
250
251                 if (netconfig_is_wifi_profile(service_profile) != TRUE ||
252                                 g_strcmp0(service_profile, netconfig_get_default_profile()) != 0)
253                         return;
254
255                 if (dbus_message_iter_get_arg_type(&variant) != DBUS_TYPE_ARRAY)
256                         return;
257
258                 dbus_message_iter_recurse(&variant, &iter1);
259                 while (dbus_message_iter_get_arg_type(&iter1) ==
260                                 DBUS_TYPE_DICT_ENTRY) {
261                         dbus_message_iter_recurse(&iter1, &iter2);
262                         dbus_message_iter_get_basic(&iter2, &property);
263
264                         if (g_strcmp0(property, "Servers") == 0) {
265                                 dbus_message_iter_next(&iter2);
266                                 dbus_message_iter_recurse(&iter2, &iter3);
267
268                                 if (dbus_message_iter_get_arg_type(&iter3) !=
269                                                 DBUS_TYPE_ARRAY)
270                                         return;
271
272                                 dbus_message_iter_recurse(&iter3, &iter4);
273                                 if (dbus_message_iter_get_arg_type(&iter4) !=
274                                                 DBUS_TYPE_STRING)
275                                         return;
276
277                                 dbus_message_iter_get_basic(&iter4, &value);
278                                 DBG("Proxy - [%s]", value);
279
280                                 vconf_set_str(VCONFKEY_NETWORK_PROXY, value);
281                                 break;
282                         } else if (g_strcmp0(property, "Method") == 0) {
283                                 dbus_message_iter_next(&iter2);
284                                 dbus_message_iter_recurse(&iter2, &iter3);
285
286                                 if (dbus_message_iter_get_arg_type(&iter3) !=
287                                                 DBUS_TYPE_STRING)
288                                         return;
289
290                                 dbus_message_iter_get_basic(&iter3, &value);
291                                 DBG("Method - [%s]", value);
292
293                                 if (g_strcmp0(value, "direct") == 0)
294                                         vconf_set_str(VCONFKEY_NETWORK_PROXY, "");
295
296                                 break;
297                         }
298                         dbus_message_iter_next(&iter1);
299                 }
300         }
301 }
302
303 static void __netconfig_dbus_name_changed_signal_handler(DBusMessage *msg)
304 {
305         char *name, *old, *new;
306
307         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &name,
308                         DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new);
309
310         if (g_strcmp0(name, CONNMAN_SERVICE) == 0 && *new == '\0') {
311                 DBG("ConnMan destroyed: name %s, old %s, new %s", name, old, new);
312
313                 netconfig_agent_register();
314         }
315 }
316
317 static DBusHandlerResult __netconfig_signal_filter_handler(
318                 DBusConnection *conn, DBusMessage *msg, void *user_data)
319 {
320         if (msg == NULL) {
321                 DBG("Invalid Message. Ignore");
322                 return DBUS_HANDLER_RESULT_HANDLED;
323         }
324
325         if (dbus_message_is_signal(msg, CONNMAN_TECHNOLOGY_INTERFACE,
326                         CONNMAN_SIGNAL_PROPERTY_CHANGED)) {
327                 __netconfig_technology_signal_handler(msg);
328
329                 return DBUS_HANDLER_RESULT_HANDLED;
330         } else if (dbus_message_is_signal(msg, CONNMAN_SERVICE_INTERFACE,
331                         CONNMAN_SIGNAL_PROPERTY_CHANGED)) {
332                 __netconfig_service_signal_handler(msg);
333
334                 return DBUS_HANDLER_RESULT_HANDLED;
335         } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE,
336                         SIGNAL_INTERFACE_REMOVED)) {
337                 if (netconfig_wifi_is_wps_enabled() == TRUE)
338                         netconfig_wifi_wps_signal_scanaborted();
339
340                 return DBUS_HANDLER_RESULT_HANDLED;
341         } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
342                         SIGNAL_PROPERTIES_CHANGED)) {
343                 dbus_bool_t scanning = FALSE;
344                 void *property = &scanning;
345
346                 if (netconfig_dbus_get_basic_params_array(msg,
347                                                         "Scanning", &property) == TRUE) {
348                         if (scanning == TRUE)
349                                 netconfig_wifi_set_scanning(TRUE);
350                 }
351
352                 return DBUS_HANDLER_RESULT_HANDLED;
353         } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
354                         SIGNAL_BSS_ADDED)) {
355                 if (netconfig_wifi_get_ssid_scan_state() == TRUE)
356                         netconfig_wifi_bss_added(msg);
357                 else
358                         netconfig_wifi_set_bss_found(TRUE);
359
360                 return DBUS_HANDLER_RESULT_HANDLED;
361         } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
362                         SIGNAL_SCAN_DONE)) {
363                 netconfig_wifi_set_scanning(FALSE);
364
365                 if (netconfig_wifi_is_wps_enabled() == TRUE) {
366                         netconfig_wifi_wps_signal_scandone();
367                         if (netconfig_wifi_state_get_technology_state() <
368                                                                         NETCONFIG_WIFI_TECH_POWERED)
369                                 return DBUS_HANDLER_RESULT_HANDLED;
370                 }
371
372                 if (netconfig_wifi_get_bgscan_state() != TRUE) {
373                         if (netconfig_wifi_get_ssid_scan_state() == TRUE)
374                                 netconfig_wifi_notify_ssid_scan_done();
375                         else
376                                 netconfig_wifi_ssid_scan(NULL);
377                 } else {
378                         netconfig_wifi_check_network_notification();
379                 }
380
381                 return DBUS_HANDLER_RESULT_HANDLED;
382         } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
383                         SIGNAL_PROPERTIES_DRIVER_HANGED)) {
384                 ERR("Critical. Wi-Fi firmware crashed");
385
386                 netconfig_wifi_recover_firmware();
387
388                 return DBUS_HANDLER_RESULT_HANDLED;
389         } else if (dbus_message_is_signal(msg, DBUS_INTERFACE_DBUS,
390                         "NameOwnerChanged")) {
391                 __netconfig_dbus_name_changed_signal_handler(msg);
392
393                 return DBUS_HANDLER_RESULT_HANDLED;
394         }
395
396         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
397 }
398
399 void netconfig_register_signal(void)
400 {
401         DBusError err;
402         DBusConnection *conn = NULL;
403
404         dbus_error_init(&err);
405         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
406         if (conn == NULL) {
407                 ERR("Failed to get system bus [%s]", err.message);
408                 dbus_error_free(&err);
409                 return;
410         }
411
412         signal_connection = conn;
413
414         dbus_connection_setup_with_g_main(conn, NULL);
415
416         /* listening to messages from all objects as no path is specified */
417         /* see signals from the given interface */
418         dbus_bus_add_match(conn, CONNMAN_TECHNOLOGY_SIGNAL_FILTER, &err);
419         dbus_connection_flush(conn);
420         if (dbus_error_is_set(&err)) {
421                 ERR("Match error (%s)", err.message);
422                 dbus_error_free(&err);
423                 return;
424         }
425
426         dbus_bus_add_match(conn, CONNMAN_SERVICE_STATE_SIGNAL_FILTER, &err);
427         dbus_connection_flush(conn);
428         if (dbus_error_is_set(&err)) {
429                 ERR("Match error (%s)", err.message);
430                 dbus_error_free(&err);
431                 return;
432         }
433
434         dbus_bus_add_match(conn, CONNMAN_SERVICE_PROXY_SIGNAL_FILTER, &err);
435         dbus_connection_flush(conn);
436         if (dbus_error_is_set(&err)) {
437                 ERR("Match error (%s)", err.message);
438                 dbus_error_free(&err);
439                 return;
440         }
441
442         dbus_bus_add_match(conn, SUPPLICANT_INTERFACE_REMOVED_SIGNAL_FILTER, &err);
443         dbus_connection_flush(conn);
444         if (dbus_error_is_set(&err)) {
445                 ERR("Match error (%s)", err.message);
446                 dbus_error_free(&err);
447                 return;
448         }
449
450         dbus_bus_add_match(conn,
451                         SUPPLICANT_INTERFACE_PROPERTIESCHANGED_SIGNAL_FILTER, &err);
452         dbus_connection_flush(conn);
453         if (dbus_error_is_set(&err)) {
454                 ERR("Match error (%s)", err.message);
455                 dbus_error_free(&err);
456                 return;
457         }
458
459         dbus_bus_add_match(conn, SUPPLICANT_INTERFACE_BSSADDED_SIGNAL_FILTER, &err);
460         dbus_connection_flush(conn);
461         if (dbus_error_is_set(&err)) {
462                 ERR("Match error (%s)", err.message);
463                 dbus_error_free(&err);
464                 return;
465         }
466
467         dbus_bus_add_match(conn, SUPPLICANT_INTERFACE_SCANDONE_SIGNAL_FILTER, &err);
468         dbus_connection_flush(conn);
469         if (dbus_error_is_set(&err)) {
470                 ERR("Match error (%s)", err.message);
471                 dbus_error_free(&err);
472                 return;
473         }
474
475         dbus_bus_add_match(conn,
476                         SUPPLICANT_INTERFACE_DRIVERHANGED_SIGNAL_FILTER, &err);
477         dbus_connection_flush(conn);
478         if (dbus_error_is_set(&err)) {
479                 ERR("Match error (%s)", err.message);
480                 dbus_error_free(&err);
481                 return;
482         }
483
484         dbus_bus_add_match(conn, CONNMAN_SERVICE_NAMECHANGED_SIGNAL_FILTER, &err);
485         dbus_connection_flush(conn);
486         if (dbus_error_is_set(&err)) {
487                 ERR("Match error (%s)", err.message);
488                 dbus_error_free(&err);
489                 return;
490         }
491
492         if (dbus_connection_add_filter(conn,
493                         __netconfig_signal_filter_handler, NULL, NULL) == FALSE) {
494                 ERR("Error! dbus_connection_add_filter() failed");
495                 return;
496         }
497
498         INFO("Successfully register DBus signal filters");
499
500         /* In case ConnMan precedes this signal register,
501          * net-config should update the default connected profile.
502          */
503         netconfig_update_default();
504 }
505
506 void netconfig_deregister_signal(void)
507 {
508         if (signal_connection == NULL) {
509                 ERR("Already de-registered. Nothing to be done");
510                 return;
511         }
512
513         dbus_connection_remove_filter(signal_connection,
514                                 __netconfig_signal_filter_handler, NULL);
515         INFO("Successfully remove DBus signal filters");
516
517         dbus_connection_unref(signal_connection);
518         signal_connection = NULL;
519 }