mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-07 07:50:17 +01:00
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.
This commit is contained in:
parent
7840dde47b
commit
e84a52ea42
4 changed files with 198 additions and 38 deletions
|
|
@ -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",
|
||||
|
|
@ -981,22 +985,12 @@ 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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -669,6 +801,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)
|
||||
{
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue