[systemd-devel] [PATCH 3/4] gdbus: Integrate kdbus into GDBus core
Karol Lewandowski
k.lewandowsk at samsung.com
Thu Nov 21 03:33:51 PST 2013
This commit hooks kdbus into GDBus and provides
"--enable-kdbus-transport" configure switch.
---
configure.ac | 10 +++
gio/Makefile.am | 4 +
gio/gdbusaddress.c | 80 +++++++++++++++----
gio/gdbusconnection.c | 20 ++++-
gio/gdbusprivate.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++----
gio/gdbusprivate.h | 8 +-
gio/giotypes.h | 33 ++++++++
7 files changed, 334 insertions(+), 32 deletions(-)
diff --git a/configure.ac b/configure.ac
index deacdc1..413c9f2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -242,6 +242,10 @@ AC_ARG_ENABLE(gc_friendly,
[AS_HELP_STRING([--enable-gc-friendly],
[turn on garbage collector friendliness [default=no]])],,
[enable_gc_friendly=no])
+AC_ARG_ENABLE(kdbus_transport,
+ [AS_HELP_STRING([--enable-kdbus-transport],
+ [enable kdbus transport [default=no]])],,
+ [enable_kdbus_transport=no])
AC_ARG_ENABLE(mem_pools,
[AS_HELP_STRING([--disable-mem-pools],
[disable all glib memory pools])],,
@@ -259,6 +263,12 @@ AS_IF([test "x$enable_gc_friendly" = "xyes"], [
AC_MSG_RESULT([yes])
], [ AC_MSG_RESULT([no]) ])
+AC_MSG_CHECKING([kdbus transport])
+AS_IF([test "x$enable_kdbus_transport" = "xyes"], [
+ AC_DEFINE(KDBUS_TRANSPORT, 1, [Define if kdbus transport is enabled])
+ AC_MSG_RESULT([yes])
+], [ AC_MSG_RESULT([no]) ])
+
AC_MSG_CHECKING([whether to disable memory pools])
AS_IF([test "x$disable_mem_pools" = "xno"], [
AC_MSG_RESULT([no])
diff --git a/gio/Makefile.am b/gio/Makefile.am
index 5b6cda1..c060ef2 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -394,6 +394,8 @@ libgio_2_0_la_SOURCES = \
giostream.c \
gioprivate.h \
giowin32-priv.h \
+ gkdbus.c \
+ gkdbusconnection.c \
gloadableicon.c \
gmount.c \
gmemoryinputstream.c \
@@ -569,6 +571,8 @@ gio_headers = \
giomodule.h \
gioscheduler.h \
giostream.h \
+ gkdbus.h \
+ gkdbusconnection.h \
gloadableicon.h \
gmount.h \
gmemoryinputstream.h \
diff --git a/gio/gdbusaddress.c b/gio/gdbusaddress.c
index b5143cf..bed0bbe 100644
--- a/gio/gdbusaddress.c
+++ b/gio/gdbusaddress.c
@@ -1,6 +1,7 @@
/* GDBus - GLib D-Bus Library
*
* Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2013 Samsung Electronics
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,7 +18,9 @@
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Author: David Zeuthen <davidz at redhat.com>
+ * Author: David Zeuthen <davidz at redhat.com>
+ * Author: Lukasz Skalski <l.skalski at partner.samsung.com>
+ * Author: Michal Eljasiewicz <m.eljasiewic at samsung.com>
*/
#include "config.h"
@@ -44,6 +47,7 @@
#ifdef G_OS_UNIX
#include <gio/gunixsocketaddress.h>
+#include <gio/gkdbusconnection.h>
#endif
#ifdef G_OS_WIN32
@@ -360,6 +364,18 @@ is_valid_tcp (const gchar *address_entry,
return ret;
}
+static int
+g_dbus_is_supported_address_kdbus (const gchar *transport_name)
+{
+ int supported = 0;
+
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ supported = (g_strcmp0 (transport_name, "kdbus") == 0) || (g_strcmp0 (transport_name, "kernel") == 0);
+#endif
+
+ return supported;
+}
+
/**
* g_dbus_is_supported_address:
* @string: A string.
@@ -401,7 +417,8 @@ g_dbus_is_supported_address (const gchar *string,
goto out;
supported = FALSE;
- if (g_strcmp0 (transport_name, "unix") == 0)
+ if ((g_strcmp0 (transport_name, "unix") == 0)
+ || g_dbus_is_supported_address_kdbus (transport_name))
supported = is_valid_unix (a[n], key_value_pairs, error);
else if (g_strcmp0 (transport_name, "tcp") == 0)
supported = is_valid_tcp (a[n], key_value_pairs, error);
@@ -553,7 +570,8 @@ g_dbus_address_connect (const gchar *address_entry,
{
}
#ifdef G_OS_UNIX
- else if (g_strcmp0 (transport_name, "unix") == 0)
+ if ((g_strcmp0 (transport_name, "unix") == 0)
+ || g_dbus_is_supported_address_kdbus (transport_name))
{
const gchar *path;
const gchar *abstract;
@@ -664,21 +682,49 @@ g_dbus_address_connect (const gchar *address_entry,
if (connectable != NULL)
{
- GSocketClient *client;
- GSocketConnection *connection;
-
- g_assert (ret == NULL);
- client = g_socket_client_new ();
- connection = g_socket_client_connect (client,
- connectable,
- cancellable,
- error);
- g_object_unref (connectable);
- g_object_unref (client);
- if (connection == NULL)
- goto out;
- ret = G_IO_STREAM (connection);
+ if (FALSE)
+ {
+ }
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ else if (g_dbus_is_supported_address_kdbus (transport_name))
+ {
+ GKdbusConnection *connection;
+
+ const gchar *path;
+ path = g_hash_table_lookup (key_value_pairs, "path");
+
+ g_assert (ret == NULL);
+ connection = g_kdbus_connection_new ();
+ g_kdbus_connection_connect (connection,
+ path,
+ cancellable,
+ error);
+ g_object_unref (connectable);
+ if (connection == NULL)
+ goto out;
+
+ ret = G_IO_STREAM (connection);
+ }
+#endif
+ else
+ {
+ GSocketClient *client;
+ GSocketConnection *connection;
+
+ g_assert (ret == NULL);
+ client = g_socket_client_new ();
+ connection = g_socket_client_connect (client,
+ connectable,
+ cancellable,
+ error);
+ g_object_unref (connectable);
+ g_object_unref (client);
+ if (connection == NULL)
+ goto out;
+
+ ret = G_IO_STREAM (connection);
+ }
if (nonce_file != NULL)
{
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
index 8a0748d..790a21c 100644
--- a/gio/gdbusconnection.c
+++ b/gio/gdbusconnection.c
@@ -1,6 +1,7 @@
/* GDBus - GLib D-Bus Library
*
* Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2013 Samsung Electronics
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,7 +18,9 @@
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Author: David Zeuthen <davidz at redhat.com>
+ * Author: David Zeuthen <davidz at redhat.com>
+ * Author: Lukasz Skalski <l.skalski at partner.samsung.com>
+ * Author: Michal Eljasiewicz <m.eljasiewic at samsung.com>
*/
/*
@@ -128,6 +131,7 @@
#include "gsimpleasyncresult.h"
#ifdef G_OS_UNIX
+#include "gkdbusconnection.h"
#include "gunixconnection.h"
#include "gunixfdmessage.h"
#endif
@@ -1659,6 +1663,14 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection,
error))
goto out;
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ if (G_IS_KDBUS_CONNECTION (connection->stream))
+ {
+ if ((connection->bus_unique_name) != NULL)
+ g_dbus_message_set_sender(message, connection->bus_unique_name);
+ }
+#endif
+
blob = g_dbus_message_to_blob (message,
&blob_size,
connection->capabilities,
@@ -2591,6 +2603,10 @@ initable_init (GInitable *initable,
g_assert_not_reached ();
}
+ /* TODO: [KDBUS] Our kdbus daemon doesn't support connection authentication */
+ if (G_IS_KDBUS_CONNECTION (connection->stream))
+ goto authenticated;
+
/* Authenticate the connection */
if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER)
{
@@ -2629,6 +2645,8 @@ initable_init (GInitable *initable,
connection->authentication_observer = NULL;
}
+authenticated:
+
//g_output_stream_flush (G_SOCKET_CONNECTION (connection->stream)
//g_debug ("haz unix fd passing powers: %d", connection->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c
index 785a0c0..9d76708 100644
--- a/gio/gdbusprivate.c
+++ b/gio/gdbusprivate.c
@@ -1,6 +1,7 @@
/* GDBus - GLib D-Bus Library
*
* Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2013 Samsung Electronics
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,7 +18,9 @@
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Author: David Zeuthen <davidz at redhat.com>
+ * Author: David Zeuthen <davidz at redhat.com>
+ * Author: Lukasz Skalski <l.skalski at partner.samsung.com>
+ * Author: Michal Eljasiewicz <m.eljasiewicz at samsung.com>
*/
#include "config.h"
@@ -45,6 +48,7 @@
#include "gsocketoutputstream.h"
#ifdef G_OS_UNIX
+#include "gkdbusconnection.h"
#include "gunixfdmessage.h"
#include "gunixconnection.h"
#include "gunixcredentialsmessage.h"
@@ -117,6 +121,108 @@ typedef struct
gboolean from_mainloop;
} ReadWithControlData;
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+typedef struct
+{
+ GKdbus *kdbus;
+ GCancellable *cancellable;
+
+ GSimpleAsyncResult *simple;
+
+ gboolean from_mainloop;
+} ReadKdbusData;
+
+static void
+read_kdbus_data_free (ReadKdbusData *data)
+{
+ g_object_unref (data->kdbus);
+ if (data->cancellable != NULL)
+ g_object_unref (data->cancellable);
+ g_object_unref (data->simple);
+ g_free (data);
+}
+
+static gboolean
+_g_kdbus_read_ready (GKdbus *kdbus,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ ReadKdbusData *data = user_data;
+ GError *error;
+ gssize result;
+
+ error = NULL;
+
+ result = g_kdbus_receive (data->kdbus,
+ data->cancellable,
+ &error);
+ if (result >= 0)
+ {
+ g_simple_async_result_set_op_res_gssize (data->simple, result);
+ }
+ else
+ {
+ g_assert (error != NULL);
+ g_simple_async_result_take_error (data->simple, error);
+ }
+
+ if (data->from_mainloop)
+ g_simple_async_result_complete (data->simple);
+ else
+ g_simple_async_result_complete_in_idle (data->simple);
+
+ return FALSE;
+}
+
+static void
+_g_kdbus_read (GKdbus *kdbus,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ ReadKdbusData *data;
+ GSource *source;
+
+ data = g_new0 (ReadKdbusData, 1);
+ data->kdbus = g_object_ref (kdbus);
+ data->cancellable = cancellable != NULL ? g_object_ref (cancellable) : NULL;
+
+ data->simple = g_simple_async_result_new (G_OBJECT (kdbus),
+ callback,
+ user_data,
+ _g_kdbus_read);
+ g_simple_async_result_set_check_cancellable (data->simple, cancellable);
+
+ data->from_mainloop = TRUE;
+ source = g_kdbus_create_source (data->kdbus,
+ G_IO_IN,
+ cancellable);
+ g_source_set_callback (source,
+ (GSourceFunc) _g_kdbus_read_ready,
+ data,
+ (GDestroyNotify) read_kdbus_data_free);
+ g_source_attach (source, g_main_context_get_thread_default ());
+ g_source_unref (source);
+}
+
+static gssize
+_g_kdbus_read_finish (GKdbus *kdbus,
+ GAsyncResult *result,
+ GError **error)
+{
+ GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+
+ g_return_val_if_fail (G_IS_KDBUS (kdbus), -1);
+ g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == _g_kdbus_read);
+
+ if (g_simple_async_result_propagate_error (simple, error))
+ return -1;
+ else
+ return g_simple_async_result_get_op_res_gssize (simple);
+}
+
+#endif /* defined (G_OS_UNIX) && (KDBUS_TRANSPORT) */
+
static void
read_with_control_data_free (ReadWithControlData *data)
{
@@ -364,8 +470,11 @@ struct GDBusWorker
GDBusWorkerDisconnectedCallback disconnected_callback;
gpointer user_data;
- /* if not NULL, stream is GSocketConnection */
+ /* if GSocket and GKdbus are NULL, stream is GSocketConnection */
GSocket *socket;
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ GKdbus *kdbus;
+#endif
/* used for reading */
GMutex read_lock;
@@ -506,7 +615,7 @@ _g_dbus_worker_emit_message_about_to_be_sent (GDBusWorker *worker,
}
/* can only be called from private thread with read-lock held - takes ownership of @message */
-static void
+void
_g_dbus_worker_queue_or_deliver_received_message (GDBusWorker *worker,
GDBusMessage *message)
{
@@ -584,7 +693,25 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream,
goto out;
error = NULL;
- if (worker->socket == NULL)
+
+ if (FALSE)
+ {
+ }
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ else if (G_IS_KDBUS_CONNECTION (worker->stream))
+ {
+ bytes_read = _g_kdbus_read_finish (worker->kdbus,
+ res,
+ &error);
+
+ /* Set read_buffer pointer to KDBUS memory pool */
+ worker->read_buffer = g_kdbus_get_msg_buffer_ptr (worker->kdbus);
+
+ /* For KDBUS transport we don't have to read message header */
+ worker->read_buffer_bytes_wanted = bytes_read;
+ }
+#endif
+ else if (worker->socket == NULL)
bytes_read = g_input_stream_read_finish (g_io_stream_get_input_stream (worker->stream),
res,
&error);
@@ -819,6 +946,15 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream,
out:
g_mutex_unlock (&worker->read_lock);
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ /* release memory occupied by kdbus_msg */
+ if (G_IS_KDBUS_CONNECTION (worker->stream) && !g_kdbus_is_closed (worker->kdbus))
+ {
+ g_kdbus_release_kmsg (worker->kdbus);
+ worker->read_buffer = NULL;
+ }
+#endif
+
/* gives up the reference acquired when calling g_input_stream_read_async() */
_g_dbus_worker_unref (worker);
}
@@ -831,6 +967,23 @@ _g_dbus_worker_do_read_unlocked (GDBusWorker *worker)
* true, because only failing a read causes us to signal 'closed'.
*/
+ /* For KDBUS transport we don't have to alloc buffer, instead of it
+ * we use kdbus memory pool. On connection stage KDBUS client have
+ * to register a memory pool, large enough to carry all backlog of
+ * data enqueued for the connection.
+ */
+
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ if (G_IS_KDBUS_CONNECTION (worker->stream))
+ {
+ _g_kdbus_read(worker->kdbus,
+ worker->cancellable,
+ (GAsyncReadyCallback) _g_dbus_worker_do_read_cb,
+ _g_dbus_worker_ref (worker));
+ return;
+ }
+#endif
+
/* if bytes_wanted is zero, it means start reading a message */
if (worker->read_buffer_bytes_wanted == 0)
{
@@ -997,6 +1150,26 @@ write_message_continue_writing (MessageToWriteData *data)
simple = data->simple;
#endif
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ if (G_IS_KDBUS_CONNECTION (data->worker->stream))
+ {
+ GError *error;
+ error = NULL;
+ data->total_written = g_kdbus_send_message(data->worker,
+ data->worker->kdbus,
+ data->message,
+ data->blob,
+ data->blob_size,
+ data->worker->cancellable,
+ &error);
+
+ write_message_print_transport_debug (data->total_written, data);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ goto out;
+ }
+#endif
+
ostream = g_io_stream_get_output_stream (data->worker->stream);
#ifdef G_OS_UNIX
fd_list = g_dbus_message_get_unix_fd_list (data->message);
@@ -1452,9 +1625,17 @@ continue_writing (GDBusWorker *worker)
worker->close_expected = TRUE;
worker->output_pending = PENDING_CLOSE;
- g_io_stream_close_async (worker->stream, G_PRIORITY_DEFAULT,
- NULL, iostream_close_cb,
- _g_dbus_worker_ref (worker));
+ if (FALSE)
+ {
+ }
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ if (G_IS_KDBUS_CONNECTION (worker->stream))
+ g_kdbus_connection_close (worker->stream, NULL, NULL);
+#endif
+ else
+ g_io_stream_close_async (worker->stream, G_PRIORITY_DEFAULT,
+ NULL, iostream_close_cb,
+ _g_dbus_worker_ref (worker));
}
else
{
@@ -1677,6 +1858,12 @@ _g_dbus_worker_new (GIOStream *stream,
if (G_IS_SOCKET_CONNECTION (worker->stream))
worker->socket = g_socket_connection_get_socket (G_SOCKET_CONNECTION (worker->stream));
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ if (G_IS_KDBUS_CONNECTION (worker->stream))
+ worker->kdbus = g_kdbus_connection_get_kdbus (G_KDBUS_CONNECTION (worker->stream));
+#endif
+
+
worker->shared_thread_data = _g_dbus_shared_thread_ref ();
/* begin reading */
@@ -2156,12 +2343,11 @@ write_message_print_transport_debug (gssize bytes_written,
g_print ("========================================================================\n"
"GDBus-debug:Transport:\n"
" >>>> WROTE %" G_GSSIZE_FORMAT " bytes of message with serial %d and\n"
- " size %" G_GSIZE_FORMAT " from offset %" G_GSIZE_FORMAT " on a %s\n",
+ " size %" G_GSIZE_FORMAT " from offset %" G_GSIZE_FORMAT "\n",
bytes_written,
g_dbus_message_get_serial (data->message),
data->blob_size,
- data->total_written,
- g_type_name (G_TYPE_FROM_INSTANCE (g_io_stream_get_output_stream (data->worker->stream))));
+ data->total_written);
_g_dbus_debug_print_unlock ();
out:
;
@@ -2207,12 +2393,11 @@ read_message_print_transport_debug (gssize bytes_read,
g_print ("========================================================================\n"
"GDBus-debug:Transport:\n"
" <<<< READ %" G_GSSIZE_FORMAT " bytes of message with serial %d and\n"
- " size %d to offset %" G_GSIZE_FORMAT " from a %s\n",
+ " size %d to offset %" G_GSIZE_FORMAT "\n",
bytes_read,
serial,
message_length,
- worker->read_buffer_cur_size,
- g_type_name (G_TYPE_FROM_INSTANCE (g_io_stream_get_input_stream (worker->stream))));
+ worker->read_buffer_cur_size);
_g_dbus_debug_print_unlock ();
out:
;
diff --git a/gio/gdbusprivate.h b/gio/gdbusprivate.h
index 1bc503c..5b3046e 100644
--- a/gio/gdbusprivate.h
+++ b/gio/gdbusprivate.h
@@ -1,6 +1,7 @@
/* GDBus - GLib D-Bus Library
*
* Copyright (C) 2008-2010 Red Hat, Inc.
+ * Copyright (C) 2013 Samsung Electronics
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,7 +18,9 @@
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
- * Author: David Zeuthen <davidz at redhat.com>
+ * Author: David Zeuthen <davidz at redhat.com>
+ * Author: Lukasz Skalski <l.skalski at partner.samsung.com>
+ * Author: Michal Eljasiewicz <m.eljasiewic at samsung.com>
*/
#ifndef __G_DBUS_PRIVATE_H__
@@ -81,6 +84,9 @@ void _g_dbus_worker_close (GDBusWorker *worker,
GCancellable *cancellable,
GSimpleAsyncResult *result);
+/* kdbus transport needs this function to generate local messages */
+void _g_dbus_worker_queue_or_deliver_received_message (GDBusWorker *worker,
+ GDBusMessage *message);
/* ---------------------------------------------------------------------------------------------------- */
void _g_dbus_initialize (void);
diff --git a/gio/giotypes.h b/gio/giotypes.h
index 61f78a0..d2f2c92 100644
--- a/gio/giotypes.h
+++ b/gio/giotypes.h
@@ -254,6 +254,23 @@ typedef struct _GVolume GVolume; /* Dummy typedef */
typedef struct _GVolumeMonitor GVolumeMonitor;
/**
+ * GKdbus:
+ *
+ * A lowlevel kdbus object.
+ *
+ **/
+
+typedef struct _GKdbus GKdbus;
+
+/**
+ * GKdbusConnection:
+ *
+ * A kdbus connection GIOStream object.
+ *
+ **/
+typedef struct _GKdbusConnection GKdbusConnection;
+
+/**
* GAsyncReadyCallback:
* @source_object: the object the asynchronous operation was started with.
* @res: a #GAsyncResult.
@@ -390,6 +407,22 @@ typedef gboolean (*GSocketSourceFunc) (GSocket *socket,
gpointer user_data);
/**
+ * GKdbusSourceFunc:
+ * @socket: the #GKdbus
+ * @condition: the current condition at the source fired.
+ * @user_data: data passed in by the user.
+ *
+ * This is the function type of the callback used for the #GSource
+ * returned by g_kdbus_create_source().
+ *
+ * Returns: it should return %FALSE if the source should be removed.
+ *
+ */
+typedef gboolean (*GKdbusSourceFunc) (GKdbus *kdbus,
+ GIOCondition condition,
+ gpointer user_data);
+
+/**
* GInputVector:
* @buffer: Pointer to a buffer where data will be written.
* @size: the available size in @buffer.
--
1.8.4.rc3
More information about the systemd-devel
mailing list