GDBus: Big-endian fixes
[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           g_free (v);
906         }
907     }
908   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
909     {
910       if (!ensure_input_padding (mis, 4, &local_error))
911         goto fail;
912       if (!just_align)
913         {
914           guint32 len;
915           gchar *v;
916           len = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
917           if (local_error != NULL)
918             goto fail;
919           v = read_string (mis, dis, (gsize) len, &local_error);
920           if (v == NULL)
921             goto fail;
922           if (!g_variant_is_object_path (v))
923             {
924               g_set_error (&local_error,
925                            G_IO_ERROR,
926                            G_IO_ERROR_INVALID_ARGUMENT,
927                            _("Parsed value `%s' is not a valid D-Bus object path"),
928                            v);
929               g_free (v);
930               goto fail;
931             }
932           ret = g_variant_new_object_path (v);
933           g_free (v);
934         }
935     }
936   else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
937     {
938       if (!just_align)
939         {
940           guchar len;
941           gchar *v;
942           len = g_data_input_stream_read_byte (dis, NULL, &local_error);
943           if (local_error != NULL)
944             goto fail;
945           v = read_string (mis, dis, (gsize) len, &local_error);
946           if (v == NULL)
947             goto fail;
948           if (!g_variant_is_signature (v))
949             {
950               g_set_error (&local_error,
951                            G_IO_ERROR,
952                            G_IO_ERROR_INVALID_ARGUMENT,
953                            _("Parsed value `%s' is not a valid D-Bus signature"),
954                        v);
955               g_free (v);
956               goto fail;
957             }
958           ret = g_variant_new_signature (v);
959           g_free (v);
960         }
961     }
962   else if (g_variant_type_is_array (type))
963     {
964       guint32 array_len;
965       goffset offset;
966       goffset target;
967       const GVariantType *element_type;
968       GVariantBuilder builder;
969
970       if (!ensure_input_padding (mis, 4, &local_error))
971         goto fail;
972       array_len = g_data_input_stream_read_uint32 (dis, NULL, &local_error);
973
974       if (array_len > (2<<26))
975         {
976           g_set_error (&local_error,
977                        G_IO_ERROR,
978                        G_IO_ERROR_INVALID_ARGUMENT,
979                        _("Encountered array of length %" G_GUINT32_FORMAT " bytes. Maximum length is 2<<26 bytes."),
980                        array_len);
981           goto fail;
982         }
983
984       g_variant_builder_init (&builder, type);
985       element_type = g_variant_type_element (type);
986
987       if (array_len == 0)
988         {
989           GVariant *item;
990           item = parse_value_from_blob (mis,
991                                         dis,
992                                         element_type,
993                                         TRUE,
994                                         &local_error);
995           g_assert (item == NULL);
996         }
997       else
998         {
999           /* TODO: optimize array of primitive types */
1000           offset = g_seekable_tell (G_SEEKABLE (mis));
1001           target = offset + array_len;
1002           while (offset < target)
1003             {
1004               GVariant *item;
1005               item = parse_value_from_blob (mis,
1006                                             dis,
1007                                             element_type,
1008                                             FALSE,
1009                                             &local_error);
1010               if (item == NULL)
1011                 {
1012                   g_variant_builder_clear (&builder);
1013                   goto fail;
1014                 }
1015               g_variant_builder_add_value (&builder, item);
1016               offset = g_seekable_tell (G_SEEKABLE (mis));
1017             }
1018         }
1019
1020       if (!just_align)
1021         {
1022           ret = g_variant_builder_end (&builder);
1023         }
1024       else
1025         {
1026           g_variant_builder_clear (&builder);
1027         }
1028     }
1029   else if (g_variant_type_is_dict_entry (type))
1030     {
1031       const GVariantType *key_type;
1032       const GVariantType *value_type;
1033       GVariant *key;
1034       GVariant *value;
1035
1036       if (!ensure_input_padding (mis, 8, &local_error))
1037         goto fail;
1038
1039       if (!just_align)
1040         {
1041           key_type = g_variant_type_key (type);
1042           key = parse_value_from_blob (mis,
1043                                        dis,
1044                                        key_type,
1045                                        FALSE,
1046                                        &local_error);
1047           if (key == NULL)
1048             goto fail;
1049
1050           value_type = g_variant_type_value (type);
1051           value = parse_value_from_blob (mis,
1052                                          dis,
1053                                          value_type,
1054                                          FALSE,
1055                                          &local_error);
1056           if (value == NULL)
1057             {
1058               g_variant_unref (key);
1059               goto fail;
1060             }
1061           ret = g_variant_new_dict_entry (key, value);
1062         }
1063     }
1064   else if (g_variant_type_is_tuple (type))
1065     {
1066       if (!ensure_input_padding (mis, 8, &local_error))
1067         goto fail;
1068
1069       if (!just_align)
1070         {
1071           const GVariantType *element_type;
1072           GVariantBuilder builder;
1073
1074           g_variant_builder_init (&builder, type);
1075           element_type = g_variant_type_first (type);
1076           while (element_type != NULL)
1077             {
1078               GVariant *item;
1079               item = parse_value_from_blob (mis,
1080                                             dis,
1081                                             element_type,
1082                                             FALSE,
1083                                             &local_error);
1084               if (item == NULL)
1085                 {
1086                   g_variant_builder_clear (&builder);
1087                   goto fail;
1088                 }
1089               g_variant_builder_add_value (&builder, item);
1090
1091               element_type = g_variant_type_next (element_type);
1092             }
1093           ret = g_variant_builder_end (&builder);
1094         }
1095     }
1096   else if (g_variant_type_is_variant (type))
1097     {
1098       if (!just_align)
1099         {
1100           guchar siglen;
1101           gchar *sig;
1102           GVariantType *variant_type;
1103           GVariant *value;
1104
1105           siglen = g_data_input_stream_read_byte (dis, NULL, &local_error);
1106           if (local_error != NULL)
1107             goto fail;
1108           sig = read_string (mis, dis, (gsize) siglen, &local_error);
1109           if (sig == NULL)
1110             goto fail;
1111           if (!g_variant_is_signature (sig))
1112             {
1113               g_set_error (&local_error,
1114                            G_IO_ERROR,
1115                            G_IO_ERROR_INVALID_ARGUMENT,
1116                            _("Parsed value `%s' for variant is not a valid D-Bus signature"),
1117                            sig);
1118               g_free (sig);
1119               goto fail;
1120             }
1121           variant_type = g_variant_type_new (sig);
1122           g_free (sig);
1123           value = parse_value_from_blob (mis,
1124                                          dis,
1125                                          variant_type,
1126                                          FALSE,
1127                                          &local_error);
1128           g_variant_type_free (variant_type);
1129           if (value == NULL)
1130             goto fail;
1131           ret = g_variant_new_variant (value);
1132         }
1133     }
1134   else
1135     {
1136       gchar *s;
1137       s = g_variant_type_dup_string (type);
1138       g_set_error (&local_error,
1139                    G_IO_ERROR,
1140                    G_IO_ERROR_INVALID_ARGUMENT,
1141                    _("Error deserializing GVariant with type-string `%s' from the D-Bus wire format"),
1142                    s);
1143       g_free (s);
1144       goto fail;
1145     }
1146
1147   g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
1148   return ret;
1149
1150  fail:
1151   g_propagate_error (error, local_error);
1152   return NULL;
1153 }
1154
1155 /* ---------------------------------------------------------------------------------------------------- */
1156
1157 /* message_header must be at least 16 bytes */
1158
1159 /**
1160  * g_dbus_message_bytes_needed:
1161  * @blob: A blob represent a binary D-Bus message.
1162  * @blob_len: The length of @blob (must be at least 16).
1163  * @error: Return location for error or %NULL.
1164  *
1165  * Utility function to calculate how many bytes are needed to
1166  * completely deserialize the D-Bus message stored at @blob.
1167  *
1168  * Returns: Number of bytes needed or -1 if @error is set (e.g. if
1169  * @blob contains invalid data or not enough data is available to
1170  * determine the size).
1171  *
1172  * Since: 2.26
1173  */
1174 gssize
1175 g_dbus_message_bytes_needed (guchar                *blob,
1176                              gsize                  blob_len,
1177                              GError               **error)
1178 {
1179   gssize ret;
1180
1181   ret = -1;
1182
1183   g_return_val_if_fail (blob != NULL, -1);
1184   g_return_val_if_fail (error == NULL || *error == NULL, -1);
1185   g_return_val_if_fail (blob_len >= 16, -1);
1186
1187   if (blob[0] == 'l')
1188     {
1189       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1190       ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
1191       /* round up so it's a multiple of 8 */
1192       ret = 8 * ((ret + 7)/8);
1193       /* finally add the body size */
1194       ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
1195     }
1196   else if (blob[0] == 'B')
1197     {
1198       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1199       ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
1200       /* round up so it's a multiple of 8 */
1201       ret = 8 * ((ret + 7)/8);
1202       /* finally add the body size */
1203       ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
1204     }
1205   else
1206     {
1207       g_set_error (error,
1208                    G_IO_ERROR,
1209                    G_IO_ERROR_INVALID_ARGUMENT,
1210                    "Unable to determine message blob length - given blob is malformed");
1211     }
1212
1213   if (ret > (2<<27))
1214     {
1215       g_set_error (error,
1216                    G_IO_ERROR,
1217                    G_IO_ERROR_INVALID_ARGUMENT,
1218                    "Blob indicates that message exceeds maximum message length (128MiB)");
1219       ret = -1;
1220     }
1221
1222   return ret;
1223 }
1224
1225 /* ---------------------------------------------------------------------------------------------------- */
1226
1227 /**
1228  * g_dbus_message_new_from_blob:
1229  * @blob: A blob represent a binary D-Bus message.
1230  * @blob_len: The length of @blob.
1231  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1232  * @error: Return location for error or %NULL.
1233  *
1234  * Creates a new #GDBusMessage from the data stored at @blob.
1235  *
1236  * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
1237  * g_object_unref().
1238  *
1239  * Since: 2.26
1240  */
1241 GDBusMessage *
1242 g_dbus_message_new_from_blob (guchar                *blob,
1243                               gsize                  blob_len,
1244                               GDBusCapabilityFlags   capabilities,
1245                               GError               **error)
1246 {
1247   gboolean ret;
1248   GMemoryInputStream *mis;
1249   GDataInputStream *dis;
1250   GDBusMessage *message;
1251   guchar endianness;
1252   guchar major_protocol_version;
1253   GDataStreamByteOrder byte_order;
1254   guint32 message_body_len;
1255   GVariant *headers;
1256   GVariant *item;
1257   GVariantIter iter;
1258   GVariant *signature;
1259
1260   /* TODO: check against @capabilities */
1261
1262   ret = FALSE;
1263
1264   g_return_val_if_fail (blob != NULL, NULL);
1265   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1266   g_return_val_if_fail (blob_len >= 12, NULL);
1267
1268   message = g_dbus_message_new ();
1269
1270   mis = G_MEMORY_INPUT_STREAM (g_memory_input_stream_new_from_data (blob, blob_len, NULL));
1271   dis = g_data_input_stream_new (G_INPUT_STREAM (mis));
1272
1273   endianness = g_data_input_stream_read_byte (dis, NULL, NULL);
1274   switch (endianness)
1275     {
1276     case 'l':
1277       byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
1278       break;
1279     case 'B':
1280       byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
1281       break;
1282     default:
1283       g_set_error (error,
1284                    G_IO_ERROR,
1285                    G_IO_ERROR_INVALID_ARGUMENT,
1286                    _("Invalid endianness value. Expected 'l' or 'B' but found '%c' (%d)"),
1287                    endianness, endianness);
1288       goto out;
1289     }
1290   g_data_input_stream_set_byte_order (dis, byte_order);
1291
1292   message->priv->type = g_data_input_stream_read_byte (dis, NULL, NULL);
1293   message->priv->flags = g_data_input_stream_read_byte (dis, NULL, NULL);
1294   major_protocol_version = g_data_input_stream_read_byte (dis, NULL, NULL);
1295   if (major_protocol_version != 1)
1296     {
1297       g_set_error (error,
1298                    G_IO_ERROR,
1299                    G_IO_ERROR_INVALID_ARGUMENT,
1300                    _("Invalid major protocol version. Expected 1 but found %d"),
1301                    major_protocol_version);
1302       goto out;
1303     }
1304   message_body_len = g_data_input_stream_read_uint32 (dis, NULL, NULL);
1305   message->priv->serial = g_data_input_stream_read_uint32 (dis, NULL, NULL);
1306
1307   headers = parse_value_from_blob (mis,
1308                                    dis,
1309                                    G_VARIANT_TYPE ("a{yv}"),
1310                                    FALSE,
1311                                    error);
1312   if (headers == NULL)
1313     goto out;
1314   g_variant_ref_sink (headers);
1315   g_variant_iter_init (&iter, headers);
1316   while ((item = g_variant_iter_next_value (&iter)))
1317     {
1318       guchar header_field;
1319       GVariant *value;
1320       g_variant_get (item,
1321                      "{yv}",
1322                      &header_field,
1323                      &value);
1324       g_dbus_message_set_header (message, header_field, value);
1325     }
1326   g_variant_unref (headers);
1327
1328   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
1329   if (signature != NULL)
1330     {
1331       const gchar *signature_str;
1332       gsize signature_str_len;
1333
1334       signature_str = g_variant_get_string (signature, NULL);
1335       signature_str_len = strlen (signature_str);
1336
1337       /* signature but no body */
1338       if (message_body_len == 0 && signature_str_len > 0)
1339         {
1340           g_set_error (error,
1341                        G_IO_ERROR,
1342                        G_IO_ERROR_INVALID_ARGUMENT,
1343                        _("Signature header with signature `%s' found but message body is empty"),
1344                        signature_str);
1345           goto out;
1346         }
1347       else if (signature_str_len > 0)
1348         {
1349           GVariantType *variant_type;
1350           gchar *tupled_signature_str;
1351
1352           if (!g_variant_is_signature (signature_str))
1353             {
1354               g_set_error (error,
1355                            G_IO_ERROR,
1356                            G_IO_ERROR_INVALID_ARGUMENT,
1357                            _("Parsed value `%s' is not a valid D-Bus signature (for body)"),
1358                            signature_str);
1359               goto out;
1360             }
1361           tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
1362           variant_type = g_variant_type_new (tupled_signature_str);
1363           g_free (tupled_signature_str);
1364           message->priv->body = parse_value_from_blob (mis,
1365                                                        dis,
1366                                                        variant_type,
1367                                                        FALSE,
1368                                                        error);
1369           if (message->priv->body == NULL)
1370             {
1371               g_variant_type_free (variant_type);
1372               goto out;
1373             }
1374           g_variant_ref_sink (message->priv->body);
1375           g_variant_type_free (variant_type);
1376         }
1377     }
1378   else
1379     {
1380       /* no signature, this is only OK if the body is empty */
1381       if (message_body_len != 0)
1382         {
1383           g_set_error (error,
1384                        G_IO_ERROR,
1385                        G_IO_ERROR_INVALID_ARGUMENT,
1386                        _("No signature header in message but the message body is %" G_GUINT32_FORMAT " bytes"),
1387                        message_body_len);
1388           goto out;
1389         }
1390     }
1391
1392
1393   ret = TRUE;
1394
1395  out:
1396   g_object_unref (dis);
1397   g_object_unref (mis);
1398
1399   if (ret)
1400     {
1401       return message;
1402     }
1403   else
1404     {
1405       if (message != NULL)
1406         g_object_unref (message);
1407       return NULL;
1408     }
1409 }
1410
1411 /* ---------------------------------------------------------------------------------------------------- */
1412
1413 static gsize
1414 ensure_output_padding (GMemoryOutputStream  *mos,
1415                        GDataOutputStream    *dos,
1416                        gsize                 padding_size)
1417 {
1418   gsize offset;
1419   gsize wanted_offset;
1420   gsize padding_needed;
1421   guint n;
1422
1423   offset = g_memory_output_stream_get_data_size (mos);
1424   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1425   padding_needed = wanted_offset - offset;
1426
1427   for (n = 0; n < padding_needed; n++)
1428     g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1429
1430   return padding_needed;
1431 }
1432
1433 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
1434 static gboolean
1435 append_value_to_blob (GVariant             *value,
1436                       const GVariantType   *type,
1437                       GMemoryOutputStream  *mos,
1438                       GDataOutputStream    *dos,
1439                       gsize                *out_padding_added,
1440                       GError              **error)
1441 {
1442   gsize padding_added;
1443
1444   padding_added = 0;
1445
1446   if (g_variant_type_equal (type, G_VARIANT_TYPE_BOOLEAN))
1447     {
1448       padding_added = ensure_output_padding (mos, dos, 4);
1449       if (value != NULL)
1450         {
1451           gboolean v = g_variant_get_boolean (value);
1452           g_data_output_stream_put_uint32 (dos, v, NULL, NULL);
1453         }
1454     }
1455   else if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1456     {
1457       if (value != NULL)
1458         {
1459           guint8 v = g_variant_get_byte (value);
1460           g_data_output_stream_put_byte (dos, v, NULL, NULL);
1461         }
1462     }
1463   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT16))
1464     {
1465       padding_added = ensure_output_padding (mos, dos, 2);
1466       if (value != NULL)
1467         {
1468           gint16 v = g_variant_get_int16 (value);
1469           g_data_output_stream_put_int16 (dos, v, NULL, NULL);
1470         }
1471     }
1472   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT16))
1473     {
1474       padding_added = ensure_output_padding (mos, dos, 2);
1475       if (value != NULL)
1476         {
1477           guint16 v = g_variant_get_uint16 (value);
1478           g_data_output_stream_put_uint16 (dos, v, NULL, NULL);
1479         }
1480     }
1481   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
1482     {
1483       padding_added = ensure_output_padding (mos, dos, 4);
1484       if (value != NULL)
1485         {
1486           gint32 v = g_variant_get_int32 (value);
1487           g_data_output_stream_put_int32 (dos, v, NULL, NULL);
1488         }
1489     }
1490   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT32))
1491     {
1492       padding_added = ensure_output_padding (mos, dos, 4);
1493       if (value != NULL)
1494         {
1495           guint32 v = g_variant_get_uint32 (value);
1496           g_data_output_stream_put_uint32 (dos, v, NULL, NULL);
1497         }
1498     }
1499   else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT64))
1500     {
1501       padding_added = ensure_output_padding (mos, dos, 8);
1502       if (value != NULL)
1503         {
1504           gint64 v = g_variant_get_int64 (value);
1505           g_data_output_stream_put_int64 (dos, v, NULL, NULL);
1506         }
1507     }
1508   else if (g_variant_type_equal (type, G_VARIANT_TYPE_UINT64))
1509     {
1510       padding_added = ensure_output_padding (mos, dos, 8);
1511       if (value != NULL)
1512         {
1513           guint64 v = g_variant_get_uint64 (value);
1514           g_data_output_stream_put_uint64 (dos, v, NULL, NULL);
1515         }
1516     }
1517   else if (g_variant_type_equal (type, G_VARIANT_TYPE_DOUBLE))
1518     {
1519       padding_added = ensure_output_padding (mos, dos, 8);
1520       if (value != NULL)
1521         {
1522           guint64 *encoded;
1523           gdouble v = g_variant_get_double (value);
1524           /* TODO: hmm */
1525           encoded = (guint64 *) &v;
1526           g_data_output_stream_put_uint64 (dos, *encoded, NULL, NULL);
1527         }
1528     }
1529   else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
1530     {
1531       padding_added = ensure_output_padding (mos, dos, 4);
1532       if (value != NULL)
1533         {
1534           const gchar *v = g_variant_get_string (value, NULL);
1535           gsize len;
1536           len = strlen (v);
1537           g_data_output_stream_put_uint32 (dos, len, NULL, NULL);
1538           g_data_output_stream_put_string (dos, v, NULL, NULL);
1539           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1540         }
1541     }
1542   else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
1543     {
1544       padding_added = ensure_output_padding (mos, dos, 4);
1545       if (value != NULL)
1546         {
1547           /* TODO: validate object path */
1548           const gchar *v = g_variant_get_string (value, NULL);
1549           gsize len;
1550           len = strlen (v);
1551           g_data_output_stream_put_uint32 (dos, len, NULL, NULL);
1552           g_data_output_stream_put_string (dos, v, NULL, NULL);
1553           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1554         }
1555     }
1556   else if (g_variant_type_equal (type, G_VARIANT_TYPE_SIGNATURE))
1557     {
1558       if (value != NULL)
1559         {
1560           /* TODO: validate signature (including max len being 255) */
1561           const gchar *v = g_variant_get_string (value, NULL);
1562           gsize len;
1563           len = strlen (v);
1564           g_data_output_stream_put_byte (dos, len, NULL, NULL);
1565           g_data_output_stream_put_string (dos, v, NULL, NULL);
1566           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1567         }
1568     }
1569   else if (g_variant_type_is_array (type))
1570     {
1571       GVariant *item;
1572       GVariantIter iter;
1573       goffset array_len_offset;
1574       goffset array_payload_begin_offset;
1575       goffset cur_offset;
1576       gsize array_len;
1577
1578       padding_added = ensure_output_padding (mos, dos, 4);
1579       if (value != NULL)
1580         {
1581           /* array length - will be filled in later */
1582           array_len_offset = g_memory_output_stream_get_data_size (mos);
1583           g_data_output_stream_put_uint32 (dos, 0xF00DFACE, NULL, NULL);
1584
1585           /* From the D-Bus spec:
1586            *
1587            *   "A UINT32 giving the length of the array data in bytes,
1588            *    followed by alignment padding to the alignment boundary of
1589            *    the array element type, followed by each array element. The
1590            *    array length is from the end of the alignment padding to
1591            *    the end of the last element, i.e. it does not include the
1592            *    padding after the length, or any padding after the last
1593            *    element."
1594            *
1595            * Thus, we need to count how much padding the first element
1596            * contributes and subtract that from the array length.
1597            */
1598           array_payload_begin_offset = g_memory_output_stream_get_data_size (mos);
1599
1600           if (g_variant_n_children (value) == 0)
1601             {
1602               gsize padding_added_for_item;
1603               if (!append_value_to_blob (NULL,
1604                                          g_variant_type_element (type),
1605                                          mos,
1606                                          dos,
1607                                          &padding_added_for_item,
1608                                          error))
1609                 goto fail;
1610               array_payload_begin_offset += padding_added_for_item;
1611             }
1612           else
1613             {
1614               guint n;
1615               n = 0;
1616               g_variant_iter_init (&iter, value);
1617               while ((item = g_variant_iter_next_value (&iter)))
1618                 {
1619                   gsize padding_added_for_item;
1620                   if (!append_value_to_blob (item,
1621                                              g_variant_get_type (item),
1622                                              mos,
1623                                              dos,
1624                                              &padding_added_for_item,
1625                                              error))
1626                     goto fail;
1627                   if (n == 0)
1628                     {
1629                       array_payload_begin_offset += padding_added_for_item;
1630                     }
1631                   n++;
1632                 }
1633             }
1634
1635           cur_offset = g_memory_output_stream_get_data_size (mos);
1636
1637           array_len = cur_offset - array_payload_begin_offset;
1638
1639           if (!g_seekable_seek (G_SEEKABLE (mos), array_len_offset, G_SEEK_SET, NULL, error))
1640             goto fail;
1641
1642           g_data_output_stream_put_uint32 (dos, array_len, NULL, NULL);
1643
1644           if (!g_seekable_seek (G_SEEKABLE (mos), cur_offset, G_SEEK_SET, NULL, error))
1645             goto fail;
1646         }
1647     }
1648   else if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
1649     {
1650       padding_added = ensure_output_padding (mos, dos, 8);
1651       if (value != NULL)
1652         {
1653           GVariant *item;
1654           GVariantIter iter;
1655           g_variant_iter_init (&iter, value);
1656           while ((item = g_variant_iter_next_value (&iter)))
1657             {
1658               if (!append_value_to_blob (item,
1659                                          g_variant_get_type (item),
1660                                          mos,
1661                                          dos,
1662                                          NULL,
1663                                          error))
1664                 goto fail;
1665             }
1666         }
1667     }
1668   else if (g_variant_type_is_variant (type))
1669     {
1670       if (value != NULL)
1671         {
1672           GVariant *child;
1673           const gchar *signature;
1674           child = g_variant_get_child_value (value, 0);
1675           signature = g_variant_get_type_string (child);
1676           /* TODO: validate signature (including max len being 255) */
1677           g_data_output_stream_put_byte (dos, strlen (signature), NULL, NULL);
1678           g_data_output_stream_put_string (dos, signature, NULL, NULL);
1679           g_data_output_stream_put_byte (dos, '\0', NULL, NULL);
1680           if (!append_value_to_blob (child,
1681                                      g_variant_get_type (child),
1682                                      mos,
1683                                      dos,
1684                                      NULL,
1685                                      error))
1686             {
1687               g_variant_unref (child);
1688               goto fail;
1689             }
1690           g_variant_unref (child);
1691         }
1692     }
1693   else
1694     {
1695       g_set_error (error,
1696                    G_IO_ERROR,
1697                    G_IO_ERROR_INVALID_ARGUMENT,
1698                    _("Error serializing GVariant with type-string `%s' to the D-Bus wire format"),
1699                    g_variant_get_type_string (value));
1700       goto fail;
1701     }
1702
1703   if (out_padding_added != NULL)
1704     *out_padding_added = padding_added;
1705
1706   return TRUE;
1707
1708  fail:
1709   return FALSE;
1710 }
1711
1712 static gboolean
1713 append_body_to_blob (GVariant             *value,
1714                      GMemoryOutputStream  *mos,
1715                      GDataOutputStream    *dos,
1716                      GError              **error)
1717 {
1718   gboolean ret;
1719   GVariant *item;
1720   GVariantIter iter;
1721
1722   ret = FALSE;
1723
1724   if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
1725     {
1726       g_set_error (error,
1727                    G_IO_ERROR,
1728                    G_IO_ERROR_INVALID_ARGUMENT,
1729                    "Expected a tuple for the body of the GDBusMessage.");
1730       goto fail;
1731     }
1732
1733   g_variant_iter_init (&iter, value);
1734   while ((item = g_variant_iter_next_value (&iter)))
1735     {
1736       if (!append_value_to_blob (item,
1737                                  g_variant_get_type (item),
1738                                  mos,
1739                                  dos,
1740                                  NULL,
1741                                  error))
1742         goto fail;
1743     }
1744   return TRUE;
1745
1746  fail:
1747   return FALSE;
1748 }
1749
1750 /* ---------------------------------------------------------------------------------------------------- */
1751
1752 /**
1753  * g_dbus_message_to_blob:
1754  * @message: A #GDBusMessage.
1755  * @out_size: Return location for size of generated blob.
1756  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1757  * @error: Return location for error.
1758  *
1759  * Serializes @message to a blob.
1760  *
1761  * Returns: A pointer to a valid binary D-Bus message of @out_size bytes
1762  * generated by @message or %NULL if @error is set. Free with g_free().
1763  *
1764  * Since: 2.26
1765  */
1766 guchar *
1767 g_dbus_message_to_blob (GDBusMessage          *message,
1768                         gsize                 *out_size,
1769                         GDBusCapabilityFlags   capabilities,
1770                         GError               **error)
1771 {
1772   GMemoryOutputStream *mos;
1773   GDataOutputStream *dos;
1774   guchar *ret;
1775   gsize size;
1776   GDataStreamByteOrder byte_order;
1777   goffset body_len_offset;
1778   goffset body_start_offset;
1779   gsize body_size;
1780   GVariant *header_fields;
1781   GVariantBuilder builder;
1782   GHashTableIter hash_iter;
1783   gpointer key;
1784   GVariant *header_value;
1785   GVariant *signature;
1786   const gchar *signature_str;
1787   gint num_fds_in_message;
1788   gint num_fds_according_to_header;
1789
1790   /* TODO: check against @capabilities */
1791
1792   ret = NULL;
1793
1794   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1795   g_return_val_if_fail (out_size != NULL, NULL);
1796   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1797
1798   mos = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (NULL, 0, g_realloc, g_free));
1799   dos = g_data_output_stream_new (G_OUTPUT_STREAM (mos));
1800
1801   /* TODO: detect endianess... */
1802   byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
1803   g_data_output_stream_set_byte_order (dos, byte_order);
1804
1805   /* Core header */
1806   g_data_output_stream_put_byte (dos, byte_order == G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN ? 'l' : 'B', NULL, NULL);
1807   g_data_output_stream_put_byte (dos, message->priv->type, NULL, NULL);
1808   g_data_output_stream_put_byte (dos, message->priv->flags, NULL, NULL);
1809   g_data_output_stream_put_byte (dos, 1, NULL, NULL); /* major protocol version */
1810   body_len_offset = g_memory_output_stream_get_data_size (mos);
1811   /* body length - will be filled in later */
1812   g_data_output_stream_put_uint32 (dos, 0xF00DFACE, NULL, NULL);
1813   g_data_output_stream_put_uint32 (dos, message->priv->serial, NULL, NULL);
1814
1815   num_fds_in_message = 0;
1816 #ifdef G_OS_UNIX
1817   if (message->priv->fd_list != NULL)
1818     num_fds_in_message = g_unix_fd_list_get_length (message->priv->fd_list);
1819 #endif
1820   num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
1821   /* TODO: check we have all the right header fields and that they are the correct value etc etc */
1822   if (num_fds_in_message != num_fds_according_to_header)
1823     {
1824       g_set_error (error,
1825                    G_IO_ERROR,
1826                    G_IO_ERROR_INVALID_ARGUMENT,
1827                    _("Message has %d fds but the header field indicates %d fds"),
1828                    num_fds_in_message,
1829                    num_fds_according_to_header);
1830       goto out;
1831     }
1832
1833   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
1834   g_hash_table_iter_init (&hash_iter, message->priv->headers);
1835   while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
1836     {
1837       g_variant_builder_add (&builder,
1838                              "{yv}",
1839                              (guchar) GPOINTER_TO_UINT (key),
1840                              header_value);
1841     }
1842   header_fields = g_variant_builder_end (&builder);
1843
1844   if (!append_value_to_blob (header_fields,
1845                              g_variant_get_type (header_fields),
1846                              mos, dos,
1847                              NULL,
1848                              error))
1849     {
1850       g_variant_unref (header_fields);
1851       goto out;
1852     }
1853   g_variant_unref (header_fields);
1854
1855   /* header size must be a multiple of 8 */
1856   ensure_output_padding (mos, dos, 8);
1857
1858   body_start_offset = g_memory_output_stream_get_data_size (mos);
1859
1860   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
1861   signature_str = NULL;
1862   if (signature != NULL)
1863       signature_str = g_variant_get_string (signature, NULL);
1864   if (message->priv->body != NULL)
1865     {
1866       gchar *tupled_signature_str;
1867       tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
1868       if (signature == NULL)
1869         {
1870           g_set_error (error,
1871                        G_IO_ERROR,
1872                        G_IO_ERROR_INVALID_ARGUMENT,
1873                        _("Message body has signature `%s' but there is no signature header"),
1874                        signature_str);
1875           g_free (tupled_signature_str);
1876           goto out;
1877         }
1878       else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->priv->body)) != 0)
1879         {
1880           g_set_error (error,
1881                        G_IO_ERROR,
1882                        G_IO_ERROR_INVALID_ARGUMENT,
1883                        _("Message body has type signature `%s' but signature in the header field is `%s'"),
1884                        tupled_signature_str, g_variant_get_type_string (message->priv->body));
1885           g_free (tupled_signature_str);
1886           goto out;
1887         }
1888       g_free (tupled_signature_str);
1889       if (!append_body_to_blob (message->priv->body, mos, dos, error))
1890         goto out;
1891     }
1892   else
1893     {
1894       if (signature != NULL)
1895         {
1896           g_set_error (error,
1897                        G_IO_ERROR,
1898                        G_IO_ERROR_INVALID_ARGUMENT,
1899                        _("Message body is empty but signature in the header field is `(%s)'"),
1900                        signature_str);
1901           goto out;
1902         }
1903     }
1904
1905   /* OK, we're done writing the message - set the body length */
1906   size = g_memory_output_stream_get_data_size (mos);
1907   body_size = size - body_start_offset;
1908
1909   if (!g_seekable_seek (G_SEEKABLE (mos), body_len_offset, G_SEEK_SET, NULL, error))
1910     goto out;
1911
1912   g_data_output_stream_put_uint32 (dos, body_size, NULL, NULL);
1913
1914   *out_size = size;
1915   ret = g_memdup (g_memory_output_stream_get_data (mos), size);
1916
1917  out:
1918   g_object_unref (dos);
1919   g_object_unref (mos);
1920
1921   return ret;
1922 }
1923
1924 /* ---------------------------------------------------------------------------------------------------- */
1925
1926 static guint32
1927 get_uint32_header (GDBusMessage            *message,
1928                    GDBusMessageHeaderField  header_field)
1929 {
1930   GVariant *value;
1931   guint32 ret;
1932
1933   ret = 0;
1934   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
1935   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
1936     ret = g_variant_get_uint32 (value);
1937
1938   return ret;
1939 }
1940
1941 static const gchar *
1942 get_string_header (GDBusMessage            *message,
1943                    GDBusMessageHeaderField  header_field)
1944 {
1945   GVariant *value;
1946   const gchar *ret;
1947
1948   ret = NULL;
1949   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
1950   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
1951     ret = g_variant_get_string (value, NULL);
1952
1953   return ret;
1954 }
1955
1956 static const gchar *
1957 get_object_path_header (GDBusMessage            *message,
1958                         GDBusMessageHeaderField  header_field)
1959 {
1960   GVariant *value;
1961   const gchar *ret;
1962
1963   ret = NULL;
1964   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
1965   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
1966     ret = g_variant_get_string (value, NULL);
1967
1968   return ret;
1969 }
1970
1971 static const gchar *
1972 get_signature_header (GDBusMessage            *message,
1973                       GDBusMessageHeaderField  header_field)
1974 {
1975   GVariant *value;
1976   const gchar *ret;
1977
1978   ret = NULL;
1979   value = g_hash_table_lookup (message->priv->headers, GUINT_TO_POINTER (header_field));
1980   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
1981     ret = g_variant_get_string (value, NULL);
1982
1983   return ret;
1984 }
1985
1986 /* ---------------------------------------------------------------------------------------------------- */
1987
1988 static void
1989 set_uint32_header (GDBusMessage             *message,
1990                    GDBusMessageHeaderField   header_field,
1991                    guint32                   value)
1992 {
1993   g_dbus_message_set_header (message,
1994                              header_field,
1995                              g_variant_new_uint32 (value));
1996 }
1997
1998 static void
1999 set_string_header (GDBusMessage             *message,
2000                    GDBusMessageHeaderField   header_field,
2001                    const gchar              *value)
2002 {
2003   g_dbus_message_set_header (message,
2004                              header_field,
2005                              value == NULL ? NULL : g_variant_new_string (value));
2006 }
2007
2008 static void
2009 set_object_path_header (GDBusMessage             *message,
2010                         GDBusMessageHeaderField   header_field,
2011                         const gchar              *value)
2012 {
2013   g_dbus_message_set_header (message,
2014                              header_field,
2015                              value == NULL ? NULL : g_variant_new_object_path (value));
2016 }
2017
2018 static void
2019 set_signature_header (GDBusMessage             *message,
2020                       GDBusMessageHeaderField   header_field,
2021                       const gchar              *value)
2022 {
2023   g_dbus_message_set_header (message,
2024                              header_field,
2025                              value == NULL ? NULL : g_variant_new_signature (value));
2026 }
2027
2028 /* ---------------------------------------------------------------------------------------------------- */
2029
2030 /**
2031  * g_dbus_message_get_reply_serial:
2032  * @message: A #GDBusMessage.
2033  *
2034  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2035  *
2036  * Returns: The value.
2037  *
2038  * Since: 2.26
2039  */
2040 guint32
2041 g_dbus_message_get_reply_serial (GDBusMessage  *message)
2042 {
2043   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2044   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
2045 }
2046
2047 /**
2048  * g_dbus_message_set_reply_serial:
2049  * @message: A #GDBusMessage.
2050  * @value: The value to set.
2051  *
2052  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2053  *
2054  * Since: 2.26
2055  */
2056 void
2057 g_dbus_message_set_reply_serial (GDBusMessage  *message,
2058                                  guint32        value)
2059 {
2060   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2061   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
2062 }
2063
2064 /* ---------------------------------------------------------------------------------------------------- */
2065
2066 /**
2067  * g_dbus_message_get_interface:
2068  * @message: A #GDBusMessage.
2069  *
2070  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2071  *
2072  * Returns: The value.
2073  *
2074  * Since: 2.26
2075  */
2076 const gchar *
2077 g_dbus_message_get_interface (GDBusMessage  *message)
2078 {
2079   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2080   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
2081 }
2082
2083 /**
2084  * g_dbus_message_set_interface:
2085  * @message: A #GDBusMessage.
2086  * @value: The value to set.
2087  *
2088  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2089  *
2090  * Since: 2.26
2091  */
2092 void
2093 g_dbus_message_set_interface (GDBusMessage  *message,
2094                               const gchar   *value)
2095 {
2096   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2097   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2098   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
2099 }
2100
2101 /* ---------------------------------------------------------------------------------------------------- */
2102
2103 /**
2104  * g_dbus_message_get_member:
2105  * @message: A #GDBusMessage.
2106  *
2107  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2108  *
2109  * Returns: The value.
2110  *
2111  * Since: 2.26
2112  */
2113 const gchar *
2114 g_dbus_message_get_member (GDBusMessage  *message)
2115 {
2116   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2117   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
2118 }
2119
2120 /**
2121  * g_dbus_message_set_member:
2122  * @message: A #GDBusMessage.
2123  * @value: The value to set.
2124  *
2125  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2126  *
2127  * Since: 2.26
2128  */
2129 void
2130 g_dbus_message_set_member (GDBusMessage  *message,
2131                            const gchar   *value)
2132 {
2133   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2134   g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
2135   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
2136 }
2137
2138 /* ---------------------------------------------------------------------------------------------------- */
2139
2140 /**
2141  * g_dbus_message_get_path:
2142  * @message: A #GDBusMessage.
2143  *
2144  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2145  *
2146  * Returns: The value.
2147  *
2148  * Since: 2.26
2149  */
2150 const gchar *
2151 g_dbus_message_get_path (GDBusMessage  *message)
2152 {
2153   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2154   return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
2155 }
2156
2157 /**
2158  * g_dbus_message_set_path:
2159  * @message: A #GDBusMessage.
2160  * @value: The value to set.
2161  *
2162  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2163  *
2164  * Since: 2.26
2165  */
2166 void
2167 g_dbus_message_set_path (GDBusMessage  *message,
2168                          const gchar   *value)
2169 {
2170   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2171   g_return_if_fail (value == NULL || g_variant_is_object_path (value));
2172   set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
2173 }
2174
2175 /* ---------------------------------------------------------------------------------------------------- */
2176
2177 /**
2178  * g_dbus_message_get_sender:
2179  * @message: A #GDBusMessage.
2180  *
2181  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2182  *
2183  * Returns: The value.
2184  *
2185  * Since: 2.26
2186  */
2187 const gchar *
2188 g_dbus_message_get_sender (GDBusMessage *message)
2189 {
2190   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2191   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
2192 }
2193
2194 /**
2195  * g_dbus_message_set_sender:
2196  * @message: A #GDBusMessage.
2197  * @value: The value to set.
2198  *
2199  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2200  *
2201  * Since: 2.26
2202  */
2203 void
2204 g_dbus_message_set_sender (GDBusMessage  *message,
2205                            const gchar   *value)
2206 {
2207   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2208   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2209   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
2210 }
2211
2212 /* ---------------------------------------------------------------------------------------------------- */
2213
2214 /**
2215  * g_dbus_message_get_destination:
2216  * @message: A #GDBusMessage.
2217  *
2218  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2219  *
2220  * Returns: The value.
2221  *
2222  * Since: 2.26
2223  */
2224 const gchar *
2225 g_dbus_message_get_destination (GDBusMessage  *message)
2226 {
2227   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2228   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
2229 }
2230
2231 /**
2232  * g_dbus_message_set_destination:
2233  * @message: A #GDBusMessage.
2234  * @value: The value to set.
2235  *
2236  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2237  *
2238  * Since: 2.26
2239  */
2240 void
2241 g_dbus_message_set_destination (GDBusMessage  *message,
2242                                 const gchar   *value)
2243 {
2244   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2245   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2246   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
2247 }
2248
2249 /* ---------------------------------------------------------------------------------------------------- */
2250
2251 /**
2252  * g_dbus_message_get_error_name:
2253  * @message: A #GDBusMessage.
2254  *
2255  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
2256  *
2257  * Returns: The value.
2258  *
2259  * Since: 2.26
2260  */
2261 const gchar *
2262 g_dbus_message_get_error_name (GDBusMessage  *message)
2263 {
2264   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2265   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
2266 }
2267
2268 /**
2269  * g_dbus_message_set_error_name:
2270  * @message: A #GDBusMessage.
2271  * @value: The value to set.
2272  *
2273  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
2274  *
2275  * Since: 2.26
2276  */
2277 void
2278 g_dbus_message_set_error_name (GDBusMessage  *message,
2279                                const gchar   *value)
2280 {
2281   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2282   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2283   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
2284 }
2285
2286 /* ---------------------------------------------------------------------------------------------------- */
2287
2288 /**
2289  * g_dbus_message_get_signature:
2290  * @message: A #GDBusMessage.
2291  *
2292  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
2293  *
2294  * Returns: The value.
2295  *
2296  * Since: 2.26
2297  */
2298 const gchar *
2299 g_dbus_message_get_signature (GDBusMessage  *message)
2300 {
2301   const gchar *ret;
2302   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2303   ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2304   if (ret == NULL)
2305     ret = "";
2306   return ret;
2307 }
2308
2309 /**
2310  * g_dbus_message_set_signature:
2311  * @message: A #GDBusMessage.
2312  * @value: The value to set.
2313  *
2314  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
2315  *
2316  * Since: 2.26
2317  */
2318 void
2319 g_dbus_message_set_signature (GDBusMessage  *message,
2320                               const gchar   *value)
2321 {
2322   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2323   g_return_if_fail (value == NULL || g_variant_is_signature (value));
2324   set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
2325 }
2326
2327 /* ---------------------------------------------------------------------------------------------------- */
2328
2329 /**
2330  * g_dbus_message_get_arg0:
2331  * @message: A #GDBusMessage.
2332  *
2333  * Convenience to get the first item in the body of @message.
2334  *
2335  * Returns: The string item or %NULL if the first item in the body of
2336  * @message is not a string.
2337  *
2338  * Since: 2.26
2339  */
2340 const gchar *
2341 g_dbus_message_get_arg0 (GDBusMessage  *message)
2342 {
2343   const gchar *ret;
2344
2345   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2346
2347   ret = NULL;
2348
2349   if (message->priv->body != NULL && g_variant_is_of_type (message->priv->body, G_VARIANT_TYPE_TUPLE))
2350     {
2351       GVariant *item;
2352       item = g_variant_get_child_value (message->priv->body, 0);
2353       if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING))
2354         ret = g_variant_get_string (item, NULL);
2355     }
2356
2357   return ret;
2358 }
2359
2360 /* ---------------------------------------------------------------------------------------------------- */
2361
2362 /**
2363  * g_dbus_message_get_num_unix_fds:
2364  * @message: A #GDBusMessage.
2365  *
2366  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
2367  *
2368  * Returns: The value.
2369  *
2370  * Since: 2.26
2371  */
2372 guint32
2373 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
2374 {
2375   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2376   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
2377 }
2378
2379 /**
2380  * g_dbus_message_set_num_unix_fds:
2381  * @message: A #GDBusMessage.
2382  * @value: The value to set.
2383  *
2384  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
2385  *
2386  * Since: 2.26
2387  */
2388 void
2389 g_dbus_message_set_num_unix_fds (GDBusMessage  *message,
2390                                  guint32        value)
2391 {
2392   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2393   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
2394 }
2395
2396 /* ---------------------------------------------------------------------------------------------------- */
2397
2398 /**
2399  * g_dbus_message_to_gerror:
2400  * @message: A #GDBusMessage.
2401  * @error: The #GError to set.
2402  *
2403  * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
2404  * nothing and returns %FALSE.
2405  *
2406  * Otherwise this method encodes the error in @message as a #GError
2407  * using g_dbus_error_set_dbus_error() using the information in the
2408  * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
2409  * well as the first string item in @message's body.
2410  *
2411  * Returns: %TRUE if @error was set, %FALSE otherwise.
2412  *
2413  * Since: 2.26
2414  */
2415 gboolean
2416 g_dbus_message_to_gerror (GDBusMessage   *message,
2417                           GError        **error)
2418 {
2419   gboolean ret;
2420   const gchar *error_name;
2421
2422   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
2423
2424   ret = FALSE;
2425   if (message->priv->type != G_DBUS_MESSAGE_TYPE_ERROR)
2426     goto out;
2427
2428   error_name = g_dbus_message_get_error_name (message);
2429   if (error_name != NULL)
2430     {
2431       GVariant *body;
2432
2433       body = g_dbus_message_get_body (message);
2434
2435       if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
2436         {
2437           const gchar *error_message;
2438           g_variant_get (body, "(&s)", &error_message);
2439           g_dbus_error_set_dbus_error (error,
2440                                        error_name,
2441                                        error_message,
2442                                        NULL);
2443         }
2444       else
2445         {
2446           /* these two situations are valid, yet pretty rare */
2447           if (body != NULL)
2448             {
2449               g_dbus_error_set_dbus_error (error,
2450                                            error_name,
2451                                            "",
2452                                            _("Error return with body of type `%s'"),
2453                                            g_variant_get_type_string (body));
2454             }
2455           else
2456             {
2457               g_dbus_error_set_dbus_error (error,
2458                                            error_name,
2459                                            "",
2460                                            _("Error return with empty body"));
2461             }
2462         }
2463     }
2464   else
2465     {
2466       /* TOOD: this shouldn't happen - should check this at message serialization
2467        * time and disconnect the peer.
2468        */
2469       g_set_error (error,
2470                    G_IO_ERROR,
2471                    G_IO_ERROR_FAILED,
2472                    "Error return without error-name header!");
2473     }
2474
2475   ret = TRUE;
2476
2477  out:
2478   return ret;
2479 }
2480
2481 /* ---------------------------------------------------------------------------------------------------- */
2482
2483 static gchar *
2484 enum_to_string (GType enum_type, gint value)
2485 {
2486   gchar *ret;
2487   GEnumClass *klass;
2488   GEnumValue *enum_value;
2489
2490   klass = g_type_class_ref (enum_type);
2491   enum_value = g_enum_get_value (klass, value);
2492   if (enum_value != NULL)
2493     ret = g_strdup (enum_value->value_nick);
2494   else
2495     ret = g_strdup_printf ("unknown (value %d)", value);
2496   g_type_class_unref (klass);
2497   return ret;
2498 }
2499
2500 static gchar *
2501 flags_to_string (GType flags_type, guint value)
2502 {
2503   GString *s;
2504   GFlagsClass *klass;
2505   guint n;
2506
2507   klass = g_type_class_ref (flags_type);
2508   s = g_string_new (NULL);
2509   for (n = 0; n < 32; n++)
2510     {
2511       if ((value & (1<<n)) != 0)
2512         {
2513           GFlagsValue *flags_value;
2514           flags_value = g_flags_get_first_value (klass, (1<<n));
2515           if (s->len > 0)
2516             g_string_append_c (s, ',');
2517           if (flags_value != NULL)
2518             g_string_append (s, flags_value->value_nick);
2519           else
2520             g_string_append_printf (s, "unknown (bit %d)", n);
2521         }
2522     }
2523   if (s->len == 0)
2524     g_string_append (s, "none");
2525   g_type_class_unref (klass);
2526   return g_string_free (s, FALSE);;
2527 }
2528
2529 static gint
2530 _sort_keys_func (gconstpointer a,
2531                  gconstpointer b)
2532 {
2533   gint ia;
2534   gint ib;
2535
2536   ia = GPOINTER_TO_INT (a);
2537   ib = GPOINTER_TO_INT (b);
2538
2539   return ia - ib;
2540 }
2541
2542 /**
2543  * g_dbus_message_print:
2544  * @message: A #GDBusMessage.
2545  * @indent: Indentation level.
2546  *
2547  * Produces a human-readable multi-line description of @message.
2548  *
2549  * The contents of the description has no ABI guarantees, the contents
2550  * and formatting is subject to change at any time. Typical output
2551  * looks something like this:
2552  * <programlisting>
2553  * Type:    method-call
2554  * Flags:   none
2555  * Version: 0
2556  * Serial:  4
2557  * Headers:
2558  *   path -> objectpath '/org/gtk/GDBus/TestObject'
2559  *   interface -> 'org.gtk.GDBus.TestInterface'
2560  *   member -> 'GimmeStdout'
2561  *   destination -> ':1.146'
2562  * Body: ()
2563  * UNIX File Descriptors:
2564  *   (none)
2565  * </programlisting>
2566  * or
2567  * <programlisting>
2568  * Type:    method-return
2569  * Flags:   no-reply-expected
2570  * Version: 0
2571  * Serial:  477
2572  * Headers:
2573  *   reply-serial -> uint32 4
2574  *   destination -> ':1.159'
2575  *   sender -> ':1.146'
2576  *   num-unix-fds -> uint32 1
2577  * Body: ()
2578  * UNIX File Descriptors:
2579  *   fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
2580  * </programlisting>
2581  *
2582  * Returns: A string that should be freed with g_free().
2583  *
2584  * Since: 2.26
2585  */
2586 gchar *
2587 g_dbus_message_print (GDBusMessage *message,
2588                       guint         indent)
2589 {
2590   GString *str;
2591   gchar *s;
2592   GList *keys;
2593   GList *l;
2594
2595   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2596
2597   str = g_string_new (NULL);
2598
2599   s = enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->priv->type);
2600   g_string_append_printf (str, "%*sType:    %s\n", indent, "", s);
2601   g_free (s);
2602   s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->priv->flags);
2603   g_string_append_printf (str, "%*sFlags:   %s\n", indent, "", s);
2604   g_free (s);
2605   g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->priv->major_protocol_version);
2606   g_string_append_printf (str, "%*sSerial:  %d\n", indent, "", message->priv->serial);
2607
2608   g_string_append_printf (str, "%*sHeaders:\n", indent, "");
2609   keys = g_hash_table_get_keys (message->priv->headers);
2610   keys = g_list_sort (keys, _sort_keys_func);
2611   if (keys != NULL)
2612     {
2613       for (l = keys; l != NULL; l = l->next)
2614         {
2615           gint key = GPOINTER_TO_INT (l->data);
2616           GVariant *value;
2617           gchar *value_str;
2618
2619           value = g_hash_table_lookup (message->priv->headers, l->data);
2620           g_assert (value != NULL);
2621
2622           s = enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
2623           value_str = g_variant_print (value, TRUE);
2624           g_string_append_printf (str, "%*s  %s -> %s\n", indent, "", s, value_str);
2625           g_free (s);
2626           g_free (value_str);
2627         }
2628     }
2629   else
2630     {
2631       g_string_append_printf (str, "%*s  (none)\n", indent, "");
2632     }
2633   g_string_append_printf (str, "%*sBody: ", indent, "");
2634   if (message->priv->body != NULL)
2635     {
2636       g_variant_print_string (message->priv->body,
2637                               str,
2638                               TRUE);
2639     }
2640   else
2641     {
2642       g_string_append (str, "()");
2643     }
2644   g_string_append (str, "\n");
2645 #ifdef G_OS_UNIX
2646   g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
2647   if (message->priv->fd_list != NULL)
2648     {
2649       gint num_fds;
2650       const gint *fds;
2651       gint n;
2652
2653       fds = g_unix_fd_list_peek_fds (message->priv->fd_list, &num_fds);
2654       if (num_fds > 0)
2655         {
2656           for (n = 0; n < num_fds; n++)
2657             {
2658               GString *fs;
2659               struct stat statbuf;
2660               fs = g_string_new (NULL);
2661               if (fstat (fds[n], &statbuf) == 0)
2662                 {
2663                   g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
2664                                           major (statbuf.st_dev), minor (statbuf.st_dev));
2665                   g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
2666                                           statbuf.st_mode);
2667                   g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2668                                           (guint64) statbuf.st_ino);
2669                   g_string_append_printf (fs, "%s" "uid=%d", fs->len > 0 ? "," : "",
2670                                           statbuf.st_uid);
2671                   g_string_append_printf (fs, "%s" "gid=%d", fs->len > 0 ? "," : "",
2672                                           statbuf.st_gid);
2673                   g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
2674                                           major (statbuf.st_rdev), minor (statbuf.st_rdev));
2675                   g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2676                                           (guint64) statbuf.st_size);
2677                   g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2678                                           (guint64) statbuf.st_atime);
2679                   g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2680                                           (guint64) statbuf.st_mtime);
2681                   g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
2682                                           (guint64) statbuf.st_ctime);
2683                 }
2684               else
2685                 {
2686                   g_string_append_printf (fs, "(fstat failed: %s)", strerror (errno));
2687                 }
2688               g_string_append_printf (str, "%*s  fd %d: %s\n", indent, "", fds[n], fs->str);
2689               g_string_free (fs, TRUE);
2690             }
2691         }
2692       else
2693         {
2694           g_string_append_printf (str, "%*s  (empty)\n", indent, "");
2695         }
2696     }
2697   else
2698     {
2699       g_string_append_printf (str, "%*s  (none)\n", indent, "");
2700     }
2701 #endif
2702
2703   return g_string_free (str, FALSE);
2704 }
2705
2706
2707 #define __G_DBUS_MESSAGE_C__
2708 #include "gioaliasdef.c"