[glib/wip/kdbus-junk: 37/37] wip junk



commit b3f8546dd21a65f2f938de78d9597364c42f0386
Author: Ryan Lortie <desrt desrt ca>
Date:   Wed Dec 10 10:56:38 2014 -0500

    wip junk

 gio/gapplicationimpl-dbus.c |   12 +-
 gio/gdbusconnection.c       |   27 +--
 gio/gdbusmessage.c          |  330 ++----------------------
 gio/gdbusmessage.h          |   10 -
 gio/gdbusmethodinvocation.c |   38 +++
 gio/gdbusmethodinvocation.h |    5 +
 gio/gdbusprivate.c          |   39 +---
 gio/gdbusprivate.h          |    3 +
 gio/gkdbus.c                |  614 ++++++++++++++++++-------------------------
 gio/gkdbus.h                |    4 +-
 gio/gunixfdlist.h           |    3 +
 gio/kdbus.h                 |   11 +-
 glib/gvariant-core.c        |    7 +-
 13 files changed, 355 insertions(+), 748 deletions(-)
---
diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c
index 94cf6ea..4b1b5c9 100644
--- a/gio/gapplicationimpl-dbus.c
+++ b/gio/gapplicationimpl-dbus.c
@@ -852,13 +852,13 @@ g_dbus_command_line_get_stdin (GApplicationCommandLine *cmdline)
 
   if (fd_list && g_unix_fd_list_get_length (fd_list))
     {
-      gint *fds, n_fds, i;
+      gint *fds, i;
 
-      fds = g_unix_fd_list_steal_fds (fd_list, &n_fds);
-      result = g_unix_input_stream_new (fds[0], TRUE);
-      for (i = 1; i < n_fds; i++)
-        (void) g_close (fds[i], NULL);
-      g_free (fds);
+      fds = g_unix_fd_list_peek_fds (fd_list, NULL);
+      result = g_unix_input_stream_new (fds[0], FALSE);
+      g_object_weak_ref (G_OBJECT (result),
+                         (GWeakNotify) g_object_unref,
+                         g_object_ref (fd_list));
     }
 
   return result;
diff --git a/gio/gdbusconnection.c b/gio/gdbusconnection.c
index d9ee982..1a896b9 100644
--- a/gio/gdbusconnection.c
+++ b/gio/gdbusconnection.c
@@ -2124,29 +2124,20 @@ 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,
                                  error);
+
   if (blob == NULL)
     goto out;
 
-  if (flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL)
-    serial_to_use = g_dbus_message_get_serial (message);
-  else
-    serial_to_use = ++connection->last_serial; /* TODO: handle overflow */
+  if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL))
+    g_dbus_message_set_serial (message, ++connection->last_serial);
+
+  serial_to_use = g_dbus_message_get_serial (message);
+
+  g_dbus_message_lock (message);
 
   switch (blob[0])
     {
@@ -2183,10 +2174,6 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
                         g_thread_self (),
                         GUINT_TO_POINTER (serial_to_use));
 
-  if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL))
-    g_dbus_message_set_serial (message, serial_to_use);
-
-  g_dbus_message_lock (message);
   _g_dbus_worker_send_message (connection->worker,
                                message,
                                (gchar*) blob,
diff --git a/gio/gdbusmessage.c b/gio/gdbusmessage.c
index 4d4cb69..a0e1f7b 100644
--- a/gio/gdbusmessage.c
+++ b/gio/gdbusmessage.c
@@ -49,7 +49,6 @@
 #include "gdbusprivate.h"
 
 #ifdef G_OS_UNIX
-#include "gkdbus.h"
 #include "gunixfdlist.h"
 #endif
 
@@ -973,38 +972,6 @@ 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 */
 
 /**
@@ -2225,219 +2192,6 @@ 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)
@@ -2813,12 +2567,6 @@ 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.
@@ -2847,11 +2595,7 @@ 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;
@@ -2869,20 +2613,6 @@ 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);
@@ -2902,10 +2632,7 @@ 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);
-
-  /* major protocol version */
-  g_memory_buffer_put_byte (&mbuf, message->major_protocol_version);
-
+  g_memory_buffer_put_byte (&mbuf, 1); /* major protocol version */
   body_len_offset = mbuf.valid_len;
   /* body length - will be filled in later */
   g_memory_buffer_put_uint32 (&mbuf, 0xF00DFACE);
@@ -2945,30 +2672,15 @@ g_dbus_message_to_blob (GDBusMessage          *message,
     }
   header_fields = g_variant_builder_end (&builder);
 
-  /* header - dbus1 marshaliling */
-  if (message->major_protocol_version == 1)
-    {
-      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)
+  if (!append_value_to_blob (header_fields,
+                             g_variant_get_type (header_fields),
+                             &mbuf,
+                             NULL,
+                             error))
     {
-      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);
+      goto out;
     }
-
   g_variant_unref (header_fields);
 
   /* header size must be a multiple of 8 */
@@ -3005,23 +2717,8 @@ g_dbus_message_to_blob (GDBusMessage          *message,
           goto out;
         }
       g_free (tupled_signature_str);
-
-      /* body - dbus1 marshaliling */
-      if (message->major_protocol_version == 1)
-        {
-          if (!append_body_to_blob (message->body, &mbuf, error))
-            goto out;
-        }
-#if 0
-      /* 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);
-        }
-#endif
+      if (!append_body_to_blob (message->body, &mbuf, error))
+        goto out;
     }
   else
     {
@@ -3931,3 +3628,10 @@ g_dbus_message_copy (GDBusMessage  *message,
 #endif
   return ret;
 }
+
+void
+g_dbus_message_init_header_iter (GDBusMessage   *message,
+                                 GHashTableIter *iter)
+{
+  g_hash_table_iter_init (iter, message->headers);
+}
diff --git a/gio/gdbusmessage.h b/gio/gdbusmessage.h
index 8f9b25e..f791889 100644
--- a/gio/gdbusmessage.h
+++ b/gio/gdbusmessage.h
@@ -192,16 +192,6 @@ 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/gdbusmethodinvocation.c b/gio/gdbusmethodinvocation.c
index 5bd850b..412ed36 100644
--- a/gio/gdbusmethodinvocation.c
+++ b/gio/gdbusmethodinvocation.c
@@ -306,6 +306,44 @@ g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation)
 }
 
 /**
+ * g_dbus_method_invocation_peek_unix_fd:
+ * @invocation: A #GDBusMethodInvocation.
+ * @index_: the index
+ *
+ * Gets the fd associated with @index in the method invocation.
+ *
+ * If there is no file descriptor at the given index, -1 is returned.
+ *
+ * The returned file descriptor is owned by the message and must not be
+ * closed by the caller.  Use dup() if you want your own copy.
+ *
+ * Returns: the file descriptor, or -1
+ */
+#ifdef G_OS_UNIX
+gint
+g_dbus_method_invocation_peek_unix_fd (GDBusMethodInvocation *invocation,
+                                       guint                  index_)
+{
+  GUnixFDList *fd_list;
+
+  fd_list = g_dbus_message_get_unix_fd_list (invocation->message);
+
+  if (fd_list)
+    {
+      const gint *fds;
+      gint n_fds;
+
+      fds = g_unix_fd_list_peek_fds (fd_list, &n_fds);
+
+      if (index_ < (guint) n_fds)
+        return fds[index_];
+    }
+
+  return -1;
+}
+#endif
+
+/**
  * g_dbus_method_invocation_get_user_data: (skip)
  * @invocation: A #GDBusMethodInvocation.
  *
diff --git a/gio/gdbusmethodinvocation.h b/gio/gdbusmethodinvocation.h
index 6354e41..1d24283 100644
--- a/gio/gdbusmethodinvocation.h
+++ b/gio/gdbusmethodinvocation.h
@@ -53,6 +53,11 @@ GLIB_AVAILABLE_IN_ALL
 GDBusMessage          *g_dbus_method_invocation_get_message          (GDBusMethodInvocation *invocation);
 GLIB_AVAILABLE_IN_ALL
 GVariant              *g_dbus_method_invocation_get_parameters       (GDBusMethodInvocation *invocation);
+#ifdef G_OS_UNIX
+GLIB_AVAILABLE_IN_2_44
+gint                   g_dbus_method_invocation_peek_unix_fd         (GDBusMethodInvocation *invocation,
+                                                                      guint                  index_);
+#endif
 GLIB_AVAILABLE_IN_ALL
 gpointer               g_dbus_method_invocation_get_user_data        (GDBusMethodInvocation *invocation);
 
diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c
index 27d63bc..934bebf 100644
--- a/gio/gdbusprivate.c
+++ b/gio/gdbusprivate.c
@@ -702,12 +702,6 @@ _g_dbus_worker_do_read_cb (GInputStream  *input_stream,
                                          res,
                                          &error);
 
-      /* [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;
     }
@@ -886,30 +880,6 @@ _g_dbus_worker_do_read_cb (GInputStream  *input_stream,
 #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
@@ -995,11 +965,6 @@ _g_dbus_worker_do_read_cb (GInputStream  *input_stream,
   /* [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
@@ -1766,9 +1731,7 @@ continue_writing (GDBusWorker *worker)
           */
 
           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);
+            g_assert_not_reached ();
 
           new_blob = g_dbus_message_to_blob (data->message,
                                              &new_blob_size,
diff --git a/gio/gdbusprivate.h b/gio/gdbusprivate.h
index 0e38121..ba1e60a 100644
--- a/gio/gdbusprivate.h
+++ b/gio/gdbusprivate.h
@@ -145,6 +145,9 @@ void _g_dbus_object_proxy_remove_interface (GDBusObjectProxy *proxy,
 /* Implemented in gdbusconnection.c */
 GDBusConnection *_g_bus_get_singleton_if_exists (GBusType bus_type);
 
+void g_dbus_message_init_header_iter (GDBusMessage   *message,
+                                      GHashTableIter *iter);
+
 G_END_DECLS
 
 #endif /* __G_DBUS_PRIVATE_H__ */
diff --git a/gio/gkdbus.c b/gio/gkdbus.c
index f249b2f..67fdc43 100644
--- a/gio/gkdbus.c
+++ b/gio/gkdbus.c
@@ -93,7 +93,6 @@ struct _GKdbusPrivate
   gint               fd;
 
   gchar             *kdbus_buffer;
-  struct kdbus_msg  *kmsg;
 
   gchar             *unique_name;
   guint64            unique_id;
@@ -102,13 +101,6 @@ 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;
 
@@ -151,55 +143,6 @@ const guint8 hash_keys[8][16] =
 
 
 /**
- * _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:
  *
  */
@@ -241,9 +184,6 @@ 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);
 }
@@ -289,17 +229,10 @@ 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;
 }
 
 
@@ -1361,7 +1294,7 @@ _g_kdbus_subscribe_name_owner_changed (GDBusConnection  *connection,
   struct kdbus_cmd_match *cmd_match;
   gssize size, len;
   gint ret;
-  guint64 old_id;
+  guint64 old_id = 0; /* XXX why? */
   guint64 new_id = KDBUS_MATCH_ID_ANY;
 
   kdbus = _g_kdbus_connection_get_kdbus (G_KDBUS_CONNECTION (g_dbus_connection_get_stream (connection)));
@@ -1539,94 +1472,6 @@ _g_kdbus_unsubscribe_name_lost (GDBusConnection  *connection)
 
 
 /**
- * _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_memfd:
- *
- */
-static void
-g_kdbus_append_payload_memfd (struct kdbus_item **item,
-                              gint                fd,
-                              gssize              size)
-{
-  *item = KDBUS_ALIGN8_PTR(*item);
-  (*item)->size = G_STRUCT_OFFSET (struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
-  (*item)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
-  (*item)->memfd.fd = fd;
-  (*item)->memfd.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:
  *
  */
@@ -1649,50 +1494,6 @@ g_kdbus_append_bloom (struct kdbus_item **item,
 
 
 /**
- * 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
@@ -1884,13 +1685,13 @@ g_kdbus_setup_bloom (GKdbus                     *kdbus,
  * g_kdbus_decode_kernel_msg:
  *
  */
-static gssize
-g_kdbus_decode_kernel_msg (GKdbus  *kdbus)
+static void
+g_kdbus_decode_kernel_msg (GKdbus           *kdbus,
+                           struct kdbus_msg *msg)
 {
   struct kdbus_item *item = NULL;
-  gssize size = 0;
 
-  KDBUS_ITEM_FOREACH(item, kdbus->priv->kmsg, items)
+  KDBUS_ITEM_FOREACH(item, msg, items)
     {
      switch (item->type)
         {
@@ -1914,7 +1715,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");
 
@@ -1928,6 +1729,7 @@ g_kdbus_decode_kernel_msg (GKdbus  *kdbus)
    g_string_printf (kdbus->priv->msg_destination, ":1.%" G_GUINT64_FORMAT, (guint64) 
kdbus->priv->kmsg->dst_id);
 
   return size;
+#endif
 }
 
 
@@ -1936,21 +1738,28 @@ g_kdbus_decode_kernel_msg (GKdbus  *kdbus)
  *
  */
 static GDBusMessage *
-g_kdbus_decode_dbus_msg (GKdbus                *kdbus,
-                         struct kdbus_cmd_recv *recv)
+g_kdbus_decode_dbus_msg (GKdbus           *kdbus,
+                         struct kdbus_msg *msg)
 {
+  GDBusMessage *message;
   struct kdbus_item *item;
   gssize data_size = 0;
-  const gchar *destination = NULL;
   GArray *body_vectors;
   gsize body_size;
   GVariant *body;
+  gchar *tmp;
   guint i;
 
+  message = g_dbus_message_new ();
+
+  tmp = g_strdup_printf (":1.%"G_GUINT64_FORMAT, (guint64) msg->src_id);
+  g_dbus_message_set_sender (message, tmp);
+  g_free (tmp);
+
   body_vectors = g_array_new (FALSE, FALSE, sizeof (GVariantVector));
   body_size = 0;
 
-  KDBUS_ITEM_FOREACH(item, (struct kdbus_msg *)((guint8 *)kdbus->priv->kdbus_buffer + recv->offset), items)
+  KDBUS_ITEM_FOREACH(item, msg, items)
     {
       if (item->size <= KDBUS_ITEM_HEADER_SIZE)
         g_error("[KDBUS] %llu bytes - invalid data record\n", item->size);
@@ -1961,7 +1770,10 @@ g_kdbus_decode_dbus_msg (GKdbus                *kdbus,
         {
          /* KDBUS_ITEM_DST_NAME */
          case KDBUS_ITEM_DST_NAME:
-           destination = item->str;
+           /* Classic D-Bus doesn't make this known to the receiver, so
+            * we don't do it here either (for compatibility with the
+            * fallback case).
+            */
            break;
 
         /* KDBUS_ITEM_PALOAD_OFF */
@@ -1998,8 +1810,7 @@ g_kdbus_decode_dbus_msg (GKdbus                *kdbus,
             flavour = body_size & 7;
             //g_assert ((item->vec.offset & 7) == flavour); FIXME: kdbus bug doesn't count memfd in 
flavouring
 
-            vector.gbytes = g_bytes_new (((guchar *) kdbus->priv->kmsg) + item->vec.offset - flavour,
-                                         item->vec.size + flavour);
+            vector.gbytes = g_bytes_new (((guchar *) msg) + item->vec.offset - flavour, item->vec.size + 
flavour);
             vector.data.pointer = g_bytes_get_data (vector.gbytes, NULL);
             vector.data.pointer += flavour;
             vector.size = item->vec.size;
@@ -2025,11 +1836,13 @@ g_kdbus_decode_dbus_msg (GKdbus                *kdbus,
 
         /* KDBUS_ITEM_FDS */
         case KDBUS_ITEM_FDS:
+          {
+            GUnixFDList *fd_list;
 
-          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);
-
+            fd_list = g_unix_fd_list_new_from_array (item->fds, data_size / sizeof (int));
+            g_dbus_message_set_unix_fd_list (message, fd_list);
+            g_object_unref (fd_list);
+          }
           break;
 
         /* All of the following items, like CMDLINE,
@@ -2053,9 +1866,6 @@ g_kdbus_decode_dbus_msg (GKdbus                *kdbus,
           }
 
         case KDBUS_ITEM_PIDS:
-          {
-          }
-
         case KDBUS_ITEM_PID_COMM:
         case KDBUS_ITEM_TID_COMM:
         case KDBUS_ITEM_EXE:
@@ -2087,26 +1897,10 @@ g_kdbus_decode_dbus_msg (GKdbus                *kdbus,
 
   g_array_free (body_vectors, TRUE);
 
-  g_print ("body is %s\n", g_variant_print (body, TRUE));
-
-  /* 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);
+  g_dbus_message_set_body (message, body);
+  g_variant_unref (body);
 
-  return NULL;
+  return message;
 }
 
 
@@ -2120,6 +1914,7 @@ _g_kdbus_receive (GKdbus        *kdbus,
                   GError       **error)
 {
   struct kdbus_cmd_recv recv = {};
+  struct kdbus_msg *msg;
 
   if (g_cancellable_set_error_if_cancelled (cancellable, error))
     return -1;
@@ -2137,12 +1932,12 @@ again:
         return -1;
       }
 
-   kdbus->priv->kmsg = (struct kdbus_msg *)((guint8 *)kdbus->priv->kdbus_buffer + recv.offset);
+   msg = (struct kdbus_msg *)((guint8 *)kdbus->priv->kdbus_buffer + recv.offset);
 
-   if (kdbus->priv->kmsg->payload_type == KDBUS_PAYLOAD_DBUS)
-     g_kdbus_decode_dbus_msg (kdbus, &recv);
-   else if (kdbus->priv->kmsg->payload_type == KDBUS_PAYLOAD_KERNEL)
-     g_kdbus_decode_kernel_msg (kdbus);
+   if (msg->payload_type == KDBUS_PAYLOAD_DBUS)
+     g_kdbus_decode_dbus_msg (kdbus, msg);
+   else if (msg->payload_type == KDBUS_PAYLOAD_KERNEL)
+     g_kdbus_decode_kernel_msg (kdbus, msg);
    else
      {
        g_set_error (error,
@@ -2152,167 +1947,266 @@ again:
        return -1;
      }
 
+  ioctl(kdbus->priv->fd, KDBUS_CMD_FREE, &recv.offset);
+
    return 0;
 }
 
+struct dbus_fixed_header {
+  guint8  endian;
+  guint8  type;
+  guint8  flags;
+  guint8  version;
+  guint32 reserved;
+  guint64 serial;
+};
+
+#define DBUS_FIXED_HEADER_TYPE     ((const GVariantType *) "(yyyyut)")
+#define DBUS_EXTENDED_HEADER_TYPE  ((const GVariantType *) "a{tv}")
+#define DBUS_MESSAGE_TYPE          ((const GVariantType *) "((yyyyut)a{tv}v)")
+
+#define KDBUS_MSG_MAX_SIZE         8192
+
+static gboolean
+g_kdbus_msg_append_item (struct kdbus_msg *msg,
+                         gsize             type,
+                         gconstpointer     data,
+                         gsize             size)
+{
+  struct kdbus_item *item;
+  gsize item_size;
+
+  item_size = size + sizeof (struct kdbus_item);
+
+  if (msg->size + item_size > KDBUS_MSG_MAX_SIZE)
+    return FALSE;
+
+  item = (struct kdbus_item *) ((guchar *) msg) + msg->size;
+  item->type = type;
+  item->size = item_size;
+  memcpy (item->data, data, size);
+
+  msg->size += (item_size + 7) & ~7ull;
+
+  return TRUE;
+}
+
+static gboolean
+g_kdbus_msg_append_payload_vec (struct kdbus_msg *msg,
+                            gconstpointer     data,
+                            gsize             size)
+{
+  struct kdbus_vec vec = {
+    .size = size,
+    .address = (gsize) data
+  };
+
+  return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_VEC, &vec, sizeof vec);
+}
+
+static gboolean
+g_kdbus_msg_append_payload_memfd (struct kdbus_msg *msg,
+                                  gint              fd,
+                                  gsize             offset,
+                                  gsize             size)
+{
+  struct kdbus_memfd mfd = {
+   .start = offset,
+   .size = size,
+   .fd = fd,
+  };
+
+  return g_kdbus_msg_append_item (msg, KDBUS_ITEM_PAYLOAD_MEMFD, &mfd, sizeof mfd);
+}
+
 /**
  * _g_kdbus_send:
  * Returns: size of data sent or -1 when error
  */
 gboolean
-_g_kdbus_send (GDBusWorker   *worker,
-               GKdbus        *kdbus,
-               GDBusMessage  *dbus_msg,
-               GUnixFDList   *fd_list,
+_g_kdbus_send (GKdbus        *kdbus,
+               GDBusMessage  *message,
                GCancellable  *cancellable,
                GError       **error)
 {
+  struct kdbus_msg *msg = alloca (KDBUS_MSG_MAX_SIZE);
   GVariantVectors body_vectors;
-  GVariant *body;
-  struct kdbus_msg* kmsg;
-  struct kdbus_item *item;
-  guint64 kmsg_size = 0;
-  const gchar *name;
-  guint64 dst_id = KDBUS_DST_ID_BROADCAST;
-  guint i;
 
   g_return_val_if_fail (G_IS_KDBUS (kdbus), -1);
 
   if (g_cancellable_set_error_if_cancelled (cancellable, error))
     return FALSE;
 
-  body = g_dbus_message_get_body (dbus_msg);
-  if (body == NULL)
-    {
-      g_warning ("no body!");
-      body = g_variant_new ("()");
-      g_variant_ref_sink (body);
-    }
-  else
-    g_variant_ref (body);
-  GLIB_PRIVATE_CALL(g_variant_to_vectors) (body, &body_vectors);
+  /* fill in as we go... */
+  memset (msg, 0, sizeof (struct kdbus_msg));
+  msg->size = sizeof (struct kdbus_msg);
+  msg->payload_type = KDBUS_PAYLOAD_DBUS;
+  msg->src_id = kdbus->priv->unique_id;
+  msg->cookie = g_dbus_message_get_serial(message);
 
-  /*
-   * 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;
-        }
-    }
+  /* Message destination */
+  {
+    const gchar *dst_name;
 
-  /*
-   * check and set message size
-   */
-  kmsg_size = sizeof(struct kdbus_msg);
+    dst_name = g_dbus_message_get_destination (message);
 
-    { G_STATIC_ASSERT (sizeof (struct kdbus_vec) == sizeof (struct kdbus_memfd)); }
-  kmsg_size += KDBUS_ITEM_SIZE(sizeof (struct kdbus_vec)) * body_vectors.vectors->len;
+    if (dst_name != NULL)
+      {
+        if (g_dbus_is_unique_name (dst_name))
+          {
+            if (dst_name[1] != '1' || dst_name[2] != '.')
+              {
+                g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_NAME_HAS_NO_OWNER,
+                             "Invalid unique D-Bus name '%s'", dst_name);
+                return FALSE;
+              }
 
-  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));
+            /* We already know that it passes the checks for unique
+             * names, so no need to perform error checking on strtoull.
+             */
+            msg->dst_id = strtoull (dst_name + 3, NULL, 10);
+            dst_name = NULL;
+          }
+        else
+          {
+            g_kdbus_msg_append_item (msg, KDBUS_ITEM_DST_NAME, dst_name, strlen (dst_name) + 1);
+            msg->dst_id = KDBUS_DST_ID_NAME;
+          }
+      }
+    else
+      msg->dst_id = KDBUS_DST_ID_BROADCAST;
+  }
 
-  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);
+  /* File descriptors */
+  {
+    GUnixFDList *fd_list;
 
-  kmsg = malloc(kmsg_size);
-  if (!kmsg)
-    g_error ("[KDBUS] kmsg malloc error");
+    fd_list = g_dbus_message_get_unix_fd_list (message);
 
+    if (fd_list != NULL)
+      {
+        const gint *fds;
+        gint n_fds;
 
-  /*
-   * 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;
+        fds = g_unix_fd_list_peek_fds (fd_list, &n_fds);
 
+        if (n_fds)
+          g_kdbus_msg_append_item (msg, KDBUS_ITEM_FDS, fds, sizeof (gint) * n_fds);
+      }
+  }
+
+  /* Message body */
+  {
+    struct dbus_fixed_header fh;
+    GHashTableIter header_iter;
+    GVariantBuilder builder;
+    gpointer key, value;
+    GVariant *parts[3];
+    GVariant *body;
+
+    fh.endian = (G_BYTE_ORDER == G_LITTLE_ENDIAN) ? 'l': 'B';
+    fh.type = g_dbus_message_get_message_type (message);
+    fh.flags = g_dbus_message_get_flags (message);
+    fh.version = 2;
+    fh.reserved = 0;
+    fh.serial = g_dbus_message_get_serial (message);
+    parts[0] = g_variant_new_from_data (DBUS_FIXED_HEADER_TYPE, &fh, sizeof fh, TRUE, NULL, NULL);
+
+    g_dbus_message_init_header_iter (message, &header_iter);
+    g_variant_builder_init (&builder, DBUS_EXTENDED_HEADER_TYPE);
+    while (g_hash_table_iter_next (&header_iter, &key, &value))
+      {
+        guint64 key_int = (gsize) key;
 
-  /*
-   * 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);
+        /* We don't send these in GVariant format */
+        if (key_int == G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE ||
+            key_int == G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS)
+          continue;
 
-  if ((kmsg->flags) & KDBUS_MSG_FLAGS_EXPECT_REPLY)
-    kmsg->timeout_ns = 2000000000;
-  else
-    kmsg->cookie_reply = g_dbus_message_get_reply_serial(dbus_msg);
+        g_variant_builder_add (&builder, "{tv}", key_int, value);
+      }
+    parts[1] = g_variant_builder_end (&builder);
 
+    body = g_dbus_message_get_body (message);
+    if (!body)
+      body = g_variant_new ("()");
+    parts[2] = g_variant_new_variant (body);
 
-  /*
-   * append payload
-   */
-  item = kmsg->items;
-  for (i = 0; i < body_vectors.vectors->len; i++)
-    {
-      GVariantVector vector = g_array_index (body_vectors.vectors, GVariantVector, i);
+    body = g_variant_ref_sink (g_variant_new_tuple (parts, G_N_ELEMENTS (parts)));
+    GLIB_PRIVATE_CALL(g_variant_to_vectors) (body, &body_vectors);
+    g_variant_unref (body);
+  }
 
-      if (vector.gbytes)
-        {
-          gint fd;
+  {
+    guint i;
 
-          fd = g_bytes_get_zero_copy_fd (vector.gbytes);
+    for (i = 0; i < body_vectors.vectors->len; i++)
+      {
+        GVariantVector vector = g_array_index (body_vectors.vectors, GVariantVector, i);
 
-          if (fd >= 0)
-            {
-              gconstpointer bytes_data;
-              gsize bytes_size;
+        if (vector.gbytes)
+          {
+            gint fd;
 
-              bytes_data = g_bytes_get_data (vector.gbytes, &bytes_size);
+            fd = g_bytes_get_zero_copy_fd (vector.gbytes);
 
-              if (bytes_data == vector.data.pointer && bytes_size == vector.size)
-                g_kdbus_append_payload_memfd (&item, fd, vector.size);
-              else
-                g_kdbus_append_payload_vec (&item, vector.data.pointer, vector.size);
-            }
-          else
-            g_kdbus_append_payload_vec (&item, vector.data.pointer, vector.size);
-        }
-      else
-        g_kdbus_append_payload_vec (&item, body_vectors.extra_bytes->data + vector.data.offset, vector.size);
-    }
+            if (fd >= 0)
+              {
+                const guchar *bytes_data;
+                gsize bytes_size;
+
+                bytes_data = g_bytes_get_data (vector.gbytes, &bytes_size);
+
+                if (bytes_data <= vector.data.pointer && vector.data.pointer + vector.size <= bytes_data + 
bytes_size)
+                  {
+                    if (!g_kdbus_msg_append_payload_memfd (msg, fd, vector.data.pointer - bytes_data, 
vector.size))
+                      goto need_compact;
+                  }
+                else
+                  {
+                    if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
+                      goto need_compact;
+                  }
+              }
+            else
+              {
+                if (!g_kdbus_msg_append_payload_vec (msg, vector.data.pointer, vector.size))
+                  goto need_compact;
+              }
+          }
+        else
+          if (!g_kdbus_msg_append_payload_vec (msg, body_vectors.extra_bytes->data + vector.data.offset, 
vector.size))
+            goto need_compact;
+      }
+  }
 
-  /* if we don't use memfd, send whole message as a PAYLOAD_VEC item */
+  /*
+   * set message flags
+   */
+  msg->flags = ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) ? 0 : 
KDBUS_MSG_FLAGS_EXPECT_REPLY) |
+                ((g_dbus_message_get_flags (message) & G_DBUS_MESSAGE_FLAGS_NO_AUTO_START) ? 
KDBUS_MSG_FLAGS_NO_AUTO_START : 0);
+
+  if ((msg->flags) & KDBUS_MSG_FLAGS_EXPECT_REPLY)
+    msg->timeout_ns = 2000000000;
+  else
+    msg->cookie_reply = g_dbus_message_get_reply_serial(message);
 
 
   /*
-   * append destination or bloom filters
-   */
-  if (name)
-    g_kdbus_append_destination (&item, name, strlen(name));
-  else if (dst_id == KDBUS_DST_ID_BROADCAST)
+  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);
+      g_kdbus_setup_bloom (kdbus, message, 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))
+  if (ioctl(kdbus->priv->fd, KDBUS_CMD_MSG_SEND, msg))
     {
 /*
       GString *error_name;
@@ -2365,7 +2259,15 @@ _g_kdbus_send (GDBusWorker   *worker,
       return FALSE;
     }
 
-  free(kmsg);
-
   return TRUE;
+
+need_compact:
+  /* We end up here if:
+   *  - too many kdbus_items
+   *  - too large kdbus_msg size
+   *  - too much vector data
+   *
+   * We need to compact the message before sending it.
+   */
+  g_assert_not_reached ();
 }
diff --git a/gio/gkdbus.h b/gio/gkdbus.h
index d8c8df1..43563b2 100644
--- a/gio/gkdbus.h
+++ b/gio/gkdbus.h
@@ -121,10 +121,8 @@ void                                    _g_kdbus_unsubscribe_name_acquired  (GDB
 
 void                                    _g_kdbus_unsubscribe_name_lost      (GDBusConnection  *connection);
 
-gboolean                                _g_kdbus_send                       (GDBusWorker      *worker,
-                                                                             GKdbus           *kdbus,
+gboolean                                _g_kdbus_send                       (GKdbus           *kdbus,
                                                                              GDBusMessage     *dbus_msg,
-                                                                             GUnixFDList      *fd_list,
                                                                              GCancellable     *cancellable,
                                                                              GError          **error);
 
diff --git a/gio/gunixfdlist.h b/gio/gunixfdlist.h
index 6b1c383..cbedc95 100644
--- a/gio/gunixfdlist.h
+++ b/gio/gunixfdlist.h
@@ -68,6 +68,9 @@ GLIB_AVAILABLE_IN_ALL
 GUnixFDList *           g_unix_fd_list_new_from_array                   (const gint   *fds,
                                                                          gint          n_fds);
 
+GLIB_AVAILABLE_IN_2_44
+void                    g_unix_fd_list_lock                             (GUnixFDList  *list);
+
 GLIB_AVAILABLE_IN_ALL
 gint                    g_unix_fd_list_append                           (GUnixFDList  *list,
                                                                          gint          fd,
diff --git a/gio/kdbus.h b/gio/kdbus.h
index 7137fc9..b0e9203 100644
--- a/gio/kdbus.h
+++ b/gio/kdbus.h
@@ -183,7 +183,8 @@ struct kdbus_bloom_filter {
 
 /**
  * struct kdbus_memfd - a kdbus memfd
- * @size:              The memfd's size
+ * @start:             The offset into the memfd where the segment starts
+ * @size:              The size of the memfd segment
  * @fd:                        The file descriptor number
  * @__pad:             Padding to ensure proper alignment and size
  *
@@ -191,6 +192,7 @@ struct kdbus_bloom_filter {
  *   KDBUS_ITEM_PAYLOAD_MEMFD
  */
 struct kdbus_memfd {
+       __u64 start;
        __u64 size;
        int fd;
        __u32 __pad;
@@ -583,12 +585,15 @@ enum kdbus_policy_type {
  *                             a service
  * @KDBUS_HELLO_MONITOR:       Special-purpose connection to monitor
  *                             bus traffic
+ * @KDBUS_HELLO_UNPRIVILEGED:  Don't treat this connection as privileged once
+ *                             the bus connection was established.
  */
 enum kdbus_hello_flags {
        KDBUS_HELLO_ACCEPT_FD           =  1ULL <<  0,
        KDBUS_HELLO_ACTIVATOR           =  1ULL <<  1,
        KDBUS_HELLO_POLICY_HOLDER       =  1ULL <<  2,
        KDBUS_HELLO_MONITOR             =  1ULL <<  3,
+       KDBUS_HELLO_UNPRIVILEGED        =  1ULL <<  4,
 };
 
 /**
@@ -768,6 +773,7 @@ enum kdbus_name_list_flags {
  * @offset:            The returned offset in the caller's pool buffer.
  *                     The user must use KDBUS_CMD_FREE to free the
  *                     allocated memory.
+ * @size:              Output buffer to report size of data at @offset.
  *
  * This structure is used with the KDBUS_CMD_NAME_LIST ioctl.
  */
@@ -775,6 +781,7 @@ struct kdbus_cmd_name_list {
        __u64 flags;
        __u64 kernel_flags;
        __u64 offset;
+       __u64 size;
 } __attribute__((aligned(8)));
 
 /**
@@ -801,6 +808,7 @@ struct kdbus_name_list {
  * @offset:            Returned offset in the caller's pool buffer where the
  *                     kdbus_info struct result is stored. The user must
  *                     use KDBUS_CMD_FREE to free the allocated memory.
+ * @info_size:         Output buffer to report size of data at @offset.
  * @items:             The optional item list, containing the
  *                     well-known name to look up as a KDBUS_ITEM_NAME.
  *                     Only needed in case @id is zero.
@@ -815,6 +823,7 @@ struct kdbus_cmd_info {
        __u64 kernel_flags;
        __u64 id;
        __u64 offset;
+       __u64 info_size;
        struct kdbus_item items[0];
 } __attribute__((aligned(8)));
 
diff --git a/glib/gvariant-core.c b/glib/gvariant-core.c
index 55409c3..44f570b 100644
--- a/glib/gvariant-core.c
+++ b/glib/gvariant-core.c
@@ -731,6 +731,7 @@ g_variant_vector_deserialise (GVariantTypeInfo *type_info,
           if (unpacked->size == 0)
             {
               children[i] = g_variant_new_serialised (unpacked->type_info, g_bytes_new (NULL, 0), NULL, 0, 
trusted);
+              g_variant_ref_sink (children[i]);
               continue;
             }
 
@@ -765,7 +766,10 @@ g_variant_vector_deserialise (GVariantTypeInfo *type_info,
           vector->data.pointer = resume_at_data;
           vector->size = resume_at_size;
 
-          failed |= children[i] == NULL;
+          if (children[i])
+            g_variant_ref_sink (children[i]);
+          else
+            failed = TRUE;
         }
 
       /* We consumed all the type infos */
@@ -813,6 +817,7 @@ g_variant_from_vectors (const GVariantType *type,
   tmp = g_array_new (FALSE, FALSE, sizeof (GVariantUnpacked));
   result = g_variant_vector_deserialise (g_variant_type_info_get (type),
                                          vectors, vectors + n_vectors - 1, size, trusted, tmp);
+  g_variant_ref_sink (result);
   g_array_free (tmp, TRUE);
 
   return result;


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