[glib/wip/kdbus-junk: 29/37] [kdbus][wip] Import code from tizen.org repo
- From: Ryan Lortie <desrt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/wip/kdbus-junk: 29/37] [kdbus][wip] Import code from tizen.org repo
- Date: Wed, 10 Dec 2014 15:59:39 +0000 (UTC)
commit 1746044478e2734be6fed9bb0bee9e524685f578
Author: Lukasz Skalski <l skalski samsung com>
Date: Fri Nov 21 17:23:28 2014 +0100
[kdbus][wip] Import code from tizen.org repo
gio/gdbusconnection.c | 12 +
gio/gdbusmessage.c | 321 ++++++++++++++++++++-
gio/gdbusmessage.h | 10 +
gio/gdbusprivate.c | 195 +++++++++++---
gio/gkdbus.c | 754 ++++++++++++++++++++++++++++++++++++++++++++++++-
gio/gkdbus.h | 27 ++
6 files changed, 1260 insertions(+), 59 deletions(-)
---
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
index 55c2156..d9ee982 100644
--- a/gio/gdbusconnection.c
+++ b/gio/gdbusconnection.c
@@ -2124,6 +2124,18 @@ g_dbus_connection_send_message_unlocked (GDBusConnection *connection,
error))
goto out;
+ /* [KDBUS]
+ * Setting protocol version, before invoking g_dbus_message_to_blob() will
+ * be removed after preparing new function only for kdbus transport purposes
+ * (this function will be able to create blob directly/unconditionally in memfd
+ * object, without making copy)
+ */
+
+ if (G_IS_KDBUS_CONNECTION (connection->stream))
+ _g_dbus_message_set_protocol_ver (message,2);
+ else
+ _g_dbus_message_set_protocol_ver (message,1);
+
blob = g_dbus_message_to_blob (message,
&blob_size,
connection->capabilities,
diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c
index 766609e..bfe91e6 100644
--- a/gio/gdbusmessage.c
+++ b/gio/gdbusmessage.c
@@ -49,6 +49,7 @@
#include "gdbusprivate.h"
#ifdef G_OS_UNIX
+#include "gkdbus.h"
#include "gunixfdlist.h"
#endif
@@ -972,6 +973,38 @@ g_dbus_message_set_serial (GDBusMessage *message,
/* ---------------------------------------------------------------------------------------------------- */
+/**
+ * _g_dbus_message_get_protocol_ver:
+ * To remove - more info [1]
+ * [1] https://bugzilla.gnome.org/show_bug.cgi?id=721861
+ */
+guint32
+_g_dbus_message_get_protocol_ver (GDBusMessage *message)
+{
+ g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
+ return message->major_protocol_version;
+}
+
+/**
+ * _g_dbus_message_set_protocol_ver:
+ * To remove - more info [1]
+ * [1] https://bugzilla.gnome.org/show_bug.cgi?id=721861
+ */
+void
+_g_dbus_message_set_protocol_ver (GDBusMessage *message,
+ guint32 protocol_ver)
+{
+ g_return_if_fail (G_IS_DBUS_MESSAGE (message));
+
+ if (message->locked)
+ {
+ g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
+ return;
+ }
+
+ message->major_protocol_version = protocol_ver;
+}
+
/* TODO: need GI annotations to specify that any guchar value goes for header_field */
/**
@@ -2192,6 +2225,219 @@ g_dbus_message_new_from_blob (guchar *blob,
/* ---------------------------------------------------------------------------------------------------- */
+/*
+ * _g_dbus_message_new_from_kdbus_items:
+ *
+ * Single kdbus message may contain zero, one or more items
+ * (PAYLOAD_VEC or PAYLOAD_MEMFD), so we need this function
+ * (only for kdbus transport purposes) to parse them to GDBusMessage.
+ * kdbus_msg_items list contain list of pointer + data pair for each received item.
+ *
+ * TODO: Add support for two and more items
+ */
+
+GDBusMessage *
+_g_dbus_message_new_from_kdbus_items (GSList *kdbus_msg_items,
+ GError **error)
+{
+ gboolean ret;
+ GMemoryBuffer mbuf;
+ GDBusMessage *message;
+ guchar endianness;
+ guchar major_protocol_version;
+ guint32 message_body_len;
+ guint32 message_headers_len;
+ GVariant *headers;
+ GVariant *item;
+ GVariantIter iter;
+ GVariant *signature;
+
+ ret = FALSE;
+
+ g_return_val_if_fail (kdbus_msg_items != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ message = g_dbus_message_new ();
+ memset (&mbuf, 0, sizeof (mbuf));
+
+ /*
+ * MESSAGE HEADER
+ * message header in its entirety must be contained in a first single item
+ */
+ mbuf.data = ((msg_part*)kdbus_msg_items->data)->data;
+ mbuf.len = mbuf.valid_len = ((msg_part*)kdbus_msg_items->data)->size;
+
+ endianness = g_memory_buffer_read_byte (&mbuf);
+ switch (endianness)
+ {
+ case 'l':
+ mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
+ message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
+ break;
+ case 'B':
+ mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
+ message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
+ break;
+ default:
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid endianness value. Expected 0x6c ('l') or 0x42 ('B') but found value 0x%02x"),
+ endianness);
+ goto out;
+ }
+
+ message->type = g_memory_buffer_read_byte (&mbuf);
+ message->flags = g_memory_buffer_read_byte (&mbuf);
+ major_protocol_version = g_memory_buffer_read_byte (&mbuf);
+
+ if (major_protocol_version != 2)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid major protocol version. Expected 2 but found %d"),
+ major_protocol_version);
+ goto out;
+ }
+
+ message_body_len = g_memory_buffer_read_uint32 (&mbuf);
+ message->serial = g_memory_buffer_read_uint32 (&mbuf);
+
+ message_headers_len = g_memory_buffer_read_uint32 (&mbuf);
+ headers = g_variant_new_from_data (G_VARIANT_TYPE ("a{yv}"),
+ mbuf.data + mbuf.pos,
+ message_headers_len,
+ TRUE,
+ NULL,
+ NULL);
+ mbuf.pos += message_headers_len;
+
+ if (headers == NULL)
+ goto out;
+ g_variant_iter_init (&iter, headers);
+ while ((item = g_variant_iter_next_value (&iter)) != NULL)
+ {
+ guchar header_field;
+ GVariant *value;
+ g_variant_get (item,
+ "{yv}",
+ &header_field,
+ &value);
+ g_dbus_message_set_header (message, header_field, value);
+ g_variant_unref (value);
+ g_variant_unref (item);
+ }
+ g_variant_unref (headers);
+
+ signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
+ if (signature != NULL)
+ {
+ const gchar *signature_str;
+ gsize signature_str_len;
+
+ signature_str = g_variant_get_string (signature, &signature_str_len);
+
+ if (signature_str_len > 0)
+ {
+ GVariantType *variant_type;
+ gchar *tupled_signature_str;
+
+ gchar *data = NULL;
+ gsize size = NULL;
+
+ if (!g_variant_is_signature (signature_str))
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Parsed value '%s' is not a valid D-Bus signature (for body)"),
+ signature_str);
+ goto out;
+ }
+ tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
+ variant_type = g_variant_type_new (tupled_signature_str);
+ g_free (tupled_signature_str);
+
+ /*
+ * MESSAGE BODY
+ */
+
+ if (g_slist_length(kdbus_msg_items) == 1)
+ {
+ /* if kdbus_msg_items has only one element, head and body are
+ contained in a single PAYLOAD_VEC item */
+ ensure_input_padding (&mbuf,8);
+ data = mbuf.data + mbuf.pos;
+ size = message_body_len;
+ }
+ else if (g_slist_length(kdbus_msg_items) > 1)
+ {
+ /* message consists two or more items
+ TODO: Add support for three and more items */
+ data = ((msg_part*)g_slist_next(kdbus_msg_items)->data)->data;
+ size = ((msg_part*)g_slist_next(kdbus_msg_items)->data)->size;
+ }
+ else
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("[KDBUS] Received message is not valid"));
+ goto out;
+ }
+
+ message->body = g_variant_new_from_data (variant_type,
+ data,
+ size,
+ TRUE,
+ NULL,
+ NULL);
+
+ g_variant_type_free (variant_type);
+ if (message->body == NULL)
+ goto out;
+ }
+ }
+ else
+ {
+ /* no signature, this is only OK if the body is empty */
+ if (message_body_len != 0)
+ {
+ /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ g_dngettext (GETTEXT_PACKAGE,
+ "No signature header in message but the message body is %u byte",
+ "No signature header in message but the message body is %u bytes",
+ message_body_len),
+ message_body_len);
+ goto out;
+ }
+ }
+
+ if (!validate_headers (message, error))
+ {
+ g_prefix_error (error, _("Cannot deserialize message: "));
+ goto out;
+ }
+
+ ret = TRUE;
+
+ out:
+ if (ret)
+ {
+ return message;
+ }
+ else
+ {
+ if (message != NULL)
+ g_object_unref (message);
+ return NULL;
+ }
+}
+
static gsize
ensure_output_padding (GMemoryBuffer *mbuf,
gsize padding_size)
@@ -2567,6 +2813,12 @@ append_body_to_blob (GVariant *value,
/* ---------------------------------------------------------------------------------------------------- */
+/* [KDBUS]
+ * g_dbus_message_to_blob() will be replaced by new function only for kdbus transport
+ * purposes (this function will be able to create blob directly/unconditionally in memfd
+ * object, without making copy)
+ */
+
/**
* g_dbus_message_to_blob:
* @message: A #GDBusMessage.
@@ -2595,7 +2847,11 @@ g_dbus_message_to_blob (GDBusMessage *message,
goffset body_len_offset;
goffset body_start_offset;
gsize body_size;
+ gconstpointer message_body_data;
+ gsize message_body_size;
GVariant *header_fields;
+ gsize header_fields_size;
+ gconstpointer header_fields_data;
GVariantBuilder builder;
GHashTableIter hash_iter;
gpointer key;
@@ -2613,6 +2869,20 @@ g_dbus_message_to_blob (GDBusMessage *message,
g_return_val_if_fail (out_size != NULL, NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+ /* temporary solution */
+ if (!message->major_protocol_version)
+ g_error ("message->major_protocol_version is not set");
+
+ if (message->major_protocol_version != 1 && message->major_protocol_version != 2)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ _("Invalid major protocol version. Expected 1 or 2 but found %d"),
+ message->major_protocol_version);
+ goto out;
+ }
+
memset (&mbuf, 0, sizeof (mbuf));
mbuf.len = MIN_ARRAY_SIZE;
mbuf.data = g_malloc (mbuf.len);
@@ -2632,7 +2902,10 @@ g_dbus_message_to_blob (GDBusMessage *message,
g_memory_buffer_put_byte (&mbuf, (guchar) message->byte_order);
g_memory_buffer_put_byte (&mbuf, message->type);
g_memory_buffer_put_byte (&mbuf, message->flags);
- g_memory_buffer_put_byte (&mbuf, 1); /* major protocol version */
+
+ /* major protocol version */
+ g_memory_buffer_put_byte (&mbuf, message->major_protocol_version);
+
body_len_offset = mbuf.valid_len;
/* body length - will be filled in later */
g_memory_buffer_put_uint32 (&mbuf, 0xF00DFACE);
@@ -2672,15 +2945,30 @@ g_dbus_message_to_blob (GDBusMessage *message,
}
header_fields = g_variant_builder_end (&builder);
- if (!append_value_to_blob (header_fields,
- g_variant_get_type (header_fields),
- &mbuf,
- NULL,
- error))
+ /* header - dbus1 marshaliling */
+ if (message->major_protocol_version == 1)
{
- g_variant_unref (header_fields);
- goto out;
+ if (!append_value_to_blob (header_fields,
+ g_variant_get_type (header_fields),
+ &mbuf,
+ NULL,
+ error))
+ {
+ g_variant_unref (header_fields);
+ goto out;
+ }
+
}
+ /* header - GVariant marshalling */
+ else if (message->major_protocol_version == 2)
+ {
+ header_fields_data = g_variant_get_data (header_fields);
+ header_fields_size = g_variant_get_size (header_fields);
+
+ g_memory_buffer_put_uint32 (&mbuf, header_fields_size);
+ g_memory_buffer_write (&mbuf, header_fields_data, header_fields_size);
+ }
+
g_variant_unref (header_fields);
/* header size must be a multiple of 8 */
@@ -2717,8 +3005,21 @@ g_dbus_message_to_blob (GDBusMessage *message,
goto out;
}
g_free (tupled_signature_str);
- if (!append_body_to_blob (message->body, &mbuf, error))
- goto out;
+
+ /* body - dbus1 marshaliling */
+ if (message->major_protocol_version == 1)
+ {
+ if (!append_body_to_blob (message->body, &mbuf, error))
+ goto out;
+ }
+ /* body - GVariant marshalling */
+ else if (message->major_protocol_version == 2)
+ {
+ message_body_data = g_variant_get_data (message->body);
+ message_body_size = g_variant_get_size (message->body);
+
+ g_memory_buffer_write (&mbuf, message_body_data, message_body_size);
+ }
}
else
{
diff --git a/gio/gdbusmessage.h b/gio/gdbusmessage.h
index f791889..8f9b25e 100644
--- a/gio/gdbusmessage.h
+++ b/gio/gdbusmessage.h
@@ -192,6 +192,16 @@ GLIB_AVAILABLE_IN_ALL
gboolean g_dbus_message_to_gerror (GDBusMessage *message,
GError **error);
+GDBusMessage *_g_dbus_message_new_from_kdbus_items (GSList *kdbus_msg_items,
+ GError **error);
+
+/* to remove */
+guint32 _g_dbus_message_get_protocol_ver (GDBusMessage *message);
+
+/* to remove */
+void _g_dbus_message_set_protocol_ver (GDBusMessage *message,
+ guint32 protocol_ver);
+
G_END_DECLS
#endif /* __G_DBUS_MESSAGE_H__ */
diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c
index 91feb41..e3f1cda 100644
--- a/gio/gdbusprivate.c
+++ b/gio/gdbusprivate.c
@@ -477,6 +477,10 @@ struct GDBusWorker
GUnixFDList *read_fd_list;
GSocketControlMessage **read_ancillary_messages;
gint read_num_ancillary_messages;
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ GSList *read_kdbus_msg_items;
+#endif
+
/* Whether an async write, flush or close, or none of those, is pending.
* Only the worker thread may change its value, and only with the write_lock.
@@ -697,7 +701,15 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream,
bytes_read = _g_kdbus_read_finish (worker->kdbus,
res,
&error);
- g_error ("[KDBUS] _g_dbus_worker_do_read_cb() - work in progress");
+
+ /* [KDBUS] Get all received items*/
+ worker->read_kdbus_msg_items = _g_kdbus_get_last_msg_items (worker->kdbus);
+
+ /* [KDBUS] Attach fds (if any) to worker->read_fd_list */
+ _g_kdbus_attach_fds_to_msg (worker->kdbus, &worker->read_fd_list);
+
+ /* [KDBUS] For KDBUS transport we read whole message at once*/
+ worker->read_buffer_bytes_wanted = bytes_read;
}
#endif
else if (worker->socket == NULL)
@@ -779,9 +791,8 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream,
_g_dbus_debug_print_lock ();
g_print ("========================================================================\n"
"GDBus-debug:Transport:\n"
- " ---- READ ERROR on stream of type %s:\n"
+ " ---- READ ERROR:\n"
" ---- %s %d: %s\n",
- g_type_name (G_TYPE_FROM_INSTANCE (g_io_stream_get_input_stream (worker->stream))),
g_quark_to_string (error->domain), error->code,
error->message);
_g_dbus_debug_print_unlock ();
@@ -835,7 +846,9 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream,
goto out;
}
- read_message_print_transport_debug (bytes_read, worker);
+ /* [KDBUS] don't print transport dbus debug for kdbus connection */
+ if (!G_IS_KDBUS_CONNECTION (worker->stream))
+ read_message_print_transport_debug (bytes_read, worker);
worker->read_buffer_cur_size += bytes_read;
if (worker->read_buffer_bytes_wanted == worker->read_buffer_cur_size)
@@ -867,25 +880,61 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream,
/* TODO: use connection->priv->auth to decode the message */
- message = g_dbus_message_new_from_blob ((guchar *) worker->read_buffer,
- worker->read_buffer_cur_size,
- worker->capabilities,
- &error);
- if (message == NULL)
+ if (FALSE)
{
- gchar *s;
- s = _g_dbus_hexdump (worker->read_buffer, worker->read_buffer_cur_size, 2);
- g_warning ("Error decoding D-Bus message of %" G_GSIZE_FORMAT " bytes\n"
- "The error is: %s\n"
- "The payload is as follows:\n"
- "%s\n",
- worker->read_buffer_cur_size,
- error->message,
- s);
- g_free (s);
- _g_dbus_worker_emit_disconnected (worker, FALSE, error);
- g_error_free (error);
- goto out;
+ }
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ else if (G_IS_KDBUS_CONNECTION (worker->stream))
+ {
+ GDBusMessageType message_type;
+ gchar *sender;
+ gchar *destination;
+
+ message = _g_dbus_message_new_from_kdbus_items (worker->read_kdbus_msg_items,
+ &error);
+
+ /* [KDBUS] override informations from the user header with kernel msg header */
+ sender = _g_kdbus_get_last_msg_sender (worker->kdbus);
+ g_dbus_message_set_sender (message, sender);
+
+ message_type = g_dbus_message_get_message_type (message);
+ if (message_type == G_DBUS_MESSAGE_TYPE_SIGNAL)
+ {
+ destination = _g_kdbus_get_last_msg_destination (worker->kdbus);
+ g_dbus_message_set_destination (message, destination);
+ }
+
+ if (message == NULL)
+ {
+ g_warning ("Error decoding D-Bus (kdbus) message\n");
+ g_error_free (error);
+ goto out;
+ }
+ }
+#endif
+ else
+ {
+ message = g_dbus_message_new_from_blob ((guchar *) worker->read_buffer,
+ worker->read_buffer_cur_size,
+ worker->capabilities,
+ &error);
+
+ if (message == NULL)
+ {
+ gchar *s;
+ s = _g_dbus_hexdump (worker->read_buffer, worker->read_buffer_cur_size, 2);
+ g_warning ("Error decoding D-Bus message of %" G_GSIZE_FORMAT " bytes\n"
+ "The error is: %s\n"
+ "The payload is as follows:\n"
+ "%s\n",
+ worker->read_buffer_cur_size,
+ error->message,
+ s);
+ g_free (s);
+ _g_dbus_worker_emit_disconnected (worker, FALSE, error);
+ g_error_free (error);
+ goto out;
+ }
}
#ifdef G_OS_UNIX
@@ -910,7 +959,15 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream,
g_free (s);
if (G_UNLIKELY (_g_dbus_debug_payload ()))
{
- s = _g_dbus_hexdump (worker->read_buffer, worker->read_buffer_cur_size, 2);
+ if (FALSE)
+ {
+ }
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ else if (G_IS_KDBUS_CONNECTION (worker->stream))
+ s = _g_kdbus_hexdump_all_items (worker->read_kdbus_msg_items);
+#endif
+ else
+ s = _g_dbus_hexdump (worker->read_buffer, worker->read_buffer_cur_size, 2);
g_print ("%s\n", s);
g_free (s);
}
@@ -933,6 +990,20 @@ _g_dbus_worker_do_read_cb (GInputStream *input_stream,
}
out:
+
+#if defined (G_OS_UNIX) && (KDBUS_TRANSPORT)
+ /* [KDBUS] release memory occupied by kdbus message */
+ if (G_IS_KDBUS_CONNECTION (worker->stream))
+ {
+ if (!_g_kdbus_is_closed (worker->kdbus))
+ {
+ _g_kdbus_release_kmsg (worker->kdbus);
+ worker->read_kdbus_msg_items = NULL;
+ }
+ worker->read_buffer = NULL;
+ }
+#endif
+
g_mutex_unlock (&worker->read_lock);
/* gives up the reference acquired when calling g_input_stream_read_async() */
@@ -1119,22 +1190,41 @@ static void
write_message_continue_writing (MessageToWriteData *data)
{
GOutputStream *ostream;
+
#ifdef G_OS_UNIX
GSimpleAsyncResult *simple;
GUnixFDList *fd_list;
-#endif
-#ifdef G_OS_UNIX
/* Note: we can't access data->simple after calling g_async_result_complete () because the
* callback can free @data and we're not completing in idle. So use a copy of the pointer.
*/
simple = data->simple;
-#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);
-#endif
+
+#ifdef KDBUS_TRANSPORT
+ if (G_IS_KDBUS_CONNECTION (data->worker->stream))
+ {
+ GError *error;
+ error = NULL;
+ data->total_written = _g_kdbus_send (data->worker,
+ data->worker->kdbus,
+ data->message,
+ data->blob,
+ data->blob_size,
+ fd_list,
+ data->worker->cancellable,
+ &error);
+
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ goto out;
+ }
+#endif /* KDBUS_TRANSPORT */
+
+#endif /* G_OS_UNIX */
+
+ ostream = g_io_stream_get_output_stream (data->worker->stream);
g_assert (!g_output_stream_has_pending (ostream));
g_assert_cmpint (data->total_written, <, data->blob_size);
@@ -1370,11 +1460,33 @@ ostream_flush_cb (GObject *source_object,
static void
start_flush (FlushAsyncData *data)
{
- g_output_stream_flush_async (g_io_stream_get_output_stream (data->worker->stream),
- G_PRIORITY_DEFAULT,
- data->worker->cancellable,
- ostream_flush_cb,
- data);
+ /*[KDBUS]: TODO: to investigate */
+ if (G_IS_KDBUS_CONNECTION (data->worker->stream))
+ {
+ g_assert (data->flushers != NULL);
+ flush_data_list_complete (data->flushers, NULL);
+ g_list_free (data->flushers);
+
+ g_mutex_lock (&data->worker->write_lock);
+ data->worker->write_num_messages_flushed = data->worker->write_num_messages_written;
+ g_assert (data->worker->output_pending == PENDING_FLUSH);
+ data->worker->output_pending = PENDING_NONE;
+ g_mutex_unlock (&data->worker->write_lock);
+
+ /* OK, cool, finally kick off the next write */
+ continue_writing (data->worker);
+
+ _g_dbus_worker_unref (data->worker);
+ g_free (data);
+ }
+ else
+ {
+ g_output_stream_flush_async (g_io_stream_get_output_stream (data->worker->stream),
+ G_PRIORITY_DEFAULT,
+ data->worker->cancellable,
+ ostream_flush_cb,
+ data);
+ }
}
/* called in private thread shared by all GDBusConnection instances
@@ -1645,6 +1757,21 @@ continue_writing (GDBusWorker *worker)
{
/* filters altered the message -> reencode */
error = NULL;
+
+ /* [KDBUS]
+ * Setting protocol version, before invoking g_dbus_message_to_blob() will
+ * be removed after preparing new function only for kdbus transport purposes
+ * (this function will be able to create blob directly/unconditionally in memfd
+ * object, without making copy):
+ *
+ * [1] https://code.google.com/p/d-bus/source/browse/TODO
+ */
+
+ if (G_IS_KDBUS_CONNECTION (worker->stream))
+ _g_dbus_message_set_protocol_ver (data->message,2);
+ else
+ _g_dbus_message_set_protocol_ver (data->message,1);
+
new_blob = g_dbus_message_to_blob (data->message,
&new_blob_size,
worker->capabilities,
diff --git a/gio/gkdbus.c b/gio/gkdbus.c
index e612b8f..fabeba0 100644
--- a/gio/gkdbus.c
+++ b/gio/gkdbus.c
@@ -34,6 +34,7 @@
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <stdio.h>
+#include <stdint.h>
#ifdef HAVE_SYS_FILIO_H
# include <sys/filio.h>
@@ -43,6 +44,13 @@
#include <sys/uio.h>
#endif
+#include <glib/gstdio.h>
+#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
+
+#include "glibintl.h"
+#include "gunixfdmessage.h"
+
#define KDBUS_POOL_SIZE (16 * 1024LU * 1024LU)
#define KDBUS_ALIGN8(l) (((l) + 7) & ~7)
#define KDBUS_ALIGN8_PTR(p) ((void*) (uintptr_t)(p))
@@ -93,6 +101,16 @@ struct _GKdbusPrivate
guint64 attach_flags_send;
guint64 attach_flags_recv;
+ GString *msg_sender;
+ GString *msg_destination;
+ GSList *kdbus_msg_items;
+
+ gint *fds;
+ gint num_fds;
+
+ gsize bloom_size;
+ guint bloom_n_hash;
+
guint closed : 1;
guint inited : 1;
guint timeout;
@@ -117,6 +135,94 @@ typedef gboolean (*GKdbusSourceFunc) (GKdbus *kdbus,
GIOCondition condition,
gpointer user_data);
+/* Hash keys for bloom filters*/
+const guint8 hash_keys[8][16] =
+{
+ {0xb9,0x66,0x0b,0xf0,0x46,0x70,0x47,0xc1,0x88,0x75,0xc4,0x9c,0x54,0xb9,0xbd,0x15},
+ {0xaa,0xa1,0x54,0xa2,0xe0,0x71,0x4b,0x39,0xbf,0xe1,0xdd,0x2e,0x9f,0xc5,0x4a,0x3b},
+ {0x63,0xfd,0xae,0xbe,0xcd,0x82,0x48,0x12,0xa1,0x6e,0x41,0x26,0xcb,0xfa,0xa0,0xc8},
+ {0x23,0xbe,0x45,0x29,0x32,0xd2,0x46,0x2d,0x82,0x03,0x52,0x28,0xfe,0x37,0x17,0xf5},
+ {0x56,0x3b,0xbf,0xee,0x5a,0x4f,0x43,0x39,0xaf,0xaa,0x94,0x08,0xdf,0xf0,0xfc,0x10},
+ {0x31,0x80,0xc8,0x73,0xc7,0xea,0x46,0xd3,0xaa,0x25,0x75,0x0f,0x9e,0x4c,0x09,0x29},
+ {0x7d,0xf7,0x18,0x4b,0x7b,0xa4,0x44,0xd5,0x85,0x3c,0x06,0xe0,0x65,0x53,0x96,0x6d},
+ {0xf2,0x77,0xe9,0x6f,0x93,0xb5,0x4e,0x71,0x9a,0x0c,0x34,0x88,0x39,0x25,0xbf,0x35}
+};
+
+
+/**
+ * _g_kdbus_get_last_msg_sender
+ *
+ */
+gchar *
+_g_kdbus_get_last_msg_sender (GKdbus *kdbus)
+{
+ return kdbus->priv->msg_sender->str;
+}
+
+
+/**
+ * _g_kdbus_get_last_msg_destination
+ *
+ */
+gchar *
+_g_kdbus_get_last_msg_destination (GKdbus *kdbus)
+{
+ return kdbus->priv->msg_destination->str;
+}
+
+
+/**
+ * _g_kdbus_get_last_msg_items:
+ *
+ */
+GSList *
+_g_kdbus_get_last_msg_items (GKdbus *kdbus)
+{
+ return kdbus->priv->kdbus_msg_items;
+}
+
+
+/**
+ * g_kdbus_add_msg_part:
+ *
+ */
+static void
+g_kdbus_add_msg_part (GKdbus *kdbus,
+ gchar *data,
+ gsize size)
+{
+ msg_part* part = g_new (msg_part, 1);
+ part->data = data;
+ part->size = size;
+ kdbus->priv->kdbus_msg_items = g_slist_append (kdbus->priv->kdbus_msg_items, part);
+}
+
+
+/**
+ * _g_kdbus_hexdump_all_items:
+ *
+ */
+gchar *
+_g_kdbus_hexdump_all_items (GSList *kdbus_msg_items)
+{
+
+ GString *ret;
+ gint item = 1;
+ ret = g_string_new (NULL);
+
+ while (kdbus_msg_items != NULL)
+ {
+ g_string_append_printf (ret, "\n Item %d\n", item);
+ g_string_append (ret, _g_dbus_hexdump (((msg_part*)kdbus_msg_items->data)->data,
((msg_part*)kdbus_msg_items->data)->size, 2));
+
+ kdbus_msg_items = g_slist_next(kdbus_msg_items);
+ item++;
+ }
+
+ return g_string_free (ret, FALSE);
+}
+
+
/**
* g_kdbus_finalize:
*
@@ -134,6 +240,9 @@ g_kdbus_finalize (GObject *object)
if (kdbus->priv->fd != -1 && !kdbus->priv->closed)
_g_kdbus_close (kdbus, NULL);
+ g_string_free (kdbus->priv->msg_sender, TRUE);
+ g_string_free (kdbus->priv->msg_destination, TRUE);
+
if (G_OBJECT_CLASS (g_kdbus_parent_class)->finalize)
(*G_OBJECT_CLASS (g_kdbus_parent_class)->finalize) (object);
}
@@ -179,10 +288,17 @@ g_kdbus_init (GKdbus *kdbus)
kdbus->priv->unique_name = NULL;
kdbus->priv->kdbus_buffer = NULL;
+ kdbus->priv->kdbus_msg_items = NULL;
+
+ kdbus->priv->msg_sender = g_string_new (NULL);
+ kdbus->priv->msg_destination = g_string_new (NULL);
kdbus->priv->flags = 0; /* KDBUS_HELLO_ACCEPT_FD */
kdbus->priv->attach_flags_send = _KDBUS_ATTACH_ALL;
kdbus->priv->attach_flags_recv = _KDBUS_ATTACH_ALL;
+
+ kdbus->priv->fds = NULL;
+ kdbus->priv->num_fds = 0;
}
@@ -288,7 +404,6 @@ kdbus_source_dispatch (GSource *source,
if (kdbus->priv->timeout)
kdbus_source->timeout_time = g_get_monotonic_time ()
+ kdbus->priv->timeout * 1000000;
-
else
kdbus_source->timeout_time = 0;
@@ -609,11 +724,15 @@ _g_kdbus_Hello (GIOStream *stream,
kdbus->priv->unique_id = hello->id;
asprintf(&kdbus->priv->unique_name, ":1.%llu", (unsigned long long) hello->id);
+ /* read bloom filters parameters */
+ kdbus->priv->bloom_size = (gsize) hello->bloom.size;
+ kdbus->priv->bloom_n_hash = (guint) hello->bloom.n_hash;
+
return g_variant_new ("(s)", kdbus->priv->unique_name);
}
-/*
+/**
* _g_kdbus_RequestName:
*
*/
@@ -697,7 +816,7 @@ _g_kdbus_RequestName (GDBusConnection *connection,
}
-/*
+/**
* _g_kdbus_ReleaseName:
*
*/
@@ -1198,7 +1317,7 @@ _g_kdbus_GetConnectionUnixUser (GDBusConnection *connection,
}
-/*
+/**
* _g_kdbus_match_remove:
*
*/
@@ -1221,7 +1340,7 @@ _g_kdbus_match_remove (GDBusConnection *connection,
}
-/*
+/**
* _g_kdbus_subscribe_name_acquired:
*
*/
@@ -1296,7 +1415,7 @@ _g_kdbus_subscribe_name_owner_changed (GDBusConnection *connection,
}
-/*
+/**
* _g_kdbus_subscribe_name_acquired:
*
*/
@@ -1341,7 +1460,7 @@ _g_kdbus_subscribe_name_acquired (GDBusConnection *connection,
}
-/*
+/**
* _g_kdbus_subscribe_name_lost:
*
*/
@@ -1386,7 +1505,7 @@ _g_kdbus_subscribe_name_lost (GDBusConnection *connection,
}
-/*
+/**
* _g_kdbus_unsubscribe_name_acquired:
*
*/
@@ -1400,7 +1519,7 @@ _g_kdbus_unsubscribe_name_acquired (GDBusConnection *connection)
}
-/*
+/**
* _g_kdbus_unsubscribe_name_lost:
*
*/
@@ -1415,9 +1534,334 @@ _g_kdbus_unsubscribe_name_lost (GDBusConnection *connection)
/**
-* g_kdbus_decode_kernel_msg:
-*
-*/
+ * _g_kdbus_release_msg:
+ *
+ */
+void
+_g_kdbus_release_kmsg (GKdbus *kdbus)
+{
+ struct kdbus_item *item = NULL;
+ GSList *iterator = NULL;
+ guint64 offset;
+
+ offset = (guint8 *)kdbus->priv->kmsg - (guint8 *)kdbus->priv->kdbus_buffer;
+ ioctl(kdbus->priv->fd, KDBUS_CMD_FREE, &offset);
+
+ for (iterator = kdbus->priv->kdbus_msg_items; iterator; iterator = iterator->next)
+ g_free ((msg_part*)iterator->data);
+
+ g_slist_free (kdbus->priv->kdbus_msg_items);
+ kdbus->priv->kdbus_msg_items = NULL;
+
+ KDBUS_ITEM_FOREACH (item, kdbus->priv->kmsg, items)
+ {
+ if (item->type == KDBUS_ITEM_PAYLOAD_MEMFD)
+ close(item->memfd.fd);
+ else if (item->type == KDBUS_ITEM_FDS)
+ {
+ gint i;
+ gint num_fds = (item->size - G_STRUCT_OFFSET(struct kdbus_item, fds)) / sizeof(int);
+
+ for (i = 0; i < num_fds; i++)
+ close(item->fds[i]);
+ }
+ }
+}
+
+
+/**
+ * g_kdbus_append_payload_vec:
+ *
+ */
+static void
+g_kdbus_append_payload_vec (struct kdbus_item **item,
+ const void *data_ptr,
+ gssize size)
+{
+ *item = KDBUS_ALIGN8_PTR(*item);
+ (*item)->size = G_STRUCT_OFFSET (struct kdbus_item, vec) + sizeof(struct kdbus_vec);
+ (*item)->type = KDBUS_ITEM_PAYLOAD_VEC;
+ (*item)->vec.address = (guint64)((guintptr)data_ptr);
+ (*item)->vec.size = size;
+ *item = KDBUS_ITEM_NEXT(*item);
+}
+
+
+/**
+ * g_kdbus_append_payload_destiantion:
+ *
+ */
+static void
+g_kdbus_append_destination (struct kdbus_item **item,
+ const gchar *destination,
+ gsize size)
+{
+ *item = KDBUS_ALIGN8_PTR(*item);
+ (*item)->size = G_STRUCT_OFFSET (struct kdbus_item, str) + size + 1;
+ (*item)->type = KDBUS_ITEM_DST_NAME;
+ memcpy ((*item)->str, destination, size+1);
+ *item = KDBUS_ITEM_NEXT(*item);
+}
+
+
+/**
+ * g_kdbus_append_payload_bloom:
+ *
+ */
+static struct kdbus_bloom_filter *
+g_kdbus_append_bloom (struct kdbus_item **item,
+ gsize size)
+{
+ struct kdbus_item *bloom_item;
+
+ bloom_item = KDBUS_ALIGN8_PTR(*item);
+ bloom_item->size = G_STRUCT_OFFSET (struct kdbus_item, bloom_filter) +
+ G_STRUCT_OFFSET (struct kdbus_bloom_filter, data) +
+ size;
+
+ bloom_item->type = KDBUS_ITEM_BLOOM_FILTER;
+
+ *item = KDBUS_ITEM_NEXT(bloom_item);
+ return &bloom_item->bloom_filter;
+}
+
+
+/**
+ * g_kdbus_append_fds:
+ *
+ */
+static void
+g_kdbus_append_fds (struct kdbus_item **item,
+ GUnixFDList *fd_list)
+{
+ *item = KDBUS_ALIGN8_PTR(*item);
+ (*item)->size = G_STRUCT_OFFSET (struct kdbus_item, fds) + sizeof(int) *
g_unix_fd_list_get_length(fd_list);
+ (*item)->type = KDBUS_ITEM_FDS;
+ memcpy ((*item)->fds, g_unix_fd_list_peek_fds(fd_list, NULL), sizeof(int) *
g_unix_fd_list_get_length(fd_list));
+
+ *item = KDBUS_ITEM_NEXT(*item);
+}
+
+
+/**
+ * _g_kdbus_attach_fds_to_msg:
+ *
+ */
+void
+_g_kdbus_attach_fds_to_msg (GKdbus *kdbus,
+ GUnixFDList **fd_list)
+{
+ if ((kdbus->priv->fds != NULL) && (kdbus->priv->num_fds > 0))
+ {
+ gint n;
+
+ if (*fd_list == NULL)
+ *fd_list = g_unix_fd_list_new();
+
+ for (n = 0; n < kdbus->priv->num_fds; n++)
+ {
+ g_unix_fd_list_append (*fd_list, kdbus->priv->fds[n], NULL);
+ (void) g_close (kdbus->priv->fds[n], NULL);
+ }
+
+ g_free (kdbus->priv->fds);
+ kdbus->priv->fds = NULL;
+ kdbus->priv->num_fds = 0;
+ }
+}
+
+/**
+ * g_kdbus_bloom_add_data:
+ * Based on bus-bloom.c from systemd
+ * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
+ */
+static void
+g_kdbus_bloom_add_data (GKdbus *kdbus,
+ guint64 bloom_data [],
+ const void *data,
+ gsize n)
+{
+ guint8 hash[8];
+ guint64 bit_num;
+ guint bytes_num = 0;
+ guint cnt_1, cnt_2;
+
+ guint c = 0;
+ guint64 p = 0;
+
+ bit_num = kdbus->priv->bloom_size * 8;
+
+ if (bit_num > 1)
+ bytes_num = ((__builtin_clzll(bit_num) ^ 63U) + 7) / 8;
+
+ for (cnt_1 = 0; cnt_1 < (kdbus->priv->bloom_n_hash); cnt_1++)
+ {
+ for (cnt_2 = 0; cnt_2 < bytes_num; cnt_2++)
+ {
+ if (c <= 0)
+ {
+ g_siphash24(hash, data, n, hash_keys[cnt_1++]);
+ c += 8;
+ }
+
+ p = (p << 8ULL) | (guint64) hash[8 - c];
+ c--;
+ }
+
+ p &= bit_num - 1;
+ bloom_data[p >> 6] |= 1ULL << (p & 63);
+ }
+}
+
+
+/**
+ * g_kdbus_bloom_add_pair:
+ *
+ */
+static void
+g_kdbus_bloom_add_pair (GKdbus *kdbus,
+ guint64 bloom_data [],
+ const gchar *parameter,
+ const gchar *value)
+{
+ GString *data = g_string_new (NULL);
+
+ g_string_printf (data,"%s:%s",parameter,value);
+ g_kdbus_bloom_add_data(kdbus, bloom_data, data->str, data->len);
+ g_string_free (data, TRUE);
+}
+
+
+/**
+ * g_kdbus_bloom_add_prefixes:
+ *
+ */
+static void
+g_kdbus_bloom_add_prefixes (GKdbus *kdbus,
+ guint64 bloom_data [],
+ const gchar *parameter,
+ const gchar *value,
+ gchar separator)
+{
+ GString *data = g_string_new (NULL);
+
+ g_string_printf (data,"%s:%s",parameter,value);
+
+ for (;;)
+ {
+ gchar *last_sep;
+ last_sep = strrchr(data->str, separator);
+ if (!last_sep || last_sep == data->str)
+ break;
+
+ *last_sep = 0;
+ g_kdbus_bloom_add_data(kdbus, bloom_data, data->str, last_sep-(data->str));
+ }
+ g_string_free (data, TRUE);
+}
+
+
+/**
+ * g_kdbus_setup_bloom:
+ * Based on bus-bloom.c from systemd
+ * http://cgit.freedesktop.org/systemd/systemd/tree/src/libsystemd/sd-bus/bus-bloom.c
+ */
+static void
+g_kdbus_setup_bloom (GKdbus *kdbus,
+ GDBusMessage *dbus_msg,
+ struct kdbus_bloom_filter *bloom_filter)
+{
+ GVariant *body;
+ GVariantIter iter;
+ GVariant *child;
+
+ const gchar *message_type;
+ const gchar *interface;
+ const gchar *member;
+ const gchar *path;
+
+ void *bloom_data;
+ gint cnt = 0;
+
+ body = g_dbus_message_get_body (dbus_msg);
+ message_type = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, g_dbus_message_get_message_type
(dbus_msg));
+ interface = g_dbus_message_get_interface (dbus_msg);
+ member = g_dbus_message_get_member (dbus_msg);
+ path = g_dbus_message_get_path (dbus_msg);
+
+ bloom_data = bloom_filter->data;
+ memset (bloom_data, 0, kdbus->priv->bloom_size);
+ bloom_filter->generation = 0;
+
+ g_kdbus_bloom_add_pair(kdbus, bloom_data, "message-type", message_type);
+
+ if (interface)
+ g_kdbus_bloom_add_pair(kdbus, bloom_data, "interface", interface);
+
+ if (member)
+ g_kdbus_bloom_add_pair(kdbus, bloom_data, "member", member);
+
+ if (path)
+ {
+ g_kdbus_bloom_add_pair(kdbus, bloom_data, "path", path);
+ g_kdbus_bloom_add_pair(kdbus, bloom_data, "path-slash-prefix", path);
+ g_kdbus_bloom_add_prefixes(kdbus, bloom_data, "path-slash-prefix", path, '/');
+ }
+
+ if (body != NULL)
+ {
+ g_variant_iter_init (&iter, body);
+ while ((child = g_variant_iter_next_value (&iter)))
+ {
+ gchar buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
+ gchar *child_string;
+ gchar *e;
+
+ /* Is it necessary? */
+ //if (g_variant_is_container (child))
+ // iterate_container_recursive (child);
+
+ if (!(g_variant_is_of_type (child, G_VARIANT_TYPE_STRING)) &&
+ !(g_variant_is_of_type (child, G_VARIANT_TYPE_OBJECT_PATH)) &&
+ !(g_variant_is_of_type (child, G_VARIANT_TYPE_SIGNATURE)))
+ break;
+
+ child_string = g_variant_dup_string (child, NULL);
+
+ e = stpcpy(buf, "arg");
+ if (cnt < 10)
+ *(e++) = '0' + (char) cnt;
+ else
+ {
+ *(e++) = '0' + (char) (cnt / 10);
+ *(e++) = '0' + (char) (cnt % 10);
+ }
+
+ *e = 0;
+ g_kdbus_bloom_add_pair(kdbus, bloom_data, buf, child_string);
+
+ strcpy(e, "-dot-prefix");
+ g_kdbus_bloom_add_prefixes(kdbus, bloom_data, buf, child_string, '.');
+
+ strcpy(e, "-slash-prefix");
+ g_kdbus_bloom_add_prefixes(kdbus, bloom_data, buf, child_string, '/');
+
+ g_free (child_string);
+ g_variant_unref (child);
+ cnt++;
+ }
+ }
+}
+
+
+/*
+ * TODO: g_kdbus_NameOwnerChanged_generate, g_kdbus_KernelMethodError_generate
+ */
+
+/**
+ * g_kdbus_decode_kernel_msg:
+ *
+ */
static gssize
g_kdbus_decode_kernel_msg (GKdbus *kdbus)
{
@@ -1448,7 +1892,7 @@ g_kdbus_decode_kernel_msg (GKdbus *kdbus)
}
}
-#if 0
+
/* Override information from the user header with data from the kernel */
g_string_printf (kdbus->priv->msg_sender, "org.freedesktop.DBus");
@@ -1460,13 +1904,120 @@ g_kdbus_decode_kernel_msg (GKdbus *kdbus)
g_string_printf (kdbus->priv->msg_destination, ":1.%" G_GUINT64_FORMAT, (guint64)
kdbus->priv->unique_id);
else
g_string_printf (kdbus->priv->msg_destination, ":1.%" G_GUINT64_FORMAT, (guint64)
kdbus->priv->kmsg->dst_id);
-#endif
return size;
}
/**
+ * g_kdbus_decode_dbus_msg:
+ *
+ */
+static gssize
+g_kdbus_decode_dbus_msg (GKdbus *kdbus)
+{
+ struct kdbus_item *item;
+ gchar *msg_ptr;
+ gssize ret_size = 0;
+ gssize data_size = 0;
+ const gchar *destination = NULL;
+
+ KDBUS_ITEM_FOREACH(item, kdbus->priv->kmsg, items)
+ {
+ if (item->size <= KDBUS_ITEM_HEADER_SIZE)
+ g_error("[KDBUS] %llu bytes - invalid data record\n", item->size);
+
+ data_size = item->size - KDBUS_ITEM_HEADER_SIZE;
+
+ switch (item->type)
+ {
+
+ /* KDBUS_ITEM_DST_NAME */
+ case KDBUS_ITEM_DST_NAME:
+ destination = item->str;
+ break;
+
+ /* KDBUS_ITEM_PALOAD_OFF */
+ case KDBUS_ITEM_PAYLOAD_OFF:
+
+ msg_ptr = (gchar*) kdbus->priv->kmsg + item->vec.offset;
+ g_kdbus_add_msg_part (kdbus, msg_ptr, item->vec.size);
+ ret_size += item->vec.size;
+
+ break;
+
+ /* KDBUS_ITEM_PAYLOAD_MEMFD */
+ case KDBUS_ITEM_PAYLOAD_MEMFD:
+
+ msg_ptr = mmap(NULL, item->memfd.size, PROT_READ, MAP_SHARED, item->memfd.fd, 0);
+
+ if (msg_ptr == MAP_FAILED)
+ {
+ g_print ("mmap() fd=%i failed:%m", item->memfd.fd);
+ break;
+ }
+
+ g_kdbus_add_msg_part (kdbus, msg_ptr, item->memfd.size);
+ ret_size += item->memfd.size;
+
+ break;
+
+ /* KDBUS_ITEM_FDS */
+ case KDBUS_ITEM_FDS:
+
+ kdbus->priv->num_fds = data_size / sizeof(int);
+ kdbus->priv->fds = g_malloc0 (sizeof(int) * kdbus->priv->num_fds);
+ memcpy(kdbus->priv->fds, item->fds, sizeof(int) * kdbus->priv->num_fds);
+
+ break;
+
+ /* All of the following items, like CMDLINE,
+ CGROUP, etc. need some GDBUS API extensions and
+ should be implemented in the future */
+ case KDBUS_ITEM_CREDS:
+ case KDBUS_ITEM_TIMESTAMP:
+ case KDBUS_ITEM_PID_COMM:
+ case KDBUS_ITEM_TID_COMM:
+ case KDBUS_ITEM_EXE:
+ case KDBUS_ITEM_CMDLINE:
+ case KDBUS_ITEM_CGROUP:
+ case KDBUS_ITEM_AUDIT:
+ case KDBUS_ITEM_CAPS:
+ case KDBUS_ITEM_SECLABEL:
+ case KDBUS_ITEM_CONN_DESCRIPTION:
+ case KDBUS_ITEM_AUXGROUPS:
+ case KDBUS_ITEM_OWNED_NAME:
+ case KDBUS_ITEM_NAME:
+ break;
+
+ default:
+ g_error ("[KDBUS] DBUS_PAYLOAD: Unknown filed - %lld", item->type);
+ break;
+ }
+ }
+
+ /* Override information from the user header with data from the kernel */
+
+ if (kdbus->priv->kmsg->src_id == KDBUS_SRC_ID_KERNEL)
+ g_string_printf (kdbus->priv->msg_sender, "org.freedesktop.DBus");
+ else
+ g_string_printf (kdbus->priv->msg_sender, ":1.%" G_GUINT64_FORMAT, (guint64) kdbus->priv->kmsg->src_id);
+
+ if (destination)
+ g_string_printf (kdbus->priv->msg_destination, "%s", destination);
+ else if (kdbus->priv->kmsg->dst_id == KDBUS_DST_ID_BROADCAST)
+ /* for broadcast messages we don't have to set destination */
+ ;
+ else if (kdbus->priv->kmsg->dst_id == KDBUS_DST_ID_NAME)
+ g_string_printf (kdbus->priv->msg_destination, ":1.%" G_GUINT64_FORMAT, (guint64)
kdbus->priv->unique_id);
+ else
+ g_string_printf (kdbus->priv->msg_destination, ":1.%" G_GUINT64_FORMAT, (guint64)
kdbus->priv->kmsg->dst_id);
+
+ return ret_size;
+}
+
+
+/**
* _g_kdbus_receive:
*
*/
@@ -1497,7 +2048,7 @@ again:
kdbus->priv->kmsg = (struct kdbus_msg *)((guint8 *)kdbus->priv->kdbus_buffer + recv.offset);
if (kdbus->priv->kmsg->payload_type == KDBUS_PAYLOAD_DBUS)
- g_error ("Received standard dbus message - not supported yet");
+ size = g_kdbus_decode_dbus_msg (kdbus);
else if (kdbus->priv->kmsg->payload_type == KDBUS_PAYLOAD_KERNEL)
size = g_kdbus_decode_kernel_msg (kdbus);
else
@@ -1511,3 +2062,176 @@ again:
return size;
}
+
+
+/**
+ * _g_kdbus_send:
+ * Returns: size of data sent or -1 when error
+ */
+gsize
+_g_kdbus_send (GDBusWorker *worker,
+ GKdbus *kdbus,
+ GDBusMessage *dbus_msg,
+ gchar *blob,
+ gsize blob_size,
+ GUnixFDList *fd_list,
+ GCancellable *cancellable,
+ GError **error)
+{
+ struct kdbus_msg* kmsg;
+ struct kdbus_item *item;
+ guint64 kmsg_size = 0;
+ const gchar *name;
+ guint64 dst_id = KDBUS_DST_ID_BROADCAST;
+
+ g_return_val_if_fail (G_IS_KDBUS (kdbus), -1);
+
+ if (g_cancellable_set_error_if_cancelled (cancellable, error))
+ return -1;
+
+ /*
+ * check destination
+ */
+ if ((name = g_dbus_message_get_destination(dbus_msg)))
+ {
+ dst_id = KDBUS_DST_ID_NAME;
+ if ((name[0] == ':') && (name[1] == '1') && (name[2] == '.'))
+ {
+ dst_id = strtoull(&name[3], NULL, 10);
+ name=NULL;
+ }
+ }
+
+ /*
+ * check and set message size
+ */
+ kmsg_size = sizeof(struct kdbus_msg);
+ kmsg_size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec)); /* header + body */
+
+ if (fd_list != NULL && g_unix_fd_list_get_length (fd_list) > 0)
+ kmsg_size += KDBUS_ALIGN8(G_STRUCT_OFFSET(struct kdbus_item, fds) + sizeof(int) *
g_unix_fd_list_get_length(fd_list));
+
+ if (name)
+ kmsg_size += KDBUS_ITEM_SIZE(strlen(name) + 1);
+ else if (dst_id == KDBUS_DST_ID_BROADCAST)
+ kmsg_size += KDBUS_ALIGN8(G_STRUCT_OFFSET(struct kdbus_item, bloom_filter) +
+ G_STRUCT_OFFSET(struct kdbus_bloom_filter, data) +
+ kdbus->priv->bloom_size);
+
+ kmsg = malloc(kmsg_size);
+ if (!kmsg)
+ g_error ("[KDBUS] kmsg malloc error");
+
+
+ /*
+ * set message header
+ */
+ memset(kmsg, 0, kmsg_size);
+ kmsg->size = kmsg_size;
+ kmsg->payload_type = KDBUS_PAYLOAD_DBUS;
+ kmsg->dst_id = name ? 0 : dst_id;
+ kmsg->src_id = kdbus->priv->unique_id;
+ kmsg->cookie = g_dbus_message_get_serial(dbus_msg);
+ kmsg->priority = 0;
+
+
+ /*
+ * set message flags
+ */
+ kmsg->flags = ((g_dbus_message_get_flags (dbus_msg) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) ? 0 :
KDBUS_MSG_FLAGS_EXPECT_REPLY) |
+ ((g_dbus_message_get_flags (dbus_msg) & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START) ?
KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
+
+ if ((kmsg->flags) & KDBUS_MSG_FLAGS_EXPECT_REPLY)
+ kmsg->timeout_ns = 2000000000;
+ else
+ kmsg->cookie_reply = g_dbus_message_get_reply_serial(dbus_msg);
+
+
+ /*
+ * append payload
+ */
+ item = kmsg->items;
+
+ /* if we don't use memfd, send whole message as a PAYLOAD_VEC item */
+ g_kdbus_append_payload_vec (&item, blob, blob_size);
+
+
+ /*
+ * append destination or bloom filters
+ */
+ if (name)
+ g_kdbus_append_destination (&item, name, strlen(name));
+ else if (dst_id == KDBUS_DST_ID_BROADCAST)
+ {
+ struct kdbus_bloom_filter *bloom_filter;
+
+ bloom_filter = g_kdbus_append_bloom (&item, kdbus->priv->bloom_size);
+ g_kdbus_setup_bloom (kdbus, dbus_msg, bloom_filter);
+ }
+
+ /*
+ * append fds if any
+ */
+ if (fd_list != NULL && g_unix_fd_list_get_length (fd_list) > 0)
+ g_kdbus_append_fds (&item, fd_list);
+
+
+ /*
+ * send message
+ */
+//again:
+ if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_SEND, kmsg))
+ {
+/*
+ GString *error_name;
+ error_name = g_string_new (NULL);
+
+ if(errno == EINTR)
+ {
+ g_string_free (error_name,TRUE);
+ goto again;
+ }
+ else if (errno == ENXIO)
+ {
+ g_string_printf (error_name, "Name %s does not exist", g_dbus_message_get_destination(dbus_msg));
+ g_kdbus_generate_local_error (worker,
+ dbus_msg,
+ g_variant_new ("(s)",error_name->str),
+ G_DBUS_ERROR_SERVICE_UNKNOWN);
+ g_string_free (error_name,TRUE);
+ return 0;
+ }
+ else if ((errno == ESRCH) || (errno == EADDRNOTAVAIL))
+ {
+ if (kmsg->flags & KDBUS_MSG_FLAGS_NO_AUTO_START)
+ {
+ g_string_printf (error_name, "Name %s does not exist",
g_dbus_message_get_destination(dbus_msg));
+ g_kdbus_generate_local_error (worker,
+ dbus_msg,
+ g_variant_new ("(s)",error_name->str),
+ G_DBUS_ERROR_SERVICE_UNKNOWN);
+ g_string_free (error_name,TRUE);
+ return 0;
+ }
+ else
+ {
+ g_string_printf (error_name, "The name %s was not provided by any .service files",
g_dbus_message_get_destination(dbus_msg));
+ g_kdbus_generate_local_error (worker,
+ dbus_msg,
+ g_variant_new ("(s)",error_name->str),
+ G_DBUS_ERROR_SERVICE_UNKNOWN);
+ g_string_free (error_name,TRUE);
+ return 0;
+ }
+ }
+
+ g_print ("[KDBUS] ioctl error sending kdbus message:%d (%m)\n",errno);
+ g_set_error (error, G_IO_ERROR, g_io_error_from_errno(errno), _("Error sending message -
KDBUS_CMD_MSG_SEND error"));
+*/
+ g_error ("IOCTL SEND: %d\n",errno);
+ return -1;
+ }
+
+ free(kmsg);
+ return blob_size;
+}
diff --git a/gio/gkdbus.h b/gio/gkdbus.h
index 82386dc..7ba6f35 100644
--- a/gio/gkdbus.h
+++ b/gio/gkdbus.h
@@ -55,6 +55,12 @@ struct _GKdbus
GKdbusPrivate *priv;
};
+typedef struct
+{
+ gchar *data;
+ gsize size;
+} msg_part;
+
GType _g_kdbus_get_type (void) G_GNUC_CONST;
gboolean _g_kdbus_open (GKdbus *kdbus,
@@ -115,10 +121,31 @@ void _g_kdbus_unsubscribe_name_acquired (GDB
void _g_kdbus_unsubscribe_name_lost (GDBusConnection *connection);
+gsize _g_kdbus_send (GDBusWorker *worker,
+ GKdbus *kdbus,
+ GDBusMessage *dbus_msg,
+ gchar *blob,
+ gsize blob_size,
+ GUnixFDList *fd_list,
+ GCancellable *cancellable,
+ GError **error);
+
gssize _g_kdbus_receive (GKdbus *kdbus,
GCancellable *cancellable,
GError **error);
+GSList * _g_kdbus_get_last_msg_items (GKdbus *kdbus);
+
+gchar * _g_kdbus_get_last_msg_sender (GKdbus *kdbus);
+
+gchar * _g_kdbus_get_last_msg_destination (GKdbus *kdbus);
+
+gchar * _g_kdbus_hexdump_all_items (GSList
*kdbus_msg_items);
+
+void _g_kdbus_release_kmsg (GKdbus *kdbus);
+
+void _g_kdbus_attach_fds_to_msg (GKdbus *kdbus,
+ GUnixFDList **fd_list);
G_END_DECLS
#endif /* __G_KDBUS_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]