diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | libnm/meson.build | 1 | ||||
-rw-r--r-- | libnm/nm-client.c | 12 | ||||
-rw-r--r-- | libnm/nm-client.h | 3 | ||||
-rw-r--r-- | libnm/nm-dbus-client.c | 237 | ||||
-rw-r--r-- | libnm/nm-dbus-client.h | 37 |
6 files changed, 292 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index 95238324a4..523caf00e9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1232,6 +1232,7 @@ libnm_lib_h_pub_mkenums = \ libnm/nm-enum-types.h libnm_lib_h_priv = \ libnm/nm-libnm-utils.h \ + libnm/nm-dbus-client.h \ libnm/nm-dbus-helpers.h \ libnm/nm-device-private.h \ libnm/nm-dhcp4-config.h \ @@ -1248,6 +1249,7 @@ libnm_lib_c_real = \ libnm/nm-active-connection.c \ libnm/nm-checkpoint.c \ libnm/nm-client.c \ + libnm/nm-dbus-client.c \ libnm/nm-dbus-helpers.c \ libnm/nm-device-6lowpan.c \ libnm/nm-device-adsl.c \ diff --git a/libnm/meson.build b/libnm/meson.build index 0d7fb3acf2..d9398b57e4 100644 --- a/libnm/meson.build +++ b/libnm/meson.build @@ -77,6 +77,7 @@ libnm_sources = files( 'nm-active-connection.c', 'nm-checkpoint.c', 'nm-client.c', + 'nm-dbus-client.c', 'nm-dbus-helpers.c', 'nm-device-6lowpan.c', 'nm-device-adsl.c', diff --git a/libnm/nm-client.c b/libnm/nm-client.c index 1e81221537..2c09698986 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -20,6 +20,7 @@ #include "nm-active-connection.h" #include "nm-vpn-connection.h" #include "nm-remote-connection.h" +#include "nm-dbus-client.h" #include "nm-dbus-helpers.h" #include "nm-wimax-nsp.h" #include "nm-object-private.h" @@ -96,6 +97,7 @@ typedef struct { typedef struct { NMManager *manager; + NMDBusClient *dbus_client; NMRemoteSettings *settings; NMDnsManager *dns_manager; GDBusObjectManager *object_manager; @@ -168,9 +170,17 @@ NM_CACHED_QUARK_FCN ("nm-client-error-quark", nm_client_error_quark) /*****************************************************************************/ +static const NMDBusClientCallbackTable dbus_client_callback_table = { +}; + static void nm_client_init (NMClient *client) { + NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (client); + + priv->dbus_client = nm_dbus_client_new (g_bus_get_sync (_nm_dbus_bus_type (), NULL, NULL), + &dbus_client_callback_table, + client); } static gboolean @@ -3408,6 +3418,8 @@ dispose (GObject *object) nm_clear_g_cancellable (&priv->new_object_manager_cancellable); + nm_clear_pointer (&priv->dbus_client, nm_dbus_client_free); + if (priv->manager) { g_signal_handlers_disconnect_by_data (priv->manager, object); g_clear_object (&priv->manager); diff --git a/libnm/nm-client.h b/libnm/nm-client.h index 44b71ee094..da66e9fe5c 100644 --- a/libnm/nm-client.h +++ b/libnm/nm-client.h @@ -221,9 +221,11 @@ typedef struct { GType nm_client_get_type (void); +_NM_LIBNM_SYNC NMClient *nm_client_new (GCancellable *cancellable, GError **error); +_NM_LIBNM_ASYNC void nm_client_new_async (GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); @@ -291,6 +293,7 @@ NMClientPermissionResult nm_client_get_permission_result (NMClient *client, NMConnectivityState nm_client_get_connectivity (NMClient *client); +_NM_LIBNM_SYNC NMConnectivityState nm_client_check_connectivity (NMClient *client, GCancellable *cancellable, GError **error); diff --git a/libnm/nm-dbus-client.c b/libnm/nm-dbus-client.c new file mode 100644 index 0000000000..109dc357fc --- /dev/null +++ b/libnm/nm-dbus-client.c @@ -0,0 +1,237 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2019 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-dbus-client.h" + +#include "c-list/src/c-list.h" +#include "nm-glib-aux/nm-dbus-aux.h" +#include "nm-glib-aux/nm-ref-string.h" +#include "nm-dbus-interface.h" + +/*****************************************************************************/ + +typedef void (*EventHandleFcn) (NMDBusClient *self, + gpointer user_data); + +typedef struct { + CList event_lst; + EventHandleFcn handle_fcn; + gpointer user_data; +} EventData; + +struct _NMDBusClient { + + const NMDBusClientCallbackTable *callback_table; + gpointer callback_user_data; + + GMutex event_lock; + + CList event_lst_head; + + GMainContext *caller_context; + GMainContext *intern_context; + + GDBusConnection *dbus_connection; + + GCancellable *i_name_owner_get_cancellable; + + char *i_name_owner; + + guint name_owner_changed_id; +}; + +/*****************************************************************************/ + +#define _LOGT(...) do { } while (0) + +static gboolean +NM_IS_DBUS_CLIENT (NMDBusClient *self) +{ + nm_assert (!self || G_IS_DBUS_CONNECTION (self->dbus_connection)); + + return !!self; +} + +/*****************************************************************************/ + +static void +_event_queue (NMDBusClient *self, + EventHandleFcn handle_fcn, + gpointer user_data) +{ + EventData *e; + + e = g_slice_new (EventData); + e->handle_fcn = handle_fcn; + e->user_data = user_data; + + g_mutex_lock (&self->event_lock); + c_list_link_tail (&self->event_lst_head, &e->event_lst); + g_mutex_unlock (&self->event_lock); +} + +static gboolean +_event_dequeue_and_handle (NMDBusClient *self) +{ + EventData *e; + + g_mutex_lock (&self->event_lock); + e = c_list_first_entry (&self->event_lst_head, EventData, event_lst); + if (e) + c_list_unlink (&e->event_lst); + g_mutex_unlock (&self->event_lock); + + if (!e) + return FALSE; + + e->handle_fcn (self, e->user_data); + nm_g_slice_free (e); + return TRUE; +} + +/*****************************************************************************/ + +static void +i_name_owner_changed (NMDBusClient *self, + const char *name_owner, + gboolean from_get_callback) +{ + if (G_UNLIKELY (self->i_name_owner_get_cancellable)) + g_clear_object (&self->i_name_owner_get_cancellable); + else { + if (nm_streq0 (self->i_name_owner, name_owner)) + return; + } + + g_free (self->i_name_owner); + self->i_name_owner = g_strdup (name_owner); + + if (!self->i_name_owner) + _LOGT ("D-Bus name for %s has no owner", NM_DBUS_SERVICE); + else + _LOGT ("D-Bus name for %s has owner %s", NM_DBUS_SERVICE, i_name_owner); + + //XXX: initialize parts. + + //XXX: notify caller about name owner changed. +} + +static void +i_name_owner_changed_cb (GDBusConnection *connection, + const char *sender_name, + const char *object_path, + const char *interface_name, + const char *signal_name, + GVariant *parameters, + gpointer user_data) +{ + const char *new_owner; + + if (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sss)"))) { + g_variant_get (parameters, + "(&s&s&s)", + NULL, + NULL, + &new_owner); + i_name_owner_changed (user_data, nm_str_not_empty (new_owner), FALSE); + } +} + +static void +i_name_owner_get_cb (const char *name_owner, + GError *error, + gpointer user_data) +{ + if ( name_owner + || !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + i_name_owner_changed (user_data, name_owner, TRUE); +} + +/*****************************************************************************/ + +NMDBusClient * +nm_dbus_client_new (GDBusConnection *dbus_connection, + const NMDBusClientCallbackTable *callback_table, + gpointer callback_user_data) +{ + NMDBusClient *self; + + g_return_val_if_fail (G_IS_DBUS_CONNECTION (dbus_connection), NULL); + g_return_val_if_fail (callback_table, NULL); + + self = g_slice_new (NMDBusClient); + + *self = (NMDBusClient) { + .callback_table = callback_table, + .callback_user_data = callback_user_data, + .dbus_connection = g_object_ref (dbus_connection), + .caller_context = g_main_context_ref_thread_default (), + .intern_context = g_main_context_new (), + .event_lst_head = C_LIST_INIT (self->event_lst_head), + }; + + g_mutex_init (&self->event_lock); + + g_main_context_push_thread_default (self->intern_context); + + self->name_owner_changed_id = nm_dbus_connection_signal_subscribe_name_owner_changed (self->dbus_connection, + NM_DBUS_SERVICE, + i_name_owner_changed_cb, + self, + NULL); + + self->i_name_owner_get_cancellable = g_cancellable_new (); + nm_dbus_connection_call_get_name_owner (self->dbus_connection, + NM_DBUS_SERVICE, + -1, + self->i_name_owner_get_cancellable, + i_name_owner_get_cb, + self); + + g_main_context_pop_thread_default (self->intern_context); + + return self; +} + +void +nm_dbus_client_free (NMDBusClient *self) +{ + g_return_if_fail (NM_IS_DBUS_CLIENT (self)); + + //XXX: handle pending events in event_lst_head + nm_assert (c_list_is_empty (&self->event_lst_head)); + + nm_clear_g_cancellable (&self->i_name_owner_get_cancellable); + + nm_clear_g_dbus_connection_signal (self->dbus_connection, + &self->name_owner_changed_id); + + g_object_unref (self->dbus_connection); + + g_main_context_unref (self->caller_context); + + //XXX: ensure there are no pending jobs (or we handle them correctly). + g_main_context_unref (self->intern_context); + + g_mutex_clear (&self->event_lock); + + nm_g_slice_free (self); +} diff --git a/libnm/nm-dbus-client.h b/libnm/nm-dbus-client.h new file mode 100644 index 0000000000..542744f68c --- /dev/null +++ b/libnm/nm-dbus-client.h @@ -0,0 +1,37 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * Copyright 2019 Red Hat, Inc. + */ + +#ifndef __NM_DBUS_CLIENT_H__ +#define __NM_DBUS_CLIENT_H__ + +typedef struct _NMDBusClient NMDBusClient; + +typedef struct { + void (*name_owner_changed) (NMDBusClient *self, + const char *new_owner, + gpointer user_data); +} NMDBusClientCallbackTable; + +NMDBusClient *nm_dbus_client_new (GDBusConnection *dbus_connection, + const NMDBusClientCallbackTable *callback_table, + gpointer callback_user_data); + +void nm_dbus_client_free (NMDBusClient *self); + +#endif /* __NM_DBUS_CLIENT_H__ */ |