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