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