GDBusMessage: simplify byteswapping
[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, see <http://www.gnu.org/licenses/>.
17  *
18  * Author: David Zeuthen <davidz@redhat.com>
19  */
20
21 /* Uncomment to debug serializer code */
22 /* #define DEBUG_SERIALIZER */
23
24 #include "config.h"
25
26 #include <string.h>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30
31 #if MAJOR_IN_MKDEV
32 #include <sys/mkdev.h>
33 #elif MAJOR_IN_SYSMACROS
34 #include <sys/sysmacros.h>
35 #endif
36
37 #include "gdbusutils.h"
38 #include "gdbusmessage.h"
39 #include "gdbuserror.h"
40 #include "gioenumtypes.h"
41 #include "ginputstream.h"
42 #include "gdatainputstream.h"
43 #include "gmemoryinputstream.h"
44 #include "goutputstream.h"
45 #include "gdataoutputstream.h"
46 #include "gmemoryoutputstream.h"
47 #include "gseekable.h"
48 #include "gioerror.h"
49 #include "gdbusprivate.h"
50
51 #ifdef G_OS_UNIX
52 #include "gunixfdlist.h"
53 #endif
54
55 #include "glibintl.h"
56
57 typedef struct _GMemoryBuffer GMemoryBuffer;
58 struct _GMemoryBuffer
59 {
60   gsize len;
61   gsize valid_len;
62   gsize pos;
63   gchar *data;
64   GDataStreamByteOrder byte_order;
65 };
66
67 static gboolean
68 g_memory_buffer_is_byteswapped (GMemoryBuffer *mbuf)
69 {
70 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
71   return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
72 #else
73   return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
74 #endif
75 }
76
77 static guchar
78 g_memory_buffer_read_byte (GMemoryBuffer  *mbuf)
79 {
80   if (mbuf->pos >= mbuf->valid_len)
81     return 0;
82   return mbuf->data [mbuf->pos++];
83 }
84
85 static gint16
86 g_memory_buffer_read_int16 (GMemoryBuffer  *mbuf)
87 {
88   gint16 v;
89   
90   if (mbuf->pos > mbuf->valid_len - 2)
91     {
92       mbuf->pos = mbuf->valid_len;
93       return 0;
94     }
95
96   memcpy (&v, mbuf->data + mbuf->pos, 2);
97   mbuf->pos += 2;
98
99   if (g_memory_buffer_is_byteswapped (mbuf))
100     v = GUINT16_SWAP_LE_BE (v);
101
102   return v;
103 }
104
105 static guint16
106 g_memory_buffer_read_uint16 (GMemoryBuffer  *mbuf)
107 {
108   guint16 v;
109   
110   if (mbuf->pos > mbuf->valid_len - 2)
111     {
112       mbuf->pos = mbuf->valid_len;
113       return 0;
114     }
115
116   memcpy (&v, mbuf->data + mbuf->pos, 2);
117   mbuf->pos += 2;
118
119   if (g_memory_buffer_is_byteswapped (mbuf))
120     v = GUINT16_SWAP_LE_BE (v);
121
122   return v;
123 }
124
125 static gint32
126 g_memory_buffer_read_int32 (GMemoryBuffer  *mbuf)
127 {
128   gint32 v;
129   
130   if (mbuf->pos > mbuf->valid_len - 4)
131     {
132       mbuf->pos = mbuf->valid_len;
133       return 0;
134     }
135
136   memcpy (&v, mbuf->data + mbuf->pos, 4);
137   mbuf->pos += 4;
138
139   if (g_memory_buffer_is_byteswapped (mbuf))
140     v = GUINT32_SWAP_LE_BE (v);
141
142   return v;
143 }
144
145 static guint32
146 g_memory_buffer_read_uint32 (GMemoryBuffer  *mbuf)
147 {
148   guint32 v;
149   
150   if (mbuf->pos > mbuf->valid_len - 4)
151     {
152       mbuf->pos = mbuf->valid_len;
153       return 0;
154     }
155
156   memcpy (&v, mbuf->data + mbuf->pos, 4);
157   mbuf->pos += 4;
158
159   if (g_memory_buffer_is_byteswapped (mbuf))
160     v = GUINT32_SWAP_LE_BE (v);
161
162   return v;
163 }
164
165 static gint64
166 g_memory_buffer_read_int64 (GMemoryBuffer  *mbuf)
167 {
168   gint64 v;
169   
170   if (mbuf->pos > mbuf->valid_len - 8)
171     {
172       mbuf->pos = mbuf->valid_len;
173       return 0;
174     }
175
176   memcpy (&v, mbuf->data + mbuf->pos, 8);
177   mbuf->pos += 8;
178
179   if (g_memory_buffer_is_byteswapped (mbuf))
180     v = GUINT64_SWAP_LE_BE (v);
181
182   return v;
183 }
184
185 static guint64
186 g_memory_buffer_read_uint64 (GMemoryBuffer  *mbuf)
187 {
188   guint64 v;
189   
190   if (mbuf->pos > mbuf->valid_len - 8)
191     {
192       mbuf->pos = mbuf->valid_len;
193       return 0;
194     }
195
196   memcpy (&v, mbuf->data + mbuf->pos, 8);
197   mbuf->pos += 8;
198
199   if (g_memory_buffer_is_byteswapped (mbuf))
200     v = GUINT64_SWAP_LE_BE (v);
201
202   return v;
203 }
204
205 #define MIN_ARRAY_SIZE  128
206
207 static gint
208 g_nearest_pow (gint num)
209 {
210   gint n = 1;
211
212   while (n < num)
213     n <<= 1;
214
215   return n;
216 }
217
218 static void
219 array_resize (GMemoryBuffer  *mbuf,
220               gsize           size)
221 {
222   gpointer data;
223   gsize len;
224
225   if (mbuf->len == size)
226     return;
227
228   len = mbuf->len;
229   data = g_realloc (mbuf->data, size);
230
231   if (size > len)
232     memset ((guint8 *)data + len, 0, size - len);
233
234   mbuf->data = data;
235   mbuf->len = size;
236
237   if (mbuf->len < mbuf->valid_len)
238     mbuf->valid_len = mbuf->len;
239 }
240
241 static gboolean
242 g_memory_buffer_write (GMemoryBuffer  *mbuf,
243                        const void     *buffer,
244                        gsize           count)
245 {
246   guint8   *dest;
247   gsize new_size;
248
249   if (count == 0)
250     return TRUE;
251
252   /* Check for address space overflow, but only if the buffer is resizable.
253      Otherwise we just do a short write and don't worry. */
254   if (mbuf->pos + count < mbuf->pos)
255     return FALSE;
256
257   if (mbuf->pos + count > mbuf->len)
258     {
259       /* At least enought to fit the write, rounded up
260              for greater than linear growth.
261          TODO: This wastes a lot of memory at large buffer sizes.
262                Figure out a more rational allocation strategy. */
263       new_size = g_nearest_pow (mbuf->pos + count);
264       /* Check for overflow again. We have only checked if
265          pos + count > G_MAXSIZE, but it only catches the case of writing
266          more than 4GiB total on a 32-bit system. There's still the problem
267          of g_nearest_pow overflowing above 0x7fffffff, so we're
268          effectively limited to 2GiB. */
269       if (new_size < mbuf->len)
270         return FALSE;
271
272       new_size = MAX (new_size, MIN_ARRAY_SIZE);
273       array_resize (mbuf, new_size);
274     }
275
276   dest = (guint8 *)mbuf->data + mbuf->pos;
277   memcpy (dest, buffer, count);
278   mbuf->pos += count;
279
280   if (mbuf->pos > mbuf->valid_len)
281     mbuf->valid_len = mbuf->pos;
282
283   return TRUE;
284 }
285
286 static gboolean
287 g_memory_buffer_put_byte (GMemoryBuffer  *mbuf,
288                           guchar          data)
289 {
290   return g_memory_buffer_write (mbuf, &data, 1);
291 }
292
293 static gboolean
294 g_memory_buffer_put_int16 (GMemoryBuffer  *mbuf,
295                            gint16          data)
296 {
297   switch (mbuf->byte_order)
298     {
299     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
300       data = GINT16_TO_BE (data);
301       break;
302     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
303       data = GINT16_TO_LE (data);
304       break;
305     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
306     default:
307       break;
308     }
309   
310   return g_memory_buffer_write (mbuf, &data, 2);
311 }
312
313 static gboolean
314 g_memory_buffer_put_uint16 (GMemoryBuffer  *mbuf,
315                             guint16         data)
316 {
317   switch (mbuf->byte_order)
318     {
319     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
320       data = GUINT16_TO_BE (data);
321       break;
322     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
323       data = GUINT16_TO_LE (data);
324       break;
325     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
326     default:
327       break;
328     }
329   
330   return g_memory_buffer_write (mbuf, &data, 2);
331 }
332
333 static gboolean
334 g_memory_buffer_put_int32 (GMemoryBuffer  *mbuf,
335                            gint32          data)
336 {
337   switch (mbuf->byte_order)
338     {
339     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
340       data = GINT32_TO_BE (data);
341       break;
342     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
343       data = GINT32_TO_LE (data);
344       break;
345     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
346     default:
347       break;
348     }
349   
350   return g_memory_buffer_write (mbuf, &data, 4);
351 }
352
353 static gboolean
354 g_memory_buffer_put_uint32 (GMemoryBuffer  *mbuf,
355                             guint32         data)
356 {
357   switch (mbuf->byte_order)
358     {
359     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
360       data = GUINT32_TO_BE (data);
361       break;
362     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
363       data = GUINT32_TO_LE (data);
364       break;
365     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
366     default:
367       break;
368     }
369   
370   return g_memory_buffer_write (mbuf, &data, 4);
371 }
372
373 static gboolean
374 g_memory_buffer_put_int64 (GMemoryBuffer  *mbuf,
375                            gint64          data)
376 {
377   switch (mbuf->byte_order)
378     {
379     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
380       data = GINT64_TO_BE (data);
381       break;
382     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
383       data = GINT64_TO_LE (data);
384       break;
385     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
386     default:
387       break;
388     }
389   
390   return g_memory_buffer_write (mbuf, &data, 8);
391 }
392
393 static gboolean
394 g_memory_buffer_put_uint64 (GMemoryBuffer  *mbuf,
395                             guint64         data)
396 {
397   switch (mbuf->byte_order)
398     {
399     case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
400       data = GUINT64_TO_BE (data);
401       break;
402     case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
403       data = GUINT64_TO_LE (data);
404       break;
405     case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
406     default:
407       break;
408     }
409   
410   return g_memory_buffer_write (mbuf, &data, 8);
411 }
412
413 static gboolean
414 g_memory_buffer_put_string (GMemoryBuffer  *mbuf,
415                             const char     *str)
416 {
417   g_return_val_if_fail (str != NULL, FALSE);
418
419   return g_memory_buffer_write (mbuf, str, strlen (str));
420 }
421
422
423 /**
424  * SECTION:gdbusmessage
425  * @short_description: D-Bus Message
426  * @include: gio/gio.h
427  *
428  * A type for representing D-Bus messages that can be sent or received
429  * on a #GDBusConnection.
430  */
431
432 typedef struct _GDBusMessageClass GDBusMessageClass;
433
434 /**
435  * GDBusMessageClass:
436  *
437  * Class structure for #GDBusMessage.
438  *
439  * Since: 2.26
440  */
441 struct _GDBusMessageClass
442 {
443   /*< private >*/
444   GObjectClass parent_class;
445 };
446
447 /**
448  * GDBusMessage:
449  *
450  * The #GDBusMessage structure contains only private data and should
451  * only be accessed using the provided API.
452  *
453  * Since: 2.26
454  */
455 struct _GDBusMessage
456 {
457   /*< private >*/
458   GObject parent_instance;
459
460   GDBusMessageType type;
461   GDBusMessageFlags flags;
462   gboolean locked;
463   GDBusMessageByteOrder byte_order;
464   guchar major_protocol_version;
465   guint32 serial;
466   GHashTable *headers;
467   GVariant *body;
468 #ifdef G_OS_UNIX
469   GUnixFDList *fd_list;
470 #endif
471 };
472
473 enum
474 {
475   PROP_0,
476   PROP_LOCKED
477 };
478
479 G_DEFINE_TYPE (GDBusMessage, g_dbus_message, G_TYPE_OBJECT);
480
481 static void
482 g_dbus_message_finalize (GObject *object)
483 {
484   GDBusMessage *message = G_DBUS_MESSAGE (object);
485
486   if (message->headers != NULL)
487     g_hash_table_unref (message->headers);
488   if (message->body != NULL)
489     g_variant_unref (message->body);
490 #ifdef G_OS_UNIX
491   if (message->fd_list != NULL)
492     g_object_unref (message->fd_list);
493 #endif
494
495   if (G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize != NULL)
496     G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize (object);
497 }
498
499 static void
500 g_dbus_message_get_property (GObject    *object,
501                              guint       prop_id,
502                              GValue     *value,
503                              GParamSpec *pspec)
504 {
505   GDBusMessage *message = G_DBUS_MESSAGE (object);
506
507   switch (prop_id)
508     {
509     case PROP_LOCKED:
510       g_value_set_boolean (value, g_dbus_message_get_locked (message));
511       break;
512
513     default:
514       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
515       break;
516     }
517 }
518
519 static void
520 g_dbus_message_class_init (GDBusMessageClass *klass)
521 {
522   GObjectClass *gobject_class;
523
524   gobject_class = G_OBJECT_CLASS (klass);
525   gobject_class->finalize     = g_dbus_message_finalize;
526   gobject_class->get_property = g_dbus_message_get_property;
527
528   /**
529    * GDBusConnection:locked:
530    *
531    * A boolean specifying whether the message is locked.
532    *
533    * Since: 2.26
534    */
535   g_object_class_install_property (gobject_class,
536                                    PROP_LOCKED,
537                                    g_param_spec_boolean ("locked",
538                                                          P_("Locked"),
539                                                          P_("Whether the message is locked"),
540                                                          FALSE,
541                                                          G_PARAM_READABLE |
542                                                          G_PARAM_STATIC_NAME |
543                                                          G_PARAM_STATIC_BLURB |
544                                                          G_PARAM_STATIC_NICK));
545 }
546
547 static void
548 g_dbus_message_init (GDBusMessage *message)
549 {
550   /* Any D-Bus implementation is supposed to handle both Big and
551    * Little Endian encodings and the Endianness is part of the D-Bus
552    * message - we prefer to use Big Endian (since it's Network Byte
553    * Order and just easier to read for humans) but if the machine is
554    * Little Endian we use that for performance reasons.
555    */
556 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
557   message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
558 #else
559   /* this could also be G_PDP_ENDIAN */
560   message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
561 #endif
562   message->headers = g_hash_table_new_full (g_direct_hash,
563                                             g_direct_equal,
564                                             NULL,
565                                             (GDestroyNotify) g_variant_unref);
566 }
567
568 /**
569  * g_dbus_message_new:
570  *
571  * Creates a new empty #GDBusMessage.
572  *
573  * Returns: A #GDBusMessage. Free with g_object_unref().
574  *
575  * Since: 2.26
576  */
577 GDBusMessage *
578 g_dbus_message_new (void)
579 {
580   return g_object_new (G_TYPE_DBUS_MESSAGE, NULL);
581 }
582
583 /**
584  * g_dbus_message_new_method_call:
585  * @name: (allow-none): A valid D-Bus name or %NULL.
586  * @path: A valid object path.
587  * @interface_: (allow-none): A valid D-Bus interface name or %NULL.
588  * @method: A valid method name.
589  *
590  * Creates a new #GDBusMessage for a method call.
591  *
592  * Returns: A #GDBusMessage. Free with g_object_unref().
593  *
594  * Since: 2.26
595  */
596 GDBusMessage *
597 g_dbus_message_new_method_call (const gchar *name,
598                                 const gchar *path,
599                                 const gchar *interface_,
600                                 const gchar *method)
601 {
602   GDBusMessage *message;
603
604   g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
605   g_return_val_if_fail (g_variant_is_object_path (path), NULL);
606   g_return_val_if_fail (g_dbus_is_member_name (method), NULL);
607   g_return_val_if_fail (interface_ == NULL || g_dbus_is_interface_name (interface_), NULL);
608
609   message = g_dbus_message_new ();
610   message->type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
611
612   if (name != NULL)
613     g_dbus_message_set_destination (message, name);
614   g_dbus_message_set_path (message, path);
615   g_dbus_message_set_member (message, method);
616   if (interface_ != NULL)
617     g_dbus_message_set_interface (message, interface_);
618
619   return message;
620 }
621
622 /**
623  * g_dbus_message_new_signal:
624  * @path: A valid object path.
625  * @interface_: A valid D-Bus interface name.
626  * @signal: A valid signal name.
627  *
628  * Creates a new #GDBusMessage for a signal emission.
629  *
630  * Returns: A #GDBusMessage. Free with g_object_unref().
631  *
632  * Since: 2.26
633  */
634 GDBusMessage *
635 g_dbus_message_new_signal (const gchar  *path,
636                            const gchar  *interface_,
637                            const gchar  *signal)
638 {
639   GDBusMessage *message;
640
641   g_return_val_if_fail (g_variant_is_object_path (path), NULL);
642   g_return_val_if_fail (g_dbus_is_member_name (signal), NULL);
643   g_return_val_if_fail (g_dbus_is_interface_name (interface_), NULL);
644
645   message = g_dbus_message_new ();
646   message->type = G_DBUS_MESSAGE_TYPE_SIGNAL;
647   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
648
649   g_dbus_message_set_path (message, path);
650   g_dbus_message_set_member (message, signal);
651   g_dbus_message_set_interface (message, interface_);
652
653   return message;
654 }
655
656
657 /**
658  * g_dbus_message_new_method_reply:
659  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
660  * create a reply message to.
661  *
662  * Creates a new #GDBusMessage that is a reply to @method_call_message.
663  *
664  * Returns: (transfer full):  #GDBusMessage. Free with g_object_unref().
665  *
666  * Since: 2.26
667  */
668 GDBusMessage *
669 g_dbus_message_new_method_reply (GDBusMessage *method_call_message)
670 {
671   GDBusMessage *message;
672   const gchar *sender;
673
674   g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
675   g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
676   g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
677
678   message = g_dbus_message_new ();
679   message->type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
680   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
681   /* reply with same endianness */
682   message->byte_order = method_call_message->byte_order;
683
684   g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
685   sender = g_dbus_message_get_sender (method_call_message);
686   if (sender != NULL)
687     g_dbus_message_set_destination (message, sender);
688
689   return message;
690 }
691
692 /**
693  * g_dbus_message_new_method_error:
694  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
695  * create a reply message to.
696  * @error_name: A valid D-Bus error name.
697  * @error_message_format: The D-Bus error message in a printf() format.
698  * @...: Arguments for @error_message_format.
699  *
700  * Creates a new #GDBusMessage that is an error reply to @method_call_message.
701  *
702  * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
703  *
704  * Since: 2.26
705  */
706 GDBusMessage *
707 g_dbus_message_new_method_error (GDBusMessage             *method_call_message,
708                                  const gchar              *error_name,
709                                  const gchar              *error_message_format,
710                                  ...)
711 {
712   GDBusMessage *ret;
713   va_list var_args;
714
715   va_start (var_args, error_message_format);
716   ret = g_dbus_message_new_method_error_valist (method_call_message,
717                                                 error_name,
718                                                 error_message_format,
719                                                 var_args);
720   va_end (var_args);
721
722   return ret;
723 }
724
725 /**
726  * g_dbus_message_new_method_error_literal:
727  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
728  * create a reply message to.
729  * @error_name: A valid D-Bus error name.
730  * @error_message: The D-Bus error message.
731  *
732  * Creates a new #GDBusMessage that is an error reply to @method_call_message.
733  *
734  * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
735  *
736  * Since: 2.26
737  */
738 GDBusMessage *
739 g_dbus_message_new_method_error_literal (GDBusMessage  *method_call_message,
740                                          const gchar   *error_name,
741                                          const gchar   *error_message)
742 {
743   GDBusMessage *message;
744   const gchar *sender;
745
746   g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
747   g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
748   g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
749   g_return_val_if_fail (g_dbus_is_name (error_name), NULL);
750   g_return_val_if_fail (error_message != NULL, NULL);
751
752   message = g_dbus_message_new ();
753   message->type = G_DBUS_MESSAGE_TYPE_ERROR;
754   message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
755   /* reply with same endianness */
756   message->byte_order = method_call_message->byte_order;
757
758   g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
759   g_dbus_message_set_error_name (message, error_name);
760   g_dbus_message_set_body (message, g_variant_new ("(s)", error_message));
761
762   sender = g_dbus_message_get_sender (method_call_message);
763   if (sender != NULL)
764     g_dbus_message_set_destination (message, sender);
765
766   return message;
767 }
768
769 /**
770  * g_dbus_message_new_method_error_valist:
771  * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
772  * create a reply message to.
773  * @error_name: A valid D-Bus error name.
774  * @error_message_format: The D-Bus error message in a printf() format.
775  * @var_args: Arguments for @error_message_format.
776  *
777  * Like g_dbus_message_new_method_error() but intended for language bindings.
778  *
779  * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
780  *
781  * Since: 2.26
782  */
783 G_GNUC_PRINTF(3, 0)
784 GDBusMessage *
785 g_dbus_message_new_method_error_valist (GDBusMessage             *method_call_message,
786                                         const gchar              *error_name,
787                                         const gchar              *error_message_format,
788                                         va_list                   var_args)
789 {
790   GDBusMessage *ret;
791   gchar *error_message;
792   error_message = g_strdup_vprintf (error_message_format, var_args);
793   ret = g_dbus_message_new_method_error_literal (method_call_message,
794                                                  error_name,
795                                                  error_message);
796   g_free (error_message);
797   return ret;
798 }
799
800 /* ---------------------------------------------------------------------------------------------------- */
801
802 /**
803  * g_dbus_message_get_byte_order:
804  * @message: A #GDBusMessage.
805  *
806  * Gets the byte order of @message.
807  *
808  * Returns: The byte order.
809  */
810 GDBusMessageByteOrder
811 g_dbus_message_get_byte_order (GDBusMessage *message)
812 {
813   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), (GDBusMessageByteOrder) 0);
814   return message->byte_order;
815 }
816
817 /**
818  * g_dbus_message_set_byte_order:
819  * @message: A #GDBusMessage.
820  * @byte_order: The byte order.
821  *
822  * Sets the byte order of @message.
823  */
824 void
825 g_dbus_message_set_byte_order (GDBusMessage          *message,
826                                GDBusMessageByteOrder  byte_order)
827 {
828   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
829
830   if (message->locked)
831     {
832       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
833       return;
834     }
835
836   message->byte_order = byte_order;
837 }
838
839 /* ---------------------------------------------------------------------------------------------------- */
840
841 /* TODO: need GI annotations to specify that any guchar value goes for the type */
842
843 /**
844  * g_dbus_message_get_message_type:
845  * @message: A #GDBusMessage.
846  *
847  * Gets the type of @message.
848  *
849  * Returns: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
850  *
851  * Since: 2.26
852  */
853 GDBusMessageType
854 g_dbus_message_get_message_type (GDBusMessage  *message)
855 {
856   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_TYPE_INVALID);
857   return message->type;
858 }
859
860 /**
861  * g_dbus_message_set_message_type:
862  * @message: A #GDBusMessage.
863  * @type: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
864  *
865  * Sets @message to be of @type.
866  *
867  * Since: 2.26
868  */
869 void
870 g_dbus_message_set_message_type (GDBusMessage      *message,
871                                  GDBusMessageType   type)
872 {
873   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
874   g_return_if_fail (type >=0 && type < 256);
875
876   if (message->locked)
877     {
878       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
879       return;
880     }
881
882   message->type = type;
883 }
884
885 /* ---------------------------------------------------------------------------------------------------- */
886
887 /* TODO: need GI annotations to specify that any guchar value goes for flags */
888
889 /**
890  * g_dbus_message_get_flags:
891  * @message: A #GDBusMessage.
892  *
893  * Gets the flags for @message.
894  *
895  * Returns: Flags that are set (typically values from the #GDBusMessageFlags enumeration bitwise ORed together).
896  *
897  * Since: 2.26
898  */
899 GDBusMessageFlags
900 g_dbus_message_get_flags (GDBusMessage  *message)
901 {
902   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_FLAGS_NONE);
903   return message->flags;
904 }
905
906 /**
907  * g_dbus_message_set_flags:
908  * @message: A #GDBusMessage.
909  * @flags: Flags for @message that are set (typically values from the #GDBusMessageFlags
910  * enumeration bitwise ORed together).
911  *
912  * Sets the flags to set on @message.
913  *
914  * Since: 2.26
915  */
916 void
917 g_dbus_message_set_flags (GDBusMessage       *message,
918                           GDBusMessageFlags   flags)
919 {
920   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
921   g_return_if_fail (flags >=0 && flags < 256);
922
923   if (message->locked)
924     {
925       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
926       return;
927     }
928
929   message->flags = flags;
930 }
931
932 /* ---------------------------------------------------------------------------------------------------- */
933
934 /**
935  * g_dbus_message_get_serial:
936  * @message: A #GDBusMessage.
937  *
938  * Gets the serial for @message.
939  *
940  * Returns: A #guint32.
941  *
942  * Since: 2.26
943  */
944 guint32
945 g_dbus_message_get_serial (GDBusMessage *message)
946 {
947   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
948   return message->serial;
949 }
950
951 /**
952  * g_dbus_message_set_serial:
953  * @message: A #GDBusMessage.
954  * @serial: A #guint32.
955  *
956  * Sets the serial for @message.
957  *
958  * Since: 2.26
959  */
960 void
961 g_dbus_message_set_serial (GDBusMessage  *message,
962                            guint32        serial)
963 {
964   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
965
966   if (message->locked)
967     {
968       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
969       return;
970     }
971
972   message->serial = serial;
973 }
974
975 /* ---------------------------------------------------------------------------------------------------- */
976
977 /* TODO: need GI annotations to specify that any guchar value goes for header_field */
978
979 /**
980  * g_dbus_message_get_header:
981  * @message: A #GDBusMessage.
982  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
983  *
984  * Gets a header field on @message.
985  *
986  * Returns: A #GVariant with the value if the header was found, %NULL
987  * otherwise. Do not free, it is owned by @message.
988  *
989  * Since: 2.26
990  */
991 GVariant *
992 g_dbus_message_get_header (GDBusMessage             *message,
993                            GDBusMessageHeaderField   header_field)
994 {
995   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
996   g_return_val_if_fail (header_field >=0 && header_field < 256, NULL);
997   return g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
998 }
999
1000 /**
1001  * g_dbus_message_set_header:
1002  * @message: A #GDBusMessage.
1003  * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1004  * @value: (allow-none): A #GVariant to set the header field or %NULL to clear the header field.
1005  *
1006  * Sets a header field on @message.
1007  *
1008  * If @value is floating, @message assumes ownership of @value.
1009  *
1010  * Since: 2.26
1011  */
1012 void
1013 g_dbus_message_set_header (GDBusMessage             *message,
1014                            GDBusMessageHeaderField   header_field,
1015                            GVariant                 *value)
1016 {
1017   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1018   g_return_if_fail (header_field >=0 && header_field < 256);
1019
1020   if (message->locked)
1021     {
1022       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1023       return;
1024     }
1025
1026   if (value == NULL)
1027     {
1028       g_hash_table_remove (message->headers, GUINT_TO_POINTER (header_field));
1029     }
1030   else
1031     {
1032       g_hash_table_insert (message->headers, GUINT_TO_POINTER (header_field), g_variant_ref_sink (value));
1033     }
1034 }
1035
1036 /**
1037  * g_dbus_message_get_header_fields:
1038  * @message: A #GDBusMessage.
1039  *
1040  * Gets an array of all header fields on @message that are set.
1041  *
1042  * Returns: (array zero-terminated=1): An array of header fields
1043  * terminated by %G_DBUS_MESSAGE_HEADER_FIELD_INVALID.  Each element
1044  * is a #guchar. Free with g_free().
1045  *
1046  * Since: 2.26
1047  */
1048 guchar *
1049 g_dbus_message_get_header_fields (GDBusMessage  *message)
1050 {
1051   GList *keys;
1052   guchar *ret;
1053   guint num_keys;
1054   GList *l;
1055   guint n;
1056
1057   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1058
1059   keys = g_hash_table_get_keys (message->headers);
1060   num_keys = g_list_length (keys);
1061   ret = g_new (guchar, num_keys + 1);
1062   for (l = keys, n = 0; l != NULL; l = l->next, n++)
1063     ret[n] = GPOINTER_TO_UINT (l->data);
1064   g_assert (n == num_keys);
1065   ret[n] = G_DBUS_MESSAGE_HEADER_FIELD_INVALID;
1066   g_list_free (keys);
1067
1068   return ret;
1069 }
1070
1071 /* ---------------------------------------------------------------------------------------------------- */
1072
1073 /**
1074  * g_dbus_message_get_body:
1075  * @message: A #GDBusMessage.
1076  *
1077  * Gets the body of a message.
1078  *
1079  * Returns: (transfer none): A #GVariant or %NULL if the body is
1080  * empty. Do not free, it is owned by @message.
1081  *
1082  * Since: 2.26
1083  */
1084 GVariant *
1085 g_dbus_message_get_body (GDBusMessage  *message)
1086 {
1087   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1088   return message->body;
1089 }
1090
1091 /**
1092  * g_dbus_message_set_body:
1093  * @message: A #GDBusMessage.
1094  * @body: Either %NULL or a #GVariant that is a tuple.
1095  *
1096  * Sets the body @message. As a side-effect the
1097  * %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field is set to the
1098  * type string of @body (or cleared if @body is %NULL).
1099  *
1100  * If @body is floating, @message assumes ownership of @body.
1101  *
1102  * Since: 2.26
1103  */
1104 void
1105 g_dbus_message_set_body (GDBusMessage  *message,
1106                          GVariant      *body)
1107 {
1108   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1109   g_return_if_fail ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE));
1110
1111   if (message->locked)
1112     {
1113       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1114       return;
1115     }
1116
1117   if (message->body != NULL)
1118     g_variant_unref (message->body);
1119   if (body == NULL)
1120     {
1121       message->body = NULL;
1122       g_dbus_message_set_signature (message, NULL);
1123     }
1124   else
1125     {
1126       const gchar *type_string;
1127       gsize type_string_len;
1128       gchar *signature;
1129
1130       message->body = g_variant_ref_sink (body);
1131
1132       type_string = g_variant_get_type_string (body);
1133       type_string_len = strlen (type_string);
1134       g_assert (type_string_len >= 2);
1135       signature = g_strndup (type_string + 1, type_string_len - 2);
1136       g_dbus_message_set_signature (message, signature);
1137       g_free (signature);
1138     }
1139 }
1140
1141 /* ---------------------------------------------------------------------------------------------------- */
1142
1143 #ifdef G_OS_UNIX
1144 /**
1145  * g_dbus_message_get_unix_fd_list:
1146  * @message: A #GDBusMessage.
1147  *
1148  * Gets the UNIX file descriptors associated with @message, if any.
1149  *
1150  * This method is only available on UNIX.
1151  *
1152  * Returns: (transfer none):A #GUnixFDList or %NULL if no file descriptors are
1153  * associated. Do not free, this object is owned by @message.
1154  *
1155  * Since: 2.26
1156  */
1157 GUnixFDList *
1158 g_dbus_message_get_unix_fd_list (GDBusMessage  *message)
1159 {
1160   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1161   return message->fd_list;
1162 }
1163
1164 /**
1165  * g_dbus_message_set_unix_fd_list:
1166  * @message: A #GDBusMessage.
1167  * @fd_list: (allow-none): A #GUnixFDList or %NULL.
1168  *
1169  * Sets the UNIX file descriptors associated with @message. As a
1170  * side-effect the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header
1171  * field is set to the number of fds in @fd_list (or cleared if
1172  * @fd_list is %NULL).
1173  *
1174  * This method is only available on UNIX.
1175  *
1176  * Since: 2.26
1177  */
1178 void
1179 g_dbus_message_set_unix_fd_list (GDBusMessage  *message,
1180                                  GUnixFDList   *fd_list)
1181 {
1182   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1183   g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
1184
1185   if (message->locked)
1186     {
1187       g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1188       return;
1189     }
1190
1191   if (message->fd_list != NULL)
1192     g_object_unref (message->fd_list);
1193   if (fd_list != NULL)
1194     {
1195       message->fd_list = g_object_ref (fd_list);
1196       g_dbus_message_set_num_unix_fds (message, g_unix_fd_list_get_length (fd_list));
1197     }
1198   else
1199     {
1200       message->fd_list = NULL;
1201       g_dbus_message_set_num_unix_fds (message, 0);
1202     }
1203 }
1204 #endif
1205
1206 /* ---------------------------------------------------------------------------------------------------- */
1207
1208 static gboolean
1209 validate_headers (GDBusMessage  *message,
1210                   GError       **error)
1211 {
1212   gboolean ret;
1213
1214   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1215   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1216
1217   ret = FALSE;
1218
1219   switch (message->type)
1220     {
1221     case G_DBUS_MESSAGE_TYPE_INVALID:
1222       g_set_error_literal (error,
1223                            G_IO_ERROR,
1224                            G_IO_ERROR_INVALID_ARGUMENT,
1225                            _("type is INVALID"));
1226       goto out;
1227       break;
1228
1229     case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
1230       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1231           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1232         {
1233           g_set_error_literal (error,
1234                                G_IO_ERROR,
1235                                G_IO_ERROR_INVALID_ARGUMENT,
1236                                _("METHOD_CALL message: PATH or MEMBER header field is missing"));
1237           goto out;
1238         }
1239       break;
1240
1241     case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
1242       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1243         {
1244           g_set_error_literal (error,
1245                                G_IO_ERROR,
1246                                G_IO_ERROR_INVALID_ARGUMENT,
1247                                _("METHOD_RETURN message: REPLY_SERIAL header field is missing"));
1248           goto out;
1249         }
1250       break;
1251
1252     case G_DBUS_MESSAGE_TYPE_ERROR:
1253       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME) == NULL ||
1254           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1255         {
1256           g_set_error_literal (error,
1257                                G_IO_ERROR,
1258                                G_IO_ERROR_INVALID_ARGUMENT,
1259                                _("ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing"));
1260           goto out;
1261         }
1262       break;
1263
1264     case G_DBUS_MESSAGE_TYPE_SIGNAL:
1265       if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1266           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE) == NULL ||
1267           g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1268         {
1269           g_set_error_literal (error,
1270                                G_IO_ERROR,
1271                                G_IO_ERROR_INVALID_ARGUMENT,
1272                                _("SIGNAL message: PATH, INTERFACE or MEMBER header field is missing"));
1273           goto out;
1274         }
1275       if (g_strcmp0 (g_dbus_message_get_path (message), "/org/freedesktop/DBus/Local") == 0)
1276         {
1277           g_set_error_literal (error,
1278                                G_IO_ERROR,
1279                                G_IO_ERROR_INVALID_ARGUMENT,
1280                                _("SIGNAL message: The PATH header field is using the reserved value /org/freedesktop/DBus/Local"));
1281           goto out;
1282         }
1283       if (g_strcmp0 (g_dbus_message_get_interface (message), "org.freedesktop.DBus.Local") == 0)
1284         {
1285           g_set_error_literal (error,
1286                                G_IO_ERROR,
1287                                G_IO_ERROR_INVALID_ARGUMENT,
1288                                _("SIGNAL message: The INTERFACE header field is using the reserved value org.freedesktop.DBus.Local"));
1289           goto out;
1290         }
1291       break;
1292
1293     default:
1294       /* hitherto unknown type - nothing to check */
1295       break;
1296     }
1297
1298   ret = TRUE;
1299
1300  out:
1301   g_assert (ret || (error == NULL || *error != NULL));
1302   return ret;
1303 }
1304
1305 /* ---------------------------------------------------------------------------------------------------- */
1306
1307 static gboolean
1308 ensure_input_padding (GMemoryBuffer  *buf,
1309                       gsize           padding_size)
1310 {
1311   gsize offset;
1312   gsize wanted_offset;
1313
1314   offset = buf->pos;
1315   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1316   buf->pos = wanted_offset;
1317   return TRUE;
1318 }
1319
1320 static const gchar *
1321 read_string (GMemoryBuffer  *mbuf,
1322              gsize           len,
1323              GError        **error)
1324 {
1325   gchar *str;
1326   const gchar *end_valid;
1327
1328   if (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1329     {
1330       mbuf->pos = mbuf->valid_len;
1331       /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1332       g_set_error (error,
1333                    G_IO_ERROR,
1334                    G_IO_ERROR_INVALID_ARGUMENT,
1335                    g_dngettext (GETTEXT_PACKAGE,
1336                                 "Wanted to read %lu byte but only got %lu",
1337                                 "Wanted to read %lu bytes but only got %lu",
1338                                 (gulong)len),
1339                                 (gulong)len,
1340                    (gulong)(mbuf->valid_len - mbuf->pos));
1341       return NULL;
1342     }
1343
1344   if (mbuf->data[mbuf->pos + len] != '\0')
1345     {
1346       str = g_strndup (mbuf->data + mbuf->pos, len);
1347       g_set_error (error,
1348                    G_IO_ERROR,
1349                    G_IO_ERROR_INVALID_ARGUMENT,
1350                    _("Expected NUL byte after the string '%s' but found byte %d"),
1351                    str, mbuf->data[mbuf->pos + len]);
1352       g_free (str);
1353       mbuf->pos += len + 1;
1354       return NULL;
1355     }
1356
1357   str = mbuf->data + mbuf->pos;
1358   mbuf->pos += len + 1;
1359
1360   if (!g_utf8_validate (str, -1, &end_valid))
1361     {
1362       gint offset;
1363       gchar *valid_str;
1364       offset = (gint) (end_valid - str);
1365       valid_str = g_strndup (str, offset);
1366       g_set_error (error,
1367                    G_IO_ERROR,
1368                    G_IO_ERROR_INVALID_ARGUMENT,
1369                    _("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
1370                      "The valid UTF-8 string up until that point was '%s'"),
1371                    offset,
1372                    (gint) len,
1373                    valid_str);
1374       g_free (valid_str);
1375       return NULL;
1376     }
1377
1378   return str;
1379 }
1380
1381 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
1382
1383 /* returns a non-floating GVariant! */
1384 static GVariant *
1385 parse_value_from_blob (GMemoryBuffer       *buf,
1386                        const GVariantType  *type,
1387                        gboolean             just_align,
1388                        guint                indent,
1389                        GError             **error)
1390 {
1391   GVariant *ret;
1392   GError *local_error;
1393   gboolean is_leaf;
1394   const gchar *type_string;
1395
1396   type_string = g_variant_type_peek_string (type);
1397
1398 #ifdef DEBUG_SERIALIZER
1399     {
1400       gchar *s;
1401       s = g_variant_type_dup_string (type);
1402       g_print ("%*s%s type %s from offset 0x%04x",
1403                indent, "",
1404                just_align ? "Aligning" : "Reading",
1405                s,
1406                (gint) g_seekable_tell (G_SEEKABLE (buf)));
1407       g_free (s);
1408     }
1409 #endif /* DEBUG_SERIALIZER */
1410
1411   ret = NULL;
1412
1413   is_leaf = TRUE;
1414   local_error = NULL;
1415   switch (type_string[0])
1416     {
1417     case 'b': /* G_VARIANT_TYPE_BOOLEAN */
1418       ensure_input_padding (buf, 4);
1419       if (!just_align)
1420         {
1421           gboolean v;
1422           v = g_memory_buffer_read_uint32 (buf);
1423           ret = g_variant_new_boolean (v);
1424         }
1425       break;
1426
1427     case 'y': /* G_VARIANT_TYPE_BYTE */
1428       if (!just_align)
1429         {
1430           guchar v;
1431           v = g_memory_buffer_read_byte (buf);
1432           ret = g_variant_new_byte (v);
1433         }
1434       break;
1435
1436     case 'n': /* G_VARIANT_TYPE_INT16 */
1437       ensure_input_padding (buf, 2);
1438       if (!just_align)
1439         {
1440           gint16 v;
1441           v = g_memory_buffer_read_int16 (buf);
1442           ret = g_variant_new_int16 (v);
1443         }
1444       break;
1445
1446     case 'q': /* G_VARIANT_TYPE_UINT16 */
1447       ensure_input_padding (buf, 2);
1448       if (!just_align)
1449         {
1450           guint16 v;
1451           v = g_memory_buffer_read_uint16 (buf);
1452           ret = g_variant_new_uint16 (v);
1453         }
1454       break;
1455
1456     case 'i': /* G_VARIANT_TYPE_INT32 */
1457       ensure_input_padding (buf, 4);
1458       if (!just_align)
1459         {
1460           gint32 v;
1461           v = g_memory_buffer_read_int32 (buf);
1462           ret = g_variant_new_int32 (v);
1463         }
1464       break;
1465
1466     case 'u': /* G_VARIANT_TYPE_UINT32 */
1467       ensure_input_padding (buf, 4);
1468       if (!just_align)
1469         {
1470           guint32 v;
1471           v = g_memory_buffer_read_uint32 (buf);
1472           ret = g_variant_new_uint32 (v);
1473         }
1474       break;
1475
1476     case 'x': /* G_VARIANT_TYPE_INT64 */
1477       ensure_input_padding (buf, 8);
1478       if (!just_align)
1479         {
1480           gint64 v;
1481           v = g_memory_buffer_read_int64 (buf);
1482           ret = g_variant_new_int64 (v);
1483         }
1484       break;
1485
1486     case 't': /* G_VARIANT_TYPE_UINT64 */
1487       ensure_input_padding (buf, 8);
1488       if (!just_align)
1489         {
1490           guint64 v;
1491           v = g_memory_buffer_read_uint64 (buf);
1492           ret = g_variant_new_uint64 (v);
1493         }
1494       break;
1495
1496     case 'd': /* G_VARIANT_TYPE_DOUBLE */
1497       ensure_input_padding (buf, 8);
1498       if (!just_align)
1499         {
1500           union {
1501             guint64 v_uint64;
1502             gdouble v_double;
1503           } u;
1504           G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
1505           u.v_uint64 = g_memory_buffer_read_uint64 (buf);
1506           ret = g_variant_new_double (u.v_double);
1507         }
1508       break;
1509
1510     case 's': /* G_VARIANT_TYPE_STRING */
1511       ensure_input_padding (buf, 4);
1512       if (!just_align)
1513         {
1514           guint32 len;
1515           const gchar *v;
1516           len = g_memory_buffer_read_uint32 (buf);
1517           v = read_string (buf, (gsize) len, &local_error);
1518           if (v == NULL)
1519             goto fail;
1520           ret = g_variant_new_string (v);
1521         }
1522       break;
1523
1524     case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
1525       ensure_input_padding (buf, 4);
1526       if (!just_align)
1527         {
1528           guint32 len;
1529           const gchar *v;
1530           len = g_memory_buffer_read_uint32 (buf);
1531           v = read_string (buf, (gsize) len, &local_error);
1532           if (v == NULL)
1533             goto fail;
1534           if (!g_variant_is_object_path (v))
1535             {
1536               g_set_error (&local_error,
1537                            G_IO_ERROR,
1538                            G_IO_ERROR_INVALID_ARGUMENT,
1539                            _("Parsed value '%s' is not a valid D-Bus object path"),
1540                            v);
1541               goto fail;
1542             }
1543           ret = g_variant_new_object_path (v);
1544         }
1545       break;
1546
1547     case 'g': /* G_VARIANT_TYPE_SIGNATURE */
1548       if (!just_align)
1549         {
1550           guchar len;
1551           const gchar *v;
1552           len = g_memory_buffer_read_byte (buf);
1553           v = read_string (buf, (gsize) len, &local_error);
1554           if (v == NULL)
1555             goto fail;
1556           if (!g_variant_is_signature (v))
1557             {
1558               g_set_error (&local_error,
1559                            G_IO_ERROR,
1560                            G_IO_ERROR_INVALID_ARGUMENT,
1561                            _("Parsed value '%s' is not a valid D-Bus signature"),
1562                        v);
1563               goto fail;
1564             }
1565           ret = g_variant_new_signature (v);
1566         }
1567       break;
1568
1569     case 'h': /* G_VARIANT_TYPE_HANDLE */
1570       ensure_input_padding (buf, 4);
1571       if (!just_align)
1572         {
1573           gint32 v;
1574           v = g_memory_buffer_read_int32 (buf);
1575           ret = g_variant_new_handle (v);
1576         }
1577       break;
1578
1579     case 'a': /* G_VARIANT_TYPE_ARRAY */
1580       ensure_input_padding (buf, 4);
1581
1582       /* If we are only aligning for this array type, it is the child type of
1583        * another array, which is empty. So, we do not need to add padding for
1584        * this nonexistent array's elements: we only need to align for this
1585        * array itself (4 bytes). See
1586        * <https://bugzilla.gnome.org/show_bug.cgi?id=673612>.
1587        */
1588       if (!just_align)
1589         {
1590           guint32 array_len;
1591           goffset offset;
1592           goffset target;
1593           const GVariantType *element_type;
1594           GVariantBuilder builder;
1595
1596           array_len = g_memory_buffer_read_uint32 (buf);
1597
1598           is_leaf = FALSE;
1599 #ifdef DEBUG_SERIALIZER
1600           g_print (": array spans 0x%04x bytes\n", array_len);
1601 #endif /* DEBUG_SERIALIZER */
1602
1603           if (array_len > (2<<26))
1604             {
1605               /* G_GUINT32_FORMAT doesn't work with gettext, so use u */
1606               g_set_error (&local_error,
1607                            G_IO_ERROR,
1608                            G_IO_ERROR_INVALID_ARGUMENT,
1609                            g_dngettext (GETTEXT_PACKAGE,
1610                                         "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB).",
1611                                         "Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB).",
1612                                         array_len),
1613                            array_len);
1614               goto fail;
1615             }
1616
1617           g_variant_builder_init (&builder, type);
1618           element_type = g_variant_type_element (type);
1619
1620           if (array_len == 0)
1621             {
1622               GVariant *item;
1623               item = parse_value_from_blob (buf,
1624                                             element_type,
1625                                             TRUE,
1626                                             indent + 2,
1627                                             NULL);
1628               g_assert (item == NULL);
1629             }
1630           else
1631             {
1632               /* TODO: optimize array of primitive types */
1633               offset = buf->pos;
1634               target = offset + array_len;
1635               while (offset < target)
1636                 {
1637                   GVariant *item;
1638                   item = parse_value_from_blob (buf,
1639                                                 element_type,
1640                                                 FALSE,
1641                                                 indent + 2,
1642                                                 &local_error);
1643                   if (item == NULL)
1644                     {
1645                       g_variant_builder_clear (&builder);
1646                       goto fail;
1647                     }
1648                   g_variant_builder_add_value (&builder, item);
1649                   g_variant_unref (item);
1650                   offset = buf->pos;
1651                 }
1652             }
1653
1654           ret = g_variant_builder_end (&builder);
1655         }
1656       break;
1657
1658     default:
1659       if (g_variant_type_is_dict_entry (type))
1660         {
1661           const GVariantType *key_type;
1662           const GVariantType *value_type;
1663           GVariant *key;
1664           GVariant *value;
1665
1666           ensure_input_padding (buf, 8);
1667
1668           is_leaf = FALSE;
1669 #ifdef DEBUG_SERIALIZER
1670           g_print ("\n");
1671 #endif /* DEBUG_SERIALIZER */
1672
1673           if (!just_align)
1674             {
1675               key_type = g_variant_type_key (type);
1676               key = parse_value_from_blob (buf,
1677                                            key_type,
1678                                            FALSE,
1679                                            indent + 2,
1680                                            &local_error);
1681               if (key == NULL)
1682                 goto fail;
1683               value_type = g_variant_type_value (type);
1684               value = parse_value_from_blob (buf,
1685                                              value_type,
1686                                              FALSE,
1687                                              indent + 2,
1688                                              &local_error);
1689               if (value == NULL)
1690                 {
1691                   g_variant_unref (key);
1692                   goto fail;
1693                 }
1694               ret = g_variant_new_dict_entry (key, value);
1695               g_variant_unref (key);
1696               g_variant_unref (value);
1697             }
1698         }
1699       else if (g_variant_type_is_tuple (type))
1700         {
1701           ensure_input_padding (buf, 8);
1702
1703           is_leaf = FALSE;
1704 #ifdef DEBUG_SERIALIZER
1705           g_print ("\n");
1706 #endif /* DEBUG_SERIALIZER */
1707
1708           if (!just_align)
1709             {
1710               const GVariantType *element_type;
1711               GVariantBuilder builder;
1712
1713               g_variant_builder_init (&builder, type);
1714               element_type = g_variant_type_first (type);
1715               while (element_type != NULL)
1716                 {
1717                   GVariant *item;
1718                   item = parse_value_from_blob (buf,
1719                                                 element_type,
1720                                                 FALSE,
1721                                                 indent + 2,
1722                                                 &local_error);
1723                   if (item == NULL)
1724                     {
1725                       g_variant_builder_clear (&builder);
1726                       goto fail;
1727                     }
1728                   g_variant_builder_add_value (&builder, item);
1729                   g_variant_unref (item);
1730
1731                   element_type = g_variant_type_next (element_type);
1732                 }
1733               ret = g_variant_builder_end (&builder);
1734             }
1735         }
1736       else if (g_variant_type_is_variant (type))
1737         {
1738           is_leaf = FALSE;
1739 #ifdef DEBUG_SERIALIZER
1740           g_print ("\n");
1741 #endif /* DEBUG_SERIALIZER */
1742
1743           if (!just_align)
1744             {
1745               guchar siglen;
1746               const gchar *sig;
1747               GVariantType *variant_type;
1748               GVariant *value;
1749
1750               siglen = g_memory_buffer_read_byte (buf);
1751               sig = read_string (buf, (gsize) siglen, &local_error);
1752               if (sig == NULL)
1753                 goto fail;
1754               if (!g_variant_is_signature (sig))
1755                 {
1756                   g_set_error (&local_error,
1757                                G_IO_ERROR,
1758                                G_IO_ERROR_INVALID_ARGUMENT,
1759                                _("Parsed value '%s' for variant is not a valid D-Bus signature"),
1760                                sig);
1761                   goto fail;
1762                 }
1763               variant_type = g_variant_type_new (sig);
1764               value = parse_value_from_blob (buf,
1765                                              variant_type,
1766                                              FALSE,
1767                                              indent + 2,
1768                                              &local_error);
1769               g_variant_type_free (variant_type);
1770               if (value == NULL)
1771                 goto fail;
1772               ret = g_variant_new_variant (value);
1773               g_variant_unref (value);
1774             }
1775         }
1776       else
1777         {
1778           gchar *s;
1779           s = g_variant_type_dup_string (type);
1780           g_set_error (&local_error,
1781                        G_IO_ERROR,
1782                        G_IO_ERROR_INVALID_ARGUMENT,
1783                        _("Error deserializing GVariant with type string '%s' from the D-Bus wire format"),
1784                        s);
1785           g_free (s);
1786           goto fail;
1787         }
1788       break;
1789     }
1790
1791   g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
1792
1793 #ifdef DEBUG_SERIALIZER
1794   if (ret != NULL)
1795     {
1796       if (is_leaf)
1797         {
1798           gchar *s;
1799           if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1800             {
1801               s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
1802             }
1803           else
1804             {
1805               s = g_variant_print (ret, FALSE);
1806             }
1807           g_print (": %s\n", s);
1808           g_free (s);
1809         }
1810     }
1811 #else
1812   is_leaf = is_leaf; /* To avoid -Wunused-but-set-variable */
1813 #endif /* DEBUG_SERIALIZER */
1814
1815   /* sink the reference */
1816   if (ret != NULL)
1817     {
1818       g_assert (g_variant_is_floating (ret));
1819       g_variant_ref_sink (ret);
1820     }
1821   return ret;
1822
1823  fail:
1824 #ifdef DEBUG_SERIALIZER
1825   g_print ("\n"
1826            "%*sFAILURE: %s (%s, %d)\n",
1827            indent, "",
1828            local_error->message,
1829            g_quark_to_string (local_error->domain),
1830            local_error->code);
1831 #endif /* DEBUG_SERIALIZER */
1832   g_propagate_error (error, local_error);
1833   return NULL;
1834 }
1835
1836 /* ---------------------------------------------------------------------------------------------------- */
1837
1838 /* message_header must be at least 16 bytes */
1839
1840 /**
1841  * g_dbus_message_bytes_needed:
1842  * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1843  * @blob_len: The length of @blob (must be at least 16).
1844  * @error: Return location for error or %NULL.
1845  *
1846  * Utility function to calculate how many bytes are needed to
1847  * completely deserialize the D-Bus message stored at @blob.
1848  *
1849  * Returns: Number of bytes needed or -1 if @error is set (e.g. if
1850  * @blob contains invalid data or not enough data is available to
1851  * determine the size).
1852  *
1853  * Since: 2.26
1854  */
1855 gssize
1856 g_dbus_message_bytes_needed (guchar  *blob,
1857                              gsize    blob_len,
1858                              GError **error)
1859 {
1860   gssize ret;
1861
1862   ret = -1;
1863
1864   g_return_val_if_fail (blob != NULL, -1);
1865   g_return_val_if_fail (error == NULL || *error == NULL, -1);
1866   g_return_val_if_fail (blob_len >= 16, -1);
1867
1868   if (blob[0] == 'l')
1869     {
1870       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1871       ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
1872       /* round up so it's a multiple of 8 */
1873       ret = 8 * ((ret + 7)/8);
1874       /* finally add the body size */
1875       ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
1876     }
1877   else if (blob[0] == 'B')
1878     {
1879       /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1880       ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
1881       /* round up so it's a multiple of 8 */
1882       ret = 8 * ((ret + 7)/8);
1883       /* finally add the body size */
1884       ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
1885     }
1886   else
1887     {
1888       g_set_error (error,
1889                    G_IO_ERROR,
1890                    G_IO_ERROR_INVALID_ARGUMENT,
1891                    "Unable to determine message blob length - given blob is malformed");
1892     }
1893
1894   if (ret > (2<<27))
1895     {
1896       g_set_error (error,
1897                    G_IO_ERROR,
1898                    G_IO_ERROR_INVALID_ARGUMENT,
1899                    "Blob indicates that message exceeds maximum message length (128MiB)");
1900       ret = -1;
1901     }
1902
1903   return ret;
1904 }
1905
1906 /* ---------------------------------------------------------------------------------------------------- */
1907
1908 /**
1909  * g_dbus_message_new_from_blob:
1910  * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1911  * @blob_len: The length of @blob.
1912  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1913  * @error: Return location for error or %NULL.
1914  *
1915  * Creates a new #GDBusMessage from the data stored at @blob. The byte
1916  * order that the message was in can be retrieved using
1917  * g_dbus_message_get_byte_order().
1918  *
1919  * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
1920  * g_object_unref().
1921  *
1922  * Since: 2.26
1923  */
1924 GDBusMessage *
1925 g_dbus_message_new_from_blob (guchar                *blob,
1926                               gsize                  blob_len,
1927                               GDBusCapabilityFlags   capabilities,
1928                               GError               **error)
1929 {
1930   gboolean ret;
1931   GMemoryBuffer mbuf;
1932   GDBusMessage *message;
1933   guchar endianness;
1934   guchar major_protocol_version;
1935   guint32 message_body_len;
1936   GVariant *headers;
1937   GVariant *item;
1938   GVariantIter iter;
1939   GVariant *signature;
1940
1941   /* TODO: check against @capabilities */
1942
1943   ret = FALSE;
1944
1945   g_return_val_if_fail (blob != NULL, NULL);
1946   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
1947   g_return_val_if_fail (blob_len >= 12, NULL);
1948
1949   message = g_dbus_message_new ();
1950
1951   memset (&mbuf, 0, sizeof (mbuf));
1952   mbuf.data = (gchar *)blob;
1953   mbuf.len = mbuf.valid_len = blob_len;
1954
1955   endianness = g_memory_buffer_read_byte (&mbuf);
1956   switch (endianness)
1957     {
1958     case 'l':
1959       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
1960       message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
1961       break;
1962     case 'B':
1963       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
1964       message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
1965       break;
1966     default:
1967       g_set_error (error,
1968                    G_IO_ERROR,
1969                    G_IO_ERROR_INVALID_ARGUMENT,
1970                    _("Invalid endianness value. Expected 0x6c ('l') or 0x42 ('B') but found value 0x%02x"),
1971                    endianness);
1972       goto out;
1973     }
1974
1975   message->type = g_memory_buffer_read_byte (&mbuf);
1976   message->flags = g_memory_buffer_read_byte (&mbuf);
1977   major_protocol_version = g_memory_buffer_read_byte (&mbuf);
1978   if (major_protocol_version != 1)
1979     {
1980       g_set_error (error,
1981                    G_IO_ERROR,
1982                    G_IO_ERROR_INVALID_ARGUMENT,
1983                    _("Invalid major protocol version. Expected 1 but found %d"),
1984                    major_protocol_version);
1985       goto out;
1986     }
1987   message_body_len = g_memory_buffer_read_uint32 (&mbuf);
1988   message->serial = g_memory_buffer_read_uint32 (&mbuf);
1989
1990 #ifdef DEBUG_SERIALIZER
1991   g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
1992   {
1993     gchar *s;
1994     s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
1995     g_print ("%s\n", s);
1996     g_free (s);
1997   }
1998 #endif /* DEBUG_SERIALIZER */
1999
2000 #ifdef DEBUG_SERIALIZER
2001   g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2002 #endif /* DEBUG_SERIALIZER */
2003   headers = parse_value_from_blob (&mbuf,
2004                                    G_VARIANT_TYPE ("a{yv}"),
2005                                    FALSE,
2006                                    2,
2007                                    error);
2008   if (headers == NULL)
2009     goto out;
2010   g_variant_iter_init (&iter, headers);
2011   while ((item = g_variant_iter_next_value (&iter)) != NULL)
2012     {
2013       guchar header_field;
2014       GVariant *value;
2015       g_variant_get (item,
2016                      "{yv}",
2017                      &header_field,
2018                      &value);
2019       g_dbus_message_set_header (message, header_field, value);
2020       g_variant_unref (value);
2021       g_variant_unref (item);
2022     }
2023   g_variant_unref (headers);
2024
2025   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2026   if (signature != NULL)
2027     {
2028       const gchar *signature_str;
2029       gsize signature_str_len;
2030
2031       signature_str = g_variant_get_string (signature, &signature_str_len);
2032
2033       /* signature but no body */
2034       if (message_body_len == 0 && signature_str_len > 0)
2035         {
2036           g_set_error (error,
2037                        G_IO_ERROR,
2038                        G_IO_ERROR_INVALID_ARGUMENT,
2039                        _("Signature header with signature '%s' found but message body is empty"),
2040                        signature_str);
2041           goto out;
2042         }
2043       else if (signature_str_len > 0)
2044         {
2045           GVariantType *variant_type;
2046           gchar *tupled_signature_str;
2047
2048           if (!g_variant_is_signature (signature_str))
2049             {
2050               g_set_error (error,
2051                            G_IO_ERROR,
2052                            G_IO_ERROR_INVALID_ARGUMENT,
2053                            _("Parsed value '%s' is not a valid D-Bus signature (for body)"),
2054                            signature_str);
2055               goto out;
2056             }
2057           tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2058           variant_type = g_variant_type_new (tupled_signature_str);
2059           g_free (tupled_signature_str);
2060 #ifdef DEBUG_SERIALIZER
2061           g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2062 #endif /* DEBUG_SERIALIZER */
2063           message->body = parse_value_from_blob (&mbuf,
2064                                                  variant_type,
2065                                                  FALSE,
2066                                                  2,
2067                                                  error);
2068           g_variant_type_free (variant_type);
2069           if (message->body == NULL)
2070             goto out;
2071         }
2072     }
2073   else
2074     {
2075       /* no signature, this is only OK if the body is empty */
2076       if (message_body_len != 0)
2077         {
2078           /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
2079           g_set_error (error,
2080                        G_IO_ERROR,
2081                        G_IO_ERROR_INVALID_ARGUMENT,
2082                        g_dngettext (GETTEXT_PACKAGE,
2083                                     "No signature header in message but the message body is %u byte",
2084                                     "No signature header in message but the message body is %u bytes",
2085                                     message_body_len),
2086                        message_body_len);
2087           goto out;
2088         }
2089     }
2090
2091   if (!validate_headers (message, error))
2092     {
2093       g_prefix_error (error, _("Cannot deserialize message: "));
2094       goto out;
2095     }
2096
2097   ret = TRUE;
2098
2099  out:
2100   if (ret)
2101     {
2102       return message;
2103     }
2104   else
2105     {
2106       if (message != NULL)
2107         g_object_unref (message);
2108       return NULL;
2109     }
2110 }
2111
2112 /* ---------------------------------------------------------------------------------------------------- */
2113
2114 static gsize
2115 ensure_output_padding (GMemoryBuffer  *mbuf,
2116                        gsize           padding_size)
2117 {
2118   gsize offset;
2119   gsize wanted_offset;
2120   gsize padding_needed;
2121   guint n;
2122
2123   offset = mbuf->pos;
2124   wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
2125   padding_needed = wanted_offset - offset;
2126
2127   for (n = 0; n < padding_needed; n++)
2128     g_memory_buffer_put_byte (mbuf, '\0');
2129
2130   return padding_needed;
2131 }
2132
2133 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
2134 static gboolean
2135 append_value_to_blob (GVariant            *value,
2136                       const GVariantType  *type,
2137                       GMemoryBuffer       *mbuf,
2138                       gsize               *out_padding_added,
2139                       GError             **error)
2140 {
2141   gsize padding_added;
2142   const gchar *type_string;
2143
2144   type_string = g_variant_type_peek_string (type);
2145
2146   padding_added = 0;
2147
2148   switch (type_string[0])
2149     {
2150     case 'b': /* G_VARIANT_TYPE_BOOLEAN */
2151       padding_added = ensure_output_padding (mbuf, 4);
2152       if (value != NULL)
2153         {
2154           gboolean v = g_variant_get_boolean (value);
2155           g_memory_buffer_put_uint32 (mbuf, v);
2156         }
2157       break;
2158
2159     case 'y': /* G_VARIANT_TYPE_BYTE */
2160       if (value != NULL)
2161         {
2162           guint8 v = g_variant_get_byte (value);
2163           g_memory_buffer_put_byte (mbuf, v);
2164         }
2165       break;
2166
2167     case 'n': /* G_VARIANT_TYPE_INT16 */
2168       padding_added = ensure_output_padding (mbuf, 2);
2169       if (value != NULL)
2170         {
2171           gint16 v = g_variant_get_int16 (value);
2172           g_memory_buffer_put_int16 (mbuf, v);
2173         }
2174       break;
2175
2176     case 'q': /* G_VARIANT_TYPE_UINT16 */
2177       padding_added = ensure_output_padding (mbuf, 2);
2178       if (value != NULL)
2179         {
2180           guint16 v = g_variant_get_uint16 (value);
2181           g_memory_buffer_put_uint16 (mbuf, v);
2182         }
2183       break;
2184
2185     case 'i': /* G_VARIANT_TYPE_INT32 */
2186       padding_added = ensure_output_padding (mbuf, 4);
2187       if (value != NULL)
2188         {
2189           gint32 v = g_variant_get_int32 (value);
2190           g_memory_buffer_put_int32 (mbuf, v);
2191         }
2192       break;
2193
2194     case 'u': /* G_VARIANT_TYPE_UINT32 */
2195       padding_added = ensure_output_padding (mbuf, 4);
2196       if (value != NULL)
2197         {
2198           guint32 v = g_variant_get_uint32 (value);
2199           g_memory_buffer_put_uint32 (mbuf, v);
2200         }
2201       break;
2202
2203     case 'x': /* G_VARIANT_TYPE_INT64 */
2204       padding_added = ensure_output_padding (mbuf, 8);
2205       if (value != NULL)
2206         {
2207           gint64 v = g_variant_get_int64 (value);
2208           g_memory_buffer_put_int64 (mbuf, v);
2209         }
2210       break;
2211
2212     case 't': /* G_VARIANT_TYPE_UINT64 */
2213       padding_added = ensure_output_padding (mbuf, 8);
2214       if (value != NULL)
2215         {
2216           guint64 v = g_variant_get_uint64 (value);
2217           g_memory_buffer_put_uint64 (mbuf, v);
2218         }
2219       break;
2220
2221     case 'd': /* G_VARIANT_TYPE_DOUBLE */
2222       padding_added = ensure_output_padding (mbuf, 8);
2223       if (value != NULL)
2224         {
2225           union {
2226             guint64 v_uint64;
2227             gdouble v_double;
2228           } u;
2229           G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
2230           u.v_double = g_variant_get_double (value);
2231           g_memory_buffer_put_uint64 (mbuf, u.v_uint64);
2232         }
2233       break;
2234
2235     case 's': /* G_VARIANT_TYPE_STRING */
2236       padding_added = ensure_output_padding (mbuf, 4);
2237       if (value != NULL)
2238         {
2239           gsize len;
2240           const gchar *v;
2241           const gchar *end;
2242           v = g_variant_get_string (value, &len);
2243           g_assert (g_utf8_validate (v, -1, &end) && (end == v + len));
2244           g_memory_buffer_put_uint32 (mbuf, len);
2245           g_memory_buffer_put_string (mbuf, v);
2246           g_memory_buffer_put_byte (mbuf, '\0');
2247         }
2248       break;
2249
2250     case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
2251       padding_added = ensure_output_padding (mbuf, 4);
2252       if (value != NULL)
2253         {
2254           gsize len;
2255           const gchar *v = g_variant_get_string (value, &len);
2256           g_assert (g_variant_is_object_path (v));
2257           g_memory_buffer_put_uint32 (mbuf, len);
2258           g_memory_buffer_put_string (mbuf, v);
2259           g_memory_buffer_put_byte (mbuf, '\0');
2260         }
2261       break;
2262
2263     case 'g': /* G_VARIANT_TYPE_SIGNATURE */
2264       if (value != NULL)
2265         {
2266           gsize len;
2267           const gchar *v = g_variant_get_string (value, &len);
2268           g_assert (g_variant_is_signature (v));
2269           g_memory_buffer_put_byte (mbuf, len);
2270           g_memory_buffer_put_string (mbuf, v);
2271           g_memory_buffer_put_byte (mbuf, '\0');
2272         }
2273       break;
2274
2275     case 'h': /* G_VARIANT_TYPE_HANDLE */
2276       padding_added = ensure_output_padding (mbuf, 4);
2277       if (value != NULL)
2278         {
2279           gint32 v = g_variant_get_handle (value);
2280           g_memory_buffer_put_int32 (mbuf, v);
2281         }
2282       break;
2283
2284     case 'a': /* G_VARIANT_TYPE_ARRAY */
2285       {
2286         GVariant *item;
2287         GVariantIter iter;
2288         goffset array_len_offset;
2289         goffset array_payload_begin_offset;
2290         goffset cur_offset;
2291         gsize array_len;
2292
2293         padding_added = ensure_output_padding (mbuf, 4);
2294         if (value != NULL)
2295           {
2296             /* array length - will be filled in later */
2297             array_len_offset = mbuf->valid_len;
2298             g_memory_buffer_put_uint32 (mbuf, 0xF00DFACE);
2299
2300             /* From the D-Bus spec:
2301              *
2302              *   "A UINT32 giving the length of the array data in bytes,
2303              *    followed by alignment padding to the alignment boundary of
2304              *    the array element type, followed by each array element. The
2305              *    array length is from the end of the alignment padding to
2306              *    the end of the last element, i.e. it does not include the
2307              *    padding after the length, or any padding after the last
2308              *    element."
2309              *
2310              * Thus, we need to count how much padding the first element
2311              * contributes and subtract that from the array length.
2312              */
2313             array_payload_begin_offset = mbuf->valid_len;
2314
2315             if (g_variant_n_children (value) == 0)
2316               {
2317                 gsize padding_added_for_item;
2318                 if (!append_value_to_blob (NULL,
2319                                            g_variant_type_element (type),
2320                                            mbuf,
2321                                            &padding_added_for_item,
2322                                            error))
2323                   goto fail;
2324                 array_payload_begin_offset += padding_added_for_item;
2325               }
2326             else
2327               {
2328                 guint n;
2329                 n = 0;
2330                 g_variant_iter_init (&iter, value);
2331                 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2332                   {
2333                     gsize padding_added_for_item;
2334                     if (!append_value_to_blob (item,
2335                                                g_variant_get_type (item),
2336                                                mbuf,
2337                                                &padding_added_for_item,
2338                                                error))
2339                       {
2340                         g_variant_unref (item);
2341                         goto fail;
2342                       }
2343                     g_variant_unref (item);
2344                     if (n == 0)
2345                       {
2346                         array_payload_begin_offset += padding_added_for_item;
2347                       }
2348                     n++;
2349                   }
2350               }
2351
2352             cur_offset = mbuf->valid_len;
2353             array_len = cur_offset - array_payload_begin_offset;
2354             mbuf->pos = array_len_offset;
2355
2356             g_memory_buffer_put_uint32 (mbuf, array_len);
2357             mbuf->pos = cur_offset;
2358           }
2359       }
2360       break;
2361
2362     default:
2363       if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
2364         {
2365           padding_added = ensure_output_padding (mbuf, 8);
2366           if (value != NULL)
2367             {
2368               GVariant *item;
2369               GVariantIter iter;
2370               g_variant_iter_init (&iter, value);
2371               while ((item = g_variant_iter_next_value (&iter)) != NULL)
2372                 {
2373                   if (!append_value_to_blob (item,
2374                                              g_variant_get_type (item),
2375                                              mbuf,
2376                                              NULL,
2377                                              error))
2378                     {
2379                       g_variant_unref (item);
2380                       goto fail;
2381                     }
2382                   g_variant_unref (item);
2383                 }
2384             }
2385         }
2386       else if (g_variant_type_is_variant (type))
2387         {
2388           if (value != NULL)
2389             {
2390               GVariant *child;
2391               const gchar *signature;
2392               child = g_variant_get_child_value (value, 0);
2393               signature = g_variant_get_type_string (child);
2394               g_memory_buffer_put_byte (mbuf, strlen (signature));
2395               g_memory_buffer_put_string (mbuf, signature);
2396               g_memory_buffer_put_byte (mbuf, '\0');
2397               if (!append_value_to_blob (child,
2398                                          g_variant_get_type (child),
2399                                          mbuf,
2400                                          NULL,
2401                                          error))
2402                 {
2403                   g_variant_unref (child);
2404                   goto fail;
2405                 }
2406               g_variant_unref (child);
2407             }
2408         }
2409       else
2410         {
2411           g_set_error (error,
2412                        G_IO_ERROR,
2413                        G_IO_ERROR_INVALID_ARGUMENT,
2414                        _("Error serializing GVariant with type string '%s' to the D-Bus wire format"),
2415                        g_variant_get_type_string (value));
2416           goto fail;
2417         }
2418       break;
2419     }
2420
2421   if (out_padding_added != NULL)
2422     *out_padding_added = padding_added;
2423
2424   return TRUE;
2425
2426  fail:
2427   return FALSE;
2428 }
2429
2430 static gboolean
2431 append_body_to_blob (GVariant       *value,
2432                      GMemoryBuffer  *mbuf,
2433                      GError        **error)
2434 {
2435   GVariant *item;
2436   GVariantIter iter;
2437
2438   if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
2439     {
2440       g_set_error (error,
2441                    G_IO_ERROR,
2442                    G_IO_ERROR_INVALID_ARGUMENT,
2443                    "Expected a tuple for the body of the GDBusMessage.");
2444       goto fail;
2445     }
2446
2447   g_variant_iter_init (&iter, value);
2448   while ((item = g_variant_iter_next_value (&iter)) != NULL)
2449     {
2450       if (!append_value_to_blob (item,
2451                                  g_variant_get_type (item),
2452                                  mbuf,
2453                                  NULL,
2454                                  error))
2455         {
2456           g_variant_unref (item);
2457           goto fail;
2458         }
2459       g_variant_unref (item);
2460     }
2461   return TRUE;
2462
2463  fail:
2464   return FALSE;
2465 }
2466
2467 /* ---------------------------------------------------------------------------------------------------- */
2468
2469 /**
2470  * g_dbus_message_to_blob:
2471  * @message: A #GDBusMessage.
2472  * @out_size: Return location for size of generated blob.
2473  * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2474  * @error: Return location for error.
2475  *
2476  * Serializes @message to a blob. The byte order returned by
2477  * g_dbus_message_get_byte_order() will be used.
2478  *
2479  * Returns: (array length=out_size) (transfer full): A pointer to a
2480  * valid binary D-Bus message of @out_size bytes generated by @message
2481  * or %NULL if @error is set. Free with g_free().
2482  *
2483  * Since: 2.26
2484  */
2485 guchar *
2486 g_dbus_message_to_blob (GDBusMessage          *message,
2487                         gsize                 *out_size,
2488                         GDBusCapabilityFlags   capabilities,
2489                         GError               **error)
2490 {
2491   GMemoryBuffer mbuf;
2492   guchar *ret;
2493   gsize size;
2494   goffset body_len_offset;
2495   goffset body_start_offset;
2496   gsize body_size;
2497   GVariant *header_fields;
2498   GVariantBuilder builder;
2499   GHashTableIter hash_iter;
2500   gpointer key;
2501   GVariant *header_value;
2502   GVariant *signature;
2503   const gchar *signature_str;
2504   gint num_fds_in_message;
2505   gint num_fds_according_to_header;
2506
2507   /* TODO: check against @capabilities */
2508
2509   ret = NULL;
2510
2511   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2512   g_return_val_if_fail (out_size != NULL, NULL);
2513   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2514
2515   memset (&mbuf, 0, sizeof (mbuf));
2516   mbuf.len = MIN_ARRAY_SIZE;
2517   mbuf.data = g_malloc (mbuf.len);
2518
2519   mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN;
2520   switch (message->byte_order)
2521     {
2522     case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
2523       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2524       break;
2525     case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
2526       mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2527       break;
2528     }
2529
2530   /* Core header */
2531   g_memory_buffer_put_byte (&mbuf, (guchar) message->byte_order);
2532   g_memory_buffer_put_byte (&mbuf, message->type);
2533   g_memory_buffer_put_byte (&mbuf, message->flags);
2534   g_memory_buffer_put_byte (&mbuf, 1); /* major protocol version */
2535   body_len_offset = mbuf.valid_len;
2536   /* body length - will be filled in later */
2537   g_memory_buffer_put_uint32 (&mbuf, 0xF00DFACE);
2538   g_memory_buffer_put_uint32 (&mbuf, message->serial);
2539
2540   num_fds_in_message = 0;
2541 #ifdef G_OS_UNIX
2542   if (message->fd_list != NULL)
2543     num_fds_in_message = g_unix_fd_list_get_length (message->fd_list);
2544 #endif
2545   num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
2546   if (num_fds_in_message != num_fds_according_to_header)
2547     {
2548       g_set_error (error,
2549                    G_IO_ERROR,
2550                    G_IO_ERROR_INVALID_ARGUMENT,
2551                    _("Message has %d file descriptors but the header field indicates %d file descriptors"),
2552                    num_fds_in_message,
2553                    num_fds_according_to_header);
2554       goto out;
2555     }
2556
2557   if (!validate_headers (message, error))
2558     {
2559       g_prefix_error (error, _("Cannot serialize message: "));
2560       goto out;
2561     }
2562
2563   g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
2564   g_hash_table_iter_init (&hash_iter, message->headers);
2565   while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
2566     {
2567       g_variant_builder_add (&builder,
2568                              "{yv}",
2569                              (guchar) GPOINTER_TO_UINT (key),
2570                              header_value);
2571     }
2572   header_fields = g_variant_builder_end (&builder);
2573
2574   if (!append_value_to_blob (header_fields,
2575                              g_variant_get_type (header_fields),
2576                              &mbuf,
2577                              NULL,
2578                              error))
2579     {
2580       g_variant_unref (header_fields);
2581       goto out;
2582     }
2583   g_variant_unref (header_fields);
2584
2585   /* header size must be a multiple of 8 */
2586   ensure_output_padding (&mbuf, 8);
2587
2588   body_start_offset = mbuf.valid_len;
2589
2590   signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2591   signature_str = NULL;
2592   if (signature != NULL)
2593       signature_str = g_variant_get_string (signature, NULL);
2594   if (message->body != NULL)
2595     {
2596       gchar *tupled_signature_str;
2597       tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2598       if (signature == NULL)
2599         {
2600           g_set_error (error,
2601                        G_IO_ERROR,
2602                        G_IO_ERROR_INVALID_ARGUMENT,
2603                        _("Message body has signature '%s' but there is no signature header"),
2604                        signature_str);
2605           g_free (tupled_signature_str);
2606           goto out;
2607         }
2608       else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
2609         {
2610           g_set_error (error,
2611                        G_IO_ERROR,
2612                        G_IO_ERROR_INVALID_ARGUMENT,
2613                        _("Message body has type signature '%s' but signature in the header field is '%s'"),
2614                        tupled_signature_str, g_variant_get_type_string (message->body));
2615           g_free (tupled_signature_str);
2616           goto out;
2617         }
2618       g_free (tupled_signature_str);
2619       if (!append_body_to_blob (message->body, &mbuf, error))
2620         goto out;
2621     }
2622   else
2623     {
2624       if (signature != NULL && strlen (signature_str) > 0)
2625         {
2626           g_set_error (error,
2627                        G_IO_ERROR,
2628                        G_IO_ERROR_INVALID_ARGUMENT,
2629                        _("Message body is empty but signature in the header field is '(%s)'"),
2630                        signature_str);
2631           goto out;
2632         }
2633     }
2634
2635   /* OK, we're done writing the message - set the body length */
2636   size = mbuf.valid_len;
2637   body_size = size - body_start_offset;
2638
2639   mbuf.pos = body_len_offset;
2640
2641   g_memory_buffer_put_uint32 (&mbuf, body_size);
2642
2643   *out_size = size;
2644   ret = (guchar *)mbuf.data;
2645
2646  out:
2647   return ret;
2648 }
2649
2650 /* ---------------------------------------------------------------------------------------------------- */
2651
2652 static guint32
2653 get_uint32_header (GDBusMessage            *message,
2654                    GDBusMessageHeaderField  header_field)
2655 {
2656   GVariant *value;
2657   guint32 ret;
2658
2659   ret = 0;
2660   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2661   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
2662     ret = g_variant_get_uint32 (value);
2663
2664   return ret;
2665 }
2666
2667 static const gchar *
2668 get_string_header (GDBusMessage            *message,
2669                    GDBusMessageHeaderField  header_field)
2670 {
2671   GVariant *value;
2672   const gchar *ret;
2673
2674   ret = NULL;
2675   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2676   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
2677     ret = g_variant_get_string (value, NULL);
2678
2679   return ret;
2680 }
2681
2682 static const gchar *
2683 get_object_path_header (GDBusMessage            *message,
2684                         GDBusMessageHeaderField  header_field)
2685 {
2686   GVariant *value;
2687   const gchar *ret;
2688
2689   ret = NULL;
2690   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2691   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
2692     ret = g_variant_get_string (value, NULL);
2693
2694   return ret;
2695 }
2696
2697 static const gchar *
2698 get_signature_header (GDBusMessage            *message,
2699                       GDBusMessageHeaderField  header_field)
2700 {
2701   GVariant *value;
2702   const gchar *ret;
2703
2704   ret = NULL;
2705   value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2706   if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
2707     ret = g_variant_get_string (value, NULL);
2708
2709   return ret;
2710 }
2711
2712 /* ---------------------------------------------------------------------------------------------------- */
2713
2714 static void
2715 set_uint32_header (GDBusMessage             *message,
2716                    GDBusMessageHeaderField   header_field,
2717                    guint32                   value)
2718 {
2719   g_dbus_message_set_header (message,
2720                              header_field,
2721                              g_variant_new_uint32 (value));
2722 }
2723
2724 static void
2725 set_string_header (GDBusMessage             *message,
2726                    GDBusMessageHeaderField   header_field,
2727                    const gchar              *value)
2728 {
2729   g_dbus_message_set_header (message,
2730                              header_field,
2731                              value == NULL ? NULL : g_variant_new_string (value));
2732 }
2733
2734 static void
2735 set_object_path_header (GDBusMessage             *message,
2736                         GDBusMessageHeaderField   header_field,
2737                         const gchar              *value)
2738 {
2739   g_dbus_message_set_header (message,
2740                              header_field,
2741                              value == NULL ? NULL : g_variant_new_object_path (value));
2742 }
2743
2744 static void
2745 set_signature_header (GDBusMessage             *message,
2746                       GDBusMessageHeaderField   header_field,
2747                       const gchar              *value)
2748 {
2749   g_dbus_message_set_header (message,
2750                              header_field,
2751                              value == NULL ? NULL : g_variant_new_signature (value));
2752 }
2753
2754 /* ---------------------------------------------------------------------------------------------------- */
2755
2756 /**
2757  * g_dbus_message_get_reply_serial:
2758  * @message: A #GDBusMessage.
2759  *
2760  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2761  *
2762  * Returns: The value.
2763  *
2764  * Since: 2.26
2765  */
2766 guint32
2767 g_dbus_message_get_reply_serial (GDBusMessage  *message)
2768 {
2769   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2770   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
2771 }
2772
2773 /**
2774  * g_dbus_message_set_reply_serial:
2775  * @message: A #GDBusMessage.
2776  * @value: The value to set.
2777  *
2778  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2779  *
2780  * Since: 2.26
2781  */
2782 void
2783 g_dbus_message_set_reply_serial (GDBusMessage  *message,
2784                                  guint32        value)
2785 {
2786   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2787   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
2788 }
2789
2790 /* ---------------------------------------------------------------------------------------------------- */
2791
2792 /**
2793  * g_dbus_message_get_interface:
2794  * @message: A #GDBusMessage.
2795  *
2796  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2797  *
2798  * Returns: The value.
2799  *
2800  * Since: 2.26
2801  */
2802 const gchar *
2803 g_dbus_message_get_interface (GDBusMessage  *message)
2804 {
2805   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2806   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
2807 }
2808
2809 /**
2810  * g_dbus_message_set_interface:
2811  * @message: A #GDBusMessage.
2812  * @value: The value to set.
2813  *
2814  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2815  *
2816  * Since: 2.26
2817  */
2818 void
2819 g_dbus_message_set_interface (GDBusMessage  *message,
2820                               const gchar   *value)
2821 {
2822   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2823   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2824   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
2825 }
2826
2827 /* ---------------------------------------------------------------------------------------------------- */
2828
2829 /**
2830  * g_dbus_message_get_member:
2831  * @message: A #GDBusMessage.
2832  *
2833  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2834  *
2835  * Returns: The value.
2836  *
2837  * Since: 2.26
2838  */
2839 const gchar *
2840 g_dbus_message_get_member (GDBusMessage  *message)
2841 {
2842   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2843   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
2844 }
2845
2846 /**
2847  * g_dbus_message_set_member:
2848  * @message: A #GDBusMessage.
2849  * @value: The value to set.
2850  *
2851  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2852  *
2853  * Since: 2.26
2854  */
2855 void
2856 g_dbus_message_set_member (GDBusMessage  *message,
2857                            const gchar   *value)
2858 {
2859   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2860   g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
2861   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
2862 }
2863
2864 /* ---------------------------------------------------------------------------------------------------- */
2865
2866 /**
2867  * g_dbus_message_get_path:
2868  * @message: A #GDBusMessage.
2869  *
2870  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2871  *
2872  * Returns: The value.
2873  *
2874  * Since: 2.26
2875  */
2876 const gchar *
2877 g_dbus_message_get_path (GDBusMessage  *message)
2878 {
2879   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2880   return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
2881 }
2882
2883 /**
2884  * g_dbus_message_set_path:
2885  * @message: A #GDBusMessage.
2886  * @value: The value to set.
2887  *
2888  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2889  *
2890  * Since: 2.26
2891  */
2892 void
2893 g_dbus_message_set_path (GDBusMessage  *message,
2894                          const gchar   *value)
2895 {
2896   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2897   g_return_if_fail (value == NULL || g_variant_is_object_path (value));
2898   set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
2899 }
2900
2901 /* ---------------------------------------------------------------------------------------------------- */
2902
2903 /**
2904  * g_dbus_message_get_sender:
2905  * @message: A #GDBusMessage.
2906  *
2907  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2908  *
2909  * Returns: The value.
2910  *
2911  * Since: 2.26
2912  */
2913 const gchar *
2914 g_dbus_message_get_sender (GDBusMessage *message)
2915 {
2916   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2917   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
2918 }
2919
2920 /**
2921  * g_dbus_message_set_sender:
2922  * @message: A #GDBusMessage.
2923  * @value: The value to set.
2924  *
2925  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
2926  *
2927  * Since: 2.26
2928  */
2929 void
2930 g_dbus_message_set_sender (GDBusMessage  *message,
2931                            const gchar   *value)
2932 {
2933   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2934   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2935   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
2936 }
2937
2938 /* ---------------------------------------------------------------------------------------------------- */
2939
2940 /**
2941  * g_dbus_message_get_destination:
2942  * @message: A #GDBusMessage.
2943  *
2944  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2945  *
2946  * Returns: The value.
2947  *
2948  * Since: 2.26
2949  */
2950 const gchar *
2951 g_dbus_message_get_destination (GDBusMessage  *message)
2952 {
2953   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2954   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
2955 }
2956
2957 /**
2958  * g_dbus_message_set_destination:
2959  * @message: A #GDBusMessage.
2960  * @value: The value to set.
2961  *
2962  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
2963  *
2964  * Since: 2.26
2965  */
2966 void
2967 g_dbus_message_set_destination (GDBusMessage  *message,
2968                                 const gchar   *value)
2969 {
2970   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2971   g_return_if_fail (value == NULL || g_dbus_is_name (value));
2972   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
2973 }
2974
2975 /* ---------------------------------------------------------------------------------------------------- */
2976
2977 /**
2978  * g_dbus_message_get_error_name:
2979  * @message: A #GDBusMessage.
2980  *
2981  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
2982  *
2983  * Returns: The value.
2984  *
2985  * Since: 2.26
2986  */
2987 const gchar *
2988 g_dbus_message_get_error_name (GDBusMessage  *message)
2989 {
2990   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2991   return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
2992 }
2993
2994 /**
2995  * g_dbus_message_set_error_name:
2996  * @message: A #GDBusMessage.
2997  * @value: The value to set.
2998  *
2999  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3000  *
3001  * Since: 2.26
3002  */
3003 void
3004 g_dbus_message_set_error_name (GDBusMessage  *message,
3005                                const gchar   *value)
3006 {
3007   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3008   g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
3009   set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
3010 }
3011
3012 /* ---------------------------------------------------------------------------------------------------- */
3013
3014 /**
3015  * g_dbus_message_get_signature:
3016  * @message: A #GDBusMessage.
3017  *
3018  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3019  *
3020  * Returns: The value.
3021  *
3022  * Since: 2.26
3023  */
3024 const gchar *
3025 g_dbus_message_get_signature (GDBusMessage  *message)
3026 {
3027   const gchar *ret;
3028   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3029   ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
3030   if (ret == NULL)
3031     ret = "";
3032   return ret;
3033 }
3034
3035 /**
3036  * g_dbus_message_set_signature:
3037  * @message: A #GDBusMessage.
3038  * @value: The value to set.
3039  *
3040  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3041  *
3042  * Since: 2.26
3043  */
3044 void
3045 g_dbus_message_set_signature (GDBusMessage  *message,
3046                               const gchar   *value)
3047 {
3048   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3049   g_return_if_fail (value == NULL || g_variant_is_signature (value));
3050   set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
3051 }
3052
3053 /* ---------------------------------------------------------------------------------------------------- */
3054
3055 /**
3056  * g_dbus_message_get_arg0:
3057  * @message: A #GDBusMessage.
3058  *
3059  * Convenience to get the first item in the body of @message.
3060  *
3061  * Returns: The string item or %NULL if the first item in the body of
3062  * @message is not a string.
3063  *
3064  * Since: 2.26
3065  */
3066 const gchar *
3067 g_dbus_message_get_arg0 (GDBusMessage  *message)
3068 {
3069   const gchar *ret;
3070
3071   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3072
3073   ret = NULL;
3074
3075   if (message->body != NULL && g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE))
3076     {
3077       GVariant *item;
3078       item = g_variant_get_child_value (message->body, 0);
3079       if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING))
3080         ret = g_variant_get_string (item, NULL);
3081       g_variant_unref (item);
3082     }
3083
3084   return ret;
3085 }
3086
3087 /* ---------------------------------------------------------------------------------------------------- */
3088
3089 /**
3090  * g_dbus_message_get_num_unix_fds:
3091  * @message: A #GDBusMessage.
3092  *
3093  * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3094  *
3095  * Returns: The value.
3096  *
3097  * Since: 2.26
3098  */
3099 guint32
3100 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
3101 {
3102   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3103   return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
3104 }
3105
3106 /**
3107  * g_dbus_message_set_num_unix_fds:
3108  * @message: A #GDBusMessage.
3109  * @value: The value to set.
3110  *
3111  * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3112  *
3113  * Since: 2.26
3114  */
3115 void
3116 g_dbus_message_set_num_unix_fds (GDBusMessage  *message,
3117                                  guint32        value)
3118 {
3119   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3120   set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
3121 }
3122
3123 /* ---------------------------------------------------------------------------------------------------- */
3124
3125 /**
3126  * g_dbus_message_to_gerror:
3127  * @message: A #GDBusMessage.
3128  * @error: The #GError to set.
3129  *
3130  * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
3131  * nothing and returns %FALSE.
3132  *
3133  * Otherwise this method encodes the error in @message as a #GError
3134  * using g_dbus_error_set_dbus_error() using the information in the
3135  * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
3136  * well as the first string item in @message's body.
3137  *
3138  * Returns: %TRUE if @error was set, %FALSE otherwise.
3139  *
3140  * Since: 2.26
3141  */
3142 gboolean
3143 g_dbus_message_to_gerror (GDBusMessage   *message,
3144                           GError        **error)
3145 {
3146   gboolean ret;
3147   const gchar *error_name;
3148
3149   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3150
3151   ret = FALSE;
3152   if (message->type != G_DBUS_MESSAGE_TYPE_ERROR)
3153     goto out;
3154
3155   error_name = g_dbus_message_get_error_name (message);
3156   if (error_name != NULL)
3157     {
3158       GVariant *body;
3159
3160       body = g_dbus_message_get_body (message);
3161
3162       if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
3163         {
3164           const gchar *error_message;
3165           g_variant_get (body, "(&s)", &error_message);
3166           g_dbus_error_set_dbus_error (error,
3167                                        error_name,
3168                                        error_message,
3169                                        NULL);
3170         }
3171       else
3172         {
3173           /* these two situations are valid, yet pretty rare */
3174           if (body != NULL)
3175             {
3176               g_dbus_error_set_dbus_error (error,
3177                                            error_name,
3178                                            "",
3179                                            _("Error return with body of type '%s'"),
3180                                            g_variant_get_type_string (body));
3181             }
3182           else
3183             {
3184               g_dbus_error_set_dbus_error (error,
3185                                            error_name,
3186                                            "",
3187                                            _("Error return with empty body"));
3188             }
3189         }
3190     }
3191   else
3192     {
3193       /* TOOD: this shouldn't happen - should check this at message serialization
3194        * time and disconnect the peer.
3195        */
3196       g_set_error (error,
3197                    G_IO_ERROR,
3198                    G_IO_ERROR_FAILED,
3199                    "Error return without error-name header!");
3200     }
3201
3202   ret = TRUE;
3203
3204  out:
3205   return ret;
3206 }
3207
3208 /* ---------------------------------------------------------------------------------------------------- */
3209
3210 static gchar *
3211 flags_to_string (GType flags_type, guint value)
3212 {
3213   GString *s;
3214   GFlagsClass *klass;
3215   guint n;
3216
3217   klass = g_type_class_ref (flags_type);
3218   s = g_string_new (NULL);
3219   for (n = 0; n < 32; n++)
3220     {
3221       if ((value & (1<<n)) != 0)
3222         {
3223           GFlagsValue *flags_value;
3224           flags_value = g_flags_get_first_value (klass, (1<<n));
3225           if (s->len > 0)
3226             g_string_append_c (s, ',');
3227           if (flags_value != NULL)
3228             g_string_append (s, flags_value->value_nick);
3229           else
3230             g_string_append_printf (s, "unknown (bit %d)", n);
3231         }
3232     }
3233   if (s->len == 0)
3234     g_string_append (s, "none");
3235   g_type_class_unref (klass);
3236   return g_string_free (s, FALSE);
3237 }
3238
3239 static gint
3240 _sort_keys_func (gconstpointer a,
3241                  gconstpointer b)
3242 {
3243   gint ia;
3244   gint ib;
3245
3246   ia = GPOINTER_TO_INT (a);
3247   ib = GPOINTER_TO_INT (b);
3248
3249   return ia - ib;
3250 }
3251
3252 /**
3253  * g_dbus_message_print:
3254  * @message: A #GDBusMessage.
3255  * @indent: Indentation level.
3256  *
3257  * Produces a human-readable multi-line description of @message.
3258  *
3259  * The contents of the description has no ABI guarantees, the contents
3260  * and formatting is subject to change at any time. Typical output
3261  * looks something like this:
3262  * |[
3263  * Type:    method-call
3264  * Flags:   none
3265  * Version: 0
3266  * Serial:  4
3267  * Headers:
3268  *   path -> objectpath '/org/gtk/GDBus/TestObject'
3269  *   interface -> 'org.gtk.GDBus.TestInterface'
3270  *   member -> 'GimmeStdout'
3271  *   destination -> ':1.146'
3272  * Body: ()
3273  * UNIX File Descriptors:
3274  *   (none)
3275  * ]|
3276  * or
3277  * |[
3278  * Type:    method-return
3279  * Flags:   no-reply-expected
3280  * Version: 0
3281  * Serial:  477
3282  * Headers:
3283  *   reply-serial -> uint32 4
3284  *   destination -> ':1.159'
3285  *   sender -> ':1.146'
3286  *   num-unix-fds -> uint32 1
3287  * Body: ()
3288  * UNIX File Descriptors:
3289  *   fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
3290  * ]|
3291  *
3292  * Returns: A string that should be freed with g_free().
3293  *
3294  * Since: 2.26
3295  */
3296 gchar *
3297 g_dbus_message_print (GDBusMessage *message,
3298                       guint         indent)
3299 {
3300   GString *str;
3301   gchar *s;
3302   GList *keys;
3303   GList *l;
3304
3305   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3306
3307   str = g_string_new (NULL);
3308
3309   s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->type);
3310   g_string_append_printf (str, "%*sType:    %s\n", indent, "", s);
3311   g_free (s);
3312   s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->flags);
3313   g_string_append_printf (str, "%*sFlags:   %s\n", indent, "", s);
3314   g_free (s);
3315   g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->major_protocol_version);
3316   g_string_append_printf (str, "%*sSerial:  %d\n", indent, "", message->serial);
3317
3318   g_string_append_printf (str, "%*sHeaders:\n", indent, "");
3319   keys = g_hash_table_get_keys (message->headers);
3320   keys = g_list_sort (keys, _sort_keys_func);
3321   if (keys != NULL)
3322     {
3323       for (l = keys; l != NULL; l = l->next)
3324         {
3325           gint key = GPOINTER_TO_INT (l->data);
3326           GVariant *value;
3327           gchar *value_str;
3328
3329           value = g_hash_table_lookup (message->headers, l->data);
3330           g_assert (value != NULL);
3331
3332           s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
3333           value_str = g_variant_print (value, TRUE);
3334           g_string_append_printf (str, "%*s  %s -> %s\n", indent, "", s, value_str);
3335           g_free (s);
3336           g_free (value_str);
3337         }
3338     }
3339   else
3340     {
3341       g_string_append_printf (str, "%*s  (none)\n", indent, "");
3342     }
3343   g_string_append_printf (str, "%*sBody: ", indent, "");
3344   if (message->body != NULL)
3345     {
3346       g_variant_print_string (message->body,
3347                               str,
3348                               TRUE);
3349     }
3350   else
3351     {
3352       g_string_append (str, "()");
3353     }
3354   g_string_append (str, "\n");
3355 #ifdef G_OS_UNIX
3356   g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
3357   if (message->fd_list != NULL)
3358     {
3359       gint num_fds;
3360       const gint *fds;
3361       gint n;
3362
3363       fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3364       if (num_fds > 0)
3365         {
3366           for (n = 0; n < num_fds; n++)
3367             {
3368               GString *fs;
3369               struct stat statbuf;
3370               fs = g_string_new (NULL);
3371               if (fstat (fds[n], &statbuf) == 0)
3372                 {
3373                   g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
3374                                           major (statbuf.st_dev), minor (statbuf.st_dev));
3375                   g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
3376                                           statbuf.st_mode);
3377                   g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3378                                           (guint64) statbuf.st_ino);
3379                   g_string_append_printf (fs, "%s" "uid=%u", fs->len > 0 ? "," : "",
3380                                           (guint) statbuf.st_uid);
3381                   g_string_append_printf (fs, "%s" "gid=%u", fs->len > 0 ? "," : "",
3382                                           (guint) statbuf.st_gid);
3383                   g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
3384                                           major (statbuf.st_rdev), minor (statbuf.st_rdev));
3385                   g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3386                                           (guint64) statbuf.st_size);
3387                   g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3388                                           (guint64) statbuf.st_atime);
3389                   g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3390                                           (guint64) statbuf.st_mtime);
3391                   g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3392                                           (guint64) statbuf.st_ctime);
3393                 }
3394               else
3395                 {
3396                   g_string_append_printf (fs, "(fstat failed: %s)", strerror (errno));
3397                 }
3398               g_string_append_printf (str, "%*s  fd %d: %s\n", indent, "", fds[n], fs->str);
3399               g_string_free (fs, TRUE);
3400             }
3401         }
3402       else
3403         {
3404           g_string_append_printf (str, "%*s  (empty)\n", indent, "");
3405         }
3406     }
3407   else
3408     {
3409       g_string_append_printf (str, "%*s  (none)\n", indent, "");
3410     }
3411 #endif
3412
3413   return g_string_free (str, FALSE);
3414 }
3415
3416 /**
3417  * g_dbus_message_get_locked:
3418  * @message: A #GDBusMessage.
3419  *
3420  * Checks whether @message is locked. To monitor changes to this
3421  * value, conncet to the #GObject::notify signal to listen for changes
3422  * on the #GDBusMessage:locked property.
3423  *
3424  * Returns: %TRUE if @message is locked, %FALSE otherwise.
3425  *
3426  * Since: 2.26
3427  */
3428 gboolean
3429 g_dbus_message_get_locked (GDBusMessage *message)
3430 {
3431   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3432   return message->locked;
3433 }
3434
3435 /**
3436  * g_dbus_message_lock:
3437  * @message: A #GDBusMessage.
3438  *
3439  * If @message is locked, does nothing. Otherwise locks the message.
3440  *
3441  * Since: 2.26
3442  */
3443 void
3444 g_dbus_message_lock (GDBusMessage *message)
3445 {
3446   g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3447
3448   if (message->locked)
3449     goto out;
3450
3451   message->locked = TRUE;
3452   g_object_notify (G_OBJECT (message), "locked");
3453
3454  out:
3455   ;
3456 }
3457
3458 /**
3459  * g_dbus_message_copy:
3460  * @message: A #GDBusMessage.
3461  * @error: Return location for error or %NULL.
3462  *
3463  * Copies @message. The copy is a deep copy and the returned
3464  * #GDBusMessage is completely identical except that it is guaranteed
3465  * to not be locked.
3466  *
3467  * This operation can fail if e.g. @message contains file descriptors
3468  * and the per-process or system-wide open files limit is reached.
3469  *
3470  * Returns: (transfer full): A new #GDBusMessage or %NULL if @error is set.
3471  *     Free with g_object_unref().
3472  *
3473  * Since: 2.26
3474  */
3475 GDBusMessage *
3476 g_dbus_message_copy (GDBusMessage  *message,
3477                      GError       **error)
3478 {
3479   GDBusMessage *ret;
3480   GHashTableIter iter;
3481   gpointer header_key;
3482   GVariant *header_value;
3483
3484   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3485   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
3486
3487   ret = g_dbus_message_new ();
3488   ret->type                   = message->type;
3489   ret->flags                  = message->flags;
3490   ret->byte_order             = message->byte_order;
3491   ret->major_protocol_version = message->major_protocol_version;
3492   ret->serial                 = message->serial;
3493
3494 #ifdef G_OS_UNIX
3495   if (message->fd_list != NULL)
3496     {
3497       gint n;
3498       gint num_fds;
3499       const gint *fds;
3500
3501       ret->fd_list = g_unix_fd_list_new ();
3502       fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3503       for (n = 0; n < num_fds; n++)
3504         {
3505           if (g_unix_fd_list_append (ret->fd_list,
3506                                      fds[n],
3507                                      error) == -1)
3508             {
3509               g_object_unref (ret);
3510               ret = NULL;
3511               goto out;
3512             }
3513         }
3514     }
3515 #endif
3516
3517   /* see https://bugzilla.gnome.org/show_bug.cgi?id=624546#c8 for why it's fine
3518    * to just ref (as opposed to deep-copying) the GVariant instances
3519    */
3520   ret->body = message->body != NULL ? g_variant_ref (message->body) : NULL;
3521   g_hash_table_iter_init (&iter, message->headers);
3522   while (g_hash_table_iter_next (&iter, &header_key, (gpointer) &header_value))
3523     g_hash_table_insert (ret->headers, header_key, g_variant_ref (header_value));
3524
3525 #ifdef G_OS_UNIX
3526  out:
3527 #endif
3528   return ret;
3529 }