doc: improve doc of g_file_equal()
[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: (transfer none): A #GVariant or %NULL if the body is
1118  * empty. Do not free, it is owned by @message.
1119  *
1120  * Since: 2.26
1121  */
1122 GVariant *
1123 g_dbus_message_get_body (GDBusMessage  *message)
1124 {
1125   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1126   return message->body;
1127 }
1128
1129 /**
1130  * g_dbus_message_set_body:
1131  * @message: A #GDBusMessage.
1132  * @body: Either %NULL or a #GVariant that is a tuple.
1133  *
1134  * Sets the body @message. As a side-effect the
1135  * %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field is set to the
1136  * type string of @body (or cleared if @body is %NULL).
1137  *
1138  * If @body is floating, @message assumes ownership of @body.
1139  *
1140  * Since: 2.26
1141  */
1142 void
1143 g_dbus_message_set_body (GDBusMessage  *message,
1144                          GVariant      *body)
1145 {
1146   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1147   g_return_if_fail ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE));
1148
1149   if (message->locked)
1150     {
1151       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1152       return;
1153     }
1154
1155   if (message->body != NULL)
1156     g_variant_unref (message->body);
1157   if (body == NULL)
1158     {
1159       message->body = NULL;
1160       g_dbus_message_set_signature (message, NULL);
1161     }
1162   else
1163     {
1164       const gchar *type_string;
1165       gsize type_string_len;
1166       gchar *signature;
1167
1168       message->body = g_variant_ref_sink (body);
1169
1170       type_string = g_variant_get_type_string (body);
1171       type_string_len = strlen (type_string);
1172       g_assert (type_string_len >= 2);
1173       signature = g_strndup (type_string + 1, type_string_len - 2);
1174       g_dbus_message_set_signature (message, signature);
1175       g_free (signature);
1176     }
1177 }
1178
1179 /* ---------------------------------------------------------------------------------------------------- */
1180
1181 #ifdef G_OS_UNIX
1182 /**
1183  * g_dbus_message_get_unix_fd_list:
1184  * @message: A #GDBusMessage.
1185  *
1186  * Gets the UNIX file descriptors associated with @message, if any.
1187  *
1188  * This method is only available on UNIX.
1189  *
1190  * Returns: (transfer none):A #GUnixFDList or %NULL if no file descriptors are
1191  * associated. Do not free, this object is owned by @message.
1192  *
1193  * Since: 2.26
1194  */
1195 GUnixFDList *
1196 g_dbus_message_get_unix_fd_list (GDBusMessage  *message)
1197 {
1198   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1199   return message->fd_list;
1200 }
1201
1202 /**
1203  * g_dbus_message_set_unix_fd_list:
1204  * @message: A #GDBusMessage.
1205  * @fd_list: (allow-none): A #GUnixFDList or %NULL.
1206  *
1207  * Sets the UNIX file descriptors associated with @message. As a
1208  * side-effect the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header
1209  * field is set to the number of fds in @fd_list (or cleared if
1210  * @fd_list is %NULL).
1211  *
1212  * This method is only available on UNIX.
1213  *
1214  * Since: 2.26
1215  */
1216 void
1217 g_dbus_message_set_unix_fd_list (GDBusMessage  *message,
1218                                  GUnixFDList   *fd_list)
1219 {
1220   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1221   g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
1222
1223   if (message->locked)
1224     {
1225       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1226       return;
1227     }
1228
1229   if (message->fd_list != NULL)
1230     g_object_unref (message->fd_list);
1231   if (fd_list != NULL)
1232     {
1233       message->fd_list = g_object_ref (fd_list);
1234       g_dbus_message_set_num_unix_fds (message, g_unix_fd_list_get_length (fd_list));
1235     }
1236   else
1237     {
1238       message->fd_list = NULL;
1239       g_dbus_message_set_num_unix_fds (message, 0);
1240     }
1241 }
1242 #endif
1243
1244 /* ---------------------------------------------------------------------------------------------------- */
1245
1246 static gboolean
1247 validate_headers (GDBusMessage  *message,
1248                   GError       **error)
1249 {
1250   gboolean ret;
1251
1252   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1253   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1254
1255   ret = FALSE;
1256
1257   switch (message->type)
1258     {
1259     case G_DBUS_MESSAGE_TYPE_INVALID:
1260       g_set_error_literal (error,
1261                            G_IO_ERROR,
1262                            G_IO_ERROR_INVALID_ARGUMENT,
1263                            _("type is INVALID"));
1264       goto out;
1265       break;
1266
1267     case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
1268       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1269           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1270         {
1271           g_set_error_literal (error,
1272                                G_IO_ERROR,
1273                                G_IO_ERROR_INVALID_ARGUMENT,
1274                                _("METHOD_CALL message: PATH or MEMBER header field is missing"));
1275           goto out;
1276         }
1277       break;
1278
1279     case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
1280       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1281         {
1282           g_set_error_literal (error,
1283                                G_IO_ERROR,
1284                                G_IO_ERROR_INVALID_ARGUMENT,
1285                                _("METHOD_RETURN message: REPLY_SERIAL header field is missing"));
1286           goto out;
1287         }
1288       break;
1289
1290     case G_DBUS_MESSAGE_TYPE_ERROR:
1291       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME) == NULL ||
1292           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1293         {
1294           g_set_error_literal (error,
1295                                G_IO_ERROR,
1296                                G_IO_ERROR_INVALID_ARGUMENT,
1297                                _("ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing"));
1298           goto out;
1299         }
1300       break;
1301
1302     case G_DBUS_MESSAGE_TYPE_SIGNAL:
1303       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1304           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE) == NULL ||
1305           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1306         {
1307           g_set_error_literal (error,
1308                                G_IO_ERROR,
1309                                G_IO_ERROR_INVALID_ARGUMENT,
1310                                _("SIGNAL message: PATH, INTERFACE or MEMBER header field is missing"));
1311           goto out;
1312         }
1313       if (g_strcmp0 (g_dbus_message_get_path (message), "/org/freedesktop/DBus/Local") == 0)
1314         {
1315           g_set_error_literal (error,
1316                                G_IO_ERROR,
1317                                G_IO_ERROR_INVALID_ARGUMENT,
1318                                _("SIGNAL message: The PATH header field is using the reserved value /org/freedesktop/DBus/Local"));
1319           goto out;
1320         }
1321       if (g_strcmp0 (g_dbus_message_get_interface (message), "org.freedesktop.DBus.Local") == 0)
1322         {
1323           g_set_error_literal (error,
1324                                G_IO_ERROR,
1325                                G_IO_ERROR_INVALID_ARGUMENT,
1326                                _("SIGNAL message: The INTERFACE header field is using the reserved value org.freedesktop.DBus.Local"));
1327           goto out;
1328         }
1329       break;
1330
1331     default:
1332       /* hitherto unknown type - nothing to check */
1333       break;
1334     }
1335
1336   ret = TRUE;
1337
1338  out:
1339   g_assert (ret || (error == NULL || *error != NULL));
1340   return ret;
1341 }
1342
1343 /* ---------------------------------------------------------------------------------------------------- */
1344
1345 static gboolean
1346 ensure_input_padding (GMemoryBuffer  *buf,
1347                       gsize           padding_size)
1348 {
1349   gsize offset;
1350   gsize wanted_offset;
1351
1352   offset = buf->pos;
1353   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1354   buf->pos = wanted_offset;
1355   return TRUE;
1356 }
1357
1358 static const gchar *
1359 read_string (GMemoryBuffer  *mbuf,
1360              gsize           len,
1361              GError        **error)
1362 {
1363   gchar *str;
1364   const gchar *end_valid;
1365
1366   if (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1367     {
1368       mbuf->pos = mbuf->valid_len;
1369       /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1370       g_set_error (error,
1371                    G_IO_ERROR,
1372                    G_IO_ERROR_INVALID_ARGUMENT,
1373                    g_dngettext (GETTEXT_PACKAGE,
1374                                 "Wanted to read %lu byte but only got %lu",
1375                                 "Wanted to read %lu bytes but only got %lu",
1376                                 (gulong)len),
1377                                 (gulong)len,
1378                    (gulong)(mbuf->valid_len - mbuf->pos));
1379       return NULL;
1380     }
1381
1382   if (mbuf->data[mbuf->pos + len] != '\0')
1383     {
1384       str = g_strndup (mbuf->data + mbuf->pos, len);
1385       g_set_error (error,
1386                    G_IO_ERROR,
1387                    G_IO_ERROR_INVALID_ARGUMENT,
1388                    _("Expected NUL byte after the string '%s' but found byte %d"),
1389                    str, mbuf->data[mbuf->pos + len]);
1390       g_free (str);
1391       mbuf->pos += len + 1;
1392       return NULL;
1393     }
1394
1395   str = mbuf->data + mbuf->pos;
1396   mbuf->pos += len + 1;
1397
1398   if (!g_utf8_validate (str, -1, &end_valid))
1399     {
1400       gint offset;
1401       gchar *valid_str;
1402       offset = (gint) (end_valid - str);
1403       valid_str = g_strndup (str, offset);
1404       g_set_error (error,
1405                    G_IO_ERROR,
1406                    G_IO_ERROR_INVALID_ARGUMENT,
1407                    _("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
1408                      "The valid UTF-8 string up until that point was '%s'"),
1409                    offset,
1410                    (gint) len,
1411                    valid_str);
1412       g_free (valid_str);
1413       return NULL;
1414     }
1415
1416   return str;
1417 }
1418
1419 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
1420
1421 /* returns a non-floating GVariant! */
1422 static GVariant *
1423 parse_value_from_blob (GMemoryBuffer       *buf,
1424                        const GVariantType  *type,
1425                        gboolean             just_align,
1426                        guint                indent,
1427                        GError             **error)
1428 {
1429   GVariant *ret;
1430   GError *local_error;
1431   gboolean is_leaf;
1432   const gchar *type_string;
1433
1434   type_string = g_variant_type_peek_string (type);
1435
1436 #ifdef DEBUG_SERIALIZER
1437     {
1438       gchar *s;
1439       s = g_variant_type_dup_string (type);
1440       g_print ("%*s%s type %s from offset 0x%04x",
1441                indent, "",
1442                just_align ? "Aligning" : "Reading",
1443                s,
1444                (gint) g_seekable_tell (G_SEEKABLE (buf)));
1445       g_free (s);
1446     }
1447 #endif /* DEBUG_SERIALIZER */
1448
1449   ret = NULL;
1450
1451   is_leaf = TRUE;
1452   local_error = NULL;
1453   switch (type_string[0])
1454     {
1455     case 'b': /* G_VARIANT_TYPE_BOOLEAN */
1456       ensure_input_padding (buf, 4);
1457       if (!just_align)
1458         {
1459           gboolean v;
1460           v = g_memory_buffer_read_uint32 (buf);
1461           ret = g_variant_new_boolean (v);
1462         }
1463       break;
1464
1465     case 'y': /* G_VARIANT_TYPE_BYTE */
1466       if (!just_align)
1467         {
1468           guchar v;
1469           v = g_memory_buffer_read_byte (buf);
1470           ret = g_variant_new_byte (v);
1471         }
1472       break;
1473
1474     case 'n': /* G_VARIANT_TYPE_INT16 */
1475       ensure_input_padding (buf, 2);
1476       if (!just_align)
1477         {
1478           gint16 v;
1479           v = g_memory_buffer_read_int16 (buf);
1480           ret = g_variant_new_int16 (v);
1481         }
1482       break;
1483
1484     case 'q': /* G_VARIANT_TYPE_UINT16 */
1485       ensure_input_padding (buf, 2);
1486       if (!just_align)
1487         {
1488           guint16 v;
1489           v = g_memory_buffer_read_uint16 (buf);
1490           ret = g_variant_new_uint16 (v);
1491         }
1492       break;
1493
1494     case 'i': /* G_VARIANT_TYPE_INT32 */
1495       ensure_input_padding (buf, 4);
1496       if (!just_align)
1497         {
1498           gint32 v;
1499           v = g_memory_buffer_read_int32 (buf);
1500           ret = g_variant_new_int32 (v);
1501         }
1502       break;
1503
1504     case 'u': /* G_VARIANT_TYPE_UINT32 */
1505       ensure_input_padding (buf, 4);
1506       if (!just_align)
1507         {
1508           guint32 v;
1509           v = g_memory_buffer_read_uint32 (buf);
1510           ret = g_variant_new_uint32 (v);
1511         }
1512       break;
1513
1514     case 'x': /* G_VARIANT_TYPE_INT64 */
1515       ensure_input_padding (buf, 8);
1516       if (!just_align)
1517         {
1518           gint64 v;
1519           v = g_memory_buffer_read_int64 (buf);
1520           ret = g_variant_new_int64 (v);
1521         }
1522       break;
1523
1524     case 't': /* G_VARIANT_TYPE_UINT64 */
1525       ensure_input_padding (buf, 8);
1526       if (!just_align)
1527         {
1528           guint64 v;
1529           v = g_memory_buffer_read_uint64 (buf);
1530           ret = g_variant_new_uint64 (v);
1531         }
1532       break;
1533
1534     case 'd': /* G_VARIANT_TYPE_DOUBLE */
1535       ensure_input_padding (buf, 8);
1536       if (!just_align)
1537         {
1538           union {
1539             guint64 v_uint64;
1540             gdouble v_double;
1541           } u;
1542           G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
1543           u.v_uint64 = g_memory_buffer_read_uint64 (buf);
1544           ret = g_variant_new_double (u.v_double);
1545         }
1546       break;
1547
1548     case 's': /* G_VARIANT_TYPE_STRING */
1549       ensure_input_padding (buf, 4);
1550       if (!just_align)
1551         {
1552           guint32 len;
1553           const gchar *v;
1554           len = g_memory_buffer_read_uint32 (buf);
1555           v = read_string (buf, (gsize) len, &local_error);
1556           if (v == NULL)
1557             goto fail;
1558           ret = g_variant_new_string (v);
1559         }
1560       break;
1561
1562     case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
1563       ensure_input_padding (buf, 4);
1564       if (!just_align)
1565         {
1566           guint32 len;
1567           const gchar *v;
1568           len = g_memory_buffer_read_uint32 (buf);
1569           v = read_string (buf, (gsize) len, &local_error);
1570           if (v == NULL)
1571             goto fail;
1572           if (!g_variant_is_object_path (v))
1573             {
1574               g_set_error (&local_error,
1575                            G_IO_ERROR,
1576                            G_IO_ERROR_INVALID_ARGUMENT,
1577                            _("Parsed value '%s' is not a valid D-Bus object path"),
1578                            v);
1579               goto fail;
1580             }
1581           ret = g_variant_new_object_path (v);
1582         }
1583       break;
1584
1585     case 'g': /* G_VARIANT_TYPE_SIGNATURE */
1586       if (!just_align)
1587         {
1588           guchar len;
1589           const gchar *v;
1590           len = g_memory_buffer_read_byte (buf);
1591           v = read_string (buf, (gsize) len, &local_error);
1592           if (v == NULL)
1593             goto fail;
1594           if (!g_variant_is_signature (v))
1595             {
1596               g_set_error (&local_error,
1597                            G_IO_ERROR,
1598                            G_IO_ERROR_INVALID_ARGUMENT,
1599                            _("Parsed value '%s' is not a valid D-Bus signature"),
1600                        v);
1601               goto fail;
1602             }
1603           ret = g_variant_new_signature (v);
1604         }
1605       break;
1606
1607     case 'h': /* G_VARIANT_TYPE_HANDLE */
1608       ensure_input_padding (buf, 4);
1609       if (!just_align)
1610         {
1611           gint32 v;
1612           v = g_memory_buffer_read_int32 (buf);
1613           ret = g_variant_new_handle (v);
1614         }
1615       break;
1616
1617     case 'a': /* G_VARIANT_TYPE_ARRAY */
1618       ensure_input_padding (buf, 4);
1619
1620       /* If we are only aligning for this array type, it is the child type of
1621        * another array, which is empty. So, we do not need to add padding for
1622        * this nonexistent array's elements: we only need to align for this
1623        * array itself (4 bytes). See
1624        * <https://bugzilla.gnome.org/show_bug.cgi?id=673612>.
1625        */
1626       if (!just_align)
1627         {
1628           guint32 array_len;
1629           goffset offset;
1630           goffset target;
1631           const GVariantType *element_type;
1632           GVariantBuilder builder;
1633
1634           array_len = g_memory_buffer_read_uint32 (buf);
1635
1636           is_leaf = FALSE;
1637 #ifdef DEBUG_SERIALIZER
1638           g_print (": array spans 0x%04x bytes\n", array_len);
1639 #endif /* DEBUG_SERIALIZER */
1640
1641           if (array_len > (2<<26))
1642             {
1643               /* G_GUINT32_FORMAT doesn't work with gettext, so use u */
1644               g_set_error (&local_error,
1645                            G_IO_ERROR,
1646                            G_IO_ERROR_INVALID_ARGUMENT,
1647                            g_dngettext (GETTEXT_PACKAGE,
1648                                         "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB).",
1649                                         "Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB).",
1650                                         array_len),
1651                            array_len);
1652               goto fail;
1653             }
1654
1655           g_variant_builder_init (&builder, type);
1656           element_type = g_variant_type_element (type);
1657
1658           if (array_len == 0)
1659             {
1660               GVariant *item;
1661               item = parse_value_from_blob (buf,
1662                                             element_type,
1663                                             TRUE,
1664                                             indent + 2,
1665                                             NULL);
1666               g_assert (item == NULL);
1667             }
1668           else
1669             {
1670               /* TODO: optimize array of primitive types */
1671               offset = buf->pos;
1672               target = offset + array_len;
1673               while (offset < target)
1674                 {
1675                   GVariant *item;
1676                   item = parse_value_from_blob (buf,
1677                                                 element_type,
1678                                                 FALSE,
1679                                                 indent + 2,
1680                                                 &local_error);
1681                   if (item == NULL)
1682                     {
1683                       g_variant_builder_clear (&builder);
1684                       goto fail;
1685                     }
1686                   g_variant_builder_add_value (&builder, item);
1687                   g_variant_unref (item);
1688                   offset = buf->pos;
1689                 }
1690             }
1691
1692           ret = g_variant_builder_end (&builder);
1693         }
1694       break;
1695
1696     default:
1697       if (g_variant_type_is_dict_entry (type))
1698         {
1699           const GVariantType *key_type;
1700           const GVariantType *value_type;
1701           GVariant *key;
1702           GVariant *value;
1703
1704           ensure_input_padding (buf, 8);
1705
1706           is_leaf = FALSE;
1707 #ifdef DEBUG_SERIALIZER
1708           g_print ("\n");
1709 #endif /* DEBUG_SERIALIZER */
1710
1711           if (!just_align)
1712             {
1713               key_type = g_variant_type_key (type);
1714               key = parse_value_from_blob (buf,
1715                                            key_type,
1716                                            FALSE,
1717                                            indent + 2,
1718                                            &local_error);
1719               if (key == NULL)
1720                 goto fail;
1721               value_type = g_variant_type_value (type);
1722               value = parse_value_from_blob (buf,
1723                                              value_type,
1724                                              FALSE,
1725                                              indent + 2,
1726                                              &local_error);
1727               if (value == NULL)
1728                 {
1729                   g_variant_unref (key);
1730                   goto fail;
1731                 }
1732               ret = g_variant_new_dict_entry (key, value);
1733               g_variant_unref (key);
1734               g_variant_unref (value);
1735             }
1736         }
1737       else if (g_variant_type_is_tuple (type))
1738         {
1739           ensure_input_padding (buf, 8);
1740
1741           is_leaf = FALSE;
1742 #ifdef DEBUG_SERIALIZER
1743           g_print ("\n");
1744 #endif /* DEBUG_SERIALIZER */
1745
1746           if (!just_align)
1747             {
1748               const GVariantType *element_type;
1749               GVariantBuilder builder;
1750
1751               g_variant_builder_init (&builder, type);
1752               element_type = g_variant_type_first (type);
1753               while (element_type != NULL)
1754                 {
1755                   GVariant *item;
1756                   item = parse_value_from_blob (buf,
1757                                                 element_type,
1758                                                 FALSE,
1759                                                 indent + 2,
1760                                                 &local_error);
1761                   if (item == NULL)
1762                     {
1763                       g_variant_builder_clear (&builder);
1764                       goto fail;
1765                     }
1766                   g_variant_builder_add_value (&builder, item);
1767                   g_variant_unref (item);
1768
1769                   element_type = g_variant_type_next (element_type);
1770                 }
1771               ret = g_variant_builder_end (&builder);
1772             }
1773         }
1774       else if (g_variant_type_is_variant (type))
1775         {
1776           is_leaf = FALSE;
1777 #ifdef DEBUG_SERIALIZER
1778           g_print ("\n");
1779 #endif /* DEBUG_SERIALIZER */
1780
1781           if (!just_align)
1782             {
1783               guchar siglen;
1784               const gchar *sig;
1785               GVariantType *variant_type;
1786               GVariant *value;
1787
1788               siglen = g_memory_buffer_read_byte (buf);
1789               sig = read_string (buf, (gsize) siglen, &local_error);
1790               if (sig == NULL)
1791                 goto fail;
1792               if (!g_variant_is_signature (sig))
1793                 {
1794                   g_set_error (&local_error,
1795                                G_IO_ERROR,
1796                                G_IO_ERROR_INVALID_ARGUMENT,
1797                                _("Parsed value '%s' for variant is not a valid D-Bus signature"),
1798                                sig);
1799                   goto fail;
1800                 }
1801               variant_type = g_variant_type_new (sig);
1802               value = parse_value_from_blob (buf,
1803                                              variant_type,
1804                                              FALSE,
1805                                              indent + 2,
1806                                              &local_error);
1807               g_variant_type_free (variant_type);
1808               if (value == NULL)
1809                 goto fail;
1810               ret = g_variant_new_variant (value);
1811               g_variant_unref (value);
1812             }
1813         }
1814       else
1815         {
1816           gchar *s;
1817           s = g_variant_type_dup_string (type);
1818           g_set_error (&local_error,
1819                        G_IO_ERROR,
1820                        G_IO_ERROR_INVALID_ARGUMENT,
1821                        _("Error deserializing GVariant with type string '%s' from the D-Bus wire format"),
1822                        s);
1823           g_free (s);
1824           goto fail;
1825         }
1826       break;
1827     }
1828
1829   g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
1830
1831 #ifdef DEBUG_SERIALIZER
1832   if (ret != NULL)
1833     {
1834       if (is_leaf)
1835         {
1836           gchar *s;
1837           if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1838             {
1839               s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
1840             }
1841           else
1842             {
1843               s = g_variant_print (ret, FALSE);
1844             }
1845           g_print (": %s\n", s);
1846           g_free (s);
1847         }
1848     }
1849 #else
1850   is_leaf = is_leaf; /* To avoid -Wunused-but-set-variable */
1851 #endif /* DEBUG_SERIALIZER */
1852
1853   /* sink the reference */
1854   if (ret != NULL)
1855     {
1856       g_assert (g_variant_is_floating (ret));
1857       g_variant_ref_sink (ret);
1858     }
1859   return ret;
1860
1861  fail:
1862 #ifdef DEBUG_SERIALIZER
1863   g_print ("\n"
1864            "%*sFAILURE: %s (%s, %d)\n",
1865            indent, "",
1866            local_error->message,
1867            g_quark_to_string (local_error->domain),
1868            local_error->code);
1869 #endif /* DEBUG_SERIALIZER */
1870   g_propagate_error (error, local_error);
1871   return NULL;
1872 }
1873
1874 /* ---------------------------------------------------------------------------------------------------- */
1875
1876 /* message_header must be at least 16 bytes */
1877
1878 /**
1879  * g_dbus_message_bytes_needed:
1880  * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1881  * @blob_len: The length of @blob (must be at least 16).
1882  * @error: Return location for error or %NULL.
1883  *
1884  * Utility function to calculate how many bytes are needed to
1885  * completely deserialize the D-Bus message stored at @blob.
1886  *
1887  * Returns: Number of bytes needed or -1 if @error is set (e.g. if
1888  * @blob contains invalid data or not enough data is available to
1889  * determine the size).
1890  *
1891  * Since: 2.26
1892  */
1893 gssize
1894 g_dbus_message_bytes_needed (guchar  *blob,
1895                              gsize    blob_len,
1896                              GError **error)
1897 {
1898   gssize ret;
1899
1900   ret = -1;
1901
1902   g_return_val_if_fail (blob != NULL, -1);
1903   g_return_val_if_fail (error == NULL || *error == NULL, -1);
1904   g_return_val_if_fail (blob_len >= 16, -1);
1905
1906   if (blob[0] == 'l')
1907     {
1908       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1909       ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
1910       /* round up so it's a multiple of 8 */
1911       ret = 8 * ((ret + 7)/8);
1912       /* finally add the body size */
1913       ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
1914     }
1915   else if (blob[0] == 'B')
1916     {
1917       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1918       ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
1919       /* round up so it's a multiple of 8 */
1920       ret = 8 * ((ret + 7)/8);
1921       /* finally add the body size */
1922       ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
1923     }
1924   else
1925     {
1926       g_set_error (error,
1927                    G_IO_ERROR,
1928                    G_IO_ERROR_INVALID_ARGUMENT,
1929                    "Unable to determine message blob length - given blob is malformed");
1930     }
1931
1932   if (ret > (2<<27))
1933     {
1934       g_set_error (error,
1935                    G_IO_ERROR,
1936                    G_IO_ERROR_INVALID_ARGUMENT,
1937                    "Blob indicates that message exceeds maximum message length (128MiB)");
1938       ret = -1;
1939     }
1940
1941   return ret;
1942 }
1943
1944 /* ---------------------------------------------------------------------------------------------------- */
1945
1946 /**
1947  * g_dbus_message_new_from_blob:
1948  * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1949  * @blob_len: The length of @blob.
1950  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1951  * @error: Return location for error or %NULL.
1952  *
1953  * Creates a new #GDBusMessage from the data stored at @blob. The byte
1954  * order that the message was in can be retrieved using
1955  * g_dbus_message_get_byte_order().
1956  *
1957  * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
1958  * g_object_unref().
1959  *
1960  * Since: 2.26
1961  */
1962 GDBusMessage *
1963 g_dbus_message_new_from_blob (guchar                *blob,
1964                               gsize                  blob_len,
1965                               GDBusCapabilityFlags   capabilities,
1966                               GError               **error)
1967 {
1968   gboolean ret;
1969   GMemoryBuffer mbuf;
1970   GDBusMessage *message;
1971   guchar endianness;
1972   guchar major_protocol_version;
1973   guint32 message_body_len;
1974   GVariant *headers;
1975   GVariant *item;
1976   GVariantIter iter;
1977   GVariant *signature;
1978
1979   /* TODO: check against @capabilities */
1980
1981   ret = FALSE;
1982
1983   g_return_val_if_fail (blob != NULL, NULL);
1984   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1985   g_return_val_if_fail (blob_len >= 12, NULL);
1986
1987   message = g_dbus_message_new ();
1988
1989   memset (&mbuf, 0, sizeof (mbuf));
1990   mbuf.data = (gchar *)blob;
1991   mbuf.len = mbuf.valid_len = blob_len;
1992
1993   endianness = g_memory_buffer_read_byte (&mbuf);
1994   switch (endianness)
1995     {
1996     case 'l':
1997       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
1998       message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
1999       break;
2000     case 'B':
2001       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2002       message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
2003       break;
2004     default:
2005       g_set_error (error,
2006                    G_IO_ERROR,
2007                    G_IO_ERROR_INVALID_ARGUMENT,
2008                    _("Invalid endianness value. Expected 0x6c ('l') or 0x42 ('B') but found value 0x%02x"),
2009                    endianness);
2010       goto out;
2011     }
2012
2013   message->type = g_memory_buffer_read_byte (&mbuf);
2014   message->flags = g_memory_buffer_read_byte (&mbuf);
2015   major_protocol_version = g_memory_buffer_read_byte (&mbuf);
2016   if (major_protocol_version != 1)
2017     {
2018       g_set_error (error,
2019                    G_IO_ERROR,
2020                    G_IO_ERROR_INVALID_ARGUMENT,
2021                    _("Invalid major protocol version. Expected 1 but found %d"),
2022                    major_protocol_version);
2023       goto out;
2024     }
2025   message_body_len = g_memory_buffer_read_uint32 (&mbuf);
2026   message->serial = g_memory_buffer_read_uint32 (&mbuf);
2027
2028 #ifdef DEBUG_SERIALIZER
2029   g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2030   {
2031     gchar *s;
2032     s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
2033     g_print ("%s\n", s);
2034     g_free (s);
2035   }
2036 #endif /* DEBUG_SERIALIZER */
2037
2038 #ifdef DEBUG_SERIALIZER
2039   g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2040 #endif /* DEBUG_SERIALIZER */
2041   headers = parse_value_from_blob (&mbuf,
2042                                    G_VARIANT_TYPE ("a{yv}"),
2043                                    FALSE,
2044                                    2,
2045                                    error);
2046   if (headers == NULL)
2047     goto out;
2048   g_variant_iter_init (&iter, headers);
2049   while ((item = g_variant_iter_next_value (&iter)) != NULL)
2050     {
2051       guchar header_field;
2052       GVariant *value;
2053       g_variant_get (item,
2054                      "{yv}",
2055                      &header_field,
2056                      &value);
2057       g_dbus_message_set_header (message, header_field, value);
2058       g_variant_unref (value);
2059       g_variant_unref (item);
2060     }
2061   g_variant_unref (headers);
2062
2063   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2064   if (signature != NULL)
2065     {
2066       const gchar *signature_str;
2067       gsize signature_str_len;
2068
2069       signature_str = g_variant_get_string (signature, &signature_str_len);
2070
2071       /* signature but no body */
2072       if (message_body_len == 0 && signature_str_len > 0)
2073         {
2074           g_set_error (error,
2075                        G_IO_ERROR,
2076                        G_IO_ERROR_INVALID_ARGUMENT,
2077                        _("Signature header with signature '%s' found but message body is empty"),
2078                        signature_str);
2079           goto out;
2080         }
2081       else if (signature_str_len > 0)
2082         {
2083           GVariantType *variant_type;
2084           gchar *tupled_signature_str;
2085
2086           if (!g_variant_is_signature (signature_str))
2087             {
2088               g_set_error (error,
2089                            G_IO_ERROR,
2090                            G_IO_ERROR_INVALID_ARGUMENT,
2091                            _("Parsed value '%s' is not a valid D-Bus signature (for body)"),
2092                            signature_str);
2093               goto out;
2094             }
2095           tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2096           variant_type = g_variant_type_new (tupled_signature_str);
2097           g_free (tupled_signature_str);
2098 #ifdef DEBUG_SERIALIZER
2099           g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2100 #endif /* DEBUG_SERIALIZER */
2101           message->body = parse_value_from_blob (&mbuf,
2102                                                  variant_type,
2103                                                  FALSE,
2104                                                  2,
2105                                                  error);
2106           g_variant_type_free (variant_type);
2107           if (message->body == NULL)
2108             goto out;
2109         }
2110     }
2111   else
2112     {
2113       /* no signature, this is only OK if the body is empty */
2114       if (message_body_len != 0)
2115         {
2116           /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
2117           g_set_error (error,
2118                        G_IO_ERROR,
2119                        G_IO_ERROR_INVALID_ARGUMENT,
2120                        g_dngettext (GETTEXT_PACKAGE,
2121                                     "No signature header in message but the message body is %u byte",
2122                                     "No signature header in message but the message body is %u bytes",
2123                                     message_body_len),
2124                        message_body_len);
2125           goto out;
2126         }
2127     }
2128
2129   if (!validate_headers (message, error))
2130     {
2131       g_prefix_error (error, _("Cannot deserialize message: "));
2132       goto out;
2133     }
2134
2135   ret = TRUE;
2136
2137  out:
2138   if (ret)
2139     {
2140       return message;
2141     }
2142   else
2143     {
2144       if (message != NULL)
2145         g_object_unref (message);
2146       return NULL;
2147     }
2148 }
2149
2150 /* ---------------------------------------------------------------------------------------------------- */
2151
2152 static gsize
2153 ensure_output_padding (GMemoryBuffer  *mbuf,
2154                        gsize           padding_size)
2155 {
2156   gsize offset;
2157   gsize wanted_offset;
2158   gsize padding_needed;
2159   guint n;
2160
2161   offset = mbuf->pos;
2162   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
2163   padding_needed = wanted_offset - offset;
2164
2165   for (n = 0; n < padding_needed; n++)
2166     g_memory_buffer_put_byte (mbuf, '\0');
2167
2168   return padding_needed;
2169 }
2170
2171 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
2172 static gboolean
2173 append_value_to_blob (GVariant            *value,
2174                       const GVariantType  *type,
2175                       GMemoryBuffer       *mbuf,
2176                       gsize               *out_padding_added,
2177                       GError             **error)
2178 {
2179   gsize padding_added;
2180   const gchar *type_string;
2181
2182   type_string = g_variant_type_peek_string (type);
2183
2184   padding_added = 0;
2185
2186   switch (type_string[0])
2187     {
2188     case 'b': /* G_VARIANT_TYPE_BOOLEAN */
2189       padding_added = ensure_output_padding (mbuf, 4);
2190       if (value != NULL)
2191         {
2192           gboolean v = g_variant_get_boolean (value);
2193           g_memory_buffer_put_uint32 (mbuf, v);
2194         }
2195       break;
2196
2197     case 'y': /* G_VARIANT_TYPE_BYTE */
2198       if (value != NULL)
2199         {
2200           guint8 v = g_variant_get_byte (value);
2201           g_memory_buffer_put_byte (mbuf, v);
2202         }
2203       break;
2204
2205     case 'n': /* G_VARIANT_TYPE_INT16 */
2206       padding_added = ensure_output_padding (mbuf, 2);
2207       if (value != NULL)
2208         {
2209           gint16 v = g_variant_get_int16 (value);
2210           g_memory_buffer_put_int16 (mbuf, v);
2211         }
2212       break;
2213
2214     case 'q': /* G_VARIANT_TYPE_UINT16 */
2215       padding_added = ensure_output_padding (mbuf, 2);
2216       if (value != NULL)
2217         {
2218           guint16 v = g_variant_get_uint16 (value);
2219           g_memory_buffer_put_uint16 (mbuf, v);
2220         }
2221       break;
2222
2223     case 'i': /* G_VARIANT_TYPE_INT32 */
2224       padding_added = ensure_output_padding (mbuf, 4);
2225       if (value != NULL)
2226         {
2227           gint32 v = g_variant_get_int32 (value);
2228           g_memory_buffer_put_int32 (mbuf, v);
2229         }
2230       break;
2231
2232     case 'u': /* G_VARIANT_TYPE_UINT32 */
2233       padding_added = ensure_output_padding (mbuf, 4);
2234       if (value != NULL)
2235         {
2236           guint32 v = g_variant_get_uint32 (value);
2237           g_memory_buffer_put_uint32 (mbuf, v);
2238         }
2239       break;
2240
2241     case 'x': /* G_VARIANT_TYPE_INT64 */
2242       padding_added = ensure_output_padding (mbuf, 8);
2243       if (value != NULL)
2244         {
2245           gint64 v = g_variant_get_int64 (value);
2246           g_memory_buffer_put_int64 (mbuf, v);
2247         }
2248       break;
2249
2250     case 't': /* G_VARIANT_TYPE_UINT64 */
2251       padding_added = ensure_output_padding (mbuf, 8);
2252       if (value != NULL)
2253         {
2254           guint64 v = g_variant_get_uint64 (value);
2255           g_memory_buffer_put_uint64 (mbuf, v);
2256         }
2257       break;
2258
2259     case 'd': /* G_VARIANT_TYPE_DOUBLE */
2260       padding_added = ensure_output_padding (mbuf, 8);
2261       if (value != NULL)
2262         {
2263           union {
2264             guint64 v_uint64;
2265             gdouble v_double;
2266           } u;
2267           G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
2268           u.v_double = g_variant_get_double (value);
2269           g_memory_buffer_put_uint64 (mbuf, u.v_uint64);
2270         }
2271       break;
2272
2273     case 's': /* G_VARIANT_TYPE_STRING */
2274       padding_added = ensure_output_padding (mbuf, 4);
2275       if (value != NULL)
2276         {
2277           gsize len;
2278           const gchar *v;
2279           const gchar *end;
2280           v = g_variant_get_string (value, &len);
2281           g_assert (g_utf8_validate (v, -1, &end) && (end == v + len));
2282           g_memory_buffer_put_uint32 (mbuf, len);
2283           g_memory_buffer_put_string (mbuf, v);
2284           g_memory_buffer_put_byte (mbuf, '\0');
2285         }
2286       break;
2287
2288     case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
2289       padding_added = ensure_output_padding (mbuf, 4);
2290       if (value != NULL)
2291         {
2292           gsize len;
2293           const gchar *v = g_variant_get_string (value, &len);
2294           g_assert (g_variant_is_object_path (v));
2295           g_memory_buffer_put_uint32 (mbuf, len);
2296           g_memory_buffer_put_string (mbuf, v);
2297           g_memory_buffer_put_byte (mbuf, '\0');
2298         }
2299       break;
2300
2301     case 'g': /* G_VARIANT_TYPE_SIGNATURE */
2302       if (value != NULL)
2303         {
2304           gsize len;
2305           const gchar *v = g_variant_get_string (value, &len);
2306           g_assert (g_variant_is_signature (v));
2307           g_memory_buffer_put_byte (mbuf, len);
2308           g_memory_buffer_put_string (mbuf, v);
2309           g_memory_buffer_put_byte (mbuf, '\0');
2310         }
2311       break;
2312
2313     case 'h': /* G_VARIANT_TYPE_HANDLE */
2314       padding_added = ensure_output_padding (mbuf, 4);
2315       if (value != NULL)
2316         {
2317           gint32 v = g_variant_get_handle (value);
2318           g_memory_buffer_put_int32 (mbuf, v);
2319         }
2320       break;
2321
2322     case 'a': /* G_VARIANT_TYPE_ARRAY */
2323       {
2324         GVariant *item;
2325         GVariantIter iter;
2326         goffset array_len_offset;
2327         goffset array_payload_begin_offset;
2328         goffset cur_offset;
2329         gsize array_len;
2330
2331         padding_added = ensure_output_padding (mbuf, 4);
2332         if (value != NULL)
2333           {
2334             /* array length - will be filled in later */
2335             array_len_offset = mbuf->valid_len;
2336             g_memory_buffer_put_uint32 (mbuf, 0xF00DFACE);
2337
2338             /* From the D-Bus spec:
2339              *
2340              *   "A UINT32 giving the length of the array data in bytes,
2341              *    followed by alignment padding to the alignment boundary of
2342              *    the array element type, followed by each array element. The
2343              *    array length is from the end of the alignment padding to
2344              *    the end of the last element, i.e. it does not include the
2345              *    padding after the length, or any padding after the last
2346              *    element."
2347              *
2348              * Thus, we need to count how much padding the first element
2349              * contributes and subtract that from the array length.
2350              */
2351             array_payload_begin_offset = mbuf->valid_len;
2352
2353             if (g_variant_n_children (value) == 0)
2354               {
2355                 gsize padding_added_for_item;
2356                 if (!append_value_to_blob (NULL,
2357                                            g_variant_type_element (type),
2358                                            mbuf,
2359                                            &padding_added_for_item,
2360                                            error))
2361                   goto fail;
2362                 array_payload_begin_offset += padding_added_for_item;
2363               }
2364             else
2365               {
2366                 guint n;
2367                 n = 0;
2368                 g_variant_iter_init (&iter, value);
2369                 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2370                   {
2371                     gsize padding_added_for_item;
2372                     if (!append_value_to_blob (item,
2373                                                g_variant_get_type (item),
2374                                                mbuf,
2375                                                &padding_added_for_item,
2376                                                error))
2377                       {
2378                         g_variant_unref (item);
2379                         goto fail;
2380                       }
2381                     g_variant_unref (item);
2382                     if (n == 0)
2383                       {
2384                         array_payload_begin_offset += padding_added_for_item;
2385                       }
2386                     n++;
2387                   }
2388               }
2389
2390             cur_offset = mbuf->valid_len;
2391             array_len = cur_offset - array_payload_begin_offset;
2392             mbuf->pos = array_len_offset;
2393
2394             g_memory_buffer_put_uint32 (mbuf, array_len);
2395             mbuf->pos = cur_offset;
2396           }
2397       }
2398       break;
2399
2400     default:
2401       if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
2402         {
2403           padding_added = ensure_output_padding (mbuf, 8);
2404           if (value != NULL)
2405             {
2406               GVariant *item;
2407               GVariantIter iter;
2408               g_variant_iter_init (&iter, value);
2409               while ((item = g_variant_iter_next_value (&iter)) != NULL)
2410                 {
2411                   if (!append_value_to_blob (item,
2412                                              g_variant_get_type (item),
2413                                              mbuf,
2414                                              NULL,
2415                                              error))
2416                     {
2417                       g_variant_unref (item);
2418                       goto fail;
2419                     }
2420                   g_variant_unref (item);
2421                 }
2422             }
2423         }
2424       else if (g_variant_type_is_variant (type))
2425         {
2426           if (value != NULL)
2427             {
2428               GVariant *child;
2429               const gchar *signature;
2430               child = g_variant_get_child_value (value, 0);
2431               signature = g_variant_get_type_string (child);
2432               g_memory_buffer_put_byte (mbuf, strlen (signature));
2433               g_memory_buffer_put_string (mbuf, signature);
2434               g_memory_buffer_put_byte (mbuf, '\0');
2435               if (!append_value_to_blob (child,
2436                                          g_variant_get_type (child),
2437                                          mbuf,
2438                                          NULL,
2439                                          error))
2440                 {
2441                   g_variant_unref (child);
2442                   goto fail;
2443                 }
2444               g_variant_unref (child);
2445             }
2446         }
2447       else
2448         {
2449           g_set_error (error,
2450                        G_IO_ERROR,
2451                        G_IO_ERROR_INVALID_ARGUMENT,
2452                        _("Error serializing GVariant with type string '%s' to the D-Bus wire format"),
2453                        g_variant_get_type_string (value));
2454           goto fail;
2455         }
2456       break;
2457     }
2458
2459   if (out_padding_added != NULL)
2460     *out_padding_added = padding_added;
2461
2462   return TRUE;
2463
2464  fail:
2465   return FALSE;
2466 }
2467
2468 static gboolean
2469 append_body_to_blob (GVariant       *value,
2470                      GMemoryBuffer  *mbuf,
2471                      GError        **error)
2472 {
2473   GVariant *item;
2474   GVariantIter iter;
2475
2476   if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
2477     {
2478       g_set_error (error,
2479                    G_IO_ERROR,
2480                    G_IO_ERROR_INVALID_ARGUMENT,
2481                    "Expected a tuple for the body of the GDBusMessage.");
2482       goto fail;
2483     }
2484
2485   g_variant_iter_init (&iter, value);
2486   while ((item = g_variant_iter_next_value (&iter)) != NULL)
2487     {
2488       if (!append_value_to_blob (item,
2489                                  g_variant_get_type (item),
2490                                  mbuf,
2491                                  NULL,
2492                                  error))
2493         {
2494           g_variant_unref (item);
2495           goto fail;
2496         }
2497       g_variant_unref (item);
2498     }
2499   return TRUE;
2500
2501  fail:
2502   return FALSE;
2503 }
2504
2505 /* ---------------------------------------------------------------------------------------------------- */
2506
2507 /**
2508  * g_dbus_message_to_blob:
2509  * @message: A #GDBusMessage.
2510  * @out_size: Return location for size of generated blob.
2511  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2512  * @error: Return location for error.
2513  *
2514  * Serializes @message to a blob. The byte order returned by
2515  * g_dbus_message_get_byte_order() will be used.
2516  *
2517  * Returns: (array length=out_size) (transfer full): A pointer to a
2518  * valid binary D-Bus message of @out_size bytes generated by @message
2519  * or %NULL if @error is set. Free with g_free().
2520  *
2521  * Since: 2.26
2522  */
2523 guchar *
2524 g_dbus_message_to_blob (GDBusMessage          *message,
2525                         gsize                 *out_size,
2526                         GDBusCapabilityFlags   capabilities,
2527                         GError               **error)
2528 {
2529   GMemoryBuffer mbuf;
2530   guchar *ret;
2531   gsize size;
2532   goffset body_len_offset;
2533   goffset body_start_offset;
2534   gsize body_size;
2535   GVariant *header_fields;
2536   GVariantBuilder builder;
2537   GHashTableIter hash_iter;
2538   gpointer key;
2539   GVariant *header_value;
2540   GVariant *signature;
2541   const gchar *signature_str;
2542   gint num_fds_in_message;
2543   gint num_fds_according_to_header;
2544
2545   /* TODO: check against @capabilities */
2546
2547   ret = NULL;
2548
2549   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2550   g_return_val_if_fail (out_size != NULL, NULL);
2551   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2552
2553   memset (&mbuf, 0, sizeof (mbuf));
2554   mbuf.len = MIN_ARRAY_SIZE;
2555   mbuf.data = g_malloc (mbuf.len);
2556
2557   mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN;
2558   switch (message->byte_order)
2559     {
2560     case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
2561       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2562       break;
2563     case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
2564       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2565       break;
2566     }
2567
2568   /* Core header */
2569   g_memory_buffer_put_byte (&mbuf, (guchar) message->byte_order);
2570   g_memory_buffer_put_byte (&mbuf, message->type);
2571   g_memory_buffer_put_byte (&mbuf, message->flags);
2572   g_memory_buffer_put_byte (&mbuf, 1); /* major protocol version */
2573   body_len_offset = mbuf.valid_len;
2574   /* body length - will be filled in later */
2575   g_memory_buffer_put_uint32 (&mbuf, 0xF00DFACE);
2576   g_memory_buffer_put_uint32 (&mbuf, message->serial);
2577
2578   num_fds_in_message = 0;
2579 #ifdef G_OS_UNIX
2580   if (message->fd_list != NULL)
2581     num_fds_in_message = g_unix_fd_list_get_length (message->fd_list);
2582 #endif
2583   num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
2584   if (num_fds_in_message != num_fds_according_to_header)
2585     {
2586       g_set_error (error,
2587                    G_IO_ERROR,
2588                    G_IO_ERROR_INVALID_ARGUMENT,
2589                    _("Message has %d file descriptors but the header field indicates %d file descriptors"),
2590                    num_fds_in_message,
2591                    num_fds_according_to_header);
2592       goto out;
2593     }
2594
2595   if (!validate_headers (message, error))
2596     {
2597       g_prefix_error (error, _("Cannot serialize message: "));
2598       goto out;
2599     }
2600
2601   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
2602   g_hash_table_iter_init (&hash_iter, message->headers);
2603   while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
2604     {
2605       g_variant_builder_add (&builder,
2606                              "{yv}",
2607                              (guchar) GPOINTER_TO_UINT (key),
2608                              header_value);
2609     }
2610   header_fields = g_variant_builder_end (&builder);
2611
2612   if (!append_value_to_blob (header_fields,
2613                              g_variant_get_type (header_fields),
2614                              &mbuf,
2615                              NULL,
2616                              error))
2617     {
2618       g_variant_unref (header_fields);
2619       goto out;
2620     }
2621   g_variant_unref (header_fields);
2622
2623   /* header size must be a multiple of 8 */
2624   ensure_output_padding (&mbuf, 8);
2625
2626   body_start_offset = mbuf.valid_len;
2627
2628   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2629   signature_str = NULL;
2630   if (signature != NULL)
2631       signature_str = g_variant_get_string (signature, NULL);
2632   if (message->body != NULL)
2633     {
2634       gchar *tupled_signature_str;
2635       tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2636       if (signature == NULL)
2637         {
2638           g_set_error (error,
2639                        G_IO_ERROR,
2640                        G_IO_ERROR_INVALID_ARGUMENT,
2641                        _("Message body has signature '%s' but there is no signature header"),
2642                        signature_str);
2643           g_free (tupled_signature_str);
2644           goto out;
2645         }
2646       else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
2647         {
2648           g_set_error (error,
2649                        G_IO_ERROR,
2650                        G_IO_ERROR_INVALID_ARGUMENT,
2651                        _("Message body has type signature '%s' but signature in the header field is '%s'"),
2652                        tupled_signature_str, g_variant_get_type_string (message->body));
2653           g_free (tupled_signature_str);
2654           goto out;
2655         }
2656       g_free (tupled_signature_str);
2657       if (!append_body_to_blob (message->body, &mbuf, error))
2658         goto out;
2659     }
2660   else
2661     {
2662       if (signature != NULL && strlen (signature_str) > 0)
2663         {
2664           g_set_error (error,
2665                        G_IO_ERROR,
2666                        G_IO_ERROR_INVALID_ARGUMENT,
2667                        _("Message body is empty but signature in the header field is '(%s)'"),
2668                        signature_str);
2669           goto out;
2670         }
2671     }
2672
2673   /* OK, we're done writing the message - set the body length */
2674   size = mbuf.valid_len;
2675   body_size = size - body_start_offset;
2676
2677   mbuf.pos = body_len_offset;
2678
2679   g_memory_buffer_put_uint32 (&mbuf, body_size);
2680
2681   *out_size = size;
2682   ret = (guchar *)mbuf.data;
2683
2684  out:
2685   return ret;
2686 }
2687
2688 /* ---------------------------------------------------------------------------------------------------- */
2689
2690 static guint32
2691 get_uint32_header (GDBusMessage            *message,
2692                    GDBusMessageHeaderField  header_field)
2693 {
2694   GVariant *value;
2695   guint32 ret;
2696
2697   ret = 0;
2698   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2699   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
2700     ret = g_variant_get_uint32 (value);
2701
2702   return ret;
2703 }
2704
2705 static const gchar *
2706 get_string_header (GDBusMessage            *message,
2707                    GDBusMessageHeaderField  header_field)
2708 {
2709   GVariant *value;
2710   const gchar *ret;
2711
2712   ret = NULL;
2713   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2714   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
2715     ret = g_variant_get_string (value, NULL);
2716
2717   return ret;
2718 }
2719
2720 static const gchar *
2721 get_object_path_header (GDBusMessage            *message,
2722                         GDBusMessageHeaderField  header_field)
2723 {
2724   GVariant *value;
2725   const gchar *ret;
2726
2727   ret = NULL;
2728   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2729   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
2730     ret = g_variant_get_string (value, NULL);
2731
2732   return ret;
2733 }
2734
2735 static const gchar *
2736 get_signature_header (GDBusMessage            *message,
2737                       GDBusMessageHeaderField  header_field)
2738 {
2739   GVariant *value;
2740   const gchar *ret;
2741
2742   ret = NULL;
2743   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2744   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
2745     ret = g_variant_get_string (value, NULL);
2746
2747   return ret;
2748 }
2749
2750 /* ---------------------------------------------------------------------------------------------------- */
2751
2752 static void
2753 set_uint32_header (GDBusMessage             *message,
2754                    GDBusMessageHeaderField   header_field,
2755                    guint32                   value)
2756 {
2757   g_dbus_message_set_header (message,
2758                              header_field,
2759                              g_variant_new_uint32 (value));
2760 }
2761
2762 static void
2763 set_string_header (GDBusMessage             *message,
2764                    GDBusMessageHeaderField   header_field,
2765                    const gchar              *value)
2766 {
2767   g_dbus_message_set_header (message,
2768                              header_field,
2769                              value == NULL ? NULL : g_variant_new_string (value));
2770 }
2771
2772 static void
2773 set_object_path_header (GDBusMessage             *message,
2774                         GDBusMessageHeaderField   header_field,
2775                         const gchar              *value)
2776 {
2777   g_dbus_message_set_header (message,
2778                              header_field,
2779                              value == NULL ? NULL : g_variant_new_object_path (value));
2780 }
2781
2782 static void
2783 set_signature_header (GDBusMessage             *message,
2784                       GDBusMessageHeaderField   header_field,
2785                       const gchar              *value)
2786 {
2787   g_dbus_message_set_header (message,
2788                              header_field,
2789                              value == NULL ? NULL : g_variant_new_signature (value));
2790 }
2791
2792 /* ---------------------------------------------------------------------------------------------------- */
2793
2794 /**
2795  * g_dbus_message_get_reply_serial:
2796  * @message: A #GDBusMessage.
2797  *
2798  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2799  *
2800  * Returns: The value.
2801  *
2802  * Since: 2.26
2803  */
2804 guint32
2805 g_dbus_message_get_reply_serial (GDBusMessage  *message)
2806 {
2807   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2808   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
2809 }
2810
2811 /**
2812  * g_dbus_message_set_reply_serial:
2813  * @message: A #GDBusMessage.
2814  * @value: The value to set.
2815  *
2816  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2817  *
2818  * Since: 2.26
2819  */
2820 void
2821 g_dbus_message_set_reply_serial (GDBusMessage  *message,
2822                                  guint32        value)
2823 {
2824   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2825   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
2826 }
2827
2828 /* ---------------------------------------------------------------------------------------------------- */
2829
2830 /**
2831  * g_dbus_message_get_interface:
2832  * @message: A #GDBusMessage.
2833  *
2834  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2835  *
2836  * Returns: The value.
2837  *
2838  * Since: 2.26
2839  */
2840 const gchar *
2841 g_dbus_message_get_interface (GDBusMessage  *message)
2842 {
2843   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2844   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
2845 }
2846
2847 /**
2848  * g_dbus_message_set_interface:
2849  * @message: A #GDBusMessage.
2850  * @value: The value to set.
2851  *
2852  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2853  *
2854  * Since: 2.26
2855  */
2856 void
2857 g_dbus_message_set_interface (GDBusMessage  *message,
2858                               const gchar   *value)
2859 {
2860   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2861   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2862   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
2863 }
2864
2865 /* ---------------------------------------------------------------------------------------------------- */
2866
2867 /**
2868  * g_dbus_message_get_member:
2869  * @message: A #GDBusMessage.
2870  *
2871  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2872  *
2873  * Returns: The value.
2874  *
2875  * Since: 2.26
2876  */
2877 const gchar *
2878 g_dbus_message_get_member (GDBusMessage  *message)
2879 {
2880   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2881   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
2882 }
2883
2884 /**
2885  * g_dbus_message_set_member:
2886  * @message: A #GDBusMessage.
2887  * @value: The value to set.
2888  *
2889  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2890  *
2891  * Since: 2.26
2892  */
2893 void
2894 g_dbus_message_set_member (GDBusMessage  *message,
2895                            const gchar   *value)
2896 {
2897   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2898   g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
2899   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
2900 }
2901
2902 /* ---------------------------------------------------------------------------------------------------- */
2903
2904 /**
2905  * g_dbus_message_get_path:
2906  * @message: A #GDBusMessage.
2907  *
2908  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2909  *
2910  * Returns: The value.
2911  *
2912  * Since: 2.26
2913  */
2914 const gchar *
2915 g_dbus_message_get_path (GDBusMessage  *message)
2916 {
2917   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2918   return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
2919 }
2920
2921 /**
2922  * g_dbus_message_set_path:
2923  * @message: A #GDBusMessage.
2924  * @value: The value to set.
2925  *
2926  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2927  *
2928  * Since: 2.26
2929  */
2930 void
2931 g_dbus_message_set_path (GDBusMessage  *message,
2932                          const gchar   *value)
2933 {
2934   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2935   g_return_if_fail (value == NULL || g_variant_is_object_path (value));
2936   set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
2937 }
2938
2939 /* ---------------------------------------------------------------------------------------------------- */
2940
2941 /**
2942  * g_dbus_message_get_sender:
2943  * @message: A #GDBusMessage.
2944  *
2945  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2946  *
2947  * Returns: The value.
2948  *
2949  * Since: 2.26
2950  */
2951 const gchar *
2952 g_dbus_message_get_sender (GDBusMessage *message)
2953 {
2954   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2955   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
2956 }
2957
2958 /**
2959  * g_dbus_message_set_sender:
2960  * @message: A #GDBusMessage.
2961  * @value: The value to set.
2962  *
2963  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2964  *
2965  * Since: 2.26
2966  */
2967 void
2968 g_dbus_message_set_sender (GDBusMessage  *message,
2969                            const gchar   *value)
2970 {
2971   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2972   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2973   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
2974 }
2975
2976 /* ---------------------------------------------------------------------------------------------------- */
2977
2978 /**
2979  * g_dbus_message_get_destination:
2980  * @message: A #GDBusMessage.
2981  *
2982  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2983  *
2984  * Returns: The value.
2985  *
2986  * Since: 2.26
2987  */
2988 const gchar *
2989 g_dbus_message_get_destination (GDBusMessage  *message)
2990 {
2991   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2992   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
2993 }
2994
2995 /**
2996  * g_dbus_message_set_destination:
2997  * @message: A #GDBusMessage.
2998  * @value: The value to set.
2999  *
3000  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3001  *
3002  * Since: 2.26
3003  */
3004 void
3005 g_dbus_message_set_destination (GDBusMessage  *message,
3006                                 const gchar   *value)
3007 {
3008   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3009   g_return_if_fail (value == NULL || g_dbus_is_name (value));
3010   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
3011 }
3012
3013 /* ---------------------------------------------------------------------------------------------------- */
3014
3015 /**
3016  * g_dbus_message_get_error_name:
3017  * @message: A #GDBusMessage.
3018  *
3019  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3020  *
3021  * Returns: The value.
3022  *
3023  * Since: 2.26
3024  */
3025 const gchar *
3026 g_dbus_message_get_error_name (GDBusMessage  *message)
3027 {
3028   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3029   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
3030 }
3031
3032 /**
3033  * g_dbus_message_set_error_name:
3034  * @message: A #GDBusMessage.
3035  * @value: The value to set.
3036  *
3037  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3038  *
3039  * Since: 2.26
3040  */
3041 void
3042 g_dbus_message_set_error_name (GDBusMessage  *message,
3043                                const gchar   *value)
3044 {
3045   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3046   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
3047   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
3048 }
3049
3050 /* ---------------------------------------------------------------------------------------------------- */
3051
3052 /**
3053  * g_dbus_message_get_signature:
3054  * @message: A #GDBusMessage.
3055  *
3056  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3057  *
3058  * Returns: The value.
3059  *
3060  * Since: 2.26
3061  */
3062 const gchar *
3063 g_dbus_message_get_signature (GDBusMessage  *message)
3064 {
3065   const gchar *ret;
3066   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3067   ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
3068   if (ret == NULL)
3069     ret = "";
3070   return ret;
3071 }
3072
3073 /**
3074  * g_dbus_message_set_signature:
3075  * @message: A #GDBusMessage.
3076  * @value: The value to set.
3077  *
3078  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3079  *
3080  * Since: 2.26
3081  */
3082 void
3083 g_dbus_message_set_signature (GDBusMessage  *message,
3084                               const gchar   *value)
3085 {
3086   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3087   g_return_if_fail (value == NULL || g_variant_is_signature (value));
3088   set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
3089 }
3090
3091 /* ---------------------------------------------------------------------------------------------------- */
3092
3093 /**
3094  * g_dbus_message_get_arg0:
3095  * @message: A #GDBusMessage.
3096  *
3097  * Convenience to get the first item in the body of @message.
3098  *
3099  * Returns: The string item or %NULL if the first item in the body of
3100  * @message is not a string.
3101  *
3102  * Since: 2.26
3103  */
3104 const gchar *
3105 g_dbus_message_get_arg0 (GDBusMessage  *message)
3106 {
3107   const gchar *ret;
3108
3109   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3110
3111   ret = NULL;
3112
3113   if (message->body != NULL && g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE))
3114     {
3115       GVariant *item;
3116       item = g_variant_get_child_value (message->body, 0);
3117       if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING))
3118         ret = g_variant_get_string (item, NULL);
3119       g_variant_unref (item);
3120     }
3121
3122   return ret;
3123 }
3124
3125 /* ---------------------------------------------------------------------------------------------------- */
3126
3127 /**
3128  * g_dbus_message_get_num_unix_fds:
3129  * @message: A #GDBusMessage.
3130  *
3131  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3132  *
3133  * Returns: The value.
3134  *
3135  * Since: 2.26
3136  */
3137 guint32
3138 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
3139 {
3140   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3141   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
3142 }
3143
3144 /**
3145  * g_dbus_message_set_num_unix_fds:
3146  * @message: A #GDBusMessage.
3147  * @value: The value to set.
3148  *
3149  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3150  *
3151  * Since: 2.26
3152  */
3153 void
3154 g_dbus_message_set_num_unix_fds (GDBusMessage  *message,
3155                                  guint32        value)
3156 {
3157   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3158   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
3159 }
3160
3161 /* ---------------------------------------------------------------------------------------------------- */
3162
3163 /**
3164  * g_dbus_message_to_gerror:
3165  * @message: A #GDBusMessage.
3166  * @error: The #GError to set.
3167  *
3168  * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
3169  * nothing and returns %FALSE.
3170  *
3171  * Otherwise this method encodes the error in @message as a #GError
3172  * using g_dbus_error_set_dbus_error() using the information in the
3173  * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
3174  * well as the first string item in @message's body.
3175  *
3176  * Returns: %TRUE if @error was set, %FALSE otherwise.
3177  *
3178  * Since: 2.26
3179  */
3180 gboolean
3181 g_dbus_message_to_gerror (GDBusMessage   *message,
3182                           GError        **error)
3183 {
3184   gboolean ret;
3185   const gchar *error_name;
3186
3187   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3188
3189   ret = FALSE;
3190   if (message->type != G_DBUS_MESSAGE_TYPE_ERROR)
3191     goto out;
3192
3193   error_name = g_dbus_message_get_error_name (message);
3194   if (error_name != NULL)
3195     {
3196       GVariant *body;
3197
3198       body = g_dbus_message_get_body (message);
3199
3200       if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
3201         {
3202           const gchar *error_message;
3203           g_variant_get (body, "(&s)", &error_message);
3204           g_dbus_error_set_dbus_error (error,
3205                                        error_name,
3206                                        error_message,
3207                                        NULL);
3208         }
3209       else
3210         {
3211           /* these two situations are valid, yet pretty rare */
3212           if (body != NULL)
3213             {
3214               g_dbus_error_set_dbus_error (error,
3215                                            error_name,
3216                                            "",
3217                                            _("Error return with body of type '%s'"),
3218                                            g_variant_get_type_string (body));
3219             }
3220           else
3221             {
3222               g_dbus_error_set_dbus_error (error,
3223                                            error_name,
3224                                            "",
3225                                            _("Error return with empty body"));
3226             }
3227         }
3228     }
3229   else
3230     {
3231       /* TOOD: this shouldn't happen - should check this at message serialization
3232        * time and disconnect the peer.
3233        */
3234       g_set_error (error,
3235                    G_IO_ERROR,
3236                    G_IO_ERROR_FAILED,
3237                    "Error return without error-name header!");
3238     }
3239
3240   ret = TRUE;
3241
3242  out:
3243   return ret;
3244 }
3245
3246 /* ---------------------------------------------------------------------------------------------------- */
3247
3248 static gchar *
3249 flags_to_string (GType flags_type, guint value)
3250 {
3251   GString *s;
3252   GFlagsClass *klass;
3253   guint n;
3254
3255   klass = g_type_class_ref (flags_type);
3256   s = g_string_new (NULL);
3257   for (n = 0; n < 32; n++)
3258     {
3259       if ((value & (1<<n)) != 0)
3260         {
3261           GFlagsValue *flags_value;
3262           flags_value = g_flags_get_first_value (klass, (1<<n));
3263           if (s->len > 0)
3264             g_string_append_c (s, ',');
3265           if (flags_value != NULL)
3266             g_string_append (s, flags_value->value_nick);
3267           else
3268             g_string_append_printf (s, "unknown (bit %d)", n);
3269         }
3270     }
3271   if (s->len == 0)
3272     g_string_append (s, "none");
3273   g_type_class_unref (klass);
3274   return g_string_free (s, FALSE);
3275 }
3276
3277 static gint
3278 _sort_keys_func (gconstpointer a,
3279                  gconstpointer b)
3280 {
3281   gint ia;
3282   gint ib;
3283
3284   ia = GPOINTER_TO_INT (a);
3285   ib = GPOINTER_TO_INT (b);
3286
3287   return ia - ib;
3288 }
3289
3290 /**
3291  * g_dbus_message_print:
3292  * @message: A #GDBusMessage.
3293  * @indent: Indentation level.
3294  *
3295  * Produces a human-readable multi-line description of @message.
3296  *
3297  * The contents of the description has no ABI guarantees, the contents
3298  * and formatting is subject to change at any time. Typical output
3299  * looks something like this:
3300  * |[
3301  * Type:    method-call
3302  * Flags:   none
3303  * Version: 0
3304  * Serial:  4
3305  * Headers:
3306  *   path -> objectpath '/org/gtk/GDBus/TestObject'
3307  *   interface -> 'org.gtk.GDBus.TestInterface'
3308  *   member -> 'GimmeStdout'
3309  *   destination -> ':1.146'
3310  * Body: ()
3311  * UNIX File Descriptors:
3312  *   (none)
3313  * ]|
3314  * or
3315  * |[
3316  * Type:    method-return
3317  * Flags:   no-reply-expected
3318  * Version: 0
3319  * Serial:  477
3320  * Headers:
3321  *   reply-serial -> uint32 4
3322  *   destination -> ':1.159'
3323  *   sender -> ':1.146'
3324  *   num-unix-fds -> uint32 1
3325  * Body: ()
3326  * UNIX File Descriptors:
3327  *   fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
3328  * ]|
3329  *
3330  * Returns: A string that should be freed with g_free().
3331  *
3332  * Since: 2.26
3333  */
3334 gchar *
3335 g_dbus_message_print (GDBusMessage *message,
3336                       guint         indent)
3337 {
3338   GString *str;
3339   gchar *s;
3340   GList *keys;
3341   GList *l;
3342
3343   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3344
3345   str = g_string_new (NULL);
3346
3347   s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->type);
3348   g_string_append_printf (str, "%*sType:    %s\n", indent, "", s);
3349   g_free (s);
3350   s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->flags);
3351   g_string_append_printf (str, "%*sFlags:   %s\n", indent, "", s);
3352   g_free (s);
3353   g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->major_protocol_version);
3354   g_string_append_printf (str, "%*sSerial:  %d\n", indent, "", message->serial);
3355
3356   g_string_append_printf (str, "%*sHeaders:\n", indent, "");
3357   keys = g_hash_table_get_keys (message->headers);
3358   keys = g_list_sort (keys, _sort_keys_func);
3359   if (keys != NULL)
3360     {
3361       for (l = keys; l != NULL; l = l->next)
3362         {
3363           gint key = GPOINTER_TO_INT (l->data);
3364           GVariant *value;
3365           gchar *value_str;
3366
3367           value = g_hash_table_lookup (message->headers, l->data);
3368           g_assert (value != NULL);
3369
3370           s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
3371           value_str = g_variant_print (value, TRUE);
3372           g_string_append_printf (str, "%*s  %s -> %s\n", indent, "", s, value_str);
3373           g_free (s);
3374           g_free (value_str);
3375         }
3376     }
3377   else
3378     {
3379       g_string_append_printf (str, "%*s  (none)\n", indent, "");
3380     }
3381   g_string_append_printf (str, "%*sBody: ", indent, "");
3382   if (message->body != NULL)
3383     {
3384       g_variant_print_string (message->body,
3385                               str,
3386                               TRUE);
3387     }
3388   else
3389     {
3390       g_string_append (str, "()");
3391     }
3392   g_string_append (str, "\n");
3393 #ifdef G_OS_UNIX
3394   g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
3395   if (message->fd_list != NULL)
3396     {
3397       gint num_fds;
3398       const gint *fds;
3399       gint n;
3400
3401       fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3402       if (num_fds > 0)
3403         {
3404           for (n = 0; n < num_fds; n++)
3405             {
3406               GString *fs;
3407               struct stat statbuf;
3408               fs = g_string_new (NULL);
3409               if (fstat (fds[n], &statbuf) == 0)
3410                 {
3411                   g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
3412                                           major (statbuf.st_dev), minor (statbuf.st_dev));
3413                   g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
3414                                           statbuf.st_mode);
3415                   g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3416                                           (guint64) statbuf.st_ino);
3417                   g_string_append_printf (fs, "%s" "uid=%u", fs->len > 0 ? "," : "",
3418                                           (guint) statbuf.st_uid);
3419                   g_string_append_printf (fs, "%s" "gid=%u", fs->len > 0 ? "," : "",
3420                                           (guint) statbuf.st_gid);
3421                   g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
3422                                           major (statbuf.st_rdev), minor (statbuf.st_rdev));
3423                   g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3424                                           (guint64) statbuf.st_size);
3425                   g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3426                                           (guint64) statbuf.st_atime);
3427                   g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3428                                           (guint64) statbuf.st_mtime);
3429                   g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3430                                           (guint64) statbuf.st_ctime);
3431                 }
3432               else
3433                 {
3434                   g_string_append_printf (fs, "(fstat failed: %s)", strerror (errno));
3435                 }
3436               g_string_append_printf (str, "%*s  fd %d: %s\n", indent, "", fds[n], fs->str);
3437               g_string_free (fs, TRUE);
3438             }
3439         }
3440       else
3441         {
3442           g_string_append_printf (str, "%*s  (empty)\n", indent, "");
3443         }
3444     }
3445   else
3446     {
3447       g_string_append_printf (str, "%*s  (none)\n", indent, "");
3448     }
3449 #endif
3450
3451   return g_string_free (str, FALSE);
3452 }
3453
3454 /**
3455  * g_dbus_message_get_locked:
3456  * @message: A #GDBusMessage.
3457  *
3458  * Checks whether @message is locked. To monitor changes to this
3459  * value, conncet to the #GObject::notify signal to listen for changes
3460  * on the #GDBusMessage:locked property.
3461  *
3462  * Returns: %TRUE if @message is locked, %FALSE otherwise.
3463  *
3464  * Since: 2.26
3465  */
3466 gboolean
3467 g_dbus_message_get_locked (GDBusMessage *message)
3468 {
3469   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3470   return message->locked;
3471 }
3472
3473 /**
3474  * g_dbus_message_lock:
3475  * @message: A #GDBusMessage.
3476  *
3477  * If @message is locked, does nothing. Otherwise locks the message.
3478  *
3479  * Since: 2.26
3480  */
3481 void
3482 g_dbus_message_lock (GDBusMessage *message)
3483 {
3484   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3485
3486   if (message->locked)
3487     goto out;
3488
3489   message->locked = TRUE;
3490   g_object_notify (G_OBJECT (message), "locked");
3491
3492  out:
3493   ;
3494 }
3495
3496 /**
3497  * g_dbus_message_copy:
3498  * @message: A #GDBusMessage.
3499  * @error: Return location for error or %NULL.
3500  *
3501  * Copies @message. The copy is a deep copy and the returned
3502  * #GDBusMessage is completely identical except that it is guaranteed
3503  * to not be locked.
3504  *
3505  * This operation can fail if e.g. @message contains file descriptors
3506  * and the per-process or system-wide open files limit is reached.
3507  *
3508  * Returns: (transfer full): A new #GDBusMessage or %NULL if @error is set.
3509  *     Free with g_object_unref().
3510  *
3511  * Since: 2.26
3512  */
3513 GDBusMessage *
3514 g_dbus_message_copy (GDBusMessage  *message,
3515                      GError       **error)
3516 {
3517   GDBusMessage *ret;
3518   GHashTableIter iter;
3519   gpointer header_key;
3520   GVariant *header_value;
3521
3522   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3523   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
3524
3525   ret = g_dbus_message_new ();
3526   ret->type                   = message->type;
3527   ret->flags                  = message->flags;
3528   ret->byte_order             = message->byte_order;
3529   ret->major_protocol_version = message->major_protocol_version;
3530   ret->serial                 = message->serial;
3531
3532 #ifdef G_OS_UNIX
3533   if (message->fd_list != NULL)
3534     {
3535       gint n;
3536       gint num_fds;
3537       const gint *fds;
3538
3539       ret->fd_list = g_unix_fd_list_new ();
3540       fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3541       for (n = 0; n < num_fds; n++)
3542         {
3543           if (g_unix_fd_list_append (ret->fd_list,
3544                                      fds[n],
3545                                      error) == -1)
3546             {
3547               g_object_unref (ret);
3548               ret = NULL;
3549               goto out;
3550             }
3551         }
3552     }
3553 #endif
3554
3555   /* see https://bugzilla.gnome.org/show_bug.cgi?id=624546#c8 for why it's fine
3556    * to just ref (as opposed to deep-copying) the GVariant instances
3557    */
3558   ret->body = message->body != NULL ? g_variant_ref (message->body) : NULL;
3559   g_hash_table_iter_init (&iter, message->headers);
3560   while (g_hash_table_iter_next (&iter, &header_key, (gpointer) &header_value))
3561     g_hash_table_insert (ret->headers, header_key, g_variant_ref (header_value));
3562
3563 #ifdef G_OS_UNIX
3564  out:
3565 #endif
3566   return ret;
3567 }