Add some more cases to the app-id unit tests
[glib.git] / gio / gdbusmessage.c
blob94b75ff8837399b659ac17d690b92844df87708d
1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
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.
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/>.
18 * Author: David Zeuthen <davidz@redhat.com>
21 /* Uncomment to debug serializer code */
22 /* #define DEBUG_SERIALIZER */
24 #include "config.h"
26 #include <string.h>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
31 #if MAJOR_IN_MKDEV
32 #include <sys/mkdev.h>
33 #elif MAJOR_IN_SYSMACROS
34 #include <sys/sysmacros.h>
35 #endif
37 #include "gdbusutils.h"
38 #include "gdbusmessage.h"
39 #include "gdbuserror.h"
40 #include "gioenumtypes.h"
41 #include "ginputstream.h"
42 #include "gdatainputstream.h"
43 #include "gmemoryinputstream.h"
44 #include "goutputstream.h"
45 #include "gdataoutputstream.h"
46 #include "gmemoryoutputstream.h"
47 #include "gseekable.h"
48 #include "gioerror.h"
49 #include "gdbusprivate.h"
51 #ifdef G_OS_UNIX
52 #include "gunixfdlist.h"
53 #endif
55 #include "glibintl.h"
57 typedef struct _GMemoryBuffer GMemoryBuffer;
58 struct _GMemoryBuffer
60 gsize len;
61 gsize valid_len;
62 gsize pos;
63 gchar *data;
64 GDataStreamByteOrder byte_order;
67 static gboolean
68 g_memory_buffer_is_byteswapped (GMemoryBuffer *mbuf)
70 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
71 return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
72 #else
73 return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
74 #endif
77 static guchar
78 g_memory_buffer_read_byte (GMemoryBuffer *mbuf)
80 if (mbuf->pos >= mbuf->valid_len)
81 return 0;
82 return mbuf->data [mbuf->pos++];
85 static gint16
86 g_memory_buffer_read_int16 (GMemoryBuffer *mbuf)
88 gint16 v;
90 if (mbuf->pos > mbuf->valid_len - 2)
92 mbuf->pos = mbuf->valid_len;
93 return 0;
96 memcpy (&v, mbuf->data + mbuf->pos, 2);
97 mbuf->pos += 2;
99 if (g_memory_buffer_is_byteswapped (mbuf))
100 v = GUINT16_SWAP_LE_BE (v);
102 return v;
105 static guint16
106 g_memory_buffer_read_uint16 (GMemoryBuffer *mbuf)
108 guint16 v;
110 if (mbuf->pos > mbuf->valid_len - 2)
112 mbuf->pos = mbuf->valid_len;
113 return 0;
116 memcpy (&v, mbuf->data + mbuf->pos, 2);
117 mbuf->pos += 2;
119 if (g_memory_buffer_is_byteswapped (mbuf))
120 v = GUINT16_SWAP_LE_BE (v);
122 return v;
125 static gint32
126 g_memory_buffer_read_int32 (GMemoryBuffer *mbuf)
128 gint32 v;
130 if (mbuf->pos > mbuf->valid_len - 4)
132 mbuf->pos = mbuf->valid_len;
133 return 0;
136 memcpy (&v, mbuf->data + mbuf->pos, 4);
137 mbuf->pos += 4;
139 if (g_memory_buffer_is_byteswapped (mbuf))
140 v = GUINT32_SWAP_LE_BE (v);
142 return v;
145 static guint32
146 g_memory_buffer_read_uint32 (GMemoryBuffer *mbuf)
148 guint32 v;
150 if (mbuf->pos > mbuf->valid_len - 4)
152 mbuf->pos = mbuf->valid_len;
153 return 0;
156 memcpy (&v, mbuf->data + mbuf->pos, 4);
157 mbuf->pos += 4;
159 if (g_memory_buffer_is_byteswapped (mbuf))
160 v = GUINT32_SWAP_LE_BE (v);
162 return v;
165 static gint64
166 g_memory_buffer_read_int64 (GMemoryBuffer *mbuf)
168 gint64 v;
170 if (mbuf->pos > mbuf->valid_len - 8)
172 mbuf->pos = mbuf->valid_len;
173 return 0;
176 memcpy (&v, mbuf->data + mbuf->pos, 8);
177 mbuf->pos += 8;
179 if (g_memory_buffer_is_byteswapped (mbuf))
180 v = GUINT64_SWAP_LE_BE (v);
182 return v;
185 static guint64
186 g_memory_buffer_read_uint64 (GMemoryBuffer *mbuf)
188 guint64 v;
190 if (mbuf->pos > mbuf->valid_len - 8)
192 mbuf->pos = mbuf->valid_len;
193 return 0;
196 memcpy (&v, mbuf->data + mbuf->pos, 8);
197 mbuf->pos += 8;
199 if (g_memory_buffer_is_byteswapped (mbuf))
200 v = GUINT64_SWAP_LE_BE (v);
202 return v;
205 #define MIN_ARRAY_SIZE 128
207 static gsize
208 g_nearest_pow (gsize num)
210 gsize n = 1;
212 while (n < num && n > 0)
213 n <<= 1;
215 return n;
218 static void
219 array_resize (GMemoryBuffer *mbuf,
220 gsize size)
222 gpointer data;
223 gsize len;
225 if (mbuf->len == size)
226 return;
228 len = mbuf->len;
229 data = g_realloc (mbuf->data, size);
231 if (size > len)
232 memset ((guint8 *)data + len, 0, size - len);
234 mbuf->data = data;
235 mbuf->len = size;
237 if (mbuf->len < mbuf->valid_len)
238 mbuf->valid_len = mbuf->len;
241 static gboolean
242 g_memory_buffer_write (GMemoryBuffer *mbuf,
243 const void *buffer,
244 gsize count)
246 guint8 *dest;
247 gsize new_size;
249 if (count == 0)
250 return TRUE;
252 /* Check for address space overflow, but only if the buffer is resizable.
253 Otherwise we just do a short write and don't worry. */
254 if (mbuf->pos + count < mbuf->pos)
255 return FALSE;
257 if (mbuf->pos + count > mbuf->len)
259 /* At least enought to fit the write, rounded up
260 for greater than linear growth.
261 TODO: This wastes a lot of memory at large buffer sizes.
262 Figure out a more rational allocation strategy. */
263 new_size = g_nearest_pow (mbuf->pos + count);
264 /* Check for overflow again. We have checked if
265 pos + count > G_MAXSIZE, but now check if g_nearest_pow () has
266 overflowed */
267 if (new_size == 0)
268 return FALSE;
270 new_size = MAX (new_size, MIN_ARRAY_SIZE);
271 array_resize (mbuf, new_size);
274 dest = (guint8 *)mbuf->data + mbuf->pos;
275 memcpy (dest, buffer, count);
276 mbuf->pos += count;
278 if (mbuf->pos > mbuf->valid_len)
279 mbuf->valid_len = mbuf->pos;
281 return TRUE;
284 static gboolean
285 g_memory_buffer_put_byte (GMemoryBuffer *mbuf,
286 guchar data)
288 return g_memory_buffer_write (mbuf, &data, 1);
291 static gboolean
292 g_memory_buffer_put_int16 (GMemoryBuffer *mbuf,
293 gint16 data)
295 switch (mbuf->byte_order)
297 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
298 data = GINT16_TO_BE (data);
299 break;
300 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
301 data = GINT16_TO_LE (data);
302 break;
303 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
304 default:
305 break;
308 return g_memory_buffer_write (mbuf, &data, 2);
311 static gboolean
312 g_memory_buffer_put_uint16 (GMemoryBuffer *mbuf,
313 guint16 data)
315 switch (mbuf->byte_order)
317 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
318 data = GUINT16_TO_BE (data);
319 break;
320 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
321 data = GUINT16_TO_LE (data);
322 break;
323 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
324 default:
325 break;
328 return g_memory_buffer_write (mbuf, &data, 2);
331 static gboolean
332 g_memory_buffer_put_int32 (GMemoryBuffer *mbuf,
333 gint32 data)
335 switch (mbuf->byte_order)
337 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
338 data = GINT32_TO_BE (data);
339 break;
340 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
341 data = GINT32_TO_LE (data);
342 break;
343 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
344 default:
345 break;
348 return g_memory_buffer_write (mbuf, &data, 4);
351 static gboolean
352 g_memory_buffer_put_uint32 (GMemoryBuffer *mbuf,
353 guint32 data)
355 switch (mbuf->byte_order)
357 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
358 data = GUINT32_TO_BE (data);
359 break;
360 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
361 data = GUINT32_TO_LE (data);
362 break;
363 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
364 default:
365 break;
368 return g_memory_buffer_write (mbuf, &data, 4);
371 static gboolean
372 g_memory_buffer_put_int64 (GMemoryBuffer *mbuf,
373 gint64 data)
375 switch (mbuf->byte_order)
377 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
378 data = GINT64_TO_BE (data);
379 break;
380 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
381 data = GINT64_TO_LE (data);
382 break;
383 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
384 default:
385 break;
388 return g_memory_buffer_write (mbuf, &data, 8);
391 static gboolean
392 g_memory_buffer_put_uint64 (GMemoryBuffer *mbuf,
393 guint64 data)
395 switch (mbuf->byte_order)
397 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
398 data = GUINT64_TO_BE (data);
399 break;
400 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
401 data = GUINT64_TO_LE (data);
402 break;
403 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
404 default:
405 break;
408 return g_memory_buffer_write (mbuf, &data, 8);
411 static gboolean
412 g_memory_buffer_put_string (GMemoryBuffer *mbuf,
413 const char *str)
415 g_return_val_if_fail (str != NULL, FALSE);
417 return g_memory_buffer_write (mbuf, str, strlen (str));
422 * SECTION:gdbusmessage
423 * @short_description: D-Bus Message
424 * @include: gio/gio.h
426 * A type for representing D-Bus messages that can be sent or received
427 * on a #GDBusConnection.
430 typedef struct _GDBusMessageClass GDBusMessageClass;
433 * GDBusMessageClass:
435 * Class structure for #GDBusMessage.
437 * Since: 2.26
439 struct _GDBusMessageClass
441 /*< private >*/
442 GObjectClass parent_class;
446 * GDBusMessage:
448 * The #GDBusMessage structure contains only private data and should
449 * only be accessed using the provided API.
451 * Since: 2.26
453 struct _GDBusMessage
455 /*< private >*/
456 GObject parent_instance;
458 GDBusMessageType type;
459 GDBusMessageFlags flags;
460 gboolean locked;
461 GDBusMessageByteOrder byte_order;
462 guchar major_protocol_version;
463 guint32 serial;
464 GHashTable *headers;
465 GVariant *body;
466 #ifdef G_OS_UNIX
467 GUnixFDList *fd_list;
468 #endif
471 enum
473 PROP_0,
474 PROP_LOCKED
477 G_DEFINE_TYPE (GDBusMessage, g_dbus_message, G_TYPE_OBJECT);
479 static void
480 g_dbus_message_finalize (GObject *object)
482 GDBusMessage *message = G_DBUS_MESSAGE (object);
484 if (message->headers != NULL)
485 g_hash_table_unref (message->headers);
486 if (message->body != NULL)
487 g_variant_unref (message->body);
488 #ifdef G_OS_UNIX
489 if (message->fd_list != NULL)
490 g_object_unref (message->fd_list);
491 #endif
493 if (G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize != NULL)
494 G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize (object);
497 static void
498 g_dbus_message_get_property (GObject *object,
499 guint prop_id,
500 GValue *value,
501 GParamSpec *pspec)
503 GDBusMessage *message = G_DBUS_MESSAGE (object);
505 switch (prop_id)
507 case PROP_LOCKED:
508 g_value_set_boolean (value, g_dbus_message_get_locked (message));
509 break;
511 default:
512 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
513 break;
517 static void
518 g_dbus_message_class_init (GDBusMessageClass *klass)
520 GObjectClass *gobject_class;
522 gobject_class = G_OBJECT_CLASS (klass);
523 gobject_class->finalize = g_dbus_message_finalize;
524 gobject_class->get_property = g_dbus_message_get_property;
527 * GDBusConnection:locked:
529 * A boolean specifying whether the message is locked.
531 * Since: 2.26
533 g_object_class_install_property (gobject_class,
534 PROP_LOCKED,
535 g_param_spec_boolean ("locked",
536 P_("Locked"),
537 P_("Whether the message is locked"),
538 FALSE,
539 G_PARAM_READABLE |
540 G_PARAM_STATIC_NAME |
541 G_PARAM_STATIC_BLURB |
542 G_PARAM_STATIC_NICK));
545 static void
546 g_dbus_message_init (GDBusMessage *message)
548 /* Any D-Bus implementation is supposed to handle both Big and
549 * Little Endian encodings and the Endianness is part of the D-Bus
550 * message - we prefer to use Big Endian (since it's Network Byte
551 * Order and just easier to read for humans) but if the machine is
552 * Little Endian we use that for performance reasons.
554 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
555 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
556 #else
557 /* this could also be G_PDP_ENDIAN */
558 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
559 #endif
560 message->headers = g_hash_table_new_full (g_direct_hash,
561 g_direct_equal,
562 NULL,
563 (GDestroyNotify) g_variant_unref);
567 * g_dbus_message_new:
569 * Creates a new empty #GDBusMessage.
571 * Returns: A #GDBusMessage. Free with g_object_unref().
573 * Since: 2.26
575 GDBusMessage *
576 g_dbus_message_new (void)
578 return g_object_new (G_TYPE_DBUS_MESSAGE, NULL);
582 * g_dbus_message_new_method_call:
583 * @name: (nullable): A valid D-Bus name or %NULL.
584 * @path: A valid object path.
585 * @interface_: (nullable): A valid D-Bus interface name or %NULL.
586 * @method: A valid method name.
588 * Creates a new #GDBusMessage for a method call.
590 * Returns: A #GDBusMessage. Free with g_object_unref().
592 * Since: 2.26
594 GDBusMessage *
595 g_dbus_message_new_method_call (const gchar *name,
596 const gchar *path,
597 const gchar *interface_,
598 const gchar *method)
600 GDBusMessage *message;
602 g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
603 g_return_val_if_fail (g_variant_is_object_path (path), NULL);
604 g_return_val_if_fail (g_dbus_is_member_name (method), NULL);
605 g_return_val_if_fail (interface_ == NULL || g_dbus_is_interface_name (interface_), NULL);
607 message = g_dbus_message_new ();
608 message->type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
610 if (name != NULL)
611 g_dbus_message_set_destination (message, name);
612 g_dbus_message_set_path (message, path);
613 g_dbus_message_set_member (message, method);
614 if (interface_ != NULL)
615 g_dbus_message_set_interface (message, interface_);
617 return message;
621 * g_dbus_message_new_signal:
622 * @path: A valid object path.
623 * @interface_: A valid D-Bus interface name.
624 * @signal: A valid signal name.
626 * Creates a new #GDBusMessage for a signal emission.
628 * Returns: A #GDBusMessage. Free with g_object_unref().
630 * Since: 2.26
632 GDBusMessage *
633 g_dbus_message_new_signal (const gchar *path,
634 const gchar *interface_,
635 const gchar *signal)
637 GDBusMessage *message;
639 g_return_val_if_fail (g_variant_is_object_path (path), NULL);
640 g_return_val_if_fail (g_dbus_is_member_name (signal), NULL);
641 g_return_val_if_fail (g_dbus_is_interface_name (interface_), NULL);
643 message = g_dbus_message_new ();
644 message->type = G_DBUS_MESSAGE_TYPE_SIGNAL;
645 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
647 g_dbus_message_set_path (message, path);
648 g_dbus_message_set_member (message, signal);
649 g_dbus_message_set_interface (message, interface_);
651 return message;
656 * g_dbus_message_new_method_reply:
657 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
658 * create a reply message to.
660 * Creates a new #GDBusMessage that is a reply to @method_call_message.
662 * Returns: (transfer full): #GDBusMessage. Free with g_object_unref().
664 * Since: 2.26
666 GDBusMessage *
667 g_dbus_message_new_method_reply (GDBusMessage *method_call_message)
669 GDBusMessage *message;
670 const gchar *sender;
672 g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
673 g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
674 g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
676 message = g_dbus_message_new ();
677 message->type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
678 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
679 /* reply with same endianness */
680 message->byte_order = method_call_message->byte_order;
682 g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
683 sender = g_dbus_message_get_sender (method_call_message);
684 if (sender != NULL)
685 g_dbus_message_set_destination (message, sender);
687 return message;
691 * g_dbus_message_new_method_error:
692 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
693 * create a reply message to.
694 * @error_name: A valid D-Bus error name.
695 * @error_message_format: The D-Bus error message in a printf() format.
696 * @...: Arguments for @error_message_format.
698 * Creates a new #GDBusMessage that is an error reply to @method_call_message.
700 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
702 * Since: 2.26
704 GDBusMessage *
705 g_dbus_message_new_method_error (GDBusMessage *method_call_message,
706 const gchar *error_name,
707 const gchar *error_message_format,
708 ...)
710 GDBusMessage *ret;
711 va_list var_args;
713 va_start (var_args, error_message_format);
714 ret = g_dbus_message_new_method_error_valist (method_call_message,
715 error_name,
716 error_message_format,
717 var_args);
718 va_end (var_args);
720 return ret;
724 * g_dbus_message_new_method_error_literal:
725 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
726 * create a reply message to.
727 * @error_name: A valid D-Bus error name.
728 * @error_message: The D-Bus error message.
730 * Creates a new #GDBusMessage that is an error reply to @method_call_message.
732 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
734 * Since: 2.26
736 GDBusMessage *
737 g_dbus_message_new_method_error_literal (GDBusMessage *method_call_message,
738 const gchar *error_name,
739 const gchar *error_message)
741 GDBusMessage *message;
742 const gchar *sender;
744 g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
745 g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
746 g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
747 g_return_val_if_fail (g_dbus_is_name (error_name), NULL);
748 g_return_val_if_fail (error_message != NULL, NULL);
750 message = g_dbus_message_new ();
751 message->type = G_DBUS_MESSAGE_TYPE_ERROR;
752 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
753 /* reply with same endianness */
754 message->byte_order = method_call_message->byte_order;
756 g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
757 g_dbus_message_set_error_name (message, error_name);
758 g_dbus_message_set_body (message, g_variant_new ("(s)", error_message));
760 sender = g_dbus_message_get_sender (method_call_message);
761 if (sender != NULL)
762 g_dbus_message_set_destination (message, sender);
764 return message;
768 * g_dbus_message_new_method_error_valist:
769 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
770 * create a reply message to.
771 * @error_name: A valid D-Bus error name.
772 * @error_message_format: The D-Bus error message in a printf() format.
773 * @var_args: Arguments for @error_message_format.
775 * Like g_dbus_message_new_method_error() but intended for language bindings.
777 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
779 * Since: 2.26
781 G_GNUC_PRINTF(3, 0)
782 GDBusMessage *
783 g_dbus_message_new_method_error_valist (GDBusMessage *method_call_message,
784 const gchar *error_name,
785 const gchar *error_message_format,
786 va_list var_args)
788 GDBusMessage *ret;
789 gchar *error_message;
790 error_message = g_strdup_vprintf (error_message_format, var_args);
791 ret = g_dbus_message_new_method_error_literal (method_call_message,
792 error_name,
793 error_message);
794 g_free (error_message);
795 return ret;
798 /* ---------------------------------------------------------------------------------------------------- */
801 * g_dbus_message_get_byte_order:
802 * @message: A #GDBusMessage.
804 * Gets the byte order of @message.
806 * Returns: The byte order.
808 GDBusMessageByteOrder
809 g_dbus_message_get_byte_order (GDBusMessage *message)
811 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), (GDBusMessageByteOrder) 0);
812 return message->byte_order;
816 * g_dbus_message_set_byte_order:
817 * @message: A #GDBusMessage.
818 * @byte_order: The byte order.
820 * Sets the byte order of @message.
822 void
823 g_dbus_message_set_byte_order (GDBusMessage *message,
824 GDBusMessageByteOrder byte_order)
826 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
828 if (message->locked)
830 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
831 return;
834 message->byte_order = byte_order;
837 /* ---------------------------------------------------------------------------------------------------- */
839 /* TODO: need GI annotations to specify that any guchar value goes for the type */
842 * g_dbus_message_get_message_type:
843 * @message: A #GDBusMessage.
845 * Gets the type of @message.
847 * Returns: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
849 * Since: 2.26
851 GDBusMessageType
852 g_dbus_message_get_message_type (GDBusMessage *message)
854 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_TYPE_INVALID);
855 return message->type;
859 * g_dbus_message_set_message_type:
860 * @message: A #GDBusMessage.
861 * @type: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
863 * Sets @message to be of @type.
865 * Since: 2.26
867 void
868 g_dbus_message_set_message_type (GDBusMessage *message,
869 GDBusMessageType type)
871 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
872 g_return_if_fail (type >=0 && type < 256);
874 if (message->locked)
876 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
877 return;
880 message->type = type;
883 /* ---------------------------------------------------------------------------------------------------- */
885 /* TODO: need GI annotations to specify that any guchar value goes for flags */
888 * g_dbus_message_get_flags:
889 * @message: A #GDBusMessage.
891 * Gets the flags for @message.
893 * Returns: Flags that are set (typically values from the #GDBusMessageFlags enumeration bitwise ORed together).
895 * Since: 2.26
897 GDBusMessageFlags
898 g_dbus_message_get_flags (GDBusMessage *message)
900 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_FLAGS_NONE);
901 return message->flags;
905 * g_dbus_message_set_flags:
906 * @message: A #GDBusMessage.
907 * @flags: Flags for @message that are set (typically values from the #GDBusMessageFlags
908 * enumeration bitwise ORed together).
910 * Sets the flags to set on @message.
912 * Since: 2.26
914 void
915 g_dbus_message_set_flags (GDBusMessage *message,
916 GDBusMessageFlags flags)
918 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
919 g_return_if_fail (flags >=0 && flags < 256);
921 if (message->locked)
923 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
924 return;
927 message->flags = flags;
930 /* ---------------------------------------------------------------------------------------------------- */
933 * g_dbus_message_get_serial:
934 * @message: A #GDBusMessage.
936 * Gets the serial for @message.
938 * Returns: A #guint32.
940 * Since: 2.26
942 guint32
943 g_dbus_message_get_serial (GDBusMessage *message)
945 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
946 return message->serial;
950 * g_dbus_message_set_serial:
951 * @message: A #GDBusMessage.
952 * @serial: A #guint32.
954 * Sets the serial for @message.
956 * Since: 2.26
958 void
959 g_dbus_message_set_serial (GDBusMessage *message,
960 guint32 serial)
962 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
964 if (message->locked)
966 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
967 return;
970 message->serial = serial;
973 /* ---------------------------------------------------------------------------------------------------- */
975 /* TODO: need GI annotations to specify that any guchar value goes for header_field */
978 * g_dbus_message_get_header:
979 * @message: A #GDBusMessage.
980 * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
982 * Gets a header field on @message.
984 * Returns: A #GVariant with the value if the header was found, %NULL
985 * otherwise. Do not free, it is owned by @message.
987 * Since: 2.26
989 GVariant *
990 g_dbus_message_get_header (GDBusMessage *message,
991 GDBusMessageHeaderField header_field)
993 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
994 g_return_val_if_fail (header_field >=0 && header_field < 256, NULL);
995 return g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
999 * g_dbus_message_set_header:
1000 * @message: A #GDBusMessage.
1001 * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1002 * @value: (nullable): A #GVariant to set the header field or %NULL to clear the header field.
1004 * Sets a header field on @message.
1006 * If @value is floating, @message assumes ownership of @value.
1008 * Since: 2.26
1010 void
1011 g_dbus_message_set_header (GDBusMessage *message,
1012 GDBusMessageHeaderField header_field,
1013 GVariant *value)
1015 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1016 g_return_if_fail (header_field >=0 && header_field < 256);
1018 if (message->locked)
1020 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1021 return;
1024 if (value == NULL)
1026 g_hash_table_remove (message->headers, GUINT_TO_POINTER (header_field));
1028 else
1030 g_hash_table_insert (message->headers, GUINT_TO_POINTER (header_field), g_variant_ref_sink (value));
1035 * g_dbus_message_get_header_fields:
1036 * @message: A #GDBusMessage.
1038 * Gets an array of all header fields on @message that are set.
1040 * Returns: (array zero-terminated=1): An array of header fields
1041 * terminated by %G_DBUS_MESSAGE_HEADER_FIELD_INVALID. Each element
1042 * is a #guchar. Free with g_free().
1044 * Since: 2.26
1046 guchar *
1047 g_dbus_message_get_header_fields (GDBusMessage *message)
1049 GList *keys;
1050 guchar *ret;
1051 guint num_keys;
1052 GList *l;
1053 guint n;
1055 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1057 keys = g_hash_table_get_keys (message->headers);
1058 num_keys = g_list_length (keys);
1059 ret = g_new (guchar, num_keys + 1);
1060 for (l = keys, n = 0; l != NULL; l = l->next, n++)
1061 ret[n] = GPOINTER_TO_UINT (l->data);
1062 g_assert (n == num_keys);
1063 ret[n] = G_DBUS_MESSAGE_HEADER_FIELD_INVALID;
1064 g_list_free (keys);
1066 return ret;
1069 /* ---------------------------------------------------------------------------------------------------- */
1072 * g_dbus_message_get_body:
1073 * @message: A #GDBusMessage.
1075 * Gets the body of a message.
1077 * Returns: (transfer none): A #GVariant or %NULL if the body is
1078 * empty. Do not free, it is owned by @message.
1080 * Since: 2.26
1082 GVariant *
1083 g_dbus_message_get_body (GDBusMessage *message)
1085 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1086 return message->body;
1090 * g_dbus_message_set_body:
1091 * @message: A #GDBusMessage.
1092 * @body: Either %NULL or a #GVariant that is a tuple.
1094 * Sets the body @message. As a side-effect the
1095 * %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field is set to the
1096 * type string of @body (or cleared if @body is %NULL).
1098 * If @body is floating, @message assumes ownership of @body.
1100 * Since: 2.26
1102 void
1103 g_dbus_message_set_body (GDBusMessage *message,
1104 GVariant *body)
1106 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1107 g_return_if_fail ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE));
1109 if (message->locked)
1111 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1112 return;
1115 if (message->body != NULL)
1116 g_variant_unref (message->body);
1117 if (body == NULL)
1119 message->body = NULL;
1120 g_dbus_message_set_signature (message, NULL);
1122 else
1124 const gchar *type_string;
1125 gsize type_string_len;
1126 gchar *signature;
1128 message->body = g_variant_ref_sink (body);
1130 type_string = g_variant_get_type_string (body);
1131 type_string_len = strlen (type_string);
1132 g_assert (type_string_len >= 2);
1133 signature = g_strndup (type_string + 1, type_string_len - 2);
1134 g_dbus_message_set_signature (message, signature);
1135 g_free (signature);
1139 /* ---------------------------------------------------------------------------------------------------- */
1141 #ifdef G_OS_UNIX
1143 * g_dbus_message_get_unix_fd_list:
1144 * @message: A #GDBusMessage.
1146 * Gets the UNIX file descriptors associated with @message, if any.
1148 * This method is only available on UNIX.
1150 * Returns: (transfer none):A #GUnixFDList or %NULL if no file descriptors are
1151 * associated. Do not free, this object is owned by @message.
1153 * Since: 2.26
1155 GUnixFDList *
1156 g_dbus_message_get_unix_fd_list (GDBusMessage *message)
1158 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1159 return message->fd_list;
1163 * g_dbus_message_set_unix_fd_list:
1164 * @message: A #GDBusMessage.
1165 * @fd_list: (nullable): A #GUnixFDList or %NULL.
1167 * Sets the UNIX file descriptors associated with @message. As a
1168 * side-effect the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header
1169 * field is set to the number of fds in @fd_list (or cleared if
1170 * @fd_list is %NULL).
1172 * This method is only available on UNIX.
1174 * Since: 2.26
1176 void
1177 g_dbus_message_set_unix_fd_list (GDBusMessage *message,
1178 GUnixFDList *fd_list)
1180 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1181 g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
1183 if (message->locked)
1185 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1186 return;
1189 if (message->fd_list != NULL)
1190 g_object_unref (message->fd_list);
1191 if (fd_list != NULL)
1193 message->fd_list = g_object_ref (fd_list);
1194 g_dbus_message_set_num_unix_fds (message, g_unix_fd_list_get_length (fd_list));
1196 else
1198 message->fd_list = NULL;
1199 g_dbus_message_set_num_unix_fds (message, 0);
1202 #endif
1204 /* ---------------------------------------------------------------------------------------------------- */
1206 static guint
1207 get_type_fixed_size (const GVariantType *type)
1209 /* NB: we do not treat 'b' as fixed-size here because GVariant and
1210 * D-Bus disagree about the size.
1212 switch (*g_variant_type_peek_string (type))
1214 case 'y':
1215 return 1;
1216 case 'n': case 'q':
1217 return 2;
1218 case 'i': case 'u': case 'h':
1219 return 4;
1220 case 'x': case 't': case 'd':
1221 return 8;
1222 default:
1223 return 0;
1227 static gboolean
1228 validate_headers (GDBusMessage *message,
1229 GError **error)
1231 gboolean ret;
1233 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1234 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1236 ret = FALSE;
1238 switch (message->type)
1240 case G_DBUS_MESSAGE_TYPE_INVALID:
1241 g_set_error_literal (error,
1242 G_IO_ERROR,
1243 G_IO_ERROR_INVALID_ARGUMENT,
1244 _("type is INVALID"));
1245 goto out;
1246 break;
1248 case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
1249 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1250 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1252 g_set_error_literal (error,
1253 G_IO_ERROR,
1254 G_IO_ERROR_INVALID_ARGUMENT,
1255 _("METHOD_CALL message: PATH or MEMBER header field is missing"));
1256 goto out;
1258 break;
1260 case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
1261 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1263 g_set_error_literal (error,
1264 G_IO_ERROR,
1265 G_IO_ERROR_INVALID_ARGUMENT,
1266 _("METHOD_RETURN message: REPLY_SERIAL header field is missing"));
1267 goto out;
1269 break;
1271 case G_DBUS_MESSAGE_TYPE_ERROR:
1272 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME) == NULL ||
1273 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1275 g_set_error_literal (error,
1276 G_IO_ERROR,
1277 G_IO_ERROR_INVALID_ARGUMENT,
1278 _("ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing"));
1279 goto out;
1281 break;
1283 case G_DBUS_MESSAGE_TYPE_SIGNAL:
1284 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1285 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE) == NULL ||
1286 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1288 g_set_error_literal (error,
1289 G_IO_ERROR,
1290 G_IO_ERROR_INVALID_ARGUMENT,
1291 _("SIGNAL message: PATH, INTERFACE or MEMBER header field is missing"));
1292 goto out;
1294 if (g_strcmp0 (g_dbus_message_get_path (message), "/org/freedesktop/DBus/Local") == 0)
1296 g_set_error_literal (error,
1297 G_IO_ERROR,
1298 G_IO_ERROR_INVALID_ARGUMENT,
1299 _("SIGNAL message: The PATH header field is using the reserved value /org/freedesktop/DBus/Local"));
1300 goto out;
1302 if (g_strcmp0 (g_dbus_message_get_interface (message), "org.freedesktop.DBus.Local") == 0)
1304 g_set_error_literal (error,
1305 G_IO_ERROR,
1306 G_IO_ERROR_INVALID_ARGUMENT,
1307 _("SIGNAL message: The INTERFACE header field is using the reserved value org.freedesktop.DBus.Local"));
1308 goto out;
1310 break;
1312 default:
1313 /* hitherto unknown type - nothing to check */
1314 break;
1317 ret = TRUE;
1319 out:
1320 g_assert (ret || (error == NULL || *error != NULL));
1321 return ret;
1324 /* ---------------------------------------------------------------------------------------------------- */
1326 static gboolean
1327 ensure_input_padding (GMemoryBuffer *buf,
1328 gsize padding_size)
1330 gsize offset;
1331 gsize wanted_offset;
1333 offset = buf->pos;
1334 wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1335 buf->pos = wanted_offset;
1336 return TRUE;
1339 static const gchar *
1340 read_string (GMemoryBuffer *mbuf,
1341 gsize len,
1342 GError **error)
1344 gchar *str;
1345 const gchar *end_valid;
1347 if G_UNLIKELY (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1349 mbuf->pos = mbuf->valid_len;
1350 /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1351 g_set_error (error,
1352 G_IO_ERROR,
1353 G_IO_ERROR_INVALID_ARGUMENT,
1354 g_dngettext (GETTEXT_PACKAGE,
1355 "Wanted to read %lu byte but only got %lu",
1356 "Wanted to read %lu bytes but only got %lu",
1357 (gulong)len),
1358 (gulong)len,
1359 (gulong)(mbuf->valid_len - mbuf->pos));
1360 return NULL;
1363 if G_UNLIKELY (mbuf->data[mbuf->pos + len] != '\0')
1365 str = g_strndup (mbuf->data + mbuf->pos, len);
1366 g_set_error (error,
1367 G_IO_ERROR,
1368 G_IO_ERROR_INVALID_ARGUMENT,
1369 _("Expected NUL byte after the string “%s” but found byte %d"),
1370 str, mbuf->data[mbuf->pos + len]);
1371 g_free (str);
1372 mbuf->pos += len + 1;
1373 return NULL;
1376 str = mbuf->data + mbuf->pos;
1377 mbuf->pos += len + 1;
1379 if G_UNLIKELY (!g_utf8_validate (str, -1, &end_valid))
1381 gint offset;
1382 gchar *valid_str;
1383 offset = (gint) (end_valid - str);
1384 valid_str = g_strndup (str, offset);
1385 g_set_error (error,
1386 G_IO_ERROR,
1387 G_IO_ERROR_INVALID_ARGUMENT,
1388 _("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
1389 "The valid UTF-8 string up until that point was “%s”"),
1390 offset,
1391 (gint) len,
1392 valid_str);
1393 g_free (valid_str);
1394 return NULL;
1397 return str;
1400 static gconstpointer
1401 read_bytes (GMemoryBuffer *mbuf,
1402 gsize len,
1403 GError **error)
1405 gconstpointer result;
1407 if G_UNLIKELY (mbuf->pos + len > mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1409 mbuf->pos = mbuf->valid_len;
1410 /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1411 g_set_error (error,
1412 G_IO_ERROR,
1413 G_IO_ERROR_INVALID_ARGUMENT,
1414 g_dngettext (GETTEXT_PACKAGE,
1415 "Wanted to read %lu byte but only got %lu",
1416 "Wanted to read %lu bytes but only got %lu",
1417 (gulong)len),
1418 (gulong)len,
1419 (gulong)(mbuf->valid_len - mbuf->pos));
1420 return NULL;
1423 result = mbuf->data + mbuf->pos;
1424 mbuf->pos += len;
1426 return result;
1429 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
1431 /* returns a non-floating GVariant! */
1432 static GVariant *
1433 parse_value_from_blob (GMemoryBuffer *buf,
1434 const GVariantType *type,
1435 gboolean just_align,
1436 guint indent,
1437 GError **error)
1439 GVariant *ret;
1440 GError *local_error;
1441 gboolean is_leaf;
1442 const gchar *type_string;
1444 type_string = g_variant_type_peek_string (type);
1446 #ifdef DEBUG_SERIALIZER
1448 gchar *s;
1449 s = g_variant_type_dup_string (type);
1450 g_print ("%*s%s type %s from offset 0x%04x",
1451 indent, "",
1452 just_align ? "Aligning" : "Reading",
1454 (gint) buf->pos);
1455 g_free (s);
1457 #endif /* DEBUG_SERIALIZER */
1459 ret = NULL;
1461 is_leaf = TRUE;
1462 local_error = NULL;
1463 switch (type_string[0])
1465 case 'b': /* G_VARIANT_TYPE_BOOLEAN */
1466 ensure_input_padding (buf, 4);
1467 if (!just_align)
1469 gboolean v;
1470 v = g_memory_buffer_read_uint32 (buf);
1471 ret = g_variant_new_boolean (v);
1473 break;
1475 case 'y': /* G_VARIANT_TYPE_BYTE */
1476 if (!just_align)
1478 guchar v;
1479 v = g_memory_buffer_read_byte (buf);
1480 ret = g_variant_new_byte (v);
1482 break;
1484 case 'n': /* G_VARIANT_TYPE_INT16 */
1485 ensure_input_padding (buf, 2);
1486 if (!just_align)
1488 gint16 v;
1489 v = g_memory_buffer_read_int16 (buf);
1490 ret = g_variant_new_int16 (v);
1492 break;
1494 case 'q': /* G_VARIANT_TYPE_UINT16 */
1495 ensure_input_padding (buf, 2);
1496 if (!just_align)
1498 guint16 v;
1499 v = g_memory_buffer_read_uint16 (buf);
1500 ret = g_variant_new_uint16 (v);
1502 break;
1504 case 'i': /* G_VARIANT_TYPE_INT32 */
1505 ensure_input_padding (buf, 4);
1506 if (!just_align)
1508 gint32 v;
1509 v = g_memory_buffer_read_int32 (buf);
1510 ret = g_variant_new_int32 (v);
1512 break;
1514 case 'u': /* G_VARIANT_TYPE_UINT32 */
1515 ensure_input_padding (buf, 4);
1516 if (!just_align)
1518 guint32 v;
1519 v = g_memory_buffer_read_uint32 (buf);
1520 ret = g_variant_new_uint32 (v);
1522 break;
1524 case 'x': /* G_VARIANT_TYPE_INT64 */
1525 ensure_input_padding (buf, 8);
1526 if (!just_align)
1528 gint64 v;
1529 v = g_memory_buffer_read_int64 (buf);
1530 ret = g_variant_new_int64 (v);
1532 break;
1534 case 't': /* G_VARIANT_TYPE_UINT64 */
1535 ensure_input_padding (buf, 8);
1536 if (!just_align)
1538 guint64 v;
1539 v = g_memory_buffer_read_uint64 (buf);
1540 ret = g_variant_new_uint64 (v);
1542 break;
1544 case 'd': /* G_VARIANT_TYPE_DOUBLE */
1545 ensure_input_padding (buf, 8);
1546 if (!just_align)
1548 union {
1549 guint64 v_uint64;
1550 gdouble v_double;
1551 } u;
1552 G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
1553 u.v_uint64 = g_memory_buffer_read_uint64 (buf);
1554 ret = g_variant_new_double (u.v_double);
1556 break;
1558 case 's': /* G_VARIANT_TYPE_STRING */
1559 ensure_input_padding (buf, 4);
1560 if (!just_align)
1562 guint32 len;
1563 const gchar *v;
1564 len = g_memory_buffer_read_uint32 (buf);
1565 v = read_string (buf, (gsize) len, &local_error);
1566 if (v == NULL)
1567 goto fail;
1568 ret = g_variant_new_string (v);
1570 break;
1572 case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
1573 ensure_input_padding (buf, 4);
1574 if (!just_align)
1576 guint32 len;
1577 const gchar *v;
1578 len = g_memory_buffer_read_uint32 (buf);
1579 v = read_string (buf, (gsize) len, &local_error);
1580 if (v == NULL)
1581 goto fail;
1582 if (!g_variant_is_object_path (v))
1584 g_set_error (&local_error,
1585 G_IO_ERROR,
1586 G_IO_ERROR_INVALID_ARGUMENT,
1587 _("Parsed value “%s” is not a valid D-Bus object path"),
1589 goto fail;
1591 ret = g_variant_new_object_path (v);
1593 break;
1595 case 'g': /* G_VARIANT_TYPE_SIGNATURE */
1596 if (!just_align)
1598 guchar len;
1599 const gchar *v;
1600 len = g_memory_buffer_read_byte (buf);
1601 v = read_string (buf, (gsize) len, &local_error);
1602 if (v == NULL)
1603 goto fail;
1604 if (!g_variant_is_signature (v))
1606 g_set_error (&local_error,
1607 G_IO_ERROR,
1608 G_IO_ERROR_INVALID_ARGUMENT,
1609 _("Parsed value “%s” is not a valid D-Bus signature"),
1611 goto fail;
1613 ret = g_variant_new_signature (v);
1615 break;
1617 case 'h': /* G_VARIANT_TYPE_HANDLE */
1618 ensure_input_padding (buf, 4);
1619 if (!just_align)
1621 gint32 v;
1622 v = g_memory_buffer_read_int32 (buf);
1623 ret = g_variant_new_handle (v);
1625 break;
1627 case 'a': /* G_VARIANT_TYPE_ARRAY */
1628 ensure_input_padding (buf, 4);
1630 /* If we are only aligning for this array type, it is the child type of
1631 * another array, which is empty. So, we do not need to add padding for
1632 * this nonexistent array's elements: we only need to align for this
1633 * array itself (4 bytes). See
1634 * <https://bugzilla.gnome.org/show_bug.cgi?id=673612>.
1636 if (!just_align)
1638 guint32 array_len;
1639 const GVariantType *element_type;
1640 guint fixed_size;
1642 array_len = g_memory_buffer_read_uint32 (buf);
1644 is_leaf = FALSE;
1645 #ifdef DEBUG_SERIALIZER
1646 g_print (": array spans 0x%04x bytes\n", array_len);
1647 #endif /* DEBUG_SERIALIZER */
1649 if (array_len > (2<<26))
1651 /* G_GUINT32_FORMAT doesn't work with gettext, so use u */
1652 g_set_error (&local_error,
1653 G_IO_ERROR,
1654 G_IO_ERROR_INVALID_ARGUMENT,
1655 g_dngettext (GETTEXT_PACKAGE,
1656 "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB).",
1657 "Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB).",
1658 array_len),
1659 array_len);
1660 goto fail;
1663 element_type = g_variant_type_element (type);
1664 fixed_size = get_type_fixed_size (element_type);
1666 /* Fast-path the cases like 'ay', etc. */
1667 if (fixed_size != 0)
1669 gconstpointer array_data;
1671 if (array_len % fixed_size != 0)
1673 g_set_error (&local_error,
1674 G_IO_ERROR,
1675 G_IO_ERROR_INVALID_ARGUMENT,
1676 _("Encountered array of type “a%c”, expected to have a length a multiple "
1677 "of %u bytes, but found to be %u bytes in length"),
1678 g_variant_type_peek_string (element_type)[0], fixed_size, array_len);
1679 goto fail;
1682 ensure_input_padding (buf, fixed_size);
1683 array_data = read_bytes (buf, array_len, &local_error);
1684 if (array_data == NULL)
1685 goto fail;
1687 ret = g_variant_new_fixed_array (element_type, array_data, array_len / fixed_size, fixed_size);
1689 if (g_memory_buffer_is_byteswapped (buf))
1691 GVariant *tmp = g_variant_ref_sink (ret);
1692 ret = g_variant_byteswap (tmp);
1693 g_variant_unref (tmp);
1696 else
1698 GVariantBuilder builder;
1699 goffset offset;
1700 goffset target;
1702 g_variant_builder_init (&builder, type);
1704 if (array_len == 0)
1706 GVariant *item;
1707 item = parse_value_from_blob (buf,
1708 element_type,
1709 TRUE,
1710 indent + 2,
1711 NULL);
1712 g_assert (item == NULL);
1714 else
1716 offset = buf->pos;
1717 target = offset + array_len;
1718 while (offset < target)
1720 GVariant *item;
1721 item = parse_value_from_blob (buf,
1722 element_type,
1723 FALSE,
1724 indent + 2,
1725 &local_error);
1726 if (item == NULL)
1728 g_variant_builder_clear (&builder);
1729 goto fail;
1731 g_variant_builder_add_value (&builder, item);
1732 g_variant_unref (item);
1733 offset = buf->pos;
1737 ret = g_variant_builder_end (&builder);
1740 break;
1742 default:
1743 if (g_variant_type_is_dict_entry (type))
1745 const GVariantType *key_type;
1746 const GVariantType *value_type;
1747 GVariant *key;
1748 GVariant *value;
1750 ensure_input_padding (buf, 8);
1752 is_leaf = FALSE;
1753 #ifdef DEBUG_SERIALIZER
1754 g_print ("\n");
1755 #endif /* DEBUG_SERIALIZER */
1757 if (!just_align)
1759 key_type = g_variant_type_key (type);
1760 key = parse_value_from_blob (buf,
1761 key_type,
1762 FALSE,
1763 indent + 2,
1764 &local_error);
1765 if (key == NULL)
1766 goto fail;
1767 value_type = g_variant_type_value (type);
1768 value = parse_value_from_blob (buf,
1769 value_type,
1770 FALSE,
1771 indent + 2,
1772 &local_error);
1773 if (value == NULL)
1775 g_variant_unref (key);
1776 goto fail;
1778 ret = g_variant_new_dict_entry (key, value);
1779 g_variant_unref (key);
1780 g_variant_unref (value);
1783 else if (g_variant_type_is_tuple (type))
1785 ensure_input_padding (buf, 8);
1787 is_leaf = FALSE;
1788 #ifdef DEBUG_SERIALIZER
1789 g_print ("\n");
1790 #endif /* DEBUG_SERIALIZER */
1792 if (!just_align)
1794 const GVariantType *element_type;
1795 GVariantBuilder builder;
1797 g_variant_builder_init (&builder, type);
1798 element_type = g_variant_type_first (type);
1799 while (element_type != NULL)
1801 GVariant *item;
1802 item = parse_value_from_blob (buf,
1803 element_type,
1804 FALSE,
1805 indent + 2,
1806 &local_error);
1807 if (item == NULL)
1809 g_variant_builder_clear (&builder);
1810 goto fail;
1812 g_variant_builder_add_value (&builder, item);
1813 g_variant_unref (item);
1815 element_type = g_variant_type_next (element_type);
1817 ret = g_variant_builder_end (&builder);
1820 else if (g_variant_type_is_variant (type))
1822 is_leaf = FALSE;
1823 #ifdef DEBUG_SERIALIZER
1824 g_print ("\n");
1825 #endif /* DEBUG_SERIALIZER */
1827 if (!just_align)
1829 guchar siglen;
1830 const gchar *sig;
1831 GVariantType *variant_type;
1832 GVariant *value;
1834 siglen = g_memory_buffer_read_byte (buf);
1835 sig = read_string (buf, (gsize) siglen, &local_error);
1836 if (sig == NULL)
1837 goto fail;
1838 if (!g_variant_is_signature (sig))
1840 g_set_error (&local_error,
1841 G_IO_ERROR,
1842 G_IO_ERROR_INVALID_ARGUMENT,
1843 _("Parsed value “%s” for variant is not a valid D-Bus signature"),
1844 sig);
1845 goto fail;
1847 variant_type = g_variant_type_new (sig);
1848 value = parse_value_from_blob (buf,
1849 variant_type,
1850 FALSE,
1851 indent + 2,
1852 &local_error);
1853 g_variant_type_free (variant_type);
1854 if (value == NULL)
1855 goto fail;
1856 ret = g_variant_new_variant (value);
1857 g_variant_unref (value);
1860 else
1862 gchar *s;
1863 s = g_variant_type_dup_string (type);
1864 g_set_error (&local_error,
1865 G_IO_ERROR,
1866 G_IO_ERROR_INVALID_ARGUMENT,
1867 _("Error deserializing GVariant with type string “%s” from the D-Bus wire format"),
1869 g_free (s);
1870 goto fail;
1872 break;
1875 g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
1877 #ifdef DEBUG_SERIALIZER
1878 if (ret != NULL)
1880 if (is_leaf)
1882 gchar *s;
1883 if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1885 s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
1887 else
1889 s = g_variant_print (ret, FALSE);
1891 g_print (": %s\n", s);
1892 g_free (s);
1895 #else
1896 is_leaf = is_leaf; /* To avoid -Wunused-but-set-variable */
1897 #endif /* DEBUG_SERIALIZER */
1899 /* sink the reference, if floating */
1900 if (ret != NULL)
1901 g_variant_take_ref (ret);
1902 return ret;
1904 fail:
1905 #ifdef DEBUG_SERIALIZER
1906 g_print ("\n"
1907 "%*sFAILURE: %s (%s, %d)\n",
1908 indent, "",
1909 local_error->message,
1910 g_quark_to_string (local_error->domain),
1911 local_error->code);
1912 #endif /* DEBUG_SERIALIZER */
1913 g_propagate_error (error, local_error);
1914 return NULL;
1917 /* ---------------------------------------------------------------------------------------------------- */
1919 /* message_header must be at least 16 bytes */
1922 * g_dbus_message_bytes_needed:
1923 * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1924 * @blob_len: The length of @blob (must be at least 16).
1925 * @error: Return location for error or %NULL.
1927 * Utility function to calculate how many bytes are needed to
1928 * completely deserialize the D-Bus message stored at @blob.
1930 * Returns: Number of bytes needed or -1 if @error is set (e.g. if
1931 * @blob contains invalid data or not enough data is available to
1932 * determine the size).
1934 * Since: 2.26
1936 gssize
1937 g_dbus_message_bytes_needed (guchar *blob,
1938 gsize blob_len,
1939 GError **error)
1941 gssize ret;
1943 ret = -1;
1945 g_return_val_if_fail (blob != NULL, -1);
1946 g_return_val_if_fail (error == NULL || *error == NULL, -1);
1947 g_return_val_if_fail (blob_len >= 16, -1);
1949 if (blob[0] == 'l')
1951 /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1952 ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
1953 /* round up so it's a multiple of 8 */
1954 ret = 8 * ((ret + 7)/8);
1955 /* finally add the body size */
1956 ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
1958 else if (blob[0] == 'B')
1960 /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1961 ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
1962 /* round up so it's a multiple of 8 */
1963 ret = 8 * ((ret + 7)/8);
1964 /* finally add the body size */
1965 ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
1967 else
1969 g_set_error (error,
1970 G_IO_ERROR,
1971 G_IO_ERROR_INVALID_ARGUMENT,
1972 "Unable to determine message blob length - given blob is malformed");
1975 if (ret > (2<<27))
1977 g_set_error (error,
1978 G_IO_ERROR,
1979 G_IO_ERROR_INVALID_ARGUMENT,
1980 "Blob indicates that message exceeds maximum message length (128MiB)");
1981 ret = -1;
1984 return ret;
1987 /* ---------------------------------------------------------------------------------------------------- */
1990 * g_dbus_message_new_from_blob:
1991 * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1992 * @blob_len: The length of @blob.
1993 * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
1994 * @error: Return location for error or %NULL.
1996 * Creates a new #GDBusMessage from the data stored at @blob. The byte
1997 * order that the message was in can be retrieved using
1998 * g_dbus_message_get_byte_order().
2000 * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
2001 * g_object_unref().
2003 * Since: 2.26
2005 GDBusMessage *
2006 g_dbus_message_new_from_blob (guchar *blob,
2007 gsize blob_len,
2008 GDBusCapabilityFlags capabilities,
2009 GError **error)
2011 gboolean ret;
2012 GMemoryBuffer mbuf;
2013 GDBusMessage *message;
2014 guchar endianness;
2015 guchar major_protocol_version;
2016 guint32 message_body_len;
2017 GVariant *headers;
2018 GVariant *item;
2019 GVariantIter iter;
2020 GVariant *signature;
2022 /* TODO: check against @capabilities */
2024 ret = FALSE;
2026 g_return_val_if_fail (blob != NULL, NULL);
2027 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2028 g_return_val_if_fail (blob_len >= 12, NULL);
2030 message = g_dbus_message_new ();
2032 memset (&mbuf, 0, sizeof (mbuf));
2033 mbuf.data = (gchar *)blob;
2034 mbuf.len = mbuf.valid_len = blob_len;
2036 endianness = g_memory_buffer_read_byte (&mbuf);
2037 switch (endianness)
2039 case 'l':
2040 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2041 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
2042 break;
2043 case 'B':
2044 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2045 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
2046 break;
2047 default:
2048 g_set_error (error,
2049 G_IO_ERROR,
2050 G_IO_ERROR_INVALID_ARGUMENT,
2051 _("Invalid endianness value. Expected 0x6c (“l”) or 0x42 (“B”) but found value 0x%02x"),
2052 endianness);
2053 goto out;
2056 message->type = g_memory_buffer_read_byte (&mbuf);
2057 message->flags = g_memory_buffer_read_byte (&mbuf);
2058 major_protocol_version = g_memory_buffer_read_byte (&mbuf);
2059 if (major_protocol_version != 1)
2061 g_set_error (error,
2062 G_IO_ERROR,
2063 G_IO_ERROR_INVALID_ARGUMENT,
2064 _("Invalid major protocol version. Expected 1 but found %d"),
2065 major_protocol_version);
2066 goto out;
2068 message_body_len = g_memory_buffer_read_uint32 (&mbuf);
2069 message->serial = g_memory_buffer_read_uint32 (&mbuf);
2071 #ifdef DEBUG_SERIALIZER
2072 g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2074 gchar *s;
2075 s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
2076 g_print ("%s\n", s);
2077 g_free (s);
2079 #endif /* DEBUG_SERIALIZER */
2081 #ifdef DEBUG_SERIALIZER
2082 g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2083 #endif /* DEBUG_SERIALIZER */
2084 headers = parse_value_from_blob (&mbuf,
2085 G_VARIANT_TYPE ("a{yv}"),
2086 FALSE,
2088 error);
2089 if (headers == NULL)
2090 goto out;
2091 g_variant_iter_init (&iter, headers);
2092 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2094 guchar header_field;
2095 GVariant *value;
2096 g_variant_get (item,
2097 "{yv}",
2098 &header_field,
2099 &value);
2100 g_dbus_message_set_header (message, header_field, value);
2101 g_variant_unref (value);
2102 g_variant_unref (item);
2104 g_variant_unref (headers);
2106 signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2107 if (signature != NULL)
2109 const gchar *signature_str;
2110 gsize signature_str_len;
2112 signature_str = g_variant_get_string (signature, &signature_str_len);
2114 /* signature but no body */
2115 if (message_body_len == 0 && signature_str_len > 0)
2117 g_set_error (error,
2118 G_IO_ERROR,
2119 G_IO_ERROR_INVALID_ARGUMENT,
2120 _("Signature header with signature “%s” found but message body is empty"),
2121 signature_str);
2122 goto out;
2124 else if (signature_str_len > 0)
2126 GVariantType *variant_type;
2127 gchar *tupled_signature_str;
2129 if (!g_variant_is_signature (signature_str))
2131 g_set_error (error,
2132 G_IO_ERROR,
2133 G_IO_ERROR_INVALID_ARGUMENT,
2134 _("Parsed value “%s” is not a valid D-Bus signature (for body)"),
2135 signature_str);
2136 goto out;
2138 tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2139 variant_type = g_variant_type_new (tupled_signature_str);
2140 g_free (tupled_signature_str);
2141 #ifdef DEBUG_SERIALIZER
2142 g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2143 #endif /* DEBUG_SERIALIZER */
2144 message->body = parse_value_from_blob (&mbuf,
2145 variant_type,
2146 FALSE,
2148 error);
2149 g_variant_type_free (variant_type);
2150 if (message->body == NULL)
2151 goto out;
2154 else
2156 /* no signature, this is only OK if the body is empty */
2157 if (message_body_len != 0)
2159 /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
2160 g_set_error (error,
2161 G_IO_ERROR,
2162 G_IO_ERROR_INVALID_ARGUMENT,
2163 g_dngettext (GETTEXT_PACKAGE,
2164 "No signature header in message but the message body is %u byte",
2165 "No signature header in message but the message body is %u bytes",
2166 message_body_len),
2167 message_body_len);
2168 goto out;
2172 if (!validate_headers (message, error))
2174 g_prefix_error (error, _("Cannot deserialize message: "));
2175 goto out;
2178 ret = TRUE;
2180 out:
2181 if (ret)
2183 return message;
2185 else
2187 if (message != NULL)
2188 g_object_unref (message);
2189 return NULL;
2193 /* ---------------------------------------------------------------------------------------------------- */
2195 static gsize
2196 ensure_output_padding (GMemoryBuffer *mbuf,
2197 gsize padding_size)
2199 gsize offset;
2200 gsize wanted_offset;
2201 gsize padding_needed;
2202 guint n;
2204 offset = mbuf->pos;
2205 wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
2206 padding_needed = wanted_offset - offset;
2208 for (n = 0; n < padding_needed; n++)
2209 g_memory_buffer_put_byte (mbuf, '\0');
2211 return padding_needed;
2214 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
2215 static gboolean
2216 append_value_to_blob (GVariant *value,
2217 const GVariantType *type,
2218 GMemoryBuffer *mbuf,
2219 gsize *out_padding_added,
2220 GError **error)
2222 gsize padding_added;
2223 const gchar *type_string;
2225 type_string = g_variant_type_peek_string (type);
2227 padding_added = 0;
2229 switch (type_string[0])
2231 case 'b': /* G_VARIANT_TYPE_BOOLEAN */
2232 padding_added = ensure_output_padding (mbuf, 4);
2233 if (value != NULL)
2235 gboolean v = g_variant_get_boolean (value);
2236 g_memory_buffer_put_uint32 (mbuf, v);
2238 break;
2240 case 'y': /* G_VARIANT_TYPE_BYTE */
2241 if (value != NULL)
2243 guint8 v = g_variant_get_byte (value);
2244 g_memory_buffer_put_byte (mbuf, v);
2246 break;
2248 case 'n': /* G_VARIANT_TYPE_INT16 */
2249 padding_added = ensure_output_padding (mbuf, 2);
2250 if (value != NULL)
2252 gint16 v = g_variant_get_int16 (value);
2253 g_memory_buffer_put_int16 (mbuf, v);
2255 break;
2257 case 'q': /* G_VARIANT_TYPE_UINT16 */
2258 padding_added = ensure_output_padding (mbuf, 2);
2259 if (value != NULL)
2261 guint16 v = g_variant_get_uint16 (value);
2262 g_memory_buffer_put_uint16 (mbuf, v);
2264 break;
2266 case 'i': /* G_VARIANT_TYPE_INT32 */
2267 padding_added = ensure_output_padding (mbuf, 4);
2268 if (value != NULL)
2270 gint32 v = g_variant_get_int32 (value);
2271 g_memory_buffer_put_int32 (mbuf, v);
2273 break;
2275 case 'u': /* G_VARIANT_TYPE_UINT32 */
2276 padding_added = ensure_output_padding (mbuf, 4);
2277 if (value != NULL)
2279 guint32 v = g_variant_get_uint32 (value);
2280 g_memory_buffer_put_uint32 (mbuf, v);
2282 break;
2284 case 'x': /* G_VARIANT_TYPE_INT64 */
2285 padding_added = ensure_output_padding (mbuf, 8);
2286 if (value != NULL)
2288 gint64 v = g_variant_get_int64 (value);
2289 g_memory_buffer_put_int64 (mbuf, v);
2291 break;
2293 case 't': /* G_VARIANT_TYPE_UINT64 */
2294 padding_added = ensure_output_padding (mbuf, 8);
2295 if (value != NULL)
2297 guint64 v = g_variant_get_uint64 (value);
2298 g_memory_buffer_put_uint64 (mbuf, v);
2300 break;
2302 case 'd': /* G_VARIANT_TYPE_DOUBLE */
2303 padding_added = ensure_output_padding (mbuf, 8);
2304 if (value != NULL)
2306 union {
2307 guint64 v_uint64;
2308 gdouble v_double;
2309 } u;
2310 G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
2311 u.v_double = g_variant_get_double (value);
2312 g_memory_buffer_put_uint64 (mbuf, u.v_uint64);
2314 break;
2316 case 's': /* G_VARIANT_TYPE_STRING */
2317 padding_added = ensure_output_padding (mbuf, 4);
2318 if (value != NULL)
2320 gsize len;
2321 const gchar *v;
2322 const gchar *end;
2323 v = g_variant_get_string (value, &len);
2324 g_assert (g_utf8_validate (v, -1, &end) && (end == v + len));
2325 g_memory_buffer_put_uint32 (mbuf, len);
2326 g_memory_buffer_put_string (mbuf, v);
2327 g_memory_buffer_put_byte (mbuf, '\0');
2329 break;
2331 case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
2332 padding_added = ensure_output_padding (mbuf, 4);
2333 if (value != NULL)
2335 gsize len;
2336 const gchar *v = g_variant_get_string (value, &len);
2337 g_assert (g_variant_is_object_path (v));
2338 g_memory_buffer_put_uint32 (mbuf, len);
2339 g_memory_buffer_put_string (mbuf, v);
2340 g_memory_buffer_put_byte (mbuf, '\0');
2342 break;
2344 case 'g': /* G_VARIANT_TYPE_SIGNATURE */
2345 if (value != NULL)
2347 gsize len;
2348 const gchar *v = g_variant_get_string (value, &len);
2349 g_assert (g_variant_is_signature (v));
2350 g_memory_buffer_put_byte (mbuf, len);
2351 g_memory_buffer_put_string (mbuf, v);
2352 g_memory_buffer_put_byte (mbuf, '\0');
2354 break;
2356 case 'h': /* G_VARIANT_TYPE_HANDLE */
2357 padding_added = ensure_output_padding (mbuf, 4);
2358 if (value != NULL)
2360 gint32 v = g_variant_get_handle (value);
2361 g_memory_buffer_put_int32 (mbuf, v);
2363 break;
2365 case 'a': /* G_VARIANT_TYPE_ARRAY */
2367 const GVariantType *element_type;
2368 GVariant *item;
2369 GVariantIter iter;
2370 goffset array_len_offset;
2371 goffset array_payload_begin_offset;
2372 goffset cur_offset;
2373 gsize array_len;
2374 guint fixed_size;
2376 padding_added = ensure_output_padding (mbuf, 4);
2377 if (value != NULL)
2379 /* array length - will be filled in later */
2380 array_len_offset = mbuf->valid_len;
2381 g_memory_buffer_put_uint32 (mbuf, 0xF00DFACE);
2383 /* From the D-Bus spec:
2385 * "A UINT32 giving the length of the array data in bytes,
2386 * followed by alignment padding to the alignment boundary of
2387 * the array element type, followed by each array element. The
2388 * array length is from the end of the alignment padding to
2389 * the end of the last element, i.e. it does not include the
2390 * padding after the length, or any padding after the last
2391 * element."
2393 * Thus, we need to count how much padding the first element
2394 * contributes and subtract that from the array length.
2396 array_payload_begin_offset = mbuf->valid_len;
2398 element_type = g_variant_type_element (type);
2399 fixed_size = get_type_fixed_size (element_type);
2401 if (g_variant_n_children (value) == 0)
2403 gsize padding_added_for_item;
2404 if (!append_value_to_blob (NULL,
2405 element_type,
2406 mbuf,
2407 &padding_added_for_item,
2408 error))
2409 goto fail;
2410 array_payload_begin_offset += padding_added_for_item;
2412 else if (fixed_size != 0)
2414 GVariant *use_value;
2416 if (g_memory_buffer_is_byteswapped (mbuf))
2417 use_value = g_variant_byteswap (value);
2418 else
2419 use_value = g_variant_ref (value);
2421 array_payload_begin_offset += ensure_output_padding (mbuf, fixed_size);
2423 array_len = g_variant_get_size (use_value);
2424 g_memory_buffer_write (mbuf, g_variant_get_data (use_value), array_len);
2425 g_variant_unref (use_value);
2427 else
2429 guint n;
2430 n = 0;
2431 g_variant_iter_init (&iter, value);
2432 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2434 gsize padding_added_for_item;
2435 if (!append_value_to_blob (item,
2436 g_variant_get_type (item),
2437 mbuf,
2438 &padding_added_for_item,
2439 error))
2441 g_variant_unref (item);
2442 goto fail;
2444 g_variant_unref (item);
2445 if (n == 0)
2447 array_payload_begin_offset += padding_added_for_item;
2449 n++;
2453 cur_offset = mbuf->valid_len;
2454 array_len = cur_offset - array_payload_begin_offset;
2455 mbuf->pos = array_len_offset;
2457 g_memory_buffer_put_uint32 (mbuf, array_len);
2458 mbuf->pos = cur_offset;
2461 break;
2463 default:
2464 if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
2466 padding_added = ensure_output_padding (mbuf, 8);
2467 if (value != NULL)
2469 GVariant *item;
2470 GVariantIter iter;
2471 g_variant_iter_init (&iter, value);
2472 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2474 if (!append_value_to_blob (item,
2475 g_variant_get_type (item),
2476 mbuf,
2477 NULL,
2478 error))
2480 g_variant_unref (item);
2481 goto fail;
2483 g_variant_unref (item);
2487 else if (g_variant_type_is_variant (type))
2489 if (value != NULL)
2491 GVariant *child;
2492 const gchar *signature;
2493 child = g_variant_get_child_value (value, 0);
2494 signature = g_variant_get_type_string (child);
2495 g_memory_buffer_put_byte (mbuf, strlen (signature));
2496 g_memory_buffer_put_string (mbuf, signature);
2497 g_memory_buffer_put_byte (mbuf, '\0');
2498 if (!append_value_to_blob (child,
2499 g_variant_get_type (child),
2500 mbuf,
2501 NULL,
2502 error))
2504 g_variant_unref (child);
2505 goto fail;
2507 g_variant_unref (child);
2510 else
2512 g_set_error (error,
2513 G_IO_ERROR,
2514 G_IO_ERROR_INVALID_ARGUMENT,
2515 _("Error serializing GVariant with type string “%s” to the D-Bus wire format"),
2516 g_variant_get_type_string (value));
2517 goto fail;
2519 break;
2522 if (out_padding_added != NULL)
2523 *out_padding_added = padding_added;
2525 return TRUE;
2527 fail:
2528 return FALSE;
2531 static gboolean
2532 append_body_to_blob (GVariant *value,
2533 GMemoryBuffer *mbuf,
2534 GError **error)
2536 GVariant *item;
2537 GVariantIter iter;
2539 if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
2541 g_set_error (error,
2542 G_IO_ERROR,
2543 G_IO_ERROR_INVALID_ARGUMENT,
2544 "Expected a tuple for the body of the GDBusMessage.");
2545 goto fail;
2548 g_variant_iter_init (&iter, value);
2549 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2551 if (!append_value_to_blob (item,
2552 g_variant_get_type (item),
2553 mbuf,
2554 NULL,
2555 error))
2557 g_variant_unref (item);
2558 goto fail;
2560 g_variant_unref (item);
2562 return TRUE;
2564 fail:
2565 return FALSE;
2568 /* ---------------------------------------------------------------------------------------------------- */
2571 * g_dbus_message_to_blob:
2572 * @message: A #GDBusMessage.
2573 * @out_size: Return location for size of generated blob.
2574 * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2575 * @error: Return location for error.
2577 * Serializes @message to a blob. The byte order returned by
2578 * g_dbus_message_get_byte_order() will be used.
2580 * Returns: (array length=out_size) (transfer full): A pointer to a
2581 * valid binary D-Bus message of @out_size bytes generated by @message
2582 * or %NULL if @error is set. Free with g_free().
2584 * Since: 2.26
2586 guchar *
2587 g_dbus_message_to_blob (GDBusMessage *message,
2588 gsize *out_size,
2589 GDBusCapabilityFlags capabilities,
2590 GError **error)
2592 GMemoryBuffer mbuf;
2593 guchar *ret;
2594 gsize size;
2595 goffset body_len_offset;
2596 goffset body_start_offset;
2597 gsize body_size;
2598 GVariant *header_fields;
2599 GVariantBuilder builder;
2600 GHashTableIter hash_iter;
2601 gpointer key;
2602 GVariant *header_value;
2603 GVariant *signature;
2604 const gchar *signature_str;
2605 gint num_fds_in_message;
2606 gint num_fds_according_to_header;
2608 /* TODO: check against @capabilities */
2610 ret = NULL;
2612 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2613 g_return_val_if_fail (out_size != NULL, NULL);
2614 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2616 memset (&mbuf, 0, sizeof (mbuf));
2617 mbuf.len = MIN_ARRAY_SIZE;
2618 mbuf.data = g_malloc (mbuf.len);
2620 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN;
2621 switch (message->byte_order)
2623 case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
2624 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2625 break;
2626 case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
2627 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2628 break;
2631 /* Core header */
2632 g_memory_buffer_put_byte (&mbuf, (guchar) message->byte_order);
2633 g_memory_buffer_put_byte (&mbuf, message->type);
2634 g_memory_buffer_put_byte (&mbuf, message->flags);
2635 g_memory_buffer_put_byte (&mbuf, 1); /* major protocol version */
2636 body_len_offset = mbuf.valid_len;
2637 /* body length - will be filled in later */
2638 g_memory_buffer_put_uint32 (&mbuf, 0xF00DFACE);
2639 g_memory_buffer_put_uint32 (&mbuf, message->serial);
2641 num_fds_in_message = 0;
2642 #ifdef G_OS_UNIX
2643 if (message->fd_list != NULL)
2644 num_fds_in_message = g_unix_fd_list_get_length (message->fd_list);
2645 #endif
2646 num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
2647 if (num_fds_in_message != num_fds_according_to_header)
2649 g_set_error (error,
2650 G_IO_ERROR,
2651 G_IO_ERROR_INVALID_ARGUMENT,
2652 _("Message has %d file descriptors but the header field indicates %d file descriptors"),
2653 num_fds_in_message,
2654 num_fds_according_to_header);
2655 goto out;
2658 if (!validate_headers (message, error))
2660 g_prefix_error (error, _("Cannot serialize message: "));
2661 goto out;
2664 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
2665 g_hash_table_iter_init (&hash_iter, message->headers);
2666 while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
2668 g_variant_builder_add (&builder,
2669 "{yv}",
2670 (guchar) GPOINTER_TO_UINT (key),
2671 header_value);
2673 header_fields = g_variant_builder_end (&builder);
2675 if (!append_value_to_blob (header_fields,
2676 g_variant_get_type (header_fields),
2677 &mbuf,
2678 NULL,
2679 error))
2681 g_variant_unref (header_fields);
2682 goto out;
2684 g_variant_unref (header_fields);
2686 /* header size must be a multiple of 8 */
2687 ensure_output_padding (&mbuf, 8);
2689 body_start_offset = mbuf.valid_len;
2691 signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2692 signature_str = NULL;
2693 if (signature != NULL)
2694 signature_str = g_variant_get_string (signature, NULL);
2695 if (message->body != NULL)
2697 gchar *tupled_signature_str;
2698 tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2699 if (signature == NULL)
2701 g_set_error (error,
2702 G_IO_ERROR,
2703 G_IO_ERROR_INVALID_ARGUMENT,
2704 _("Message body has signature “%s” but there is no signature header"),
2705 signature_str);
2706 g_free (tupled_signature_str);
2707 goto out;
2709 else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
2711 g_set_error (error,
2712 G_IO_ERROR,
2713 G_IO_ERROR_INVALID_ARGUMENT,
2714 _("Message body has type signature “%s” but signature in the header field is “%s”"),
2715 tupled_signature_str, g_variant_get_type_string (message->body));
2716 g_free (tupled_signature_str);
2717 goto out;
2719 g_free (tupled_signature_str);
2720 if (!append_body_to_blob (message->body, &mbuf, error))
2721 goto out;
2723 else
2725 if (signature != NULL && strlen (signature_str) > 0)
2727 g_set_error (error,
2728 G_IO_ERROR,
2729 G_IO_ERROR_INVALID_ARGUMENT,
2730 _("Message body is empty but signature in the header field is “(%s)”"),
2731 signature_str);
2732 goto out;
2736 /* OK, we're done writing the message - set the body length */
2737 size = mbuf.valid_len;
2738 body_size = size - body_start_offset;
2740 mbuf.pos = body_len_offset;
2742 g_memory_buffer_put_uint32 (&mbuf, body_size);
2744 *out_size = size;
2745 ret = (guchar *)mbuf.data;
2747 out:
2748 if (ret == NULL)
2749 g_free (mbuf.data);
2751 return ret;
2754 /* ---------------------------------------------------------------------------------------------------- */
2756 static guint32
2757 get_uint32_header (GDBusMessage *message,
2758 GDBusMessageHeaderField header_field)
2760 GVariant *value;
2761 guint32 ret;
2763 ret = 0;
2764 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2765 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
2766 ret = g_variant_get_uint32 (value);
2768 return ret;
2771 static const gchar *
2772 get_string_header (GDBusMessage *message,
2773 GDBusMessageHeaderField header_field)
2775 GVariant *value;
2776 const gchar *ret;
2778 ret = NULL;
2779 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2780 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
2781 ret = g_variant_get_string (value, NULL);
2783 return ret;
2786 static const gchar *
2787 get_object_path_header (GDBusMessage *message,
2788 GDBusMessageHeaderField header_field)
2790 GVariant *value;
2791 const gchar *ret;
2793 ret = NULL;
2794 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2795 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
2796 ret = g_variant_get_string (value, NULL);
2798 return ret;
2801 static const gchar *
2802 get_signature_header (GDBusMessage *message,
2803 GDBusMessageHeaderField header_field)
2805 GVariant *value;
2806 const gchar *ret;
2808 ret = NULL;
2809 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2810 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
2811 ret = g_variant_get_string (value, NULL);
2813 return ret;
2816 /* ---------------------------------------------------------------------------------------------------- */
2818 static void
2819 set_uint32_header (GDBusMessage *message,
2820 GDBusMessageHeaderField header_field,
2821 guint32 value)
2823 g_dbus_message_set_header (message,
2824 header_field,
2825 g_variant_new_uint32 (value));
2828 static void
2829 set_string_header (GDBusMessage *message,
2830 GDBusMessageHeaderField header_field,
2831 const gchar *value)
2833 g_dbus_message_set_header (message,
2834 header_field,
2835 value == NULL ? NULL : g_variant_new_string (value));
2838 static void
2839 set_object_path_header (GDBusMessage *message,
2840 GDBusMessageHeaderField header_field,
2841 const gchar *value)
2843 g_dbus_message_set_header (message,
2844 header_field,
2845 value == NULL ? NULL : g_variant_new_object_path (value));
2848 static void
2849 set_signature_header (GDBusMessage *message,
2850 GDBusMessageHeaderField header_field,
2851 const gchar *value)
2853 g_dbus_message_set_header (message,
2854 header_field,
2855 value == NULL ? NULL : g_variant_new_signature (value));
2858 /* ---------------------------------------------------------------------------------------------------- */
2861 * g_dbus_message_get_reply_serial:
2862 * @message: A #GDBusMessage.
2864 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2866 * Returns: The value.
2868 * Since: 2.26
2870 guint32
2871 g_dbus_message_get_reply_serial (GDBusMessage *message)
2873 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2874 return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
2878 * g_dbus_message_set_reply_serial:
2879 * @message: A #GDBusMessage.
2880 * @value: The value to set.
2882 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2884 * Since: 2.26
2886 void
2887 g_dbus_message_set_reply_serial (GDBusMessage *message,
2888 guint32 value)
2890 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2891 set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
2894 /* ---------------------------------------------------------------------------------------------------- */
2897 * g_dbus_message_get_interface:
2898 * @message: A #GDBusMessage.
2900 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2902 * Returns: The value.
2904 * Since: 2.26
2906 const gchar *
2907 g_dbus_message_get_interface (GDBusMessage *message)
2909 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2910 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
2914 * g_dbus_message_set_interface:
2915 * @message: A #GDBusMessage.
2916 * @value: The value to set.
2918 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2920 * Since: 2.26
2922 void
2923 g_dbus_message_set_interface (GDBusMessage *message,
2924 const gchar *value)
2926 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2927 g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2928 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
2931 /* ---------------------------------------------------------------------------------------------------- */
2934 * g_dbus_message_get_member:
2935 * @message: A #GDBusMessage.
2937 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2939 * Returns: The value.
2941 * Since: 2.26
2943 const gchar *
2944 g_dbus_message_get_member (GDBusMessage *message)
2946 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2947 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
2951 * g_dbus_message_set_member:
2952 * @message: A #GDBusMessage.
2953 * @value: The value to set.
2955 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2957 * Since: 2.26
2959 void
2960 g_dbus_message_set_member (GDBusMessage *message,
2961 const gchar *value)
2963 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2964 g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
2965 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
2968 /* ---------------------------------------------------------------------------------------------------- */
2971 * g_dbus_message_get_path:
2972 * @message: A #GDBusMessage.
2974 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2976 * Returns: The value.
2978 * Since: 2.26
2980 const gchar *
2981 g_dbus_message_get_path (GDBusMessage *message)
2983 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2984 return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
2988 * g_dbus_message_set_path:
2989 * @message: A #GDBusMessage.
2990 * @value: The value to set.
2992 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2994 * Since: 2.26
2996 void
2997 g_dbus_message_set_path (GDBusMessage *message,
2998 const gchar *value)
3000 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3001 g_return_if_fail (value == NULL || g_variant_is_object_path (value));
3002 set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
3005 /* ---------------------------------------------------------------------------------------------------- */
3008 * g_dbus_message_get_sender:
3009 * @message: A #GDBusMessage.
3011 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3013 * Returns: The value.
3015 * Since: 2.26
3017 const gchar *
3018 g_dbus_message_get_sender (GDBusMessage *message)
3020 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3021 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
3025 * g_dbus_message_set_sender:
3026 * @message: A #GDBusMessage.
3027 * @value: The value to set.
3029 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3031 * Since: 2.26
3033 void
3034 g_dbus_message_set_sender (GDBusMessage *message,
3035 const gchar *value)
3037 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3038 g_return_if_fail (value == NULL || g_dbus_is_name (value));
3039 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
3042 /* ---------------------------------------------------------------------------------------------------- */
3045 * g_dbus_message_get_destination:
3046 * @message: A #GDBusMessage.
3048 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3050 * Returns: The value.
3052 * Since: 2.26
3054 const gchar *
3055 g_dbus_message_get_destination (GDBusMessage *message)
3057 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3058 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
3062 * g_dbus_message_set_destination:
3063 * @message: A #GDBusMessage.
3064 * @value: The value to set.
3066 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3068 * Since: 2.26
3070 void
3071 g_dbus_message_set_destination (GDBusMessage *message,
3072 const gchar *value)
3074 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3075 g_return_if_fail (value == NULL || g_dbus_is_name (value));
3076 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
3079 /* ---------------------------------------------------------------------------------------------------- */
3082 * g_dbus_message_get_error_name:
3083 * @message: A #GDBusMessage.
3085 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3087 * Returns: The value.
3089 * Since: 2.26
3091 const gchar *
3092 g_dbus_message_get_error_name (GDBusMessage *message)
3094 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3095 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
3099 * g_dbus_message_set_error_name:
3100 * @message: A #GDBusMessage.
3101 * @value: The value to set.
3103 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3105 * Since: 2.26
3107 void
3108 g_dbus_message_set_error_name (GDBusMessage *message,
3109 const gchar *value)
3111 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3112 g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
3113 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
3116 /* ---------------------------------------------------------------------------------------------------- */
3119 * g_dbus_message_get_signature:
3120 * @message: A #GDBusMessage.
3122 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3124 * Returns: The value.
3126 * Since: 2.26
3128 const gchar *
3129 g_dbus_message_get_signature (GDBusMessage *message)
3131 const gchar *ret;
3132 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3133 ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
3134 if (ret == NULL)
3135 ret = "";
3136 return ret;
3140 * g_dbus_message_set_signature:
3141 * @message: A #GDBusMessage.
3142 * @value: The value to set.
3144 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3146 * Since: 2.26
3148 void
3149 g_dbus_message_set_signature (GDBusMessage *message,
3150 const gchar *value)
3152 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3153 g_return_if_fail (value == NULL || g_variant_is_signature (value));
3154 set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
3157 /* ---------------------------------------------------------------------------------------------------- */
3160 * g_dbus_message_get_arg0:
3161 * @message: A #GDBusMessage.
3163 * Convenience to get the first item in the body of @message.
3165 * Returns: The string item or %NULL if the first item in the body of
3166 * @message is not a string.
3168 * Since: 2.26
3170 const gchar *
3171 g_dbus_message_get_arg0 (GDBusMessage *message)
3173 const gchar *ret;
3175 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3177 ret = NULL;
3179 if (message->body != NULL && g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE))
3181 GVariant *item;
3182 item = g_variant_get_child_value (message->body, 0);
3183 if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING))
3184 ret = g_variant_get_string (item, NULL);
3185 g_variant_unref (item);
3188 return ret;
3191 /* ---------------------------------------------------------------------------------------------------- */
3194 * g_dbus_message_get_num_unix_fds:
3195 * @message: A #GDBusMessage.
3197 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3199 * Returns: The value.
3201 * Since: 2.26
3203 guint32
3204 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
3206 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3207 return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
3211 * g_dbus_message_set_num_unix_fds:
3212 * @message: A #GDBusMessage.
3213 * @value: The value to set.
3215 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3217 * Since: 2.26
3219 void
3220 g_dbus_message_set_num_unix_fds (GDBusMessage *message,
3221 guint32 value)
3223 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3224 set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
3227 /* ---------------------------------------------------------------------------------------------------- */
3230 * g_dbus_message_to_gerror:
3231 * @message: A #GDBusMessage.
3232 * @error: The #GError to set.
3234 * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
3235 * nothing and returns %FALSE.
3237 * Otherwise this method encodes the error in @message as a #GError
3238 * using g_dbus_error_set_dbus_error() using the information in the
3239 * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
3240 * well as the first string item in @message's body.
3242 * Returns: %TRUE if @error was set, %FALSE otherwise.
3244 * Since: 2.26
3246 gboolean
3247 g_dbus_message_to_gerror (GDBusMessage *message,
3248 GError **error)
3250 gboolean ret;
3251 const gchar *error_name;
3253 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3255 ret = FALSE;
3256 if (message->type != G_DBUS_MESSAGE_TYPE_ERROR)
3257 goto out;
3259 error_name = g_dbus_message_get_error_name (message);
3260 if (error_name != NULL)
3262 GVariant *body;
3264 body = g_dbus_message_get_body (message);
3266 if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
3268 const gchar *error_message;
3269 g_variant_get (body, "(&s)", &error_message);
3270 g_dbus_error_set_dbus_error (error,
3271 error_name,
3272 error_message,
3273 NULL);
3275 else
3277 /* these two situations are valid, yet pretty rare */
3278 if (body != NULL)
3280 g_dbus_error_set_dbus_error (error,
3281 error_name,
3283 _("Error return with body of type “%s”"),
3284 g_variant_get_type_string (body));
3286 else
3288 g_dbus_error_set_dbus_error (error,
3289 error_name,
3291 _("Error return with empty body"));
3295 else
3297 /* TOOD: this shouldn't happen - should check this at message serialization
3298 * time and disconnect the peer.
3300 g_set_error (error,
3301 G_IO_ERROR,
3302 G_IO_ERROR_FAILED,
3303 "Error return without error-name header!");
3306 ret = TRUE;
3308 out:
3309 return ret;
3312 /* ---------------------------------------------------------------------------------------------------- */
3314 static gchar *
3315 flags_to_string (GType flags_type, guint value)
3317 GString *s;
3318 GFlagsClass *klass;
3319 guint n;
3321 klass = g_type_class_ref (flags_type);
3322 s = g_string_new (NULL);
3323 for (n = 0; n < 32; n++)
3325 if ((value & (1<<n)) != 0)
3327 GFlagsValue *flags_value;
3328 flags_value = g_flags_get_first_value (klass, (1<<n));
3329 if (s->len > 0)
3330 g_string_append_c (s, ',');
3331 if (flags_value != NULL)
3332 g_string_append (s, flags_value->value_nick);
3333 else
3334 g_string_append_printf (s, "unknown (bit %d)", n);
3337 if (s->len == 0)
3338 g_string_append (s, "none");
3339 g_type_class_unref (klass);
3340 return g_string_free (s, FALSE);
3343 static gint
3344 _sort_keys_func (gconstpointer a,
3345 gconstpointer b)
3347 gint ia;
3348 gint ib;
3350 ia = GPOINTER_TO_INT (a);
3351 ib = GPOINTER_TO_INT (b);
3353 return ia - ib;
3357 * g_dbus_message_print:
3358 * @message: A #GDBusMessage.
3359 * @indent: Indentation level.
3361 * Produces a human-readable multi-line description of @message.
3363 * The contents of the description has no ABI guarantees, the contents
3364 * and formatting is subject to change at any time. Typical output
3365 * looks something like this:
3366 * |[
3367 * Type: method-call
3368 * Flags: none
3369 * Version: 0
3370 * Serial: 4
3371 * Headers:
3372 * path -> objectpath '/org/gtk/GDBus/TestObject'
3373 * interface -> 'org.gtk.GDBus.TestInterface'
3374 * member -> 'GimmeStdout'
3375 * destination -> ':1.146'
3376 * Body: ()
3377 * UNIX File Descriptors:
3378 * (none)
3379 * ]|
3380 * or
3381 * |[
3382 * Type: method-return
3383 * Flags: no-reply-expected
3384 * Version: 0
3385 * Serial: 477
3386 * Headers:
3387 * reply-serial -> uint32 4
3388 * destination -> ':1.159'
3389 * sender -> ':1.146'
3390 * num-unix-fds -> uint32 1
3391 * Body: ()
3392 * UNIX File Descriptors:
3393 * fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
3394 * ]|
3396 * Returns: A string that should be freed with g_free().
3398 * Since: 2.26
3400 gchar *
3401 g_dbus_message_print (GDBusMessage *message,
3402 guint indent)
3404 GString *str;
3405 gchar *s;
3406 GList *keys;
3407 GList *l;
3409 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3411 str = g_string_new (NULL);
3413 s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->type);
3414 g_string_append_printf (str, "%*sType: %s\n", indent, "", s);
3415 g_free (s);
3416 s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->flags);
3417 g_string_append_printf (str, "%*sFlags: %s\n", indent, "", s);
3418 g_free (s);
3419 g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->major_protocol_version);
3420 g_string_append_printf (str, "%*sSerial: %d\n", indent, "", message->serial);
3422 g_string_append_printf (str, "%*sHeaders:\n", indent, "");
3423 keys = g_hash_table_get_keys (message->headers);
3424 keys = g_list_sort (keys, _sort_keys_func);
3425 if (keys != NULL)
3427 for (l = keys; l != NULL; l = l->next)
3429 gint key = GPOINTER_TO_INT (l->data);
3430 GVariant *value;
3431 gchar *value_str;
3433 value = g_hash_table_lookup (message->headers, l->data);
3434 g_assert (value != NULL);
3436 s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
3437 value_str = g_variant_print (value, TRUE);
3438 g_string_append_printf (str, "%*s %s -> %s\n", indent, "", s, value_str);
3439 g_free (s);
3440 g_free (value_str);
3443 else
3445 g_string_append_printf (str, "%*s (none)\n", indent, "");
3447 g_list_free (keys);
3448 g_string_append_printf (str, "%*sBody: ", indent, "");
3449 if (message->body != NULL)
3451 g_variant_print_string (message->body,
3452 str,
3453 TRUE);
3455 else
3457 g_string_append (str, "()");
3459 g_string_append (str, "\n");
3460 #ifdef G_OS_UNIX
3461 g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
3462 if (message->fd_list != NULL)
3464 gint num_fds;
3465 const gint *fds;
3466 gint n;
3468 fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3469 if (num_fds > 0)
3471 for (n = 0; n < num_fds; n++)
3473 GString *fs;
3474 struct stat statbuf;
3475 fs = g_string_new (NULL);
3476 if (fstat (fds[n], &statbuf) == 0)
3478 g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
3479 major (statbuf.st_dev), minor (statbuf.st_dev));
3480 g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
3481 statbuf.st_mode);
3482 g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3483 (guint64) statbuf.st_ino);
3484 g_string_append_printf (fs, "%s" "uid=%u", fs->len > 0 ? "," : "",
3485 (guint) statbuf.st_uid);
3486 g_string_append_printf (fs, "%s" "gid=%u", fs->len > 0 ? "," : "",
3487 (guint) statbuf.st_gid);
3488 g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
3489 major (statbuf.st_rdev), minor (statbuf.st_rdev));
3490 g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3491 (guint64) statbuf.st_size);
3492 g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3493 (guint64) statbuf.st_atime);
3494 g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3495 (guint64) statbuf.st_mtime);
3496 g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3497 (guint64) statbuf.st_ctime);
3499 else
3501 g_string_append_printf (fs, "(fstat failed: %s)", strerror (errno));
3503 g_string_append_printf (str, "%*s fd %d: %s\n", indent, "", fds[n], fs->str);
3504 g_string_free (fs, TRUE);
3507 else
3509 g_string_append_printf (str, "%*s (empty)\n", indent, "");
3512 else
3514 g_string_append_printf (str, "%*s (none)\n", indent, "");
3516 #endif
3518 return g_string_free (str, FALSE);
3522 * g_dbus_message_get_locked:
3523 * @message: A #GDBusMessage.
3525 * Checks whether @message is locked. To monitor changes to this
3526 * value, conncet to the #GObject::notify signal to listen for changes
3527 * on the #GDBusMessage:locked property.
3529 * Returns: %TRUE if @message is locked, %FALSE otherwise.
3531 * Since: 2.26
3533 gboolean
3534 g_dbus_message_get_locked (GDBusMessage *message)
3536 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3537 return message->locked;
3541 * g_dbus_message_lock:
3542 * @message: A #GDBusMessage.
3544 * If @message is locked, does nothing. Otherwise locks the message.
3546 * Since: 2.26
3548 void
3549 g_dbus_message_lock (GDBusMessage *message)
3551 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3553 if (message->locked)
3554 goto out;
3556 message->locked = TRUE;
3557 g_object_notify (G_OBJECT (message), "locked");
3559 out:
3564 * g_dbus_message_copy:
3565 * @message: A #GDBusMessage.
3566 * @error: Return location for error or %NULL.
3568 * Copies @message. The copy is a deep copy and the returned
3569 * #GDBusMessage is completely identical except that it is guaranteed
3570 * to not be locked.
3572 * This operation can fail if e.g. @message contains file descriptors
3573 * and the per-process or system-wide open files limit is reached.
3575 * Returns: (transfer full): A new #GDBusMessage or %NULL if @error is set.
3576 * Free with g_object_unref().
3578 * Since: 2.26
3580 GDBusMessage *
3581 g_dbus_message_copy (GDBusMessage *message,
3582 GError **error)
3584 GDBusMessage *ret;
3585 GHashTableIter iter;
3586 gpointer header_key;
3587 GVariant *header_value;
3589 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3590 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
3592 ret = g_dbus_message_new ();
3593 ret->type = message->type;
3594 ret->flags = message->flags;
3595 ret->byte_order = message->byte_order;
3596 ret->major_protocol_version = message->major_protocol_version;
3597 ret->serial = message->serial;
3599 #ifdef G_OS_UNIX
3600 if (message->fd_list != NULL)
3602 gint n;
3603 gint num_fds;
3604 const gint *fds;
3606 ret->fd_list = g_unix_fd_list_new ();
3607 fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3608 for (n = 0; n < num_fds; n++)
3610 if (g_unix_fd_list_append (ret->fd_list,
3611 fds[n],
3612 error) == -1)
3614 g_object_unref (ret);
3615 ret = NULL;
3616 goto out;
3620 #endif
3622 /* see https://bugzilla.gnome.org/show_bug.cgi?id=624546#c8 for why it's fine
3623 * to just ref (as opposed to deep-copying) the GVariant instances
3625 ret->body = message->body != NULL ? g_variant_ref (message->body) : NULL;
3626 g_hash_table_iter_init (&iter, message->headers);
3627 while (g_hash_table_iter_next (&iter, &header_key, (gpointer) &header_value))
3628 g_hash_table_insert (ret->headers, header_key, g_variant_ref (header_value));
3630 #ifdef G_OS_UNIX
3631 out:
3632 #endif
3633 return ret;