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