Commit e1ba13a4 authored by Dan Winship's avatar Dan Winship
Browse files

libnm-core, libnm, core: make NMConnection an interface

The fact that NMRemoteConnection has to be an NMConnection and
therefore can't be an NMObject means that it needs to reimplement bits
of NMObject functionality (and likewise NMObject needs some special
magic to deal with it). Likewise, we will need a daemon-side
equivalent of NMObject as part of the gdbus port, and we would want
NMSettingsConnection to be able to inherit from this as well.

Solve this problem by making NMConnection into an interface, and
having NMRemoteConnection and NMSettingsConnection implement it. (We
use some hacks to keep the GHashTable of NMSettings objects inside
nm-connection.c rather than having to be implemented by the
implementations.)

Since NMConnection is no longer an instantiable type, this adds
NMSimpleConnection to replace the various non-D-Bus-based uses of
NMConnection throughout the code. nm_connection_new() becomes
nm_simple_connection_new(), nm_connection_new_from_hash() becomes
nm_simple_connection_new_from_hash(), and nm_connection_duplicate()
becomes nm_simple_connection_new_clone().
parent 5ed054ac
......@@ -156,7 +156,7 @@ parse_main (GKeyFile *kf,
if (id == NULL)
return FALSE;
connection = nm_connection_new ();
connection = nm_simple_connection_new ();
g_assert (connection);
s_con = (NMSettingConnection *) nm_setting_connection_new ();
g_assert (s_con);
......
......@@ -5252,7 +5252,7 @@ do_connection_add (NmCli *nmc, int argc, char **argv)
}
/* Create a new connection object */
connection = nm_connection_new ();
connection = nm_simple_connection_new ();
/* Build up the 'connection' setting */
s_con = (NMSettingConnection *) nm_setting_connection_new ();
......@@ -7889,7 +7889,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
/* Duplicate the connection and use that so that we need not
* differentiate existing vs. new later
*/
connection = nm_connection_duplicate (found_con);
connection = nm_simple_connection_new_clone (found_con);
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
......@@ -7926,7 +7926,7 @@ do_connection_edit (NmCli *nmc, int argc, char **argv)
g_free (tmp_str);
/* Create a new connection object */
connection = nm_connection_new ();
connection = nm_simple_connection_new ();
/* Build up the 'connection' setting */
s_con = (NMSettingConnection *) nm_setting_connection_new ();
......
......@@ -2256,7 +2256,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
/* If there are some connection data from user, create a connection and
* fill them into proper settings. */
if (con_name || private || bssid2_arr || password)
connection = nm_connection_new ();
connection = nm_simple_connection_new ();
if (con_name || private) {
s_con = (NMSettingConnection *) nm_setting_connection_new ();
......@@ -2291,7 +2291,7 @@ do_device_wifi_connect_network (NmCli *nmc, int argc, char **argv)
if (password) {
if (!connection)
connection = nm_connection_new ();
connection = nm_simple_connection_new ();
s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
nm_connection_add_setting (connection, NM_SETTING (s_wsec));
......
......@@ -345,7 +345,7 @@ nm_editor_utils_create_connection (GType type,
return NULL;
}
connection = nm_connection_new ();
connection = nm_simple_connection_new ();
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
nm_connection_add_setting (connection, NM_SETTING (s_con));
......
......@@ -183,7 +183,7 @@ build_edit_connection (NMConnection *orig_connection)
const char *setting_name;
NmtSyncOp op;
edit_connection = nm_connection_duplicate (orig_connection);
edit_connection = nm_simple_connection_new_clone (orig_connection);
if (!NM_IS_REMOTE_CONNECTION (orig_connection))
return edit_connection;
......
......@@ -46,7 +46,7 @@ add_connection (DBusGProxy *proxy, const char *con_name)
GError *error = NULL;
/* Create a new connection object */
connection = (NMConnection *) nm_connection_new ();
connection = (NMConnection *) nm_simple_connection_new ();
/* Build up the 'connection' Setting */
s_con = (NMSettingConnection *) nm_setting_connection_new ();
......
......@@ -62,7 +62,7 @@ add_connection (NMRemoteSettings *settings, GMainLoop *loop, const char *con_nam
gboolean success;
/* Create a new connection object */
connection = nm_connection_new ();
connection = nm_simple_connection_new ();
/* Build up the 'connection' Setting */
s_con = (NMSettingConnection *) nm_setting_connection_new ();
......
......@@ -66,7 +66,7 @@ print_connection (DBusGConnection *bus, const char *path)
/* Using the raw configuration, create an NMConnection object for it. This
* step also verifies that the data we got from NetworkManager are valid. */
connection = nm_connection_new_from_hash (hash, &error);
connection = nm_simple_connection_new_from_hash (hash, &error);
if (!connection) {
g_warning ("Received invalid connection data: %s", error->message);
g_error_free (error);
......
......@@ -680,7 +680,7 @@ nmtst_ip6_config_clone (NMIP6Config *config)
#endif
#ifdef __NM_CONNECTION_H__
#ifdef __NM_SIMPLE_CONNECTION_H__
inline static NMConnection *
nmtst_create_minimal_connection (const char *id, const char *uuid, const char *type, NMSettingConnection **out_s_con)
......@@ -706,7 +706,7 @@ nmtst_create_minimal_connection (const char *id, const char *uuid, const char *t
g_assert (NM_IS_SETTING (s_base));
}
con = nm_connection_new ();
con = nm_simple_connection_new ();
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
g_object_set (s_con,
......
......@@ -37,6 +37,7 @@ libnm_core_headers = \
$(core)/nm-setting-wireless-security.h \
$(core)/nm-setting-wireless.h \
$(core)/nm-setting.h \
$(core)/nm-simple-connection.h \
$(core)/nm-utils.h \
$(core)/nm-vpn-dbus-interface.h
......@@ -78,6 +79,7 @@ libnm_core_sources = \
$(core)/nm-setting-wireless-security.c \
$(core)/nm-setting-wireless.c \
$(core)/nm-setting.c \
$(core)/nm-simple-connection.c \
$(core)/nm-utils.c \
$(core)/nm-value-transforms.c
......@@ -92,22 +92,18 @@ nm_connection_error_quark (void)
}
typedef struct {
NMConnection *self;
GHashTable *settings;
/* D-Bus path of the connection, if any */
char *path;
} NMConnectionPrivate;
#define NM_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_CONNECTION, NMConnectionPrivate))
G_DEFINE_TYPE (NMConnection, nm_connection, G_TYPE_OBJECT)
static NMConnectionPrivate *nm_connection_get_private (NMConnection *connection);
#define NM_CONNECTION_GET_PRIVATE(o) (nm_connection_get_private ((NMConnection *)o))
enum {
PROP_0,
PROP_PATH,
LAST_PROP
};
G_DEFINE_INTERFACE (NMConnection, nm_connection, G_TYPE_OBJECT)
enum {
SECRETS_UPDATED,
......@@ -1368,78 +1364,6 @@ nm_connection_get_virtual_iface_name (NMConnection *connection)
return nm_setting_get_virtual_iface_name (base);
}
/**
* nm_connection_new:
*
* Creates a new #NMConnection object with no #NMSetting objects.
*
* Returns: the new empty #NMConnection object
**/
NMConnection *
nm_connection_new (void)
{
return (NMConnection *) g_object_new (NM_TYPE_CONNECTION, NULL);
}
/**
* nm_connection_new_from_hash:
* @hash: (element-type utf8 GLib.HashTable): the #GHashTable describing
* the connection
* @error: on unsuccessful return, an error
*
* Creates a new #NMConnection from a hash table describing the connection. See
* nm_connection_to_hash() for a description of the expected hash table.
*
* Returns: the new #NMConnection object, populated with settings created
* from the values in the hash table, or %NULL if the connection failed to
* validate
**/
NMConnection *
nm_connection_new_from_hash (GHashTable *hash, GError **error)
{
NMConnection *connection;
g_return_val_if_fail (hash != NULL, NULL);
if (!validate_permissions_type (hash, error))
return NULL;
connection = nm_connection_new ();
if (!hash_to_connection (connection, hash, error)) {
g_object_unref (connection);
return NULL;
}
return connection;
}
/**
* nm_connection_duplicate:
* @connection: the #NMConnection to duplicate
*
* Duplicates a #NMConnection.
*
* Returns: (transfer full): a new #NMConnection containing the same settings and properties
* as the source #NMConnection
**/
NMConnection *
nm_connection_duplicate (NMConnection *connection)
{
NMConnection *dup;
GHashTableIter iter;
NMSetting *setting;
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
dup = nm_connection_new ();
nm_connection_set_path (dup, nm_connection_get_path (connection));
g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting))
nm_connection_add_setting (dup, nm_setting_duplicate (setting));
return dup;
}
/**
* nm_connection_get_uuid:
* @connection: the #NMConnection
......@@ -1965,103 +1889,41 @@ nm_connection_get_setting_vlan (NMConnection *connection)
/*************************************************************/
static void
nm_connection_init (NMConnection *connection)
{
NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
priv->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
}
static void
dispose (GObject *object)
nm_connection_private_free (NMConnectionPrivate *priv)
{
NMConnection *self = NM_CONNECTION (object);
NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (self);
NMConnection *self = priv->self;
GHashTableIter iter;
NMSetting *setting;
g_hash_table_iter_init (&iter, priv->settings);
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting))
g_signal_handlers_disconnect_by_func (setting, setting_changed_cb, self);
g_hash_table_iter_remove (&iter);
}
g_hash_table_destroy (priv->settings);
G_OBJECT_CLASS (nm_connection_parent_class)->dispose (object);
g_slice_free (NMConnectionPrivate, priv);
}
static void
finalize (GObject *object)
static NMConnectionPrivate *
nm_connection_get_private (NMConnection *connection)
{
NMConnection *connection = NM_CONNECTION (object);
NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
NMConnectionPrivate *priv;
g_hash_table_destroy (priv->settings);
g_free (priv->path);
priv = g_object_get_data (G_OBJECT (connection), "NMConnectionPrivate");
if (!priv) {
priv = g_slice_new0 (NMConnectionPrivate);
g_object_set_data_full (G_OBJECT (connection), "NMConnectionPrivate",
priv, (GDestroyNotify) nm_connection_private_free);
G_OBJECT_CLASS (nm_connection_parent_class)->finalize (object);
}
static void
set_property (GObject *object, guint prop_id,
const GValue *value, GParamSpec *pspec)
{
NMConnection *connection = NM_CONNECTION (object);
switch (prop_id) {
case PROP_PATH:
nm_connection_set_path (connection, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
priv->self = connection;
priv->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
}
}
static void
get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec)
{
NMConnection *connection = NM_CONNECTION (object);
switch (prop_id) {
case PROP_PATH:
g_value_set_string (value, nm_connection_get_path (connection));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
return priv;
}
static void
nm_connection_class_init (NMConnectionClass *klass)
nm_connection_default_init (NMConnectionInterface *iface)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
g_type_class_add_private (klass, sizeof (NMConnectionPrivate));
/* virtual methods */
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->dispose = dispose;
object_class->finalize = finalize;
/* Properties */
/**
* NMConnection:path:
*
* The connection's D-Bus path, used only by the calling process as a record
* of the D-Bus path of the connection as provided by a settings service.
**/
g_object_class_install_property
(object_class, PROP_PATH,
g_param_spec_string (NM_CONNECTION_PATH, "", "",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS));
/* Signals */
/**
......@@ -2075,9 +1937,9 @@ nm_connection_class_init (NMConnectionClass *klass)
*/
signals[SECRETS_UPDATED] =
g_signal_new (NM_CONNECTION_SECRETS_UPDATED,
G_OBJECT_CLASS_TYPE (object_class),
NM_TYPE_CONNECTION,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMConnectionClass, secrets_updated),
G_STRUCT_OFFSET (NMConnectionInterface, secrets_updated),
NULL, NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE, 1,
......@@ -2092,9 +1954,9 @@ nm_connection_class_init (NMConnectionClass *klass)
*/
signals[SECRETS_CLEARED] =
g_signal_new (NM_CONNECTION_SECRETS_CLEARED,
G_OBJECT_CLASS_TYPE (object_class),
NM_TYPE_CONNECTION,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMConnectionClass, secrets_cleared),
G_STRUCT_OFFSET (NMConnectionInterface, secrets_cleared),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
......@@ -2109,9 +1971,9 @@ nm_connection_class_init (NMConnectionClass *klass)
*/
signals[CHANGED] =
g_signal_new (NM_CONNECTION_CHANGED,
G_OBJECT_CLASS_TYPE (object_class),
NM_TYPE_CONNECTION,
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (NMConnectionClass, changed),
G_STRUCT_OFFSET (NMConnectionInterface, changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
......
......@@ -60,21 +60,16 @@
G_BEGIN_DECLS
#define NM_TYPE_CONNECTION (nm_connection_get_type ())
#define NM_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONNECTION, NMConnection))
#define NM_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CONNECTION, NMConnectionClass))
#define NM_IS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CONNECTION))
#define NM_IS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_CONNECTION))
#define NM_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_CONNECTION, NMConnectionClass))
#define NM_TYPE_CONNECTION (nm_connection_get_type ())
#define NM_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONNECTION, NMConnection))
#define NM_IS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CONNECTION))
#define NM_CONNECTION_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_CONNECTION, NMConnectionClass))
/* Signals */
#define NM_CONNECTION_SECRETS_UPDATED "secrets-updated"
#define NM_CONNECTION_SECRETS_CLEARED "secrets-cleared"
#define NM_CONNECTION_CHANGED "changed"
/* Properties */
#define NM_CONNECTION_PATH "path"
/**
* NMConnectionError:
* @NM_CONNECTION_ERROR_UNKNOWN: unknown or unclassified error
......@@ -115,15 +110,13 @@ GQuark nm_connection_error_quark (void);
/**
* NMConnection:
*
* The NMConnection struct contains only private data.
* It should only be accessed through the functions described below.
* NMConnection is the interface implemented by #NMRemoteConnection on the
* client side, and #NMSettingsConnection on the daemon side.
*/
typedef struct {
GObject parent;
} NMConnection;
typedef struct _NMConnection NMConnection;
typedef struct {
GObjectClass parent;
GTypeInterface parent;
/* Signals */
void (*secrets_updated) (NMConnection *connection,
......@@ -131,18 +124,10 @@ typedef struct {
void (*secrets_cleared) (NMConnection *connection);
void (*changed) (NMConnection *connection);
/*< private >*/
gpointer padding[8];
} NMConnectionClass;
} NMConnectionInterface;
GType nm_connection_get_type (void);
NMConnection *nm_connection_new (void);
NMConnection *nm_connection_new_from_hash (GHashTable *hash, GError **error);
NMConnection *nm_connection_duplicate (NMConnection *connection);
void nm_connection_add_setting (NMConnection *connection,
NMSetting *setting);
......
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2007 - 2008 Novell, Inc.
* Copyright 2007 - 2014 Red Hat, Inc.
*/
#include "nm-simple-connection.h"
static void nm_simple_connection_interface_init (NMConnectionInterface *iface);
G_DEFINE_TYPE_WITH_CODE (NMSimpleConnection, nm_simple_connection, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (NM_TYPE_CONNECTION, nm_simple_connection_interface_init);
)
static void
nm_simple_connection_init (NMSimpleConnection *self)
{
}
/**
* nm_simple_connection_new:
*
* Creates a new #NMSimpleConnection object with no #NMSetting objects. An
* #NMSimpleConnection does not directly represent a D-Bus-exported connection,
* but might be used in the process of creating a new one.
*
* Returns: (transfer full): the new empty #NMConnection object
**/
NMConnection *
nm_simple_connection_new (void)
{
return (NMConnection *) g_object_new (NM_TYPE_SIMPLE_CONNECTION, NULL);
}
/**
* nm_simple_connection_new_from_hash:
* @hash: (element-type utf8 GLib.HashTable): the #GHashTable describing
* the connection
* @error: on unsuccessful return, an error
*
* Creates a new #NMSimpleConnection from a hash table describing the
* connection. See nm_connection_to_hash() for a description of the expected
* hash table.
*
* Returns: (transfer full): the new #NMSimpleConnection object, populated with
* settings created from the values in the hash table, or %NULL if the
* connection failed to validate
**/
NMConnection *
nm_simple_connection_new_from_hash (GHashTable *hash, GError **error)
{
NMConnection *connection;
g_return_val_if_fail (hash != NULL, NULL);
connection = nm_simple_connection_new ();
if (!nm_connection_replace_settings (connection, hash, error)) {
g_object_unref (connection);
return NULL;
}
return connection;
}
/**
* nm_simple_connection_new_clone:
* @connection: the #NMConnection to clone
*
* Clones an #NMConnection as an #NMSimpleConnection.
*
* Returns: (transfer full): a new #NMConnection containing the same settings
* and properties as the source #NMConnection
**/
NMConnection *
nm_simple_connection_new_clone (NMConnection *connection)
{
NMConnection *clone;
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
clone = nm_simple_connection_new ();
nm_connection_set_path (clone, nm_connection_get_path (connection));
nm_connection_replace_settings_from_connection (clone, connection, NULL);
return clone;
}
static void
nm_simple_connection_class_init (NMSimpleConnectionClass *simple_class)
{
}
static void
nm_simple_connection_interface_init (NMConnectionInterface *iface)
{
}
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA.
*
* Copyright 2014 Red Hat, Inc.
*/
#ifndef __NM_SIMPLE_CONNECTION_H__
#define __NM_SIMPLE_CONNECTION_H__
#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
#error "Only <NetworkManager.h> can be included directly."
#endif
#include <nm-connection.h>