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