merge with master
[platform/core/connectivity/net-config.git] / src / signal-handler.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2012-2013 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 "netsupplicant.h"
31 #include "wifi-state.h"
32 #include "wifi-indicator.h"
33 #include "wifi-ssid-scan.h"
34 #include "wifi-background-scan.h"
35 #include "network-state.h"
36 #include "neterror.h"
37 #include "wifi.h"
38
39 #define SIGNAL_SCAN_DONE                "ScanDone"
40 #define SIGNAL_BSS_ADDED                "BSSAdded"
41 #define SIGNAL_PROPERTIES_CHANGED                       "PropertiesChanged"
42
43 #define CONNMAN_SIGNAL_SERVICES_CHANGED         "ServicesChanged"
44 #define CONNMAN_SIGNAL_PROPERTY_CHANGED         "PropertyChanged"
45
46 #define CONNMAN_MANAGER_SIGNAL_FILTER           "type='signal',interface='net.connman.Manager'"
47 #define CONNMAN_TECHNOLOGY_SIGNAL_FILTER        "type='signal',interface='net.connman.Technology'"
48 #define CONNMAN_SERVICE_SIGNAL_FILTER           "type='signal',interface='net.connman.Service'"
49 #define SUPPLICANT_INTERFACE_SIGNAL_FILTER      "type='signal',interface='fi.w1.wpa_supplicant1.Interface'"
50
51
52 static DBusConnection *signal_connection = NULL;
53
54 static char *__netconfig_get_property(DBusMessage *msg, int *prop_value)
55 {
56         DBusMessageIter args, variant;
57         char *property = NULL;
58         dbus_bool_t data;
59
60         /** read these parameters */
61         if (!dbus_message_iter_init(msg, &args)) {
62                 ERR("Message does not have parameters");
63         } else if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
64                 ERR("Argument is not string");
65         } else {
66                 dbus_message_iter_get_basic(&args, &property);
67                 dbus_message_iter_next(&args);
68                 dbus_message_iter_recurse(&args, &variant);
69                 /* Right now, checking for only 'Powered' property which has
70                  * Boolean type values
71                  */
72                 if (dbus_message_iter_get_arg_type(&variant) == DBUS_TYPE_BOOLEAN) {
73                         dbus_message_iter_get_basic(&variant, &data);
74                         if (data)
75                                 *prop_value = TRUE;
76                         else
77                                 *prop_value = FALSE;
78                 } else {
79                         *prop_value = FALSE;
80                 }
81         }
82
83         return property;
84 }
85
86 static void __netconfig_wifi_technology_state_signal_handler(
87                 const char *property, int prop_value)
88 {
89         static int previous_technology_state = FALSE;
90         GError **error = NULL;
91
92         if (property == NULL || g_str_equal(property, "Powered") != TRUE)
93                 return;
94
95         if (previous_technology_state == prop_value) {
96                 INFO("Same as previous state");
97                 return;
98         }
99
100         previous_technology_state = prop_value;
101
102         INFO("Technology property - [%s], prop_value - [%d]",
103                         property, prop_value);
104
105         if (prop_value == FALSE) {
106                 enum netconfig_wifi_tech_state state = NETCONFIG_WIFI_TECH_OFF;
107
108                 state = netconfig_wifi_get_technology_state();
109                 INFO("Wi-Fi technology state: %d", state);
110
111                 if (NETCONFIG_WIFI_TECH_OFF == state ||
112                                 NETCONFIG_WIFI_TECH_UNKNOWN == state) {
113                         if (netconfig_wifi_remove_driver() == TRUE) {
114                                 netconfig_wifi_update_power_state(FALSE);
115
116                                 netconfig_wifi_notify_power_completed(FALSE);
117                         } else {
118                                 netconfig_error_wifi_driver_failed(error);
119                         }
120                 }
121         } else {
122                 netconfig_wifi_update_power_state(TRUE);
123                 netconfig_wifi_device_picker_service_start();
124
125                 netconfig_wifi_notify_power_completed(TRUE);
126         }
127 }
128
129 static void __netconfig_wifi_service_state_signal_handler(DBusMessage *msg)
130 {
131         char *sigvalue = NULL;
132         char *property = NULL;
133         char *service_profile = NULL;
134         DBusMessageIter args, variant;
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_set_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                                         netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_IDLE);
174                                         return;
175                                 }
176
177                                 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
178                                         return;
179
180                                 netconfig_set_default_profile(NULL);
181
182                                 netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_IDLE);
183
184                         } else if (g_str_equal(property, "association") == TRUE ||
185                                         g_str_equal(property, "configuration") == TRUE) {
186                                 if (netconfig_get_default_profile() == NULL ||
187                                                 netconfig_is_wifi_profile(netconfig_get_default_profile())
188                                                 != TRUE) {
189                                         netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTING);
190                                         return;
191                                 }
192
193                                 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
194                                         return;
195
196                                 netconfig_set_default_profile(NULL);
197
198                                 netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTING);
199                         }
200                 } else {
201                         if (g_str_equal(property, "ready") == TRUE ||
202                                         g_str_equal(property, "online") == TRUE) {
203                                 if (netconfig_get_default_profile() == NULL)
204                                         netconfig_set_default_profile(service_profile);
205
206                         } else if (g_str_equal(property, "failure") == TRUE ||
207                                         g_str_equal(property, "disconnect") == TRUE ||
208                                         g_str_equal(property, "idle") == TRUE) {
209                                 if (netconfig_get_default_profile() == NULL)
210                                         return;
211
212                                 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
213                                         return;
214
215                                 netconfig_set_default_profile(NULL);
216
217                         } else if (g_str_equal(property, "association") == TRUE ||
218                                         g_str_equal(property, "configuration") == TRUE) {
219                                 if (netconfig_get_default_profile() == NULL)
220                                         return;
221
222                                 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
223                                         return;
224
225                                 netconfig_set_default_profile(NULL);
226                         }
227                 }
228         }
229 }
230
231 static DBusHandlerResult __netconfig_signal_filter_handler(
232                 DBusConnection *conn, DBusMessage *msg, void *user_data)
233 {
234         char *sigvalue = NULL;
235
236         if (msg == NULL) {
237                 DBG("Invalid Message. Ignore");
238                 return DBUS_HANDLER_RESULT_HANDLED;
239         }
240
241         if (dbus_message_is_signal(msg, CONNMAN_MANAGER_INTERFACE,
242                         CONNMAN_SIGNAL_PROPERTY_CHANGED)) {
243                 /* We have handled this message, don't pass it on */
244                 return DBUS_HANDLER_RESULT_HANDLED;
245         } else if (dbus_message_is_signal(msg, CONNMAN_TECHNOLOGY_INTERFACE,
246                         CONNMAN_SIGNAL_PROPERTY_CHANGED)) {
247                 int prop_value = FALSE;
248                 char *technology_path = NULL;
249
250                 technology_path = (char *)dbus_message_get_path(msg);
251                 INFO("Technology object path: %s", technology_path);
252
253                 if (g_str_has_prefix(technology_path,
254                                 CONNMAN_WIFI_TECHNOLOGY_PREFIX) == FALSE) {
255                         return DBUS_HANDLER_RESULT_HANDLED;
256                 }
257
258                 sigvalue = __netconfig_get_property(msg, &prop_value);
259                 if (sigvalue == NULL)
260                         return DBUS_HANDLER_RESULT_HANDLED;
261
262                 INFO("Technology Property - [%s], Value - [%d]", sigvalue, prop_value);
263                 __netconfig_wifi_technology_state_signal_handler(
264                                 (const char *)sigvalue, prop_value);
265
266                 /* We have handled this message, don't pass it on */
267                 return DBUS_HANDLER_RESULT_HANDLED;
268         } else if (dbus_message_is_signal(msg, CONNMAN_SERVICE_INTERFACE,
269                         CONNMAN_SIGNAL_PROPERTY_CHANGED)) {
270                 __netconfig_wifi_service_state_signal_handler(msg);
271
272                 return DBUS_HANDLER_RESULT_HANDLED;
273         } else if (dbus_message_is_signal(msg, CONNMAN_MANAGER_INTERFACE,
274                         CONNMAN_SIGNAL_SERVICES_CHANGED)) {
275                 DBG("Received CONNMAN_SIGNAL_SERVICES_CHANGED message");
276                 netconfig_wifi_check_network_notification(msg);
277
278                 return DBUS_HANDLER_RESULT_HANDLED;
279         } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
280                         SIGNAL_PROPERTIES_CHANGED)) {
281                 dbus_bool_t scanning = FALSE;
282                 void *property = &scanning;
283
284                 if (netconfig_dbus_get_basic_params_array(msg,
285                                 &sigvalue, &property) != TRUE)
286                         return DBUS_HANDLER_RESULT_HANDLED;
287
288                 if (sigvalue == NULL)
289                         return DBUS_HANDLER_RESULT_HANDLED;
290
291                 if (scanning == TRUE)
292                         netconfig_wifi_set_scanning(TRUE);
293
294                 return DBUS_HANDLER_RESULT_HANDLED;
295         } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
296                         SIGNAL_BSS_ADDED)) {
297                 if (netconfig_wifi_get_ssid_scan_state() == TRUE)
298                         netconfig_wifi_bss_added(msg);
299
300                 return DBUS_HANDLER_RESULT_HANDLED;
301         } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
302                         SIGNAL_SCAN_DONE)) {
303                 netconfig_wifi_set_scanning(FALSE);
304
305                 if (netconfig_wifi_get_bgscan_state() != TRUE) {
306                         if (netconfig_wifi_get_ssid_scan_state() == TRUE)
307                                 netconfig_wifi_notify_ssid_scan_done();
308                         else
309                                 netconfig_wifi_ssid_scan(NULL);
310                 }
311
312                 return DBUS_HANDLER_RESULT_HANDLED;
313         }
314
315         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
316 }
317
318 void netconfig_register_signal(void)
319 {
320         DBusConnection *conn = NULL;
321         DBusError err;
322
323         DBG("Register DBus signal filters");
324
325         dbus_error_init(&err);
326         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
327         if (conn == NULL) {
328                 ERR("Error! Failed to connect to the D-BUS daemon: [%s]",
329                                 err.message);
330                 dbus_error_free(&err);
331                 return;
332         }
333
334         signal_connection = conn;
335
336         dbus_connection_setup_with_g_main(conn, NULL);
337
338         /* listening to messages from all objects as no path is specified */
339         /* see signals from the given interface */
340         dbus_bus_add_match(conn, CONNMAN_MANAGER_SIGNAL_FILTER, &err);
341         dbus_connection_flush(conn);
342         if (dbus_error_is_set(&err)) {
343                 ERR("Error! Match Error (%s)", err.message);
344                 dbus_error_free(&err);
345                 return;
346         }
347
348         dbus_bus_add_match(conn, CONNMAN_TECHNOLOGY_SIGNAL_FILTER, &err);
349         dbus_connection_flush(conn);
350         if (dbus_error_is_set(&err)) {
351                 ERR("Error! Match Error (%s)", err.message);
352                 dbus_error_free(&err);
353                 return;
354         }
355
356         dbus_bus_add_match(conn, CONNMAN_SERVICE_SIGNAL_FILTER, &err);
357         dbus_connection_flush(conn);
358         if (dbus_error_is_set(&err)) {
359                 ERR("Error! Match Error (%s)", err.message);
360                 dbus_error_free(&err);
361                 return;
362         }
363
364         dbus_bus_add_match(conn, SUPPLICANT_INTERFACE_SIGNAL_FILTER, &err);
365         dbus_connection_flush(conn);
366         if (dbus_error_is_set(&err)) {
367                 ERR("Error! Match Error (%s)", err.message);
368                 dbus_error_free(&err);
369                 return;
370         }
371
372         if (dbus_connection_add_filter(conn,
373                         __netconfig_signal_filter_handler, NULL, NULL) == FALSE) {
374                 ERR("Error! dbus_connection_add_filter() failed");
375                 return;
376         }
377
378         INFO("Successfully register signal filters");
379 }
380
381 void netconfig_deregister_signal(void)
382 {
383         if (signal_connection == NULL) {
384                 ERR("Error! Already de-registered. Nothing to be done");
385                 return;
386         }
387
388         dbus_connection_remove_filter(signal_connection,
389                                 __netconfig_signal_filter_handler, NULL);
390         INFO("Successfully remove DBus signal filters");
391
392         dbus_connection_unref(signal_connection);
393         signal_connection = NULL;
394
395         netconfig_wifi_deinit_bgscan();
396 }