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