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