mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-07-23 19:24:38 +00:00
libnm-glib: simplify handling of object and object array properties
Add an "object_type" field to NMPropertiesInfo, and use that with DBUS_TYPE_G_OBJECT_PATH and DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH properties so that we don't need custom marshallers for each one. When creating an NMDevice or NMActiveConnection, we need to fetch an extra property first to figure out the exact subclass to use, so add a bit of infrastructure for that as well. Also, do that preprocessing asynchronously when processing a property change notification, so that it doesn't block the main loop.
This commit is contained in:
parent
5afcee4693
commit
cc90f1010e
|
@ -28,15 +28,25 @@
|
|||
#include "nm-object-private.h"
|
||||
#include "nm-types-private.h"
|
||||
#include "nm-device.h"
|
||||
#include "nm-device-private.h"
|
||||
#include "nm-connection.h"
|
||||
#include "nm-vpn-connection.h"
|
||||
|
||||
G_DEFINE_TYPE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJECT)
|
||||
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);
|
||||
|
||||
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);
|
||||
)
|
||||
|
||||
#define NM_ACTIVE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate))
|
||||
|
||||
static gboolean demarshal_devices (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
|
||||
|
||||
|
||||
typedef struct {
|
||||
gboolean disposed;
|
||||
DBusGProxy *proxy;
|
||||
|
@ -95,6 +105,104 @@ nm_active_connection_new (DBusGConnection *connection, const char *path)
|
|||
NULL);
|
||||
}
|
||||
|
||||
static GType
|
||||
nm_active_connection_type_for_path (DBusGConnection *connection,
|
||||
const char *path)
|
||||
{
|
||||
DBusGProxy *proxy;
|
||||
GError *error = NULL;
|
||||
GValue value = {0,};
|
||||
GType type;
|
||||
|
||||
proxy = dbus_g_proxy_new_for_name (connection,
|
||||
NM_DBUS_SERVICE,
|
||||
path,
|
||||
"org.freedesktop.DBus.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 = dbus_g_proxy_new_for_name (connection, NM_DBUS_SERVICE, path,
|
||||
"org.freedesktop.DBus.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);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_active_connection_get_connection:
|
||||
* @connection: a #NMActiveConnection
|
||||
|
@ -316,19 +424,6 @@ get_property (GObject *object,
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demarshal_devices (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
|
||||
{
|
||||
DBusGConnection *connection;
|
||||
|
||||
connection = nm_object_get_connection (object);
|
||||
if (!_nm_object_array_demarshal (value, (GPtrArray **) field, connection, nm_device_new))
|
||||
return FALSE;
|
||||
|
||||
_nm_object_queue_notify (object, NM_ACTIVE_CONNECTION_DEVICES);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
register_properties (NMActiveConnection *connection)
|
||||
{
|
||||
|
@ -337,7 +432,7 @@ register_properties (NMActiveConnection *connection)
|
|||
{ NM_ACTIVE_CONNECTION_CONNECTION, &priv->connection },
|
||||
{ NM_ACTIVE_CONNECTION_UUID, &priv->uuid },
|
||||
{ NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, &priv->specific_object },
|
||||
{ NM_ACTIVE_CONNECTION_DEVICES, &priv->devices, demarshal_devices },
|
||||
{ NM_ACTIVE_CONNECTION_DEVICES, &priv->devices, NULL, NM_TYPE_DEVICE },
|
||||
{ NM_ACTIVE_CONNECTION_STATE, &priv->state },
|
||||
{ NM_ACTIVE_CONNECTION_DEFAULT, &priv->is_default },
|
||||
{ NM_ACTIVE_CONNECTION_DEFAULT6, &priv->is_default6 },
|
||||
|
|
|
@ -235,62 +235,6 @@ update_wimax_status (NMClient *client, gboolean notify)
|
|||
}
|
||||
}
|
||||
|
||||
static GObject *
|
||||
new_active_connection (DBusGConnection *connection, const char *path)
|
||||
{
|
||||
DBusGProxy *proxy;
|
||||
GError *error = NULL;
|
||||
GValue value = {0,};
|
||||
GObject *object = NULL;
|
||||
|
||||
proxy = dbus_g_proxy_new_for_name (connection,
|
||||
NM_DBUS_SERVICE,
|
||||
path,
|
||||
"org.freedesktop.DBus.Properties");
|
||||
if (!proxy) {
|
||||
g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 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))
|
||||
object = nm_vpn_connection_new (connection, path);
|
||||
else
|
||||
object = nm_active_connection_new (connection, path);
|
||||
} else {
|
||||
g_warning ("Error in getting active connection 'Vpn' property: (%d) %s",
|
||||
error->code, error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_object_unref (proxy);
|
||||
return object;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demarshal_active_connections (NMObject *object,
|
||||
GParamSpec *pspec,
|
||||
GValue *value,
|
||||
gpointer field)
|
||||
{
|
||||
DBusGConnection *connection;
|
||||
|
||||
connection = nm_object_get_connection (object);
|
||||
if (!_nm_object_array_demarshal (value, (GPtrArray **) field, connection, new_active_connection))
|
||||
return FALSE;
|
||||
|
||||
_nm_object_queue_notify (object, NM_CLIENT_ACTIVE_CONNECTIONS);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
register_properties (NMClient *client)
|
||||
{
|
||||
|
@ -305,7 +249,7 @@ register_properties (NMClient *client)
|
|||
{ NM_CLIENT_WWAN_HARDWARE_ENABLED, &priv->wwan_hw_enabled },
|
||||
{ NM_CLIENT_WIMAX_ENABLED, &priv->wimax_enabled },
|
||||
{ NM_CLIENT_WIMAX_HARDWARE_ENABLED, &priv->wimax_hw_enabled },
|
||||
{ NM_CLIENT_ACTIVE_CONNECTIONS, &priv->active_connections, demarshal_active_connections },
|
||||
{ NM_CLIENT_ACTIVE_CONNECTIONS, &priv->active_connections, NULL, NM_TYPE_ACTIVE_CONNECTION },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
|
|
@ -29,8 +29,4 @@ DBusGConnection *nm_device_get_connection (NMDevice *device);
|
|||
const char *nm_device_get_path (NMDevice *device);
|
||||
DBusGProxy *nm_device_get_properties_proxy (NMDevice *device);
|
||||
|
||||
/* static methods */
|
||||
NMDeviceType nm_device_type_for_path (DBusGConnection *connection,
|
||||
const char *path);
|
||||
|
||||
#endif /* NM_DEVICE_PRIVATE_H */
|
||||
|
|
|
@ -40,8 +40,6 @@ G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE)
|
|||
|
||||
#define NM_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIFI, NMDeviceWifiPrivate))
|
||||
|
||||
static gboolean demarshal_active_ap (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
|
||||
|
||||
void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
|
||||
|
||||
typedef struct {
|
||||
|
@ -566,40 +564,6 @@ state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demarshal_active_ap (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
|
||||
{
|
||||
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object);
|
||||
const char *path;
|
||||
NMAccessPoint *ap = NULL;
|
||||
DBusGConnection *connection;
|
||||
|
||||
if (value) {
|
||||
if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
|
||||
return FALSE;
|
||||
|
||||
path = g_value_get_boxed (value);
|
||||
if (path) {
|
||||
ap = NM_ACCESS_POINT (_nm_object_cache_get (path));
|
||||
if (!ap) {
|
||||
connection = nm_object_get_connection (object);
|
||||
ap = NM_ACCESS_POINT (nm_access_point_new (connection, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->active_ap) {
|
||||
g_object_unref (priv->active_ap);
|
||||
priv->active_ap = NULL;
|
||||
}
|
||||
|
||||
if (ap)
|
||||
priv->active_ap = ap;
|
||||
|
||||
_nm_object_queue_notify (object, NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
register_properties (NMDeviceWifi *device)
|
||||
{
|
||||
|
@ -609,7 +573,7 @@ register_properties (NMDeviceWifi *device)
|
|||
{ NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, &priv->perm_hw_address },
|
||||
{ NM_DEVICE_WIFI_MODE, &priv->mode },
|
||||
{ NM_DEVICE_WIFI_BITRATE, &priv->rate },
|
||||
{ NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, &priv->active_ap, demarshal_active_ap },
|
||||
{ NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, &priv->active_ap, NULL, NM_TYPE_ACCESS_POINT },
|
||||
{ NM_DEVICE_WIFI_CAPABILITIES, &priv->wireless_caps },
|
||||
{ NULL },
|
||||
};
|
||||
|
|
|
@ -38,8 +38,6 @@ G_DEFINE_TYPE (NMDeviceWimax, nm_device_wimax, NM_TYPE_DEVICE)
|
|||
|
||||
#define NM_DEVICE_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxPrivate))
|
||||
|
||||
static gboolean demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
|
||||
|
||||
void _nm_device_wimax_set_wireless_enabled (NMDeviceWimax *wimax, gboolean enabled);
|
||||
|
||||
typedef struct {
|
||||
|
@ -552,47 +550,13 @@ state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
|
||||
{
|
||||
NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object);
|
||||
const char *path;
|
||||
NMWimaxNsp *nsp = NULL;
|
||||
DBusGConnection *connection;
|
||||
|
||||
if (value) {
|
||||
if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
|
||||
return FALSE;
|
||||
|
||||
path = g_value_get_boxed (value);
|
||||
if (path) {
|
||||
nsp = NM_WIMAX_NSP (_nm_object_cache_get (path));
|
||||
if (!nsp) {
|
||||
connection = nm_object_get_connection (object);
|
||||
nsp = NM_WIMAX_NSP (nm_wimax_nsp_new (connection, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->active_nsp) {
|
||||
g_object_unref (priv->active_nsp);
|
||||
priv->active_nsp = NULL;
|
||||
}
|
||||
|
||||
if (nsp)
|
||||
priv->active_nsp = nsp;
|
||||
|
||||
_nm_object_queue_notify (object, NM_DEVICE_WIMAX_ACTIVE_NSP);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
register_properties (NMDeviceWimax *wimax)
|
||||
{
|
||||
NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax);
|
||||
const NMPropertiesInfo property_info[] = {
|
||||
{ NM_DEVICE_WIMAX_HW_ADDRESS, &priv->hw_address },
|
||||
{ NM_DEVICE_WIMAX_ACTIVE_NSP, &priv->active_nsp, demarshal_active_nsp },
|
||||
{ NM_DEVICE_WIMAX_ACTIVE_NSP, &priv->active_nsp, NULL, NM_TYPE_WIMAX_NSP },
|
||||
{ NM_DEVICE_WIMAX_CENTER_FREQUENCY, &priv->center_freq },
|
||||
{ NM_DEVICE_WIMAX_RSSI, &priv->rssi },
|
||||
{ NM_DEVICE_WIMAX_CINR, &priv->cinr },
|
||||
|
|
|
@ -39,7 +39,17 @@
|
|||
#include "nm-marshal.h"
|
||||
#include "nm-dbus-glib-types.h"
|
||||
|
||||
G_DEFINE_TYPE (NMDevice, nm_device, NM_TYPE_OBJECT)
|
||||
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);
|
||||
|
||||
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);
|
||||
)
|
||||
|
||||
#define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate))
|
||||
|
||||
|
@ -107,176 +117,6 @@ nm_device_init (NMDevice *device)
|
|||
priv->state = NM_DEVICE_STATE_UNKNOWN;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demarshal_ip4_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
|
||||
const char *path;
|
||||
NMIP4Config *config = NULL;
|
||||
DBusGConnection *connection;
|
||||
|
||||
if (value) {
|
||||
if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
|
||||
return FALSE;
|
||||
|
||||
path = g_value_get_boxed (value);
|
||||
if (path) {
|
||||
config = NM_IP4_CONFIG (_nm_object_cache_get (path));
|
||||
if (!config) {
|
||||
connection = nm_object_get_connection (object);
|
||||
config = NM_IP4_CONFIG (nm_ip4_config_new (connection, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->ip4_config) {
|
||||
g_object_unref (priv->ip4_config);
|
||||
priv->ip4_config = NULL;
|
||||
}
|
||||
|
||||
if (config)
|
||||
priv->ip4_config = config;
|
||||
|
||||
_nm_object_queue_notify (object, NM_DEVICE_IP4_CONFIG);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demarshal_dhcp4_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
|
||||
const char *path;
|
||||
NMDHCP4Config *config = NULL;
|
||||
DBusGConnection *connection;
|
||||
|
||||
if (value) {
|
||||
if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
|
||||
return FALSE;
|
||||
|
||||
path = g_value_get_boxed (value);
|
||||
if (path) {
|
||||
config = NM_DHCP4_CONFIG (_nm_object_cache_get (path));
|
||||
if (!config) {
|
||||
connection = nm_object_get_connection (object);
|
||||
config = NM_DHCP4_CONFIG (nm_dhcp4_config_new (connection, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->dhcp4_config) {
|
||||
g_object_unref (priv->dhcp4_config);
|
||||
priv->dhcp4_config = NULL;
|
||||
}
|
||||
|
||||
if (config)
|
||||
priv->dhcp4_config = config;
|
||||
|
||||
_nm_object_queue_notify (object, NM_DEVICE_DHCP4_CONFIG);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demarshal_ip6_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
|
||||
const char *path;
|
||||
NMIP6Config *config = NULL;
|
||||
DBusGConnection *connection;
|
||||
|
||||
if (value) {
|
||||
if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
|
||||
return FALSE;
|
||||
|
||||
path = g_value_get_boxed (value);
|
||||
if (path) {
|
||||
config = NM_IP6_CONFIG (_nm_object_cache_get (path));
|
||||
if (!config) {
|
||||
connection = nm_object_get_connection (object);
|
||||
config = NM_IP6_CONFIG (nm_ip6_config_new (connection, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->ip6_config) {
|
||||
g_object_unref (priv->ip6_config);
|
||||
priv->ip6_config = NULL;
|
||||
}
|
||||
|
||||
if (config)
|
||||
priv->ip6_config = config;
|
||||
|
||||
_nm_object_queue_notify (object, NM_DEVICE_IP6_CONFIG);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demarshal_dhcp6_config (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
|
||||
const char *path;
|
||||
NMDHCP6Config *config = NULL;
|
||||
DBusGConnection *connection;
|
||||
|
||||
if (value) {
|
||||
if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
|
||||
return FALSE;
|
||||
|
||||
path = g_value_get_boxed (value);
|
||||
if (path) {
|
||||
config = NM_DHCP6_CONFIG (_nm_object_cache_get (path));
|
||||
if (!config) {
|
||||
connection = nm_object_get_connection (object);
|
||||
config = NM_DHCP6_CONFIG (nm_dhcp6_config_new (connection, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->dhcp6_config) {
|
||||
g_object_unref (priv->dhcp6_config);
|
||||
priv->dhcp6_config = NULL;
|
||||
}
|
||||
|
||||
if (config)
|
||||
priv->dhcp6_config = config;
|
||||
|
||||
_nm_object_queue_notify (object, NM_DEVICE_DHCP6_CONFIG);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
demarshal_active_connection (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
|
||||
{
|
||||
NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (object);
|
||||
const char *path;
|
||||
NMActiveConnection *active = NULL;
|
||||
DBusGConnection *connection;
|
||||
|
||||
if (value) {
|
||||
if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
|
||||
return FALSE;
|
||||
|
||||
path = g_value_get_boxed (value);
|
||||
if (path) {
|
||||
active = NM_ACTIVE_CONNECTION (_nm_object_cache_get (path));
|
||||
if (!active) {
|
||||
connection = nm_object_get_connection (object);
|
||||
active = NM_ACTIVE_CONNECTION (nm_active_connection_new (connection, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->active_connection) {
|
||||
g_object_unref (priv->active_connection);
|
||||
priv->active_connection = NULL;
|
||||
}
|
||||
|
||||
if (active)
|
||||
priv->active_connection = active;
|
||||
|
||||
_nm_object_queue_notify (object, NM_DEVICE_ACTIVE_CONNECTION);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
register_properties (NMDevice *device)
|
||||
{
|
||||
|
@ -289,12 +129,12 @@ register_properties (NMDevice *device)
|
|||
{ NM_DEVICE_CAPABILITIES, &priv->capabilities },
|
||||
{ NM_DEVICE_MANAGED, &priv->managed },
|
||||
{ NM_DEVICE_FIRMWARE_MISSING, &priv->firmware_missing },
|
||||
{ NM_DEVICE_IP4_CONFIG, &priv->ip4_config, demarshal_ip4_config },
|
||||
{ NM_DEVICE_DHCP4_CONFIG, &priv->dhcp4_config, demarshal_dhcp4_config },
|
||||
{ NM_DEVICE_IP6_CONFIG, &priv->ip6_config, demarshal_ip6_config },
|
||||
{ NM_DEVICE_DHCP6_CONFIG, &priv->dhcp6_config, demarshal_dhcp6_config },
|
||||
{ NM_DEVICE_IP4_CONFIG, &priv->ip4_config, NULL, NM_TYPE_IP4_CONFIG },
|
||||
{ NM_DEVICE_DHCP4_CONFIG, &priv->dhcp4_config, NULL, NM_TYPE_DHCP4_CONFIG },
|
||||
{ NM_DEVICE_IP6_CONFIG, &priv->ip6_config, NULL, NM_TYPE_IP6_CONFIG },
|
||||
{ NM_DEVICE_DHCP6_CONFIG, &priv->dhcp6_config, NULL, NM_TYPE_DHCP6_CONFIG },
|
||||
{ NM_DEVICE_STATE, &priv->state },
|
||||
{ NM_DEVICE_ACTIVE_CONNECTION, &priv->active_connection, demarshal_active_connection },
|
||||
{ NM_DEVICE_ACTIVE_CONNECTION, &priv->active_connection, NULL, NM_TYPE_ACTIVE_CONNECTION },
|
||||
|
||||
/* The D-Bus interface has this property, but we don't; register
|
||||
* it so that handle_property_changed() doesn't complain.
|
||||
|
@ -795,6 +635,62 @@ nm_device_class_init (NMDeviceClass *device_class)
|
|||
G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
|
||||
}
|
||||
|
||||
static GType
|
||||
nm_device_gtype_from_dtype (NMDeviceType dtype)
|
||||
{
|
||||
switch (dtype) {
|
||||
case NM_DEVICE_TYPE_ETHERNET:
|
||||
return NM_TYPE_DEVICE_ETHERNET;
|
||||
case NM_DEVICE_TYPE_WIFI:
|
||||
return NM_TYPE_DEVICE_WIFI;
|
||||
case NM_DEVICE_TYPE_MODEM:
|
||||
return NM_TYPE_DEVICE_MODEM;
|
||||
case NM_DEVICE_TYPE_BT:
|
||||
return NM_TYPE_DEVICE_BT;
|
||||
case NM_DEVICE_TYPE_WIMAX:
|
||||
return NM_TYPE_DEVICE_WIMAX;
|
||||
case NM_DEVICE_TYPE_INFINIBAND:
|
||||
return NM_TYPE_DEVICE_INFINIBAND;
|
||||
default:
|
||||
g_warning ("Unknown device type %d", dtype);
|
||||
return G_TYPE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static GType
|
||||
nm_device_type_for_path (DBusGConnection *connection,
|
||||
const char *path)
|
||||
{
|
||||
DBusGProxy *proxy;
|
||||
GError *err = NULL;
|
||||
GValue value = {0,};
|
||||
NMDeviceType nm_dtype;
|
||||
|
||||
proxy = dbus_g_proxy_new_for_name (connection,
|
||||
NM_DBUS_SERVICE,
|
||||
path,
|
||||
"org.freedesktop.DBus.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_object_unref (proxy);
|
||||
g_warning ("Error in get_property: %s\n", err->message);
|
||||
g_error_free (err);
|
||||
}
|
||||
g_object_unref (proxy);
|
||||
|
||||
nm_dtype = g_value_get_uint (&value);
|
||||
return nm_device_gtype_from_dtype (nm_dtype);
|
||||
}
|
||||
|
||||
/**
|
||||
* nm_device_new:
|
||||
* @connection: the #DBusGConnection
|
||||
|
@ -807,72 +703,75 @@ nm_device_class_init (NMDeviceClass *device_class)
|
|||
GObject *
|
||||
nm_device_new (DBusGConnection *connection, const char *path)
|
||||
{
|
||||
DBusGProxy *proxy;
|
||||
GError *err = NULL;
|
||||
GValue value = {0,};
|
||||
GType dtype = 0;
|
||||
NMDevice *device = NULL;
|
||||
NMDeviceType nm_dtype;
|
||||
GType dtype;
|
||||
|
||||
g_return_val_if_fail (connection != NULL, NULL);
|
||||
g_return_val_if_fail (path != NULL, NULL);
|
||||
|
||||
proxy = dbus_g_proxy_new_for_name (connection,
|
||||
NM_DBUS_SERVICE,
|
||||
path,
|
||||
"org.freedesktop.DBus.Properties");
|
||||
if (!proxy) {
|
||||
g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
|
||||
dtype = nm_device_type_for_path (connection, path);
|
||||
if (dtype == G_TYPE_INVALID)
|
||||
return NULL;
|
||||
|
||||
return g_object_new (dtype,
|
||||
NM_OBJECT_DBUS_CONNECTION, connection,
|
||||
NM_OBJECT_DBUS_PATH, path,
|
||||
NULL);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nm_dtype = g_value_get_uint (&value);
|
||||
switch (nm_dtype) {
|
||||
case NM_DEVICE_TYPE_ETHERNET:
|
||||
dtype = NM_TYPE_DEVICE_ETHERNET;
|
||||
break;
|
||||
case NM_DEVICE_TYPE_WIFI:
|
||||
dtype = NM_TYPE_DEVICE_WIFI;
|
||||
break;
|
||||
case NM_DEVICE_TYPE_MODEM:
|
||||
dtype = NM_TYPE_DEVICE_MODEM;
|
||||
break;
|
||||
case NM_DEVICE_TYPE_BT:
|
||||
dtype = NM_TYPE_DEVICE_BT;
|
||||
break;
|
||||
case NM_DEVICE_TYPE_WIMAX:
|
||||
dtype = NM_TYPE_DEVICE_WIMAX;
|
||||
break;
|
||||
case NM_DEVICE_TYPE_INFINIBAND:
|
||||
dtype = NM_TYPE_DEVICE_INFINIBAND;
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unknown device type %d", g_value_get_uint (&value));
|
||||
break;
|
||||
}
|
||||
|
||||
if (dtype) {
|
||||
device = (NMDevice *) g_object_new (dtype,
|
||||
NM_OBJECT_DBUS_CONNECTION, connection,
|
||||
NM_OBJECT_DBUS_PATH, path,
|
||||
NM_DEVICE_DEVICE_TYPE, nm_dtype,
|
||||
NULL);
|
||||
}
|
||||
|
||||
out:
|
||||
async_data->callback (type, async_data->user_data);
|
||||
g_object_unref (proxy);
|
||||
return G_OBJECT (device);
|
||||
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 = dbus_g_proxy_new_for_name (connection, NM_DBUS_SERVICE, path,
|
||||
"org.freedesktop.DBus.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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -923,9 +822,31 @@ nm_device_get_ip_iface (NMDevice *device)
|
|||
NMDeviceType
|
||||
nm_device_get_device_type (NMDevice *self)
|
||||
{
|
||||
NMDevicePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_TYPE_UNKNOWN);
|
||||
|
||||
return NM_DEVICE_GET_PRIVATE (self)->device_type;
|
||||
priv = NM_DEVICE_GET_PRIVATE (self);
|
||||
|
||||
/* Fill this in if it wasn't set at construct time */
|
||||
if (priv->device_type == NM_DEVICE_TYPE_UNKNOWN) {
|
||||
if (NM_IS_DEVICE_ETHERNET (self))
|
||||
priv->device_type = NM_DEVICE_TYPE_ETHERNET;
|
||||
else if (NM_IS_DEVICE_WIFI (self))
|
||||
priv->device_type = NM_DEVICE_TYPE_WIFI;
|
||||
else if (NM_IS_DEVICE_MODEM (self))
|
||||
priv->device_type = NM_DEVICE_TYPE_MODEM;
|
||||
else if (NM_IS_DEVICE_BT (self))
|
||||
priv->device_type = NM_DEVICE_TYPE_BT;
|
||||
else if (NM_IS_DEVICE_WIMAX (self))
|
||||
priv->device_type = NM_DEVICE_TYPE_WIMAX;
|
||||
else if (NM_IS_DEVICE_INFINIBAND (self))
|
||||
priv->device_type = NM_DEVICE_TYPE_INFINIBAND;
|
||||
else
|
||||
g_warn_if_reached ();
|
||||
}
|
||||
|
||||
return priv->device_type;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,12 +30,14 @@
|
|||
void _nm_object_ensure_inited (NMObject *object);
|
||||
|
||||
typedef gboolean (*PropertyMarshalFunc) (NMObject *, GParamSpec *, GValue *, gpointer);
|
||||
|
||||
typedef GObject * (*NMObjectCreatorFunc) (DBusGConnection *, const char *);
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
gpointer field;
|
||||
PropertyMarshalFunc func;
|
||||
GType object_type;
|
||||
} NMPropertiesInfo;
|
||||
|
||||
|
||||
|
@ -69,4 +71,12 @@ handle_ptr_array_return (GPtrArray *array)
|
|||
return array;
|
||||
}
|
||||
|
||||
/* object demarshalling support */
|
||||
typedef GType (*NMObjectTypeFunc) (DBusGConnection *, const char *);
|
||||
typedef void (*NMObjectTypeCallbackFunc) (GType, gpointer);
|
||||
typedef void (*NMObjectTypeAsyncFunc) (DBusGConnection *, const char *, NMObjectTypeCallbackFunc, gpointer);
|
||||
|
||||
void _nm_object_register_type_func (GType base_type, NMObjectTypeFunc type_func,
|
||||
NMObjectTypeAsyncFunc type_async_func);
|
||||
|
||||
#endif /* NM_OBJECT_PRIVATE_H */
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "nm-object-private.h"
|
||||
#include "nm-dbus-glib-types.h"
|
||||
#include "nm-glib-compat.h"
|
||||
#include "nm-types.h"
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
|
@ -37,8 +38,12 @@ G_DEFINE_ABSTRACT_TYPE (NMObject, nm_object, G_TYPE_OBJECT)
|
|||
|
||||
#define NM_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OBJECT, NMObjectPrivate))
|
||||
|
||||
static GHashTable *type_funcs, *type_async_funcs;
|
||||
|
||||
typedef struct {
|
||||
PropertyMarshalFunc func;
|
||||
GType object_type;
|
||||
|
||||
gpointer field;
|
||||
} PropertyInfo;
|
||||
|
||||
|
@ -192,6 +197,11 @@ nm_object_class_init (NMObjectClass *nm_object_class)
|
|||
|
||||
g_type_class_add_private (nm_object_class, sizeof (NMObjectPrivate));
|
||||
|
||||
if (!type_funcs) {
|
||||
type_funcs = g_hash_table_new (NULL, NULL);
|
||||
type_async_funcs = g_hash_table_new (NULL, NULL);
|
||||
}
|
||||
|
||||
/* virtual methods */
|
||||
object_class->constructor = constructor;
|
||||
object_class->set_property = set_property;
|
||||
|
@ -311,6 +321,81 @@ _nm_object_queue_notify (NMObject *object, const char *property)
|
|||
priv->notify_props = g_slist_prepend (priv->notify_props, g_strdup (property));
|
||||
}
|
||||
|
||||
void
|
||||
_nm_object_register_type_func (GType base_type, NMObjectTypeFunc type_func,
|
||||
NMObjectTypeAsyncFunc type_async_func)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
static GObject *
|
||||
_nm_object_create (GType type, DBusGConnection *connection, const char *path)
|
||||
{
|
||||
NMObjectTypeFunc type_func;
|
||||
|
||||
type_func = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
|
||||
if (type_func)
|
||||
type = type_func (connection, path);
|
||||
|
||||
return g_object_new (type,
|
||||
NM_OBJECT_DBUS_CONNECTION, connection,
|
||||
NM_OBJECT_DBUS_PATH, path,
|
||||
NULL);
|
||||
}
|
||||
|
||||
typedef void (*NMObjectCreateCallbackFunc) (GObject *, gpointer);
|
||||
typedef struct {
|
||||
DBusGConnection *connection;
|
||||
char *path;
|
||||
NMObjectCreateCallbackFunc callback;
|
||||
gpointer user_data;
|
||||
} NMObjectTypeAsyncData;
|
||||
|
||||
static void
|
||||
async_got_type (GType type, gpointer user_data)
|
||||
{
|
||||
NMObjectTypeAsyncData *async_data = user_data;
|
||||
GObject *object;
|
||||
|
||||
if (type != G_TYPE_INVALID) {
|
||||
object = g_object_new (type,
|
||||
NM_OBJECT_DBUS_CONNECTION, async_data->connection,
|
||||
NM_OBJECT_DBUS_PATH, async_data->path,
|
||||
NULL);
|
||||
} else
|
||||
object = NULL;
|
||||
|
||||
async_data->callback (object, async_data->user_data);
|
||||
|
||||
g_free (async_data->path);
|
||||
g_slice_free (NMObjectTypeAsyncData, async_data);
|
||||
}
|
||||
|
||||
static void
|
||||
_nm_object_create_async (GType type, DBusGConnection *connection, const char *path,
|
||||
NMObjectCreateCallbackFunc callback, gpointer user_data)
|
||||
{
|
||||
NMObjectTypeAsyncFunc type_async_func;
|
||||
NMObjectTypeAsyncData *async_data;
|
||||
|
||||
async_data = g_slice_new (NMObjectTypeAsyncData);
|
||||
async_data->connection = connection;
|
||||
async_data->path = g_strdup (path);
|
||||
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);
|
||||
else
|
||||
async_got_type (type, async_data);
|
||||
}
|
||||
|
||||
/* Stolen from dbus-glib */
|
||||
static char*
|
||||
wincaps_to_dash (const char *caps)
|
||||
|
@ -333,19 +418,155 @@ wincaps_to_dash (const char *caps)
|
|||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
NMObject *self;
|
||||
PropertyInfo *pi;
|
||||
|
||||
GObject **objects;
|
||||
int length, remaining;
|
||||
|
||||
gboolean array;
|
||||
const char *property_name;
|
||||
} ObjectCreatedData;
|
||||
|
||||
static void
|
||||
handle_property_changed (gpointer key, gpointer data, gpointer user_data)
|
||||
object_created (GObject *obj, gpointer user_data)
|
||||
{
|
||||
ObjectCreatedData *odata = user_data;
|
||||
NMObject *self = odata->self;
|
||||
PropertyInfo *pi = odata->pi;
|
||||
|
||||
/* We assume that on error, the creator_func printed something */
|
||||
|
||||
odata->objects[--odata->remaining] = obj;
|
||||
if (odata->remaining)
|
||||
return;
|
||||
|
||||
if (odata->array) {
|
||||
GPtrArray **array = pi->field;
|
||||
int i;
|
||||
|
||||
if (*array)
|
||||
g_boxed_free (NM_TYPE_OBJECT_ARRAY, *array);
|
||||
*array = g_ptr_array_sized_new (odata->length);
|
||||
for (i = 0; i < odata->length; i++) {
|
||||
if (odata->objects[i])
|
||||
g_ptr_array_add (*array, odata->objects[i]);
|
||||
}
|
||||
} else {
|
||||
GObject **obj_p = pi->field;
|
||||
|
||||
g_clear_object (obj_p);
|
||||
*obj_p = odata->objects[0];
|
||||
}
|
||||
|
||||
if (odata->property_name)
|
||||
_nm_object_queue_notify (self, odata->property_name);
|
||||
|
||||
g_object_unref (self);
|
||||
g_free (odata->objects);
|
||||
g_slice_free (ObjectCreatedData, odata);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_object_property (NMObject *self, const char *property_name, GValue *value,
|
||||
PropertyInfo *pi, gboolean synchronously)
|
||||
{
|
||||
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
|
||||
GObject *obj;
|
||||
const char *path;
|
||||
ObjectCreatedData *odata;
|
||||
|
||||
odata = g_slice_new (ObjectCreatedData);
|
||||
odata->self = g_object_ref (self);
|
||||
odata->pi = pi;
|
||||
odata->objects = g_new (GObject *, 1);
|
||||
odata->length = odata->remaining = 1;
|
||||
odata->array = FALSE;
|
||||
odata->property_name = property_name;
|
||||
|
||||
path = g_value_get_boxed (value);
|
||||
if (!strcmp (path, "/")) {
|
||||
object_created (NULL, odata);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
obj = G_OBJECT (_nm_object_cache_get (path));
|
||||
if (obj) {
|
||||
object_created (obj, odata);
|
||||
return TRUE;
|
||||
} else if (synchronously) {
|
||||
obj = _nm_object_create (pi->object_type, priv->connection, path);
|
||||
object_created (obj, odata);
|
||||
return obj != NULL;
|
||||
} else {
|
||||
_nm_object_create_async (pi->object_type, priv->connection, path,
|
||||
object_created, odata);
|
||||
/* Assume success */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_object_array_property (NMObject *self, const char *property_name, GValue *value,
|
||||
PropertyInfo *pi, gboolean synchronously)
|
||||
{
|
||||
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
|
||||
GObject *obj;
|
||||
GPtrArray *paths;
|
||||
GPtrArray **array = pi->field;
|
||||
const char *path;
|
||||
ObjectCreatedData *odata;
|
||||
int i;
|
||||
|
||||
paths = g_value_get_boxed (value);
|
||||
|
||||
odata = g_slice_new (ObjectCreatedData);
|
||||
odata->self = g_object_ref (self);
|
||||
odata->pi = pi;
|
||||
odata->objects = g_new0 (GObject *, paths->len);
|
||||
odata->length = odata->remaining = paths->len;
|
||||
odata->array = TRUE;
|
||||
odata->property_name = property_name;
|
||||
|
||||
for (i = 0; i < paths->len; i++) {
|
||||
path = paths->pdata[i];
|
||||
if (!strcmp (path, "/")) {
|
||||
/* FIXME: can't happen? */
|
||||
continue;
|
||||
}
|
||||
|
||||
obj = G_OBJECT (_nm_object_cache_get (path));
|
||||
if (obj) {
|
||||
object_created (obj, odata);
|
||||
} else if (synchronously) {
|
||||
obj = _nm_object_create (pi->object_type, priv->connection, path);
|
||||
object_created (obj, odata);
|
||||
} else {
|
||||
_nm_object_create_async (pi->object_type, priv->connection, path,
|
||||
object_created, odata);
|
||||
}
|
||||
}
|
||||
|
||||
if (!synchronously) {
|
||||
/* Assume success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return *array && ((*array)->len == paths->len);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_property_changed (NMObject *self, const char *dbus_name, GValue *value, gboolean synchronously)
|
||||
{
|
||||
NMObject *self = NM_OBJECT (user_data);
|
||||
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
|
||||
char *prop_name;
|
||||
PropertyInfo *pi;
|
||||
GParamSpec *pspec;
|
||||
gboolean success = FALSE, found = FALSE;
|
||||
GSList *iter;
|
||||
GValue *value = data;
|
||||
|
||||
prop_name = wincaps_to_dash ((char *) key);
|
||||
prop_name = wincaps_to_dash (dbus_name);
|
||||
|
||||
/* Iterate through the object and its parents to find the property */
|
||||
for (iter = priv->property_tables; iter; iter = g_slist_next (iter)) {
|
||||
|
@ -377,13 +598,18 @@ handle_property_changed (gpointer key, gpointer data, gpointer user_data)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Handle NULL object paths */
|
||||
if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)) {
|
||||
if (g_strcmp0 (g_value_get_boxed (value), "/") == 0)
|
||||
value = NULL;
|
||||
}
|
||||
if (pi->object_type) {
|
||||
if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
|
||||
success = handle_object_property (self, pspec->name, value, pi, synchronously);
|
||||
else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH))
|
||||
success = handle_object_array_property (self, pspec->name, value, pi, synchronously);
|
||||
else {
|
||||
g_warn_if_reached ();
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
success = (*(pi->func)) (self, pspec, value, pi->field);
|
||||
|
||||
success = (*(pi->func)) (self, pspec, value, pi->field);
|
||||
if (!success) {
|
||||
g_warning ("%s: failed to update property '%s' of object type %s.",
|
||||
__func__,
|
||||
|
@ -398,7 +624,12 @@ out:
|
|||
void
|
||||
_nm_object_process_properties_changed (NMObject *self, GHashTable *properties)
|
||||
{
|
||||
g_hash_table_foreach (properties, handle_property_changed, self);
|
||||
GHashTableIter iter;
|
||||
gpointer name, value;
|
||||
|
||||
g_hash_table_iter_init (&iter, properties);
|
||||
while (g_hash_table_iter_next (&iter, &name, &value))
|
||||
handle_property_changed (self, name, value, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -509,6 +740,7 @@ _nm_object_register_properties (NMObject *object,
|
|||
|
||||
pi = g_malloc0 (sizeof (PropertyInfo));
|
||||
pi->func = tmp->func ? tmp->func : demarshal_generic;
|
||||
pi->object_type = tmp->object_type;
|
||||
pi->field = tmp->field;
|
||||
g_hash_table_insert (instance, g_strdup (tmp->name), pi);
|
||||
}
|
||||
|
@ -591,7 +823,7 @@ _nm_object_reload_property (NMObject *object,
|
|||
return;
|
||||
}
|
||||
|
||||
handle_property_changed ((gpointer)prop_name, &value, object);
|
||||
handle_property_changed (object, prop_name, &value, TRUE);
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue