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