diff --git a/ChangeLog b/ChangeLog index 6f5c9283f..96137ae04 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2007-10-08 Dan Williams + + Fix problems with interrupted activation. Previously, choosing an AP + from the menu, then choosing another one before the first connection was + successful wouldn't deactivate the device before starting the new connection + on that same device. + + * src/NetworkManagerPolicy.c + - (deactivate_old_device, device_state_changed, state_changed, + nm_policy_new): wrong place to deactivate old devices + + * src/nm-manager.c + - (pending_connection_info_destroy, finalize, + wait_for_connection_expired): decouple destruction of the pending + connection info from the manager device + - (connection_added_default_handler): deactivate any active or + activating device before starting a new activation + - (impl_manager_activate_device): deactivate any active or activating + device before starting a new activation; be sure not to leak + pending connection info if a new activation request arrives but + there's already a pending one in-process + 2007-10-08 Dan Williams * src/NetworkManagerAP.h diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index 821e36a79..c368934df 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -387,41 +387,12 @@ schedule_change_check (NMPolicy *policy) device_change_check_done); } -/* FIXME: remove when multiple active device support has landed */ -static void -deactivate_old_device (NMPolicy *policy, NMDevice *new_device) -{ - GSList *iter; - - for (iter = nm_manager_get_devices (policy->manager); iter; iter = iter->next) { - NMDevice *dev = NM_DEVICE (iter->data); - - if (dev == new_device) - continue; - - switch (nm_device_get_state (dev)) { - case NM_DEVICE_STATE_PREPARE: - case NM_DEVICE_STATE_CONFIG: - case NM_DEVICE_STATE_NEED_AUTH: - case NM_DEVICE_STATE_IP_CONFIG: - case NM_DEVICE_STATE_ACTIVATED: - nm_device_interface_deactivate (NM_DEVICE_INTERFACE (dev)); - break; - default: - break; - } - } -} - static void device_state_changed (NMDevice *device, NMDeviceState state, gpointer user_data) { NMPolicy *policy = (NMPolicy *) user_data; - if (state == NM_DEVICE_STATE_PREPARE) - deactivate_old_device (policy, device); /* FIXME: remove when multiple active device support has landed */ - - else if (state == NM_DEVICE_STATE_FAILED || state == NM_DEVICE_STATE_CANCELLED) + if (state == NM_DEVICE_STATE_FAILED || state == NM_DEVICE_STATE_CANCELLED) schedule_change_check (policy); } @@ -474,23 +445,6 @@ device_removed (NMManager *manager, NMDevice *device, gpointer user_data) schedule_change_check (policy); } -static void -state_changed (NMManager *manager, NMState state, gpointer user_data) -{ - NMPolicy *policy = (NMPolicy *) user_data; - - if (state == NM_STATE_CONNECTING) { - /* A device starts activation, bring all devices down - * Remove this when we support multiple active devices. - */ - - NMDevice *old_dev; - - if ((old_dev = nm_manager_get_active_device (policy->manager))) - nm_device_interface_deactivate (NM_DEVICE_INTERFACE (old_dev)); - } -} - static void connections_added (NMManager *manager, NMConnectionType connection_type, @@ -567,9 +521,6 @@ nm_policy_new (NMManager *manager) g_signal_connect (manager, "device-removed", G_CALLBACK (device_removed), policy); - g_signal_connect (manager, "state-change", - G_CALLBACK (state_changed), policy); - /* Large batch of connections added, manager doesn't want us to * process each one individually. */ diff --git a/src/nm-manager.c b/src/nm-manager.c index e69affc0f..5c050c89c 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -155,11 +155,8 @@ nm_manager_update_state (NMManager *manager) } static void -pending_connection_info_destroy (NMManager *manager) +pending_connection_info_destroy (PendingConnectionInfo *info) { - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - PendingConnectionInfo *info = priv->pending_connection_info; - if (!info) return; @@ -171,7 +168,6 @@ pending_connection_info_destroy (NMManager *manager) g_object_unref (info->device); g_slice_free (PendingConnectionInfo, info); - priv->pending_connection_info = NULL; } static void @@ -180,7 +176,8 @@ finalize (GObject *object) NMManager *manager = NM_MANAGER (object); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - pending_connection_info_destroy (manager); + pending_connection_info_destroy (priv->pending_connection_info); + priv->pending_connection_info = NULL; nm_manager_connections_destroy (manager, NM_CONNECTION_TYPE_USER); g_hash_table_destroy (priv->user_connections); @@ -1103,7 +1100,8 @@ static gboolean wait_for_connection_expired (gpointer data) { NMManager *manager = NM_MANAGER (data); - PendingConnectionInfo *info = NM_MANAGER_GET_PRIVATE (manager)->pending_connection_info; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + PendingConnectionInfo *info = priv->pending_connection_info; GError *err; nm_info ("%s: didn't receive connection details soon enough for activation.", @@ -1114,23 +1112,60 @@ wait_for_connection_expired (gpointer data) g_error_free (err); info->timeout_id = 0; - pending_connection_info_destroy (manager); + pending_connection_info_destroy (priv->pending_connection_info); + priv->pending_connection_info = NULL; return FALSE; } +/* ICK ICK ICK; should go away with multiple device support. There is + * corresponding code in NetworkManagerPolicy.c that handles this for + * automatically activated connections. + */ +static void +deactivate_old_device (NMManager *manager) +{ + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + NMDevice *device = NULL; + GSList *iter; + + switch (priv->state) { + case NM_STATE_CONNECTED: + device = nm_manager_get_active_device (manager); + break; + case NM_STATE_CONNECTING: + for (iter = nm_manager_get_devices (manager); iter; iter = iter->next) { + NMDevice *d = NM_DEVICE (iter->data); + + if (nm_device_is_activating (d)) { + device = d; + break; + } + } + break; + default: + break; + } + + if (device) + nm_device_interface_deactivate (NM_DEVICE_INTERFACE (device)); +} + static void connection_added_default_handler (NMManager *manager, NMConnection *connection, NMConnectionType connection_type) { + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); PendingConnectionInfo *info; const char *path; if (!nm_manager_activation_pending (manager)) return; - info = NM_MANAGER_GET_PRIVATE (manager)->pending_connection_info; + info = priv->pending_connection_info; + priv->pending_connection_info = NULL; + if (connection_type != info->connection_type) return; @@ -1138,6 +1173,9 @@ connection_added_default_handler (NMManager *manager, if (strcmp (info->connection_path, path)) return; + // FIXME: remove old_dev deactivation when multiple device support lands + deactivate_old_device (manager); + if (nm_manager_activate_device (manager, info->device, connection, info->specific_object_path, TRUE)) { dbus_g_method_return (info->context, TRUE); } else { @@ -1148,7 +1186,7 @@ connection_added_default_handler (NMManager *manager, g_error_free (err); } - pending_connection_info_destroy (manager); + pending_connection_info_destroy (info); } static void @@ -1183,6 +1221,9 @@ impl_manager_activate_device (NMManager *manager, connection = nm_manager_get_connection_by_object_path (manager, connection_type, connection_path); if (connection) { + // FIXME: remove old_dev deactivation when multiple device support lands + deactivate_old_device (manager); + if (nm_manager_activate_device (manager, device, connection, specific_object_path, TRUE)) { dbus_g_method_return (context, TRUE); } else { @@ -1191,6 +1232,12 @@ impl_manager_activate_device (NMManager *manager, } } else { PendingConnectionInfo *info; + NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); + + if (priv->pending_connection_info) { + pending_connection_info_destroy (priv->pending_connection_info); + priv->pending_connection_info = NULL; + } /* Don't have the connection quite yet, probably created by * the client on-the-fly. Defer the activation until we have it @@ -1204,6 +1251,7 @@ impl_manager_activate_device (NMManager *manager, info->specific_object_path = g_strdup (specific_object_path); info->timeout_id = g_timeout_add (5000, wait_for_connection_expired, manager); + // FIXME: should probably be per-device, not global to the manager NM_MANAGER_GET_PRIVATE (manager)->pending_connection_info = info; }