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