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);
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);
unsigned int ssid_len;
char *identity;
char *passphrase;
+ gpointer user_data;
};
/**
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;
}
*/
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;
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);
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;
}
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);
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);
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)
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);
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;
}
/**
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) {
* 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();
}
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);
}