summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-04-22 11:05:31 +0200
committerThomas Haller <thaller@redhat.com>2017-05-11 18:57:23 +0200
commit5a2151937db1c37ce79d1bd90f524eee73283157 (patch)
treeffdb6bd588c53b6c101b8de905f595ecc82a961a
parent52fe0f9066edb079aa074ea13730b102c397aaca (diff)
downloadNetworkManager-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.c61
-rw-r--r--src/devices/wwan/libnm-wwan.ver4
-rw-r--r--src/devices/wwan/nm-modem-manager.c164
-rw-r--r--src/devices/wwan/nm-modem-manager.h7
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__ */