ad77aa60b0e87296b1de8140658ea0b294acf6e0
[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 G_GNUC_PRINTF(3, 0)
831 GDBusMessage *
832 g_dbus_message_new_method_error_valist (GDBusMessage             *method_call_message,
833                                         const gchar              *error_name,
834                                         const gchar              *error_message_format,
835                                         va_list                   var_args)
836 {
837   GDBusMessage *ret;
838   gchar *error_message;
839   error_message = g_strdup_vprintf (error_message_format, var_args);
840   ret = g_dbus_message_new_method_error_literal (method_call_message,
841                                                  error_name,
842                                                  error_message);
843   g_free (error_message);
844   return ret;
845 }
846
847 /* ---------------------------------------------------------------------------------------------------- */
848
849 /**
850  * g_dbus_message_get_byte_order:
851  * @message: A #GDBusMessage.
852  *
853  * Gets the byte order of @message.
854  *
855  * Returns: The byte order.
856  */
857 GDBusMessageByteOrder
858 g_dbus_message_get_byte_order (GDBusMessage *message)
859 {
860   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), (GDBusMessageByteOrder) 0);
861   return message->byte_order;
862 }
863
864 /**
865  * g_dbus_message_set_byte_order:
866  * @message: A #GDBusMessage.
867  * @byte_order: The byte order.
868  *
869  * Sets the byte order of @message.
870  */
871 void
872 g_dbus_message_set_byte_order (GDBusMessage          *message,
873                                GDBusMessageByteOrder  byte_order)
874 {
875   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
876
877   if (message->locked)
878     {
879       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
880       return;
881     }
882
883   message->byte_order = byte_order;
884 }
885
886 /* ---------------------------------------------------------------------------------------------------- */
887
888 /* TODO: need GI annotations to specify that any guchar value goes for the type */
889
890 /**
891  * g_dbus_message_get_message_type:
892  * @message: A #GDBusMessage.
893  *
894  * Gets the type of @message.
895  *
896  * Returns: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
897  *
898  * Since: 2.26
899  */
900 GDBusMessageType
901 g_dbus_message_get_message_type (GDBusMessage  *message)
902 {
903   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_TYPE_INVALID);
904   return message->type;
905 }
906
907 /**
908  * g_dbus_message_set_message_type:
909  * @message: A #GDBusMessage.
910  * @type: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
911  *
912  * Sets @message to be of @type.
913  *
914  * Since: 2.26
915  */
916 void
917 g_dbus_message_set_message_type (GDBusMessage      *message,
918                                  GDBusMessageType   type)
919 {
920   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
921   g_return_if_fail (type >=0 && type < 256);
922
923   if (message->locked)
924     {
925       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
926       return;
927     }
928
929   message->type = type;
930 }
931
932 /* ---------------------------------------------------------------------------------------------------- */
933
934 /* TODO: need GI annotations to specify that any guchar value goes for flags */
935
936 /**
937  * g_dbus_message_get_flags:
938  * @message: A #GDBusMessage.
939  *
940  * Gets the flags for @message.
941  *
942  * Returns: Flags that are set (typically values from the #GDBusMessageFlags enumeration bitwise ORed together).
943  *
944  * Since: 2.26
945  */
946 GDBusMessageFlags
947 g_dbus_message_get_flags (GDBusMessage  *message)
948 {
949   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_FLAGS_NONE);
950   return message->flags;
951 }
952
953 /**
954  * g_dbus_message_set_flags:
955  * @message: A #GDBusMessage.
956  * @flags: Flags for @message that are set (typically values from the #GDBusMessageFlags
957  * enumeration bitwise ORed together).
958  *
959  * Sets the flags to set on @message.
960  *
961  * Since: 2.26
962  */
963 void
964 g_dbus_message_set_flags (GDBusMessage       *message,
965                           GDBusMessageFlags   flags)
966 {
967   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
968   g_return_if_fail (flags >=0 && flags < 256);
969
970   if (message->locked)
971     {
972       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
973       return;
974     }
975
976   message->flags = flags;
977 }
978
979 /* ---------------------------------------------------------------------------------------------------- */
980
981 /**
982  * g_dbus_message_get_serial:
983  * @message: A #GDBusMessage.
984  *
985  * Gets the serial for @message.
986  *
987  * Returns: A #guint32.
988  *
989  * Since: 2.26
990  */
991 guint32
992 g_dbus_message_get_serial (GDBusMessage *message)
993 {
994   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
995   return message->serial;
996 }
997
998 /**
999  * g_dbus_message_set_serial:
1000  * @message: A #GDBusMessage.
1001  * @serial: A #guint32.
1002  *
1003  * Sets the serial for @message.
1004  *
1005  * Since: 2.26
1006  */
1007 void
1008 g_dbus_message_set_serial (GDBusMessage  *message,
1009                            guint32        serial)
1010 {
1011   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1012
1013   if (message->locked)
1014     {
1015       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1016       return;
1017     }
1018
1019   message->serial = serial;
1020 }
1021
1022 /* ---------------------------------------------------------------------------------------------------- */
1023
1024 /* TODO: need GI annotations to specify that any guchar value goes for header_field */
1025
1026 /**
1027  * g_dbus_message_get_header:
1028  * @message: A #GDBusMessage.
1029  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1030  *
1031  * Gets a header field on @message.
1032  *
1033  * Returns: A #GVariant with the value if the header was found, %NULL
1034  * otherwise. Do not free, it is owned by @message.
1035  *
1036  * Since: 2.26
1037  */
1038 GVariant *
1039 g_dbus_message_get_header (GDBusMessage             *message,
1040                            GDBusMessageHeaderField   header_field)
1041 {
1042   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1043   g_return_val_if_fail (header_field >=0 && header_field < 256, NULL);
1044   return g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
1045 }
1046
1047 /**
1048  * g_dbus_message_set_header:
1049  * @message: A #GDBusMessage.
1050  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1051  * @value: (allow-none): A #GVariant to set the header field or %NULL to clear the header field.
1052  *
1053  * Sets a header field on @message.
1054  *
1055  * If @value is floating, @message assumes ownership of @value.
1056  *
1057  * Since: 2.26
1058  */
1059 void
1060 g_dbus_message_set_header (GDBusMessage             *message,
1061                            GDBusMessageHeaderField   header_field,
1062                            GVariant                 *value)
1063 {
1064   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1065   g_return_if_fail (header_field >=0 && header_field < 256);
1066
1067   if (message->locked)
1068     {
1069       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1070       return;
1071     }
1072
1073   if (value == NULL)
1074     {
1075       g_hash_table_remove (message->headers, GUINT_TO_POINTER (header_field));
1076     }
1077   else
1078     {
1079       g_hash_table_insert (message->headers, GUINT_TO_POINTER (header_field), g_variant_ref_sink (value));
1080     }
1081 }
1082
1083 /**
1084  * g_dbus_message_get_header_fields:
1085  * @message: A #GDBusMessage.
1086  *
1087  * Gets an array of all header fields on @message that are set.
1088  *
1089  * Returns: (array zero-terminated=1): An array of header fields
1090  * terminated by %G_DBUS_MESSAGE_HEADER_FIELD_INVALID.  Each element
1091  * is a #guchar. Free with g_free().
1092  *
1093  * Since: 2.26
1094  */
1095 guchar *
1096 g_dbus_message_get_header_fields (GDBusMessage  *message)
1097 {
1098   GList *keys;
1099   guchar *ret;
1100   guint num_keys;
1101   GList *l;
1102   guint n;
1103
1104   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1105
1106   keys = g_hash_table_get_keys (message->headers);
1107   num_keys = g_list_length (keys);
1108   ret = g_new (guchar, num_keys + 1);
1109   for (l = keys, n = 0; l != NULL; l = l->next, n++)
1110     ret[n] = GPOINTER_TO_UINT (l->data);
1111   g_assert (n == num_keys);
1112   ret[n] = G_DBUS_MESSAGE_HEADER_FIELD_INVALID;
1113   g_list_free (keys);
1114
1115   return ret;
1116 }
1117
1118 /* ---------------------------------------------------------------------------------------------------- */
1119
1120 /**
1121  * g_dbus_message_get_body:
1122  * @message: A #GDBusMessage.
1123  *
1124  * Gets the body of a message.
1125  *
1126  * Returns: A #GVariant or %NULL if the body is empty. Do not free, it is owned by @message.
1127  *
1128  * Since: 2.26
1129  */
1130 GVariant *
1131 g_dbus_message_get_body (GDBusMessage  *message)
1132 {
1133   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1134   return message->body;
1135 }
1136
1137 /**
1138  * g_dbus_message_set_body:
1139  * @message: A #GDBusMessage.
1140  * @body: Either %NULL or a #GVariant that is a tuple.
1141  *
1142  * Sets the body @message. As a side-effect the
1143  * %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field is set to the
1144  * type string of @body (or cleared if @body is %NULL).
1145  *
1146  * If @body is floating, @message assumes ownership of @body.
1147  *
1148  * Since: 2.26
1149  */
1150 void
1151 g_dbus_message_set_body (GDBusMessage  *message,
1152                          GVariant      *body)
1153 {
1154   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1155   g_return_if_fail ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE));
1156
1157   if (message->locked)
1158     {
1159       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1160       return;
1161     }
1162
1163   if (message->body != NULL)
1164     g_variant_unref (message->body);
1165   if (body == NULL)
1166     {
1167       message->body = NULL;
1168       g_dbus_message_set_signature (message, NULL);
1169     }
1170   else
1171     {
1172       const gchar *type_string;
1173       gsize type_string_len;
1174       gchar *signature;
1175
1176       message->body = g_variant_ref_sink (body);
1177
1178       type_string = g_variant_get_type_string (body);
1179       type_string_len = strlen (type_string);
1180       g_assert (type_string_len >= 2);
1181       signature = g_strndup (type_string + 1, type_string_len - 2);
1182       g_dbus_message_set_signature (message, signature);
1183       g_free (signature);
1184     }
1185 }
1186
1187 /* ---------------------------------------------------------------------------------------------------- */
1188
1189 #ifdef G_OS_UNIX
1190 /**
1191  * g_dbus_message_get_unix_fd_list:
1192  * @message: A #GDBusMessage.
1193  *
1194  * Gets the UNIX file descriptors associated with @message, if any.
1195  *
1196  * This method is only available on UNIX.
1197  *
1198  * Returns: (transfer none):A #GUnixFDList or %NULL if no file descriptors are
1199  * associated. Do not free, this object is owned by @message.
1200  *
1201  * Since: 2.26
1202  */
1203 GUnixFDList *
1204 g_dbus_message_get_unix_fd_list (GDBusMessage  *message)
1205 {
1206   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1207   return message->fd_list;
1208 }
1209
1210 /**
1211  * g_dbus_message_set_unix_fd_list:
1212  * @message: A #GDBusMessage.
1213  * @fd_list: (allow-none): A #GUnixFDList or %NULL.
1214  *
1215  * Sets the UNIX file descriptors associated with @message. As a
1216  * side-effect the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header
1217  * field is set to the number of fds in @fd_list (or cleared if
1218  * @fd_list is %NULL).
1219  *
1220  * This method is only available on UNIX.
1221  *
1222  * Since: 2.26
1223  */
1224 void
1225 g_dbus_message_set_unix_fd_list (GDBusMessage  *message,
1226                                  GUnixFDList   *fd_list)
1227 {
1228   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1229   g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
1230
1231   if (message->locked)
1232     {
1233       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1234       return;
1235     }
1236
1237   if (message->fd_list != NULL)
1238     g_object_unref (message->fd_list);
1239   if (fd_list != NULL)
1240     {
1241       message->fd_list = g_object_ref (fd_list);
1242       g_dbus_message_set_num_unix_fds (message, g_unix_fd_list_get_length (fd_list));
1243     }
1244   else
1245     {
1246       message->fd_list = NULL;
1247       g_dbus_message_set_num_unix_fds (message, 0);
1248     }
1249 }
1250 #endif
1251
1252 /* ---------------------------------------------------------------------------------------------------- */
1253
1254 static gboolean
1255 validate_headers (GDBusMessage  *message,
1256                   GError       **error)
1257 {
1258   gboolean ret;
1259
1260   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1261   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1262
1263   ret = FALSE;
1264
1265   switch (message->type)
1266     {
1267     case G_DBUS_MESSAGE_TYPE_INVALID:
1268       g_set_error_literal (error,
1269                            G_IO_ERROR,
1270                            G_IO_ERROR_INVALID_ARGUMENT,
1271                            _("type is INVALID"));
1272       goto out;
1273       break;
1274
1275     case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
1276       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1277           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1278         {
1279           g_set_error_literal (error,
1280                                G_IO_ERROR,
1281                                G_IO_ERROR_INVALID_ARGUMENT,
1282                                _("METHOD_CALL message: PATH or MEMBER header field is missing"));
1283           goto out;
1284         }
1285       break;
1286
1287     case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
1288       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1289         {
1290           g_set_error_literal (error,
1291                                G_IO_ERROR,
1292                                G_IO_ERROR_INVALID_ARGUMENT,
1293                                _("METHOD_RETURN message: REPLY_SERIAL header field is missing"));
1294           goto out;
1295         }
1296       break;
1297
1298     case G_DBUS_MESSAGE_TYPE_ERROR:
1299       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME) == NULL ||
1300           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1301         {
1302           g_set_error_literal (error,
1303                                G_IO_ERROR,
1304                                G_IO_ERROR_INVALID_ARGUMENT,
1305                                _("ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing"));
1306           goto out;
1307         }
1308       break;
1309
1310     case G_DBUS_MESSAGE_TYPE_SIGNAL:
1311       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1312           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE) == NULL ||
1313           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1314         {
1315           g_set_error_literal (error,
1316                                G_IO_ERROR,
1317                                G_IO_ERROR_INVALID_ARGUMENT,
1318                                _("SIGNAL message: PATH, INTERFACE or MEMBER header field is missing"));
1319           goto out;
1320         }
1321       if (g_strcmp0 (g_dbus_message_get_path (message), "/org/freedesktop/DBus/Local") == 0)
1322         {
1323           g_set_error_literal (error,
1324                                G_IO_ERROR,
1325                                G_IO_ERROR_INVALID_ARGUMENT,
1326                                _("SIGNAL message: The PATH header field is using the reserved value /org/freedesktop/DBus/Local"));
1327           goto out;
1328         }
1329       if (g_strcmp0 (g_dbus_message_get_interface (message), "org.freedesktop.DBus.Local") == 0)
1330         {
1331           g_set_error_literal (error,
1332                                G_IO_ERROR,
1333                                G_IO_ERROR_INVALID_ARGUMENT,
1334                                _("SIGNAL message: The INTERFACE header field is using the reserved value org.freedesktop.DBus.Local"));
1335           goto out;
1336         }
1337       break;
1338
1339     default:
1340       /* hitherto unknown type - nothing to check */
1341       break;
1342     }
1343
1344   ret = TRUE;
1345
1346  out:
1347   g_assert (ret || (error == NULL || *error != NULL));
1348   return ret;
1349 }
1350
1351 /* ---------------------------------------------------------------------------------------------------- */
1352
1353 static gboolean
1354 ensure_input_padding (GMemoryBuffer         *buf,
1355                       gsize                 padding_size,
1356                       GError              **error)
1357 {
1358   gsize offset;
1359   gsize wanted_offset;
1360
1361   offset = buf->pos;
1362   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1363   buf->pos = wanted_offset;
1364   return TRUE;
1365 }
1366
1367 static const gchar *
1368 read_string (GMemoryBuffer          *mbuf,
1369              gsize                  len,
1370              GError               **error)
1371 {
1372   gchar *str;
1373   const gchar *end_valid;
1374
1375   if (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1376     {
1377       mbuf->pos = mbuf->valid_len;
1378       /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1379       g_set_error (error,
1380                    G_IO_ERROR,
1381                    G_IO_ERROR_INVALID_ARGUMENT,
1382                    g_dngettext (GETTEXT_PACKAGE,
1383                                 "Wanted to read %lu byte but only got %lu",
1384                                 "Wanted to read %lu bytes but only got %lu",
1385                                 (gulong)len),
1386                                 (gulong)len,
1387                    (gulong)(mbuf->valid_len - mbuf->pos));
1388       mbuf->pos = mbuf->valid_len;
1389       return NULL;
1390     }
1391
1392   if (mbuf->data[mbuf->pos + len] != '\0')
1393     {
1394       str = g_strndup (mbuf->data + mbuf->pos, len);
1395       g_set_error (error,
1396                    G_IO_ERROR,
1397                    G_IO_ERROR_INVALID_ARGUMENT,
1398                    _("Expected NUL byte after the string '%s' but found byte %d"),
1399                    str, mbuf->data[mbuf->pos + len]);
1400       g_free (str);
1401       mbuf->pos += len + 1;
1402       return NULL;
1403     }
1404
1405   str = mbuf->data + mbuf->pos;
1406   mbuf->pos += len + 1;
1407
1408   if (!g_utf8_validate (str, -1, &end_valid))
1409     {
1410       gint offset;
1411       gchar *valid_str;
1412       offset = (gint) (end_valid - str);
1413       valid_str = g_strndup (str, offset);
1414       g_set_error (error,
1415                    G_IO_ERROR,
1416                    G_IO_ERROR_INVALID_ARGUMENT,
1417                    _("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
1418                      "The valid UTF-8 string up until that point was '%s'"),
1419                    offset,
1420                    (gint) len,
1421                    valid_str);
1422       g_free (valid_str);
1423       return NULL;
1424     }
1425
1426   return str;
1427 }
1428
1429 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
1430
1431 /* returns a non-floating GVariant! */
1432 static GVariant *
1433 parse_value_from_blob (GMemoryBuffer          *buf,
1434                        const GVariantType    *type,
1435                        gboolean               just_align,
1436                        guint                  indent,
1437                        GError               **error)
1438 {
1439   GVariant *ret;
1440   GError *local_error;
1441   gboolean is_leaf;
1442   const gchar *type_string;
1443
1444   type_string = g_variant_type_peek_string (type);
1445
1446 #ifdef DEBUG_SERIALIZER
1447     {
1448       gchar *s;
1449       s = g_variant_type_dup_string (type);
1450       g_print ("%*s%s type %s from offset 0x%04x",
1451                indent, "",
1452                just_align ? "Aligning" : "Reading",
1453                s,
1454                (gint) g_seekable_tell (G_SEEKABLE (buf)));
1455       g_free (s);
1456     }
1457 #endif /* DEBUG_SERIALIZER */
1458
1459   ret = NULL;
1460
1461   is_leaf = TRUE;
1462   local_error = NULL;
1463   switch (type_string[0])
1464     {
1465     case 'b': /* G_VARIANT_TYPE_BOOLEAN */
1466       if (!ensure_input_padding (buf, 4, &local_error))
1467         goto fail;
1468       if (!just_align)
1469         {
1470           gboolean v;
1471           v = g_memory_buffer_read_uint32 (buf, &local_error);
1472           if (local_error != NULL)
1473             goto fail;
1474           ret = g_variant_new_boolean (v);
1475         }
1476       break;
1477
1478     case 'y': /* G_VARIANT_TYPE_BYTE */
1479       if (!just_align)
1480         {
1481           guchar v;
1482           v = g_memory_buffer_read_byte (buf, &local_error);
1483           if (local_error != NULL)
1484             goto fail;
1485           ret = g_variant_new_byte (v);
1486         }
1487       break;
1488
1489     case 'n': /* G_VARIANT_TYPE_INT16 */
1490       if (!ensure_input_padding (buf, 2, &local_error))
1491         goto fail;
1492       if (!just_align)
1493         {
1494           gint16 v;
1495           v = g_memory_buffer_read_int16 (buf, &local_error);
1496           if (local_error != NULL)
1497             goto fail;
1498           ret = g_variant_new_int16 (v);
1499         }
1500       break;
1501
1502     case 'q': /* G_VARIANT_TYPE_UINT16 */
1503       if (!ensure_input_padding (buf, 2, &local_error))
1504         goto fail;
1505       if (!just_align)
1506         {
1507           guint16 v;
1508           v = g_memory_buffer_read_uint16 (buf, &local_error);
1509           if (local_error != NULL)
1510             goto fail;
1511           ret = g_variant_new_uint16 (v);
1512         }
1513       break;
1514
1515     case 'i': /* G_VARIANT_TYPE_INT32 */
1516       if (!ensure_input_padding (buf, 4, &local_error))
1517         goto fail;
1518       if (!just_align)
1519         {
1520           gint32 v;
1521           v = g_memory_buffer_read_int32 (buf, &local_error);
1522           if (local_error != NULL)
1523             goto fail;
1524           ret = g_variant_new_int32 (v);
1525         }
1526       break;
1527
1528     case 'u': /* G_VARIANT_TYPE_UINT32 */
1529       if (!ensure_input_padding (buf, 4, &local_error))
1530         goto fail;
1531       if (!just_align)
1532         {
1533           guint32 v;
1534           v = g_memory_buffer_read_uint32 (buf, &local_error);
1535           if (local_error != NULL)
1536             goto fail;
1537           ret = g_variant_new_uint32 (v);
1538         }
1539       break;
1540
1541     case 'x': /* G_VARIANT_TYPE_INT64 */
1542       if (!ensure_input_padding (buf, 8, &local_error))
1543         goto fail;
1544       if (!just_align)
1545         {
1546           gint64 v;
1547           v = g_memory_buffer_read_int64 (buf, &local_error);
1548           if (local_error != NULL)
1549             goto fail;
1550           ret = g_variant_new_int64 (v);
1551         }
1552       break;
1553
1554     case 't': /* G_VARIANT_TYPE_UINT64 */
1555       if (!ensure_input_padding (buf, 8, &local_error))
1556         goto fail;
1557       if (!just_align)
1558         {
1559           guint64 v;
1560           v = g_memory_buffer_read_uint64 (buf, &local_error);
1561           if (local_error != NULL)
1562             goto fail;
1563           ret = g_variant_new_uint64 (v);
1564         }
1565       break;
1566
1567     case 'd': /* G_VARIANT_TYPE_DOUBLE */
1568       if (!ensure_input_padding (buf, 8, &local_error))
1569         goto fail;
1570       if (!just_align)
1571         {
1572           union {
1573             guint64 v_uint64;
1574             gdouble v_double;
1575           } u;
1576           G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
1577           u.v_uint64 = g_memory_buffer_read_uint64 (buf, &local_error);
1578           if (local_error != NULL)
1579             goto fail;
1580           ret = g_variant_new_double (u.v_double);
1581         }
1582       break;
1583
1584     case 's': /* G_VARIANT_TYPE_STRING */
1585       if (!ensure_input_padding (buf, 4, &local_error))
1586         goto fail;
1587       if (!just_align)
1588         {
1589           guint32 len;
1590           const gchar *v;
1591           len = g_memory_buffer_read_uint32 (buf, &local_error);
1592           if (local_error != NULL)
1593             goto fail;
1594           v = read_string (buf, (gsize) len, &local_error);
1595           if (v == NULL)
1596             goto fail;
1597           ret = g_variant_new_string (v);
1598         }
1599       break;
1600
1601     case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
1602       if (!ensure_input_padding (buf, 4, &local_error))
1603         goto fail;
1604       if (!just_align)
1605         {
1606           guint32 len;
1607           const gchar *v;
1608           len = g_memory_buffer_read_uint32 (buf, &local_error);
1609           if (local_error != NULL)
1610             goto fail;
1611           v = read_string (buf, (gsize) len, &local_error);
1612           if (v == NULL)
1613             goto fail;
1614           if (!g_variant_is_object_path (v))
1615             {
1616               g_set_error (&local_error,
1617                            G_IO_ERROR,
1618                            G_IO_ERROR_INVALID_ARGUMENT,
1619                            _("Parsed value '%s' is not a valid D-Bus object path"),
1620                            v);
1621               goto fail;
1622             }
1623           ret = g_variant_new_object_path (v);
1624         }
1625       break;
1626
1627     case 'g': /* G_VARIANT_TYPE_SIGNATURE */
1628       if (!just_align)
1629         {
1630           guchar len;
1631           const gchar *v;
1632           len = g_memory_buffer_read_byte (buf, &local_error);
1633           if (local_error != NULL)
1634             goto fail;
1635           v = read_string (buf, (gsize) len, &local_error);
1636           if (v == NULL)
1637             goto fail;
1638           if (!g_variant_is_signature (v))
1639             {
1640               g_set_error (&local_error,
1641                            G_IO_ERROR,
1642                            G_IO_ERROR_INVALID_ARGUMENT,
1643                            _("Parsed value '%s' is not a valid D-Bus signature"),
1644                        v);
1645               goto fail;
1646             }
1647           ret = g_variant_new_signature (v);
1648         }
1649       break;
1650
1651     case 'h': /* G_VARIANT_TYPE_HANDLE */
1652       if (!ensure_input_padding (buf, 4, &local_error))
1653         goto fail;
1654       if (!just_align)
1655         {
1656           gint32 v;
1657           v = g_memory_buffer_read_int32 (buf, &local_error);
1658           if (local_error != NULL)
1659             goto fail;
1660           ret = g_variant_new_handle (v);
1661         }
1662       break;
1663
1664     case 'a': /* G_VARIANT_TYPE_ARRAY */
1665       if (!ensure_input_padding (buf, 4, &local_error))
1666         goto fail;
1667
1668       /* If we are only aligning for this array type, it is the child type of
1669        * another array, which is empty. So, we do not need to add padding for
1670        * this nonexistent array's elements: we only need to align for this
1671        * array itself (4 bytes). See
1672        * <https://bugzilla.gnome.org/show_bug.cgi?id=673612>.
1673        */
1674       if (!just_align)
1675         {
1676           guint32 array_len;
1677           goffset offset;
1678           goffset target;
1679           const GVariantType *element_type;
1680           GVariantBuilder builder;
1681
1682           array_len = g_memory_buffer_read_uint32 (buf, &local_error);
1683           if (local_error != NULL)
1684             goto fail;
1685
1686           is_leaf = FALSE;
1687 #ifdef DEBUG_SERIALIZER
1688           g_print (": array spans 0x%04x bytes\n", array_len);
1689 #endif /* DEBUG_SERIALIZER */
1690
1691           if (array_len > (2<<26))
1692             {
1693               /* G_GUINT32_FORMAT doesn't work with gettext, so use u */
1694               g_set_error (&local_error,
1695                            G_IO_ERROR,
1696                            G_IO_ERROR_INVALID_ARGUMENT,
1697                            g_dngettext (GETTEXT_PACKAGE,
1698                                         "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB).",
1699                                         "Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB).",
1700                                         array_len),
1701                            array_len);
1702               goto fail;
1703             }
1704
1705           g_variant_builder_init (&builder, type);
1706           element_type = g_variant_type_element (type);
1707
1708           if (array_len == 0)
1709             {
1710               GVariant *item;
1711               item = parse_value_from_blob (buf,
1712                                             element_type,
1713                                             TRUE,
1714                                             indent + 2,
1715                                             NULL);
1716               g_assert (item == NULL);
1717             }
1718           else
1719             {
1720               /* TODO: optimize array of primitive types */
1721               offset = buf->pos;
1722               target = offset + array_len;
1723               while (offset < target)
1724                 {
1725                   GVariant *item;
1726                   item = parse_value_from_blob (buf,
1727                                                 element_type,
1728                                                 FALSE,
1729                                                 indent + 2,
1730                                                 &local_error);
1731                   if (item == NULL)
1732                     {
1733                       g_variant_builder_clear (&builder);
1734                       goto fail;
1735                     }
1736                   g_variant_builder_add_value (&builder, item);
1737                   g_variant_unref (item);
1738                   offset = buf->pos;
1739                 }
1740             }
1741
1742           ret = g_variant_builder_end (&builder);
1743         }
1744       break;
1745
1746     default:
1747       if (g_variant_type_is_dict_entry (type))
1748         {
1749           const GVariantType *key_type;
1750           const GVariantType *value_type;
1751           GVariant *key;
1752           GVariant *value;
1753
1754           if (!ensure_input_padding (buf, 8, &local_error))
1755             goto fail;
1756
1757           is_leaf = FALSE;
1758 #ifdef DEBUG_SERIALIZER
1759           g_print ("\n");
1760 #endif /* DEBUG_SERIALIZER */
1761
1762           if (!just_align)
1763             {
1764               key_type = g_variant_type_key (type);
1765               key = parse_value_from_blob (buf,
1766                                            key_type,
1767                                            FALSE,
1768                                            indent + 2,
1769                                            &local_error);
1770               if (key == NULL)
1771                 goto fail;
1772               value_type = g_variant_type_value (type);
1773               value = parse_value_from_blob (buf,
1774                                              value_type,
1775                                              FALSE,
1776                                              indent + 2,
1777                                              &local_error);
1778               if (value == NULL)
1779                 {
1780                   g_variant_unref (key);
1781                   goto fail;
1782                 }
1783               ret = g_variant_new_dict_entry (key, value);
1784               g_variant_unref (key);
1785               g_variant_unref (value);
1786             }
1787         }
1788       else if (g_variant_type_is_tuple (type))
1789         {
1790           if (!ensure_input_padding (buf, 8, &local_error))
1791             goto fail;
1792
1793           is_leaf = FALSE;
1794 #ifdef DEBUG_SERIALIZER
1795           g_print ("\n");
1796 #endif /* DEBUG_SERIALIZER */
1797
1798           if (!just_align)
1799             {
1800               const GVariantType *element_type;
1801               GVariantBuilder builder;
1802
1803               g_variant_builder_init (&builder, type);
1804               element_type = g_variant_type_first (type);
1805               while (element_type != NULL)
1806                 {
1807                   GVariant *item;
1808                   item = parse_value_from_blob (buf,
1809                                                 element_type,
1810                                                 FALSE,
1811                                                 indent + 2,
1812                                                 &local_error);
1813                   if (item == NULL)
1814                     {
1815                       g_variant_builder_clear (&builder);
1816                       goto fail;
1817                     }
1818                   g_variant_builder_add_value (&builder, item);
1819                   g_variant_unref (item);
1820
1821                   element_type = g_variant_type_next (element_type);
1822                 }
1823               ret = g_variant_builder_end (&builder);
1824             }
1825         }
1826       else if (g_variant_type_is_variant (type))
1827         {
1828           is_leaf = FALSE;
1829 #ifdef DEBUG_SERIALIZER
1830           g_print ("\n");
1831 #endif /* DEBUG_SERIALIZER */
1832
1833           if (!just_align)
1834             {
1835               guchar siglen;
1836               const gchar *sig;
1837               GVariantType *variant_type;
1838               GVariant *value;
1839
1840               siglen = g_memory_buffer_read_byte (buf, &local_error);
1841               if (local_error != NULL)
1842                 goto fail;
1843               sig = read_string (buf, (gsize) siglen, &local_error);
1844               if (sig == NULL)
1845                 goto fail;
1846               if (!g_variant_is_signature (sig))
1847                 {
1848                   g_set_error (&local_error,
1849                                G_IO_ERROR,
1850                                G_IO_ERROR_INVALID_ARGUMENT,
1851                                _("Parsed value '%s' for variant is not a valid D-Bus signature"),
1852                                sig);
1853                   goto fail;
1854                 }
1855               variant_type = g_variant_type_new (sig);
1856               value = parse_value_from_blob (buf,
1857                                              variant_type,
1858                                              FALSE,
1859                                              indent + 2,
1860                                              &local_error);
1861               g_variant_type_free (variant_type);
1862               if (value == NULL)
1863                 goto fail;
1864               ret = g_variant_new_variant (value);
1865               g_variant_unref (value);
1866             }
1867         }
1868       else
1869         {
1870           gchar *s;
1871           s = g_variant_type_dup_string (type);
1872           g_set_error (&local_error,
1873                        G_IO_ERROR,
1874                        G_IO_ERROR_INVALID_ARGUMENT,
1875                        _("Error deserializing GVariant with type string '%s' from the D-Bus wire format"),
1876                        s);
1877           g_free (s);
1878           goto fail;
1879         }
1880       break;
1881     }
1882
1883   g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
1884
1885 #ifdef DEBUG_SERIALIZER
1886   if (ret != NULL)
1887     {
1888       if (is_leaf)
1889         {
1890           gchar *s;
1891           if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1892             {
1893               s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
1894             }
1895           else
1896             {
1897               s = g_variant_print (ret, FALSE);
1898             }
1899           g_print (": %s\n", s);
1900           g_free (s);
1901         }
1902     }
1903 #else
1904   is_leaf = is_leaf; /* To avoid -Wunused-but-set-variable */
1905 #endif /* DEBUG_SERIALIZER */
1906
1907   /* sink the reference */
1908   if (ret != NULL)
1909     {
1910       g_assert (g_variant_is_floating (ret));
1911       g_variant_ref_sink (ret);
1912     }
1913   return ret;
1914
1915  fail:
1916 #ifdef DEBUG_SERIALIZER
1917   g_print ("\n"
1918            "%*sFAILURE: %s (%s, %d)\n",
1919            indent, "",
1920            local_error->message,
1921            g_quark_to_string (local_error->domain),
1922            local_error->code);
1923 #endif /* DEBUG_SERIALIZER */
1924   g_propagate_error (error, local_error);
1925   return NULL;
1926 }
1927
1928 /* ---------------------------------------------------------------------------------------------------- */
1929
1930 /* message_header must be at least 16 bytes */
1931
1932 /**
1933  * g_dbus_message_bytes_needed:
1934  * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1935  * @blob_len: The length of @blob (must be at least 16).
1936  * @error: Return location for error or %NULL.
1937  *
1938  * Utility function to calculate how many bytes are needed to
1939  * completely deserialize the D-Bus message stored at @blob.
1940  *
1941  * Returns: Number of bytes needed or -1 if @error is set (e.g. if
1942  * @blob contains invalid data or not enough data is available to
1943  * determine the size).
1944  *
1945  * Since: 2.26
1946  */
1947 gssize
1948 g_dbus_message_bytes_needed (guchar                *blob,
1949                              gsize                  blob_len,
1950                              GError               **error)
1951 {
1952   gssize ret;
1953
1954   ret = -1;
1955
1956   g_return_val_if_fail (blob != NULL, -1);
1957   g_return_val_if_fail (error == NULL || *error == NULL, -1);
1958   g_return_val_if_fail (blob_len >= 16, -1);
1959
1960   if (blob[0] == 'l')
1961     {
1962       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1963       ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
1964       /* round up so it's a multiple of 8 */
1965       ret = 8 * ((ret + 7)/8);
1966       /* finally add the body size */
1967       ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
1968     }
1969   else if (blob[0] == 'B')
1970     {
1971       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1972       ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
1973       /* round up so it's a multiple of 8 */
1974       ret = 8 * ((ret + 7)/8);
1975       /* finally add the body size */
1976       ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
1977     }
1978   else
1979     {
1980       g_set_error (error,
1981                    G_IO_ERROR,
1982                    G_IO_ERROR_INVALID_ARGUMENT,
1983                    "Unable to determine message blob length - given blob is malformed");
1984     }
1985
1986   if (ret > (2<<27))
1987     {
1988       g_set_error (error,
1989                    G_IO_ERROR,
1990                    G_IO_ERROR_INVALID_ARGUMENT,
1991                    "Blob indicates that message exceeds maximum message length (128MiB)");
1992       ret = -1;
1993     }
1994
1995   return ret;
1996 }
1997
1998 /* ---------------------------------------------------------------------------------------------------- */
1999
2000 /**
2001  * g_dbus_message_new_from_blob:
2002  * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
2003  * @blob_len: The length of @blob.
2004  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2005  * @error: Return location for error or %NULL.
2006  *
2007  * Creates a new #GDBusMessage from the data stored at @blob. The byte
2008  * order that the message was in can be retrieved using
2009  * g_dbus_message_get_byte_order().
2010  *
2011  * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
2012  * g_object_unref().
2013  *
2014  * Since: 2.26
2015  */
2016 GDBusMessage *
2017 g_dbus_message_new_from_blob (guchar                *blob,
2018                               gsize                  blob_len,
2019                               GDBusCapabilityFlags   capabilities,
2020                               GError               **error)
2021 {
2022   gboolean ret;
2023   GMemoryBuffer mbuf;
2024   GDBusMessage *message;
2025   guchar endianness;
2026   guchar major_protocol_version;
2027   guint32 message_body_len;
2028   GVariant *headers;
2029   GVariant *item;
2030   GVariantIter iter;
2031   GVariant *signature;
2032
2033   /* TODO: check against @capabilities */
2034
2035   ret = FALSE;
2036
2037   g_return_val_if_fail (blob != NULL, NULL);
2038   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2039   g_return_val_if_fail (blob_len >= 12, NULL);
2040
2041   message = g_dbus_message_new ();
2042
2043   memset (&mbuf, 0, sizeof (mbuf));
2044   mbuf.data = (gchar *)blob;
2045   mbuf.len = mbuf.valid_len = blob_len;
2046
2047   endianness = g_memory_buffer_read_byte (&mbuf, NULL);
2048   switch (endianness)
2049     {
2050     case 'l':
2051       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2052       message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
2053       break;
2054     case 'B':
2055       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2056       message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
2057       break;
2058     default:
2059       g_set_error (error,
2060                    G_IO_ERROR,
2061                    G_IO_ERROR_INVALID_ARGUMENT,
2062                    _("Invalid endianness value. Expected 0x6c ('l') or 0x42 ('B') but found value 0x%02x"),
2063                    endianness);
2064       goto out;
2065     }
2066
2067   message->type = g_memory_buffer_read_byte (&mbuf, NULL);
2068   message->flags = g_memory_buffer_read_byte (&mbuf, NULL);
2069   major_protocol_version = g_memory_buffer_read_byte (&mbuf, NULL);
2070   if (major_protocol_version != 1)
2071     {
2072       g_set_error (error,
2073                    G_IO_ERROR,
2074                    G_IO_ERROR_INVALID_ARGUMENT,
2075                    _("Invalid major protocol version. Expected 1 but found %d"),
2076                    major_protocol_version);
2077       goto out;
2078     }
2079   message_body_len = g_memory_buffer_read_uint32 (&mbuf, NULL);
2080   message->serial = g_memory_buffer_read_uint32 (&mbuf, NULL);
2081
2082 #ifdef DEBUG_SERIALIZER
2083   g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2084   {
2085     gchar *s;
2086     s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
2087     g_print ("%s\n", s);
2088     g_free (s);
2089   }
2090 #endif /* DEBUG_SERIALIZER */
2091
2092 #ifdef DEBUG_SERIALIZER
2093   g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2094 #endif /* DEBUG_SERIALIZER */
2095   headers = parse_value_from_blob (&mbuf,
2096                                    G_VARIANT_TYPE ("a{yv}"),
2097                                    FALSE,
2098                                    2,
2099                                    error);
2100   if (headers == NULL)
2101     goto out;
2102   g_variant_iter_init (&iter, headers);
2103   while ((item = g_variant_iter_next_value (&iter)) != NULL)
2104     {
2105       guchar header_field;
2106       GVariant *value;
2107       g_variant_get (item,
2108                      "{yv}",
2109                      &header_field,
2110                      &value);
2111       g_dbus_message_set_header (message, header_field, value);
2112       g_variant_unref (value);
2113       g_variant_unref (item);
2114     }
2115   g_variant_unref (headers);
2116
2117   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2118   if (signature != NULL)
2119     {
2120       const gchar *signature_str;
2121       gsize signature_str_len;
2122
2123       signature_str = g_variant_get_string (signature, &signature_str_len);
2124
2125       /* signature but no body */
2126       if (message_body_len == 0 && signature_str_len > 0)
2127         {
2128           g_set_error (error,
2129                        G_IO_ERROR,
2130                        G_IO_ERROR_INVALID_ARGUMENT,
2131                        _("Signature header with signature '%s' found but message body is empty"),
2132                        signature_str);
2133           goto out;
2134         }
2135       else if (signature_str_len > 0)
2136         {
2137           GVariantType *variant_type;
2138           gchar *tupled_signature_str;
2139
2140           if (!g_variant_is_signature (signature_str))
2141             {
2142               g_set_error (error,
2143                            G_IO_ERROR,
2144                            G_IO_ERROR_INVALID_ARGUMENT,
2145                            _("Parsed value '%s' is not a valid D-Bus signature (for body)"),
2146                            signature_str);
2147               goto out;
2148             }
2149           tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2150           variant_type = g_variant_type_new (tupled_signature_str);
2151           g_free (tupled_signature_str);
2152 #ifdef DEBUG_SERIALIZER
2153           g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2154 #endif /* DEBUG_SERIALIZER */
2155           message->body = parse_value_from_blob (&mbuf,
2156                                                  variant_type,
2157                                                  FALSE,
2158                                                  2,
2159                                                  error);
2160           g_variant_type_free (variant_type);
2161           if (message->body == NULL)
2162             goto out;
2163         }
2164     }
2165   else
2166     {
2167       /* no signature, this is only OK if the body is empty */
2168       if (message_body_len != 0)
2169         {
2170           /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
2171           g_set_error (error,
2172                        G_IO_ERROR,
2173                        G_IO_ERROR_INVALID_ARGUMENT,
2174                        g_dngettext (GETTEXT_PACKAGE,
2175                                     "No signature header in message but the message body is %u byte",
2176                                     "No signature header in message but the message body is %u bytes",
2177                                     message_body_len),
2178                        message_body_len);
2179           goto out;
2180         }
2181     }
2182
2183   if (!validate_headers (message, error))
2184     {
2185       g_prefix_error (error, _("Cannot deserialize message: "));
2186       goto out;
2187     }
2188
2189   ret = TRUE;
2190
2191  out:
2192   if (ret)
2193     {
2194       return message;
2195     }
2196   else
2197     {
2198       if (message != NULL)
2199         g_object_unref (message);
2200       return NULL;
2201     }
2202 }
2203
2204 /* ---------------------------------------------------------------------------------------------------- */
2205
2206 static gsize
2207 ensure_output_padding (GMemoryBuffer  *mbuf,
2208                        gsize                 padding_size)
2209 {
2210   gsize offset;
2211   gsize wanted_offset;
2212   gsize padding_needed;
2213   guint n;
2214
2215   offset = mbuf->pos;
2216   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
2217   padding_needed = wanted_offset - offset;
2218
2219   for (n = 0; n < padding_needed; n++)
2220     g_memory_buffer_put_byte (mbuf, '\0');
2221
2222   return padding_needed;
2223 }
2224
2225 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
2226 static gboolean
2227 append_value_to_blob (GVariant             *value,
2228                       const GVariantType   *type,
2229                       GMemoryBuffer  *mbuf,
2230                       gsize                *out_padding_added,
2231                       GError              **error)
2232 {
2233   gsize padding_added;
2234   const gchar *type_string;
2235
2236   type_string = g_variant_type_peek_string (type);
2237
2238   padding_added = 0;
2239
2240   switch (type_string[0])
2241     {
2242     case 'b': /* G_VARIANT_TYPE_BOOLEAN */
2243       padding_added = ensure_output_padding (mbuf, 4);
2244       if (value != NULL)
2245         {
2246           gboolean v = g_variant_get_boolean (value);
2247           g_memory_buffer_put_uint32 (mbuf, v);
2248         }
2249       break;
2250
2251     case 'y': /* G_VARIANT_TYPE_BYTE */
2252       if (value != NULL)
2253         {
2254           guint8 v = g_variant_get_byte (value);
2255           g_memory_buffer_put_byte (mbuf, v);
2256         }
2257       break;
2258
2259     case 'n': /* G_VARIANT_TYPE_INT16 */
2260       padding_added = ensure_output_padding (mbuf, 2);
2261       if (value != NULL)
2262         {
2263           gint16 v = g_variant_get_int16 (value);
2264           g_memory_buffer_put_int16 (mbuf, v);
2265         }
2266       break;
2267
2268     case 'q': /* G_VARIANT_TYPE_UINT16 */
2269       padding_added = ensure_output_padding (mbuf, 2);
2270       if (value != NULL)
2271         {
2272           guint16 v = g_variant_get_uint16 (value);
2273           g_memory_buffer_put_uint16 (mbuf, v);
2274         }
2275       break;
2276
2277     case 'i': /* G_VARIANT_TYPE_INT32 */
2278       padding_added = ensure_output_padding (mbuf, 4);
2279       if (value != NULL)
2280         {
2281           gint32 v = g_variant_get_int32 (value);
2282           g_memory_buffer_put_int32 (mbuf, v);
2283         }
2284       break;
2285
2286     case 'u': /* G_VARIANT_TYPE_UINT32 */
2287       padding_added = ensure_output_padding (mbuf, 4);
2288       if (value != NULL)
2289         {
2290           guint32 v = g_variant_get_uint32 (value);
2291           g_memory_buffer_put_uint32 (mbuf, v);
2292         }
2293       break;
2294
2295     case 'x': /* G_VARIANT_TYPE_INT64 */
2296       padding_added = ensure_output_padding (mbuf, 8);
2297       if (value != NULL)
2298         {
2299           gint64 v = g_variant_get_int64 (value);
2300           g_memory_buffer_put_int64 (mbuf, v);
2301         }
2302       break;
2303
2304     case 't': /* G_VARIANT_TYPE_UINT64 */
2305       padding_added = ensure_output_padding (mbuf, 8);
2306       if (value != NULL)
2307         {
2308           guint64 v = g_variant_get_uint64 (value);
2309           g_memory_buffer_put_uint64 (mbuf, v);
2310         }
2311       break;
2312
2313     case 'd': /* G_VARIANT_TYPE_DOUBLE */
2314       padding_added = ensure_output_padding (mbuf, 8);
2315       if (value != NULL)
2316         {
2317           union {
2318             guint64 v_uint64;
2319             gdouble v_double;
2320           } u;
2321           G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
2322           u.v_double = g_variant_get_double (value);
2323           g_memory_buffer_put_uint64 (mbuf, u.v_uint64);
2324         }
2325       break;
2326
2327     case 's': /* G_VARIANT_TYPE_STRING */
2328       padding_added = ensure_output_padding (mbuf, 4);
2329       if (value != NULL)
2330         {
2331           gsize len;
2332           const gchar *v;
2333           const gchar *end;
2334           v = g_variant_get_string (value, &len);
2335           g_assert (g_utf8_validate (v, -1, &end) && (end == v + len));
2336           g_memory_buffer_put_uint32 (mbuf, len);
2337           g_memory_buffer_put_string (mbuf, v);
2338           g_memory_buffer_put_byte (mbuf, '\0');
2339         }
2340       break;
2341
2342     case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
2343       padding_added = ensure_output_padding (mbuf, 4);
2344       if (value != NULL)
2345         {
2346           gsize len;
2347           const gchar *v = g_variant_get_string (value, &len);
2348           g_assert (g_variant_is_object_path (v));
2349           g_memory_buffer_put_uint32 (mbuf, len);
2350           g_memory_buffer_put_string (mbuf, v);
2351           g_memory_buffer_put_byte (mbuf, '\0');
2352         }
2353       break;
2354
2355     case 'g': /* G_VARIANT_TYPE_SIGNATURE */
2356       if (value != NULL)
2357         {
2358           gsize len;
2359           const gchar *v = g_variant_get_string (value, &len);
2360           g_assert (g_variant_is_signature (v));
2361           g_memory_buffer_put_byte (mbuf, len);
2362           g_memory_buffer_put_string (mbuf, v);
2363           g_memory_buffer_put_byte (mbuf, '\0');
2364         }
2365       break;
2366
2367     case 'h': /* G_VARIANT_TYPE_HANDLE */
2368       padding_added = ensure_output_padding (mbuf, 4);
2369       if (value != NULL)
2370         {
2371           gint32 v = g_variant_get_handle (value);
2372           g_memory_buffer_put_int32 (mbuf, v);
2373         }
2374       break;
2375
2376     case 'a': /* G_VARIANT_TYPE_ARRAY */
2377       {
2378         GVariant *item;
2379         GVariantIter iter;
2380         goffset array_len_offset;
2381         goffset array_payload_begin_offset;
2382         goffset cur_offset;
2383         gsize array_len;
2384
2385         padding_added = ensure_output_padding (mbuf, 4);
2386         if (value != NULL)
2387           {
2388             /* array length - will be filled in later */
2389             array_len_offset = mbuf->valid_len;
2390             g_memory_buffer_put_uint32 (mbuf, 0xF00DFACE);
2391
2392             /* From the D-Bus spec:
2393              *
2394              *   "A UINT32 giving the length of the array data in bytes,
2395              *    followed by alignment padding to the alignment boundary of
2396              *    the array element type, followed by each array element. The
2397              *    array length is from the end of the alignment padding to
2398              *    the end of the last element, i.e. it does not include the
2399              *    padding after the length, or any padding after the last
2400              *    element."
2401              *
2402              * Thus, we need to count how much padding the first element
2403              * contributes and subtract that from the array length.
2404              */
2405             array_payload_begin_offset = mbuf->valid_len;
2406
2407             if (g_variant_n_children (value) == 0)
2408               {
2409                 gsize padding_added_for_item;
2410                 if (!append_value_to_blob (NULL,
2411                                            g_variant_type_element (type),
2412                                            mbuf,
2413                                            &padding_added_for_item,
2414                                            error))
2415                   goto fail;
2416                 array_payload_begin_offset += padding_added_for_item;
2417               }
2418             else
2419               {
2420                 guint n;
2421                 n = 0;
2422                 g_variant_iter_init (&iter, value);
2423                 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2424                   {
2425                     gsize padding_added_for_item;
2426                     if (!append_value_to_blob (item,
2427                                                g_variant_get_type (item),
2428                                                mbuf,
2429                                                &padding_added_for_item,
2430                                                error))
2431                       {
2432                         g_variant_unref (item);
2433                         goto fail;
2434                       }
2435                     g_variant_unref (item);
2436                     if (n == 0)
2437                       {
2438                         array_payload_begin_offset += padding_added_for_item;
2439                       }
2440                     n++;
2441                   }
2442               }
2443
2444             cur_offset = mbuf->valid_len;
2445             array_len = cur_offset - array_payload_begin_offset;
2446             mbuf->pos = array_len_offset;
2447
2448             g_memory_buffer_put_uint32 (mbuf, array_len);
2449             mbuf->pos = cur_offset;
2450           }
2451       }
2452       break;
2453
2454     default:
2455       if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
2456         {
2457           padding_added = ensure_output_padding (mbuf, 8);
2458           if (value != NULL)
2459             {
2460               GVariant *item;
2461               GVariantIter iter;
2462               g_variant_iter_init (&iter, value);
2463               while ((item = g_variant_iter_next_value (&iter)) != NULL)
2464                 {
2465                   if (!append_value_to_blob (item,
2466                                              g_variant_get_type (item),
2467                                              mbuf,
2468                                              NULL,
2469                                              error))
2470                     {
2471                       g_variant_unref (item);
2472                       goto fail;
2473                     }
2474                   g_variant_unref (item);
2475                 }
2476             }
2477         }
2478       else if (g_variant_type_is_variant (type))
2479         {
2480           if (value != NULL)
2481             {
2482               GVariant *child;
2483               const gchar *signature;
2484               child = g_variant_get_child_value (value, 0);
2485               signature = g_variant_get_type_string (child);
2486               g_memory_buffer_put_byte (mbuf, strlen (signature));
2487               g_memory_buffer_put_string (mbuf, signature);
2488               g_memory_buffer_put_byte (mbuf, '\0');
2489               if (!append_value_to_blob (child,
2490                                          g_variant_get_type (child),
2491                                          mbuf,
2492                                          NULL,
2493                                          error))
2494                 {
2495                   g_variant_unref (child);
2496                   goto fail;
2497                 }
2498               g_variant_unref (child);
2499             }
2500         }
2501       else
2502         {
2503           g_set_error (error,
2504                        G_IO_ERROR,
2505                        G_IO_ERROR_INVALID_ARGUMENT,
2506                        _("Error serializing GVariant with type string '%s' to the D-Bus wire format"),
2507                        g_variant_get_type_string (value));
2508           goto fail;
2509         }
2510       break;
2511     }
2512
2513   if (out_padding_added != NULL)
2514     *out_padding_added = padding_added;
2515
2516   return TRUE;
2517
2518  fail:
2519   return FALSE;
2520 }
2521
2522 static gboolean
2523 append_body_to_blob (GVariant             *value,
2524                      GMemoryBuffer  *mbuf,
2525                      GError              **error)
2526 {
2527   GVariant *item;
2528   GVariantIter iter;
2529
2530   if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
2531     {
2532       g_set_error (error,
2533                    G_IO_ERROR,
2534                    G_IO_ERROR_INVALID_ARGUMENT,
2535                    "Expected a tuple for the body of the GDBusMessage.");
2536       goto fail;
2537     }
2538
2539   g_variant_iter_init (&iter, value);
2540   while ((item = g_variant_iter_next_value (&iter)) != NULL)
2541     {
2542       if (!append_value_to_blob (item,
2543                                  g_variant_get_type (item),
2544                                  mbuf,
2545                                  NULL,
2546                                  error))
2547         {
2548           g_variant_unref (item);
2549           goto fail;
2550         }
2551       g_variant_unref (item);
2552     }
2553   return TRUE;
2554
2555  fail:
2556   return FALSE;
2557 }
2558
2559 /* ---------------------------------------------------------------------------------------------------- */
2560
2561 /**
2562  * g_dbus_message_to_blob:
2563  * @message: A #GDBusMessage.
2564  * @out_size: Return location for size of generated blob.
2565  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2566  * @error: Return location for error.
2567  *
2568  * Serializes @message to a blob. The byte order returned by
2569  * g_dbus_message_get_byte_order() will be used.
2570  *
2571  * Returns: (array length=out_size) (transfer full): A pointer to a
2572  * valid binary D-Bus message of @out_size bytes generated by @message
2573  * or %NULL if @error is set. Free with g_free().
2574  *
2575  * Since: 2.26
2576  */
2577 guchar *
2578 g_dbus_message_to_blob (GDBusMessage          *message,
2579                         gsize                 *out_size,
2580                         GDBusCapabilityFlags   capabilities,
2581                         GError               **error)
2582 {
2583   GMemoryBuffer mbuf;
2584   guchar *ret;
2585   gsize size;
2586   goffset body_len_offset;
2587   goffset body_start_offset;
2588   gsize body_size;
2589   GVariant *header_fields;
2590   GVariantBuilder builder;
2591   GHashTableIter hash_iter;
2592   gpointer key;
2593   GVariant *header_value;
2594   GVariant *signature;
2595   const gchar *signature_str;
2596   gint num_fds_in_message;
2597   gint num_fds_according_to_header;
2598
2599   /* TODO: check against @capabilities */
2600
2601   ret = NULL;
2602
2603   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2604   g_return_val_if_fail (out_size != NULL, NULL);
2605   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2606
2607   memset (&mbuf, 0, sizeof (mbuf));
2608   mbuf.len = MIN_ARRAY_SIZE;
2609   mbuf.data = g_malloc (mbuf.len);
2610
2611   mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN;
2612   switch (message->byte_order)
2613     {
2614     case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
2615       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2616       break;
2617     case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
2618       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2619       break;
2620     }
2621
2622   /* Core header */
2623   g_memory_buffer_put_byte (&mbuf, (guchar) message->byte_order);
2624   g_memory_buffer_put_byte (&mbuf, message->type);
2625   g_memory_buffer_put_byte (&mbuf, message->flags);
2626   g_memory_buffer_put_byte (&mbuf, 1); /* major protocol version */
2627   body_len_offset = mbuf.valid_len;
2628   /* body length - will be filled in later */
2629   g_memory_buffer_put_uint32 (&mbuf, 0xF00DFACE);
2630   g_memory_buffer_put_uint32 (&mbuf, message->serial);
2631
2632   num_fds_in_message = 0;
2633 #ifdef G_OS_UNIX
2634   if (message->fd_list != NULL)
2635     num_fds_in_message = g_unix_fd_list_get_length (message->fd_list);
2636 #endif
2637   num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
2638   if (num_fds_in_message != num_fds_according_to_header)
2639     {
2640       g_set_error (error,
2641                    G_IO_ERROR,
2642                    G_IO_ERROR_INVALID_ARGUMENT,
2643                    _("Message has %d file descriptors but the header field indicates %d file descriptors"),
2644                    num_fds_in_message,
2645                    num_fds_according_to_header);
2646       goto out;
2647     }
2648
2649   if (!validate_headers (message, error))
2650     {
2651       g_prefix_error (error, _("Cannot serialize message: "));
2652       goto out;
2653     }
2654
2655   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
2656   g_hash_table_iter_init (&hash_iter, message->headers);
2657   while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
2658     {
2659       g_variant_builder_add (&builder,
2660                              "{yv}",
2661                              (guchar) GPOINTER_TO_UINT (key),
2662                              header_value);
2663     }
2664   header_fields = g_variant_builder_end (&builder);
2665
2666   if (!append_value_to_blob (header_fields,
2667                              g_variant_get_type (header_fields),
2668                              &mbuf,
2669                              NULL,
2670                              error))
2671     {
2672       g_variant_unref (header_fields);
2673       goto out;
2674     }
2675   g_variant_unref (header_fields);
2676
2677   /* header size must be a multiple of 8 */
2678   ensure_output_padding (&mbuf, 8);
2679
2680   body_start_offset = mbuf.valid_len;
2681
2682   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2683   signature_str = NULL;
2684   if (signature != NULL)
2685       signature_str = g_variant_get_string (signature, NULL);
2686   if (message->body != NULL)
2687     {
2688       gchar *tupled_signature_str;
2689       tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2690       if (signature == NULL)
2691         {
2692           g_set_error (error,
2693                        G_IO_ERROR,
2694                        G_IO_ERROR_INVALID_ARGUMENT,
2695                        _("Message body has signature '%s' but there is no signature header"),
2696                        signature_str);
2697           g_free (tupled_signature_str);
2698           goto out;
2699         }
2700       else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
2701         {
2702           g_set_error (error,
2703                        G_IO_ERROR,
2704                        G_IO_ERROR_INVALID_ARGUMENT,
2705                        _("Message body has type signature '%s' but signature in the header field is '%s'"),
2706                        tupled_signature_str, g_variant_get_type_string (message->body));
2707           g_free (tupled_signature_str);
2708           goto out;
2709         }
2710       g_free (tupled_signature_str);
2711       if (!append_body_to_blob (message->body, &mbuf, error))
2712         goto out;
2713     }
2714   else
2715     {
2716       if (signature != NULL && strlen (signature_str) > 0)
2717         {
2718           g_set_error (error,
2719                        G_IO_ERROR,
2720                        G_IO_ERROR_INVALID_ARGUMENT,
2721                        _("Message body is empty but signature in the header field is '(%s)'"),
2722                        signature_str);
2723           goto out;
2724         }
2725     }
2726
2727   /* OK, we're done writing the message - set the body length */
2728   size = mbuf.valid_len;
2729   body_size = size - body_start_offset;
2730
2731   mbuf.pos = body_len_offset;
2732
2733   g_memory_buffer_put_uint32 (&mbuf, body_size);
2734
2735   *out_size = size;
2736   ret = (guchar *)mbuf.data;
2737
2738  out:
2739   return ret;
2740 }
2741
2742 /* ---------------------------------------------------------------------------------------------------- */
2743
2744 static guint32
2745 get_uint32_header (GDBusMessage            *message,
2746                    GDBusMessageHeaderField  header_field)
2747 {
2748   GVariant *value;
2749   guint32 ret;
2750
2751   ret = 0;
2752   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2753   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
2754     ret = g_variant_get_uint32 (value);
2755
2756   return ret;
2757 }
2758
2759 static const gchar *
2760 get_string_header (GDBusMessage            *message,
2761                    GDBusMessageHeaderField  header_field)
2762 {
2763   GVariant *value;
2764   const gchar *ret;
2765
2766   ret = NULL;
2767   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2768   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
2769     ret = g_variant_get_string (value, NULL);
2770
2771   return ret;
2772 }
2773
2774 static const gchar *
2775 get_object_path_header (GDBusMessage            *message,
2776                         GDBusMessageHeaderField  header_field)
2777 {
2778   GVariant *value;
2779   const gchar *ret;
2780
2781   ret = NULL;
2782   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2783   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
2784     ret = g_variant_get_string (value, NULL);
2785
2786   return ret;
2787 }
2788
2789 static const gchar *
2790 get_signature_header (GDBusMessage            *message,
2791                       GDBusMessageHeaderField  header_field)
2792 {
2793   GVariant *value;
2794   const gchar *ret;
2795
2796   ret = NULL;
2797   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2798   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
2799     ret = g_variant_get_string (value, NULL);
2800
2801   return ret;
2802 }
2803
2804 /* ---------------------------------------------------------------------------------------------------- */
2805
2806 static void
2807 set_uint32_header (GDBusMessage             *message,
2808                    GDBusMessageHeaderField   header_field,
2809                    guint32                   value)
2810 {
2811   g_dbus_message_set_header (message,
2812                              header_field,
2813                              g_variant_new_uint32 (value));
2814 }
2815
2816 static void
2817 set_string_header (GDBusMessage             *message,
2818                    GDBusMessageHeaderField   header_field,
2819                    const gchar              *value)
2820 {
2821   g_dbus_message_set_header (message,
2822                              header_field,
2823                              value == NULL ? NULL : g_variant_new_string (value));
2824 }
2825
2826 static void
2827 set_object_path_header (GDBusMessage             *message,
2828                         GDBusMessageHeaderField   header_field,
2829                         const gchar              *value)
2830 {
2831   g_dbus_message_set_header (message,
2832                              header_field,
2833                              value == NULL ? NULL : g_variant_new_object_path (value));
2834 }
2835
2836 static void
2837 set_signature_header (GDBusMessage             *message,
2838                       GDBusMessageHeaderField   header_field,
2839                       const gchar              *value)
2840 {
2841   g_dbus_message_set_header (message,
2842                              header_field,
2843                              value == NULL ? NULL : g_variant_new_signature (value));
2844 }
2845
2846 /* ---------------------------------------------------------------------------------------------------- */
2847
2848 /**
2849  * g_dbus_message_get_reply_serial:
2850  * @message: A #GDBusMessage.
2851  *
2852  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2853  *
2854  * Returns: The value.
2855  *
2856  * Since: 2.26
2857  */
2858 guint32
2859 g_dbus_message_get_reply_serial (GDBusMessage  *message)
2860 {
2861   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2862   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
2863 }
2864
2865 /**
2866  * g_dbus_message_set_reply_serial:
2867  * @message: A #GDBusMessage.
2868  * @value: The value to set.
2869  *
2870  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2871  *
2872  * Since: 2.26
2873  */
2874 void
2875 g_dbus_message_set_reply_serial (GDBusMessage  *message,
2876                                  guint32        value)
2877 {
2878   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2879   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
2880 }
2881
2882 /* ---------------------------------------------------------------------------------------------------- */
2883
2884 /**
2885  * g_dbus_message_get_interface:
2886  * @message: A #GDBusMessage.
2887  *
2888  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2889  *
2890  * Returns: The value.
2891  *
2892  * Since: 2.26
2893  */
2894 const gchar *
2895 g_dbus_message_get_interface (GDBusMessage  *message)
2896 {
2897   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2898   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
2899 }
2900
2901 /**
2902  * g_dbus_message_set_interface:
2903  * @message: A #GDBusMessage.
2904  * @value: The value to set.
2905  *
2906  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2907  *
2908  * Since: 2.26
2909  */
2910 void
2911 g_dbus_message_set_interface (GDBusMessage  *message,
2912                               const gchar   *value)
2913 {
2914   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2915   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2916   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
2917 }
2918
2919 /* ---------------------------------------------------------------------------------------------------- */
2920
2921 /**
2922  * g_dbus_message_get_member:
2923  * @message: A #GDBusMessage.
2924  *
2925  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2926  *
2927  * Returns: The value.
2928  *
2929  * Since: 2.26
2930  */
2931 const gchar *
2932 g_dbus_message_get_member (GDBusMessage  *message)
2933 {
2934   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2935   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
2936 }
2937
2938 /**
2939  * g_dbus_message_set_member:
2940  * @message: A #GDBusMessage.
2941  * @value: The value to set.
2942  *
2943  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2944  *
2945  * Since: 2.26
2946  */
2947 void
2948 g_dbus_message_set_member (GDBusMessage  *message,
2949                            const gchar   *value)
2950 {
2951   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2952   g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
2953   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
2954 }
2955
2956 /* ---------------------------------------------------------------------------------------------------- */
2957
2958 /**
2959  * g_dbus_message_get_path:
2960  * @message: A #GDBusMessage.
2961  *
2962  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2963  *
2964  * Returns: The value.
2965  *
2966  * Since: 2.26
2967  */
2968 const gchar *
2969 g_dbus_message_get_path (GDBusMessage  *message)
2970 {
2971   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2972   return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
2973 }
2974
2975 /**
2976  * g_dbus_message_set_path:
2977  * @message: A #GDBusMessage.
2978  * @value: The value to set.
2979  *
2980  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2981  *
2982  * Since: 2.26
2983  */
2984 void
2985 g_dbus_message_set_path (GDBusMessage  *message,
2986                          const gchar   *value)
2987 {
2988   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2989   g_return_if_fail (value == NULL || g_variant_is_object_path (value));
2990   set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
2991 }
2992
2993 /* ---------------------------------------------------------------------------------------------------- */
2994
2995 /**
2996  * g_dbus_message_get_sender:
2997  * @message: A #GDBusMessage.
2998  *
2999  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3000  *
3001  * Returns: The value.
3002  *
3003  * Since: 2.26
3004  */
3005 const gchar *
3006 g_dbus_message_get_sender (GDBusMessage *message)
3007 {
3008   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3009   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
3010 }
3011
3012 /**
3013  * g_dbus_message_set_sender:
3014  * @message: A #GDBusMessage.
3015  * @value: The value to set.
3016  *
3017  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3018  *
3019  * Since: 2.26
3020  */
3021 void
3022 g_dbus_message_set_sender (GDBusMessage  *message,
3023                            const gchar   *value)
3024 {
3025   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3026   g_return_if_fail (value == NULL || g_dbus_is_name (value));
3027   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
3028 }
3029
3030 /* ---------------------------------------------------------------------------------------------------- */
3031
3032 /**
3033  * g_dbus_message_get_destination:
3034  * @message: A #GDBusMessage.
3035  *
3036  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3037  *
3038  * Returns: The value.
3039  *
3040  * Since: 2.26
3041  */
3042 const gchar *
3043 g_dbus_message_get_destination (GDBusMessage  *message)
3044 {
3045   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3046   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
3047 }
3048
3049 /**
3050  * g_dbus_message_set_destination:
3051  * @message: A #GDBusMessage.
3052  * @value: The value to set.
3053  *
3054  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3055  *
3056  * Since: 2.26
3057  */
3058 void
3059 g_dbus_message_set_destination (GDBusMessage  *message,
3060                                 const gchar   *value)
3061 {
3062   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3063   g_return_if_fail (value == NULL || g_dbus_is_name (value));
3064   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
3065 }
3066
3067 /* ---------------------------------------------------------------------------------------------------- */
3068
3069 /**
3070  * g_dbus_message_get_error_name:
3071  * @message: A #GDBusMessage.
3072  *
3073  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3074  *
3075  * Returns: The value.
3076  *
3077  * Since: 2.26
3078  */
3079 const gchar *
3080 g_dbus_message_get_error_name (GDBusMessage  *message)
3081 {
3082   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3083   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
3084 }
3085
3086 /**
3087  * g_dbus_message_set_error_name:
3088  * @message: A #GDBusMessage.
3089  * @value: The value to set.
3090  *
3091  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3092  *
3093  * Since: 2.26
3094  */
3095 void
3096 g_dbus_message_set_error_name (GDBusMessage  *message,
3097                                const gchar   *value)
3098 {
3099   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3100   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
3101   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
3102 }
3103
3104 /* ---------------------------------------------------------------------------------------------------- */
3105
3106 /**
3107  * g_dbus_message_get_signature:
3108  * @message: A #GDBusMessage.
3109  *
3110  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3111  *
3112  * Returns: The value.
3113  *
3114  * Since: 2.26
3115  */
3116 const gchar *
3117 g_dbus_message_get_signature (GDBusMessage  *message)
3118 {
3119   const gchar *ret;
3120   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3121   ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
3122   if (ret == NULL)
3123     ret = "";
3124   return ret;
3125 }
3126
3127 /**
3128  * g_dbus_message_set_signature:
3129  * @message: A #GDBusMessage.
3130  * @value: The value to set.
3131  *
3132  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3133  *
3134  * Since: 2.26
3135  */
3136 void
3137 g_dbus_message_set_signature (GDBusMessage  *message,
3138                               const gchar   *value)
3139 {
3140   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3141   g_return_if_fail (value == NULL || g_variant_is_signature (value));
3142   set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
3143 }
3144
3145 /* ---------------------------------------------------------------------------------------------------- */
3146
3147 /**
3148  * g_dbus_message_get_arg0:
3149  * @message: A #GDBusMessage.
3150  *
3151  * Convenience to get the first item in the body of @message.
3152  *
3153  * Returns: The string item or %NULL if the first item in the body of
3154  * @message is not a string.
3155  *
3156  * Since: 2.26
3157  */
3158 const gchar *
3159 g_dbus_message_get_arg0 (GDBusMessage  *message)
3160 {
3161   const gchar *ret;
3162
3163   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3164
3165   ret = NULL;
3166
3167   if (message->body != NULL && g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE))
3168     {
3169       GVariant *item;
3170       item = g_variant_get_child_value (message->body, 0);
3171       if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING))
3172         ret = g_variant_get_string (item, NULL);
3173       g_variant_unref (item);
3174     }
3175
3176   return ret;
3177 }
3178
3179 /* ---------------------------------------------------------------------------------------------------- */
3180
3181 /**
3182  * g_dbus_message_get_num_unix_fds:
3183  * @message: A #GDBusMessage.
3184  *
3185  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3186  *
3187  * Returns: The value.
3188  *
3189  * Since: 2.26
3190  */
3191 guint32
3192 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
3193 {
3194   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3195   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
3196 }
3197
3198 /**
3199  * g_dbus_message_set_num_unix_fds:
3200  * @message: A #GDBusMessage.
3201  * @value: The value to set.
3202  *
3203  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3204  *
3205  * Since: 2.26
3206  */
3207 void
3208 g_dbus_message_set_num_unix_fds (GDBusMessage  *message,
3209                                  guint32        value)
3210 {
3211   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3212   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
3213 }
3214
3215 /* ---------------------------------------------------------------------------------------------------- */
3216
3217 /**
3218  * g_dbus_message_to_gerror:
3219  * @message: A #GDBusMessage.
3220  * @error: The #GError to set.
3221  *
3222  * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
3223  * nothing and returns %FALSE.
3224  *
3225  * Otherwise this method encodes the error in @message as a #GError
3226  * using g_dbus_error_set_dbus_error() using the information in the
3227  * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
3228  * well as the first string item in @message's body.
3229  *
3230  * Returns: %TRUE if @error was set, %FALSE otherwise.
3231  *
3232  * Since: 2.26
3233  */
3234 gboolean
3235 g_dbus_message_to_gerror (GDBusMessage   *message,
3236                           GError        **error)
3237 {
3238   gboolean ret;
3239   const gchar *error_name;
3240
3241   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3242
3243   ret = FALSE;
3244   if (message->type != G_DBUS_MESSAGE_TYPE_ERROR)
3245     goto out;
3246
3247   error_name = g_dbus_message_get_error_name (message);
3248   if (error_name != NULL)
3249     {
3250       GVariant *body;
3251
3252       body = g_dbus_message_get_body (message);
3253
3254       if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
3255         {
3256           const gchar *error_message;
3257           g_variant_get (body, "(&s)", &error_message);
3258           g_dbus_error_set_dbus_error (error,
3259                                        error_name,
3260                                        error_message,
3261                                        NULL);
3262         }
3263       else
3264         {
3265           /* these two situations are valid, yet pretty rare */
3266           if (body != NULL)
3267             {
3268               g_dbus_error_set_dbus_error (error,
3269                                            error_name,
3270                                            "",
3271                                            _("Error return with body of type '%s'"),
3272                                            g_variant_get_type_string (body));
3273             }
3274           else
3275             {
3276               g_dbus_error_set_dbus_error (error,
3277                                            error_name,
3278                                            "",
3279                                            _("Error return with empty body"));
3280             }
3281         }
3282     }
3283   else
3284     {
3285       /* TOOD: this shouldn't happen - should check this at message serialization
3286        * time and disconnect the peer.
3287        */
3288       g_set_error (error,
3289                    G_IO_ERROR,
3290                    G_IO_ERROR_FAILED,
3291                    "Error return without error-name header!");
3292     }
3293
3294   ret = TRUE;
3295
3296  out:
3297   return ret;
3298 }
3299
3300 /* ---------------------------------------------------------------------------------------------------- */
3301
3302 static gchar *
3303 flags_to_string (GType flags_type, guint value)
3304 {
3305   GString *s;
3306   GFlagsClass *klass;
3307   guint n;
3308
3309   klass = g_type_class_ref (flags_type);
3310   s = g_string_new (NULL);
3311   for (n = 0; n < 32; n++)
3312     {
3313       if ((value & (1<<n)) != 0)
3314         {
3315           GFlagsValue *flags_value;
3316           flags_value = g_flags_get_first_value (klass, (1<<n));
3317           if (s->len > 0)
3318             g_string_append_c (s, ',');
3319           if (flags_value != NULL)
3320             g_string_append (s, flags_value->value_nick);
3321           else
3322             g_string_append_printf (s, "unknown (bit %d)", n);
3323         }
3324     }
3325   if (s->len == 0)
3326     g_string_append (s, "none");
3327   g_type_class_unref (klass);
3328   return g_string_free (s, FALSE);
3329 }
3330
3331 static gint
3332 _sort_keys_func (gconstpointer a,
3333                  gconstpointer b)
3334 {
3335   gint ia;
3336   gint ib;
3337
3338   ia = GPOINTER_TO_INT (a);
3339   ib = GPOINTER_TO_INT (b);
3340
3341   return ia - ib;
3342 }
3343
3344 /**
3345  * g_dbus_message_print:
3346  * @message: A #GDBusMessage.
3347  * @indent: Indentation level.
3348  *
3349  * Produces a human-readable multi-line description of @message.
3350  *
3351  * The contents of the description has no ABI guarantees, the contents
3352  * and formatting is subject to change at any time. Typical output
3353  * looks something like this:
3354  * <programlisting>
3355  * Type&colon;    method-call
3356  * Flags&colon;   none
3357  * Version&colon; 0
3358  * Serial&colon;  4
3359  * Headers&colon;
3360  *   path -> objectpath '/org/gtk/GDBus/TestObject'
3361  *   interface -> 'org.gtk.GDBus.TestInterface'
3362  *   member -> 'GimmeStdout'
3363  *   destination -> ':1.146'
3364  * Body&colon; ()
3365  * UNIX File Descriptors:
3366  *   (none)
3367  * </programlisting>
3368  * or
3369  * <programlisting>
3370  * Type&colon;    method-return
3371  * Flags&colon;   no-reply-expected
3372  * Version&colon; 0
3373  * Serial&colon;  477
3374  * Headers&colon;
3375  *   reply-serial -> uint32 4
3376  *   destination -> ':1.159'
3377  *   sender -> ':1.146'
3378  *   num-unix-fds -> uint32 1
3379  * Body&colon; ()
3380  * UNIX File Descriptors&colon;
3381  *   fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
3382  * </programlisting>
3383  *
3384  * Returns: A string that should be freed with g_free().
3385  *
3386  * Since: 2.26
3387  */
3388 gchar *
3389 g_dbus_message_print (GDBusMessage *message,
3390                       guint         indent)
3391 {
3392   GString *str;
3393   gchar *s;
3394   GList *keys;
3395   GList *l;
3396
3397   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3398
3399   str = g_string_new (NULL);
3400
3401   s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->type);
3402   g_string_append_printf (str, "%*sType:    %s\n", indent, "", s);
3403   g_free (s);
3404   s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->flags);
3405   g_string_append_printf (str, "%*sFlags:   %s\n", indent, "", s);
3406   g_free (s);
3407   g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->major_protocol_version);
3408   g_string_append_printf (str, "%*sSerial:  %d\n", indent, "", message->serial);
3409
3410   g_string_append_printf (str, "%*sHeaders:\n", indent, "");
3411   keys = g_hash_table_get_keys (message->headers);
3412   keys = g_list_sort (keys, _sort_keys_func);
3413   if (keys != NULL)
3414     {
3415       for (l = keys; l != NULL; l = l->next)
3416         {
3417           gint key = GPOINTER_TO_INT (l->data);
3418           GVariant *value;
3419           gchar *value_str;
3420
3421           value = g_hash_table_lookup (message->headers, l->data);
3422           g_assert (value != NULL);
3423
3424           s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
3425           value_str = g_variant_print (value, TRUE);
3426           g_string_append_printf (str, "%*s  %s -> %s\n", indent, "", s, value_str);
3427           g_free (s);
3428           g_free (value_str);
3429         }
3430     }
3431   else
3432     {
3433       g_string_append_printf (str, "%*s  (none)\n", indent, "");
3434     }
3435   g_string_append_printf (str, "%*sBody: ", indent, "");
3436   if (message->body != NULL)
3437     {
3438       g_variant_print_string (message->body,
3439                               str,
3440                               TRUE);
3441     }
3442   else
3443     {
3444       g_string_append (str, "()");
3445     }
3446   g_string_append (str, "\n");
3447 #ifdef G_OS_UNIX
3448   g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
3449   if (message->fd_list != NULL)
3450     {
3451       gint num_fds;
3452       const gint *fds;
3453       gint n;
3454
3455       fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3456       if (num_fds > 0)
3457         {
3458           for (n = 0; n < num_fds; n++)
3459             {
3460               GString *fs;
3461               struct stat statbuf;
3462               fs = g_string_new (NULL);
3463               if (fstat (fds[n], &statbuf) == 0)
3464                 {
3465                   g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
3466                                           major (statbuf.st_dev), minor (statbuf.st_dev));
3467                   g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
3468                                           statbuf.st_mode);
3469                   g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3470                                           (guint64) statbuf.st_ino);
3471                   g_string_append_printf (fs, "%s" "uid=%u", fs->len > 0 ? "," : "",
3472                                           (guint) statbuf.st_uid);
3473                   g_string_append_printf (fs, "%s" "gid=%u", fs->len > 0 ? "," : "",
3474                                           (guint) statbuf.st_gid);
3475                   g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
3476                                           major (statbuf.st_rdev), minor (statbuf.st_rdev));
3477                   g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3478                                           (guint64) statbuf.st_size);
3479                   g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3480                                           (guint64) statbuf.st_atime);
3481                   g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3482                                           (guint64) statbuf.st_mtime);
3483                   g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3484                                           (guint64) statbuf.st_ctime);
3485                 }
3486               else
3487                 {
3488                   g_string_append_printf (fs, "(fstat failed: %s)", strerror (errno));
3489                 }
3490               g_string_append_printf (str, "%*s  fd %d: %s\n", indent, "", fds[n], fs->str);
3491               g_string_free (fs, TRUE);
3492             }
3493         }
3494       else
3495         {
3496           g_string_append_printf (str, "%*s  (empty)\n", indent, "");
3497         }
3498     }
3499   else
3500     {
3501       g_string_append_printf (str, "%*s  (none)\n", indent, "");
3502     }
3503 #endif
3504
3505   return g_string_free (str, FALSE);
3506 }
3507
3508 /**
3509  * g_dbus_message_get_locked:
3510  * @message: A #GDBusMessage.
3511  *
3512  * Checks whether @message is locked. To monitor changes to this
3513  * value, conncet to the #GObject::notify signal to listen for changes
3514  * on the #GDBusMessage:locked property.
3515  *
3516  * Returns: %TRUE if @message is locked, %FALSE otherwise.
3517  *
3518  * Since: 2.26
3519  */
3520 gboolean
3521 g_dbus_message_get_locked (GDBusMessage *message)
3522 {
3523   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3524   return message->locked;
3525 }
3526
3527 /**
3528  * g_dbus_message_lock:
3529  * @message: A #GDBusMessage.
3530  *
3531  * If @message is locked, does nothing. Otherwise locks the message.
3532  *
3533  * Since: 2.26
3534  */
3535 void
3536 g_dbus_message_lock (GDBusMessage *message)
3537 {
3538   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3539
3540   if (message->locked)
3541     goto out;
3542
3543   message->locked = TRUE;
3544   g_object_notify (G_OBJECT (message), "locked");
3545
3546  out:
3547   ;
3548 }
3549
3550 /**
3551  * g_dbus_message_copy:
3552  * @message: A #GDBusMessage.
3553  * @error: Return location for error or %NULL.
3554  *
3555  * Copies @message. The copy is a deep copy and the returned
3556  * #GDBusMessage is completely identical except that it is guaranteed
3557  * to not be locked.
3558  *
3559  * This operation can fail if e.g. @message contains file descriptors
3560  * and the per-process or system-wide open files limit is reached.
3561  *
3562  * Returns: (transfer full): A new #GDBusMessage or %NULL if @error is set.
3563  *     Free with g_object_unref().
3564  *
3565  * Since: 2.26
3566  */
3567 GDBusMessage *
3568 g_dbus_message_copy (GDBusMessage  *message,
3569                      GError       **error)
3570 {
3571   GDBusMessage *ret;
3572   GHashTableIter iter;
3573   gpointer header_key;
3574   GVariant *header_value;
3575
3576   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3577   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
3578
3579   ret = g_dbus_message_new ();
3580   ret->type                   = message->type;
3581   ret->flags                  = message->flags;
3582   ret->byte_order             = message->byte_order;
3583   ret->major_protocol_version = message->major_protocol_version;
3584   ret->serial                 = message->serial;
3585
3586 #ifdef G_OS_UNIX
3587   if (message->fd_list != NULL)
3588     {
3589       gint n;
3590       gint num_fds;
3591       const gint *fds;
3592
3593       ret->fd_list = g_unix_fd_list_new ();
3594       fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3595       for (n = 0; n < num_fds; n++)
3596         {
3597           if (g_unix_fd_list_append (ret->fd_list,
3598                                      fds[n],
3599                                      error) == -1)
3600             {
3601               g_object_unref (ret);
3602               ret = NULL;
3603               goto out;
3604             }
3605         }
3606     }
3607 #endif
3608
3609   /* see https://bugzilla.gnome.org/show_bug.cgi?id=624546#c8 for why it's fine
3610    * to just ref (as opposed to deep-copying) the GVariant instances
3611    */
3612   ret->body = message->body != NULL ? g_variant_ref (message->body) : NULL;
3613   g_hash_table_iter_init (&iter, message->headers);
3614   while (g_hash_table_iter_next (&iter, &header_key, (gpointer) &header_value))
3615     g_hash_table_insert (ret->headers, header_key, g_variant_ref (header_value));
3616
3617 #ifdef G_OS_UNIX
3618  out:
3619 #endif
3620   return ret;
3621 }