From c766867b6540823bf79382c224eff0720d1d6b61 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 14 Sep 2007 19:51:04 +0000 Subject: [PATCH] 2007-09-14 Dan Williams Implement deferred activation support in the device class. * src/nm-device-interface.c src/nm-device-interface.h - (nm_device_interface_activate): take more arguments to support deferred activation; callers must pass one of (connection) OR (service_name, connection_path) - (impl_device_activate): connection validation is punted to the device to be able to handle deferred activation. Yes, this means errors don't get returned from the Activate() dbus call, and yes, that should be fixed somehow later. * src/nm-device.c src/nm-device.h - (clear_act_request): clear additional deferred activation stuff too - (deferred_activation_timeout_cb): new function; clean up when deferred activation times out. - (deferred_activation_start_cb): new function; when the connection finally becomes available, start device activation - (nm_device_activate): attach to the right signals of the activation request if we need to defer activation until the connection is valid * src/NetworkManagerPolicy.c - (nm_policy_device_change_check): update for additional arguments required for nm_device_interface_activate(). Pass NULL for these though because this function already knows exactly which NMConnection to use git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2812 4912f4e0-d625-0410-9fb7-b9a5a253dbdc --- ChangeLog | 30 +++++++ src/NetworkManagerPolicy.c | 6 +- src/nm-device-interface.c | 51 ++++------- src/nm-device-interface.h | 12 ++- src/nm-device.c | 172 +++++++++++++++++++++++++++++++------ 5 files changed, 208 insertions(+), 63 deletions(-) diff --git a/ChangeLog b/ChangeLog index 89ab88779d..af8c28a984 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +2007-09-14 Dan Williams + + Implement deferred activation support in the device class. + + * src/nm-device-interface.c + src/nm-device-interface.h + - (nm_device_interface_activate): take more arguments to support + deferred activation; callers must pass one of (connection) OR + (service_name, connection_path) + - (impl_device_activate): connection validation is punted to the device + to be able to handle deferred activation. Yes, this means errors + don't get returned from the Activate() dbus call, and yes, that + should be fixed somehow later. + + * src/nm-device.c + src/nm-device.h + - (clear_act_request): clear additional deferred activation stuff too + - (deferred_activation_timeout_cb): new function; clean up when + deferred activation times out. + - (deferred_activation_start_cb): new function; when the connection + finally becomes available, start device activation + - (nm_device_activate): attach to the right signals of the activation + request if we need to defer activation until the connection is valid + + * src/NetworkManagerPolicy.c + - (nm_policy_device_change_check): update for additional arguments + required for nm_device_interface_activate(). Pass NULL for these + though because this function already knows exactly which + NMConnection to use + 2007-09-14 Dan Williams Implement deferred activation handling in the NMActRequest class. When a diff --git a/src/NetworkManagerPolicy.c b/src/NetworkManagerPolicy.c index 90eb1af77c..44b73dabcd 100644 --- a/src/NetworkManagerPolicy.c +++ b/src/NetworkManagerPolicy.c @@ -338,7 +338,11 @@ nm_policy_device_change_check (gpointer user_data) if (new_dev) { nm_device_interface_activate (NM_DEVICE_INTERFACE (new_dev), - connection, specific_object, FALSE); + NULL, + NULL, + connection, + specific_object, + FALSE); } } diff --git a/src/nm-device-interface.c b/src/nm-device-interface.c index 213e5c57e4..a850a4eda6 100644 --- a/src/nm-device-interface.c +++ b/src/nm-device-interface.c @@ -177,16 +177,22 @@ nm_device_interface_get_type (void) return device_interface_type; } +/* Pass _either_ connection_path or connection. Passing 'connection' is + * meant for internal use only. + */ void nm_device_interface_activate (NMDeviceInterface *device, - NMConnection *connection, - const char *specific_object, - gboolean user_requested) + const char *service_name, + const char *connection_path, + NMConnection *connection, + const char *specific_object, + gboolean user_requested) { g_return_if_fail (NM_IS_DEVICE_INTERFACE (device)); - g_return_if_fail (connection != NULL); NM_DEVICE_INTERFACE_GET_INTERFACE (device)->activate (device, + service_name, + connection_path, connection, specific_object, user_requested); @@ -199,36 +205,13 @@ impl_device_activate (NMDeviceInterface *device, const char *specific_object, GError **err) { - NMManager *manager; - NMConnection *connection; - gboolean success = FALSE; - - manager = nm_manager_get (); - if (!strcmp (service_name, NM_DBUS_SERVICE_USER_SETTINGS)) { - connection = nm_manager_get_connection_by_object_path (manager, - NM_CONNECTION_TYPE_USER, - connection_path); - } else if (!strcmp (service_name, NM_DBUS_SERVICE_USER_SETTINGS)) { - connection = nm_manager_get_connection_by_object_path (manager, - NM_CONNECTION_TYPE_SYSTEM, - connection_path); - } - - if (connection == NULL) { - g_set_error (err, - NM_DEVICE_INTERFACE_ERROR, - NM_DEVICE_INTERFACE_ERROR_UNKNOWN_CONNECTION, - "%s", - "Connection object or service unknown"); - goto out; - } - - nm_connection_dump (connection); - nm_device_interface_activate (device, connection, specific_object, TRUE); - success = TRUE; - -out: - return success; + nm_device_interface_activate (device, + service_name, + connection_path, + NULL, + specific_object, + TRUE); + return TRUE; } void diff --git a/src/nm-device-interface.h b/src/nm-device-interface.h index 95b914e7fc..f7b568fb3c 100644 --- a/src/nm-device-interface.h +++ b/src/nm-device-interface.h @@ -51,6 +51,8 @@ struct _NMDeviceInterface { /* Methods */ void (*activate) (NMDeviceInterface *device, + const char *service_name, + const char *connection_path, NMConnection *connection, const char *specific_object, gboolean user_requested); @@ -66,10 +68,12 @@ GType nm_device_interface_error_get_type (void); GType nm_device_interface_get_type (void); -void nm_device_interface_activate (NMDeviceInterface *device, - NMConnection *connection, - const char *specific_object, - gboolean user_requested); +void nm_device_interface_activate (NMDeviceInterface *device, + const char *service_name, + const char *connection_path, + NMConnection *connection, + const char *specific_object, + gboolean user_requested); void nm_device_interface_deactivate (NMDeviceInterface *device); diff --git a/src/nm-device.c b/src/nm-device.c index f5f0e1746b..eb1640d999 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -69,6 +69,8 @@ struct _NMDevicePrivate struct in6_addr ip6_address; NMActRequest * act_request; + gulong act_deferred_timeout_id; + gulong act_deferred_start_id; guint act_source_id; gulong secrets_updated_id; @@ -81,9 +83,11 @@ struct _NMDevicePrivate }; static void nm_device_activate (NMDeviceInterface *device, - NMConnection *connection, - const char *specific_object, - gboolean user_requested); + const char *service_name, + const char *connection_path, + NMConnection *connection, + const char *specific_object, + gboolean user_requested); static void nm_device_activate_schedule_stage5_ip_config_commit (NMDevice *self); static void nm_device_deactivate (NMDeviceInterface *device); @@ -121,6 +125,8 @@ nm_device_init (NMDevice * self) self->priv->ip4_address = 0; memset (&self->priv->ip6_address, 0, sizeof (struct in6_addr)); + self->priv->act_deferred_timeout_id = 0; + self->priv->act_deferred_start_id = 0; self->priv->act_source_id = 0; self->priv->system_config_data = NULL; @@ -952,9 +958,23 @@ clear_act_request (NMDevice *self) if (!priv->act_request) return; - g_signal_handler_disconnect (priv->act_request, - priv->secrets_updated_id); - priv->secrets_updated_id = 0; + if (priv->act_deferred_timeout_id) { + g_signal_handler_disconnect (priv->act_request, + priv->act_deferred_timeout_id); + priv->act_deferred_timeout_id = 0; + } + + if (priv->act_deferred_start_id) { + g_signal_handler_disconnect (priv->act_request, + priv->act_deferred_start_id); + priv->act_deferred_start_id = 0; + } + + if (priv->secrets_updated_id) { + g_signal_handler_disconnect (priv->act_request, + priv->secrets_updated_id); + priv->secrets_updated_id = 0; + } g_object_unref (priv->act_request); priv->act_request = NULL; @@ -1096,33 +1116,53 @@ connection_secrets_updated_cb (NMActRequest *req, } static void -nm_device_activate (NMDeviceInterface *device, - NMConnection *connection, - const char *specific_object, - gboolean user_requested) +deferred_activation_timeout_cb (NMActRequest *req, gpointer user_data) { - NMDevice *self = NM_DEVICE (device); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - gulong id; + NMDevice *self = NM_DEVICE (user_data); + + if (nm_device_get_act_request (self) != req) + return; + + nm_info ("%s: didn't receive connection details soon enough for activation.", + nm_device_get_iface (self)); + + clear_act_request (self); + nm_device_state_changed (self, NM_DEVICE_STATE_DISCONNECTED); +} + +static gboolean +device_activation_precheck (NMDevice *self, NMConnection *connection) +{ + NMConnection *current_connection; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); if (!NM_DEVICE_GET_CLASS (self)->check_connection (self, connection)) /* connection is invalid */ - return; + return FALSE; - if (nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED || nm_device_is_activating (self)) { - NMConnection *current_connection; + if (nm_device_get_state (self) != NM_DEVICE_STATE_ACTIVATED) + return TRUE; - current_connection = nm_act_request_get_connection (nm_device_get_act_request (self)); + if (!nm_device_is_activating (self)) + return TRUE; - if (nm_connection_compare (connection, current_connection)) - /* Already activating or activated with the same connection */ - return; + current_connection = nm_act_request_get_connection (nm_device_get_act_request (self)); + if (nm_connection_compare (connection, current_connection)) + /* Already activating or activated with the same connection */ + return FALSE; - nm_device_deactivate (device); - } + return TRUE; +} - nm_info ("Activating device %s", nm_device_get_iface (self)); - priv->act_request = nm_act_request_new (connection, specific_object, user_requested); +static void +device_activation_go (NMDevice *self) +{ + NMDevicePrivate * priv; + gulong id; + + priv = NM_DEVICE_GET_PRIVATE (self); id = g_signal_connect (priv->act_request, "connection-secrets-updated", G_CALLBACK (connection_secrets_updated_cb), @@ -1132,6 +1172,90 @@ nm_device_activate (NMDeviceInterface *device, nm_device_activate_schedule_stage1_device_prepare (self); } +static void +deferred_activation_start_cb (NMActRequest *req, gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + NMDevicePrivate * priv; + NMConnection *connection; + + if (nm_device_get_act_request (self) != req) + return; + + priv = NM_DEVICE_GET_PRIVATE (self); + g_signal_handler_disconnect (priv->act_request, + priv->act_deferred_start_id); + priv->act_deferred_start_id = 0; + + connection = nm_act_request_get_connection (req); + if (device_activation_precheck (self, connection) == FALSE) + return; + + nm_info ("%s: connection details received, will start activation.", + nm_device_get_iface (self)); + + device_activation_go (self); +} + +static void +nm_device_activate (NMDeviceInterface *device, + const char *service_name, + const char *connection_path, + NMConnection *connection, + const char *specific_object, + gboolean user_requested) +{ + NMDevice *self = NM_DEVICE (device); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + /* Only one of: + * - connection + * - service_name AND connection_path + * is valid. + */ + if (!connection) { + g_return_if_fail (service_name != NULL); + g_return_if_fail (connection_path != NULL); + } else if (connection) { + g_return_if_fail (service_name == NULL); + g_return_if_fail (connection_path == NULL); + } + + nm_info ("Activating device %s", nm_device_get_iface (self)); + if (connection) { + if (device_activation_precheck (self, connection) == FALSE) + return; + + priv->act_request = nm_act_request_new (connection, + specific_object, + user_requested); + device_activation_go (self); + } else { + gulong id; + + /* Don't have the connection quite yet, probably created by + * the client on-the-fly. Defer the activation until we have it + */ + priv->act_request = nm_act_request_new_deferred (service_name, + connection_path, + specific_object, + user_requested); + + id = g_signal_connect (priv->act_request, "deferred-activation-timeout", + G_CALLBACK (deferred_activation_timeout_cb), + self); + priv->act_deferred_timeout_id = id; + + id = g_signal_connect (priv->act_request, "deferred-activation-start", + G_CALLBACK (deferred_activation_start_cb), + self); + priv->act_deferred_start_id = id; + + nm_info ("%s: Deferring activation until connection information is " + "received.", nm_device_get_iface (self)); + } +} + /* * nm_device_is_activating *