2007-09-14 Dan Williams <dcbw@redhat.com>

Implement deferred activation handling in the NMActRequest class.  When a
	client wants to activate a device but must create the NMConnection details
	on the fly, there likely hasn't been enough time yet for NM to receive the
	new connection signal and grab all the connection details.  So the
	activation is deferred (and bounded by a timer) for a while, and if the
	connection appears within the window, it is activated.

	* src/nm-activation-request.c
	  src/nm-activation-request.h
		- (nm_act_request_class_init): two new signals to support deferred
			activation, to allow the listener to handle both timeout and success
		- (nm_act_request_new_deferred): new function, starts the deferred
			activation timeout handler and listens to the NMManager for
			new-connection signals to notice when the connection comes in



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@2811 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams
2007-09-14 19:43:28 +00:00
parent 13f21985d4
commit 92ee635c59
3 changed files with 199 additions and 12 deletions

View File

@@ -22,6 +22,8 @@
#include "nm-activation-request.h"
#include "nm-marshal.h"
#include "nm-manager.h"
#include "nm-utils.h"
G_DEFINE_TYPE (NMActRequest, nm_act_request, G_TYPE_OBJECT)
@@ -29,6 +31,8 @@ G_DEFINE_TYPE (NMActRequest, nm_act_request, G_TYPE_OBJECT)
enum {
CONNECTION_SECRETS_UPDATED,
DEFERRED_ACTIVATION_TIMEOUT,
DEFERRED_ACTIVATION_START,
LAST_SIGNAL
};
@@ -41,6 +45,11 @@ static void connection_secrets_updated_cb (NMConnection *connection,
NMActRequest *self);
typedef struct {
char *deferred_service_name;
char *deferred_connection_path;
gulong deferred_connection_id;
guint32 deferred_timeout_id;
NMConnection *connection;
char *specific_object;
gboolean user_requested;
@@ -53,15 +62,53 @@ nm_act_request_init (NMActRequest *req)
{
}
static void
clear_deferred_stuff (NMActRequest *req)
{
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (req);
g_free (priv->deferred_service_name);
priv->deferred_service_name = NULL;
g_free (priv->deferred_connection_path);
priv->deferred_connection_path = NULL;
if (priv->deferred_connection_id) {
NMManager *manager = nm_manager_get ();
g_signal_handler_disconnect (manager, priv->deferred_connection_id);
g_object_unref (manager);
priv->deferred_connection_id = 0;
}
if (priv->deferred_timeout_id) {
g_source_remove (priv->deferred_timeout_id);
priv->deferred_timeout_id = 0;
}
}
static void
dispose (GObject *object)
{
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
clear_deferred_stuff (NM_ACT_REQUEST (object));
if (priv->secrets_updated_id) {
g_signal_handler_disconnect (priv->connection,
priv->secrets_updated_id);
priv->secrets_updated_id = 0;
}
if (priv->connection)
g_object_unref (priv->connection);
}
static void
finalize (GObject *object)
{
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
g_signal_handler_disconnect (priv->connection,
priv->secrets_updated_id);
g_object_unref (priv->connection);
g_free (priv->deferred_service_name);
g_free (priv->deferred_connection_path);
g_free (priv->specific_object);
G_OBJECT_CLASS (nm_act_request_parent_class)->finalize (object);
@@ -74,6 +121,7 @@ nm_act_request_class_init (NMActRequestClass *req_class)
g_type_class_add_private (req_class, sizeof (NMActRequestPrivate));
object_class->dispose = dispose;
object_class->finalize = finalize;
/* Signals */
@@ -81,11 +129,31 @@ nm_act_request_class_init (NMActRequestClass *req_class)
g_signal_new ("connection-secrets-updated",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMConnectionClass, secrets_updated),
G_STRUCT_OFFSET (NMActRequestClass, connection_secrets_updated),
NULL, NULL,
nm_marshal_VOID__OBJECT_STRING,
G_TYPE_NONE, 2,
G_TYPE_OBJECT, G_TYPE_STRING);
signals[DEFERRED_ACTIVATION_TIMEOUT] =
g_signal_new ("deferred-activation-timeout",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMActRequestClass, deferred_activation_timeout),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0,
G_TYPE_NONE);
signals[DEFERRED_ACTIVATION_START] =
g_signal_new ("deferred-activation-start",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMActRequestClass, deferred_activation_start),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0,
G_TYPE_NONE);
}
NMActRequest *
@@ -97,7 +165,7 @@ nm_act_request_new (NMConnection *connection,
NMActRequestPrivate *priv;
gulong id;
g_return_val_if_fail (connection != NULL, NULL);
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
obj = g_object_new (NM_TYPE_ACT_REQUEST, NULL);
if (!obj)
@@ -119,6 +187,101 @@ nm_act_request_new (NMConnection *connection,
return NM_ACT_REQUEST (obj);
}
static gboolean
deferred_timeout_cb (gpointer data)
{
NMActRequest *self = NM_ACT_REQUEST (data);
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
priv->deferred_timeout_id = 0;
clear_deferred_stuff (self);
g_signal_emit (self, signals[DEFERRED_ACTIVATION_TIMEOUT], 0);
return FALSE;
}
static void
connection_added_cb (NMManager *manager,
NMConnection *connection,
gpointer user_data)
{
NMActRequest *self;
NMActRequestPrivate *priv;
const char *service_name;
const char *path;
gulong id;
g_return_if_fail (NM_IS_ACT_REQUEST (user_data));
g_return_if_fail (NM_IS_CONNECTION (connection));
g_return_if_fail (NM_IS_MANAGER (manager));
self = NM_ACT_REQUEST (user_data);
service_name = nm_manager_get_connection_service_name (manager, connection);
path = nm_manager_get_connection_dbus_path (manager, connection);
if (!service_name || !path) {
nm_warning ("Couldn't get connection service name or path (%s, %s)",
service_name, path);
return;
}
priv = NM_ACT_REQUEST_GET_PRIVATE (self);
if ( strcmp (service_name, priv->deferred_service_name)
|| strcmp (path, priv->deferred_connection_path))
return;
clear_deferred_stuff (self);
priv->connection = g_object_ref (connection);
id = g_signal_connect (priv->connection,
"secrets-updated",
G_CALLBACK (connection_secrets_updated_cb),
self);
priv->secrets_updated_id = id;
g_signal_emit (self, signals[DEFERRED_ACTIVATION_START], 0);
}
NMActRequest *
nm_act_request_new_deferred (const char *service_name,
const char *connection_path,
const char *specific_object,
gboolean user_requested)
{
GObject *obj;
NMManager *manager;
NMActRequestPrivate *priv;
gulong id;
g_return_val_if_fail (service_name != NULL, NULL);
g_return_val_if_fail (connection_path != NULL, NULL);
obj = g_object_new (NM_TYPE_ACT_REQUEST, NULL);
if (!obj)
return NULL;
priv = NM_ACT_REQUEST_GET_PRIVATE (obj);
priv->deferred_service_name = g_strdup (service_name);
priv->deferred_connection_path = g_strdup (connection_path);
priv->user_requested = user_requested;
if (specific_object)
priv->specific_object = g_strdup (specific_object);
id = g_timeout_add (5000, deferred_timeout_cb, NM_ACT_REQUEST (obj));
priv->deferred_timeout_id = id;
manager = nm_manager_get ();
id = g_signal_connect (manager,
"connection-added",
G_CALLBACK (connection_added_cb),
NM_ACT_REQUEST (obj));
priv->deferred_connection_id = id;
g_object_unref (manager);
return NM_ACT_REQUEST (obj);
}
static void
connection_secrets_updated_cb (NMConnection *connection,
const char *setting_name,