This is RFC/preview-only patch - initial work of adding D-Bus interface for vdagent. --- Makefile.am | 12 +++-- configure.ac | 3 +- src/vdagent-dbus.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/vdagent-dbus.h | 27 ++++++++++++ src/vdagent.c | 30 +++++++++++++ 5 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 src/vdagent-dbus.c create mode 100644 src/vdagent-dbus.h diff --git a/Makefile.am b/Makefile.am index 74cc313..c61a0dd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,9 +4,14 @@ NULL = bin_PROGRAMS = src/spice-vdagent sbin_PROGRAMS = src/spice-vdagentd -src_spice_vdagent_CFLAGS = $(X_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) -src_spice_vdagent_LDADD = $(X_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) -src_spice_vdagent_SOURCES = src/vdagent.c src/vdagent-x11.c src/vdagent-x11-randr.c src/vdagent-file-xfers.c src/udscs.c +src_spice_vdagent_CFLAGS = $(X_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) ${GIO2_CFLAGS} +src_spice_vdagent_LDADD = $(X_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS) ${GIO2_LIBS} +src_spice_vdagent_SOURCES = src/vdagent.c \ + src/vdagent-x11.c \ + src/vdagent-x11-randr.c \ + src/vdagent-file-xfers.c \ + src/udscs.c \ + src/vdagent-dbus.c src_spice_vdagentd_CFLAGS = $(DBUS_CFLAGS) $(LIBSYSTEMD_LOGIN_CFLAGS) \ $(PCIACCESS_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS) $(PIE_CFLAGS) @@ -34,6 +39,7 @@ noinst_HEADERS = src/glib-compat.h \ src/vdagent-virtio-port.h \ src/vdagent-x11.h \ src/vdagent-x11-priv.h \ + src/vdagent-dbus.h \ src/vdagentd-proto.h \ src/vdagentd-proto-strings.h \ src/vdagentd-uinput.h \ diff --git a/configure.ac b/configure.ac index 79905a8..2d98c43 100644 --- a/configure.ac +++ b/configure.ac @@ -76,7 +76,8 @@ AC_ARG_ENABLE([static-uinput], [enable_static_uinput="$enableval"], [enable_static_uinput="no"]) -PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.12]) +PKG_CHECK_MODULES([GLIB2], [glib-2.0 >= 2.26]) +PKG_CHECK_MODULES([GIO2], [gio-2.0 >= 2.26]) PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11]) PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.5]) diff --git a/src/vdagent-dbus.c b/src/vdagent-dbus.c new file mode 100644 index 0000000..47f1d31 --- /dev/null +++ b/src/vdagent-dbus.c @@ -0,0 +1,126 @@ +/* vdagent-dbus.c vdagent dbus interface + + Copyright 2013 Fedor Lyakhov + + Authors: + Fedor Lyakhov <fedor.lyakhov@xxxxxxxxx> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdio.h> +#include <syslog.h> +#include <glib.h> +#include <gio/gio.h> + +#include <spice/vd_agent.h> +#include "vdagent-dbus.h" + +static const char *vdagent_dbus_name = "com.redhat.spice.vdagent"; +static guint vdagent_dbus_name_owner_id = 0; +static const char *vdagent_dbus_connection_info_object_path = + "/com/redhat/spice/vdagent/ConnectionInfo"; + +/* Introspection data for vdagent service */ +/* TODO: document the interface */ +static const gchar *vdagent_dbus_introspection_xml = + "<node>" + " <interface name='com.redhat.spice.vdagent.ConnectionInfo'>" + " <property type='b' name='Connected' access='read' />" + " <property type='s' name='Type' access='read' />" /* local, remote */ + " <property type='u' name='Speed' access='read' />" /* In kbps, e.g. 512K, 1024K = 1M etc. */ + " </interface>" + "</node>"; + +static GDBusNodeInfo *vdagent_dbus_introspection_data = NULL; + +static GVariant *vdagent_dbus_handle_get_property(GDBusConnection *connection, const gchar *sender, + const gchar *object_path, const gchar *interface_name, const gchar *property_name, + GError **error, gpointer user_data) +{ + GVariant *ret = NULL; + + syslog(LOG_DEBUG, "Handling D-Bus get property"); + + /* TODO: implement actual handlers */ + if (g_strcmp0(property_name, "Connected") == 0) + { + ret = g_variant_new_boolean(TRUE); + } + else if (g_strcmp0 (property_name, "Type") == 0) + { + ret = g_variant_new_string("remote"); + } + else if (g_strcmp0 (property_name, "Speed") == 0) + { + ret = g_variant_new_uint32(512); + } + return ret; +} + +static const GDBusInterfaceVTable vdagent_dbus_interface_vtable = +{ + NULL, + vdagent_dbus_handle_get_property, /* Only handling getters now */ + NULL +}; + +static void vdagent_dbus_handle_bus_acquired(GDBusConnection *connection, + const gchar *name, gpointer user_data) +{ + guint registration_id; + + syslog(LOG_DEBUG, "Acquired connection to session bus"); + registration_id = g_dbus_connection_register_object(connection, + vdagent_dbus_connection_info_object_path, vdagent_dbus_introspection_data->interfaces[0], + &vdagent_dbus_interface_vtable, NULL, NULL, NULL); + /* TODO: handle GError in case of registration failure */ + g_assert(registration_id > 0); +} + +static void vdagent_dbus_handle_name_acquired(GDBusConnection *connection, + const gchar *name, gpointer user_data) +{ + syslog(LOG_DEBUG, "Acquired the name %s on the session bus", name); +} + +static void vdagent_dbus_handle_bus_name_lost(GDBusConnection *connection, + const gchar *name, gpointer user_data) +{ + if (!connection) + { + syslog(LOG_ERR, "Failed to acquire connection to session bus"); + return; + } + syslog(LOG_DEBUG, "Lost the name %s on the session bus", name); +} + +int vdagent_dbus_init() +{ + vdagent_dbus_introspection_data = g_dbus_node_info_new_for_xml(vdagent_dbus_introspection_xml, + NULL); + /* TODO: handle GError in case of generation failure */ + g_assert(vdagent_dbus_introspection_data != NULL); + + vdagent_dbus_name_owner_id = g_bus_own_name(G_BUS_TYPE_SESSION, vdagent_dbus_name, + G_BUS_NAME_OWNER_FLAGS_NONE, vdagent_dbus_handle_bus_acquired, + vdagent_dbus_handle_name_acquired, vdagent_dbus_handle_bus_name_lost, NULL, NULL); + return (vdagent_dbus_name_owner_id > 0); +} + +void vdagent_dbus_cleanup() +{ + g_bus_unown_name(vdagent_dbus_name_owner_id); + g_dbus_node_info_unref(vdagent_dbus_introspection_data); +} diff --git a/src/vdagent-dbus.h b/src/vdagent-dbus.h new file mode 100644 index 0000000..7bbc66a --- /dev/null +++ b/src/vdagent-dbus.h @@ -0,0 +1,27 @@ +/* vdagent-dbus.h vdagent dbus code header file + + Copyright 2013 Fedor Lyakhov + + Authors: + Fedor Lyakhov <fedor.lyakhov@xxxxxxxxx> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +#ifndef __VDAGENT_DBUS_H +#define __VDAGENT_DBUS_H + +int vdagent_dbus_init(); +void vdagent_dbus_cleanup(); + +#endif diff --git a/src/vdagent.c b/src/vdagent.c index d7f7aba..beeb756 100644 --- a/src/vdagent.c +++ b/src/vdagent.c @@ -35,12 +35,14 @@ #include <sys/stat.h> #include <spice/vd_agent.h> #include <glib.h> +#include <gio/gio.h> #include "udscs.h" #include "vdagentd-proto.h" #include "vdagentd-proto-strings.h" #include "vdagent-x11.h" #include "vdagent-file-xfers.h" +#include "vdagent-dbus.h" static const char *portdev = "/dev/virtio-ports/com.redhat.spice.0"; static const char *vdagentd_socket = VDAGENTD_SOCKET; @@ -52,6 +54,7 @@ static struct vdagent_file_xfers *vdagent_file_xfers = NULL; static struct udscs_connection *client = NULL; static int quit = 0; static int version_mismatch = 0; +static GMainLoop *loop = NULL; void daemon_read_complete(struct udscs_connection **connp, struct udscs_message_header *header, uint8_t *data) @@ -177,6 +180,14 @@ static int file_test(const char *path) return stat(path, &buffer); } +static gpointer thread_func_loop(gpointer data) +{ + syslog(LOG_INFO, "Loop thread func entered"); + loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(loop); + return NULL; +} + int main(int argc, char *argv[]) { fd_set readfds, writefds; @@ -184,6 +195,7 @@ int main(int argc, char *argv[]) int do_daemonize = 1; int x11_sync = 0; struct sigaction act; + GThread *thread_loop = NULL; for (;;) { if (-1 == (c = getopt(argc, argv, "-dxhys:f:o:S:"))) @@ -238,6 +250,21 @@ int main(int argc, char *argv[]) if (do_daemonize) daemonize(); + g_type_init(); + + /* TODO: use g_thread_create for GIO < 2.32, g_thread_new for GIO >= 2.32 */ + thread_loop = g_thread_new("Loop", thread_func_loop, NULL); + if (thread_loop == NULL) + { + syslog(LOG_ERR, "Failed to create loop thread"); + return 1; + } + + if (!vdagent_dbus_init()) { + syslog(LOG_ERR, "Failed to own DBus name"); + return 1; + } + reconnect: if (version_mismatch) { syslog(LOG_INFO, "Version mismatch, restarting"); @@ -304,5 +331,8 @@ reconnect: if (!quit && do_daemonize) goto reconnect; + g_main_loop_quit(loop); + g_thread_join(thread_loop); + vdagent_dbus_cleanup(); return 0; } -- 1.8.1.4 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel