core: separate active and applied connection
Clone the connection upon activation. This makes it safe for the user to modify the original connection while it is activated. This involves several changes: - NMActiveConnection gets @settings_connection and @applied_connection. To support add-and-activate, we constructing a NMActiveConnection with no connection set. Previously, we would set the "connection" field to a temporary NMConnection. Now NMManager piggybacks this temporary connection as object-data (TAG_ACTIVE_CONNETION_ADD_AND_ACTIVATE). - get rid of the functions nm_active_connection_get_connection_type() and nm_active_connection_get_connection_uuid(). From their names it is unclear whether this returns the settings or applied connection. The (few) callers should figure that out themselves. - rename nm_active_connection_get_id() to nm_active_connection_get_settings_connection_id(). This function is only used internally for logging. - dispatcher calls now get two connections as well. The applied-connection is used for the connection data, while the settings-connection is used for the connection path. - needs special handling for properties that apply immediately when changed (nm_device_reapply_settings_immediately()). Co-Authored-By: Thomas Haller <thaller@redhat.com> https://bugzilla.gnome.org/show_bug.cgi?id=724041
This commit is contained in:

committed by
Thomas Haller

parent
c9b3617c35
commit
06da353242
@@ -65,25 +65,52 @@ enum {
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
NMConnection *
|
||||
nm_act_request_get_connection (NMActRequest *req)
|
||||
NMSettingsConnection *
|
||||
nm_act_request_get_settings_connection (NMActRequest *req)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NULL);
|
||||
|
||||
return nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (req));
|
||||
return nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (req));
|
||||
}
|
||||
|
||||
NMConnection *
|
||||
nm_act_request_get_applied_connection (NMActRequest *req)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NULL);
|
||||
|
||||
return nm_active_connection_get_applied_connection (NM_ACTIVE_CONNECTION (req));
|
||||
}
|
||||
|
||||
/*******************************************************************/
|
||||
|
||||
struct _NMActRequestGetSecretsCallId {
|
||||
NMActRequest *self;
|
||||
NMSettingsConnectionCallId call_id_s;
|
||||
NMActRequestSecretsFunc callback;
|
||||
gpointer callback_data;
|
||||
NMSettingsConnectionCallId call_id;
|
||||
};
|
||||
|
||||
typedef struct _NMActRequestGetSecretsCallId GetSecretsInfo;
|
||||
|
||||
static GetSecretsInfo *
|
||||
_get_secrets_info_new (NMActRequest *self, NMActRequestSecretsFunc callback, gpointer callback_data)
|
||||
{
|
||||
GetSecretsInfo *info;
|
||||
|
||||
info = g_slice_new0 (GetSecretsInfo);
|
||||
info->self = self;
|
||||
info->callback = callback;
|
||||
info->callback_data = callback_data;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
_get_secrets_info_free (GetSecretsInfo *info)
|
||||
{
|
||||
g_slice_free (GetSecretsInfo, info);
|
||||
}
|
||||
|
||||
static void
|
||||
get_secrets_cb (NMSettingsConnection *connection,
|
||||
NMSettingsConnectionCallId call_id_s,
|
||||
@@ -93,16 +120,24 @@ get_secrets_cb (NMSettingsConnection *connection,
|
||||
gpointer user_data)
|
||||
{
|
||||
GetSecretsInfo *info = user_data;
|
||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (info->self);
|
||||
NMActRequestPrivate *priv;
|
||||
|
||||
g_return_if_fail (info && info->call_id == call_id_s);
|
||||
g_return_if_fail (NM_IS_ACT_REQUEST (info->self));
|
||||
|
||||
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
|
||||
return;
|
||||
|
||||
priv = NM_ACT_REQUEST_GET_PRIVATE (info->self);
|
||||
|
||||
g_return_if_fail (info->call_id_s == call_id_s);
|
||||
g_return_if_fail (g_slist_find (priv->secrets_calls, info));
|
||||
|
||||
priv->secrets_calls = g_slist_remove (priv->secrets_calls, info);
|
||||
|
||||
if (info->callback)
|
||||
info->callback (info->self, info, NM_CONNECTION (connection), error, info->callback_data);
|
||||
g_free (info);
|
||||
info->callback (info->self, info, connection, error, info->callback_data);
|
||||
|
||||
_get_secrets_info_free (info);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,57 +170,92 @@ nm_act_request_get_secrets (NMActRequest *self,
|
||||
NMActRequestPrivate *priv;
|
||||
GetSecretsInfo *info;
|
||||
NMSettingsConnectionCallId call_id_s;
|
||||
NMConnection *connection;
|
||||
NMSettingsConnection *settings_connection;
|
||||
NMConnection *applied_connection;
|
||||
const char *hints[2] = { hint, NULL };
|
||||
|
||||
g_return_val_if_fail (self, 0);
|
||||
g_return_val_if_fail (NM_IS_ACT_REQUEST (self), 0);
|
||||
|
||||
priv = NM_ACT_REQUEST_GET_PRIVATE (self);
|
||||
|
||||
info = g_malloc0 (sizeof (GetSecretsInfo));
|
||||
info->self = self;
|
||||
info->callback = callback;
|
||||
info->callback_data = callback_data;
|
||||
settings_connection = nm_act_request_get_settings_connection (self);
|
||||
applied_connection = nm_act_request_get_applied_connection (self);
|
||||
|
||||
info = _get_secrets_info_new (self, callback, callback_data);
|
||||
|
||||
priv->secrets_calls = g_slist_append (priv->secrets_calls, info);
|
||||
|
||||
if (nm_active_connection_get_user_requested (NM_ACTIVE_CONNECTION (self)))
|
||||
flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED;
|
||||
|
||||
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self));
|
||||
call_id_s = nm_settings_connection_get_secrets (NM_SETTINGS_CONNECTION (connection),
|
||||
call_id_s = nm_settings_connection_get_secrets (settings_connection,
|
||||
applied_connection,
|
||||
nm_active_connection_get_subject (NM_ACTIVE_CONNECTION (self)),
|
||||
setting_name,
|
||||
flags,
|
||||
hints,
|
||||
get_secrets_cb,
|
||||
info,
|
||||
NULL);
|
||||
if (call_id_s) {
|
||||
info->call_id_s = call_id_s;
|
||||
priv->secrets_calls = g_slist_append (priv->secrets_calls, info);
|
||||
} else
|
||||
g_free (info);
|
||||
|
||||
info);
|
||||
info->call_id = call_id_s;
|
||||
g_return_val_if_fail (call_id_s, NULL);
|
||||
return info;
|
||||
}
|
||||
|
||||
static void
|
||||
_do_cancel_secrets (NMActRequest *self, GetSecretsInfo *info, gboolean is_disposing)
|
||||
{
|
||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
|
||||
|
||||
nm_assert (info && info->self == self);
|
||||
nm_assert (g_slist_find (priv->secrets_calls, info));
|
||||
|
||||
priv->secrets_calls = g_slist_remove (priv->secrets_calls, info);
|
||||
|
||||
nm_settings_connection_cancel_secrets (nm_act_request_get_settings_connection (self), info->call_id);
|
||||
|
||||
if (info->callback) {
|
||||
gs_free_error GError *error = NULL;
|
||||
|
||||
if (is_disposing) {
|
||||
/* Use a different error code. G_IO_ERROR_CANCELLED is only used synchronously
|
||||
* when the user calls nm_act_request_cancel_secrets(). Disposing the instance
|
||||
* with pending requests also cancels the requests, but with a different error
|
||||
* code. */
|
||||
g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
"Disposing NMActRequest instance");
|
||||
} else {
|
||||
g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_CANCELLED,
|
||||
"Request cancelled");
|
||||
}
|
||||
|
||||
info->callback (self, info, NULL, error, info->callback_data);
|
||||
}
|
||||
|
||||
_get_secrets_info_free (info);
|
||||
}
|
||||
|
||||
void
|
||||
nm_act_request_cancel_secrets (NMActRequest *self, NMActRequestGetSecretsCallId call_id)
|
||||
{
|
||||
NMActRequestPrivate *priv;
|
||||
NMConnection *connection;
|
||||
|
||||
g_return_if_fail (self);
|
||||
g_return_if_fail (NM_IS_ACT_REQUEST (self));
|
||||
g_return_if_fail (call_id);
|
||||
|
||||
priv = NM_ACT_REQUEST_GET_PRIVATE (self);
|
||||
|
||||
if (g_slist_find (priv->secrets_calls, call_id))
|
||||
if (!g_slist_find (priv->secrets_calls, call_id))
|
||||
g_return_if_reached ();
|
||||
|
||||
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (self));
|
||||
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (connection), call_id->call_id_s);
|
||||
_do_cancel_secrets (self, call_id, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
nm_act_request_clear_secrets (NMActRequest *self)
|
||||
{
|
||||
g_return_if_fail (NM_IS_ACT_REQUEST (self));
|
||||
|
||||
nm_active_connection_clear_secrets ((NMActiveConnection *) self);
|
||||
}
|
||||
|
||||
/********************************************************************/
|
||||
@@ -405,7 +475,7 @@ master_failed (NMActiveConnection *self)
|
||||
/**
|
||||
* nm_act_request_new:
|
||||
*
|
||||
* @connection: the connection to activate @device with
|
||||
* @settings_connection: (allow-none): 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
|
||||
* @subject: the #NMAuthSubject representing the requestor of the activation
|
||||
@@ -418,17 +488,17 @@ master_failed (NMActiveConnection *self)
|
||||
* Returns: the new activation request on success, %NULL on error.
|
||||
*/
|
||||
NMActRequest *
|
||||
nm_act_request_new (NMConnection *connection,
|
||||
nm_act_request_new (NMSettingsConnection *settings_connection,
|
||||
const char *specific_object,
|
||||
NMAuthSubject *subject,
|
||||
NMDevice *device)
|
||||
{
|
||||
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
||||
g_return_val_if_fail (!settings_connection || NM_IS_SETTINGS_CONNECTION (settings_connection), NULL);
|
||||
g_return_val_if_fail (!device || NM_IS_DEVICE (device), NULL);
|
||||
g_return_val_if_fail (NM_IS_AUTH_SUBJECT (subject), NULL);
|
||||
|
||||
return (NMActRequest *) g_object_new (NM_TYPE_ACT_REQUEST,
|
||||
NM_ACTIVE_CONNECTION_INT_CONNECTION, connection,
|
||||
NM_ACTIVE_CONNECTION_INT_SETTINGS_CONNECTION, settings_connection,
|
||||
NM_ACTIVE_CONNECTION_INT_DEVICE, device,
|
||||
NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, specific_object,
|
||||
NM_ACTIVE_CONNECTION_INT_SUBJECT, subject,
|
||||
@@ -443,8 +513,12 @@ nm_act_request_init (NMActRequest *req)
|
||||
static void
|
||||
dispose (GObject *object)
|
||||
{
|
||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (object);
|
||||
NMConnection *connection;
|
||||
NMActRequest *self = NM_ACT_REQUEST (object);
|
||||
NMActRequestPrivate *priv = NM_ACT_REQUEST_GET_PRIVATE (self);
|
||||
|
||||
/* Kill any in-progress secrets requests */
|
||||
while (priv->secrets_calls)
|
||||
_do_cancel_secrets (self, priv->secrets_calls->data, TRUE);
|
||||
|
||||
/* Clear any share rules */
|
||||
if (priv->share_rules) {
|
||||
@@ -452,16 +526,6 @@ dispose (GObject *object)
|
||||
clear_share_rules (NM_ACT_REQUEST (object));
|
||||
}
|
||||
|
||||
/* Kill any in-progress secrets requests */
|
||||
connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (object));
|
||||
while (priv->secrets_calls) {
|
||||
GetSecretsInfo *info = priv->secrets_calls->data;
|
||||
|
||||
nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (connection), info->call_id_s);
|
||||
|
||||
g_return_if_fail (!priv->secrets_calls || info != priv->secrets_calls->data);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (nm_act_request_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user