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