[RFC spice-vdagent 13/18] systemd-login: use GDBus

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Rewrite systemd-login.c using GDBus instead of libdbus.

Use GDBusProxy. This is less efficient than the previous impl
as it caches all properties and listens to all signals of the
given DBus object. But it is just so much more convenient...
---
 src/vdagentd/systemd-login.c | 254 +++++++++++------------------------
 1 file changed, 79 insertions(+), 175 deletions(-)

diff --git a/src/vdagentd/systemd-login.c b/src/vdagentd/systemd-login.c
index 88de1a6..2afd0dd 100644
--- a/src/vdagentd/systemd-login.c
+++ b/src/vdagentd/systemd-login.c
@@ -20,23 +20,21 @@
 */
 
 #include "session-info.h"
-#include <errno.h>
 #include <stdlib.h>
-#include <string.h>
 #include <syslog.h>
 #include <systemd/sd-login.h>
-#include <dbus/dbus.h>
+#include <gio/gio.h>
+#include <glib-unix.h>
 
 struct session_info {
     int verbose;
     sd_login_monitor *mon;
     char *session;
-    struct {
-        DBusConnection *system_connection;
-        char *match_session_signals;
-    } dbus;
+    GDBusProxy *dbus_proxy;
     gboolean session_is_locked;
-    gboolean session_locked_hint;
+    GIOChannel *io_channel;
+    guint io_watch_id;
+    ActiveSessionChangeCb session_change_cb;
 };
 
 #define LOGIND_INTERFACE            "org.freedesktop.login1"
@@ -44,185 +42,66 @@ struct session_info {
 #define LOGIND_SESSION_INTERFACE    "org.freedesktop.login1.Session"
 #define LOGIND_SESSION_OBJ_TEMPLATE "/org/freedesktop/login1/session/_3%s"
 
-#define DBUS_PROPERTIES_INTERFACE   "org.freedesktop.DBus.Properties"
-
 #define SESSION_SIGNAL_LOCK         "Lock"
 #define SESSION_SIGNAL_UNLOCK       "Unlock"
 
 #define SESSION_PROP_LOCKED_HINT    "LockedHint"
 
-/* dbus related */
-static DBusConnection *si_dbus_get_system_bus(void)
-{
-    DBusConnection *connection;
-    DBusError error;
-
-    dbus_error_init(&error);
-    connection = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error);
-    if (connection == NULL || dbus_error_is_set(&error)) {
-        if (dbus_error_is_set(&error)) {
-            syslog(LOG_WARNING, "Unable to connect to system bus: %s",
-                   error.message);
-            dbus_error_free(&error);
-        } else {
-            syslog(LOG_WARNING, "Unable to connect to system bus");
-        }
-        return NULL;
-    }
-    return connection;
-}
-
-static void si_dbus_match_remove(struct session_info *si)
-{
-    DBusError error;
-    if (si->dbus.match_session_signals == NULL)
-        return;
-
-    dbus_error_init(&error);
-    dbus_bus_remove_match(si->dbus.system_connection,
-                          si->dbus.match_session_signals,
-                          &error);
-
-    g_free(si->dbus.match_session_signals);
-    si->dbus.match_session_signals = NULL;
-}
-
-static void si_dbus_match_rule_update(struct session_info *si)
+static void session_signal_cb(GDBusProxy *proxy,
+                              gchar      *sender_name,
+                              gchar      *signal_name,
+                              GVariant   *parameters,
+                              gpointer    user_data)
 {
-    DBusError error;
-
-    if (si->dbus.system_connection == NULL ||
-            si->session == NULL)
-        return;
-
-    si_dbus_match_remove(si);
-
-    si->dbus.match_session_signals =
-        g_strdup_printf ("type='signal',interface='%s',path='"
-                         LOGIND_SESSION_OBJ_TEMPLATE"'",
-                         LOGIND_SESSION_INTERFACE,
-                         si->session);
-    if (si->verbose)
-        syslog(LOG_DEBUG, "logind match: %s", si->dbus.match_session_signals);
-
-    dbus_error_init(&error);
-    dbus_bus_add_match(si->dbus.system_connection,
-                       si->dbus.match_session_signals,
-                       &error);
-    if (dbus_error_is_set(&error)) {
-        syslog(LOG_WARNING, "Unable to add dbus rule match: %s",
-               error.message);
-        dbus_error_free(&error);
-        g_free(si->dbus.match_session_signals);
-        si->dbus.match_session_signals = NULL;
+    struct session_info *si = user_data;
+
+    if (g_strcmp0(signal_name, SESSION_SIGNAL_LOCK) == 0) {
+        si->session_is_locked = TRUE;
+    } else if (g_strcmp0(signal_name, SESSION_SIGNAL_UNLOCK) == 0) {
+        si->session_is_locked = FALSE;
+    } else if (si->verbose) {
+        syslog(LOG_DEBUG, "(systemd-login) Signal not handled: %s", signal_name);
     }
 }
 
-static void
-si_dbus_read_properties(struct session_info *si)
+static void si_dbus_proxy_update(struct session_info *si)
 {
-    dbus_bool_t locked_hint, ret;
-    DBusMessageIter iter, iter_variant;
-    gint type;
-    DBusError error;
-    DBusMessage *message = NULL;
-    DBusMessage *reply = NULL;
+    GError *err = NULL;
     gchar *session_object;
-    const gchar *interface, *property;
+
+    g_clear_object(&si->dbus_proxy);
 
     if (si->session == NULL)
         return;
 
     session_object = g_strdup_printf(LOGIND_SESSION_OBJ_TEMPLATE, si->session);
-    message = dbus_message_new_method_call(LOGIND_INTERFACE,
-                                           session_object,
-                                           DBUS_PROPERTIES_INTERFACE,
-                                           "Get");
-    g_free (session_object);
-    if (message == NULL) {
-        syslog(LOG_ERR, "Unable to create dbus message");
-        goto exit;
-    }
-
-    interface = LOGIND_SESSION_INTERFACE;
-    property = SESSION_PROP_LOCKED_HINT;
-    ret = dbus_message_append_args(message,
-                                   DBUS_TYPE_STRING, &interface,
-                                   DBUS_TYPE_STRING, &property,
-                                   DBUS_TYPE_INVALID);
-    if (!ret) {
-        syslog(LOG_ERR, "Unable to request locked-hint");
-        goto exit;
-    }
-
-    dbus_error_init(&error);
-    reply = dbus_connection_send_with_reply_and_block(si->dbus.system_connection,
-                                                      message,
-                                                      -1,
-                                                      &error);
-    if (reply == NULL) {
-        if (dbus_error_is_set(&error)) {
-            syslog(LOG_ERR, "Properties.Get failed (locked-hint) due %s", error.message);
-            dbus_error_free(&error);
-        } else {
-            syslog(LOG_ERR, "Properties.Get failed (locked-hint)");
-        }
-        goto exit;
-    }
-
-    dbus_message_iter_init(reply, &iter);
-    type = dbus_message_iter_get_arg_type(&iter);
-    if (type != DBUS_TYPE_VARIANT) {
-        syslog(LOG_ERR, "expected a variant, got a '%c' instead", type);
-        goto exit;
-    }
-
-    dbus_message_iter_recurse(&iter, &iter_variant);
-    type = dbus_message_iter_get_arg_type(&iter_variant);
-    if (type != DBUS_TYPE_BOOLEAN) {
-        syslog(LOG_ERR, "expected a boolean, got a '%c' instead", type);
-        goto exit;
-    }
-    dbus_message_iter_get_basic(&iter_variant, &locked_hint);
-
-    si->session_locked_hint = (locked_hint) ? TRUE : FALSE;
-exit:
-    if (reply != NULL) {
-        dbus_message_unref(reply);
-    }
-
-    if (message != NULL) {
-        dbus_message_unref(message);
+    si->dbus_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
+                                                   G_DBUS_PROXY_FLAGS_NONE,
+                                                   NULL,
+                                                   LOGIND_INTERFACE,
+                                                   session_object,
+                                                   LOGIND_SESSION_INTERFACE,
+                                                   NULL,
+                                                   &err);
+    g_free(session_object);
+    if (err) {
+        syslog(LOG_ERR, "(systemd-login) %s: %s", __func__, err->message);
+        g_error_free(err);
+        return;
     }
+    g_signal_connect(si->dbus_proxy, "g-signal",
+                     G_CALLBACK(session_signal_cb), si);
 }
 
-static void
-si_dbus_read_signals(struct session_info *si)
+static gboolean io_channel_cb(GIOChannel  *source,
+                              GIOCondition condition,
+                              gpointer     data)
 {
-    DBusMessage *message = NULL;
-
-    dbus_connection_read_write(si->dbus.system_connection, 0);
-    message = dbus_connection_pop_message(si->dbus.system_connection);
-    while (message != NULL) {
-        const char *member;
-
-        member = dbus_message_get_member (message);
-        if (g_strcmp0(member, SESSION_SIGNAL_LOCK) == 0) {
-            si->session_is_locked = TRUE;
-        } else if (g_strcmp0(member, SESSION_SIGNAL_UNLOCK) == 0) {
-            si->session_is_locked = FALSE;
-        } else {
-            if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL) {
-                syslog(LOG_WARNING, "(systemd-login) received non signal message");
-            } else if (si->verbose) {
-                syslog(LOG_DEBUG, "(systemd-login) Signal not handled: %s", member);
-            }
-        }
-
-        dbus_message_unref(message);
-        dbus_connection_read_write(si->dbus.system_connection, 0);
-        message = dbus_connection_pop_message(si->dbus.system_connection);
-    }
+    struct session_info *si = data;
+    session_info_get_active_session(si);
+    if (si->session_change_cb)
+        si->session_change_cb(si->session);
+    return G_SOURCE_CONTINUE;
 }
 
 struct session_info *session_info_create(int verbose, ActiveSessionChangeCb cb)
@@ -236,6 +115,7 @@ struct session_info *session_info_create(int verbose, ActiveSessionChangeCb cb)
 
     si->verbose = verbose;
     si->session_is_locked = FALSE;
+    si->session_change_cb = cb;
 
     r = sd_login_monitor_new("session", &si->mon);
     if (r < 0) {
@@ -244,7 +124,9 @@ struct session_info *session_info_create(int verbose, ActiveSessionChangeCb cb)
         return NULL;
     }
 
-    si->dbus.system_connection = si_dbus_get_system_bus();
+    si->io_channel = g_io_channel_unix_new(sd_login_monitor_get_fd(si->mon));
+    si->io_watch_id = g_io_add_watch(si->io_channel, G_IO_IN, io_channel_cb, si);
+
     return si;
 }
 
@@ -253,8 +135,9 @@ void session_info_destroy(struct session_info *si)
     if (!si)
         return;
 
-    si_dbus_match_remove(si);
-    dbus_connection_close(si->dbus.system_connection);
+    g_clear_object(&si->dbus_proxy);
+    g_source_remove(si->io_watch_id);
+    g_io_channel_unref(si->io_channel);
     sd_login_monitor_unref(si->mon);
     free(si->session);
     free(si);
@@ -284,7 +167,7 @@ const char *session_info_get_active_session(struct session_info *si)
     sd_login_monitor_flush(si->mon);
     free(old_session);
 
-    si_dbus_match_rule_update(si);
+    si_dbus_proxy_update(si);
     return si->session;
 }
 
@@ -303,16 +186,37 @@ char *session_info_session_for_pid(struct session_info *si, uint32_t pid)
     return session;
 }
 
+gboolean get_locked_hint_property(struct session_info *si)
+{
+    GVariant *prop;
+    gboolean locked = FALSE;
+
+    if (si->dbus_proxy == NULL)
+        return locked;
+
+    prop = g_dbus_proxy_get_cached_property(si->dbus_proxy,
+               SESSION_PROP_LOCKED_HINT);
+    if (prop) {
+        if (g_variant_is_of_type(prop, G_VARIANT_TYPE_BOOLEAN))
+            locked = g_variant_get_boolean(prop);
+        else
+            syslog(LOG_ERR, "(systemd-login) unexpected LockedHint property type");
+
+        g_variant_unref(prop);
+    } else {
+        syslog(LOG_ERR, "(systemd-login) cannot get LockedHint property");
+    }
+
+    return locked;
+}
+
 gboolean session_info_session_is_locked(struct session_info *si)
 {
     gboolean locked;
 
     g_return_val_if_fail (si != NULL, FALSE);
 
-    si_dbus_read_signals(si);
-    si_dbus_read_properties(si);
-
-    locked = (si->session_is_locked || si->session_locked_hint);
+    locked = (si->session_is_locked || get_locked_hint_property(si));
     if (si->verbose) {
         syslog(LOG_DEBUG, "(systemd-login) session is locked: %s",
                locked ? "yes" : "no");
-- 
2.17.1

_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel




[Index of Archives]     [Linux Virtualization]     [Linux Virtualization]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]