4 Copyright (C) 2009 Javier S. Pedro
6 @author Javier S. Pedro <javispedro@javispedro.com>
8 This file is part of libicd-network-wpa.
10 This program is free software; you can redistribute it and/or modify it
11 under the terms of the GNU General Public License as published by the
12 Free Software Foundation; either version 2 of the License, or (at your
13 option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License along
21 with this program; if not, write to the Free Software Foundation, Inc.,
22 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #include <gconf/gconf-client.h>
32 #include <icd/osso-ic-gconf.h>
33 #include <icd/osso-ic-dbus.h>
41 #define FAILED_SCAN_RETRY_WAIT 3 * 1000
42 #define FAILED_SCAN_RETRY_TRIES 10
44 #define GCONF_NETWORK_TYPE "/type"
46 static GSList *net_list = NULL;
48 int networks_initialize()
51 GConfClient *client = gconf_client_get_default();
57 DLOG_ERR("Cannot get gconf client");
61 net_list = gconf_client_all_dirs(client, ICD_GCONF_PATH, &error);
63 DLOG_ERR("Could not get setting:%s, error:%s", ICD_GCONF_PATH,
65 g_clear_error(&error);
66 g_object_unref(client);
70 // Now, filter networks
72 GSList *cur = net_list;
74 gchar* path = g_strconcat(cur->data, WPA_GCONF_NETWORK_TYPE, NULL);
75 gchar* type = gconf_client_get_string(client, path, &error);
80 DLOG_ERR("Could not get setting:%s, error:%s", path,
82 g_clear_error(&error);
84 goto initialize_error;
86 DLOG_ERR("Could not get setting:%s", path);
88 goto initialize_error;
91 if (strcmp(type, WPA_GCONF_NETWORK_TYPE_VALUE) != 0) {
92 // Remove this network from the list
93 DLOG_DEBUG("Ignoring %s from IAP (type is %s)",
94 (gchar*)cur->data, type);
98 cur = g_slist_next(cur);
102 net_list = g_slist_next(cur);
107 DLOG_DEBUG("Added network %s from IAP", (gchar*)cur->data);
110 cur = g_slist_next(cur);
119 g_object_unref(client);
125 static void free_list_item(gpointer data, gpointer user_data)
132 DLOG_DEBUG(__func__);
133 if (!net_list) return;
135 g_slist_foreach(net_list, free_list_item, NULL);
137 g_slist_free(net_list);
142 /* Scanning networks */
144 static GSList *scan_cur_net = NULL;
145 static gchar *scan_cur_ssid = NULL;
146 static int scan_tries = 0;
147 static guint scan_retry_timer = 0;
148 static networks_search_found scan_found_cb = NULL;
149 static gpointer scan_found_cb_data = NULL;
151 static void networks_search_iteration();
153 static void networks_search_finished()
155 DLOG_DEBUG(__func__);
157 scan_found_cb(SEARCH_FINISHED, NULL,
158 NULL, NULL, 0, scan_found_cb_data);
161 scan_found_cb = NULL;
162 scan_found_cb_data = NULL;
163 // Usually a new network_search will not happen on the FINISED cb,
164 // but if you do, you'll have to take care of the pseudorace here.
166 networks_search_stop();
169 static void networks_search_scan_ap_found(int status,
170 const char * ssid, const char * ap, int dB)
172 DLOG_DEBUG(__func__);
174 if (!scan_cur_net) return;
175 if (scan_retry_timer) return; // Interface was already scanning
177 if (status == SEARCH_FINISHED) {
178 DLOG_DEBUG("Searching for %s done, iterating", scan_cur_ssid);
179 // Go to next network
180 scan_cur_net = g_slist_next(scan_cur_net);
182 g_free(scan_cur_ssid);
183 scan_cur_ssid = NULL;
185 networks_search_iteration();
187 // No more networks to search
188 networks_search_finished();
190 } else if (status == SEARCH_CONTINUE) {
191 DLOG_DEBUG("Found ssid %s", ssid);
192 if (strcmp(ssid, scan_cur_ssid) == 0)
195 gchar *full_name = g_strdup(scan_cur_net->data);
197 gchar *base_name = g_strdup(basename(full_name));
199 DLOG_INFO("%s (%s) was found",
202 scan_found_cb(SEARCH_CONTINUE, base_name,
203 ssid, ap, dB, scan_found_cb_data);
211 static gboolean networks_search_retry(gpointer data)
213 DLOG_DEBUG(__func__);
215 scan_retry_timer = 0;
216 if (scan_cur_net) networks_search_iteration();
217 // Always disable this timeout,
218 // _search_iteration() will put a newer one if needed
222 static void networks_search_iteration()
224 DLOG_DEBUG(__func__);
226 GConfClient *client = gconf_client_get_default();
227 GError *error = NULL;
230 DLOG_ERR("Cannot get gconf client");
231 goto get_gconf_error;
234 DLOG_DEBUG("Test if %s is active", (gchar*)scan_cur_net->data);
236 gchar *path = g_strconcat(scan_cur_net->data, WPA_GCONF_SSID, NULL);
237 scan_cur_ssid = gconf_client_get_string(client, path, &error);
239 g_object_unref(client);
242 DLOG_ERR("Could not get setting:%s, error:%s", path,
244 g_clear_error(&error);
248 else if (!scan_cur_ssid) {
249 DLOG_ERR("Could not get setting:%s", path);
254 scan_retry_timer = 0;
256 int result = wlan_scan(scan_cur_ssid, networks_search_scan_ap_found);
259 // Something went wront scanning this network, set timeout and
262 if (scan_tries >= FAILED_SCAN_RETRY_TRIES) {
266 scan_retry_timer = g_timeout_add(FAILED_SCAN_RETRY_WAIT,
267 networks_search_retry,
278 networks_search_finished();
281 void networks_search_start(networks_search_found found_cb, gpointer user_data)
283 DLOG_DEBUG(__func__);
286 return; // Already active
288 scan_cur_net = net_list;
290 scan_found_cb = found_cb;
291 scan_found_cb_data = user_data;
294 networks_search_iteration();
295 else // No networks to scan?
296 networks_search_finished();
299 void networks_search_stop()
301 DLOG_DEBUG(__func__);
304 scan_found_cb(SEARCH_STOPPED,
305 NULL, NULL, NULL, 0, scan_found_cb_data);
308 scan_found_cb = NULL;
309 scan_found_cb_data = NULL;
311 g_free(scan_cur_ssid);
312 scan_cur_ssid = NULL;
314 DLOG_DEBUG("Search stopped");
317 /* Connecting to networks */
319 static networks_connect_result connect_result_cb = NULL;
320 static gpointer connect_result_cb_data = NULL;
322 static void networks_connected(int status, const char *error)
324 DLOG_DEBUG("%s: %d", __func__, status);
326 if (!connect_result_cb) return;
329 connect_result_cb(status, ICD_DBUS_ERROR_NETWORK_ERROR,
330 connect_result_cb_data);
332 connect_result_cb(0, NULL,
333 connect_result_cb_data);
336 connect_result_cb = NULL;
339 void networks_connect(const char * id,
340 networks_connect_result result_cb, gpointer user_data)
342 DLOG_DEBUG("%s: %s", __func__, id);
343 GConfClient *client = gconf_client_get_default();
345 connect_result_cb = result_cb;
346 connect_result_cb_data = user_data;
348 gchar *net = g_strconcat(ICD_GCONF_PATH, "/", id, NULL);
351 // Get ICD network type
352 path = g_strconcat(net, WPA_GCONF_NETWORK_TYPE, NULL);
353 value = gconf_get_string(client, path);
355 if (!value || strcmp(value, WPA_GCONF_NETWORK_TYPE_VALUE) != 0) {
356 result_cb(-1, ICD_DBUS_ERROR_INVALID_IAP, user_data);
362 path = g_strconcat(net, WPA_GCONF_SSID, NULL);
363 value = gconf_get_string(client, path);
366 result_cb(-1, ICD_DBUS_ERROR_INVALID_IAP, user_data);
370 wlan_connect(value, networks_connected);
373 if (value) g_free(value);
376 void networks_disconnect(const char * id)
383 static networks_status_result status_result_cb = NULL;
384 static gpointer status_result_cb_data = NULL;
386 static void networks_status_reply(int status,
387 const char * essid, int essid_len,
388 const char * bssid, int bssid_len,
389 int qual, int channel, unsigned long security, unsigned long capability,
392 if (!status_result_cb) return;
395 status_result_cb(status, essid, qual, status_result_cb_data);
397 status_result_cb(status, data, 0, status_result_cb_data);
401 void networks_status(networks_status_result result_cb, gpointer user_data)
403 status_result_cb = result_cb;
404 status_result_cb_data = user_data;
406 wlan_get_status(networks_status_reply);