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