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