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.
---
 include/device.h  |    3 ++-
 include/network.h |    3 ++-
 plugins/wifi.c    |   10 ++++++++--
 src/connman.h     |    3 ++-
 src/device.c      |    5 +++--
 src/network.c     |   36 ++++++++++++++++++++++++++++++------
 src/service.c     |   48 ++++++++++++++++++++++++++++++++++++++++++++----
 7 files changed, 91 insertions(+), 17 deletions(-)

diff --git a/include/device.h b/include/device.h
index 1141620..96530fd 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,
+                       gpointer user_data);
 };
 
 int connman_device_driver_register(struct connman_device_driver *driver);
diff --git a/include/network.h b/include/network.h
index 12b0621..c1ce561 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(gpointer user_data);
 int connman_network_connect_hidden(struct connman_network *network,
-                               char *identity, char* passphrase);
+                       char *identity, char* passphrase, gpointer 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 3cd2be2..3f9afad 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 7f87a56..e6e617d 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 e433991..a2deeff 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,
+                               gpointer 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 6fe1d9c..d685c36 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(gpointer 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, gpointer 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 a2c306d..1dde986 100644
--- a/src/service.c
+++ b/src/service.c
@@ -4614,15 +4614,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) {
@@ -4662,6 +4674,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();
        }
@@ -5421,8 +5444,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);
        }
-- 
1.7.9.5

_______________________________________________
connman mailing list
connman@connman.net
http://lists.connman.net/listinfo/connman

Reply via email to