summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJukka Rissanen <jukka.rissanen@linux.intel.com>2012-06-15 16:00:21 +0300
committerPatrik Flykt <patrik.flykt@linux.intel.com>2012-06-18 10:57:08 +0300
commitfc41a18566f0bb753fd8ce35873d1442942f464c (patch)
treef198bceea5eac8f186f15fd13eae23b9c1e13b11
parent3ca789e446848eed6ca3c00af080cd737d115dcb (diff)
downloadconnman-fc41a18566f0bb753fd8ce35873d1442942f464c.tar.gz
connman-fc41a18566f0bb753fd8ce35873d1442942f464c.tar.bz2
connman-fc41a18566f0bb753fd8ce35873d1442942f464c.zip
service: Connecting hidden network waits until connected
If the user is connecting to hidden network, then we delay the return of the reply to caller until the real service has connected. This way the user connect to hidden and non-hidden networks works the same way from caller point of view.
-rw-r--r--include/device.h3
-rw-r--r--include/network.h3
-rw-r--r--plugins/wifi.c10
-rw-r--r--src/connman.h3
-rw-r--r--src/device.c5
-rw-r--r--src/network.c36
-rw-r--r--src/service.c48
7 files changed, 91 insertions, 17 deletions
diff --git a/include/device.h b/include/device.h
index 11416204..f787cf48 100644
--- a/include/device.h
+++ b/include/device.h
@@ -120,7 +120,8 @@ struct connman_device_driver {
int (*scan_fast) (struct connman_device *device);
int (*scan_hidden)(struct connman_device *device,
const char *ssid, unsigned int ssid_len,
- const char *identity, const char* passphrase);
+ const char *identity, const char* passphrase,
+ void *user_data);
};
int connman_device_driver_register(struct connman_device_driver *driver);
diff --git a/include/network.h b/include/network.h
index 12b06210..3945a541 100644
--- a/include/network.h
+++ b/include/network.h
@@ -102,8 +102,9 @@ connman_bool_t connman_network_get_connected(struct connman_network *network);
connman_bool_t connman_network_get_associating(struct connman_network *network);
+void connman_network_clear_hidden(void *user_data);
int connman_network_connect_hidden(struct connman_network *network,
- char *identity, char* passphrase);
+ char *identity, char* passphrase, void *user_data);
void connman_network_set_ipv4_method(struct connman_network *network,
enum connman_ipconfig_method method);
diff --git a/plugins/wifi.c b/plugins/wifi.c
index 3cd2be29..3f9afad9 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -68,6 +68,7 @@ struct hidden_params {
unsigned int ssid_len;
char *identity;
char *passphrase;
+ gpointer user_data;
};
/**
@@ -664,6 +665,7 @@ static void scan_callback(int result, GSupplicantInterface *interface,
DBG("result %d", result);
if (wifi != NULL && wifi->hidden != NULL) {
+ connman_network_clear_hidden(wifi->hidden->user_data);
hidden_free(wifi->hidden);
wifi->hidden = NULL;
}
@@ -865,7 +867,8 @@ static int wifi_scan_fast(struct connman_device *device)
*/
static int wifi_scan_hidden(struct connman_device *device,
const char *ssid, unsigned int ssid_len,
- const char *identity, const char* passphrase)
+ const char *identity, const char* passphrase,
+ gpointer user_data)
{
struct wifi_data *wifi = connman_device_get_data(device);
GSupplicantScanParams *scan_params = NULL;
@@ -911,6 +914,7 @@ static int wifi_scan_hidden(struct connman_device *device,
hidden->ssid_len = ssid_len;
hidden->identity = g_strdup(identity);
hidden->passphrase = g_strdup(passphrase);
+ hidden->user_data = user_data;
wifi->hidden = hidden;
connman_device_ref(device);
@@ -1572,7 +1576,9 @@ static void network_added(GSupplicantNetwork *supplicant_network)
ssid_len) == 0) {
connman_network_connect_hidden(network,
wifi->hidden->identity,
- wifi->hidden->passphrase);
+ wifi->hidden->passphrase,
+ wifi->hidden->user_data);
+ wifi->hidden->user_data = NULL;
hidden_free(wifi->hidden);
wifi->hidden = NULL;
}
diff --git a/src/connman.h b/src/connman.h
index db3934d2..0418a7e7 100644
--- a/src/connman.h
+++ b/src/connman.h
@@ -470,7 +470,8 @@ struct connman_device *__connman_device_find_device(enum connman_service_type ty
int __connman_device_request_scan(enum connman_service_type type);
int __connman_device_request_hidden_scan(struct connman_device *device,
const char *ssid, unsigned int ssid_len,
- const char *identity, const char *passphrase);
+ const char *identity, const char *passphrase,
+ gpointer user_data);
connman_bool_t __connman_device_isfiltered(const char *devname);
diff --git a/src/device.c b/src/device.c
index e4339915..3af36800 100644
--- a/src/device.c
+++ b/src/device.c
@@ -1102,7 +1102,8 @@ int __connman_device_request_scan(enum connman_service_type type)
int __connman_device_request_hidden_scan(struct connman_device *device,
const char *ssid, unsigned int ssid_len,
- const char *identity, const char *passphrase)
+ const char *identity, const char *passphrase,
+ void *user_data)
{
DBG("device %p", device);
@@ -1114,7 +1115,7 @@ int __connman_device_request_hidden_scan(struct connman_device *device,
return -EALREADY;
return device->driver->scan_hidden(device, ssid, ssid_len,
- identity, passphrase);
+ identity, passphrase, user_data);
}
connman_bool_t __connman_device_isfiltered(const char *devname)
diff --git a/src/network.c b/src/network.c
index 6fe1d9c5..bf017676 100644
--- a/src/network.c
+++ b/src/network.c
@@ -1455,17 +1455,36 @@ connman_bool_t connman_network_get_associating(struct connman_network *network)
return network->associating;
}
+void connman_network_clear_hidden(void *user_data)
+{
+ if (user_data == NULL)
+ return;
+
+ DBG("user_data %p", user_data);
+
+ /*
+ * Hidden service does not have a connect timeout so
+ * we do not need to remove it. We can just return
+ * error to the caller telling that we could not find
+ * any network that we could connect to.
+ */
+ __connman_service_reply_dbus_pending(user_data, EIO);
+}
+
int connman_network_connect_hidden(struct connman_network *network,
- char *identity, char* passphrase)
+ char *identity, char* passphrase, void *user_data)
{
int err = 0;
struct connman_service *service;
- DBG("");
-
service = __connman_service_lookup_from_network(network);
- if (service == NULL)
- return -EINVAL;
+
+ DBG("network %p service %p user_data %p", network, service, user_data);
+
+ if (service == NULL) {
+ err = -EINVAL;
+ goto out;
+ }
if (identity != NULL)
__connman_service_set_agent_identity(service, identity);
@@ -1476,12 +1495,17 @@ int connman_network_connect_hidden(struct connman_network *network,
if (err == -ENOKEY) {
__connman_service_indicate_error(service,
CONNMAN_SERVICE_ERROR_INVALID_KEY);
- return err;
+ goto out;
} else {
__connman_service_set_hidden(service);
__connman_service_set_userconnect(service, TRUE);
+ __connman_service_set_hidden_data(service, user_data);
return __connman_service_connect(service);
}
+
+out:
+ __connman_service_return_error(service, -err, user_data);
+ return err;
}
/**
diff --git a/src/service.c b/src/service.c
index a3a0160a..72f5af4c 100644
--- a/src/service.c
+++ b/src/service.c
@@ -4631,15 +4631,27 @@ static void request_input_cb (struct connman_service *service,
if (g_strcmp0(error,
"net.connman.Agent.Error.Canceled") == 0) {
err = -EINVAL;
+
+ if (service->hidden == TRUE)
+ __connman_service_return_error(service,
+ ECANCELED, user_data);
goto done;
+ } else {
+ if (service->hidden == TRUE)
+ __connman_service_return_error(service,
+ ETIMEDOUT, user_data);
}
}
if (service->hidden == TRUE && name_len > 0 && name_len <= 32) {
device = connman_network_get_device(service->network);
- __connman_device_request_hidden_scan(device,
+ err = __connman_device_request_hidden_scan(device,
name, name_len,
- identity, passphrase);
+ identity, passphrase,
+ user_data);
+ if (err < 0)
+ __connman_service_return_error(service, -err,
+ user_data);
}
if (values_received == FALSE || service->hidden == TRUE) {
@@ -4682,6 +4694,17 @@ static void request_input_cb (struct connman_service *service,
* when failing is due to wrong user input */
service->state = CONNMAN_SERVICE_STATE_IDLE;
+ if (service->hidden == FALSE) {
+ /*
+ * If there was a real error when requesting
+ * hidden scan, then that error is returned already
+ * to the user somewhere above so do not try to
+ * do this again.
+ */
+ __connman_service_return_error(service, -err,
+ user_data);
+ }
+
service_complete(service);
__connman_connection_update_gateway();
}
@@ -5443,8 +5466,25 @@ int __connman_service_connect(struct connman_service *service)
if (service->userconnect == TRUE) {
if (err == -ENOKEY || err == -EPERM) {
- return __connman_agent_request_passphrase_input(service,
- request_input_cb, NULL);
+ DBusMessage *pending = NULL;
+
+ /*
+ * We steal the reply here. The idea is that the
+ * connecting client will see the connection status
+ * after the real hidden network is connected or
+ * connection failed.
+ */
+ if (service->hidden == TRUE) {
+ pending = service->pending;
+ service->pending = NULL;
+ }
+
+ err = __connman_agent_request_passphrase_input(service,
+ request_input_cb, pending);
+ if (service->hidden == TRUE && err != -EINPROGRESS)
+ service->pending = pending;
+
+ return err;
}
reply_pending(service, -err);
}