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