libnm: move most of the subclass-type-deciding code into NMObject

NMObject has a system that lets devices and active connections get
created as the correct subtypes (NMDeviceFoo / NMActiveConnection vs
NMVpnConnection). But it was much more generic than it needed to be,
because NMDevice and NMActiveConnection both did the same thing (fetch
a D-Bus property and then look at its value). So move the
property-fetching part into NMObject, and only use the callback for
converting the property value to a GType.
This commit is contained in:
Dan Winship
2014-08-18 18:12:01 -04:00
parent b728d1fb70
commit b3c4917b0f
4 changed files with 116 additions and 220 deletions

View File

@@ -32,17 +32,13 @@
#include "nm-glib-compat.h"
#include "nm-dbus-helpers-private.h"
static GType _nm_active_connection_type_for_path (DBusGConnection *connection,
const char *path);
static void _nm_active_connection_type_for_path_async (DBusGConnection *connection,
const char *path,
NMObjectTypeCallbackFunc callback,
gpointer user_data);
static GType _nm_active_connection_decide_type (GValue *value);
G_DEFINE_TYPE_WITH_CODE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJECT,
_nm_object_register_type_func (g_define_type_id,
_nm_active_connection_type_for_path,
_nm_active_connection_type_for_path_async);
_nm_active_connection_decide_type,
NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
"Vpn");
)
#define NM_ACTIVE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate))
@@ -87,97 +83,13 @@ enum {
};
static GType
_nm_active_connection_type_for_path (DBusGConnection *connection,
const char *path)
_nm_active_connection_decide_type (GValue *value)
{
DBusGProxy *proxy;
GError *error = NULL;
GValue value = G_VALUE_INIT;
GType type;
proxy = _nm_dbus_new_proxy_for_connection (connection, path, DBUS_INTERFACE_PROPERTIES);
if (!proxy) {
g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
return G_TYPE_INVALID;
}
/* Have to create an NMVpnConnection if it's a VPN connection, otherwise
* a plain NMActiveConnection.
*/
if (dbus_g_proxy_call (proxy,
"Get", &error,
G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
G_TYPE_STRING, "Vpn",
G_TYPE_INVALID,
G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
if (g_value_get_boolean (&value))
type = NM_TYPE_VPN_CONNECTION;
else
type = NM_TYPE_ACTIVE_CONNECTION;
} else {
g_warning ("Error in getting active connection 'Vpn' property: (%d) %s",
error->code, error->message);
g_error_free (error);
type = G_TYPE_INVALID;
}
g_object_unref (proxy);
return type;
}
typedef struct {
DBusGConnection *connection;
NMObjectTypeCallbackFunc callback;
gpointer user_data;
} NMActiveConnectionAsyncData;
static void
async_got_type (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
NMActiveConnectionAsyncData *async_data = user_data;
GValue value = G_VALUE_INIT;
const char *path = dbus_g_proxy_get_path (proxy);
GError *error = NULL;
GType type;
if (dbus_g_proxy_end_call (proxy, call, &error,
G_TYPE_VALUE, &value,
G_TYPE_INVALID)) {
if (g_value_get_boolean (&value))
type = NM_TYPE_VPN_CONNECTION;
else
type = NM_TYPE_ACTIVE_CONNECTION;
} else {
g_warning ("%s: could not read properties for %s: %s", __func__, path, error->message);
type = G_TYPE_INVALID;
}
async_data->callback (type, async_data->user_data);
g_object_unref (proxy);
g_slice_free (NMActiveConnectionAsyncData, async_data);
}
static void
_nm_active_connection_type_for_path_async (DBusGConnection *connection,
const char *path,
NMObjectTypeCallbackFunc callback,
gpointer user_data)
{
NMActiveConnectionAsyncData *async_data;
DBusGProxy *proxy;
async_data = g_slice_new (NMActiveConnectionAsyncData);
async_data->connection = connection;
async_data->callback = callback;
async_data->user_data = user_data;
proxy = _nm_dbus_new_proxy_for_connection (connection, path, DBUS_INTERFACE_PROPERTIES);
dbus_g_proxy_begin_call (proxy, "Get",
async_got_type, async_data, NULL,
G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
G_TYPE_STRING, "Vpn",
G_TYPE_INVALID);
/* @value is the value of the o.fd.NM.ActiveConnection property "VPN" */
if (g_value_get_boolean (value))
return NM_TYPE_VPN_CONNECTION;
else
return NM_TYPE_ACTIVE_CONNECTION;
}
/**

View File

@@ -49,17 +49,14 @@
#include "nm-utils.h"
#include "nm-dbus-helpers-private.h"
static GType _nm_device_type_for_path (DBusGConnection *connection,
const char *path);
static void _nm_device_type_for_path_async (DBusGConnection *connection,
const char *path,
NMObjectTypeCallbackFunc callback,
gpointer user_data);
static GType _nm_device_decide_type (GValue *value);
gboolean connection_compatible (NMDevice *device, NMConnection *connection, GError **error);
G_DEFINE_TYPE_WITH_CODE (NMDevice, nm_device, NM_TYPE_OBJECT,
_nm_object_register_type_func (g_define_type_id, _nm_device_type_for_path,
_nm_device_type_for_path_async);
_nm_object_register_type_func (g_define_type_id,
_nm_device_decide_type,
NM_DBUS_INTERFACE_DEVICE,
"DeviceType");
)
#define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
@@ -865,90 +862,9 @@ _nm_device_set_device_type (NMDevice *device, NMDeviceType dtype)
}
static GType
_nm_device_type_for_path (DBusGConnection *connection,
const char *path)
_nm_device_decide_type (GValue *value)
{
DBusGProxy *proxy;
GError *err = NULL;
GValue value = G_VALUE_INIT;
NMDeviceType nm_dtype;
proxy = _nm_dbus_new_proxy_for_connection (connection, path, DBUS_INTERFACE_PROPERTIES);
if (!proxy) {
g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
return G_TYPE_INVALID;
}
if (!dbus_g_proxy_call (proxy,
"Get", &err,
G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
G_TYPE_STRING, "DeviceType",
G_TYPE_INVALID,
G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
g_warning ("Error in get_property: %s\n", err->message);
g_error_free (err);
g_object_unref (proxy);
return G_TYPE_INVALID;
}
g_object_unref (proxy);
nm_dtype = g_value_get_uint (&value);
return _nm_device_gtype_from_dtype (nm_dtype);
}
typedef struct {
DBusGConnection *connection;
NMObjectTypeCallbackFunc callback;
gpointer user_data;
} NMDeviceAsyncData;
static void
async_got_type (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
NMDeviceAsyncData *async_data = user_data;
GValue value = G_VALUE_INIT;
const char *path = dbus_g_proxy_get_path (proxy);
GError *error = NULL;
GType type;
if (dbus_g_proxy_end_call (proxy, call, &error,
G_TYPE_VALUE, &value,
G_TYPE_INVALID)) {
NMDeviceType dtype;
dtype = g_value_get_uint (&value);
type = _nm_device_gtype_from_dtype (dtype);
} else {
g_warning ("%s: could not read properties for %s: %s", __func__, path, error->message);
g_error_free (error);
type = G_TYPE_INVALID;
}
async_data->callback (type, async_data->user_data);
g_object_unref (proxy);
g_slice_free (NMDeviceAsyncData, async_data);
}
static void
_nm_device_type_for_path_async (DBusGConnection *connection,
const char *path,
NMObjectTypeCallbackFunc callback,
gpointer user_data)
{
NMDeviceAsyncData *async_data;
DBusGProxy *proxy;
async_data = g_slice_new (NMDeviceAsyncData);
async_data->connection = connection;
async_data->callback = callback;
async_data->user_data = user_data;
proxy = _nm_dbus_new_proxy_for_connection (connection, path, DBUS_INTERFACE_PROPERTIES);
dbus_g_proxy_begin_call (proxy, "Get",
async_got_type, async_data, NULL,
G_TYPE_STRING, NM_DBUS_INTERFACE_DEVICE,
G_TYPE_STRING, "DeviceType",
G_TYPE_INVALID);
return _nm_device_gtype_from_dtype (g_value_get_uint (value));
}
/**

View File

@@ -65,12 +65,12 @@ void _nm_object_set_property (NMObject *object,
GValue *value);
/* object demarshalling support */
typedef GType (*NMObjectTypeFunc) (DBusGConnection *, const char *);
typedef void (*NMObjectTypeCallbackFunc) (GType, gpointer);
typedef void (*NMObjectTypeAsyncFunc) (DBusGConnection *, const char *, NMObjectTypeCallbackFunc, gpointer);
typedef GType (*NMObjectDecideTypeFunc) (GValue *);
void _nm_object_register_type_func (GType base_type, NMObjectTypeFunc type_func,
NMObjectTypeAsyncFunc type_async_func);
void _nm_object_register_type_func (GType base_type,
NMObjectDecideTypeFunc type_func,
const char *interface,
const char *property);
#define NM_OBJECT_NM_RUNNING "nm-running-internal"
gboolean _nm_object_get_nm_running (NMObject *self);

View File

@@ -39,7 +39,13 @@ static gboolean debug = FALSE;
static void nm_object_initable_iface_init (GInitableIface *iface);
static void nm_object_async_initable_iface_init (GAsyncInitableIface *iface);
static GHashTable *type_funcs, *type_async_funcs;
typedef struct {
NMObjectDecideTypeFunc type_func;
char *interface;
char *property;
} NMObjectTypeFuncData;
static GHashTable *type_funcs;
typedef struct {
GSList *interfaces;
@@ -49,7 +55,6 @@ typedef struct {
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMObject, nm_object, G_TYPE_OBJECT,
type_funcs = g_hash_table_new (NULL, NULL);
type_async_funcs = g_hash_table_new (NULL, NULL);
g_type_add_class_private (g_define_type_id, sizeof (NMObjectClassPrivate));
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_object_initable_iface_init);
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_object_async_initable_iface_init);
@@ -586,27 +591,63 @@ _nm_object_queue_notify (NMObject *object, const char *property)
}
void
_nm_object_register_type_func (GType base_type, NMObjectTypeFunc type_func,
NMObjectTypeAsyncFunc type_async_func)
_nm_object_register_type_func (GType base_type,
NMObjectDecideTypeFunc type_func,
const char *interface,
const char *property)
{
NMObjectTypeFuncData *type_data;
g_return_if_fail (type_func != NULL);
g_return_if_fail (interface != NULL);
g_return_if_fail (property != NULL);
type_data = g_slice_new (NMObjectTypeFuncData);
type_data->type_func = type_func;
type_data->interface = g_strdup (interface);
type_data->property = g_strdup (property);
g_hash_table_insert (type_funcs,
GSIZE_TO_POINTER (base_type),
type_func);
g_hash_table_insert (type_async_funcs,
GSIZE_TO_POINTER (base_type),
type_async_func);
type_data);
}
static GObject *
_nm_object_create (GType type, DBusGConnection *connection, const char *path)
{
NMObjectTypeFunc type_func;
NMObjectTypeFuncData *type_data;
GObject *object;
GError *error = NULL;
type_func = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
if (type_func)
type = type_func (connection, path);
type_data = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
if (type_data) {
DBusGProxy *proxy;
GValue value = G_VALUE_INIT;
proxy = _nm_dbus_new_proxy_for_connection (connection, path, DBUS_INTERFACE_PROPERTIES);
if (!proxy) {
g_warning ("Could not create proxy for %s.", path);
return G_TYPE_INVALID;
}
if (!dbus_g_proxy_call (proxy,
"Get", &error,
G_TYPE_STRING, type_data->interface,
G_TYPE_STRING, type_data->property,
G_TYPE_INVALID,
G_TYPE_VALUE, &value,
G_TYPE_INVALID)) {
g_warning ("Could not fetch property '%s' of interface '%s' on %s: %s\n",
type_data->property, type_data->interface, path, error->message);
g_error_free (error);
g_object_unref (proxy);
return G_TYPE_INVALID;
}
g_object_unref (proxy);
type = type_data->type_func (&value);
g_value_unset (&value);
}
if (type == G_TYPE_INVALID) {
dbgmsg ("Could not create object for %s: unknown object type", path);
@@ -638,6 +679,7 @@ typedef struct {
char *path;
NMObjectCreateCallbackFunc callback;
gpointer user_data;
NMObjectTypeFuncData *type_data;
} NMObjectTypeAsyncData;
static void
@@ -650,7 +692,7 @@ create_async_complete (GObject *object, NMObjectTypeAsyncData *async_data)
}
static void
async_inited (GObject *object, GAsyncResult *result, gpointer user_data)
create_async_inited (GObject *object, GAsyncResult *result, gpointer user_data)
{
NMObjectTypeAsyncData *async_data = user_data;
GError *error = NULL;
@@ -681,9 +723,8 @@ async_inited (GObject *object, GAsyncResult *result, gpointer user_data)
}
static void
async_got_type (GType type, gpointer user_data)
create_async_got_type (NMObjectTypeAsyncData *async_data, GType type)
{
NMObjectTypeAsyncData *async_data = user_data;
GObject *object;
if (type == G_TYPE_INVALID) {
@@ -696,15 +737,39 @@ async_got_type (GType type, gpointer user_data)
NM_OBJECT_PATH, async_data->path,
NULL);
g_async_initable_init_async (G_ASYNC_INITABLE (object), G_PRIORITY_DEFAULT,
NULL, async_inited, async_data);
NULL, create_async_inited, async_data);
}
static void
create_async_got_property (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
NMObjectTypeAsyncData *async_data = user_data;
NMObjectTypeFuncData *type_data = async_data->type_data;
GValue value = G_VALUE_INIT;
GError *error = NULL;
GType type;
if (dbus_g_proxy_end_call (proxy, call, &error,
G_TYPE_VALUE, &value,
G_TYPE_INVALID)) {
type = type_data->type_func (&value);
g_value_unset (&value);
} else {
const char *path = dbus_g_proxy_get_path (proxy);
g_warning ("Could not fetch property '%s' of interface '%s' on %s: %s\n",
type_data->property, type_data->interface, path, error->message);
g_clear_error (&error);
type = G_TYPE_INVALID;
}
create_async_got_type (async_data, type);
}
static void
_nm_object_create_async (GType type, DBusGConnection *connection, const char *path,
NMObjectCreateCallbackFunc callback, gpointer user_data)
{
NMObjectTypeAsyncFunc type_async_func;
NMObjectTypeFunc type_func;
NMObjectTypeAsyncData *async_data;
async_data = g_slice_new (NMObjectTypeAsyncData);
@@ -712,17 +777,20 @@ _nm_object_create_async (GType type, DBusGConnection *connection, const char *pa
async_data->callback = callback;
async_data->user_data = user_data;
type_async_func = g_hash_table_lookup (type_async_funcs, GSIZE_TO_POINTER (type));
if (type_async_func) {
type_async_func (connection, path, async_got_type, async_data);
async_data->type_data = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
if (async_data->type_data) {
DBusGProxy *proxy;
proxy = _nm_dbus_new_proxy_for_connection (connection, path, DBUS_INTERFACE_PROPERTIES);
dbus_g_proxy_begin_call (proxy, "Get",
create_async_got_property, async_data, NULL,
G_TYPE_STRING, async_data->type_data->interface,
G_TYPE_STRING, async_data->type_data->property,
G_TYPE_INVALID);
return;
}
type_func = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
if (type_func)
type = type_func (connection, path);
async_got_type (type, async_data);
create_async_got_type (async_data, type);
}
/* Stolen from dbus-glib */