diff options
-rw-r--r-- | include/device.h | 3 | ||||
-rw-r--r-- | include/network.h | 3 | ||||
-rw-r--r-- | plugins/wifi.c | 10 | ||||
-rw-r--r-- | src/connman.h | 3 | ||||
-rw-r--r-- | src/device.c | 5 | ||||
-rw-r--r-- | src/network.c | 36 | ||||
-rw-r--r-- | src/service.c | 48 |
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); } |