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

@@ -1,3 +1,20 @@
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
2007-09-14 Dan Williams <dcbw@redhat.com> 2007-09-14 Dan Williams <dcbw@redhat.com>
* src/nm-manager.h * src/nm-manager.h

View File

@@ -22,6 +22,8 @@
#include "nm-activation-request.h" #include "nm-activation-request.h"
#include "nm-marshal.h" #include "nm-marshal.h"
#include "nm-manager.h"
#include "nm-utils.h"
G_DEFINE_TYPE (NMActRequest, nm_act_request, G_TYPE_OBJECT) 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 { enum {
CONNECTION_SECRETS_UPDATED, CONNECTION_SECRETS_UPDATED,
DEFERRED_ACTIVATION_TIMEOUT,
DEFERRED_ACTIVATION_START,
LAST_SIGNAL LAST_SIGNAL
}; };
@@ -41,6 +45,11 @@ static void connection_secrets_updated_cb (NMConnection *connection,
NMActRequest *self); NMActRequest *self);
typedef struct { typedef struct {
char *deferred_service_name;
char *deferred_connection_path;
gulong deferred_connection_id;
guint32 deferred_timeout_id;
NMConnection *connection; NMConnection *connection;
char *specific_object; char *specific_object;
gboolean user_requested; 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 static void
finalize (GObject *object) finalize (GObject *object)
{ {
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object); NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
g_signal_handler_disconnect (priv->connection, g_free (priv->deferred_service_name);
priv->secrets_updated_id); g_free (priv->deferred_connection_path);
g_object_unref (priv->connection);
g_free (priv->specific_object); g_free (priv->specific_object);
G_OBJECT_CLASS (nm_act_request_parent_class)->finalize (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)); g_type_class_add_private (req_class, sizeof (NMActRequestPrivate));
object_class->dispose = dispose;
object_class->finalize = finalize; object_class->finalize = finalize;
/* Signals */ /* Signals */
@@ -81,11 +129,31 @@ nm_act_request_class_init (NMActRequestClass *req_class)
g_signal_new ("connection-secrets-updated", g_signal_new ("connection-secrets-updated",
G_OBJECT_CLASS_TYPE (object_class), G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST, G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMConnectionClass, secrets_updated), G_STRUCT_OFFSET (NMActRequestClass, connection_secrets_updated),
NULL, NULL, NULL, NULL,
nm_marshal_VOID__OBJECT_STRING, nm_marshal_VOID__OBJECT_STRING,
G_TYPE_NONE, 2, G_TYPE_NONE, 2,
G_TYPE_OBJECT, G_TYPE_STRING); 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 * NMActRequest *
@@ -97,7 +165,7 @@ nm_act_request_new (NMConnection *connection,
NMActRequestPrivate *priv; NMActRequestPrivate *priv;
gulong id; 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); obj = g_object_new (NM_TYPE_ACT_REQUEST, NULL);
if (!obj) if (!obj)
@@ -119,6 +187,101 @@ nm_act_request_new (NMConnection *connection,
return NM_ACT_REQUEST (obj); 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 static void
connection_secrets_updated_cb (NMConnection *connection, connection_secrets_updated_cb (NMConnection *connection,
const char *setting_name, const char *setting_name,

View File

@@ -44,6 +44,8 @@ typedef struct {
void (*connection_secrets_updated) (NMActRequest *req, void (*connection_secrets_updated) (NMActRequest *req,
NMConnection *connection, NMConnection *connection,
const char * setting); const char * setting);
void (*deferred_activation_timeout) (NMActRequest *req);
void (*deferred_activation_start) (NMActRequest *req);
} NMActRequestClass; } NMActRequestClass;
GType nm_act_request_get_type (void); GType nm_act_request_get_type (void);
@@ -52,6 +54,11 @@ NMActRequest *nm_act_request_new (NMConnection *connection,
const char *specific_object, const char *specific_object,
gboolean user_requested); gboolean user_requested);
NMActRequest *nm_act_request_new_deferred (const char *service_name,
const char *connection_path,
const char *specific_object,
gboolean user_requested);
NMConnection *nm_act_request_get_connection (NMActRequest *req); NMConnection *nm_act_request_get_connection (NMActRequest *req);
const char * nm_act_request_get_specific_object(NMActRequest *req); const char * nm_act_request_get_specific_object(NMActRequest *req);
gboolean nm_act_request_get_user_requested (NMActRequest *req); gboolean nm_act_request_get_user_requested (NMActRequest *req);