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