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