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