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