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:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user