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 <dav...@redhat.com> + * Author: David Zeuthen <dav...@redhat.com> + * Author: Lukasz Skalski <l.skal...@partner.samsung.com> + * Author: Michal Eljasiewicz <m.eljasie...@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 <dav...@redhat.com> + * Author: David Zeuthen <dav...@redhat.com> + * Author: Lukasz Skalski <l.skal...@partner.samsung.com> + * Author: Michal Eljasiewicz <m.eljasie...@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 <dav...@redhat.com> + * Author: David Zeuthen <dav...@redhat.com> + * Author: Lukasz Skalski <l.skal...@partner.samsung.com> + * Author: Michal Eljasiewicz <m.eljasiew...@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 <dav...@redhat.com> + * Author: David Zeuthen <dav...@redhat.com> + * Author: Lukasz Skalski <l.skal...@partner.samsung.com> + * Author: Michal Eljasiewicz <m.eljasie...@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 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel