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