gio: cleanup gdbusmessage.c file
[platform/upstream/glib.git] / gio / gdbusmessage.c
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: David Zeuthen <davidz@redhat.com>
19  */
20
21 /* Uncomment to debug serializer code */
22 /* #define DEBUG_SERIALIZER */
23
24 #include "config.h"
25
26 #include <string.h>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30
31 #if MAJOR_IN_MKDEV
32 #include <sys/mkdev.h>
33 #elif MAJOR_IN_SYSMACROS
34 #include <sys/sysmacros.h>
35 #endif
36
37 #include "gdbusutils.h"
38 #include "gdbusmessage.h"
39 #include "gdbuserror.h"
40 #include "gioenumtypes.h"
41 #include "ginputstream.h"
42 #include "gdatainputstream.h"
43 #include "gmemoryinputstream.h"
44 #include "goutputstream.h"
45 #include "gdataoutputstream.h"
46 #include "gmemoryoutputstream.h"
47 #include "gseekable.h"
48 #include "gioerror.h"
49 #include "gdbusprivate.h"
50
51 #ifdef G_OS_UNIX
52 #include "gunixfdlist.h"
53 #endif
54
55 #include "glibintl.h"
56
57 typedef struct _GMemoryBuffer GMemoryBuffer;
58 struct _GMemoryBuffer
59 {
60   gsize len;
61   gsize valid_len;
62   gsize pos;
63   gchar *data;
64   GDataStreamByteOrder byte_order;
65 };
66
67 static guchar
68 g_memory_buffer_read_byte (GMemoryBuffer  *mbuf)
69 {
70   if (mbuf->pos >= mbuf->valid_len)
71     return 0;
72   return mbuf->data [mbuf->pos++];
73 }
74
75 static gint16
76 g_memory_buffer_read_int16 (GMemoryBuffer  *mbuf)
77 {
78   gint16 v;
79   
80   if (mbuf->pos > mbuf->valid_len - 2)
81     {
82       mbuf->pos = mbuf->valid_len;
83       return 0;
84     }
85
86   memcpy (&v, mbuf->data + mbuf->pos, 2);
87   mbuf->pos += 2;
88   switch (mbuf->byte_order)
89     {
90     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
91       v = GINT16_FROM_BE (v);
92       break;
93     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
94       v = GINT16_FROM_LE (v);
95       break;
96     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
97     default:
98       break;
99     }
100   return v;
101 }
102
103 static guint16
104 g_memory_buffer_read_uint16 (GMemoryBuffer  *mbuf)
105 {
106   guint16 v;
107   
108   if (mbuf->pos > mbuf->valid_len - 2)
109     {
110       mbuf->pos = mbuf->valid_len;
111       return 0;
112     }
113
114   memcpy (&v, mbuf->data + mbuf->pos, 2);
115   mbuf->pos += 2;
116   switch (mbuf->byte_order)
117     {
118     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
119       v = GINT16_FROM_BE (v);
120       break;
121     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
122       v = GINT16_FROM_LE (v);
123       break;
124     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
125     default:
126       break;
127     }
128   return v;
129 }
130
131 static gint32
132 g_memory_buffer_read_int32 (GMemoryBuffer  *mbuf)
133 {
134   gint32 v;
135   
136   if (mbuf->pos > mbuf->valid_len - 4)
137     {
138       mbuf->pos = mbuf->valid_len;
139       return 0;
140     }
141
142   memcpy (&v, mbuf->data + mbuf->pos, 4);
143   mbuf->pos += 4;
144   switch (mbuf->byte_order)
145     {
146     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
147       v = GINT32_FROM_BE (v);
148       break;
149     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
150       v = GINT32_FROM_LE (v);
151       break;
152     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
153     default:
154       break;
155     }
156   return v;
157 }
158
159 static guint32
160 g_memory_buffer_read_uint32 (GMemoryBuffer  *mbuf)
161 {
162   guint32 v;
163   
164   if (mbuf->pos > mbuf->valid_len - 4)
165     {
166       mbuf->pos = mbuf->valid_len;
167       return 0;
168     }
169
170   memcpy (&v, mbuf->data + mbuf->pos, 4);
171   mbuf->pos += 4;
172   switch (mbuf->byte_order)
173     {
174     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
175       v = GUINT32_FROM_BE (v);
176       break;
177     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
178       v = GUINT32_FROM_LE (v);
179       break;
180     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
181     default:
182       break;
183     }
184   return v;
185 }
186
187 static gint64
188 g_memory_buffer_read_int64 (GMemoryBuffer  *mbuf)
189 {
190   gint64 v;
191   
192   if (mbuf->pos > mbuf->valid_len - 8)
193     {
194       mbuf->pos = mbuf->valid_len;
195       return 0;
196     }
197
198   memcpy (&v, mbuf->data + mbuf->pos, 8);
199   mbuf->pos += 8;
200   switch (mbuf->byte_order)
201     {
202     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
203       v = GINT64_FROM_BE (v);
204       break;
205     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
206       v = GINT64_FROM_LE (v);
207       break;
208     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
209     default:
210       break;
211     }
212   return v;
213 }
214
215 static guint64
216 g_memory_buffer_read_uint64 (GMemoryBuffer  *mbuf)
217 {
218   guint64 v;
219   
220   if (mbuf->pos > mbuf->valid_len - 8)
221     {
222       mbuf->pos = mbuf->valid_len;
223       return 0;
224     }
225
226   memcpy (&v, mbuf->data + mbuf->pos, 8);
227   mbuf->pos += 8;
228   switch (mbuf->byte_order)
229     {
230     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
231       v = GUINT64_FROM_BE (v);
232       break;
233     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
234       v = GUINT64_FROM_LE (v);
235       break;
236         case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
237         default:
238           break;
239         }
240       return v;
241 }
242
243 #define MIN_ARRAY_SIZE  128
244
245 static gint
246 g_nearest_pow (gint num)
247 {
248   gint n = 1;
249
250   while (n < num)
251     n <<= 1;
252
253   return n;
254 }
255
256 static void
257 array_resize (GMemoryBuffer  *mbuf,
258               gsize           size)
259 {
260   gpointer data;
261   gsize len;
262
263   if (mbuf->len == size)
264     return;
265
266   len = mbuf->len;
267   data = g_realloc (mbuf->data, size);
268
269   if (size > len)
270     memset ((guint8 *)data + len, 0, size - len);
271
272   mbuf->data = data;
273   mbuf->len = size;
274
275   if (mbuf->len < mbuf->valid_len)
276     mbuf->valid_len = mbuf->len;
277 }
278
279 static gboolean
280 g_memory_buffer_write (GMemoryBuffer  *mbuf,
281                        const void     *buffer,
282                        gsize           count)
283 {
284   guint8   *dest;
285   gsize new_size;
286
287   if (count == 0)
288     return TRUE;
289
290   /* Check for address space overflow, but only if the buffer is resizable.
291      Otherwise we just do a short write and don't worry. */
292   if (mbuf->pos + count < mbuf->pos)
293     return FALSE;
294
295   if (mbuf->pos + count > mbuf->len)
296     {
297       /* At least enought to fit the write, rounded up
298              for greater than linear growth.
299          TODO: This wastes a lot of memory at large buffer sizes.
300                Figure out a more rational allocation strategy. */
301       new_size = g_nearest_pow (mbuf->pos + count);
302       /* Check for overflow again. We have only checked if
303          pos + count > G_MAXSIZE, but it only catches the case of writing
304          more than 4GiB total on a 32-bit system. There's still the problem
305          of g_nearest_pow overflowing above 0x7fffffff, so we're
306          effectively limited to 2GiB. */
307       if (new_size < mbuf->len)
308         return FALSE;
309
310       new_size = MAX (new_size, MIN_ARRAY_SIZE);
311       array_resize (mbuf, new_size);
312     }
313
314   dest = (guint8 *)mbuf->data + mbuf->pos;
315   memcpy (dest, buffer, count);
316   mbuf->pos += count;
317
318   if (mbuf->pos > mbuf->valid_len)
319     mbuf->valid_len = mbuf->pos;
320
321   return TRUE;
322 }
323
324 static gboolean
325 g_memory_buffer_put_byte (GMemoryBuffer  *mbuf,
326                           guchar          data)
327 {
328   return g_memory_buffer_write (mbuf, &data, 1);
329 }
330
331 static gboolean
332 g_memory_buffer_put_int16 (GMemoryBuffer  *mbuf,
333                            gint16          data)
334 {
335   switch (mbuf->byte_order)
336     {
337     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
338       data = GINT16_TO_BE (data);
339       break;
340     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
341       data = GINT16_TO_LE (data);
342       break;
343     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
344     default:
345       break;
346     }
347   
348   return g_memory_buffer_write (mbuf, &data, 2);
349 }
350
351 static gboolean
352 g_memory_buffer_put_uint16 (GMemoryBuffer  *mbuf,
353                             guint16         data)
354 {
355   switch (mbuf->byte_order)
356     {
357     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
358       data = GUINT16_TO_BE (data);
359       break;
360     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
361       data = GUINT16_TO_LE (data);
362       break;
363     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
364     default:
365       break;
366     }
367   
368   return g_memory_buffer_write (mbuf, &data, 2);
369 }
370
371 static gboolean
372 g_memory_buffer_put_int32 (GMemoryBuffer  *mbuf,
373                            gint32          data)
374 {
375   switch (mbuf->byte_order)
376     {
377     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
378       data = GINT32_TO_BE (data);
379       break;
380     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
381       data = GINT32_TO_LE (data);
382       break;
383     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
384     default:
385       break;
386     }
387   
388   return g_memory_buffer_write (mbuf, &data, 4);
389 }
390
391 static gboolean
392 g_memory_buffer_put_uint32 (GMemoryBuffer  *mbuf,
393                             guint32         data)
394 {
395   switch (mbuf->byte_order)
396     {
397     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
398       data = GUINT32_TO_BE (data);
399       break;
400     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
401       data = GUINT32_TO_LE (data);
402       break;
403     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
404     default:
405       break;
406     }
407   
408   return g_memory_buffer_write (mbuf, &data, 4);
409 }
410
411 static gboolean
412 g_memory_buffer_put_int64 (GMemoryBuffer  *mbuf,
413                            gint64          data)
414 {
415   switch (mbuf->byte_order)
416     {
417     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
418       data = GINT64_TO_BE (data);
419       break;
420     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
421       data = GINT64_TO_LE (data);
422       break;
423     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
424     default:
425       break;
426     }
427   
428   return g_memory_buffer_write (mbuf, &data, 8);
429 }
430
431 static gboolean
432 g_memory_buffer_put_uint64 (GMemoryBuffer  *mbuf,
433                             guint64         data)
434 {
435   switch (mbuf->byte_order)
436     {
437     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
438       data = GUINT64_TO_BE (data);
439       break;
440     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
441       data = GUINT64_TO_LE (data);
442       break;
443     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
444     default:
445       break;
446     }
447   
448   return g_memory_buffer_write (mbuf, &data, 8);
449 }
450
451 static gboolean
452 g_memory_buffer_put_string (GMemoryBuffer  *mbuf,
453                             const char     *str)
454 {
455   g_return_val_if_fail (str != NULL, FALSE);
456
457   return g_memory_buffer_write (mbuf, str, strlen (str));
458 }
459
460
461 /**
462  * SECTION:gdbusmessage
463  * @short_description: D-Bus Message
464  * @include: gio/gio.h
465  *
466  * A type for representing D-Bus messages that can be sent or received
467  * on a #GDBusConnection.
468  */
469
470 typedef struct _GDBusMessageClass GDBusMessageClass;
471
472 /**
473  * GDBusMessageClass:
474  *
475  * Class structure for #GDBusMessage.
476  *
477  * Since: 2.26
478  */
479 struct _GDBusMessageClass
480 {
481   /*< private >*/
482   GObjectClass parent_class;
483 };
484
485 /**
486  * GDBusMessage:
487  *
488  * The #GDBusMessage structure contains only private data and should
489  * only be accessed using the provided API.
490  *
491  * Since: 2.26
492  */
493 struct _GDBusMessage
494 {
495   /*< private >*/
496   GObject parent_instance;
497
498   GDBusMessageType type;
499   GDBusMessageFlags flags;
500   gboolean locked;
501   GDBusMessageByteOrder byte_order;
502   guchar major_protocol_version;
503   guint32 serial;
504   GHashTable *headers;
505   GVariant *body;
506 #ifdef G_OS_UNIX
507   GUnixFDList *fd_list;
508 #endif
509 };
510
511 enum
512 {
513   PROP_0,
514   PROP_LOCKED
515 };
516
517 G_DEFINE_TYPE (GDBusMessage, g_dbus_message, G_TYPE_OBJECT);
518
519 static void
520 g_dbus_message_finalize (GObject *object)
521 {
522   GDBusMessage *message = G_DBUS_MESSAGE (object);
523
524   if (message->headers != NULL)
525     g_hash_table_unref (message->headers);
526   if (message->body != NULL)
527     g_variant_unref (message->body);
528 #ifdef G_OS_UNIX
529   if (message->fd_list != NULL)
530     g_object_unref (message->fd_list);
531 #endif
532
533   if (G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize != NULL)
534     G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize (object);
535 }
536
537 static void
538 g_dbus_message_get_property (GObject    *object,
539                              guint       prop_id,
540                              GValue     *value,
541                              GParamSpec *pspec)
542 {
543   GDBusMessage *message = G_DBUS_MESSAGE (object);
544
545   switch (prop_id)
546     {
547     case PROP_LOCKED:
548       g_value_set_boolean (value, g_dbus_message_get_locked (message));
549       break;
550
551     default:
552       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
553       break;
554     }
555 }
556
557 static void
558 g_dbus_message_class_init (GDBusMessageClass *klass)
559 {
560   GObjectClass *gobject_class;
561
562   gobject_class = G_OBJECT_CLASS (klass);
563   gobject_class->finalize     = g_dbus_message_finalize;
564   gobject_class->get_property = g_dbus_message_get_property;
565
566   /**
567    * GDBusConnection:locked:
568    *
569    * A boolean specifying whether the message is locked.
570    *
571    * Since: 2.26
572    */
573   g_object_class_install_property (gobject_class,
574                                    PROP_LOCKED,
575                                    g_param_spec_boolean ("locked",
576                                                          P_("Locked"),
577                                                          P_("Whether the message is locked"),
578                                                          FALSE,
579                                                          G_PARAM_READABLE |
580                                                          G_PARAM_STATIC_NAME |
581                                                          G_PARAM_STATIC_BLURB |
582                                                          G_PARAM_STATIC_NICK));
583 }
584
585 static void
586 g_dbus_message_init (GDBusMessage *message)
587 {
588   /* Any D-Bus implementation is supposed to handle both Big and
589    * Little Endian encodings and the Endianness is part of the D-Bus
590    * message - we prefer to use Big Endian (since it's Network Byte
591    * Order and just easier to read for humans) but if the machine is
592    * Little Endian we use that for performance reasons.
593    */
594 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
595   message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
596 #else
597   /* this could also be G_PDP_ENDIAN */
598   message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
599 #endif
600   message->headers = g_hash_table_new_full (g_direct_hash,
601                                             g_direct_equal,
602                                             NULL,
603                                             (GDestroyNotify) g_variant_unref);
604 }
605
606 /**
607  * g_dbus_message_new:
608  *
609  * Creates a new empty #GDBusMessage.
610  *
611  * Returns: A #GDBusMessage. Free with g_object_unref().
612  *
613  * Since: 2.26
614  */
615 GDBusMessage *
616 g_dbus_message_new (void)
617 {
618   return g_object_new (G_TYPE_DBUS_MESSAGE, NULL);
619 }
620
621 /**
622  * g_dbus_message_new_method_call:
623  * @name: (allow-none): A valid D-Bus name or %NULL.
624  * @path: A valid object path.
625  * @interface_: (allow-none): A valid D-Bus interface name or %NULL.
626  * @method: A valid method name.
627  *
628  * Creates a new #GDBusMessage for a method call.
629  *
630  * Returns: A #GDBusMessage. Free with g_object_unref().
631  *
632  * Since: 2.26
633  */
634 GDBusMessage *
635 g_dbus_message_new_method_call (const gchar *name,
636                                 const gchar *path,
637                                 const gchar *interface_,
638                                 const gchar *method)
639 {
640   GDBusMessage *message;
641
642   g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
643   g_return_val_if_fail (g_variant_is_object_path (path), NULL);
644   g_return_val_if_fail (g_dbus_is_member_name (method), NULL);
645   g_return_val_if_fail (interface_ == NULL || g_dbus_is_interface_name (interface_), NULL);
646
647   message = g_dbus_message_new ();
648   message->type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
649
650   if (name != NULL)
651     g_dbus_message_set_destination (message, name);
652   g_dbus_message_set_path (message, path);
653   g_dbus_message_set_member (message, method);
654   if (interface_ != NULL)
655     g_dbus_message_set_interface (message, interface_);
656
657   return message;
658 }
659
660 /**
661  * g_dbus_message_new_signal:
662  * @path: A valid object path.
663  * @interface_: A valid D-Bus interface name.
664  * @signal: A valid signal name.
665  *
666  * Creates a new #GDBusMessage for a signal emission.
667  *
668  * Returns: A #GDBusMessage. Free with g_object_unref().
669  *
670  * Since: 2.26
671  */
672 GDBusMessage *
673 g_dbus_message_new_signal (const gchar  *path,
674                            const gchar  *interface_,
675                            const gchar  *signal)
676 {
677   GDBusMessage *message;
678
679   g_return_val_if_fail (g_variant_is_object_path (path), NULL);
680   g_return_val_if_fail (g_dbus_is_member_name (signal), NULL);
681   g_return_val_if_fail (g_dbus_is_interface_name (interface_), NULL);
682
683   message = g_dbus_message_new ();
684   message->type = G_DBUS_MESSAGE_TYPE_SIGNAL;
685   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
686
687   g_dbus_message_set_path (message, path);
688   g_dbus_message_set_member (message, signal);
689   g_dbus_message_set_interface (message, interface_);
690
691   return message;
692 }
693
694
695 /**
696  * g_dbus_message_new_method_reply:
697  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
698  * create a reply message to.
699  *
700  * Creates a new #GDBusMessage that is a reply to @method_call_message.
701  *
702  * Returns: (transfer full):  #GDBusMessage. Free with g_object_unref().
703  *
704  * Since: 2.26
705  */
706 GDBusMessage *
707 g_dbus_message_new_method_reply (GDBusMessage *method_call_message)
708 {
709   GDBusMessage *message;
710   const gchar *sender;
711
712   g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
713   g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
714   g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
715
716   message = g_dbus_message_new ();
717   message->type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
718   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
719   /* reply with same endianness */
720   message->byte_order = method_call_message->byte_order;
721
722   g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
723   sender = g_dbus_message_get_sender (method_call_message);
724   if (sender != NULL)
725     g_dbus_message_set_destination (message, sender);
726
727   return message;
728 }
729
730 /**
731  * g_dbus_message_new_method_error:
732  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
733  * create a reply message to.
734  * @error_name: A valid D-Bus error name.
735  * @error_message_format: The D-Bus error message in a printf() format.
736  * @...: Arguments for @error_message_format.
737  *
738  * Creates a new #GDBusMessage that is an error reply to @method_call_message.
739  *
740  * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
741  *
742  * Since: 2.26
743  */
744 GDBusMessage *
745 g_dbus_message_new_method_error (GDBusMessage             *method_call_message,
746                                  const gchar              *error_name,
747                                  const gchar              *error_message_format,
748                                  ...)
749 {
750   GDBusMessage *ret;
751   va_list var_args;
752
753   va_start (var_args, error_message_format);
754   ret = g_dbus_message_new_method_error_valist (method_call_message,
755                                                 error_name,
756                                                 error_message_format,
757                                                 var_args);
758   va_end (var_args);
759
760   return ret;
761 }
762
763 /**
764  * g_dbus_message_new_method_error_literal:
765  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
766  * create a reply message to.
767  * @error_name: A valid D-Bus error name.
768  * @error_message: The D-Bus error message.
769  *
770  * Creates a new #GDBusMessage that is an error reply to @method_call_message.
771  *
772  * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
773  *
774  * Since: 2.26
775  */
776 GDBusMessage *
777 g_dbus_message_new_method_error_literal (GDBusMessage  *method_call_message,
778                                          const gchar   *error_name,
779                                          const gchar   *error_message)
780 {
781   GDBusMessage *message;
782   const gchar *sender;
783
784   g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
785   g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
786   g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
787   g_return_val_if_fail (g_dbus_is_name (error_name), NULL);
788   g_return_val_if_fail (error_message != NULL, NULL);
789
790   message = g_dbus_message_new ();
791   message->type = G_DBUS_MESSAGE_TYPE_ERROR;
792   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
793   /* reply with same endianness */
794   message->byte_order = method_call_message->byte_order;
795
796   g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
797   g_dbus_message_set_error_name (message, error_name);
798   g_dbus_message_set_body (message, g_variant_new ("(s)", error_message));
799
800   sender = g_dbus_message_get_sender (method_call_message);
801   if (sender != NULL)
802     g_dbus_message_set_destination (message, sender);
803
804   return message;
805 }
806
807 /**
808  * g_dbus_message_new_method_error_valist:
809  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
810  * create a reply message to.
811  * @error_name: A valid D-Bus error name.
812  * @error_message_format: The D-Bus error message in a printf() format.
813  * @var_args: Arguments for @error_message_format.
814  *
815  * Like g_dbus_message_new_method_error() but intended for language bindings.
816  *
817  * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
818  *
819  * Since: 2.26
820  */
821 G_GNUC_PRINTF(3, 0)
822 GDBusMessage *
823 g_dbus_message_new_method_error_valist (GDBusMessage             *method_call_message,
824                                         const gchar              *error_name,
825                                         const gchar              *error_message_format,
826                                         va_list                   var_args)
827 {
828   GDBusMessage *ret;
829   gchar *error_message;
830   error_message = g_strdup_vprintf (error_message_format, var_args);
831   ret = g_dbus_message_new_method_error_literal (method_call_message,
832                                                  error_name,
833                                                  error_message);
834   g_free (error_message);
835   return ret;
836 }
837
838 /* ---------------------------------------------------------------------------------------------------- */
839
840 /**
841  * g_dbus_message_get_byte_order:
842  * @message: A #GDBusMessage.
843  *
844  * Gets the byte order of @message.
845  *
846  * Returns: The byte order.
847  */
848 GDBusMessageByteOrder
849 g_dbus_message_get_byte_order (GDBusMessage *message)
850 {
851   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), (GDBusMessageByteOrder) 0);
852   return message->byte_order;
853 }
854
855 /**
856  * g_dbus_message_set_byte_order:
857  * @message: A #GDBusMessage.
858  * @byte_order: The byte order.
859  *
860  * Sets the byte order of @message.
861  */
862 void
863 g_dbus_message_set_byte_order (GDBusMessage          *message,
864                                GDBusMessageByteOrder  byte_order)
865 {
866   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
867
868   if (message->locked)
869     {
870       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
871       return;
872     }
873
874   message->byte_order = byte_order;
875 }
876
877 /* ---------------------------------------------------------------------------------------------------- */
878
879 /* TODO: need GI annotations to specify that any guchar value goes for the type */
880
881 /**
882  * g_dbus_message_get_message_type:
883  * @message: A #GDBusMessage.
884  *
885  * Gets the type of @message.
886  *
887  * Returns: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
888  *
889  * Since: 2.26
890  */
891 GDBusMessageType
892 g_dbus_message_get_message_type (GDBusMessage  *message)
893 {
894   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_TYPE_INVALID);
895   return message->type;
896 }
897
898 /**
899  * g_dbus_message_set_message_type:
900  * @message: A #GDBusMessage.
901  * @type: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
902  *
903  * Sets @message to be of @type.
904  *
905  * Since: 2.26
906  */
907 void
908 g_dbus_message_set_message_type (GDBusMessage      *message,
909                                  GDBusMessageType   type)
910 {
911   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
912   g_return_if_fail (type >=0 && type < 256);
913
914   if (message->locked)
915     {
916       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
917       return;
918     }
919
920   message->type = type;
921 }
922
923 /* ---------------------------------------------------------------------------------------------------- */
924
925 /* TODO: need GI annotations to specify that any guchar value goes for flags */
926
927 /**
928  * g_dbus_message_get_flags:
929  * @message: A #GDBusMessage.
930  *
931  * Gets the flags for @message.
932  *
933  * Returns: Flags that are set (typically values from the #GDBusMessageFlags enumeration bitwise ORed together).
934  *
935  * Since: 2.26
936  */
937 GDBusMessageFlags
938 g_dbus_message_get_flags (GDBusMessage  *message)
939 {
940   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_FLAGS_NONE);
941   return message->flags;
942 }
943
944 /**
945  * g_dbus_message_set_flags:
946  * @message: A #GDBusMessage.
947  * @flags: Flags for @message that are set (typically values from the #GDBusMessageFlags
948  * enumeration bitwise ORed together).
949  *
950  * Sets the flags to set on @message.
951  *
952  * Since: 2.26
953  */
954 void
955 g_dbus_message_set_flags (GDBusMessage       *message,
956                           GDBusMessageFlags   flags)
957 {
958   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
959   g_return_if_fail (flags >=0 && flags < 256);
960
961   if (message->locked)
962     {
963       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
964       return;
965     }
966
967   message->flags = flags;
968 }
969
970 /* ---------------------------------------------------------------------------------------------------- */
971
972 /**
973  * g_dbus_message_get_serial:
974  * @message: A #GDBusMessage.
975  *
976  * Gets the serial for @message.
977  *
978  * Returns: A #guint32.
979  *
980  * Since: 2.26
981  */
982 guint32
983 g_dbus_message_get_serial (GDBusMessage *message)
984 {
985   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
986   return message->serial;
987 }
988
989 /**
990  * g_dbus_message_set_serial:
991  * @message: A #GDBusMessage.
992  * @serial: A #guint32.
993  *
994  * Sets the serial for @message.
995  *
996  * Since: 2.26
997  */
998 void
999 g_dbus_message_set_serial (GDBusMessage  *message,
1000                            guint32        serial)
1001 {
1002   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1003
1004   if (message->locked)
1005     {
1006       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1007       return;
1008     }
1009
1010   message->serial = serial;
1011 }
1012
1013 /* ---------------------------------------------------------------------------------------------------- */
1014
1015 /* TODO: need GI annotations to specify that any guchar value goes for header_field */
1016
1017 /**
1018  * g_dbus_message_get_header:
1019  * @message: A #GDBusMessage.
1020  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1021  *
1022  * Gets a header field on @message.
1023  *
1024  * Returns: A #GVariant with the value if the header was found, %NULL
1025  * otherwise. Do not free, it is owned by @message.
1026  *
1027  * Since: 2.26
1028  */
1029 GVariant *
1030 g_dbus_message_get_header (GDBusMessage             *message,
1031                            GDBusMessageHeaderField   header_field)
1032 {
1033   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1034   g_return_val_if_fail (header_field >=0 && header_field < 256, NULL);
1035   return g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
1036 }
1037
1038 /**
1039  * g_dbus_message_set_header:
1040  * @message: A #GDBusMessage.
1041  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1042  * @value: (allow-none): A #GVariant to set the header field or %NULL to clear the header field.
1043  *
1044  * Sets a header field on @message.
1045  *
1046  * If @value is floating, @message assumes ownership of @value.
1047  *
1048  * Since: 2.26
1049  */
1050 void
1051 g_dbus_message_set_header (GDBusMessage             *message,
1052                            GDBusMessageHeaderField   header_field,
1053                            GVariant                 *value)
1054 {
1055   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1056   g_return_if_fail (header_field >=0 && header_field < 256);
1057
1058   if (message->locked)
1059     {
1060       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1061       return;
1062     }
1063
1064   if (value == NULL)
1065     {
1066       g_hash_table_remove (message->headers, GUINT_TO_POINTER (header_field));
1067     }
1068   else
1069     {
1070       g_hash_table_insert (message->headers, GUINT_TO_POINTER (header_field), g_variant_ref_sink (value));
1071     }
1072 }
1073
1074 /**
1075  * g_dbus_message_get_header_fields:
1076  * @message: A #GDBusMessage.
1077  *
1078  * Gets an array of all header fields on @message that are set.
1079  *
1080  * Returns: (array zero-terminated=1): An array of header fields
1081  * terminated by %G_DBUS_MESSAGE_HEADER_FIELD_INVALID.  Each element
1082  * is a #guchar. Free with g_free().
1083  *
1084  * Since: 2.26
1085  */
1086 guchar *
1087 g_dbus_message_get_header_fields (GDBusMessage  *message)
1088 {
1089   GList *keys;
1090   guchar *ret;
1091   guint num_keys;
1092   GList *l;
1093   guint n;
1094
1095   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1096
1097   keys = g_hash_table_get_keys (message->headers);
1098   num_keys = g_list_length (keys);
1099   ret = g_new (guchar, num_keys + 1);
1100   for (l = keys, n = 0; l != NULL; l = l->next, n++)
1101     ret[n] = GPOINTER_TO_UINT (l->data);
1102   g_assert (n == num_keys);
1103   ret[n] = G_DBUS_MESSAGE_HEADER_FIELD_INVALID;
1104   g_list_free (keys);
1105
1106   return ret;
1107 }
1108
1109 /* ---------------------------------------------------------------------------------------------------- */
1110
1111 /**
1112  * g_dbus_message_get_body:
1113  * @message: A #GDBusMessage.
1114  *
1115  * Gets the body of a message.
1116  *
1117  * Returns: A #GVariant or %NULL if the body is empty. Do not free, it is owned by @message.
1118  *
1119  * Since: 2.26
1120  */
1121 GVariant *
1122 g_dbus_message_get_body (GDBusMessage  *message)
1123 {
1124   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1125   return message->body;
1126 }
1127
1128 /**
1129  * g_dbus_message_set_body:
1130  * @message: A #GDBusMessage.
1131  * @body: Either %NULL or a #GVariant that is a tuple.
1132  *
1133  * Sets the body @message. As a side-effect the
1134  * %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field is set to the
1135  * type string of @body (or cleared if @body is %NULL).
1136  *
1137  * If @body is floating, @message assumes ownership of @body.
1138  *
1139  * Since: 2.26
1140  */
1141 void
1142 g_dbus_message_set_body (GDBusMessage  *message,
1143                          GVariant      *body)
1144 {
1145   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1146   g_return_if_fail ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE));
1147
1148   if (message->locked)
1149     {
1150       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1151       return;
1152     }
1153
1154   if (message->body != NULL)
1155     g_variant_unref (message->body);
1156   if (body == NULL)
1157     {
1158       message->body = NULL;
1159       g_dbus_message_set_signature (message, NULL);
1160     }
1161   else
1162     {
1163       const gchar *type_string;
1164       gsize type_string_len;
1165       gchar *signature;
1166
1167       message->body = g_variant_ref_sink (body);
1168
1169       type_string = g_variant_get_type_string (body);
1170       type_string_len = strlen (type_string);
1171       g_assert (type_string_len >= 2);
1172       signature = g_strndup (type_string + 1, type_string_len - 2);
1173       g_dbus_message_set_signature (message, signature);
1174       g_free (signature);
1175     }
1176 }
1177
1178 /* ---------------------------------------------------------------------------------------------------- */
1179
1180 #ifdef G_OS_UNIX
1181 /**
1182  * g_dbus_message_get_unix_fd_list:
1183  * @message: A #GDBusMessage.
1184  *
1185  * Gets the UNIX file descriptors associated with @message, if any.
1186  *
1187  * This method is only available on UNIX.
1188  *
1189  * Returns: (transfer none):A #GUnixFDList or %NULL if no file descriptors are
1190  * associated. Do not free, this object is owned by @message.
1191  *
1192  * Since: 2.26
1193  */
1194 GUnixFDList *
1195 g_dbus_message_get_unix_fd_list (GDBusMessage  *message)
1196 {
1197   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1198   return message->fd_list;
1199 }
1200
1201 /**
1202  * g_dbus_message_set_unix_fd_list:
1203  * @message: A #GDBusMessage.
1204  * @fd_list: (allow-none): A #GUnixFDList or %NULL.
1205  *
1206  * Sets the UNIX file descriptors associated with @message. As a
1207  * side-effect the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header
1208  * field is set to the number of fds in @fd_list (or cleared if
1209  * @fd_list is %NULL).
1210  *
1211  * This method is only available on UNIX.
1212  *
1213  * Since: 2.26
1214  */
1215 void
1216 g_dbus_message_set_unix_fd_list (GDBusMessage  *message,
1217                                  GUnixFDList   *fd_list)
1218 {
1219   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1220   g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
1221
1222   if (message->locked)
1223     {
1224       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1225       return;
1226     }
1227
1228   if (message->fd_list != NULL)
1229     g_object_unref (message->fd_list);
1230   if (fd_list != NULL)
1231     {
1232       message->fd_list = g_object_ref (fd_list);
1233       g_dbus_message_set_num_unix_fds (message, g_unix_fd_list_get_length (fd_list));
1234     }
1235   else
1236     {
1237       message->fd_list = NULL;
1238       g_dbus_message_set_num_unix_fds (message, 0);
1239     }
1240 }
1241 #endif
1242
1243 /* ---------------------------------------------------------------------------------------------------- */
1244
1245 static gboolean
1246 validate_headers (GDBusMessage  *message,
1247                   GError       **error)
1248 {
1249   gboolean ret;
1250
1251   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1252   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1253
1254   ret = FALSE;
1255
1256   switch (message->type)
1257     {
1258     case G_DBUS_MESSAGE_TYPE_INVALID:
1259       g_set_error_literal (error,
1260                            G_IO_ERROR,
1261                            G_IO_ERROR_INVALID_ARGUMENT,
1262                            _("type is INVALID"));
1263       goto out;
1264       break;
1265
1266     case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
1267       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1268           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1269         {
1270           g_set_error_literal (error,
1271                                G_IO_ERROR,
1272                                G_IO_ERROR_INVALID_ARGUMENT,
1273                                _("METHOD_CALL message: PATH or MEMBER header field is missing"));
1274           goto out;
1275         }
1276       break;
1277
1278     case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
1279       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1280         {
1281           g_set_error_literal (error,
1282                                G_IO_ERROR,
1283                                G_IO_ERROR_INVALID_ARGUMENT,
1284                                _("METHOD_RETURN message: REPLY_SERIAL header field is missing"));
1285           goto out;
1286         }
1287       break;
1288
1289     case G_DBUS_MESSAGE_TYPE_ERROR:
1290       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME) == NULL ||
1291           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1292         {
1293           g_set_error_literal (error,
1294                                G_IO_ERROR,
1295                                G_IO_ERROR_INVALID_ARGUMENT,
1296                                _("ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing"));
1297           goto out;
1298         }
1299       break;
1300
1301     case G_DBUS_MESSAGE_TYPE_SIGNAL:
1302       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1303           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE) == NULL ||
1304           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1305         {
1306           g_set_error_literal (error,
1307                                G_IO_ERROR,
1308                                G_IO_ERROR_INVALID_ARGUMENT,
1309                                _("SIGNAL message: PATH, INTERFACE or MEMBER header field is missing"));
1310           goto out;
1311         }
1312       if (g_strcmp0 (g_dbus_message_get_path (message), "/org/freedesktop/DBus/Local") == 0)
1313         {
1314           g_set_error_literal (error,
1315                                G_IO_ERROR,
1316                                G_IO_ERROR_INVALID_ARGUMENT,
1317                                _("SIGNAL message: The PATH header field is using the reserved value /org/freedesktop/DBus/Local"));
1318           goto out;
1319         }
1320       if (g_strcmp0 (g_dbus_message_get_interface (message), "org.freedesktop.DBus.Local") == 0)
1321         {
1322           g_set_error_literal (error,
1323                                G_IO_ERROR,
1324                                G_IO_ERROR_INVALID_ARGUMENT,
1325                                _("SIGNAL message: The INTERFACE header field is using the reserved value org.freedesktop.DBus.Local"));
1326           goto out;
1327         }
1328       break;
1329
1330     default:
1331       /* hitherto unknown type - nothing to check */
1332       break;
1333     }
1334
1335   ret = TRUE;
1336
1337  out:
1338   g_assert (ret || (error == NULL || *error != NULL));
1339   return ret;
1340 }
1341
1342 /* ---------------------------------------------------------------------------------------------------- */
1343
1344 static gboolean
1345 ensure_input_padding (GMemoryBuffer  *buf,
1346                       gsize           padding_size)
1347 {
1348   gsize offset;
1349   gsize wanted_offset;
1350
1351   offset = buf->pos;
1352   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1353   buf->pos = wanted_offset;
1354   return TRUE;
1355 }
1356
1357 static const gchar *
1358 read_string (GMemoryBuffer  *mbuf,
1359              gsize           len,
1360              GError        **error)
1361 {
1362   gchar *str;
1363   const gchar *end_valid;
1364
1365   if (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1366     {
1367       mbuf->pos = mbuf->valid_len;
1368       /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1369       g_set_error (error,
1370                    G_IO_ERROR,
1371                    G_IO_ERROR_INVALID_ARGUMENT,
1372                    g_dngettext (GETTEXT_PACKAGE,
1373                                 "Wanted to read %lu byte but only got %lu",
1374                                 "Wanted to read %lu bytes but only got %lu",
1375                                 (gulong)len),
1376                                 (gulong)len,
1377                    (gulong)(mbuf->valid_len - mbuf->pos));
1378       return NULL;
1379     }
1380
1381   if (mbuf->data[mbuf->pos + len] != '\0')
1382     {
1383       str = g_strndup (mbuf->data + mbuf->pos, len);
1384       g_set_error (error,
1385                    G_IO_ERROR,
1386                    G_IO_ERROR_INVALID_ARGUMENT,
1387                    _("Expected NUL byte after the string '%s' but found byte %d"),
1388                    str, mbuf->data[mbuf->pos + len]);
1389       g_free (str);
1390       mbuf->pos += len + 1;
1391       return NULL;
1392     }
1393
1394   str = mbuf->data + mbuf->pos;
1395   mbuf->pos += len + 1;
1396
1397   if (!g_utf8_validate (str, -1, &end_valid))
1398     {
1399       gint offset;
1400       gchar *valid_str;
1401       offset = (gint) (end_valid - str);
1402       valid_str = g_strndup (str, offset);
1403       g_set_error (error,
1404                    G_IO_ERROR,
1405                    G_IO_ERROR_INVALID_ARGUMENT,
1406                    _("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
1407                      "The valid UTF-8 string up until that point was '%s'"),
1408                    offset,
1409                    (gint) len,
1410                    valid_str);
1411       g_free (valid_str);
1412       return NULL;
1413     }
1414
1415   return str;
1416 }
1417
1418 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
1419
1420 /* returns a non-floating GVariant! */
1421 static GVariant *
1422 parse_value_from_blob (GMemoryBuffer       *buf,
1423                        const GVariantType  *type,
1424                        gboolean             just_align,
1425                        guint                indent,
1426                        GError             **error)
1427 {
1428   GVariant *ret;
1429   GError *local_error;
1430   gboolean is_leaf;
1431   const gchar *type_string;
1432
1433   type_string = g_variant_type_peek_string (type);
1434
1435 #ifdef DEBUG_SERIALIZER
1436     {
1437       gchar *s;
1438       s = g_variant_type_dup_string (type);
1439       g_print ("%*s%s type %s from offset 0x%04x",
1440                indent, "",
1441                just_align ? "Aligning" : "Reading",
1442                s,
1443                (gint) g_seekable_tell (G_SEEKABLE (buf)));
1444       g_free (s);
1445     }
1446 #endif /* DEBUG_SERIALIZER */
1447
1448   ret = NULL;
1449
1450   is_leaf = TRUE;
1451   local_error = NULL;
1452   switch (type_string[0])
1453     {
1454     case 'b': /* G_VARIANT_TYPE_BOOLEAN */
1455       ensure_input_padding (buf, 4);
1456       if (!just_align)
1457         {
1458           gboolean v;
1459           v = g_memory_buffer_read_uint32 (buf);
1460           ret = g_variant_new_boolean (v);
1461         }
1462       break;
1463
1464     case 'y': /* G_VARIANT_TYPE_BYTE */
1465       if (!just_align)
1466         {
1467           guchar v;
1468           v = g_memory_buffer_read_byte (buf);
1469           ret = g_variant_new_byte (v);
1470         }
1471       break;
1472
1473     case 'n': /* G_VARIANT_TYPE_INT16 */
1474       ensure_input_padding (buf, 2);
1475       if (!just_align)
1476         {
1477           gint16 v;
1478           v = g_memory_buffer_read_int16 (buf);
1479           ret = g_variant_new_int16 (v);
1480         }
1481       break;
1482
1483     case 'q': /* G_VARIANT_TYPE_UINT16 */
1484       ensure_input_padding (buf, 2);
1485       if (!just_align)
1486         {
1487           guint16 v;
1488           v = g_memory_buffer_read_uint16 (buf);
1489           ret = g_variant_new_uint16 (v);
1490         }
1491       break;
1492
1493     case 'i': /* G_VARIANT_TYPE_INT32 */
1494       ensure_input_padding (buf, 4);
1495       if (!just_align)
1496         {
1497           gint32 v;
1498           v = g_memory_buffer_read_int32 (buf);
1499           ret = g_variant_new_int32 (v);
1500         }
1501       break;
1502
1503     case 'u': /* G_VARIANT_TYPE_UINT32 */
1504       ensure_input_padding (buf, 4);
1505       if (!just_align)
1506         {
1507           guint32 v;
1508           v = g_memory_buffer_read_uint32 (buf);
1509           ret = g_variant_new_uint32 (v);
1510         }
1511       break;
1512
1513     case 'x': /* G_VARIANT_TYPE_INT64 */
1514       ensure_input_padding (buf, 8);
1515       if (!just_align)
1516         {
1517           gint64 v;
1518           v = g_memory_buffer_read_int64 (buf);
1519           ret = g_variant_new_int64 (v);
1520         }
1521       break;
1522
1523     case 't': /* G_VARIANT_TYPE_UINT64 */
1524       ensure_input_padding (buf, 8);
1525       if (!just_align)
1526         {
1527           guint64 v;
1528           v = g_memory_buffer_read_uint64 (buf);
1529           ret = g_variant_new_uint64 (v);
1530         }
1531       break;
1532
1533     case 'd': /* G_VARIANT_TYPE_DOUBLE */
1534       ensure_input_padding (buf, 8);
1535       if (!just_align)
1536         {
1537           union {
1538             guint64 v_uint64;
1539             gdouble v_double;
1540           } u;
1541           G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
1542           u.v_uint64 = g_memory_buffer_read_uint64 (buf);
1543           ret = g_variant_new_double (u.v_double);
1544         }
1545       break;
1546
1547     case 's': /* G_VARIANT_TYPE_STRING */
1548       ensure_input_padding (buf, 4);
1549       if (!just_align)
1550         {
1551           guint32 len;
1552           const gchar *v;
1553           len = g_memory_buffer_read_uint32 (buf);
1554           v = read_string (buf, (gsize) len, &local_error);
1555           if (v == NULL)
1556             goto fail;
1557           ret = g_variant_new_string (v);
1558         }
1559       break;
1560
1561     case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
1562       ensure_input_padding (buf, 4);
1563       if (!just_align)
1564         {
1565           guint32 len;
1566           const gchar *v;
1567           len = g_memory_buffer_read_uint32 (buf);
1568           v = read_string (buf, (gsize) len, &local_error);
1569           if (v == NULL)
1570             goto fail;
1571           if (!g_variant_is_object_path (v))
1572             {
1573               g_set_error (&local_error,
1574                            G_IO_ERROR,
1575                            G_IO_ERROR_INVALID_ARGUMENT,
1576                            _("Parsed value '%s' is not a valid D-Bus object path"),
1577                            v);
1578               goto fail;
1579             }
1580           ret = g_variant_new_object_path (v);
1581         }
1582       break;
1583
1584     case 'g': /* G_VARIANT_TYPE_SIGNATURE */
1585       if (!just_align)
1586         {
1587           guchar len;
1588           const gchar *v;
1589           len = g_memory_buffer_read_byte (buf);
1590           v = read_string (buf, (gsize) len, &local_error);
1591           if (v == NULL)
1592             goto fail;
1593           if (!g_variant_is_signature (v))
1594             {
1595               g_set_error (&local_error,
1596                            G_IO_ERROR,
1597                            G_IO_ERROR_INVALID_ARGUMENT,
1598                            _("Parsed value '%s' is not a valid D-Bus signature"),
1599                        v);
1600               goto fail;
1601             }
1602           ret = g_variant_new_signature (v);
1603         }
1604       break;
1605
1606     case 'h': /* G_VARIANT_TYPE_HANDLE */
1607       ensure_input_padding (buf, 4);
1608       if (!just_align)
1609         {
1610           gint32 v;
1611           v = g_memory_buffer_read_int32 (buf);
1612           ret = g_variant_new_handle (v);
1613         }
1614       break;
1615
1616     case 'a': /* G_VARIANT_TYPE_ARRAY */
1617       ensure_input_padding (buf, 4);
1618
1619       /* If we are only aligning for this array type, it is the child type of
1620        * another array, which is empty. So, we do not need to add padding for
1621        * this nonexistent array's elements: we only need to align for this
1622        * array itself (4 bytes). See
1623        * <https://bugzilla.gnome.org/show_bug.cgi?id=673612>.
1624        */
1625       if (!just_align)
1626         {
1627           guint32 array_len;
1628           goffset offset;
1629           goffset target;
1630           const GVariantType *element_type;
1631           GVariantBuilder builder;
1632
1633           array_len = g_memory_buffer_read_uint32 (buf);
1634
1635           is_leaf = FALSE;
1636 #ifdef DEBUG_SERIALIZER
1637           g_print (": array spans 0x%04x bytes\n", array_len);
1638 #endif /* DEBUG_SERIALIZER */
1639
1640           if (array_len > (2<<26))
1641             {
1642               /* G_GUINT32_FORMAT doesn't work with gettext, so use u */
1643               g_set_error (&local_error,
1644                            G_IO_ERROR,
1645                            G_IO_ERROR_INVALID_ARGUMENT,
1646                            g_dngettext (GETTEXT_PACKAGE,
1647                                         "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB).",
1648                                         "Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB).",
1649                                         array_len),
1650                            array_len);
1651               goto fail;
1652             }
1653
1654           g_variant_builder_init (&builder, type);
1655           element_type = g_variant_type_element (type);
1656
1657           if (array_len == 0)
1658             {
1659               GVariant *item;
1660               item = parse_value_from_blob (buf,
1661                                             element_type,
1662                                             TRUE,
1663                                             indent + 2,
1664                                             NULL);
1665               g_assert (item == NULL);
1666             }
1667           else
1668             {
1669               /* TODO: optimize array of primitive types */
1670               offset = buf->pos;
1671               target = offset + array_len;
1672               while (offset < target)
1673                 {
1674                   GVariant *item;
1675                   item = parse_value_from_blob (buf,
1676                                                 element_type,
1677                                                 FALSE,
1678                                                 indent + 2,
1679                                                 &local_error);
1680                   if (item == NULL)
1681                     {
1682                       g_variant_builder_clear (&builder);
1683                       goto fail;
1684                     }
1685                   g_variant_builder_add_value (&builder, item);
1686                   g_variant_unref (item);
1687                   offset = buf->pos;
1688                 }
1689             }
1690
1691           ret = g_variant_builder_end (&builder);
1692         }
1693       break;
1694
1695     default:
1696       if (g_variant_type_is_dict_entry (type))
1697         {
1698           const GVariantType *key_type;
1699           const GVariantType *value_type;
1700           GVariant *key;
1701           GVariant *value;
1702
1703           ensure_input_padding (buf, 8);
1704
1705           is_leaf = FALSE;
1706 #ifdef DEBUG_SERIALIZER
1707           g_print ("\n");
1708 #endif /* DEBUG_SERIALIZER */
1709
1710           if (!just_align)
1711             {
1712               key_type = g_variant_type_key (type);
1713               key = parse_value_from_blob (buf,
1714                                            key_type,
1715                                            FALSE,
1716                                            indent + 2,
1717                                            &local_error);
1718               if (key == NULL)
1719                 goto fail;
1720               value_type = g_variant_type_value (type);
1721               value = parse_value_from_blob (buf,
1722                                              value_type,
1723                                              FALSE,
1724                                              indent + 2,
1725                                              &local_error);
1726               if (value == NULL)
1727                 {
1728                   g_variant_unref (key);
1729                   goto fail;
1730                 }
1731               ret = g_variant_new_dict_entry (key, value);
1732               g_variant_unref (key);
1733               g_variant_unref (value);
1734             }
1735         }
1736       else if (g_variant_type_is_tuple (type))
1737         {
1738           ensure_input_padding (buf, 8);
1739
1740           is_leaf = FALSE;
1741 #ifdef DEBUG_SERIALIZER
1742           g_print ("\n");
1743 #endif /* DEBUG_SERIALIZER */
1744
1745           if (!just_align)
1746             {
1747               const GVariantType *element_type;
1748               GVariantBuilder builder;
1749
1750               g_variant_builder_init (&builder, type);
1751               element_type = g_variant_type_first (type);
1752               while (element_type != NULL)
1753                 {
1754                   GVariant *item;
1755                   item = parse_value_from_blob (buf,
1756                                                 element_type,
1757                                                 FALSE,
1758                                                 indent + 2,
1759                                                 &local_error);
1760                   if (item == NULL)
1761                     {
1762                       g_variant_builder_clear (&builder);
1763                       goto fail;
1764                     }
1765                   g_variant_builder_add_value (&builder, item);
1766                   g_variant_unref (item);
1767
1768                   element_type = g_variant_type_next (element_type);
1769                 }
1770               ret = g_variant_builder_end (&builder);
1771             }
1772         }
1773       else if (g_variant_type_is_variant (type))
1774         {
1775           is_leaf = FALSE;
1776 #ifdef DEBUG_SERIALIZER
1777           g_print ("\n");
1778 #endif /* DEBUG_SERIALIZER */
1779
1780           if (!just_align)
1781             {
1782               guchar siglen;
1783               const gchar *sig;
1784               GVariantType *variant_type;
1785               GVariant *value;
1786
1787               siglen = g_memory_buffer_read_byte (buf);
1788               sig = read_string (buf, (gsize) siglen, &local_error);
1789               if (sig == NULL)
1790                 goto fail;
1791               if (!g_variant_is_signature (sig))
1792                 {
1793                   g_set_error (&local_error,
1794                                G_IO_ERROR,
1795                                G_IO_ERROR_INVALID_ARGUMENT,
1796                                _("Parsed value '%s' for variant is not a valid D-Bus signature"),
1797                                sig);
1798                   goto fail;
1799                 }
1800               variant_type = g_variant_type_new (sig);
1801               value = parse_value_from_blob (buf,
1802                                              variant_type,
1803                                              FALSE,
1804                                              indent + 2,
1805                                              &local_error);
1806               g_variant_type_free (variant_type);
1807               if (value == NULL)
1808                 goto fail;
1809               ret = g_variant_new_variant (value);
1810               g_variant_unref (value);
1811             }
1812         }
1813       else
1814         {
1815           gchar *s;
1816           s = g_variant_type_dup_string (type);
1817           g_set_error (&local_error,
1818                        G_IO_ERROR,
1819                        G_IO_ERROR_INVALID_ARGUMENT,
1820                        _("Error deserializing GVariant with type string '%s' from the D-Bus wire format"),
1821                        s);
1822           g_free (s);
1823           goto fail;
1824         }
1825       break;
1826     }
1827
1828   g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
1829
1830 #ifdef DEBUG_SERIALIZER
1831   if (ret != NULL)
1832     {
1833       if (is_leaf)
1834         {
1835           gchar *s;
1836           if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1837             {
1838               s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
1839             }
1840           else
1841             {
1842               s = g_variant_print (ret, FALSE);
1843             }
1844           g_print (": %s\n", s);
1845           g_free (s);
1846         }
1847     }
1848 #else
1849   is_leaf = is_leaf; /* To avoid -Wunused-but-set-variable */
1850 #endif /* DEBUG_SERIALIZER */
1851
1852   /* sink the reference */
1853   if (ret != NULL)
1854     {
1855       g_assert (g_variant_is_floating (ret));
1856       g_variant_ref_sink (ret);
1857     }
1858   return ret;
1859
1860  fail:
1861 #ifdef DEBUG_SERIALIZER
1862   g_print ("\n"
1863            "%*sFAILURE: %s (%s, %d)\n",
1864            indent, "",
1865            local_error->message,
1866            g_quark_to_string (local_error->domain),
1867            local_error->code);
1868 #endif /* DEBUG_SERIALIZER */
1869   g_propagate_error (error, local_error);
1870   return NULL;
1871 }
1872
1873 /* ---------------------------------------------------------------------------------------------------- */
1874
1875 /* message_header must be at least 16 bytes */
1876
1877 /**
1878  * g_dbus_message_bytes_needed:
1879  * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1880  * @blob_len: The length of @blob (must be at least 16).
1881  * @error: Return location for error or %NULL.
1882  *
1883  * Utility function to calculate how many bytes are needed to
1884  * completely deserialize the D-Bus message stored at @blob.
1885  *
1886  * Returns: Number of bytes needed or -1 if @error is set (e.g. if
1887  * @blob contains invalid data or not enough data is available to
1888  * determine the size).
1889  *
1890  * Since: 2.26
1891  */
1892 gssize
1893 g_dbus_message_bytes_needed (guchar  *blob,
1894                              gsize    blob_len,
1895                              GError **error)
1896 {
1897   gssize ret;
1898
1899   ret = -1;
1900
1901   g_return_val_if_fail (blob != NULL, -1);
1902   g_return_val_if_fail (error == NULL || *error == NULL, -1);
1903   g_return_val_if_fail (blob_len >= 16, -1);
1904
1905   if (blob[0] == 'l')
1906     {
1907       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1908       ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
1909       /* round up so it's a multiple of 8 */
1910       ret = 8 * ((ret + 7)/8);
1911       /* finally add the body size */
1912       ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
1913     }
1914   else if (blob[0] == 'B')
1915     {
1916       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1917       ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
1918       /* round up so it's a multiple of 8 */
1919       ret = 8 * ((ret + 7)/8);
1920       /* finally add the body size */
1921       ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
1922     }
1923   else
1924     {
1925       g_set_error (error,
1926                    G_IO_ERROR,
1927                    G_IO_ERROR_INVALID_ARGUMENT,
1928                    "Unable to determine message blob length - given blob is malformed");
1929     }
1930
1931   if (ret > (2<<27))
1932     {
1933       g_set_error (error,
1934                    G_IO_ERROR,
1935                    G_IO_ERROR_INVALID_ARGUMENT,
1936                    "Blob indicates that message exceeds maximum message length (128MiB)");
1937       ret = -1;
1938     }
1939
1940   return ret;
1941 }
1942
1943 /* ---------------------------------------------------------------------------------------------------- */
1944
1945 /**
1946  * g_dbus_message_new_from_blob:
1947  * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1948  * @blob_len: The length of @blob.
1949  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1950  * @error: Return location for error or %NULL.
1951  *
1952  * Creates a new #GDBusMessage from the data stored at @blob. The byte
1953  * order that the message was in can be retrieved using
1954  * g_dbus_message_get_byte_order().
1955  *
1956  * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
1957  * g_object_unref().
1958  *
1959  * Since: 2.26
1960  */
1961 GDBusMessage *
1962 g_dbus_message_new_from_blob (guchar                *blob,
1963                               gsize                  blob_len,
1964                               GDBusCapabilityFlags   capabilities,
1965                               GError               **error)
1966 {
1967   gboolean ret;
1968   GMemoryBuffer mbuf;
1969   GDBusMessage *message;
1970   guchar endianness;
1971   guchar major_protocol_version;
1972   guint32 message_body_len;
1973   GVariant *headers;
1974   GVariant *item;
1975   GVariantIter iter;
1976   GVariant *signature;
1977
1978   /* TODO: check against @capabilities */
1979
1980   ret = FALSE;
1981
1982   g_return_val_if_fail (blob != NULL, NULL);
1983   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1984   g_return_val_if_fail (blob_len >= 12, NULL);
1985
1986   message = g_dbus_message_new ();
1987
1988   memset (&mbuf, 0, sizeof (mbuf));
1989   mbuf.data = (gchar *)blob;
1990   mbuf.len = mbuf.valid_len = blob_len;
1991
1992   endianness = g_memory_buffer_read_byte (&mbuf);
1993   switch (endianness)
1994     {
1995     case 'l':
1996       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
1997       message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
1998       break;
1999     case 'B':
2000       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2001       message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
2002       break;
2003     default:
2004       g_set_error (error,
2005                    G_IO_ERROR,
2006                    G_IO_ERROR_INVALID_ARGUMENT,
2007                    _("Invalid endianness value. Expected 0x6c ('l') or 0x42 ('B') but found value 0x%02x"),
2008                    endianness);
2009       goto out;
2010     }
2011
2012   message->type = g_memory_buffer_read_byte (&mbuf);
2013   message->flags = g_memory_buffer_read_byte (&mbuf);
2014   major_protocol_version = g_memory_buffer_read_byte (&mbuf);
2015   if (major_protocol_version != 1)
2016     {
2017       g_set_error (error,
2018                    G_IO_ERROR,
2019                    G_IO_ERROR_INVALID_ARGUMENT,
2020                    _("Invalid major protocol version. Expected 1 but found %d"),
2021                    major_protocol_version);
2022       goto out;
2023     }
2024   message_body_len = g_memory_buffer_read_uint32 (&mbuf);
2025   message->serial = g_memory_buffer_read_uint32 (&mbuf);
2026
2027 #ifdef DEBUG_SERIALIZER
2028   g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2029   {
2030     gchar *s;
2031     s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
2032     g_print ("%s\n", s);
2033     g_free (s);
2034   }
2035 #endif /* DEBUG_SERIALIZER */
2036
2037 #ifdef DEBUG_SERIALIZER
2038   g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2039 #endif /* DEBUG_SERIALIZER */
2040   headers = parse_value_from_blob (&mbuf,
2041                                    G_VARIANT_TYPE ("a{yv}"),
2042                                    FALSE,
2043                                    2,
2044                                    error);
2045   if (headers == NULL)
2046     goto out;
2047   g_variant_iter_init (&iter, headers);
2048   while ((item = g_variant_iter_next_value (&iter)) != NULL)
2049     {
2050       guchar header_field;
2051       GVariant *value;
2052       g_variant_get (item,
2053                      "{yv}",
2054                      &header_field,
2055                      &value);
2056       g_dbus_message_set_header (message, header_field, value);
2057       g_variant_unref (value);
2058       g_variant_unref (item);
2059     }
2060   g_variant_unref (headers);
2061
2062   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2063   if (signature != NULL)
2064     {
2065       const gchar *signature_str;
2066       gsize signature_str_len;
2067
2068       signature_str = g_variant_get_string (signature, &signature_str_len);
2069
2070       /* signature but no body */
2071       if (message_body_len == 0 && signature_str_len > 0)
2072         {
2073           g_set_error (error,
2074                        G_IO_ERROR,
2075                        G_IO_ERROR_INVALID_ARGUMENT,
2076                        _("Signature header with signature '%s' found but message body is empty"),
2077                        signature_str);
2078           goto out;
2079         }
2080       else if (signature_str_len > 0)
2081         {
2082           GVariantType *variant_type;
2083           gchar *tupled_signature_str;
2084
2085           if (!g_variant_is_signature (signature_str))
2086             {
2087               g_set_error (error,
2088                            G_IO_ERROR,
2089                            G_IO_ERROR_INVALID_ARGUMENT,
2090                            _("Parsed value '%s' is not a valid D-Bus signature (for body)"),
2091                            signature_str);
2092               goto out;
2093             }
2094           tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2095           variant_type = g_variant_type_new (tupled_signature_str);
2096           g_free (tupled_signature_str);
2097 #ifdef DEBUG_SERIALIZER
2098           g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2099 #endif /* DEBUG_SERIALIZER */
2100           message->body = parse_value_from_blob (&mbuf,
2101                                                  variant_type,
2102                                                  FALSE,
2103                                                  2,
2104                                                  error);
2105           g_variant_type_free (variant_type);
2106           if (message->body == NULL)
2107             goto out;
2108         }
2109     }
2110   else
2111     {
2112       /* no signature, this is only OK if the body is empty */
2113       if (message_body_len != 0)
2114         {
2115           /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
2116           g_set_error (error,
2117                        G_IO_ERROR,
2118                        G_IO_ERROR_INVALID_ARGUMENT,
2119                        g_dngettext (GETTEXT_PACKAGE,
2120                                     "No signature header in message but the message body is %u byte",
2121                                     "No signature header in message but the message body is %u bytes",
2122                                     message_body_len),
2123                        message_body_len);
2124           goto out;
2125         }
2126     }
2127
2128   if (!validate_headers (message, error))
2129     {
2130       g_prefix_error (error, _("Cannot deserialize message: "));
2131       goto out;
2132     }
2133
2134   ret = TRUE;
2135
2136  out:
2137   if (ret)
2138     {
2139       return message;
2140     }
2141   else
2142     {
2143       if (message != NULL)
2144         g_object_unref (message);
2145       return NULL;
2146     }
2147 }
2148
2149 /* ---------------------------------------------------------------------------------------------------- */
2150
2151 static gsize
2152 ensure_output_padding (GMemoryBuffer  *mbuf,
2153                        gsize           padding_size)
2154 {
2155   gsize offset;
2156   gsize wanted_offset;
2157   gsize padding_needed;
2158   guint n;
2159
2160   offset = mbuf->pos;
2161   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
2162   padding_needed = wanted_offset - offset;
2163
2164   for (n = 0; n < padding_needed; n++)
2165     g_memory_buffer_put_byte (mbuf, '\0');
2166
2167   return padding_needed;
2168 }
2169
2170 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
2171 static gboolean
2172 append_value_to_blob (GVariant            *value,
2173                       const GVariantType  *type,
2174                       GMemoryBuffer       *mbuf,
2175                       gsize               *out_padding_added,
2176                       GError             **error)
2177 {
2178   gsize padding_added;
2179   const gchar *type_string;
2180
2181   type_string = g_variant_type_peek_string (type);
2182
2183   padding_added = 0;
2184
2185   switch (type_string[0])
2186     {
2187     case 'b': /* G_VARIANT_TYPE_BOOLEAN */
2188       padding_added = ensure_output_padding (mbuf, 4);
2189       if (value != NULL)
2190         {
2191           gboolean v = g_variant_get_boolean (value);
2192           g_memory_buffer_put_uint32 (mbuf, v);
2193         }
2194       break;
2195
2196     case 'y': /* G_VARIANT_TYPE_BYTE */
2197       if (value != NULL)
2198         {
2199           guint8 v = g_variant_get_byte (value);
2200           g_memory_buffer_put_byte (mbuf, v);
2201         }
2202       break;
2203
2204     case 'n': /* G_VARIANT_TYPE_INT16 */
2205       padding_added = ensure_output_padding (mbuf, 2);
2206       if (value != NULL)
2207         {
2208           gint16 v = g_variant_get_int16 (value);
2209           g_memory_buffer_put_int16 (mbuf, v);
2210         }
2211       break;
2212
2213     case 'q': /* G_VARIANT_TYPE_UINT16 */
2214       padding_added = ensure_output_padding (mbuf, 2);
2215       if (value != NULL)
2216         {
2217           guint16 v = g_variant_get_uint16 (value);
2218           g_memory_buffer_put_uint16 (mbuf, v);
2219         }
2220       break;
2221
2222     case 'i': /* G_VARIANT_TYPE_INT32 */
2223       padding_added = ensure_output_padding (mbuf, 4);
2224       if (value != NULL)
2225         {
2226           gint32 v = g_variant_get_int32 (value);
2227           g_memory_buffer_put_int32 (mbuf, v);
2228         }
2229       break;
2230
2231     case 'u': /* G_VARIANT_TYPE_UINT32 */
2232       padding_added = ensure_output_padding (mbuf, 4);
2233       if (value != NULL)
2234         {
2235           guint32 v = g_variant_get_uint32 (value);
2236           g_memory_buffer_put_uint32 (mbuf, v);
2237         }
2238       break;
2239
2240     case 'x': /* G_VARIANT_TYPE_INT64 */
2241       padding_added = ensure_output_padding (mbuf, 8);
2242       if (value != NULL)
2243         {
2244           gint64 v = g_variant_get_int64 (value);
2245           g_memory_buffer_put_int64 (mbuf, v);
2246         }
2247       break;
2248
2249     case 't': /* G_VARIANT_TYPE_UINT64 */
2250       padding_added = ensure_output_padding (mbuf, 8);
2251       if (value != NULL)
2252         {
2253           guint64 v = g_variant_get_uint64 (value);
2254           g_memory_buffer_put_uint64 (mbuf, v);
2255         }
2256       break;
2257
2258     case 'd': /* G_VARIANT_TYPE_DOUBLE */
2259       padding_added = ensure_output_padding (mbuf, 8);
2260       if (value != NULL)
2261         {
2262           union {
2263             guint64 v_uint64;
2264             gdouble v_double;
2265           } u;
2266           G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
2267           u.v_double = g_variant_get_double (value);
2268           g_memory_buffer_put_uint64 (mbuf, u.v_uint64);
2269         }
2270       break;
2271
2272     case 's': /* G_VARIANT_TYPE_STRING */
2273       padding_added = ensure_output_padding (mbuf, 4);
2274       if (value != NULL)
2275         {
2276           gsize len;
2277           const gchar *v;
2278           const gchar *end;
2279           v = g_variant_get_string (value, &len);
2280           g_assert (g_utf8_validate (v, -1, &end) && (end == v + len));
2281           g_memory_buffer_put_uint32 (mbuf, len);
2282           g_memory_buffer_put_string (mbuf, v);
2283           g_memory_buffer_put_byte (mbuf, '\0');
2284         }
2285       break;
2286
2287     case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
2288       padding_added = ensure_output_padding (mbuf, 4);
2289       if (value != NULL)
2290         {
2291           gsize len;
2292           const gchar *v = g_variant_get_string (value, &len);
2293           g_assert (g_variant_is_object_path (v));
2294           g_memory_buffer_put_uint32 (mbuf, len);
2295           g_memory_buffer_put_string (mbuf, v);
2296           g_memory_buffer_put_byte (mbuf, '\0');
2297         }
2298       break;
2299
2300     case 'g': /* G_VARIANT_TYPE_SIGNATURE */
2301       if (value != NULL)
2302         {
2303           gsize len;
2304           const gchar *v = g_variant_get_string (value, &len);
2305           g_assert (g_variant_is_signature (v));
2306           g_memory_buffer_put_byte (mbuf, len);
2307           g_memory_buffer_put_string (mbuf, v);
2308           g_memory_buffer_put_byte (mbuf, '\0');
2309         }
2310       break;
2311
2312     case 'h': /* G_VARIANT_TYPE_HANDLE */
2313       padding_added = ensure_output_padding (mbuf, 4);
2314       if (value != NULL)
2315         {
2316           gint32 v = g_variant_get_handle (value);
2317           g_memory_buffer_put_int32 (mbuf, v);
2318         }
2319       break;
2320
2321     case 'a': /* G_VARIANT_TYPE_ARRAY */
2322       {
2323         GVariant *item;
2324         GVariantIter iter;
2325         goffset array_len_offset;
2326         goffset array_payload_begin_offset;
2327         goffset cur_offset;
2328         gsize array_len;
2329
2330         padding_added = ensure_output_padding (mbuf, 4);
2331         if (value != NULL)
2332           {
2333             /* array length - will be filled in later */
2334             array_len_offset = mbuf->valid_len;
2335             g_memory_buffer_put_uint32 (mbuf, 0xF00DFACE);
2336
2337             /* From the D-Bus spec:
2338              *
2339              *   "A UINT32 giving the length of the array data in bytes,
2340              *    followed by alignment padding to the alignment boundary of
2341              *    the array element type, followed by each array element. The
2342              *    array length is from the end of the alignment padding to
2343              *    the end of the last element, i.e. it does not include the
2344              *    padding after the length, or any padding after the last
2345              *    element."
2346              *
2347              * Thus, we need to count how much padding the first element
2348              * contributes and subtract that from the array length.
2349              */
2350             array_payload_begin_offset = mbuf->valid_len;
2351
2352             if (g_variant_n_children (value) == 0)
2353               {
2354                 gsize padding_added_for_item;
2355                 if (!append_value_to_blob (NULL,
2356                                            g_variant_type_element (type),
2357                                            mbuf,
2358                                            &padding_added_for_item,
2359                                            error))
2360                   goto fail;
2361                 array_payload_begin_offset += padding_added_for_item;
2362               }
2363             else
2364               {
2365                 guint n;
2366                 n = 0;
2367                 g_variant_iter_init (&iter, value);
2368                 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2369                   {
2370                     gsize padding_added_for_item;
2371                     if (!append_value_to_blob (item,
2372                                                g_variant_get_type (item),
2373                                                mbuf,
2374                                                &padding_added_for_item,
2375                                                error))
2376                       {
2377                         g_variant_unref (item);
2378                         goto fail;
2379                       }
2380                     g_variant_unref (item);
2381                     if (n == 0)
2382                       {
2383                         array_payload_begin_offset += padding_added_for_item;
2384                       }
2385                     n++;
2386                   }
2387               }
2388
2389             cur_offset = mbuf->valid_len;
2390             array_len = cur_offset - array_payload_begin_offset;
2391             mbuf->pos = array_len_offset;
2392
2393             g_memory_buffer_put_uint32 (mbuf, array_len);
2394             mbuf->pos = cur_offset;
2395           }
2396       }
2397       break;
2398
2399     default:
2400       if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
2401         {
2402           padding_added = ensure_output_padding (mbuf, 8);
2403           if (value != NULL)
2404             {
2405               GVariant *item;
2406               GVariantIter iter;
2407               g_variant_iter_init (&iter, value);
2408               while ((item = g_variant_iter_next_value (&iter)) != NULL)
2409                 {
2410                   if (!append_value_to_blob (item,
2411                                              g_variant_get_type (item),
2412                                              mbuf,
2413                                              NULL,
2414                                              error))
2415                     {
2416                       g_variant_unref (item);
2417                       goto fail;
2418                     }
2419                   g_variant_unref (item);
2420                 }
2421             }
2422         }
2423       else if (g_variant_type_is_variant (type))
2424         {
2425           if (value != NULL)
2426             {
2427               GVariant *child;
2428               const gchar *signature;
2429               child = g_variant_get_child_value (value, 0);
2430               signature = g_variant_get_type_string (child);
2431               g_memory_buffer_put_byte (mbuf, strlen (signature));
2432               g_memory_buffer_put_string (mbuf, signature);
2433               g_memory_buffer_put_byte (mbuf, '\0');
2434               if (!append_value_to_blob (child,
2435                                          g_variant_get_type (child),
2436                                          mbuf,
2437                                          NULL,
2438                                          error))
2439                 {
2440                   g_variant_unref (child);
2441                   goto fail;
2442                 }
2443               g_variant_unref (child);
2444             }
2445         }
2446       else
2447         {
2448           g_set_error (error,
2449                        G_IO_ERROR,
2450                        G_IO_ERROR_INVALID_ARGUMENT,
2451                        _("Error serializing GVariant with type string '%s' to the D-Bus wire format"),
2452                        g_variant_get_type_string (value));
2453           goto fail;
2454         }
2455       break;
2456     }
2457
2458   if (out_padding_added != NULL)
2459     *out_padding_added = padding_added;
2460
2461   return TRUE;
2462
2463  fail:
2464   return FALSE;
2465 }
2466
2467 static gboolean
2468 append_body_to_blob (GVariant       *value,
2469                      GMemoryBuffer  *mbuf,
2470                      GError        **error)
2471 {
2472   GVariant *item;
2473   GVariantIter iter;
2474
2475   if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
2476     {
2477       g_set_error (error,
2478                    G_IO_ERROR,
2479                    G_IO_ERROR_INVALID_ARGUMENT,
2480                    "Expected a tuple for the body of the GDBusMessage.");
2481       goto fail;
2482     }
2483
2484   g_variant_iter_init (&iter, value);
2485   while ((item = g_variant_iter_next_value (&iter)) != NULL)
2486     {
2487       if (!append_value_to_blob (item,
2488                                  g_variant_get_type (item),
2489                                  mbuf,
2490                                  NULL,
2491                                  error))
2492         {
2493           g_variant_unref (item);
2494           goto fail;
2495         }
2496       g_variant_unref (item);
2497     }
2498   return TRUE;
2499
2500  fail:
2501   return FALSE;
2502 }
2503
2504 /* ---------------------------------------------------------------------------------------------------- */
2505
2506 /**
2507  * g_dbus_message_to_blob:
2508  * @message: A #GDBusMessage.
2509  * @out_size: Return location for size of generated blob.
2510  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2511  * @error: Return location for error.
2512  *
2513  * Serializes @message to a blob. The byte order returned by
2514  * g_dbus_message_get_byte_order() will be used.
2515  *
2516  * Returns: (array length=out_size) (transfer full): A pointer to a
2517  * valid binary D-Bus message of @out_size bytes generated by @message
2518  * or %NULL if @error is set. Free with g_free().
2519  *
2520  * Since: 2.26
2521  */
2522 guchar *
2523 g_dbus_message_to_blob (GDBusMessage          *message,
2524                         gsize                 *out_size,
2525                         GDBusCapabilityFlags   capabilities,
2526                         GError               **error)
2527 {
2528   GMemoryBuffer mbuf;
2529   guchar *ret;
2530   gsize size;
2531   goffset body_len_offset;
2532   goffset body_start_offset;
2533   gsize body_size;
2534   GVariant *header_fields;
2535   GVariantBuilder builder;
2536   GHashTableIter hash_iter;
2537   gpointer key;
2538   GVariant *header_value;
2539   GVariant *signature;
2540   const gchar *signature_str;
2541   gint num_fds_in_message;
2542   gint num_fds_according_to_header;
2543
2544   /* TODO: check against @capabilities */
2545
2546   ret = NULL;
2547
2548   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2549   g_return_val_if_fail (out_size != NULL, NULL);
2550   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2551
2552   memset (&mbuf, 0, sizeof (mbuf));
2553   mbuf.len = MIN_ARRAY_SIZE;
2554   mbuf.data = g_malloc (mbuf.len);
2555
2556   mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN;
2557   switch (message->byte_order)
2558     {
2559     case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
2560       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2561       break;
2562     case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
2563       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2564       break;
2565     }
2566
2567   /* Core header */
2568   g_memory_buffer_put_byte (&mbuf, (guchar) message->byte_order);
2569   g_memory_buffer_put_byte (&mbuf, message->type);
2570   g_memory_buffer_put_byte (&mbuf, message->flags);
2571   g_memory_buffer_put_byte (&mbuf, 1); /* major protocol version */
2572   body_len_offset = mbuf.valid_len;
2573   /* body length - will be filled in later */
2574   g_memory_buffer_put_uint32 (&mbuf, 0xF00DFACE);
2575   g_memory_buffer_put_uint32 (&mbuf, message->serial);
2576
2577   num_fds_in_message = 0;
2578 #ifdef G_OS_UNIX
2579   if (message->fd_list != NULL)
2580     num_fds_in_message = g_unix_fd_list_get_length (message->fd_list);
2581 #endif
2582   num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
2583   if (num_fds_in_message != num_fds_according_to_header)
2584     {
2585       g_set_error (error,
2586                    G_IO_ERROR,
2587                    G_IO_ERROR_INVALID_ARGUMENT,
2588                    _("Message has %d file descriptors but the header field indicates %d file descriptors"),
2589                    num_fds_in_message,
2590                    num_fds_according_to_header);
2591       goto out;
2592     }
2593
2594   if (!validate_headers (message, error))
2595     {
2596       g_prefix_error (error, _("Cannot serialize message: "));
2597       goto out;
2598     }
2599
2600   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
2601   g_hash_table_iter_init (&hash_iter, message->headers);
2602   while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
2603     {
2604       g_variant_builder_add (&builder,
2605                              "{yv}",
2606                              (guchar) GPOINTER_TO_UINT (key),
2607                              header_value);
2608     }
2609   header_fields = g_variant_builder_end (&builder);
2610
2611   if (!append_value_to_blob (header_fields,
2612                              g_variant_get_type (header_fields),
2613                              &mbuf,
2614                              NULL,
2615                              error))
2616     {
2617       g_variant_unref (header_fields);
2618       goto out;
2619     }
2620   g_variant_unref (header_fields);
2621
2622   /* header size must be a multiple of 8 */
2623   ensure_output_padding (&mbuf, 8);
2624
2625   body_start_offset = mbuf.valid_len;
2626
2627   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2628   signature_str = NULL;
2629   if (signature != NULL)
2630       signature_str = g_variant_get_string (signature, NULL);
2631   if (message->body != NULL)
2632     {
2633       gchar *tupled_signature_str;
2634       tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2635       if (signature == NULL)
2636         {
2637           g_set_error (error,
2638                        G_IO_ERROR,
2639                        G_IO_ERROR_INVALID_ARGUMENT,
2640                        _("Message body has signature '%s' but there is no signature header"),
2641                        signature_str);
2642           g_free (tupled_signature_str);
2643           goto out;
2644         }
2645       else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
2646         {
2647           g_set_error (error,
2648                        G_IO_ERROR,
2649                        G_IO_ERROR_INVALID_ARGUMENT,
2650                        _("Message body has type signature '%s' but signature in the header field is '%s'"),
2651                        tupled_signature_str, g_variant_get_type_string (message->body));
2652           g_free (tupled_signature_str);
2653           goto out;
2654         }
2655       g_free (tupled_signature_str);
2656       if (!append_body_to_blob (message->body, &mbuf, error))
2657         goto out;
2658     }
2659   else
2660     {
2661       if (signature != NULL && strlen (signature_str) > 0)
2662         {
2663           g_set_error (error,
2664                        G_IO_ERROR,
2665                        G_IO_ERROR_INVALID_ARGUMENT,
2666                        _("Message body is empty but signature in the header field is '(%s)'"),
2667                        signature_str);
2668           goto out;
2669         }
2670     }
2671
2672   /* OK, we're done writing the message - set the body length */
2673   size = mbuf.valid_len;
2674   body_size = size - body_start_offset;
2675
2676   mbuf.pos = body_len_offset;
2677
2678   g_memory_buffer_put_uint32 (&mbuf, body_size);
2679
2680   *out_size = size;
2681   ret = (guchar *)mbuf.data;
2682
2683  out:
2684   return ret;
2685 }
2686
2687 /* ---------------------------------------------------------------------------------------------------- */
2688
2689 static guint32
2690 get_uint32_header (GDBusMessage            *message,
2691                    GDBusMessageHeaderField  header_field)
2692 {
2693   GVariant *value;
2694   guint32 ret;
2695
2696   ret = 0;
2697   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2698   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
2699     ret = g_variant_get_uint32 (value);
2700
2701   return ret;
2702 }
2703
2704 static const gchar *
2705 get_string_header (GDBusMessage            *message,
2706                    GDBusMessageHeaderField  header_field)
2707 {
2708   GVariant *value;
2709   const gchar *ret;
2710
2711   ret = NULL;
2712   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2713   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
2714     ret = g_variant_get_string (value, NULL);
2715
2716   return ret;
2717 }
2718
2719 static const gchar *
2720 get_object_path_header (GDBusMessage            *message,
2721                         GDBusMessageHeaderField  header_field)
2722 {
2723   GVariant *value;
2724   const gchar *ret;
2725
2726   ret = NULL;
2727   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2728   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
2729     ret = g_variant_get_string (value, NULL);
2730
2731   return ret;
2732 }
2733
2734 static const gchar *
2735 get_signature_header (GDBusMessage            *message,
2736                       GDBusMessageHeaderField  header_field)
2737 {
2738   GVariant *value;
2739   const gchar *ret;
2740
2741   ret = NULL;
2742   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2743   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
2744     ret = g_variant_get_string (value, NULL);
2745
2746   return ret;
2747 }
2748
2749 /* ---------------------------------------------------------------------------------------------------- */
2750
2751 static void
2752 set_uint32_header (GDBusMessage             *message,
2753                    GDBusMessageHeaderField   header_field,
2754                    guint32                   value)
2755 {
2756   g_dbus_message_set_header (message,
2757                              header_field,
2758                              g_variant_new_uint32 (value));
2759 }
2760
2761 static void
2762 set_string_header (GDBusMessage             *message,
2763                    GDBusMessageHeaderField   header_field,
2764                    const gchar              *value)
2765 {
2766   g_dbus_message_set_header (message,
2767                              header_field,
2768                              value == NULL ? NULL : g_variant_new_string (value));
2769 }
2770
2771 static void
2772 set_object_path_header (GDBusMessage             *message,
2773                         GDBusMessageHeaderField   header_field,
2774                         const gchar              *value)
2775 {
2776   g_dbus_message_set_header (message,
2777                              header_field,
2778                              value == NULL ? NULL : g_variant_new_object_path (value));
2779 }
2780
2781 static void
2782 set_signature_header (GDBusMessage             *message,
2783                       GDBusMessageHeaderField   header_field,
2784                       const gchar              *value)
2785 {
2786   g_dbus_message_set_header (message,
2787                              header_field,
2788                              value == NULL ? NULL : g_variant_new_signature (value));
2789 }
2790
2791 /* ---------------------------------------------------------------------------------------------------- */
2792
2793 /**
2794  * g_dbus_message_get_reply_serial:
2795  * @message: A #GDBusMessage.
2796  *
2797  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2798  *
2799  * Returns: The value.
2800  *
2801  * Since: 2.26
2802  */
2803 guint32
2804 g_dbus_message_get_reply_serial (GDBusMessage  *message)
2805 {
2806   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2807   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
2808 }
2809
2810 /**
2811  * g_dbus_message_set_reply_serial:
2812  * @message: A #GDBusMessage.
2813  * @value: The value to set.
2814  *
2815  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2816  *
2817  * Since: 2.26
2818  */
2819 void
2820 g_dbus_message_set_reply_serial (GDBusMessage  *message,
2821                                  guint32        value)
2822 {
2823   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2824   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
2825 }
2826
2827 /* ---------------------------------------------------------------------------------------------------- */
2828
2829 /**
2830  * g_dbus_message_get_interface:
2831  * @message: A #GDBusMessage.
2832  *
2833  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2834  *
2835  * Returns: The value.
2836  *
2837  * Since: 2.26
2838  */
2839 const gchar *
2840 g_dbus_message_get_interface (GDBusMessage  *message)
2841 {
2842   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2843   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
2844 }
2845
2846 /**
2847  * g_dbus_message_set_interface:
2848  * @message: A #GDBusMessage.
2849  * @value: The value to set.
2850  *
2851  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2852  *
2853  * Since: 2.26
2854  */
2855 void
2856 g_dbus_message_set_interface (GDBusMessage  *message,
2857                               const gchar   *value)
2858 {
2859   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2860   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2861   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
2862 }
2863
2864 /* ---------------------------------------------------------------------------------------------------- */
2865
2866 /**
2867  * g_dbus_message_get_member:
2868  * @message: A #GDBusMessage.
2869  *
2870  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2871  *
2872  * Returns: The value.
2873  *
2874  * Since: 2.26
2875  */
2876 const gchar *
2877 g_dbus_message_get_member (GDBusMessage  *message)
2878 {
2879   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2880   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
2881 }
2882
2883 /**
2884  * g_dbus_message_set_member:
2885  * @message: A #GDBusMessage.
2886  * @value: The value to set.
2887  *
2888  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2889  *
2890  * Since: 2.26
2891  */
2892 void
2893 g_dbus_message_set_member (GDBusMessage  *message,
2894                            const gchar   *value)
2895 {
2896   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2897   g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
2898   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
2899 }
2900
2901 /* ---------------------------------------------------------------------------------------------------- */
2902
2903 /**
2904  * g_dbus_message_get_path:
2905  * @message: A #GDBusMessage.
2906  *
2907  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2908  *
2909  * Returns: The value.
2910  *
2911  * Since: 2.26
2912  */
2913 const gchar *
2914 g_dbus_message_get_path (GDBusMessage  *message)
2915 {
2916   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2917   return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
2918 }
2919
2920 /**
2921  * g_dbus_message_set_path:
2922  * @message: A #GDBusMessage.
2923  * @value: The value to set.
2924  *
2925  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2926  *
2927  * Since: 2.26
2928  */
2929 void
2930 g_dbus_message_set_path (GDBusMessage  *message,
2931                          const gchar   *value)
2932 {
2933   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2934   g_return_if_fail (value == NULL || g_variant_is_object_path (value));
2935   set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
2936 }
2937
2938 /* ---------------------------------------------------------------------------------------------------- */
2939
2940 /**
2941  * g_dbus_message_get_sender:
2942  * @message: A #GDBusMessage.
2943  *
2944  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2945  *
2946  * Returns: The value.
2947  *
2948  * Since: 2.26
2949  */
2950 const gchar *
2951 g_dbus_message_get_sender (GDBusMessage *message)
2952 {
2953   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2954   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
2955 }
2956
2957 /**
2958  * g_dbus_message_set_sender:
2959  * @message: A #GDBusMessage.
2960  * @value: The value to set.
2961  *
2962  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2963  *
2964  * Since: 2.26
2965  */
2966 void
2967 g_dbus_message_set_sender (GDBusMessage  *message,
2968                            const gchar   *value)
2969 {
2970   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2971   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2972   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
2973 }
2974
2975 /* ---------------------------------------------------------------------------------------------------- */
2976
2977 /**
2978  * g_dbus_message_get_destination:
2979  * @message: A #GDBusMessage.
2980  *
2981  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2982  *
2983  * Returns: The value.
2984  *
2985  * Since: 2.26
2986  */
2987 const gchar *
2988 g_dbus_message_get_destination (GDBusMessage  *message)
2989 {
2990   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2991   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
2992 }
2993
2994 /**
2995  * g_dbus_message_set_destination:
2996  * @message: A #GDBusMessage.
2997  * @value: The value to set.
2998  *
2999  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3000  *
3001  * Since: 2.26
3002  */
3003 void
3004 g_dbus_message_set_destination (GDBusMessage  *message,
3005                                 const gchar   *value)
3006 {
3007   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3008   g_return_if_fail (value == NULL || g_dbus_is_name (value));
3009   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
3010 }
3011
3012 /* ---------------------------------------------------------------------------------------------------- */
3013
3014 /**
3015  * g_dbus_message_get_error_name:
3016  * @message: A #GDBusMessage.
3017  *
3018  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3019  *
3020  * Returns: The value.
3021  *
3022  * Since: 2.26
3023  */
3024 const gchar *
3025 g_dbus_message_get_error_name (GDBusMessage  *message)
3026 {
3027   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3028   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
3029 }
3030
3031 /**
3032  * g_dbus_message_set_error_name:
3033  * @message: A #GDBusMessage.
3034  * @value: The value to set.
3035  *
3036  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3037  *
3038  * Since: 2.26
3039  */
3040 void
3041 g_dbus_message_set_error_name (GDBusMessage  *message,
3042                                const gchar   *value)
3043 {
3044   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3045   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
3046   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
3047 }
3048
3049 /* ---------------------------------------------------------------------------------------------------- */
3050
3051 /**
3052  * g_dbus_message_get_signature:
3053  * @message: A #GDBusMessage.
3054  *
3055  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3056  *
3057  * Returns: The value.
3058  *
3059  * Since: 2.26
3060  */
3061 const gchar *
3062 g_dbus_message_get_signature (GDBusMessage  *message)
3063 {
3064   const gchar *ret;
3065   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3066   ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
3067   if (ret == NULL)
3068     ret = "";
3069   return ret;
3070 }
3071
3072 /**
3073  * g_dbus_message_set_signature:
3074  * @message: A #GDBusMessage.
3075  * @value: The value to set.
3076  *
3077  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3078  *
3079  * Since: 2.26
3080  */
3081 void
3082 g_dbus_message_set_signature (GDBusMessage  *message,
3083                               const gchar   *value)
3084 {
3085   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3086   g_return_if_fail (value == NULL || g_variant_is_signature (value));
3087   set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
3088 }
3089
3090 /* ---------------------------------------------------------------------------------------------------- */
3091
3092 /**
3093  * g_dbus_message_get_arg0:
3094  * @message: A #GDBusMessage.
3095  *
3096  * Convenience to get the first item in the body of @message.
3097  *
3098  * Returns: The string item or %NULL if the first item in the body of
3099  * @message is not a string.
3100  *
3101  * Since: 2.26
3102  */
3103 const gchar *
3104 g_dbus_message_get_arg0 (GDBusMessage  *message)
3105 {
3106   const gchar *ret;
3107
3108   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3109
3110   ret = NULL;
3111
3112   if (message->body != NULL && g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE))
3113     {
3114       GVariant *item;
3115       item = g_variant_get_child_value (message->body, 0);
3116       if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING))
3117         ret = g_variant_get_string (item, NULL);
3118       g_variant_unref (item);
3119     }
3120
3121   return ret;
3122 }
3123
3124 /* ---------------------------------------------------------------------------------------------------- */
3125
3126 /**
3127  * g_dbus_message_get_num_unix_fds:
3128  * @message: A #GDBusMessage.
3129  *
3130  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3131  *
3132  * Returns: The value.
3133  *
3134  * Since: 2.26
3135  */
3136 guint32
3137 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
3138 {
3139   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3140   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
3141 }
3142
3143 /**
3144  * g_dbus_message_set_num_unix_fds:
3145  * @message: A #GDBusMessage.
3146  * @value: The value to set.
3147  *
3148  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3149  *
3150  * Since: 2.26
3151  */
3152 void
3153 g_dbus_message_set_num_unix_fds (GDBusMessage  *message,
3154                                  guint32        value)
3155 {
3156   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3157   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
3158 }
3159
3160 /* ---------------------------------------------------------------------------------------------------- */
3161
3162 /**
3163  * g_dbus_message_to_gerror:
3164  * @message: A #GDBusMessage.
3165  * @error: The #GError to set.
3166  *
3167  * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
3168  * nothing and returns %FALSE.
3169  *
3170  * Otherwise this method encodes the error in @message as a #GError
3171  * using g_dbus_error_set_dbus_error() using the information in the
3172  * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
3173  * well as the first string item in @message's body.
3174  *
3175  * Returns: %TRUE if @error was set, %FALSE otherwise.
3176  *
3177  * Since: 2.26
3178  */
3179 gboolean
3180 g_dbus_message_to_gerror (GDBusMessage   *message,
3181                           GError        **error)
3182 {
3183   gboolean ret;
3184   const gchar *error_name;
3185
3186   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3187
3188   ret = FALSE;
3189   if (message->type != G_DBUS_MESSAGE_TYPE_ERROR)
3190     goto out;
3191
3192   error_name = g_dbus_message_get_error_name (message);
3193   if (error_name != NULL)
3194     {
3195       GVariant *body;
3196
3197       body = g_dbus_message_get_body (message);
3198
3199       if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
3200         {
3201           const gchar *error_message;
3202           g_variant_get (body, "(&s)", &error_message);
3203           g_dbus_error_set_dbus_error (error,
3204                                        error_name,
3205                                        error_message,
3206                                        NULL);
3207         }
3208       else
3209         {
3210           /* these two situations are valid, yet pretty rare */
3211           if (body != NULL)
3212             {
3213               g_dbus_error_set_dbus_error (error,
3214                                            error_name,
3215                                            "",
3216                                            _("Error return with body of type '%s'"),
3217                                            g_variant_get_type_string (body));
3218             }
3219           else
3220             {
3221               g_dbus_error_set_dbus_error (error,
3222                                            error_name,
3223                                            "",
3224                                            _("Error return with empty body"));
3225             }
3226         }
3227     }
3228   else
3229     {
3230       /* TOOD: this shouldn't happen - should check this at message serialization
3231        * time and disconnect the peer.
3232        */
3233       g_set_error (error,
3234                    G_IO_ERROR,
3235                    G_IO_ERROR_FAILED,
3236                    "Error return without error-name header!");
3237     }
3238
3239   ret = TRUE;
3240
3241  out:
3242   return ret;
3243 }
3244
3245 /* ---------------------------------------------------------------------------------------------------- */
3246
3247 static gchar *
3248 flags_to_string (GType flags_type, guint value)
3249 {
3250   GString *s;
3251   GFlagsClass *klass;
3252   guint n;
3253
3254   klass = g_type_class_ref (flags_type);
3255   s = g_string_new (NULL);
3256   for (n = 0; n < 32; n++)
3257     {
3258       if ((value & (1<<n)) != 0)
3259         {
3260           GFlagsValue *flags_value;
3261           flags_value = g_flags_get_first_value (klass, (1<<n));
3262           if (s->len > 0)
3263             g_string_append_c (s, ',');
3264           if (flags_value != NULL)
3265             g_string_append (s, flags_value->value_nick);
3266           else
3267             g_string_append_printf (s, "unknown (bit %d)", n);
3268         }
3269     }
3270   if (s->len == 0)
3271     g_string_append (s, "none");
3272   g_type_class_unref (klass);
3273   return g_string_free (s, FALSE);
3274 }
3275
3276 static gint
3277 _sort_keys_func (gconstpointer a,
3278                  gconstpointer b)
3279 {
3280   gint ia;
3281   gint ib;
3282
3283   ia = GPOINTER_TO_INT (a);
3284   ib = GPOINTER_TO_INT (b);
3285
3286   return ia - ib;
3287 }
3288
3289 /**
3290  * g_dbus_message_print:
3291  * @message: A #GDBusMessage.
3292  * @indent: Indentation level.
3293  *
3294  * Produces a human-readable multi-line description of @message.
3295  *
3296  * The contents of the description has no ABI guarantees, the contents
3297  * and formatting is subject to change at any time. Typical output
3298  * looks something like this:
3299  * |[
3300  * Type:    method-call
3301  * Flags:   none
3302  * Version: 0
3303  * Serial:  4
3304  * Headers:
3305  *   path -> objectpath '/org/gtk/GDBus/TestObject'
3306  *   interface -> 'org.gtk.GDBus.TestInterface'
3307  *   member -> 'GimmeStdout'
3308  *   destination -> ':1.146'
3309  * Body: ()
3310  * UNIX File Descriptors:
3311  *   (none)
3312  * ]|
3313  * or
3314  * |[
3315  * Type:    method-return
3316  * Flags:   no-reply-expected
3317  * Version: 0
3318  * Serial:  477
3319  * Headers:
3320  *   reply-serial -> uint32 4
3321  *   destination -> ':1.159'
3322  *   sender -> ':1.146'
3323  *   num-unix-fds -> uint32 1
3324  * Body: ()
3325  * UNIX File Descriptors:
3326  *   fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
3327  * ]|
3328  *
3329  * Returns: A string that should be freed with g_free().
3330  *
3331  * Since: 2.26
3332  */
3333 gchar *
3334 g_dbus_message_print (GDBusMessage *message,
3335                       guint         indent)
3336 {
3337   GString *str;
3338   gchar *s;
3339   GList *keys;
3340   GList *l;
3341
3342   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3343
3344   str = g_string_new (NULL);
3345
3346   s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->type);
3347   g_string_append_printf (str, "%*sType:    %s\n", indent, "", s);
3348   g_free (s);
3349   s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->flags);
3350   g_string_append_printf (str, "%*sFlags:   %s\n", indent, "", s);
3351   g_free (s);
3352   g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->major_protocol_version);
3353   g_string_append_printf (str, "%*sSerial:  %d\n", indent, "", message->serial);
3354
3355   g_string_append_printf (str, "%*sHeaders:\n", indent, "");
3356   keys = g_hash_table_get_keys (message->headers);
3357   keys = g_list_sort (keys, _sort_keys_func);
3358   if (keys != NULL)
3359     {
3360       for (l = keys; l != NULL; l = l->next)
3361         {
3362           gint key = GPOINTER_TO_INT (l->data);
3363           GVariant *value;
3364           gchar *value_str;
3365
3366           value = g_hash_table_lookup (message->headers, l->data);
3367           g_assert (value != NULL);
3368
3369           s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
3370           value_str = g_variant_print (value, TRUE);
3371           g_string_append_printf (str, "%*s  %s -> %s\n", indent, "", s, value_str);
3372           g_free (s);
3373           g_free (value_str);
3374         }
3375     }
3376   else
3377     {
3378       g_string_append_printf (str, "%*s  (none)\n", indent, "");
3379     }
3380   g_string_append_printf (str, "%*sBody: ", indent, "");
3381   if (message->body != NULL)
3382     {
3383       g_variant_print_string (message->body,
3384                               str,
3385                               TRUE);
3386     }
3387   else
3388     {
3389       g_string_append (str, "()");
3390     }
3391   g_string_append (str, "\n");
3392 #ifdef G_OS_UNIX
3393   g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
3394   if (message->fd_list != NULL)
3395     {
3396       gint num_fds;
3397       const gint *fds;
3398       gint n;
3399
3400       fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3401       if (num_fds > 0)
3402         {
3403           for (n = 0; n < num_fds; n++)
3404             {
3405               GString *fs;
3406               struct stat statbuf;
3407               fs = g_string_new (NULL);
3408               if (fstat (fds[n], &statbuf) == 0)
3409                 {
3410                   g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
3411                                           major (statbuf.st_dev), minor (statbuf.st_dev));
3412                   g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
3413                                           statbuf.st_mode);
3414                   g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3415                                           (guint64) statbuf.st_ino);
3416                   g_string_append_printf (fs, "%s" "uid=%u", fs->len > 0 ? "," : "",
3417                                           (guint) statbuf.st_uid);
3418                   g_string_append_printf (fs, "%s" "gid=%u", fs->len > 0 ? "," : "",
3419                                           (guint) statbuf.st_gid);
3420                   g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
3421                                           major (statbuf.st_rdev), minor (statbuf.st_rdev));
3422                   g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3423                                           (guint64) statbuf.st_size);
3424                   g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3425                                           (guint64) statbuf.st_atime);
3426                   g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3427                                           (guint64) statbuf.st_mtime);
3428                   g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3429                                           (guint64) statbuf.st_ctime);
3430                 }
3431               else
3432                 {
3433                   g_string_append_printf (fs, "(fstat failed: %s)", strerror (errno));
3434                 }
3435               g_string_append_printf (str, "%*s  fd %d: %s\n", indent, "", fds[n], fs->str);
3436               g_string_free (fs, TRUE);
3437             }
3438         }
3439       else
3440         {
3441           g_string_append_printf (str, "%*s  (empty)\n", indent, "");
3442         }
3443     }
3444   else
3445     {
3446       g_string_append_printf (str, "%*s  (none)\n", indent, "");
3447     }
3448 #endif
3449
3450   return g_string_free (str, FALSE);
3451 }
3452
3453 /**
3454  * g_dbus_message_get_locked:
3455  * @message: A #GDBusMessage.
3456  *
3457  * Checks whether @message is locked. To monitor changes to this
3458  * value, conncet to the #GObject::notify signal to listen for changes
3459  * on the #GDBusMessage:locked property.
3460  *
3461  * Returns: %TRUE if @message is locked, %FALSE otherwise.
3462  *
3463  * Since: 2.26
3464  */
3465 gboolean
3466 g_dbus_message_get_locked (GDBusMessage *message)
3467 {
3468   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3469   return message->locked;
3470 }
3471
3472 /**
3473  * g_dbus_message_lock:
3474  * @message: A #GDBusMessage.
3475  *
3476  * If @message is locked, does nothing. Otherwise locks the message.
3477  *
3478  * Since: 2.26
3479  */
3480 void
3481 g_dbus_message_lock (GDBusMessage *message)
3482 {
3483   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3484
3485   if (message->locked)
3486     goto out;
3487
3488   message->locked = TRUE;
3489   g_object_notify (G_OBJECT (message), "locked");
3490
3491  out:
3492   ;
3493 }
3494
3495 /**
3496  * g_dbus_message_copy:
3497  * @message: A #GDBusMessage.
3498  * @error: Return location for error or %NULL.
3499  *
3500  * Copies @message. The copy is a deep copy and the returned
3501  * #GDBusMessage is completely identical except that it is guaranteed
3502  * to not be locked.
3503  *
3504  * This operation can fail if e.g. @message contains file descriptors
3505  * and the per-process or system-wide open files limit is reached.
3506  *
3507  * Returns: (transfer full): A new #GDBusMessage or %NULL if @error is set.
3508  *     Free with g_object_unref().
3509  *
3510  * Since: 2.26
3511  */
3512 GDBusMessage *
3513 g_dbus_message_copy (GDBusMessage  *message,
3514                      GError       **error)
3515 {
3516   GDBusMessage *ret;
3517   GHashTableIter iter;
3518   gpointer header_key;
3519   GVariant *header_value;
3520
3521   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3522   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
3523
3524   ret = g_dbus_message_new ();
3525   ret->type                   = message->type;
3526   ret->flags                  = message->flags;
3527   ret->byte_order             = message->byte_order;
3528   ret->major_protocol_version = message->major_protocol_version;
3529   ret->serial                 = message->serial;
3530
3531 #ifdef G_OS_UNIX
3532   if (message->fd_list != NULL)
3533     {
3534       gint n;
3535       gint num_fds;
3536       const gint *fds;
3537
3538       ret->fd_list = g_unix_fd_list_new ();
3539       fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3540       for (n = 0; n < num_fds; n++)
3541         {
3542           if (g_unix_fd_list_append (ret->fd_list,
3543                                      fds[n],
3544                                      error) == -1)
3545             {
3546               g_object_unref (ret);
3547               ret = NULL;
3548               goto out;
3549             }
3550         }
3551     }
3552 #endif
3553
3554   /* see https://bugzilla.gnome.org/show_bug.cgi?id=624546#c8 for why it's fine
3555    * to just ref (as opposed to deep-copying) the GVariant instances
3556    */
3557   ret->body = message->body != NULL ? g_variant_ref (message->body) : NULL;
3558   g_hash_table_iter_init (&iter, message->headers);
3559   while (g_hash_table_iter_next (&iter, &header_key, (gpointer) &header_value))
3560     g_hash_table_insert (ret->headers, header_key, g_variant_ref (header_value));
3561
3562 #ifdef G_OS_UNIX
3563  out:
3564 #endif
3565   return ret;
3566 }