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