summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
}