+++ /dev/null
-/**
- @file networks.c
-
- Copyright (C) 2009 Javier S. Pedro
-
- @author Javier S. Pedro <javispedro@javispedro.com>
-
- This file is part of libicd-network-wpa.
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2 of the License, or (at your
- option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-*/
-
-#include <libgen.h>
-#include <string.h>
-
-#include <glib.h>
-#include <gconf/gconf-client.h>
-
-#include <icd/osso-ic-gconf.h>
-#include <icd/osso-ic-dbus.h>
-
-#include "common.h"
-#include "log.h"
-#include "wlan.h"
-#include "networks.h"
-#include "gconf.h"
-
-#define FAILED_SCAN_RETRY_WAIT 3 * 1000
-#define FAILED_SCAN_RETRY_TRIES 10
-
-#define GCONF_NETWORK_TYPE "/type"
-
-static GSList *net_list = NULL;
-
-int networks_initialize()
-{
- DLOG_DEBUG(__func__);
- GConfClient *client = gconf_client_get_default();
- GError *error = NULL;
-
- net_list = NULL;
-
- if (!client) {
- DLOG_ERR("Cannot get gconf client");
- return -1;
- }
-
- net_list = gconf_client_all_dirs(client, ICD_GCONF_PATH, &error);
- if (error) {
- DLOG_ERR("Could not get setting:%s, error:%s", ICD_GCONF_PATH,
- error->message);
- g_clear_error(&error);
- g_object_unref(client);
- return -1;
- }
-
- // Now, filter networks
- GSList *prev = NULL;
- GSList *cur = net_list;
- while (cur) {
- gchar* path = g_strconcat(cur->data, WPA_GCONF_NETWORK_TYPE, NULL);
- gchar* type = gconf_client_get_string(client, path, &error);
-
- g_free(path);
-
- if (error) {
- DLOG_ERR("Could not get setting:%s, error:%s", path,
- error->message);
- g_clear_error(&error);
-
- goto initialize_error;
- } else if (!type) {
- DLOG_ERR("Could not get setting:%s", path);
-
- goto initialize_error;
- }
-
- if (strcmp(type, WPA_GCONF_NETWORK_TYPE_VALUE) != 0) {
- // Remove this network from the list
- DLOG_DEBUG("Ignoring %s from IAP (type is %s)",
- (gchar*)cur->data, type);
- g_free(cur->data);
- if (prev) {
- GSList *del = cur;
- cur = g_slist_next(cur);
- g_slist_free1(del);
- prev->next = cur;
- } else {
- net_list = g_slist_next(cur);
- g_slist_free1(cur);
- cur = net_list;
- }
- } else {
- DLOG_DEBUG("Added network %s from IAP", (gchar*)cur->data);
-
- prev = cur;
- cur = g_slist_next(cur);
- }
-
- g_free(type);
- }
-
- return 0;
-
-initialize_error:
- g_object_unref(client);
- networks_free();
-
- return -1;
-}
-
-static void free_list_item(gpointer data, gpointer user_data)
-{
- g_free(data);
-}
-
-void networks_free()
-{
- DLOG_DEBUG(__func__);
- if (!net_list) return;
-
- g_slist_foreach(net_list, free_list_item, NULL);
-
- g_slist_free(net_list);
- net_list = NULL;
-}
-
-
-/* Scanning networks */
-
-static GSList *scan_cur_net = NULL;
-static gchar *scan_cur_ssid = NULL;
-static int scan_tries = 0;
-static guint scan_retry_timer = 0;
-static networks_search_found scan_found_cb = NULL;
-static gpointer scan_found_cb_data = NULL;
-
-static void networks_search_iteration();
-
-static void networks_search_finished()
-{
- DLOG_DEBUG(__func__);
-
- scan_found_cb(SEARCH_FINISHED, NULL,
- NULL, NULL, 0, scan_found_cb_data);
- scan_cur_net = NULL;
-
- scan_found_cb = NULL;
- scan_found_cb_data = NULL;
- // Usually a new network_search will not happen on the FINISED cb,
- // but if you do, you'll have to take care of the pseudorace here.
-
- networks_search_stop();
-}
-
-static void networks_search_scan_ap_found(int status,
- const char * ssid, const char * ap, int dB)
-{
- DLOG_DEBUG(__func__);
-
- if (!scan_cur_net) return;
- if (scan_retry_timer) return; // Interface was already scanning
-
- if (status == SEARCH_FINISHED) {
- DLOG_DEBUG("Searching for %s done, iterating", scan_cur_ssid);
- // Go to next network
- scan_cur_net = g_slist_next(scan_cur_net);
- if (scan_cur_net) {
- g_free(scan_cur_ssid);
- scan_cur_ssid = NULL;
- scan_tries = 0;
- networks_search_iteration();
- } else {
- // No more networks to search
- networks_search_finished();
- }
- } else if (status == SEARCH_CONTINUE) {
- DLOG_DEBUG("Found ssid %s", ssid);
- if (strcmp(ssid, scan_cur_ssid) == 0)
- {
- // This is our man
- gchar *full_name = g_strdup(scan_cur_net->data);
-
- gchar *base_name = g_strdup(basename(full_name));
-
- DLOG_INFO("%s (%s) was found",
- base_name, ssid);
-
- scan_found_cb(SEARCH_CONTINUE, base_name,
- ssid, ap, dB, scan_found_cb_data);
-
- g_free(base_name);
- g_free(full_name);
- }
- }
-}
-
-static gboolean networks_search_retry(gpointer data)
-{
- DLOG_DEBUG(__func__);
-
- scan_retry_timer = 0;
- if (scan_cur_net) networks_search_iteration();
- // Always disable this timeout,
- // _search_iteration() will put a newer one if needed
- return FALSE;
-}
-
-static void networks_search_iteration()
-{
- DLOG_DEBUG(__func__);
-
- GConfClient *client = gconf_client_get_default();
- GError *error = NULL;
-
- if (!client) {
- DLOG_ERR("Cannot get gconf client");
- goto get_gconf_error;
- }
-
- DLOG_DEBUG("Test if %s is active", (gchar*)scan_cur_net->data);
-
- gchar *path = g_strconcat(scan_cur_net->data, WPA_GCONF_SSID, NULL);
- scan_cur_ssid = gconf_client_get_string(client, path, &error);
-
- g_object_unref(client);
-
- if (error) {
- DLOG_ERR("Could not get setting:%s, error:%s", path,
- error->message);
- g_clear_error(&error);
-
- goto get_ssid_error;
- }
- else if (!scan_cur_ssid) {
- DLOG_ERR("Could not get setting:%s", path);
-
- goto get_ssid_error;
- }
-
- scan_retry_timer = 0;
-
- int result = wlan_scan(scan_cur_ssid, networks_search_scan_ap_found);
-
- if (result != 0) {
- // Something went wront scanning this network, set timeout and
- // try again
- scan_tries++;
- if (scan_tries >= FAILED_SCAN_RETRY_TRIES) {
- // Give up
- goto scan_error;
- } else {
- scan_retry_timer = g_timeout_add(FAILED_SCAN_RETRY_WAIT,
- networks_search_retry,
- NULL);
- }
- }
-
- return;
-get_ssid_error:
- g_free(path);
-
-get_gconf_error:
-scan_error:
- networks_search_finished();
-}
-
-void networks_search_start(networks_search_found found_cb, gpointer user_data)
-{
- DLOG_DEBUG(__func__);
-
- if (scan_cur_net)
- return; // Already active
-
- scan_cur_net = net_list;
- scan_tries = 0;
- scan_found_cb = found_cb;
- scan_found_cb_data = user_data;
-
- if (scan_cur_net)
- networks_search_iteration();
- else // No networks to scan?
- networks_search_finished();
-}
-
-void networks_search_stop()
-{
- DLOG_DEBUG(__func__);
-
- if (scan_found_cb)
- scan_found_cb(SEARCH_STOPPED,
- NULL, NULL, NULL, 0, scan_found_cb_data);
- scan_cur_net = NULL;
-
- scan_found_cb = NULL;
- scan_found_cb_data = NULL;
-
- g_free(scan_cur_ssid);
- scan_cur_ssid = NULL;
-
- DLOG_DEBUG("Search stopped");
-}
-
-/* Connecting to networks */
-
-static networks_connect_result connect_result_cb = NULL;
-static gpointer connect_result_cb_data = NULL;
-
-static void networks_connected(int status, const char *error)
-{
- DLOG_DEBUG("%s: %d", __func__, status);
-
- if (!connect_result_cb) return;
-
- if (status) {
- connect_result_cb(status, ICD_DBUS_ERROR_NETWORK_ERROR,
- connect_result_cb_data);
- } else {
- connect_result_cb(0, NULL,
- connect_result_cb_data);
- }
-
- connect_result_cb = NULL;
-}
-
-void networks_connect(const char * id,
- networks_connect_result result_cb, gpointer user_data)
-{
- DLOG_DEBUG("%s: %s", __func__, id);
- GConfClient *client = gconf_client_get_default();
-
- connect_result_cb = result_cb;
- connect_result_cb_data = user_data;
-
- gchar *net = g_strconcat(ICD_GCONF_PATH, "/", id, NULL);
- gchar *path, *value;
-
- // Get ICD network type
- path = g_strconcat(net, WPA_GCONF_NETWORK_TYPE, NULL);
- value = gconf_get_string(client, path);
-
- if (!value || strcmp(value, WPA_GCONF_NETWORK_TYPE_VALUE) != 0) {
- result_cb(-1, ICD_DBUS_ERROR_INVALID_IAP, user_data);
- goto connect_error;
- }
-
- g_free(value);
-
- path = g_strconcat(net, WPA_GCONF_SSID, NULL);
- value = gconf_get_string(client, path);
-
- if (!value) {
- result_cb(-1, ICD_DBUS_ERROR_INVALID_IAP, user_data);
- goto connect_error;
- }
-
- wlan_connect(value, networks_connected);
-
-connect_error:
- if (value) g_free(value);
-}
-
-void networks_disconnect(const char * id)
-{
- wlan_disconnect();
-}
-
-/* -- STATUS -- */
-
-static networks_status_result status_result_cb = NULL;
-static gpointer status_result_cb_data = NULL;
-
-static void networks_status_reply(int status,
- const char * essid, int essid_len,
- const char * bssid, int bssid_len,
- int qual, int channel, unsigned long security, unsigned long capability,
- const char * data)
-{
- if (!status_result_cb) return;
-
- if (status == 0) {
- status_result_cb(status, essid, qual, status_result_cb_data);
- } else {
- status_result_cb(status, data, 0, status_result_cb_data);
- }
-}
-
-void networks_status(networks_status_result result_cb, gpointer user_data)
-{
- status_result_cb = result_cb;
- status_result_cb_data = user_data;
-
- wlan_get_status(networks_status_reply);
-}
-