Commit acf86f68 authored by Dan Winship's avatar Dan Winship

libnm-core: change connection hash tables to variants in API

In preparation for porting to GDBus, make nm_connection_to_dbus(),
etc, represent connections as GVariants of type 'a{sa{sv}}' rather
than as GHashTables-of-GHashTables-of-GValues.

This means we're constantly converting back and forth internally, but
this is just a stepping stone on the way to the full GDBus port, and
all of that code will go away again later.
parent 47505595
...@@ -406,7 +406,7 @@ nm_dispatcher_utils_construct_envp (const char *action, ...@@ -406,7 +406,7 @@ nm_dispatcher_utils_construct_envp (const char *action,
} }
/* UUID and ID */ /* UUID and ID */
con_setting = g_variant_lookup_value (connection_dict, NM_SETTING_CONNECTION_SETTING_NAME, G_VARIANT_TYPE ("a{sv}")); con_setting = g_variant_lookup_value (connection_dict, NM_SETTING_CONNECTION_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
if (!con_setting) { if (!con_setting) {
g_warning ("Failed to read connection setting"); g_warning ("Failed to read connection setting");
return NULL; return NULL;
......
...@@ -30,25 +30,9 @@ ...@@ -30,25 +30,9 @@
#include "nm-dispatcher-utils.h" #include "nm-dispatcher-utils.h"
#include "nm-dispatcher-api.h" #include "nm-dispatcher-api.h"
#include "nm-utils.h" #include "nm-utils.h"
#include "nm-dbus-glib-types.h"
/*******************************************/ /*******************************************/
static GVariant *
connection_hash_to_dict (GHashTable *hash)
{
GValue val = { 0, };
GVariant *dict;
g_value_init (&val, DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT);
g_value_set_boxed (&val, hash);
dict = dbus_g_value_build_g_variant (&val);
g_value_unset (&val);
g_variant_ref_sink (dict);
return dict;
}
static gboolean static gboolean
parse_main (GKeyFile *kf, parse_main (GKeyFile *kf,
GVariant **out_con_dict, GVariant **out_con_dict,
...@@ -62,7 +46,6 @@ parse_main (GKeyFile *kf, ...@@ -62,7 +46,6 @@ parse_main (GKeyFile *kf,
NMConnection *connection; NMConnection *connection;
NMSettingConnection *s_con; NMSettingConnection *s_con;
GVariantBuilder props; GVariantBuilder props;
GHashTable *con_hash;
*out_expected_iface = g_key_file_get_string (kf, "main", "expected-iface", error); *out_expected_iface = g_key_file_get_string (kf, "main", "expected-iface", error);
if (*out_expected_iface == NULL) if (*out_expected_iface == NULL)
...@@ -93,10 +76,8 @@ parse_main (GKeyFile *kf, ...@@ -93,10 +76,8 @@ parse_main (GKeyFile *kf,
g_free (id); g_free (id);
nm_connection_add_setting (connection, NM_SETTING (s_con)); nm_connection_add_setting (connection, NM_SETTING (s_con));
con_hash = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL); *out_con_dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
g_object_unref (connection); g_object_unref (connection);
*out_con_dict = connection_hash_to_dict (con_hash);
g_hash_table_unref (con_hash);
g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}")); g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&props, "{sv}", g_variant_builder_add (&props, "{sv}",
......
...@@ -5343,19 +5343,19 @@ gen_cmd_print0 (const char *text, int state) ...@@ -5343,19 +5343,19 @@ gen_cmd_print0 (const char *text, int state)
char *ret = NULL; char *ret = NULL;
if (!state) { if (!state) {
GHashTable *settings; GVariant *settings;
GHashTableIter iter; GVariantIter iter;
const char *setting_name; const char *setting_name;
int i = 0; int i = 0;
settings = nm_connection_to_dbus (nmc_tab_completion.connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); settings = nm_connection_to_dbus (nmc_tab_completion.connection, NM_CONNECTION_SERIALIZE_NO_SECRETS);
words = g_new (char *, g_hash_table_size (settings) + 2); words = g_new (char *, g_variant_n_children (settings) + 2);
g_hash_table_iter_init (&iter, settings); g_variant_iter_init (&iter, settings);
while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, NULL)) while (g_variant_iter_next (&iter, "{&s@a{sv}}", &setting_name, NULL))
words [i++] = g_strdup (setting_name); words [i++] = g_strdup (setting_name);
words[i++] = g_strdup ("all"); words[i++] = g_strdup ("all");
words[i] = NULL; words[i] = NULL;
g_hash_table_unref (settings); g_variant_unref (settings);
} }
if (words) { if (words) {
......
...@@ -162,31 +162,21 @@ save_connection_and_exit (NmtNewtButton *button, ...@@ -162,31 +162,21 @@ save_connection_and_exit (NmtNewtButton *button,
static void static void
got_secrets (NMRemoteConnection *connection, got_secrets (NMRemoteConnection *connection,
GHashTable *secrets, GVariant *secrets,
GError *error, GError *error,
gpointer op) gpointer op)
{ {
GHashTable *copy = NULL, *setting; if (secrets)
GHashTableIter iter; g_variant_ref (secrets);
const char *name; nmt_sync_op_complete_pointer (op, secrets, error);
if (secrets) {
/* 'secrets' is owned by the caller so we must copy it */
copy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy);
g_hash_table_iter_init (&iter, secrets);
while (g_hash_table_iter_next (&iter, (gpointer) &name, (gpointer) &setting))
g_hash_table_insert (copy, g_strdup (name), nm_utils_gvalue_hash_dup (setting));
}
nmt_sync_op_complete_pointer (op, copy, error);
} }
static NMConnection * static NMConnection *
build_edit_connection (NMConnection *orig_connection) build_edit_connection (NMConnection *orig_connection)
{ {
NMConnection *edit_connection; NMConnection *edit_connection;
GHashTable *settings, *secrets; GVariant *settings, *secrets;
GHashTableIter iter; GVariantIter iter;
const char *setting_name; const char *setting_name;
NmtSyncOp op; NmtSyncOp op;
...@@ -196,8 +186,8 @@ build_edit_connection (NMConnection *orig_connection) ...@@ -196,8 +186,8 @@ build_edit_connection (NMConnection *orig_connection)
return edit_connection; return edit_connection;
settings = nm_connection_to_dbus (orig_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS); settings = nm_connection_to_dbus (orig_connection, NM_CONNECTION_SERIALIZE_NO_SECRETS);
g_hash_table_iter_init (&iter, settings); g_variant_iter_init (&iter, settings);
while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, NULL)) { while (g_variant_iter_next (&iter, "{&s@a{sv}}", &setting_name, NULL)) {
nmt_sync_op_init (&op); nmt_sync_op_init (&op);
nm_remote_connection_get_secrets (NM_REMOTE_CONNECTION (orig_connection), nm_remote_connection_get_secrets (NM_REMOTE_CONNECTION (orig_connection),
setting_name, got_secrets, &op); setting_name, got_secrets, &op);
...@@ -205,10 +195,10 @@ build_edit_connection (NMConnection *orig_connection) ...@@ -205,10 +195,10 @@ build_edit_connection (NMConnection *orig_connection)
secrets = nmt_sync_op_wait_pointer (&op, NULL); secrets = nmt_sync_op_wait_pointer (&op, NULL);
if (secrets) { if (secrets) {
(void) nm_connection_update_secrets (edit_connection, setting_name, secrets, NULL); (void) nm_connection_update_secrets (edit_connection, setting_name, secrets, NULL);
g_hash_table_unref (secrets); g_variant_unref (secrets);
} }
} }
g_hash_table_unref (settings); g_variant_unref (settings);
return edit_connection; return edit_connection;
} }
......
...@@ -482,14 +482,6 @@ nmt_secret_agent_get_secrets (NMSecretAgent *agent, ...@@ -482,14 +482,6 @@ nmt_secret_agent_get_secrets (NMSecretAgent *agent,
request_secrets_from_ui (request); request_secrets_from_ui (request);
} }
static void
gvalue_destroy_notify (gpointer data)
{
GValue *value = data;
g_value_unset (value);
g_slice_free (GValue, value);
}
/** /**
* nmt_secret_agent_response: * nmt_secret_agent_response:
* @self: the #NmtSecretAgent * @self: the #NmtSecretAgent
...@@ -511,8 +503,7 @@ nmt_secret_agent_response (NmtSecretAgent *self, ...@@ -511,8 +503,7 @@ nmt_secret_agent_response (NmtSecretAgent *self,
{ {
NmtSecretAgentPrivate *priv; NmtSecretAgentPrivate *priv;
NmtSecretAgentRequest *request; NmtSecretAgentRequest *request;
GHashTable *hash = NULL, *setting_hash; GVariant *dict = NULL;
GValue *value;
GError *error = NULL; GError *error = NULL;
int i; int i;
...@@ -523,32 +514,41 @@ nmt_secret_agent_response (NmtSecretAgent *self, ...@@ -523,32 +514,41 @@ nmt_secret_agent_response (NmtSecretAgent *self,
g_return_if_fail (request != NULL); g_return_if_fail (request != NULL);
if (secrets) { if (secrets) {
hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) g_hash_table_unref); GVariantBuilder conn_builder, *setting_builder;
GHashTable *settings;
GHashTableIter iter;
const char *name;
settings = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 0; i < secrets->len; i++) { for (i = 0; i < secrets->len; i++) {
NmtSecretAgentSecretReal *secret = secrets->pdata[i]; NmtSecretAgentSecretReal *secret = secrets->pdata[i];
setting_hash = g_hash_table_lookup (hash, nm_setting_get_name (secret->setting)); setting_builder = g_hash_table_lookup (settings, nm_setting_get_name (secret->setting));
if (!setting_hash) { if (!setting_builder) {
setting_hash = g_hash_table_new_full (g_str_hash, g_str_equal, setting_builder = g_variant_builder_new (NM_VARIANT_TYPE_SETTING);
g_free, gvalue_destroy_notify); g_hash_table_insert (settings, (char *) nm_setting_get_name (secret->setting),
g_hash_table_insert (hash, (char *)nm_setting_get_name (secret->setting), setting_builder);
setting_hash);
} }
value = g_slice_new0 (GValue); g_variant_builder_add (setting_builder, "{sv}",
g_value_init (value, G_TYPE_STRING); secret->property,
g_value_set_string (value, secret->base.value); g_variant_new_string (secret->base.value));
g_hash_table_insert (setting_hash, g_strdup (secret->property), value);
} }
g_variant_builder_init (&conn_builder, NM_VARIANT_TYPE_CONNECTION);
g_hash_table_iter_init (&iter, settings);
while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &setting_builder))
g_variant_builder_add (&conn_builder, "{sa{sv}}", name, setting_builder);
dict = g_variant_builder_end (&conn_builder);
g_hash_table_destroy (settings);
} else { } else {
error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_USER_CANCELED, error = g_error_new (NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_USER_CANCELED,
"User cancelled"); "User cancelled");
} }
request->callback (NM_SECRET_AGENT (self), request->connection, hash, error, request->callback_data); request->callback (NM_SECRET_AGENT (self), request->connection, dict, error, request->callback_data);
g_clear_pointer (&hash, g_hash_table_unref); g_clear_pointer (&dict, g_variant_unref);
g_clear_error (&error); g_clear_error (&error);
g_hash_table_remove (priv->requests, request_id); g_hash_table_remove (priv->requests, request_id);
} }
......
...@@ -62,8 +62,7 @@ GTKDOC_CFLAGS = \ ...@@ -62,8 +62,7 @@ GTKDOC_CFLAGS = \
-I$(top_srcdir)/libnm \ -I$(top_srcdir)/libnm \
-I$(top_builddir)/libnm \ -I$(top_builddir)/libnm \
-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
$(GLIB_CFLAGS) \ $(GLIB_CFLAGS)
$(DBUS_CFLAGS)
GTKDOC_LIBS = \ GTKDOC_LIBS = \
$(top_builddir)/libnm/libnm.la \ $(top_builddir)/libnm/libnm.la \
......
...@@ -81,6 +81,5 @@ libnm_core_sources = \ ...@@ -81,6 +81,5 @@ libnm_core_sources = \
$(core)/nm-setting-wireless.c \ $(core)/nm-setting-wireless.c \
$(core)/nm-setting.c \ $(core)/nm-setting.c \
$(core)/nm-simple-connection.c \ $(core)/nm-simple-connection.c \
$(core)/nm-utils.c \ $(core)/nm-utils.c
$(core)/nm-value-transforms.c
...@@ -22,11 +22,9 @@ ...@@ -22,11 +22,9 @@
#include <glib-object.h> #include <glib-object.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include <dbus/dbus-glib.h>
#include <string.h> #include <string.h>
#include "nm-connection.h" #include "nm-connection.h"
#include "nm-utils-internal.h" #include "nm-utils.h"
#include "nm-dbus-glib-types.h"
#include "nm-setting-private.h" #include "nm-setting-private.h"
#include "nm-setting-8021x.h" #include "nm-setting-8021x.h"
...@@ -243,35 +241,40 @@ nm_connection_get_setting_by_name (NMConnection *connection, const char *name) ...@@ -243,35 +241,40 @@ nm_connection_get_setting_by_name (NMConnection *connection, const char *name)
} }
static gboolean static gboolean
validate_permissions_type (GHashTable *hash, GError **error) validate_permissions_type (GVariant *variant, GError **error)
{ {
GHashTable *s_con; GVariant *s_con;
GValue *permissions; GVariant *permissions;
gboolean valid = TRUE;
/* Ensure the connection::permissions item (if present) is the correct /* Ensure the connection::permissions item (if present) is the correct
* type, otherwise the g_object_set() will throw a warning and ignore the * type, otherwise the g_object_set() will throw a warning and ignore the
* error, leaving us with no permissions. * error, leaving us with no permissions.
*/ */
s_con = g_hash_table_lookup (hash, NM_SETTING_CONNECTION_SETTING_NAME); s_con = g_variant_lookup_value (variant, NM_SETTING_CONNECTION_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
if (s_con) { if (!s_con)
permissions = g_hash_table_lookup (s_con, NM_SETTING_CONNECTION_PERMISSIONS); return TRUE;
if (permissions) {
if (!G_VALUE_HOLDS (permissions, G_TYPE_STRV)) { permissions = g_variant_lookup_value (s_con, NM_SETTING_CONNECTION_PERMISSIONS, NULL);
g_set_error_literal (error, if (permissions) {
NM_SETTING_ERROR, if (!g_variant_is_of_type (permissions, G_VARIANT_TYPE_STRING_ARRAY)) {
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, g_set_error_literal (error,
"Wrong permissions property type; should be an array of strings."); NM_SETTING_ERROR,
return FALSE; NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
} "Wrong permissions property type; should be a list of strings.");
valid = FALSE;
} }
g_variant_unref (permissions);
} }
return TRUE;
g_variant_unref (s_con);
return valid;
} }
/** /**
* nm_connection_replace_settings: * nm_connection_replace_settings:
* @connection: a #NMConnection * @connection: a #NMConnection
* @new_settings: (element-type utf8 GLib.HashTable): a #GHashTable of settings * @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings
* @error: location to store error, or %NULL * @error: location to store error, or %NULL
* *
* Replaces @connection's settings with @new_settings (which must be * Replaces @connection's settings with @new_settings (which must be
...@@ -283,18 +286,18 @@ validate_permissions_type (GHashTable *hash, GError **error) ...@@ -283,18 +286,18 @@ validate_permissions_type (GHashTable *hash, GError **error)
**/ **/
gboolean gboolean
nm_connection_replace_settings (NMConnection *connection, nm_connection_replace_settings (NMConnection *connection,
GHashTable *new_settings, GVariant *new_settings,
GError **error) GError **error)
{ {
NMConnectionPrivate *priv; NMConnectionPrivate *priv;
GHashTableIter iter; GVariantIter iter;
const char *setting_name; const char *setting_name;
GHashTable *setting_hash; GVariant *setting_dict;
GSList *settings = NULL, *s; GSList *settings = NULL, *s;
gboolean changed; gboolean changed;
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
g_return_val_if_fail (new_settings != NULL, FALSE); g_return_val_if_fail (g_variant_is_of_type (new_settings, NM_VARIANT_TYPE_CONNECTION), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
priv = NM_CONNECTION_GET_PRIVATE (connection); priv = NM_CONNECTION_GET_PRIVATE (connection);
...@@ -302,8 +305,8 @@ nm_connection_replace_settings (NMConnection *connection, ...@@ -302,8 +305,8 @@ nm_connection_replace_settings (NMConnection *connection,
if (!validate_permissions_type (new_settings, error)) if (!validate_permissions_type (new_settings, error))
return FALSE; return FALSE;
g_hash_table_iter_init (&iter, new_settings); g_variant_iter_init (&iter, new_settings);
while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, (gpointer) &setting_hash)) { while (g_variant_iter_next (&iter, "{&s@a{sv}}", &setting_name, &setting_dict)) {
NMSetting *setting; NMSetting *setting;
GType type; GType type;
...@@ -313,15 +316,19 @@ nm_connection_replace_settings (NMConnection *connection, ...@@ -313,15 +316,19 @@ nm_connection_replace_settings (NMConnection *connection,
NM_CONNECTION_ERROR, NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_SETTING, NM_CONNECTION_ERROR_INVALID_SETTING,
"unknown setting name '%s'", setting_name); "unknown setting name '%s'", setting_name);
g_variant_unref (setting_dict);
g_slist_free_full (settings, g_object_unref); g_slist_free_full (settings, g_object_unref);
return FALSE; return FALSE;
} }
setting = _nm_setting_new_from_dbus (type, setting_hash, new_settings, error); setting = _nm_setting_new_from_dbus (type, setting_dict, new_settings, error);
g_variant_unref (setting_dict);
if (!setting) { if (!setting) {
g_slist_free_full (settings, g_object_unref); g_slist_free_full (settings, g_object_unref);
return FALSE; return FALSE;
} }
settings = g_slist_prepend (settings, setting); settings = g_slist_prepend (settings, setting);
} }
...@@ -928,16 +935,16 @@ nm_connection_normalize (NMConnection *connection, ...@@ -928,16 +935,16 @@ nm_connection_normalize (NMConnection *connection,
* nm_connection_update_secrets: * nm_connection_update_secrets:
* @connection: the #NMConnection * @connection: the #NMConnection
* @setting_name: the setting object name to which the secrets apply * @setting_name: the setting object name to which the secrets apply
* @secrets: (element-type utf8 GObject.Value): a #GHashTable mapping * @secrets: a #GVariant of secrets, of type %NM_VARIANT_TYPE_CONNECTION
* string:#GValue of setting property names and secrets of the given @setting_name * or %NM_VARIANT_TYPE_SETTING
* @error: location to store error, or %NULL * @error: location to store error, or %NULL
* *
* Update the specified setting's secrets, given a hash table of secrets * Update the specified setting's secrets, given a dictionary of secrets
* intended for that setting (deserialized from D-Bus for example). Will also * intended for that setting (deserialized from D-Bus for example). Will also
* extract the given setting's secrets hash if given a hash of hashes, as would * extract the given setting's secrets hash if given a connection dictionary.
* be returned from nm_connection_to_dbus(). If @setting_name is %NULL, expects * If @setting_name is %NULL, expects a fully serialized #NMConnection as
* a fully serialized #NMConnection as returned by nm_connection_to_dbus() and * returned by nm_connection_to_dbus() and will update all secrets from all
* will update all secrets from all settings contained in @secrets. * settings contained in @secrets.
* *
* Returns: %TRUE if the secrets were successfully updated, %FALSE if the update * Returns: %TRUE if the secrets were successfully updated, %FALSE if the update
* failed (tried to update secrets for a setting that doesn't exist, etc) * failed (tried to update secrets for a setting that doesn't exist, etc)
...@@ -945,38 +952,28 @@ nm_connection_normalize (NMConnection *connection, ...@@ -945,38 +952,28 @@ nm_connection_normalize (NMConnection *connection,
gboolean gboolean
nm_connection_update_secrets (NMConnection *connection, nm_connection_update_secrets (NMConnection *connection,
const char *setting_name, const char *setting_name,
GHashTable *secrets, GVariant *secrets,
GError **error) GError **error)
{ {
NMSetting *setting; NMSetting *setting;
gboolean success = TRUE, updated = FALSE; gboolean success = TRUE, updated = FALSE;
GHashTable *setting_hash = NULL; GVariant *setting_dict = NULL;
GHashTableIter iter; GVariantIter iter;
const char *key; const char *key;
gboolean hashed_connection = FALSE; gboolean full_connection;
int success_detail; int success_detail;
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
g_return_val_if_fail (secrets != NULL, FALSE); g_return_val_if_fail ( g_variant_is_of_type (secrets, NM_VARIANT_TYPE_SETTING)
|| g_variant_is_of_type (secrets, NM_VARIANT_TYPE_CONNECTION), FALSE);
if (error) if (error)
g_return_val_if_fail (*error == NULL, FALSE); g_return_val_if_fail (*error == NULL, FALSE);
/* Empty @secrets means success */ /* Empty @secrets means success */
if (g_hash_table_size (secrets) == 0) if (g_variant_n_children (secrets) == 0)
return TRUE; return TRUE;
/* For backwards compatibility, this function accepts either a hashed full_connection = g_variant_is_of_type (secrets, NM_VARIANT_TYPE_CONNECTION);
* connection (GHashTable of GHashTables of GValues) or a single hashed
* setting (GHashTable of GValues).
*/
g_hash_table_iter_init (&iter, secrets);
while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL)) {
if (nm_setting_lookup_type (key) != G_TYPE_INVALID) {
/* @secrets looks like a hashed connection */
hashed_connection = TRUE;
break;
}
}
if (setting_name) { if (setting_name) {
/* Update just one setting's secrets */ /* Update just one setting's secrets */
...@@ -989,10 +986,10 @@ nm_connection_update_secrets (NMConnection *connection, ...@@ -989,10 +986,10 @@ nm_connection_update_secrets (NMConnection *connection,
return FALSE; return FALSE;
} }
if (hashed_connection) { if (full_connection) {
setting_hash = g_hash_table_lookup (secrets, setting_name);