Commit e79f1b62 authored by Thomas Haller's avatar Thomas Haller

bluez: merge branch 'th/bluez-rework-2'

NetworkManager/NetworkManager!251
parents d19a403f 4154d961
Pipeline #65521 passed with stages
in 46 minutes and 5 seconds
......@@ -206,6 +206,7 @@ test-*.trs
/src/NetworkManager
/src/NetworkManager.ver
/src/devices/bluetooth/tests/nm-bt-test
/src/devices/tests/test-acd
/src/devices/tests/test-lldp
/src/devices/wifi/tests/test-devices-wifi
......
......@@ -3408,18 +3408,41 @@ EXTRA_DIST += \
if WITH_MODEM_MANAGER_1
noinst_LTLIBRARIES += src/devices/bluetooth/libnm-bluetooth-utils.la
src_devices_bluetooth_libnm_bluetooth_utils_la_SOURCES = \
src/devices/bluetooth/nm-bluez-common.h \
src/devices/bluetooth/nm-bt-error.c \
src/devices/bluetooth/nm-bt-error.h \
$(NULL)
src_devices_bluetooth_libnm_bluetooth_utils_la_CPPFLAGS = \
$(src_cppflags_base) \
$(NULL)
src_devices_bluetooth_libnm_bluetooth_utils_la_LIBADD = \
$(GLIB_LIBS) \
$(NULL)
if WITH_BLUEZ5_DUN
src_devices_bluetooth_libnm_bluetooth_utils_la_SOURCES += \
src/devices/bluetooth/nm-bluez5-dun.c \
src/devices/bluetooth/nm-bluez5-dun.h \
$(NULL)
src_devices_bluetooth_libnm_bluetooth_utils_la_CPPFLAGS += $(BLUEZ5_CFLAGS)
src_devices_bluetooth_libnm_bluetooth_utils_la_LIBADD += $(BLUEZ5_LIBS)
endif
$(src_devices_bluetooth_libnm_bluetooth_utils_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
###############################################################################
core_plugins += src/devices/bluetooth/libnm-device-plugin-bluetooth.la
src_devices_bluetooth_libnm_device_plugin_bluetooth_la_SOURCES = \
src/devices/bluetooth/nm-bluez-manager.c \
src/devices/bluetooth/nm-bluez-common.h \
src/devices/bluetooth/nm-bluez-device.c \
src/devices/bluetooth/nm-bluez-device.h \
src/devices/bluetooth/nm-bluez5-manager.c \
src/devices/bluetooth/nm-bluez5-manager.h \
src/devices/bluetooth/nm-bt-error.h \
src/devices/bluetooth/nm-bt-error.c \
\
src/devices/bluetooth/nm-bluez-manager.h \
src/devices/bluetooth/nm-device-bt.c \
src/devices/bluetooth/nm-device-bt.h \
$(NULL)
......@@ -3431,18 +3454,30 @@ src_devices_bluetooth_libnm_device_plugin_bluetooth_la_LDFLAGS = \
-Wl,--version-script="$(srcdir)/linker-script-devices.ver"
src_devices_bluetooth_libnm_device_plugin_bluetooth_la_LIBADD = \
src/devices/bluetooth/libnm-bluetooth-utils.la \
src/devices/wwan/libnm-wwan.la \
$(GLIB_LIBS)
$(GLIB_LIBS) \
$(NULL)
if WITH_BLUEZ5_DUN
src_devices_bluetooth_libnm_device_plugin_bluetooth_la_CPPFLAGS += $(BLUEZ5_CFLAGS)
$(src_devices_bluetooth_libnm_device_plugin_bluetooth_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
src_devices_bluetooth_libnm_device_plugin_bluetooth_la_SOURCES += \
src/devices/bluetooth/nm-bluez5-dun.c \
src/devices/bluetooth/nm-bluez5-dun.h
###############################################################################
src_devices_bluetooth_libnm_device_plugin_bluetooth_la_LIBADD += $(BLUEZ5_LIBS)
endif
check_programs_norun += \
src/devices/bluetooth/tests/nm-bt-test
src_devices_bluetooth_tests_nm_bt_test_CPPFLAGS = \
$(src_cppflags_test) \
$(NULL)
src_devices_bluetooth_tests_nm_bt_test_LDADD = \
src/devices/bluetooth/libnm-bluetooth-utils.la \
src/libNetworkManager.la \
$(GLIB_LIBS) \
$(NULL)
$(src_devices_bluetooth_tests_nm_bt_test_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
###############################################################################
check-local-devices-bluetooth: src/devices/bluetooth/libnm-device-plugin-bluetooth.la
$(srcdir)/tools/check-exports.sh $(builddir)/src/devices/bluetooth/.libs/libnm-device-plugin-bluetooth.so "$(srcdir)/linker-script-devices.ver"
......
......@@ -131,6 +131,10 @@ _nm_setting_secret_flags_valid (NMSettingSecretFlags flags)
/*****************************************************************************/
const char *nm_bluetooth_capability_to_string (NMBluetoothCapabilities capabilities, char *buf, gsize len);
/*****************************************************************************/
typedef enum { /*< skip >*/
NM_SETTING_PARSE_FLAGS_NONE = 0,
NM_SETTING_PARSE_FLAGS_STRICT = 1LL << 0,
......
......@@ -5812,6 +5812,14 @@ nm_utils_version (void)
/*****************************************************************************/
NM_UTILS_FLAGS2STR_DEFINE (nm_bluetooth_capability_to_string, NMBluetoothCapabilities,
NM_UTILS_FLAGS2STR (NM_BT_CAPABILITY_NONE, "NONE"),
NM_UTILS_FLAGS2STR (NM_BT_CAPABILITY_DUN, "DUN"),
NM_UTILS_FLAGS2STR (NM_BT_CAPABILITY_NAP, "NAP"),
)
/*****************************************************************************/
/**
* nm_utils_base64secret_decode:
* @base64_key: the (possibly invalid) base64 encode key.
......
......@@ -587,6 +587,28 @@ Connection 'ethernet-4' (de89cdeb-a3e1-4d53-8fa0-c22546c775f4) successfully
</para>
</example>
<example><title>Bluetooth connection profiles</title>
<para>NetworkManger supports both connecting to NAP and DUN devices as a client. It also
supports sharing the network via a NAP server.
</para>
<para>For NAP client connections, NetworkManager automatically creates a suitable in-memory profile
for paired devices if none is available. You may use that generated profile directly, but you may also modify
and persist it, which will prevent to automatically re-create it. You may also create a profile from scratch.
For example, the following uses DHCP and IPv6 autoconf for address configuration:
</para>
<screen><prompt>$ </prompt><userinput>nmcli connection add type bluetooth con-name "Profile for My Bluetooth Device (NAP)" autoconnect no bluetooth.type panu bluetooth.bdaddr "$BDADDR"</userinput></screen>
<para>For DUN connections, the user needs to configure modem settings and hence no profile
gets created automatically. The modem settings depend on your device and you either need
a "gsm" or a "csma" section. For example,
</para>
<screen><prompt>$ </prompt><userinput>nmcli connection add type bluetooth con-name "Profile for My Bluetooth Device (DUN)" autoconnect no bluetooth.type dun bluetooth.bdaddr "$BDADDR" gsm.apn apn.com</userinput></screen>
<para>Finally, you can create a bluetooth hotspot. BlueZ implements those as a bridge device,
so such profiles also have a bridge section. Also, you probably want to set IP methods as "shared",
so that clients get automatic IP addressing. Note that the "shared" IPv4 method requires dnsmasq to be available.
</para>
<screen><prompt>$ </prompt><userinput>nmcli connection add type bluetooth con-name "My Bluetooth Hotspot" autoconnect no ifname btnap0 bluetooth.type nap ipv4.method shared ipv6.method shared</userinput></screen>
</example>
</refsect1>
<refsect1>
......
......@@ -148,7 +148,7 @@ src/dhcp/nm-dhcp-dhclient-utils.c
src/dhcp/nm-dhcp-manager.c
src/dns/nm-dns-manager.c
src/devices/adsl/nm-device-adsl.c
src/devices/bluetooth/nm-bluez-device.c
src/devices/bluetooth/nm-bluez-manager.c
src/devices/bluetooth/nm-device-bt.c
src/devices/nm-device-6lowpan.c
src/devices/nm-device-bond.c
......
......@@ -53,3 +53,195 @@ nm_dbus_connection_call_get_name_owner (GDBusConnection *dbus_connection,
_nm_dbus_connection_call_get_name_owner_cb,
nm_utils_user_data_pack (user_data, callback));
}
/*****************************************************************************/
static void
_nm_dbus_connection_call_get_all_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
gs_unref_variant GVariant *ret = NULL;
gs_free_error GError *error = NULL;
gpointer orig_user_data;
NMDBusConnectionCallDefaultCb callback;
nm_utils_user_data_unpack (user_data, &orig_user_data, &callback);
ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error);
nm_assert ((!!ret) != (!!error));
callback (ret, error, orig_user_data);
}
void
nm_dbus_connection_call_get_all (GDBusConnection *dbus_connection,
const char *bus_name,
const char *object_path,
const char *interface_name,
int timeout_msec,
GCancellable *cancellable,
NMDBusConnectionCallDefaultCb callback,
gpointer user_data)
{
nm_assert (callback);
g_dbus_connection_call (dbus_connection,
bus_name,
object_path,
DBUS_INTERFACE_PROPERTIES,
"GetAll",
g_variant_new ("(s)", interface_name),
G_VARIANT_TYPE ("(a{sv})"),
G_DBUS_CALL_FLAGS_NONE,
timeout_msec,
cancellable,
_nm_dbus_connection_call_get_all_cb,
nm_utils_user_data_pack (user_data, callback));
}
/*****************************************************************************/
typedef struct {
NMDBusConnectionSignalObjectMangerCb callback;
gpointer user_data;
GDestroyNotify user_data_free_func;
} SubscribeObjectManagerData;
static void
_subscribe_object_manager_cb (GDBusConnection *connection,
const char *sender_name,
const char *arg_object_path,
const char *interface_name,
const char *signal_name,
GVariant *parameters,
gpointer user_data)
{
const SubscribeObjectManagerData *d = user_data;
nm_assert (nm_streq0 (interface_name, DBUS_INTERFACE_OBJECT_MANAGER));
if (nm_streq (signal_name, "InterfacesAdded")) {
gs_unref_variant GVariant *interfaces_and_properties = NULL;
const char *object_path;
if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(oa{sa{sv}})")))
return;
g_variant_get (parameters,
"(&o@a{sa{sv}})",
&object_path,
&interfaces_and_properties);
d->callback (object_path, interfaces_and_properties, NULL, d->user_data);
return;
}
if (nm_streq (signal_name, "InterfacesRemoved")) {
gs_free const char **interfaces = NULL;
const char *object_path;
if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(oas)")))
return;
g_variant_get (parameters,
"(&o^a&s)",
&object_path,
&interfaces);
d->callback (object_path, NULL, interfaces, d->user_data);
return;
}
}
static void
_subscribe_object_manager_data_free (gpointer ptr)
{
SubscribeObjectManagerData *d = ptr;
if (d->user_data_free_func)
d->user_data_free_func (d->user_data);
nm_g_slice_free (d);
}
guint
nm_dbus_connection_signal_subscribe_object_manager (GDBusConnection *dbus_connection,
const char *service_name,
const char *object_path,
NMDBusConnectionSignalObjectMangerCb callback,
gpointer user_data,
GDestroyNotify user_data_free_func)
{
SubscribeObjectManagerData *d;
g_return_val_if_fail (callback, 0);
d = g_slice_new (SubscribeObjectManagerData);
*d = (SubscribeObjectManagerData) {
.callback = callback,
.user_data = user_data,
.user_data_free_func = user_data_free_func,
};
return nm_dbus_connection_signal_subscribe_object_manager_plain (dbus_connection,
service_name,
object_path,
NULL,
_subscribe_object_manager_cb,
d,
_subscribe_object_manager_data_free);
}
/*****************************************************************************/
static void
_nm_dbus_connection_call_get_managed_objects_cb (GObject *source,
GAsyncResult *res,
gpointer user_data)
{
gs_unref_variant GVariant *ret = NULL;
gs_unref_variant GVariant *arg = NULL;
gs_free_error GError *error = NULL;
gpointer orig_user_data;
NMDBusConnectionCallDefaultCb callback;
nm_utils_user_data_unpack (user_data, &orig_user_data, &callback);
ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), res, &error);
nm_assert ((!!ret) != (!!error));
if (ret) {
nm_assert (g_variant_is_of_type (ret, G_VARIANT_TYPE ("(a{oa{sa{sv}}})")));
arg = g_variant_get_child_value (ret, 0);
}
callback (arg, error, orig_user_data);
}
void
nm_dbus_connection_call_get_managed_objects (GDBusConnection *dbus_connection,
const char *bus_name,
const char *object_path,
GDBusCallFlags flags,
int timeout_msec,
GCancellable *cancellable,
NMDBusConnectionCallDefaultCb callback,
gpointer user_data)
{
nm_assert (callback);
g_dbus_connection_call (dbus_connection,
bus_name,
object_path,
DBUS_INTERFACE_OBJECT_MANAGER,
"GetManagedObjects",
NULL,
G_VARIANT_TYPE ("(a{oa{sa{sv}}})"),
flags,
timeout_msec,
cancellable,
_nm_dbus_connection_call_get_managed_objects_cb,
nm_utils_user_data_pack (user_data, callback));
}
......@@ -28,6 +28,12 @@ nm_clear_g_dbus_connection_signal (GDBusConnection *dbus_connection,
/*****************************************************************************/
typedef void (*NMDBusConnectionCallDefaultCb) (GVariant *result,
GError *error,
gpointer user_data);
/*****************************************************************************/
static inline void
nm_dbus_connection_call_start_service_by_name (GDBusConnection *dbus_connection,
const char *name,
......@@ -77,11 +83,95 @@ typedef void (*NMDBusConnectionCallGetNameOwnerCb) (const char *name_owner,
gpointer user_data);
void nm_dbus_connection_call_get_name_owner (GDBusConnection *dbus_connection,
const char *service_name,
int timeout_msec,
GCancellable *cancellable,
NMDBusConnectionCallGetNameOwnerCb callback,
gpointer user_data);
const char *service_name,
int timeout_msec,
GCancellable *cancellable,
NMDBusConnectionCallGetNameOwnerCb callback,
gpointer user_data);
static inline guint
nm_dbus_connection_signal_subscribe_properties_changed (GDBusConnection *dbus_connection,
const char *bus_name,
const char *object_path,
const char *interface_name,
GDBusSignalCallback callback,
gpointer user_data,
GDestroyNotify user_data_free_func)
{
nm_assert (bus_name);
/* it seems that using a non-unique name causes problems that we get signals
* also from unrelated senders. Usually, you are anyway monitoring the name-owner,
* so you should have the unique name at hand.
*
* If not, investigate this, ensure that it works, and lift this restriction. */
nm_assert (g_dbus_is_unique_name (bus_name));
return g_dbus_connection_signal_subscribe (dbus_connection,
bus_name,
DBUS_INTERFACE_PROPERTIES,
"PropertiesChanged",
object_path,
interface_name,
G_DBUS_SIGNAL_FLAGS_NONE,
callback,
user_data,
user_data_free_func);
}
void nm_dbus_connection_call_get_all (GDBusConnection *dbus_connection,
const char *bus_name,
const char *object_path,
const char *interface_name,
int timeout_msec,
GCancellable *cancellable,
NMDBusConnectionCallDefaultCb callback,
gpointer user_data);
/*****************************************************************************/
static inline guint
nm_dbus_connection_signal_subscribe_object_manager_plain (GDBusConnection *dbus_connection,
const char *service_name,
const char *object_path,
const char *signal_name,
GDBusSignalCallback callback,
gpointer user_data,
GDestroyNotify user_data_free_func)
{
return g_dbus_connection_signal_subscribe (dbus_connection,
service_name,
DBUS_INTERFACE_OBJECT_MANAGER,
signal_name,
object_path,
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
callback,
user_data,
user_data_free_func);
}
typedef void (*NMDBusConnectionSignalObjectMangerCb) (const char *object_path,
GVariant *added_interfaces_and_properties,
const char *const*removed_interfaces,
gpointer user_data);
guint nm_dbus_connection_signal_subscribe_object_manager (GDBusConnection *dbus_connection,
const char *service_name,
const char *object_path,
NMDBusConnectionSignalObjectMangerCb callback,
gpointer user_data,
GDestroyNotify user_data_free_func);
void nm_dbus_connection_call_get_managed_objects (GDBusConnection *dbus_connection,
const char *bus_name,
const char *object_path,
GDBusCallFlags flags,
int timeout_msec,
GCancellable *cancellable,
NMDBusConnectionCallDefaultCb callback,
gpointer user_data);
/*****************************************************************************/
......
......@@ -310,6 +310,12 @@ _nm_auto_protect_errno (int *p_saved_errno)
NM_AUTO_DEFINE_FCN0 (GSource *, _nm_auto_unref_gsource, g_source_unref);
#define nm_auto_unref_gsource nm_auto(_nm_auto_unref_gsource)
NM_AUTO_DEFINE_FCN0 (guint, _nm_auto_remove_source, g_source_remove);
#define nm_auto_remove_source nm_auto(_nm_auto_remove_source)
NM_AUTO_DEFINE_FCN0 (GIOChannel *, _nm_auto_unref_io_channel, g_io_channel_unref)
#define nm_auto_unref_io_channel nm_auto(_nm_auto_unref_io_channel)
NM_AUTO_DEFINE_FCN0 (GMainLoop *, _nm_auto_unref_gmainloop, g_main_loop_unref);
#define nm_auto_unref_gmainloop nm_auto(_nm_auto_unref_gmainloop)
......
......@@ -2288,6 +2288,44 @@ nm_utils_hash_keys_to_array (GHashTable *hash,
return keys;
}
gpointer *
nm_utils_hash_values_to_array (GHashTable *hash,
GCompareDataFunc compare_func,
gpointer user_data,
guint *out_len)
{
GHashTableIter iter;
gpointer value;
gpointer *arr;
guint i, len;
if ( !hash
|| (len = g_hash_table_size (hash)) == 0u) {
NM_SET_OUT (out_len, 0);
return NULL;
}
arr = g_new (gpointer, ((gsize) len) + 1);
i = 0;
g_hash_table_iter_init (&iter, hash);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &value))
arr[i++] = value;
nm_assert (i == len);
arr[len] = NULL;
if ( len > 1
&& compare_func) {
g_qsort_with_data (arr,
len,
sizeof (gpointer),
compare_func,
user_data);
}
return arr;
}
gboolean
nm_utils_hashtable_same_keys (const GHashTable *a,
const GHashTable *b)
......
......@@ -638,6 +638,7 @@ _nm_g_slice_free_fcn_define (8)
_nm_g_slice_free_fcn_define (10)
_nm_g_slice_free_fcn_define (12)
_nm_g_slice_free_fcn_define (16)
_nm_g_slice_free_fcn_define (32)
#define _nm_g_slice_free_fcn1(mem_size) \
({ \
......@@ -652,7 +653,8 @@ _nm_g_slice_free_fcn_define (16)
|| ((mem_size) == 8) \
|| ((mem_size) == 10) \
|| ((mem_size) == 12) \
|| ((mem_size) == 16)); \
|| ((mem_size) == 16) \
|| ((mem_size) == 32)); \
switch ((mem_size)) { \
case 1: _fcn = _nm_g_slice_free_fcn_1; break; \
case 2: _fcn = _nm_g_slice_free_fcn_2; break; \
......@@ -661,6 +663,7 @@ _nm_g_slice_free_fcn_define (16)
case 10: _fcn = _nm_g_slice_free_fcn_10; break; \
case 12: _fcn = _nm_g_slice_free_fcn_12; break; \
case 16: _fcn = _nm_g_slice_free_fcn_16; break; \
case 32: _fcn = _nm_g_slice_free_fcn_32; break; \
default: g_assert_not_reached (); _fcn = NULL; break; \
} \
_fcn; \
......@@ -952,6 +955,11 @@ gpointer *nm_utils_hash_keys_to_array (GHashTable *hash,
gpointer user_data,
guint *out_len);
gpointer *nm_utils_hash_values_to_array (GHashTable *hash,
GCompareDataFunc compare_func,
gpointer user_data,
guint *out_len);
static inline const char **
nm_utils_strdict_get_keys (const GHashTable *hash,
gboolean sorted,
......
......@@ -31,6 +31,8 @@
/** The interface supported by most dbus peers */
#define DBUS_INTERFACE_PEER "org.freedesktop.DBus.Peer"
#define DBUS_INTERFACE_OBJECT_MANAGER "org.freedesktop.DBus.ObjectManager"
/** This is a special interface whose methods can only be invoked
* by the local implementation (messages from remote apps aren't
* allowed to specify this interface).
......
......@@ -946,9 +946,10 @@ nm_ip_routing_rule_to_platform (const NMIPRoutingRule *rule,
struct _NMShutdownWaitObjHandle {
CList lst;
GObject *watched_obj;
gpointer watched_obj;
char *msg_reason;
bool free_msg_reason:1;
bool is_cancellable:1;
};
static CList _shutdown_waitobj_lst_head;
......@@ -967,7 +968,7 @@ _shutdown_waitobj_unregister (NMShutdownWaitObjHandle *handle)
static void
_shutdown_waitobj_cb (gpointer user_data,
GObject *where_the_object_was)
GObject *where_the_object_was)
{
NMShutdownWaitObjHandle *handle = user_data;
......@@ -980,6 +981,8 @@ _shutdown_waitobj_cb (gpointer user_data,
* nm_shutdown_wait_obj_register_full:
* @watched_obj: the object to watch. Takes a weak reference on the object
* to be notified when it gets destroyed.
* @wait_type: whether @watched_obj is just a plain GObject or a GCancellable
* that should be cancelled.
* @msg_reason: a reason message, for debugging and logging purposes.
* @free_msg_reason: if %TRUE, then ownership of @msg_reason will be taken
* and the string will be freed with g_free() afterwards. If %FALSE,
......@@ -993,21 +996,41 @@ _shutdown_waitobj_cb (gpointer user_data,
* the reference-counter of @watched_obj as signal, that the object
* is still used.
*
* If @wait_type is %NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE, then during shutdown
* (after %NM_SHUTDOWN_TIMEOUT_MS), the cancellable will be cancelled to notify
* the source of the shutdown. Note that otherwise, in this mode also @watched_obj
* is only tracked with a weak-pointer. Especially, it does not register to the
* "cancelled" signal to automatically unregister (otherwise, you would never
* know whether the returned NMShutdownWaitObjHandle is still valid.
*
* FIXME(shutdown): proper shutdown is not yet implemented, and registering
* an object (currently) has no effect.
*
* FIXME(shutdown): during shutdown, after %NM_SHUTDOWN_TIMEOUT_MS timeout, cancel
* all remaining %NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE instances. Also, when somebody
* enqueues a cancellable after that point, cancel it right away on an idle handler.
*
* Returns: a handle to unregister the object. The caller may choose to ignore
* the handle, in which case, the object will be automatically unregistered,
* once it gets destroyed.
* Note that the handle is only valid as long as @watched_obj exists. If
* you plan to use it, ensure that you take care of not using it after
* destroying @watched_obj.
*/
NMShutdownWaitObjHandle *
nm_shutdown_wait_obj_register_full (GObject *watched_obj,
nm_shutdown_wait_obj_register_full (gpointer watched_obj,
NMShutdownWaitType wait_type,
char *msg_reason,
gboolean free_msg_reason)
{
NMShutdownWaitObjHandle *handle;
g_return_val_if_fail (G_IS_OBJECT (watched_obj), NULL);
if (wait_type == NM_SHUTDOWN_WAIT_TYPE_OBJECT)
g_return_val_if_fail (G_IS_OBJECT (watched_obj), NULL);
else if (wait_type == NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE)
g_return_val_if_fail (G_IS_CANCELLABLE (watched_obj), NULL);
else
g_return_val_if_reached (NULL);
if (G_UNLIKELY (!_shutdown_waitobj_lst_head.next))
c_list_init (&_shutdown_waitobj_lst_head);
......@@ -1020,6 +1043,7 @@ nm_shutdown_wait_obj_register_full (GObject *watched_obj,
.watched_obj = watched_obj,
.msg_reason = msg_reason,
.free_msg_reason = free_msg_reason,
.is_cancellable = (wait_type == NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE),
};
c_list_link_tail (&_shutdown_waitobj_lst_head, &handle->lst);
g_object_weak_ref (watched_obj, _shutdown_waitobj_cb, handle);
......
......@@ -74,13 +74,43 @@ NMPlatformRoutingRule *nm_ip_routing_rule_to_platform (const NMIPRoutingRule *ru
#define NM_SHUTDOWN_TIMEOUT_MS 1500
#define NM_SHUTDOWN_TIMEOUT_MS_WATCHDOG 500
typedef enum {
/* The watched_obj argument is a GObject, and shutdown is delayed until the object
* gets destroyed (or unregistered). */
NM_SHUTDOWN_WAIT_TYPE_OBJECT,
/* The watched_obj argument is a GCancellable, and shutdown is delayed until the object
* gets destroyed (or unregistered). Note that after NM_SHUTDOWN_TIMEOUT_MS, the
* cancellable will be cancelled to notify listeners about the shutdown. */
NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE,
} NMShutdownWaitType;
typedef struct _NMShutdownWaitObjHandle NMShutdownWaitObjHandle;
NMShutdownWaitObjHandle *nm_shutdown_wait_obj_register_full (GObject *watched_obj,
NMShutdownWaitObjHandle *nm_shutdown_wait_obj_register_full (gpointer watched_obj,
NMShutdownWaitType wait_type,
char *msg_reason,
gboolean free_msg_reason);
#define nm_shutdown_wait_obj_register(watched_obj, msg_reason) nm_shutdown_wait_obj_register_full((watched_obj), (""msg_reason""), FALSE)
static inline NMShutdownWaitObjHandle *
nm_shutdown_wait_obj_register_object_full (gpointer watched_obj,
char *msg_reason,
gboolean free_msg_reason)
{
return nm_shutdown_wait_obj_register_full (watched_obj, NM_SHUTDOWN_WAIT_TYPE_OBJECT, msg_reason, free_msg_reason);
}
#define nm_shutdown_wait_obj_register_object(watched_obj, msg_reason) nm_shutdown_wait_obj_register_object_full((watched_obj), (""msg_reason""), FALSE)
static inline NMShutdownWaitObjHandle *
nm_shutdown_wait_obj_register_cancellable_full (GCancellable *watched_obj,
char *msg_reason,
gboolean free_msg_reason)
{
return nm_shutdown_wait_obj_register_full (watched_obj, NM_SHUTDOWN_WAIT_TYPE_CANCELLABLE, msg_reason, free_msg_reason);
}
#define nm_shutdown_wait_obj_register_cancellable(watched_obj, msg_reason) nm_shutdown_wait_obj_register_cancellable_full((watched_obj), (""msg_reason""), FALSE)
void nm_shutdown_wait_obj_unregister (NMShutdownWaitObjHandle *handle);
......
sources = files(
'nm-bluez-device.c',
'nm-bluez-manager.c',
'nm-bluez5-manager.c',
'nm-bt-error.c',
'nm-device-bt.c',
)
......
......@@ -13,7 +13,6 @@
#define NM_BLUEZ_SERVICE "org.bluez"