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