summary refs log tree commit diff
path: root/src/nm-activation-request.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-activation-request.c')
-rw-r--r--src/nm-activation-request.c318
1 files changed, 134 insertions, 184 deletions
diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c
index d3eb920d..3fc7b538 100644
--- a/src/nm-activation-request.c
+++ b/src/nm-activation-request.c
@@ -15,7 +15,7 @@
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *
- * Copyright (C) 2005 - 2011 Red Hat, Inc.
+ * Copyright (C) 2005 - 2012 Red Hat, Inc.
  * Copyright (C) 2007 - 2008 Novell, Inc.
  */
 
@@ -34,25 +34,16 @@
 #include "nm-setting-8021x.h"
 #include "nm-dbus-manager.h"
 #include "nm-device.h"
-#include "nm-properties-changed-signal.h"
 #include "nm-active-connection.h"
-#include "nm-dbus-glib-types.h"
-#include "nm-active-connection-glue.h"
 #include "nm-settings-connection.h"
 
 
-G_DEFINE_TYPE (NMActRequest, nm_act_request, G_TYPE_OBJECT)
+G_DEFINE_TYPE (NMActRequest, nm_act_request, NM_TYPE_ACTIVE_CONNECTION)
 
 #define NM_ACT_REQUEST_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
                                        NM_TYPE_ACT_REQUEST, \
                                        NMActRequestPrivate))
 
-enum {
-	PROPERTIES_CHANGED,
-	LAST_SIGNAL
-};
-static guint signals[LAST_SIGNAL] = { 0 };
-
 typedef struct {
 	char *table;
 	char *rule;
@@ -65,36 +56,30 @@ typedef struct {
 
 	GSList *secrets_calls;
 
-	char *specific_object;
 	NMDevice *device;
 	gboolean user_requested;
 	gulong user_uid;
 
-	NMActiveConnectionState state;
-	gboolean is_default;
-	gboolean is_default6;
+	NMActiveConnection *dep;
+	guint dep_state_id;
+
 	gboolean shared;
 	GSList *share_rules;
 
-	char *ac_path;
-
 	gboolean assumed;
 } NMActRequestPrivate;
 
 enum {
-	PROP_0,
-	PROP_CONNECTION,
-	PROP_UUID,
-	PROP_SPECIFIC_OBJECT,
-	PROP_DEVICES,
-	PROP_STATE,
-	PROP_DEFAULT,
-	PROP_DEFAULT6,
-	PROP_VPN,
-
-	LAST_PROP
+	PROP_MASTER = 2000,
 };
 
+enum {
+	DEP_RESULT,
+
+	LAST_SIGNAL
+};
+static guint signals[LAST_SIGNAL] = { 0 };
+
 /*******************************************************************/
 
 typedef struct {
@@ -199,29 +184,6 @@ nm_act_request_get_connection (NMActRequest *req)
 	return NM_ACT_REQUEST_GET_PRIVATE (req)->connection;
 }
 
-const char *
-nm_act_request_get_specific_object (NMActRequest *req)
-{
-	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NULL);
-
-	return NM_ACT_REQUEST_GET_PRIVATE (req)->specific_object;
-}
-
-void
-nm_act_request_set_specific_object (NMActRequest *req,
-                                    const char *specific_object)
-{
-	NMActRequestPrivate *priv;
-
-	g_return_if_fail (NM_IS_ACT_REQUEST (req));
-	g_return_if_fail (specific_object != NULL);
-
-	priv = NM_ACT_REQUEST_GET_PRIVATE (req);
-
-	g_free (priv->specific_object);
-	priv->specific_object = g_strdup (specific_object);
-}
-
 gboolean
 nm_act_request_get_user_requested (NMActRequest *req)
 {
@@ -230,74 +192,47 @@ nm_act_request_get_user_requested (NMActRequest *req)
 	return NM_ACT_REQUEST_GET_PRIVATE (req)->user_requested;
 }
 
-const char *
-nm_act_request_get_active_connection_path (NMActRequest *req)
+GObject *
+nm_act_request_get_device (NMActRequest *req)
 {
 	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NULL);
 
-	return NM_ACT_REQUEST_GET_PRIVATE (req)->ac_path;
-}
-
-void
-nm_act_request_set_default (NMActRequest *req, gboolean is_default)
-{
-	NMActRequestPrivate *priv;
-
-	g_return_if_fail (NM_IS_ACT_REQUEST (req));
-
-	priv = NM_ACT_REQUEST_GET_PRIVATE (req);
-	if (priv->is_default == is_default)
-		return;
-
-	priv->is_default = is_default;
-	g_object_notify (G_OBJECT (req), NM_ACTIVE_CONNECTION_DEFAULT);
+	return G_OBJECT (NM_ACT_REQUEST_GET_PRIVATE (req)->device);
 }
 
 gboolean
-nm_act_request_get_default (NMActRequest *req)
+nm_act_request_get_assumed (NMActRequest *req)
 {
 	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
 
-	return NM_ACT_REQUEST_GET_PRIVATE (req)->is_default;
+	return NM_ACT_REQUEST_GET_PRIVATE (req)->assumed;
 }
 
-void
-nm_act_request_set_default6 (NMActRequest *req, gboolean is_default6)
+NMActiveConnection *
+nm_act_request_get_dependency (NMActRequest *req)
 {
-	NMActRequestPrivate *priv;
-
-	g_return_if_fail (NM_IS_ACT_REQUEST (req));
-
-	priv = NM_ACT_REQUEST_GET_PRIVATE (req);
-	if (priv->is_default6 == is_default6)
-		return;
-
-	priv->is_default6 = is_default6;
-	g_object_notify (G_OBJECT (req), NM_ACTIVE_CONNECTION_DEFAULT6);
+	return NM_ACT_REQUEST_GET_PRIVATE (req)->dep;
 }
 
-gboolean
-nm_act_request_get_default6 (NMActRequest *req)
+static NMActRequestDependencyResult
+ac_state_to_dep_result (NMActiveConnection *ac)
 {
-	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
+	NMActiveConnectionState state = nm_active_connection_get_state (ac);
 
-	return NM_ACT_REQUEST_GET_PRIVATE (req)->is_default6;
-}
+	if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATING)
+		return NM_ACT_REQUEST_DEP_RESULT_WAIT;
+	else if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED)
+		return NM_ACT_REQUEST_DEP_RESULT_READY;
 
-GObject *
-nm_act_request_get_device (NMActRequest *req)
-{
-	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NULL);
-
-	return G_OBJECT (NM_ACT_REQUEST_GET_PRIVATE (req)->device);
+	return NM_ACT_REQUEST_DEP_RESULT_FAILED;
 }
 
-gboolean
-nm_act_request_get_assumed (NMActRequest *req)
+NMActRequestDependencyResult
+nm_act_request_get_dependency_result (NMActRequest *req)
 {
-	g_return_val_if_fail (NM_IS_ACT_REQUEST (req), FALSE);
+	NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (req);
 
-	return NM_ACT_REQUEST_GET_PRIVATE (req)->assumed;
+	return priv->dep ? ac_state_to_dep_result (priv->dep) : NM_ACT_REQUEST_DEP_RESULT_READY;
 }
 
 /********************************************************************/
@@ -423,9 +358,7 @@ device_state_changed (NMDevice *device,
                       gpointer user_data)
 {
 	NMActRequest *self = NM_ACT_REQUEST (user_data);
-	NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
 	NMActiveConnectionState new_ac_state;
-	gboolean new_default = FALSE, new_default6 = FALSE;
 
 	/* Set NMActiveConnection state based on the device's state */
 	switch (new_state) {
@@ -439,43 +372,84 @@ device_state_changed (NMDevice *device,
 		break;
 	case NM_DEVICE_STATE_ACTIVATED:
 		new_ac_state = NM_ACTIVE_CONNECTION_STATE_ACTIVATED;
-		new_default = priv->is_default;
-		new_default6 = priv->is_default6;
 		break;
 	case NM_DEVICE_STATE_DEACTIVATING:
 		new_ac_state = NM_ACTIVE_CONNECTION_STATE_DEACTIVATING;
 		break;
 	default:
 		new_ac_state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
-		new_default = new_default6 = FALSE;
+		nm_active_connection_set_default (NM_ACTIVE_CONNECTION (self), FALSE);
+		nm_active_connection_set_default6 (NM_ACTIVE_CONNECTION (self), FALSE);
 		break;
 	}
 
-	if (new_ac_state != priv->state) {
-		priv->state = new_ac_state;
-		g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_STATE);
-	}
+	nm_active_connection_set_state (NM_ACTIVE_CONNECTION (self), new_ac_state);
+}
 
-	if (new_default != priv->is_default) {
-		priv->is_default = new_default;
-		g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEFAULT);
-	}
+/********************************************************************/
 
-	if (new_default6 != priv->is_default6) {
-		priv->is_default6 = new_default6;
-		g_object_notify (G_OBJECT (self), NM_ACTIVE_CONNECTION_DEFAULT6);
-	}
+static void
+dep_gone (NMActRequest *self, GObject *ignored)
+{
+	NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
+
+	g_warn_if_fail (G_OBJECT (priv->dep) == ignored);
+
+	/* Dependent connection is gone; clean up and fail */
+	priv->dep = NULL;
+	priv->dep_state_id = 0;
+	g_signal_emit (self, signals[DEP_RESULT], 0, NM_ACT_REQUEST_DEP_RESULT_FAILED);
 }
 
-/********************************************************************/
+static void
+dep_state_changed (NMActiveConnection *dep,
+                   GParamSpec *pspec,
+                   NMActRequest *self)
+{
+	NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
+	NMActRequestDependencyResult result;
 
+	g_warn_if_fail (priv->dep == dep);
+
+	result = ac_state_to_dep_result (priv->dep);
+	if (result == NM_ACT_REQUEST_DEP_RESULT_FAILED) {
+		g_object_weak_unref (G_OBJECT (priv->dep), (GWeakNotify) dep_gone, self);
+		g_signal_handler_disconnect (priv->dep, priv->dep_state_id);
+		priv->dep = NULL;
+		priv->dep_state_id = 0;
+	}
+	g_signal_emit (self, signals[DEP_RESULT], 0, result);
+}
+
+/**
+ * nm_act_request_new:
+ *
+ * @connection: the connection to activate @device with
+ * @specific_object: the object path of the specific object (ie, WiFi access point,
+ *    etc) that will be used to activate @connection and @device
+ * @user_requested: pass %TRUE if the activation was requested via D-Bus,
+ *    otherwise %FALSE if requested internally by NM (ie, autoconnect)
+ * @user_uid: if @user_requested is %TRUE, the Unix UID of the user that requested
+ *    the activation
+ * @assumed: pass %TRUE if the activation should "assume" (ie, taking over) an
+ *    existing connection made before this instance of NM started
+ * @device: the device/interface to configure according to @connection
+ * @dependency: if the activation depends on another device (ie, VLAN slave,
+ *    bond slave, etc) pass the #NMActiveConnection that this activation request
+ *    should wait for before proceeding
+ *
+ * Begins activation of @device using the given @connection and other details.
+ *
+ * Returns: the new activation request on success, %NULL on error.
+ */
 NMActRequest *
 nm_act_request_new (NMConnection *connection,
                     const char *specific_object,
                     gboolean user_requested,
                     gulong user_uid,
                     gboolean assumed,
-                    gpointer *device)
+                    gpointer *device,
+                    NMActiveConnection *dependency)
 {
 	GObject *object;
 	NMActRequestPrivate *priv;
@@ -483,16 +457,15 @@ nm_act_request_new (NMConnection *connection,
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 	g_return_val_if_fail (NM_DEVICE (device), NULL);
 
-	object = g_object_new (NM_TYPE_ACT_REQUEST, NULL);
+	object = g_object_new (NM_TYPE_ACT_REQUEST,
+	                       NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object,
+	                       NULL);
 	if (!object)
 		return NULL;
 
 	priv = NM_ACT_REQUEST_GET_PRIVATE (object);
 
 	priv->connection = g_object_ref (connection);
-	if (specific_object)
-		priv->specific_object = g_strdup (specific_object);
-
 	priv->device = NM_DEVICE (device);
 	g_signal_connect (device, "state-changed",
 	                  G_CALLBACK (device_state_changed),
@@ -502,23 +475,28 @@ nm_act_request_new (NMConnection *connection,
 	priv->user_requested = user_requested;
 	priv->assumed = assumed;
 
-	return NM_ACT_REQUEST (object);
+	if (dependency) {
+		priv->dep = dependency;
+		g_object_weak_ref (G_OBJECT (dependency), (GWeakNotify) dep_gone, object);
+		priv->dep_state_id = g_signal_connect (dependency,
+		                                       "notify::" NM_ACTIVE_CONNECTION_STATE,
+		                                       G_CALLBACK (dep_state_changed),
+		                                       object);
+	}
+
+	if (!nm_active_connection_export (NM_ACTIVE_CONNECTION (object),
+	                                  connection,
+	                                  nm_device_get_path (NM_DEVICE (device)))) {
+		g_object_unref (object);
+		object = NULL;
+	}
+
+	return (NMActRequest *) object;
 }
 
 static void
 nm_act_request_init (NMActRequest *req)
 {
-	NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (req);
-	NMDBusManager *dbus_mgr;
-
-	priv->ac_path = nm_active_connection_get_next_object_path ();
-	priv->state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN;
-
-	dbus_mgr = nm_dbus_manager_get ();
-	dbus_g_connection_register_g_object (nm_dbus_manager_get_connection (dbus_mgr),
-	                                     priv->ac_path,
-	                                     G_OBJECT (req));
-	g_object_unref (dbus_mgr);
 }
 
 static void
@@ -526,38 +504,17 @@ get_property (GObject *object, guint prop_id,
 			  GValue *value, GParamSpec *pspec)
 {
 	NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
-	GPtrArray *devices;
+	NMDevice *master;
 
 	switch (prop_id) {
-	case PROP_CONNECTION:
-		g_value_set_boxed (value, nm_connection_get_path (priv->connection));
-		break;
-	case PROP_UUID:
-		g_value_set_string (value, nm_connection_get_uuid (priv->connection));
-		break;
-	case PROP_SPECIFIC_OBJECT:
-		if (priv->specific_object)
-			g_value_set_boxed (value, priv->specific_object);
-		else
+	case PROP_MASTER:
+		if (priv->dep && NM_IS_ACT_REQUEST (priv->dep)) {
+			master = NM_DEVICE (nm_act_request_get_device (NM_ACT_REQUEST (priv->dep)));
+			g_assert (master);
+			g_value_set_boxed (value, nm_device_get_path (master));
+		} else
 			g_value_set_boxed (value, "/");
 		break;
-	case PROP_DEVICES:
-		devices = g_ptr_array_sized_new (1);
-		g_ptr_array_add (devices, g_strdup (nm_device_get_path (priv->device)));
-		g_value_take_boxed (value, devices);
-		break;
-	case PROP_STATE:
-		g_value_set_uint (value, priv->state);
-		break;
-	case PROP_DEFAULT:
-		g_value_set_boolean (value, priv->is_default);
-		break;
-	case PROP_DEFAULT6:
-		g_value_set_boolean (value, priv->is_default6);
-		break;
-	case PROP_VPN:
-		g_value_set_boolean (value, FALSE);
-		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -595,17 +552,19 @@ dispose (GObject *object)
 
 	g_object_unref (priv->connection);
 
+	if (priv->dep) {
+		g_object_weak_unref (G_OBJECT (priv->dep), (GWeakNotify) dep_gone, object);
+		g_signal_handler_disconnect (priv->dep, priv->dep_state_id);
+		priv->dep = NULL;
+		priv->dep_state_id = 0;
+	}
+
 	G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object);
 }
 
 static void
 finalize (GObject *object)
 {
-	NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
-
-	g_free (priv->specific_object);
-	g_free (priv->ac_path);
-
 	clear_share_rules (NM_ACT_REQUEST (object));
 
 	G_OBJECT_CLASS (nm_act_request_parent_class)->finalize (object);
@@ -623,23 +582,14 @@ nm_act_request_class_init (NMActRequestClass *req_class)
 	object_class->dispose = dispose;
 	object_class->finalize = finalize;
 
-	/* properties */
-    nm_active_connection_install_properties (object_class,
-                                             PROP_CONNECTION,
-                                             PROP_UUID,
-                                             PROP_SPECIFIC_OBJECT,
-                                             PROP_DEVICES,
-                                             PROP_STATE,
-                                             PROP_DEFAULT,
-                                             PROP_DEFAULT6,
-                                             PROP_VPN);
-
-	/* Signals */
-	signals[PROPERTIES_CHANGED] = 
-		nm_properties_changed_signal_new (object_class,
-		                                  G_STRUCT_OFFSET (NMActRequestClass, properties_changed));
-
-	dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (req_class),
-	                                 &dbus_glib_nm_active_connection_object_info);
+	g_object_class_override_property (object_class, PROP_MASTER, NM_ACTIVE_CONNECTION_MASTER);
+
+	signals[DEP_RESULT] =
+		g_signal_new (NM_ACT_REQUEST_DEPENDENCY_RESULT,
+					  G_OBJECT_CLASS_TYPE (object_class),
+					  G_SIGNAL_RUN_FIRST,
+					  0, NULL, NULL,
+					  g_cclosure_marshal_VOID__UINT,
+					  G_TYPE_NONE, 1, G_TYPE_UINT);
 }