diff options
author | Thomas Haller <thaller@redhat.com> | 2017-04-22 11:05:31 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-05-11 18:57:23 +0200 |
commit | 5a2151937db1c37ce79d1bd90f524eee73283157 (patch) | |
tree | ffdb6bd588c53b6c101b8de905f595ecc82a961a | |
parent | 52fe0f9066edb079aa074ea13730b102c397aaca (diff) | |
download | NetworkManager-5a2151937db1c37ce79d1bd90f524eee73283157.tar.gz |
bt: track name-owner changes via NMModemManager and create D-Bus proxy asynchronously
Fix two issues of the previous code:
- the D-Bus proxy for the modem manager should not get created
synchronously.
- NMModemManager is a singleton, let it track the name-owner
change and the D-Bus proxy, instead of having one per NMDeviceBt.
-rw-r--r-- | src/devices/bluetooth/nm-device-bt.c | 61 | ||||
-rw-r--r-- | src/devices/wwan/libnm-wwan.ver | 4 | ||||
-rw-r--r-- | src/devices/wwan/nm-modem-manager.c | 164 | ||||
-rw-r--r-- | src/devices/wwan/nm-modem-manager.h | 7 |
4 files changed, 198 insertions, 38 deletions
diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index 86ee7f9780..3402532fca 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -64,7 +64,8 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; typedef struct { - GDBusProxy *mm_proxy; + NMModemManager *modem_manager; + gboolean mm_running; NMBluezDevice *bt_device; @@ -966,9 +967,12 @@ is_available (NMDevice *dev, NMDeviceCheckDevAvailableFlags flags) } static void -set_mm_running (NMDeviceBt *self, gboolean running) +set_mm_running (NMDeviceBt *self) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); + gboolean running; + + running = (nm_modem_manager_name_owner_get (priv->modem_manager) != NULL); if (priv->mm_running != running) { _LOGD (LOGD_BT, "ModemManager now %s", @@ -982,21 +986,11 @@ set_mm_running (NMDeviceBt *self, gboolean running) } static void -mm_name_owner_changed (NMDeviceBt *self) -{ - NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - gs_free char *owner = NULL; - - owner = g_dbus_proxy_get_name_owner (priv->mm_proxy); - set_mm_running (self, owner != NULL); -} - -static void mm_name_owner_changed_cb (GObject *object, GParamSpec *pspec, - NMDeviceBt *self) + gpointer user_data) { - mm_name_owner_changed (self); + set_mm_running (user_data); } /*****************************************************************************/ @@ -1063,30 +1057,18 @@ constructed (GObject *object) NMDeviceBt *self = NM_DEVICE_BT (object); NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); const char *my_hwaddr; - gs_free_error GError *error = NULL; - - priv->mm_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | - G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NULL, - NM_MODEM_MANAGER_MM_DBUS_SERVICE, - NM_MODEM_MANAGER_MM_DBUS_PATH, - NM_MODEM_MANAGER_MM_DBUS_INTERFACE, - NULL, &error); - if (priv->mm_proxy) { - g_signal_connect (priv->mm_proxy, "notify::g-name-owner", - G_CALLBACK (mm_name_owner_changed_cb), - self); - mm_name_owner_changed (self); - } else { - _LOGW (LOGD_MB, "Could not create proxy for '%s': %s", - NM_MODEM_MANAGER_MM_DBUS_SERVICE, error->message); - g_clear_error (&error); - } G_OBJECT_CLASS (nm_device_bt_parent_class)->constructed (object); + priv->modem_manager = g_object_ref (nm_modem_manager_get ()); + + nm_modem_manager_name_owner_ref (priv->modem_manager); + + g_signal_connect (priv->modem_manager, + "notify::"NM_MODEM_MANAGER_NAME_OWNER, + G_CALLBACK (mm_name_owner_changed_cb), + self); + if (priv->bt_device) { /* Watch for BT device property changes */ g_signal_connect (priv->bt_device, "notify::" NM_BLUEZ_DEVICE_CONNECTED, @@ -1100,6 +1082,8 @@ constructed (GObject *object) priv->bdaddr = g_strdup (my_hwaddr); else g_warn_if_reached (); + + set_mm_running (self); } NMDevice * @@ -1137,9 +1121,10 @@ dispose (GObject *object) g_signal_handlers_disconnect_matched (priv->bt_device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object); - if (priv->mm_proxy) { - g_signal_handlers_disconnect_by_func (priv->mm_proxy, G_CALLBACK (mm_name_owner_changed_cb), object); - g_clear_object (&priv->mm_proxy); + if (priv->modem_manager) { + g_signal_handlers_disconnect_by_func (priv->modem_manager, G_CALLBACK (mm_name_owner_changed_cb), object); + nm_modem_manager_name_owner_unref (priv->modem_manager); + g_clear_object (&priv->modem_manager); } modem_cleanup (NM_DEVICE_BT (object)); diff --git a/src/devices/wwan/libnm-wwan.ver b/src/devices/wwan/libnm-wwan.ver index eb577aafb7..6efcb03fa7 100644 --- a/src/devices/wwan/libnm-wwan.ver +++ b/src/devices/wwan/libnm-wwan.ver @@ -20,7 +20,11 @@ global: nm_modem_get_type; nm_modem_get_uid; nm_modem_ip4_pre_commit; + nm_modem_manager_get; nm_modem_manager_get_type; + nm_modem_manager_name_owner_get; + nm_modem_manager_name_owner_ref; + nm_modem_manager_name_owner_unref; nm_modem_owns_port; nm_modem_set_mm_enabled; nm_modem_stage3_ip4_config_start; diff --git a/src/devices/wwan/nm-modem-manager.c b/src/devices/wwan/nm-modem-manager.c index d6a515077a..b5aa60c87a 100644 --- a/src/devices/wwan/nm-modem-manager.c +++ b/src/devices/wwan/nm-modem-manager.c @@ -45,6 +45,10 @@ /*****************************************************************************/ +NM_GOBJECT_PROPERTIES_DEFINE (NMModemManager, + PROP_NAME_OWNER, +); + enum { MODEM_ADDED, LAST_SIGNAL, @@ -65,6 +69,11 @@ typedef struct { gulong handle_object_added_id; gulong handle_object_removed_id; guint relaunch_id; + + GDBusProxy *proxy; + GCancellable *proxy_cancellable; + guint proxy_ref_count; + char *proxy_name_owner; } modm; #if WITH_OFONO @@ -435,6 +444,129 @@ modm_schedule_manager_relaunch (NMModemManager *self, /*****************************************************************************/ +static void +modm_proxy_name_owner_reset (NMModemManager *self) +{ + NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self); + char *name = NULL; + + if (priv->modm.proxy) + name = g_dbus_proxy_get_name_owner (priv->modm.proxy); + + if (nm_streq0 (priv->modm.proxy_name_owner, name)) { + g_free (name); + return; + } + g_free (priv->modm.proxy_name_owner); + priv->modm.proxy_name_owner = name; + + _notify (self, PROP_NAME_OWNER); +} + +static void +modm_proxy_name_owner_changed_cb (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + modm_proxy_name_owner_reset (user_data); +} + +static void +modm_proxy_new_cb (GObject *source_object, + GAsyncResult *result, + gpointer user_data) +{ + NMModemManager *self; + NMModemManagerPrivate *priv; + GDBusProxy *proxy; + gs_free_error GError *error = NULL; + + proxy = g_dbus_proxy_new_for_bus_finish (result, &error); + if ( !proxy + && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + self = user_data; + priv = NM_MODEM_MANAGER_GET_PRIVATE (self); + + g_clear_object (&priv->modm.proxy_cancellable); + + if (!proxy) { + _LOGW ("could not obtain D-Bus proxy for ModemManager: %s", error->message); + return; + } + + priv->modm.proxy = proxy; + g_signal_connect (priv->modm.proxy, "notify::g-name-owner", + G_CALLBACK (modm_proxy_name_owner_changed_cb), self); + + modm_proxy_name_owner_reset (self); +} + +void +nm_modem_manager_name_owner_ref (NMModemManager *self) +{ + NMModemManagerPrivate *priv; + + g_return_if_fail (NM_IS_MODEM_MANAGER (self)); + + priv = NM_MODEM_MANAGER_GET_PRIVATE (self); + + if (priv->modm.proxy_ref_count++ > 0) { + /* only try once to create the proxy. If proxy creation + * for the first "ref" failed, it's unclear what to do. + * The proxy is hosed. */ + return; + } + + nm_assert (!priv->modm.proxy && !priv->modm.proxy_cancellable); + + priv->modm.proxy_cancellable = g_cancellable_new (); + + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES + | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS + | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + NM_MODEM_MANAGER_MM_DBUS_SERVICE, + NM_MODEM_MANAGER_MM_DBUS_PATH, + NM_MODEM_MANAGER_MM_DBUS_INTERFACE, + priv->modm.proxy_cancellable, + modm_proxy_new_cb, + self); +} + +void +nm_modem_manager_name_owner_unref (NMModemManager *self) +{ + NMModemManagerPrivate *priv; + + g_return_if_fail (NM_IS_MODEM_MANAGER (self)); + + priv = NM_MODEM_MANAGER_GET_PRIVATE (self); + + g_return_if_fail (priv->modm.proxy_ref_count > 0); + + if (--priv->modm.proxy_ref_count > 0) + return; + + nm_clear_g_cancellable (&priv->modm.proxy_cancellable); + g_clear_object (&priv->modm.proxy); + + modm_proxy_name_owner_reset (self); +} + +const char * +nm_modem_manager_name_owner_get (NMModemManager *self) +{ + g_return_val_if_fail (NM_IS_MODEM_MANAGER (self), NULL); + nm_assert (NM_MODEM_MANAGER_GET_PRIVATE (self)->modm.proxy_ref_count > 0); + + return NM_MODEM_MANAGER_GET_PRIVATE (self)->modm.proxy_name_owner; +} + +/*****************************************************************************/ + #if WITH_OFONO static void @@ -670,6 +802,25 @@ bus_get_ready (GObject *source, /*****************************************************************************/ static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMModemManager *self = NM_MODEM_MANAGER (object); + NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_NAME_OWNER: + g_value_set_string (value, priv->modm.proxy_name_owner); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void nm_modem_manager_init (NMModemManager *self) { NMModemManagerPrivate *priv = NM_MODEM_MANAGER_GET_PRIVATE (self); @@ -695,6 +846,10 @@ dispose (GObject *object) nm_clear_g_source (&priv->modm.relaunch_id); + nm_clear_g_cancellable (&priv->modm.proxy_cancellable); + g_clear_object (&priv->modm.proxy); + nm_clear_g_free (&priv->modm.proxy_name_owner); + modm_clear_manager (self); #if WITH_OFONO @@ -723,6 +878,15 @@ nm_modem_manager_class_init (NMModemManagerClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->dispose = dispose; + object_class->get_property = get_property; + + obj_properties[PROP_NAME_OWNER] = + g_param_spec_string (NM_MODEM_MANAGER_NAME_OWNER, "", "", + NULL, + G_PARAM_READABLE + | G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); signals[MODEM_ADDED] = g_signal_new (NM_MODEM_MANAGER_MODEM_ADDED, diff --git a/src/devices/wwan/nm-modem-manager.h b/src/devices/wwan/nm-modem-manager.h index 84eb232e98..5f913083a9 100644 --- a/src/devices/wwan/nm-modem-manager.h +++ b/src/devices/wwan/nm-modem-manager.h @@ -34,6 +34,8 @@ #define NM_MODEM_MANAGER_MODEM_ADDED "modem-added" +#define NM_MODEM_MANAGER_NAME_OWNER "name-owner" + #define NM_MODEM_MANAGER_MM_DBUS_SERVICE "org.freedesktop.ModemManager1" #define NM_MODEM_MANAGER_MM_DBUS_PATH "/org/freedesktop/ModemManager1" #define NM_MODEM_MANAGER_MM_DBUS_INTERFACE "org.freedesktop.ModemManager1" @@ -45,4 +47,9 @@ GType nm_modem_manager_get_type (void); NMModemManager *nm_modem_manager_get (void); +void nm_modem_manager_name_owner_ref (NMModemManager *self); +void nm_modem_manager_name_owner_unref (NMModemManager *self); + +const char *nm_modem_manager_name_owner_get (NMModemManager *self); + #endif /* __NETWORKMANAGER_MODEM_MANAGER_H__ */ |