wifi/iwd: merge branch 'az/more-iwd-fixes-pr62'

https://github.com/NetworkManager/NetworkManager/pull/62
This commit is contained in:
Thomas Haller
2018-02-09 21:34:48 +01:00
2 changed files with 141 additions and 40 deletions

View File

@@ -75,10 +75,12 @@ typedef struct {
GCancellable * cancellable;
NMDeviceWifiCapabilities capabilities;
NMActRequestGetSecretsCallId *wifi_secrets_id;
guint periodic_scan_id;
bool enabled:1;
bool can_scan:1;
bool can_connect:1;
bool scanning:1;
bool scan_requested:1;
} NMDeviceIwdPrivate;
struct _NMDeviceIwd {
@@ -101,6 +103,9 @@ G_DEFINE_TYPE (NMDeviceIwd, nm_device_iwd, NM_TYPE_DEVICE)
/*****************************************************************************/
static void schedule_periodic_scan (NMDeviceIwd *self,
NMDeviceState current_state);
static void
_ap_dump (NMDeviceIwd *self,
NMLogLevel log_level,
@@ -863,6 +868,33 @@ check_scanning_prohibited (NMDeviceIwd *self, gboolean periodic)
return prohibited;
}
static void
scan_cb (GObject *source, GAsyncResult *res, gpointer user_data)
{
NMDeviceIwd *self = user_data;
NMDeviceIwdPrivate *priv;
gs_free_error GError *error = NULL;
if ( !_nm_dbus_proxy_call_finish (G_DBUS_PROXY (source), res,
G_VARIANT_TYPE ("()"), &error)
&& g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
priv = NM_DEVICE_IWD_GET_PRIVATE (self);
priv->scan_requested = FALSE;
/* On success, priv->scanning becomes true right before or right
* after this callback, so the next automatic scan will be
* scheduled when priv->scanning goes back to false. On error,
* schedule a retry now.
*/
if (error && !priv->scanning) {
NMDeviceState state = nm_device_get_state (NM_DEVICE (self));
schedule_periodic_scan (self, state);
}
}
static void
dbus_request_scan_cb (NMDevice *device,
GDBusMethodInvocation *context,
@@ -912,8 +944,14 @@ dbus_request_scan_cb (NMDevice *device,
}
}
g_dbus_proxy_call (priv->dbus_proxy, "Scan", g_variant_new ("()"),
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
if (!priv->scanning && !priv->scan_requested) {
g_dbus_proxy_call (priv->dbus_proxy, "Scan",
g_variant_new ("()"),
G_DBUS_CALL_FLAGS_NONE, -1,
priv->cancellable, scan_cb, self);
priv->scan_requested = TRUE;
}
g_dbus_method_invocation_return_value (context, NULL);
}
@@ -1461,6 +1499,45 @@ get_configured_mtu (NMDevice *device, gboolean *out_is_user_config)
return mtu;
}
static gboolean
periodic_scan_timeout_cb (gpointer user_data)
{
NMDeviceIwd *self = user_data;
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
priv->periodic_scan_id = 0;
if (priv->scanning || priv->scan_requested)
return FALSE;
g_dbus_proxy_call (priv->dbus_proxy, "Scan", g_variant_new ("()"),
G_DBUS_CALL_FLAGS_NONE, -1,
priv->cancellable, scan_cb, self);
priv->scan_requested = TRUE;
return FALSE;
}
static void
schedule_periodic_scan (NMDeviceIwd *self, NMDeviceState current_state)
{
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
guint interval;
if (current_state <= NM_DEVICE_STATE_UNAVAILABLE)
return;
if (current_state == NM_DEVICE_STATE_DISCONNECTED)
interval = 10;
else
interval = 20;
nm_clear_g_source (&priv->periodic_scan_id);
priv->periodic_scan_id = g_timeout_add_seconds (interval,
periodic_scan_timeout_cb,
self);
}
static void
device_state_changed (NMDevice *device,
NMDeviceState new_state,
@@ -1470,10 +1547,13 @@ device_state_changed (NMDevice *device,
NMDeviceIwd *self = NM_DEVICE_IWD (device);
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
if (new_state <= NM_DEVICE_STATE_UNAVAILABLE)
if (new_state <= NM_DEVICE_STATE_UNAVAILABLE) {
remove_all_aps (self);
else if (old_state <= NM_DEVICE_STATE_UNAVAILABLE)
nm_clear_g_source (&priv->periodic_scan_id);
} else if (old_state <= NM_DEVICE_STATE_UNAVAILABLE) {
update_aps (self);
schedule_periodic_scan (self, new_state);
}
switch (new_state) {
case NM_DEVICE_STATE_UNMANAGED:
@@ -1710,6 +1790,7 @@ static void
scanning_changed (NMDeviceIwd *self, gboolean new_scanning)
{
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
NMDeviceState state = nm_device_get_state (NM_DEVICE (self));
if (new_scanning == priv->scanning)
return;
@@ -1718,8 +1799,12 @@ scanning_changed (NMDeviceIwd *self, gboolean new_scanning)
_notify (self, PROP_SCANNING);
if (!priv->scanning)
if (!priv->scanning) {
update_aps (self);
if (!priv->scan_requested)
schedule_periodic_scan (self, state);
}
}
static void
@@ -1750,7 +1835,7 @@ nm_device_iwd_set_dbus_object (NMDeviceIwd *self, GDBusObject *object)
{
NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
GDBusInterface *interface;
gs_unref_variant GVariant *value = NULL;
GVariant *value;
if (!nm_g_object_ref_set ((GObject **) &priv->dbus_obj, (GObject *) object))
return;
@@ -1779,6 +1864,12 @@ nm_device_iwd_set_dbus_object (NMDeviceIwd *self, GDBusObject *object)
value = g_dbus_proxy_get_cached_property (priv->dbus_proxy, "Scanning");
priv->scanning = g_variant_get_boolean (value);
g_variant_unref (value);
priv->scan_requested = FALSE;
value = g_dbus_proxy_get_cached_property (priv->dbus_proxy, "State");
state_changed (self, g_variant_get_string (value, NULL));
g_variant_unref (value);
g_signal_connect (priv->dbus_proxy, "g-properties-changed",
G_CALLBACK (properties_changed), self);
@@ -1861,6 +1952,8 @@ dispose (GObject *object)
nm_clear_g_cancellable (&priv->cancellable);
nm_clear_g_source (&priv->periodic_scan_id);
wifi_secrets_cancel (self);
cleanup_association_attempt (self, TRUE);

View File

@@ -39,6 +39,7 @@ typedef struct {
} KnownNetworkData;
typedef struct {
NMManager *nm_manager;
GCancellable *cancellable;
gboolean running;
GDBusObjectManager *object_manager;
@@ -97,7 +98,6 @@ psk_agent_dbus_method_cb (GDBusConnection *connection,
gs_unref_object GDBusInterface *network = NULL, *device_obj = NULL;
gs_unref_variant GVariant *value = NULL;
gint ifindex;
NMManager *manager;
NMDevice *device;
const gchar *psk;
@@ -139,9 +139,7 @@ psk_agent_dbus_method_cb (GDBusConnection *connection,
goto return_error;
}
manager = nm_manager_get ();
device = nm_manager_get_device_by_ifindex (manager, ifindex);
device = nm_manager_get_device_by_ifindex (priv->nm_manager, ifindex);
if (!NM_IS_DEVICE_IWD (device)) {
_LOGE ("IWD device named %s is not a Wifi device in IWD Agent request",
ifname);
@@ -271,7 +269,6 @@ set_device_dbus_object (NMIwdManager *self, GDBusInterface *interface,
const char *ifname;
gint ifindex;
NMDevice *device;
NMManager *manager;
if (!priv->running)
return;
@@ -301,9 +298,7 @@ set_device_dbus_object (NMIwdManager *self, GDBusInterface *interface,
return;
}
manager = nm_manager_get ();
device = nm_manager_get_device_by_ifindex (manager, ifindex);
device = nm_manager_get_device_by_ifindex (priv->nm_manager, ifindex);
if (!NM_IS_DEVICE_IWD (device)) {
_LOGE ("IWD device named %s is not a Wifi device", ifname);
return;
@@ -456,6 +451,8 @@ update_known_networks (NMIwdManager *self)
g_object_unref (known_networks_if);
}
static void prepare_object_manager (NMIwdManager *self);
static void
name_owner_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
{
@@ -466,27 +463,18 @@ name_owner_changed (GObject *object, GParamSpec *pspec, gpointer user_data)
nm_assert (object_manager == priv->object_manager);
if (_om_has_name_owner (object_manager)) {
GList *objects, *iter;
priv->running = true;
objects = g_dbus_object_manager_get_objects (object_manager);
for (iter = objects; iter; iter = iter->next)
object_added (self, G_DBUS_OBJECT (iter->data));
g_list_free_full (objects, g_object_unref);
if (priv->agent_id)
register_agent (self);
update_known_networks (self);
g_signal_handlers_disconnect_by_data (object_manager, self);
g_clear_object (&priv->object_manager);
prepare_object_manager (self);
} else {
NMManager *manager = nm_manager_get ();
const GSList *devices, *iter;
if (!priv->running)
return;
priv->running = false;
devices = nm_manager_get_devices (manager);
devices = nm_manager_get_devices (priv->nm_manager);
for (iter = devices; iter; iter = iter->next) {
NMDevice *device = NM_DEVICE (iter->data);
@@ -554,9 +542,6 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data)
GError *error = NULL;
GDBusObjectManager *object_manager;
GDBusConnection *connection;
NMManager *manager = nm_manager_get ();
g_clear_object (&priv->cancellable);
object_manager = g_dbus_object_manager_client_new_for_bus_finish (result, &error);
if (object_manager == NULL) {
@@ -568,10 +553,6 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data)
priv->object_manager = object_manager;
g_signal_connect (priv->object_manager, "interface-added",
G_CALLBACK (interface_added), self);
g_signal_connect (priv->object_manager, "interface-removed",
G_CALLBACK (interface_removed), self);
g_signal_connect (priv->object_manager, "notify::name-owner",
G_CALLBACK (name_owner_changed), self);
@@ -587,10 +568,27 @@ got_object_manager (GObject *object, GAsyncResult *result, gpointer user_data)
g_clear_error (&error);
}
name_owner_changed (G_OBJECT (object_manager), NULL, self);
if (_om_has_name_owner (object_manager)) {
GList *objects, *iter;
g_signal_connect (manager, "device-added",
G_CALLBACK (device_added), self);
priv->running = true;
g_signal_connect (priv->object_manager, "interface-added",
G_CALLBACK (interface_added), self);
g_signal_connect (priv->object_manager, "interface-removed",
G_CALLBACK (interface_removed), self);
objects = g_dbus_object_manager_get_objects (object_manager);
for (iter = objects; iter; iter = iter->next)
object_added (self, G_DBUS_OBJECT (iter->data));
g_list_free_full (objects, g_object_unref);
if (priv->agent_id)
register_agent (self);
update_known_networks (self);
}
}
static void
@@ -649,7 +647,12 @@ nm_iwd_manager_init (NMIwdManager *self)
{
NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
priv->nm_manager = g_object_ref (nm_manager_get ());
g_signal_connect (priv->nm_manager, "device-added",
G_CALLBACK (device_added), self);
priv->cancellable = g_cancellable_new ();
prepare_object_manager (self);
}
@@ -684,6 +687,11 @@ dispose (GObject *object)
g_slist_free_full (priv->known_networks, (GDestroyNotify) known_network_free);
priv->known_networks = NULL;
if (priv->nm_manager) {
g_signal_handlers_disconnect_by_data (priv->nm_manager, self);
g_clear_object (&priv->nm_manager);
}
G_OBJECT_CLASS (nm_iwd_manager_parent_class)->dispose (object);
}