c62457a7671e1ef01ae9bb16fdf4153892bb5ba8
[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 #include "wifi-power.h"
39
40 #define SIGNAL_SCAN_DONE                "ScanDone"
41 #define SIGNAL_BSS_ADDED                "BSSAdded"
42 #define SIGNAL_PROPERTIES_CHANGED                       "PropertiesChanged"
43
44 #define CONNMAN_SIGNAL_SERVICES_CHANGED         "ServicesChanged"
45 #define CONNMAN_SIGNAL_PROPERTY_CHANGED         "PropertyChanged"
46
47 #define CONNMAN_MANAGER_SIGNAL_FILTER           "type='signal',interface='net.connman.Manager'"
48 #define CONNMAN_TECHNOLOGY_SIGNAL_FILTER        "type='signal',interface='net.connman.Technology'"
49 #define CONNMAN_SERVICE_SIGNAL_FILTER           "type='signal',interface='net.connman.Service'"
50 #define SUPPLICANT_INTERFACE_SIGNAL_FILTER      "type='signal',interface='fi.w1.wpa_supplicant1.Interface'"
51
52
53 static DBusConnection *signal_connection = NULL;
54
55 static char *__netconfig_get_property(DBusMessage *msg, int *prop_value)
56 {
57         DBusMessageIter args, variant;
58         char *property = NULL;
59         dbus_bool_t data;
60
61         /** read these parameters */
62         if (!dbus_message_iter_init(msg, &args)) {
63                 ERR("Message does not have parameters");
64         } else if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_STRING) {
65                 ERR("Argument is not string");
66         } else {
67                 dbus_message_iter_get_basic(&args, &property);
68                 dbus_message_iter_next(&args);
69                 dbus_message_iter_recurse(&args, &variant);
70                 /* Right now, checking for only 'Powered' property which has
71                  * Boolean type values
72                  */
73                 if (dbus_message_iter_get_arg_type(&variant) == DBUS_TYPE_BOOLEAN) {
74                         dbus_message_iter_get_basic(&variant, &data);
75                         if (data)
76                                 *prop_value = TRUE;
77                         else
78                                 *prop_value = FALSE;
79                 } else {
80                         *prop_value = FALSE;
81                 }
82         }
83
84         return property;
85 }
86
87 static void __netconfig_technology_signal_handler(DBusMessage *msg)
88 {
89         char *key = NULL;
90         const char *tech = NULL;
91         dbus_bool_t value = FALSE;
92
93         if (netconfig_dbus_get_basic_params_string(msg,
94                         &key, DBUS_TYPE_BOOLEAN, &value) != TRUE)
95                 return;
96
97         tech = dbus_message_get_path(msg);
98         if (key == NULL || tech == NULL)
99                 return;
100
101         if (g_str_has_prefix(tech, CONNMAN_WIFI_TECHNOLOGY_PREFIX) == TRUE) {
102                 INFO("Wi-Fi Technology %s, property %d", key, value);
103
104                 if (g_strcmp0(key, "Powered") == 0) {
105                         /* Power state */
106                         if (value == TRUE)
107                                 netconfig_wifi_update_power_state(TRUE);
108                         else
109                                 netconfig_wifi_update_power_state(FALSE);
110
111                         netconfig_set_power_in_progress(FALSE);
112                         netconfig_check_fm_waiting();
113                 } else if (g_strcmp0(key, "Connected") == 0) {
114                         /* Connection state */
115                 } else if (g_strcmp0(key, "Tethering") == 0) {
116                         /* Tethering state */
117                         if (value == TRUE)
118                                 netconfig_wifi_update_power_state(FALSE);
119                         else
120                                 netconfig_wifi_update_power_state(TRUE);
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_wifi_service_state_signal_handler(DBusMessage *msg)
129 {
130         char *sigvalue = NULL;
131         char *property = NULL;
132         char *service_profile = NULL;
133         DBusMessageIter args, variant;
134
135         service_profile = (char *)dbus_message_get_path(msg);
136         if (service_profile == NULL)
137                 return;
138
139         dbus_message_iter_init(msg, &args);
140         dbus_message_iter_get_basic(&args, &sigvalue);
141         if (sigvalue == NULL)
142                 return;
143
144         if (g_str_equal(sigvalue, "State") == TRUE) {
145                 dbus_message_iter_next(&args);
146                 dbus_message_iter_recurse(&args, &variant);
147                 dbus_message_iter_get_basic(&variant, &property);
148
149                 DBG("[%s] %s", property, service_profile);
150                 if (netconfig_is_wifi_profile(service_profile) == TRUE) {
151                         int wifi_state = 0;
152
153                         vconf_get_int(VCONFKEY_WIFI_STATE, &wifi_state);
154                         if (wifi_state == VCONFKEY_WIFI_OFF)
155                                 return;
156
157                         if (g_str_equal(property, "ready") == TRUE ||
158                                         g_str_equal(property, "online") == TRUE) {
159                                 if (wifi_state >= VCONFKEY_WIFI_CONNECTED)
160                                         return;
161
162                                 netconfig_set_default_profile(service_profile);
163
164                                 netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTED);
165
166                         } else if (g_str_equal(property, "failure") == TRUE ||
167                                         g_str_equal(property, "disconnect") == TRUE ||
168                                         g_str_equal(property, "idle") == TRUE) {
169                                 if (netconfig_get_default_profile() == NULL ||
170                                                 netconfig_is_wifi_profile(netconfig_get_default_profile())
171                                                 != TRUE) {
172                                         netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_IDLE);
173                                         return;
174                                 }
175
176                                 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
177                                         return;
178
179                                 netconfig_set_default_profile(NULL);
180
181                                 netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_IDLE);
182
183                         } else if (g_str_equal(property, "association") == TRUE ||
184                                         g_str_equal(property, "configuration") == TRUE) {
185                                 if (netconfig_get_default_profile() == NULL ||
186                                                 netconfig_is_wifi_profile(netconfig_get_default_profile())
187                                                 != TRUE) {
188                                         netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTING);
189                                         return;
190                                 }
191
192                                 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
193                                         return;
194
195                                 netconfig_set_default_profile(NULL);
196
197                                 netconfig_wifi_state_set_service_state(NETCONFIG_WIFI_CONNECTING);
198                         }
199                 } else {
200                         if (g_str_equal(property, "ready") == TRUE ||
201                                         g_str_equal(property, "online") == TRUE) {
202                                 if (netconfig_get_default_profile() == NULL)
203                                         netconfig_set_default_profile(service_profile);
204
205                         } else if (g_str_equal(property, "failure") == TRUE ||
206                                         g_str_equal(property, "disconnect") == TRUE ||
207                                         g_str_equal(property, "idle") == TRUE) {
208                                 if (netconfig_get_default_profile() == NULL)
209                                         return;
210
211                                 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
212                                         return;
213
214                                 netconfig_set_default_profile(NULL);
215
216                         } else if (g_str_equal(property, "association") == TRUE ||
217                                         g_str_equal(property, "configuration") == TRUE) {
218                                 if (netconfig_get_default_profile() == NULL)
219                                         return;
220
221                                 if (g_str_equal(service_profile, netconfig_get_default_profile()) != TRUE)
222                                         return;
223
224                                 netconfig_set_default_profile(NULL);
225                         }
226                 }
227         }
228 }
229
230 static DBusHandlerResult __netconfig_signal_filter_handler(
231                 DBusConnection *conn, DBusMessage *msg, void *user_data)
232 {
233         char *sigvalue = NULL;
234
235         if (msg == NULL) {
236                 DBG("Invalid Message. Ignore");
237                 return DBUS_HANDLER_RESULT_HANDLED;
238         }
239
240         if (dbus_message_is_signal(msg, CONNMAN_MANAGER_INTERFACE,
241                         CONNMAN_SIGNAL_PROPERTY_CHANGED)) {
242                 /* We have handled this message, don't pass it on */
243                 return DBUS_HANDLER_RESULT_HANDLED;
244         } else if (dbus_message_is_signal(msg, CONNMAN_TECHNOLOGY_INTERFACE,
245                         CONNMAN_SIGNAL_PROPERTY_CHANGED)) {
246                 __netconfig_technology_signal_handler(msg);
247
248                 return DBUS_HANDLER_RESULT_HANDLED;
249         } else if (dbus_message_is_signal(msg, CONNMAN_SERVICE_INTERFACE,
250                         CONNMAN_SIGNAL_PROPERTY_CHANGED)) {
251                 __netconfig_wifi_service_state_signal_handler(msg);
252
253                 return DBUS_HANDLER_RESULT_HANDLED;
254         } else if (dbus_message_is_signal(msg, CONNMAN_MANAGER_INTERFACE,
255                         CONNMAN_SIGNAL_SERVICES_CHANGED)) {
256                 DBG("Received CONNMAN_SIGNAL_SERVICES_CHANGED message");
257                 netconfig_wifi_check_network_notification(msg);
258
259                 return DBUS_HANDLER_RESULT_HANDLED;
260         } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
261                         SIGNAL_PROPERTIES_CHANGED)) {
262                 dbus_bool_t scanning = FALSE;
263                 void *property = &scanning;
264
265                 if (netconfig_dbus_get_basic_params_array(msg,
266                                 &sigvalue, &property) != TRUE)
267                         return DBUS_HANDLER_RESULT_HANDLED;
268
269                 if (sigvalue == NULL)
270                         return DBUS_HANDLER_RESULT_HANDLED;
271
272                 if (scanning == TRUE)
273                         netconfig_wifi_set_scanning(TRUE);
274
275                 return DBUS_HANDLER_RESULT_HANDLED;
276         } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
277                         SIGNAL_BSS_ADDED)) {
278                 if (netconfig_wifi_get_ssid_scan_state() == TRUE)
279                         netconfig_wifi_bss_added(msg);
280
281                 return DBUS_HANDLER_RESULT_HANDLED;
282         } else if (dbus_message_is_signal(msg, SUPPLICANT_INTERFACE ".Interface",
283                         SIGNAL_SCAN_DONE)) {
284                 netconfig_wifi_set_scanning(FALSE);
285
286                 if (netconfig_wifi_get_bgscan_state() != TRUE) {
287                         if (netconfig_wifi_get_ssid_scan_state() == TRUE)
288                                 netconfig_wifi_notify_ssid_scan_done();
289                         else
290                                 netconfig_wifi_ssid_scan(NULL);
291                 }
292
293                 return DBUS_HANDLER_RESULT_HANDLED;
294         }
295
296         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
297 }
298
299 void netconfig_register_signal(void)
300 {
301         DBusConnection *conn = NULL;
302         DBusError err;
303
304         DBG("Register DBus signal filters");
305
306         dbus_error_init(&err);
307         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
308         if (conn == NULL) {
309                 ERR("Error! Failed to connect to the D-BUS daemon: [%s]",
310                                 err.message);
311                 dbus_error_free(&err);
312                 return;
313         }
314
315         signal_connection = conn;
316
317         dbus_connection_setup_with_g_main(conn, NULL);
318
319         /* listening to messages from all objects as no path is specified */
320         /* see signals from the given interface */
321         dbus_bus_add_match(conn, CONNMAN_MANAGER_SIGNAL_FILTER, &err);
322         dbus_connection_flush(conn);
323         if (dbus_error_is_set(&err)) {
324                 ERR("Error! Match Error (%s)", err.message);
325                 dbus_error_free(&err);
326                 return;
327         }
328
329         dbus_bus_add_match(conn, CONNMAN_TECHNOLOGY_SIGNAL_FILTER, &err);
330         dbus_connection_flush(conn);
331         if (dbus_error_is_set(&err)) {
332                 ERR("Error! Match Error (%s)", err.message);
333                 dbus_error_free(&err);
334                 return;
335         }
336
337         dbus_bus_add_match(conn, CONNMAN_SERVICE_SIGNAL_FILTER, &err);
338         dbus_connection_flush(conn);
339         if (dbus_error_is_set(&err)) {
340                 ERR("Error! Match Error (%s)", err.message);
341                 dbus_error_free(&err);
342                 return;
343         }
344
345         dbus_bus_add_match(conn, SUPPLICANT_INTERFACE_SIGNAL_FILTER, &err);
346         dbus_connection_flush(conn);
347         if (dbus_error_is_set(&err)) {
348                 ERR("Error! Match Error (%s)", err.message);
349                 dbus_error_free(&err);
350                 return;
351         }
352
353         if (dbus_connection_add_filter(conn,
354                         __netconfig_signal_filter_handler, NULL, NULL) == FALSE) {
355                 ERR("Error! dbus_connection_add_filter() failed");
356                 return;
357         }
358
359         INFO("Successfully register signal filters");
360 }
361
362 void netconfig_deregister_signal(void)
363 {
364         if (signal_connection == NULL) {
365                 ERR("Error! Already de-registered. Nothing to be done");
366                 return;
367         }
368
369         dbus_connection_remove_filter(signal_connection,
370                                 __netconfig_signal_filter_handler, NULL);
371         INFO("Successfully remove DBus signal filters");
372
373         dbus_connection_unref(signal_connection);
374         signal_connection = NULL;
375
376         netconfig_wifi_deinit_bgscan();
377 }