1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * SPDX-License-Identifier: LGPL-2.1-or-later
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 * Author: David Zeuthen <davidz@redhat.com>
23 /* Uncomment to debug serializer code */
24 /* #define DEBUG_SERIALIZER */
30 #include <sys/types.h>
34 #include <sys/mkdev.h>
35 #elif MAJOR_IN_SYSMACROS
36 #include <sys/sysmacros.h>
38 #include <sys/types.h>
40 #define MAJOR_MINOR_NOT_FOUND 1
43 #include "gdbusutils.h"
44 #include "gdbusmessage.h"
45 #include "gdbuserror.h"
46 #include "gioenumtypes.h"
47 #include "ginputstream.h"
48 #include "gdatainputstream.h"
49 #include "gmemoryinputstream.h"
50 #include "goutputstream.h"
51 #include "gdataoutputstream.h"
52 #include "gmemoryoutputstream.h"
53 #include "gseekable.h"
55 #include "gdbusprivate.h"
56 #include "gutilsprivate.h"
59 #include "gunixfdlist.h"
64 /* See https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-signature
65 * This is 64 containers plus 1 value within them. */
66 #define G_DBUS_MAX_TYPE_DEPTH (64 + 1)
68 typedef struct _GMemoryBuffer GMemoryBuffer;
75 GDataStreamByteOrder byte_order;
79 g_memory_buffer_is_byteswapped (GMemoryBuffer *mbuf)
81 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
82 return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
84 return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
89 g_memory_buffer_read_byte (GMemoryBuffer *mbuf,
92 g_return_val_if_fail (error == NULL || *error == NULL, 0);
94 if (mbuf->pos >= mbuf->valid_len)
98 G_IO_ERROR_INVALID_ARGUMENT,
99 "Unexpected end of message while reading byte.");
102 return mbuf->data [mbuf->pos++];
106 g_memory_buffer_read_int16 (GMemoryBuffer *mbuf,
111 g_return_val_if_fail (error == NULL || *error == NULL, -1);
113 if (mbuf->pos > mbuf->valid_len - 2)
117 G_IO_ERROR_INVALID_ARGUMENT,
118 "Unexpected end of message while reading int16.");
122 memcpy (&v, mbuf->data + mbuf->pos, 2);
125 if (g_memory_buffer_is_byteswapped (mbuf))
126 v = GUINT16_SWAP_LE_BE (v);
132 g_memory_buffer_read_uint16 (GMemoryBuffer *mbuf,
137 g_return_val_if_fail (error == NULL || *error == NULL, 0);
139 if (mbuf->pos > mbuf->valid_len - 2)
143 G_IO_ERROR_INVALID_ARGUMENT,
144 "Unexpected end of message while reading uint16.");
148 memcpy (&v, mbuf->data + mbuf->pos, 2);
151 if (g_memory_buffer_is_byteswapped (mbuf))
152 v = GUINT16_SWAP_LE_BE (v);
158 g_memory_buffer_read_int32 (GMemoryBuffer *mbuf,
163 g_return_val_if_fail (error == NULL || *error == NULL, -1);
165 if (mbuf->pos > mbuf->valid_len - 4)
169 G_IO_ERROR_INVALID_ARGUMENT,
170 "Unexpected end of message while reading int32.");
174 memcpy (&v, mbuf->data + mbuf->pos, 4);
177 if (g_memory_buffer_is_byteswapped (mbuf))
178 v = GUINT32_SWAP_LE_BE (v);
184 g_memory_buffer_read_uint32 (GMemoryBuffer *mbuf,
189 g_return_val_if_fail (error == NULL || *error == NULL, 0);
191 if (mbuf->pos > mbuf->valid_len - 4)
195 G_IO_ERROR_INVALID_ARGUMENT,
196 "Unexpected end of message while reading uint32.");
200 memcpy (&v, mbuf->data + mbuf->pos, 4);
203 if (g_memory_buffer_is_byteswapped (mbuf))
204 v = GUINT32_SWAP_LE_BE (v);
210 g_memory_buffer_read_int64 (GMemoryBuffer *mbuf,
215 g_return_val_if_fail (error == NULL || *error == NULL, -1);
217 if (mbuf->pos > mbuf->valid_len - 8)
221 G_IO_ERROR_INVALID_ARGUMENT,
222 "Unexpected end of message while reading int64.");
226 memcpy (&v, mbuf->data + mbuf->pos, 8);
229 if (g_memory_buffer_is_byteswapped (mbuf))
230 v = GUINT64_SWAP_LE_BE (v);
236 g_memory_buffer_read_uint64 (GMemoryBuffer *mbuf,
241 g_return_val_if_fail (error == NULL || *error == NULL, 0);
243 if (mbuf->pos > mbuf->valid_len - 8)
247 G_IO_ERROR_INVALID_ARGUMENT,
248 "Unexpected end of message while reading uint64.");
252 memcpy (&v, mbuf->data + mbuf->pos, 8);
255 if (g_memory_buffer_is_byteswapped (mbuf))
256 v = GUINT64_SWAP_LE_BE (v);
261 #define MIN_ARRAY_SIZE 128
264 array_resize (GMemoryBuffer *mbuf,
270 if (mbuf->len == size)
274 data = g_realloc (mbuf->data, size);
277 memset ((guint8 *)data + len, 0, size - len);
282 if (mbuf->len < mbuf->valid_len)
283 mbuf->valid_len = mbuf->len;
287 g_memory_buffer_write (GMemoryBuffer *mbuf,
297 /* Check for address space overflow, but only if the buffer is resizable.
298 Otherwise we just do a short write and don't worry. */
299 if (mbuf->pos + count < mbuf->pos)
302 if (mbuf->pos + count > mbuf->len)
304 /* At least enough to fit the write, rounded up
305 for greater than linear growth.
306 TODO: This wastes a lot of memory at large buffer sizes.
307 Figure out a more rational allocation strategy. */
308 new_size = g_nearest_pow (mbuf->pos + count);
309 /* Check for overflow again. We have checked if
310 pos + count > G_MAXSIZE, but now check if g_nearest_pow () has
315 new_size = MAX (new_size, MIN_ARRAY_SIZE);
316 array_resize (mbuf, new_size);
319 dest = (guint8 *)mbuf->data + mbuf->pos;
320 memcpy (dest, buffer, count);
323 if (mbuf->pos > mbuf->valid_len)
324 mbuf->valid_len = mbuf->pos;
330 g_memory_buffer_put_byte (GMemoryBuffer *mbuf,
333 return g_memory_buffer_write (mbuf, &data, 1);
337 g_memory_buffer_put_int16 (GMemoryBuffer *mbuf,
340 switch (mbuf->byte_order)
342 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
343 data = GINT16_TO_BE (data);
345 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
346 data = GINT16_TO_LE (data);
348 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
353 return g_memory_buffer_write (mbuf, &data, 2);
357 g_memory_buffer_put_uint16 (GMemoryBuffer *mbuf,
360 switch (mbuf->byte_order)
362 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
363 data = GUINT16_TO_BE (data);
365 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
366 data = GUINT16_TO_LE (data);
368 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
373 return g_memory_buffer_write (mbuf, &data, 2);
377 g_memory_buffer_put_int32 (GMemoryBuffer *mbuf,
380 switch (mbuf->byte_order)
382 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
383 data = GINT32_TO_BE (data);
385 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
386 data = GINT32_TO_LE (data);
388 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
393 return g_memory_buffer_write (mbuf, &data, 4);
397 g_memory_buffer_put_uint32 (GMemoryBuffer *mbuf,
400 switch (mbuf->byte_order)
402 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
403 data = GUINT32_TO_BE (data);
405 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
406 data = GUINT32_TO_LE (data);
408 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
413 return g_memory_buffer_write (mbuf, &data, 4);
417 g_memory_buffer_put_int64 (GMemoryBuffer *mbuf,
420 switch (mbuf->byte_order)
422 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
423 data = GINT64_TO_BE (data);
425 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
426 data = GINT64_TO_LE (data);
428 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
433 return g_memory_buffer_write (mbuf, &data, 8);
437 g_memory_buffer_put_uint64 (GMemoryBuffer *mbuf,
440 switch (mbuf->byte_order)
442 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
443 data = GUINT64_TO_BE (data);
445 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
446 data = GUINT64_TO_LE (data);
448 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
453 return g_memory_buffer_write (mbuf, &data, 8);
457 g_memory_buffer_put_string (GMemoryBuffer *mbuf,
460 g_return_val_if_fail (str != NULL, FALSE);
462 return g_memory_buffer_write (mbuf, str, strlen (str));
465 typedef struct _GDBusMessageClass GDBusMessageClass;
470 * Class structure for #GDBusMessage.
474 struct _GDBusMessageClass
477 GObjectClass parent_class;
483 * A type for representing D-Bus messages that can be sent or received
484 * on a [class@Gio.DBusConnection].
491 GObject parent_instance;
493 GDBusMessageType type;
494 GDBusMessageFlags flags;
496 GDBusMessageByteOrder byte_order;
497 guchar major_protocol_version;
501 GVariant *arg0_cache; /* (nullable) (owned) */
503 GUnixFDList *fd_list;
513 G_DEFINE_TYPE (GDBusMessage, g_dbus_message, G_TYPE_OBJECT)
516 g_dbus_message_finalize (GObject *object)
518 GDBusMessage *message = G_DBUS_MESSAGE (object);
520 if (message->headers != NULL)
521 g_hash_table_unref (message->headers);
522 if (message->body != NULL)
523 g_variant_unref (message->body);
524 g_clear_pointer (&message->arg0_cache, g_variant_unref);
526 if (message->fd_list != NULL)
527 g_object_unref (message->fd_list);
530 if (G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize != NULL)
531 G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize (object);
535 g_dbus_message_get_property (GObject *object,
540 GDBusMessage *message = G_DBUS_MESSAGE (object);
545 g_value_set_boolean (value, g_dbus_message_get_locked (message));
549 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
555 g_dbus_message_class_init (GDBusMessageClass *klass)
557 GObjectClass *gobject_class;
559 gobject_class = G_OBJECT_CLASS (klass);
560 gobject_class->finalize = g_dbus_message_finalize;
561 gobject_class->get_property = g_dbus_message_get_property;
564 * GDBusConnection:locked:
566 * A boolean specifying whether the message is locked.
570 g_object_class_install_property (gobject_class,
572 g_param_spec_boolean ("locked", NULL, NULL,
575 G_PARAM_STATIC_NAME |
576 G_PARAM_STATIC_BLURB |
577 G_PARAM_STATIC_NICK));
581 g_dbus_message_init (GDBusMessage *message)
583 /* Any D-Bus implementation is supposed to handle both Big and
584 * Little Endian encodings and the Endianness is part of the D-Bus
585 * message - we prefer to use Big Endian (since it's Network Byte
586 * Order and just easier to read for humans) but if the machine is
587 * Little Endian we use that for performance reasons.
589 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
590 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
592 /* this could also be G_PDP_ENDIAN */
593 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
595 message->headers = g_hash_table_new_full (g_direct_hash,
598 (GDestroyNotify) g_variant_unref);
602 * g_dbus_message_new:
604 * Creates a new empty #GDBusMessage.
606 * Returns: A #GDBusMessage. Free with g_object_unref().
611 g_dbus_message_new (void)
613 return g_object_new (G_TYPE_DBUS_MESSAGE, NULL);
617 * g_dbus_message_new_method_call:
618 * @name: (nullable): A valid D-Bus name or %NULL.
619 * @path: A valid object path.
620 * @interface_: (nullable): A valid D-Bus interface name or %NULL.
621 * @method: A valid method name.
623 * Creates a new #GDBusMessage for a method call.
625 * Returns: A #GDBusMessage. Free with g_object_unref().
630 g_dbus_message_new_method_call (const gchar *name,
632 const gchar *interface_,
635 GDBusMessage *message;
637 g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
638 g_return_val_if_fail (g_variant_is_object_path (path), NULL);
639 g_return_val_if_fail (g_dbus_is_member_name (method), NULL);
640 g_return_val_if_fail (interface_ == NULL || g_dbus_is_interface_name (interface_), NULL);
642 message = g_dbus_message_new ();
643 message->type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
646 g_dbus_message_set_destination (message, name);
647 g_dbus_message_set_path (message, path);
648 g_dbus_message_set_member (message, method);
649 if (interface_ != NULL)
650 g_dbus_message_set_interface (message, interface_);
656 * g_dbus_message_new_signal:
657 * @path: A valid object path.
658 * @interface_: A valid D-Bus interface name.
659 * @signal: A valid signal name.
661 * Creates a new #GDBusMessage for a signal emission.
663 * Returns: A #GDBusMessage. Free with g_object_unref().
668 g_dbus_message_new_signal (const gchar *path,
669 const gchar *interface_,
672 GDBusMessage *message;
674 g_return_val_if_fail (g_variant_is_object_path (path), NULL);
675 g_return_val_if_fail (g_dbus_is_member_name (signal), NULL);
676 g_return_val_if_fail (g_dbus_is_interface_name (interface_), NULL);
678 message = g_dbus_message_new ();
679 message->type = G_DBUS_MESSAGE_TYPE_SIGNAL;
680 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
682 g_dbus_message_set_path (message, path);
683 g_dbus_message_set_member (message, signal);
684 g_dbus_message_set_interface (message, interface_);
691 * g_dbus_message_new_method_reply:
692 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
693 * create a reply message to.
695 * Creates a new #GDBusMessage that is a reply to @method_call_message.
697 * Returns: (transfer full): #GDBusMessage. Free with g_object_unref().
702 g_dbus_message_new_method_reply (GDBusMessage *method_call_message)
704 GDBusMessage *message;
707 g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
708 g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
709 g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
711 message = g_dbus_message_new ();
712 message->type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
713 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
714 /* reply with same endianness */
715 message->byte_order = method_call_message->byte_order;
717 g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
718 sender = g_dbus_message_get_sender (method_call_message);
720 g_dbus_message_set_destination (message, sender);
726 * g_dbus_message_new_method_error:
727 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
728 * create a reply message to.
729 * @error_name: A valid D-Bus error name.
730 * @error_message_format: The D-Bus error message in a printf() format.
731 * @...: Arguments for @error_message_format.
733 * Creates a new #GDBusMessage that is an error reply to @method_call_message.
735 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
740 g_dbus_message_new_method_error (GDBusMessage *method_call_message,
741 const gchar *error_name,
742 const gchar *error_message_format,
748 va_start (var_args, error_message_format);
749 ret = g_dbus_message_new_method_error_valist (method_call_message,
751 error_message_format,
759 * g_dbus_message_new_method_error_literal:
760 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
761 * create a reply message to.
762 * @error_name: A valid D-Bus error name.
763 * @error_message: The D-Bus error message.
765 * Creates a new #GDBusMessage that is an error reply to @method_call_message.
767 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
772 g_dbus_message_new_method_error_literal (GDBusMessage *method_call_message,
773 const gchar *error_name,
774 const gchar *error_message)
776 GDBusMessage *message;
779 g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
780 g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
781 g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
782 g_return_val_if_fail (g_dbus_is_name (error_name), NULL);
783 g_return_val_if_fail (error_message != NULL, NULL);
785 message = g_dbus_message_new ();
786 message->type = G_DBUS_MESSAGE_TYPE_ERROR;
787 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
788 /* reply with same endianness */
789 message->byte_order = method_call_message->byte_order;
791 g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
792 g_dbus_message_set_error_name (message, error_name);
793 g_dbus_message_set_body (message, g_variant_new ("(s)", error_message));
795 sender = g_dbus_message_get_sender (method_call_message);
797 g_dbus_message_set_destination (message, sender);
803 * g_dbus_message_new_method_error_valist:
804 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
805 * create a reply message to.
806 * @error_name: A valid D-Bus error name.
807 * @error_message_format: The D-Bus error message in a printf() format.
808 * @var_args: Arguments for @error_message_format.
810 * Like g_dbus_message_new_method_error() but intended for language bindings.
812 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
818 g_dbus_message_new_method_error_valist (GDBusMessage *method_call_message,
819 const gchar *error_name,
820 const gchar *error_message_format,
824 gchar *error_message;
825 error_message = g_strdup_vprintf (error_message_format, var_args);
826 ret = g_dbus_message_new_method_error_literal (method_call_message,
829 g_free (error_message);
833 /* ---------------------------------------------------------------------------------------------------- */
836 * g_dbus_message_get_byte_order:
837 * @message: A #GDBusMessage.
839 * Gets the byte order of @message.
841 * Returns: The byte order.
843 GDBusMessageByteOrder
844 g_dbus_message_get_byte_order (GDBusMessage *message)
846 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), (GDBusMessageByteOrder) 0);
847 return message->byte_order;
851 * g_dbus_message_set_byte_order:
852 * @message: A #GDBusMessage.
853 * @byte_order: The byte order.
855 * Sets the byte order of @message.
858 g_dbus_message_set_byte_order (GDBusMessage *message,
859 GDBusMessageByteOrder byte_order)
861 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
865 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
869 message->byte_order = byte_order;
872 /* ---------------------------------------------------------------------------------------------------- */
874 /* TODO: need GI annotations to specify that any guchar value goes for the type */
877 * g_dbus_message_get_message_type:
878 * @message: A #GDBusMessage.
880 * Gets the type of @message.
882 * Returns: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
887 g_dbus_message_get_message_type (GDBusMessage *message)
889 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_TYPE_INVALID);
890 return message->type;
894 * g_dbus_message_set_message_type:
895 * @message: A #GDBusMessage.
896 * @type: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
898 * Sets @message to be of @type.
903 g_dbus_message_set_message_type (GDBusMessage *message,
904 GDBusMessageType type)
906 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
907 g_return_if_fail ((guint) type < 256);
911 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
915 message->type = type;
918 /* ---------------------------------------------------------------------------------------------------- */
920 /* TODO: need GI annotations to specify that any guchar value goes for flags */
923 * g_dbus_message_get_flags:
924 * @message: A #GDBusMessage.
926 * Gets the flags for @message.
928 * Returns: Flags that are set (typically values from the #GDBusMessageFlags enumeration bitwise ORed together).
933 g_dbus_message_get_flags (GDBusMessage *message)
935 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_FLAGS_NONE);
936 return message->flags;
940 * g_dbus_message_set_flags:
941 * @message: A #GDBusMessage.
942 * @flags: Flags for @message that are set (typically values from the #GDBusMessageFlags
943 * enumeration bitwise ORed together).
945 * Sets the flags to set on @message.
950 g_dbus_message_set_flags (GDBusMessage *message,
951 GDBusMessageFlags flags)
953 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
954 g_return_if_fail ((guint) flags < 256);
958 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
962 message->flags = flags;
965 /* ---------------------------------------------------------------------------------------------------- */
968 * g_dbus_message_get_serial:
969 * @message: A #GDBusMessage.
971 * Gets the serial for @message.
973 * Returns: A #guint32.
978 g_dbus_message_get_serial (GDBusMessage *message)
980 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
981 return message->serial;
985 * g_dbus_message_set_serial:
986 * @message: A #GDBusMessage.
987 * @serial: A #guint32.
989 * Sets the serial for @message.
994 g_dbus_message_set_serial (GDBusMessage *message,
997 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1001 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1005 message->serial = serial;
1008 /* ---------------------------------------------------------------------------------------------------- */
1010 /* TODO: need GI annotations to specify that any guchar value goes for header_field */
1013 * g_dbus_message_get_header:
1014 * @message: A #GDBusMessage.
1015 * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1017 * Gets a header field on @message.
1019 * The caller is responsible for checking the type of the returned #GVariant
1020 * matches what is expected.
1022 * Returns: (transfer none) (nullable): A #GVariant with the value if the header was found, %NULL
1023 * otherwise. Do not free, it is owned by @message.
1028 g_dbus_message_get_header (GDBusMessage *message,
1029 GDBusMessageHeaderField header_field)
1031 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1032 g_return_val_if_fail ((guint) header_field < 256, NULL);
1033 return g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
1037 * g_dbus_message_set_header:
1038 * @message: A #GDBusMessage.
1039 * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1040 * @value: (nullable): A #GVariant to set the header field or %NULL to clear the header field.
1042 * Sets a header field on @message.
1044 * If @value is floating, @message assumes ownership of @value.
1049 g_dbus_message_set_header (GDBusMessage *message,
1050 GDBusMessageHeaderField header_field,
1053 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1054 g_return_if_fail ((guint) header_field < 256);
1056 if (message->locked)
1058 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1064 g_hash_table_remove (message->headers, GUINT_TO_POINTER (header_field));
1068 g_hash_table_insert (message->headers, GUINT_TO_POINTER (header_field), g_variant_ref_sink (value));
1073 * g_dbus_message_get_header_fields:
1074 * @message: A #GDBusMessage.
1076 * Gets an array of all header fields on @message that are set.
1078 * Returns: (array zero-terminated=1): An array of header fields
1079 * terminated by %G_DBUS_MESSAGE_HEADER_FIELD_INVALID. Each element
1080 * is a #guchar. Free with g_free().
1085 g_dbus_message_get_header_fields (GDBusMessage *message)
1090 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1092 keys = g_hash_table_get_keys_as_ptr_array (message->headers);
1093 array = g_array_sized_new (FALSE, FALSE, sizeof (guchar), keys->len + 1);
1095 for (guint i = 0; i < keys->len; ++i)
1097 guchar val = GPOINTER_TO_UINT (g_ptr_array_index (keys, i));
1098 g_array_append_val (array, val);
1101 g_assert (array->len == keys->len);
1102 g_clear_pointer (&keys, g_ptr_array_unref);
1104 guchar invalid_field = G_DBUS_MESSAGE_HEADER_FIELD_INVALID;
1105 g_array_append_val (array, invalid_field);
1107 return (guchar *) g_array_free (array, FALSE);
1110 /* ---------------------------------------------------------------------------------------------------- */
1113 * g_dbus_message_get_body:
1114 * @message: A #GDBusMessage.
1116 * Gets the body of a message.
1118 * Returns: (nullable) (transfer none): A #GVariant or %NULL if the body is
1119 * empty. Do not free, it is owned by @message.
1124 g_dbus_message_get_body (GDBusMessage *message)
1126 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1127 return message->body;
1131 * g_dbus_message_set_body:
1132 * @message: A #GDBusMessage.
1133 * @body: Either %NULL or a #GVariant that is a tuple.
1135 * Sets the body @message. As a side-effect the
1136 * %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field is set to the
1137 * type string of @body (or cleared if @body is %NULL).
1139 * If @body is floating, @message assumes ownership of @body.
1144 g_dbus_message_set_body (GDBusMessage *message,
1147 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1148 g_return_if_fail ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE));
1150 if (message->locked)
1152 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1156 if (message->body != NULL)
1157 g_variant_unref (message->body);
1159 g_clear_pointer (&message->arg0_cache, g_variant_unref);
1163 message->body = NULL;
1164 g_dbus_message_set_signature (message, NULL);
1168 const gchar *type_string;
1169 gsize type_string_len;
1172 message->body = g_variant_ref_sink (body);
1174 if (g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE) &&
1175 g_variant_n_children (message->body) > 0)
1176 message->arg0_cache = g_variant_get_child_value (message->body, 0);
1178 type_string = g_variant_get_type_string (body);
1179 type_string_len = strlen (type_string);
1180 g_assert (type_string_len >= 2);
1181 signature = g_strndup (type_string + 1, type_string_len - 2);
1182 g_dbus_message_set_signature (message, signature);
1187 /* ---------------------------------------------------------------------------------------------------- */
1191 * g_dbus_message_get_unix_fd_list:
1192 * @message: A #GDBusMessage.
1194 * Gets the UNIX file descriptors associated with @message, if any.
1196 * This method is only available on UNIX.
1198 * The file descriptors normally correspond to %G_VARIANT_TYPE_HANDLE
1199 * values in the body of the message. For example,
1200 * if g_variant_get_handle() returns 5, that is intended to be a reference
1201 * to the file descriptor that can be accessed by
1202 * `g_unix_fd_list_get (list, 5, ...)`.
1204 * Returns: (nullable) (transfer none): A #GUnixFDList or %NULL if no file descriptors are
1205 * associated. Do not free, this object is owned by @message.
1210 g_dbus_message_get_unix_fd_list (GDBusMessage *message)
1212 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1213 return message->fd_list;
1217 * g_dbus_message_set_unix_fd_list:
1218 * @message: A #GDBusMessage.
1219 * @fd_list: (nullable): A #GUnixFDList or %NULL.
1221 * Sets the UNIX file descriptors associated with @message. As a
1222 * side-effect the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header
1223 * field is set to the number of fds in @fd_list (or cleared if
1224 * @fd_list is %NULL).
1226 * This method is only available on UNIX.
1228 * When designing D-Bus APIs that are intended to be interoperable,
1229 * please note that non-GDBus implementations of D-Bus can usually only
1230 * access file descriptors if they are referenced by a value of type
1231 * %G_VARIANT_TYPE_HANDLE in the body of the message.
1236 g_dbus_message_set_unix_fd_list (GDBusMessage *message,
1237 GUnixFDList *fd_list)
1239 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1240 g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
1242 if (message->locked)
1244 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1248 if (message->fd_list != NULL)
1249 g_object_unref (message->fd_list);
1250 if (fd_list != NULL)
1252 message->fd_list = g_object_ref (fd_list);
1253 g_dbus_message_set_num_unix_fds (message, g_unix_fd_list_get_length (fd_list));
1257 message->fd_list = NULL;
1258 g_dbus_message_set_num_unix_fds (message, 0);
1263 /* ---------------------------------------------------------------------------------------------------- */
1266 get_type_fixed_size (const GVariantType *type)
1268 /* NB: we do not treat 'b' as fixed-size here because GVariant and
1269 * D-Bus disagree about the size.
1271 switch (*g_variant_type_peek_string (type))
1277 case 'i': case 'u': case 'h':
1279 case 'x': case 't': case 'd':
1287 message_type_to_string (GDBusMessageType message_type)
1289 switch (message_type)
1291 case G_DBUS_MESSAGE_TYPE_INVALID:
1293 case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
1294 return "METHOD_CALL";
1295 case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
1296 return "METHOD_RETURN";
1297 case G_DBUS_MESSAGE_TYPE_ERROR:
1299 case G_DBUS_MESSAGE_TYPE_SIGNAL:
1302 return "unknown-type";
1307 message_header_field_to_string (GDBusMessageHeaderField field)
1311 case G_DBUS_MESSAGE_HEADER_FIELD_INVALID:
1313 case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
1315 case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
1317 case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
1319 case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
1320 return "ERROR_NAME";
1321 case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
1322 return "REPLY_SERIAL";
1323 case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
1324 return "DESTINATION";
1325 case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
1327 case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
1329 case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
1330 return "NUM_UNIX_FDS";
1332 return "unknown-field";
1337 validate_header (GDBusMessage *message,
1338 GDBusMessageHeaderField field,
1339 GVariant *header_value,
1340 const GVariantType *expected_type,
1343 g_assert (header_value != NULL);
1345 if (!g_variant_is_of_type (header_value, expected_type))
1347 char *expected_type_string = g_variant_type_dup_string (expected_type);
1350 G_IO_ERROR_INVALID_ARGUMENT,
1351 _("%s message: %s header field is invalid; expected a value of type ‘%s’"),
1352 message_type_to_string (message->type),
1353 message_header_field_to_string (field),
1354 expected_type_string);
1355 g_free (expected_type_string);
1363 require_header (GDBusMessage *message,
1364 GDBusMessageHeaderField field,
1367 GVariant *header_value = g_dbus_message_get_header (message, field);
1369 if (header_value == NULL)
1373 G_IO_ERROR_INVALID_ARGUMENT,
1374 _("%s message: %s header field is missing or invalid"),
1375 message_type_to_string (message->type),
1376 message_header_field_to_string (field));
1383 /* Implement the validation rules given in
1384 * https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-header-fields */
1386 validate_headers (GDBusMessage *message,
1390 GHashTableIter headers_iter;
1392 GVariant *header_value;
1394 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1395 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1399 /* Validate the types of all known headers. */
1400 g_hash_table_iter_init (&headers_iter, message->headers);
1401 while (g_hash_table_iter_next (&headers_iter, &key, (gpointer) &header_value))
1403 GDBusMessageHeaderField field_type = GPOINTER_TO_INT (key);
1407 case G_DBUS_MESSAGE_HEADER_FIELD_INVALID:
1408 /* The invalid header must be rejected as per
1409 * https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-header-fields */
1412 G_IO_ERROR_INVALID_ARGUMENT,
1413 _("%s message: INVALID header field supplied"),
1414 message_type_to_string (message->type));
1416 case G_DBUS_MESSAGE_HEADER_FIELD_PATH:
1417 if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_OBJECT_PATH, error))
1419 if (g_strcmp0 (g_variant_get_string (header_value, NULL), "/org/freedesktop/DBus/Local") == 0)
1423 G_IO_ERROR_INVALID_ARGUMENT,
1424 _("%s message: PATH header field is using the reserved value /org/freedesktop/DBus/Local"),
1425 message_type_to_string (message->type));
1429 case G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE:
1430 if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_STRING, error))
1432 if (!g_dbus_is_interface_name (g_variant_get_string (header_value, NULL)))
1436 G_IO_ERROR_INVALID_ARGUMENT,
1437 _("%s message: INTERFACE header field does not contain a valid interface name"),
1438 message_type_to_string (message->type));
1441 if (g_strcmp0 (g_variant_get_string (header_value, NULL), "org.freedesktop.DBus.Local") == 0)
1445 G_IO_ERROR_INVALID_ARGUMENT,
1446 _("%s message: INTERFACE header field is using the reserved value org.freedesktop.DBus.Local"),
1447 message_type_to_string (message->type));
1451 case G_DBUS_MESSAGE_HEADER_FIELD_MEMBER:
1452 if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_STRING, error))
1454 if (!g_dbus_is_member_name (g_variant_get_string (header_value, NULL)))
1458 G_IO_ERROR_INVALID_ARGUMENT,
1459 _("%s message: MEMBER header field does not contain a valid member name"),
1460 message_type_to_string (message->type));
1464 case G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME:
1465 if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_STRING, error))
1467 if (!g_dbus_is_error_name (g_variant_get_string (header_value, NULL)))
1471 G_IO_ERROR_INVALID_ARGUMENT,
1472 _("%s message: ERROR_NAME header field does not contain a valid error name"),
1473 message_type_to_string (message->type));
1477 case G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL:
1478 if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_UINT32, error))
1481 case G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION:
1482 if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_STRING, error))
1485 case G_DBUS_MESSAGE_HEADER_FIELD_SENDER:
1486 if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_STRING, error))
1489 case G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE:
1490 if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_SIGNATURE, error))
1493 case G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS:
1494 if (!validate_header (message, field_type, header_value, G_VARIANT_TYPE_UINT32, error))
1498 /* Ignore unknown fields as per
1499 * https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-header-fields. */
1504 /* Check for message-type-specific required headers. */
1505 switch (message->type)
1507 case G_DBUS_MESSAGE_TYPE_INVALID:
1508 g_set_error_literal (error,
1510 G_IO_ERROR_INVALID_ARGUMENT,
1511 _("type is INVALID"));
1514 case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
1515 if (!require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, error) ||
1516 !require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, error))
1520 case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
1521 if (!require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, error))
1525 case G_DBUS_MESSAGE_TYPE_ERROR:
1526 if (!require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, error) ||
1527 !require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, error))
1531 case G_DBUS_MESSAGE_TYPE_SIGNAL:
1532 if (!require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, error) ||
1533 !require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, error) ||
1534 !require_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, error))
1539 /* hitherto unknown type - nothing to check */
1546 g_assert (ret || (error == NULL || *error != NULL));
1550 /* ---------------------------------------------------------------------------------------------------- */
1553 ensure_input_padding (GMemoryBuffer *buf,
1557 gsize wanted_offset;
1560 wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1561 buf->pos = wanted_offset;
1565 static const gchar *
1566 read_string (GMemoryBuffer *mbuf,
1571 const gchar *end_valid;
1573 if G_UNLIKELY (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1575 mbuf->pos = mbuf->valid_len;
1576 /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1579 G_IO_ERROR_INVALID_ARGUMENT,
1580 g_dngettext (GETTEXT_PACKAGE,
1581 "Wanted to read %lu byte but only got %lu",
1582 "Wanted to read %lu bytes but only got %lu",
1585 (gulong)(mbuf->valid_len - mbuf->pos));
1589 if G_UNLIKELY (mbuf->data[mbuf->pos + len] != '\0')
1591 str = g_strndup (mbuf->data + mbuf->pos, len);
1594 G_IO_ERROR_INVALID_ARGUMENT,
1595 _("Expected NUL byte after the string “%s” but found byte %d"),
1596 str, mbuf->data[mbuf->pos + len]);
1598 mbuf->pos += len + 1;
1602 str = mbuf->data + mbuf->pos;
1603 mbuf->pos += len + 1;
1605 if G_UNLIKELY (!g_utf8_validate (str, -1, &end_valid))
1609 offset = (gint) (end_valid - str);
1610 valid_str = g_strndup (str, offset);
1613 G_IO_ERROR_INVALID_ARGUMENT,
1614 _("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
1615 "The valid UTF-8 string up until that point was “%s”"),
1626 static gconstpointer
1627 read_bytes (GMemoryBuffer *mbuf,
1631 gconstpointer result;
1633 if G_UNLIKELY (mbuf->pos + len > mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1635 mbuf->pos = mbuf->valid_len;
1636 /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1639 G_IO_ERROR_INVALID_ARGUMENT,
1640 g_dngettext (GETTEXT_PACKAGE,
1641 "Wanted to read %lu byte but only got %lu",
1642 "Wanted to read %lu bytes but only got %lu",
1645 (gulong)(mbuf->valid_len - mbuf->pos));
1649 result = mbuf->data + mbuf->pos;
1655 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
1657 /* returns a non-floating GVariant! */
1659 parse_value_from_blob (GMemoryBuffer *buf,
1660 const GVariantType *type,
1662 gboolean just_align,
1666 GVariant *ret = NULL;
1667 GError *local_error = NULL;
1668 #ifdef DEBUG_SERIALIZER
1670 #endif /* DEBUG_SERIALIZER */
1671 const gchar *type_string;
1675 g_set_error_literal (&local_error,
1677 G_IO_ERROR_INVALID_ARGUMENT,
1678 _("Value nested too deeply"));
1682 type_string = g_variant_type_peek_string (type);
1684 #ifdef DEBUG_SERIALIZER
1687 s = g_variant_type_dup_string (type);
1688 g_print ("%*s%s type %s from offset 0x%04x",
1690 just_align ? "Aligning" : "Reading",
1695 #endif /* DEBUG_SERIALIZER */
1697 #ifdef DEBUG_SERIALIZER
1699 #endif /* DEBUG_SERIALIZER */
1700 switch (type_string[0])
1702 case 'b': /* G_VARIANT_TYPE_BOOLEAN */
1703 ensure_input_padding (buf, 4);
1707 v = g_memory_buffer_read_uint32 (buf, &local_error);
1710 ret = g_variant_new_boolean (v);
1714 case 'y': /* G_VARIANT_TYPE_BYTE */
1718 v = g_memory_buffer_read_byte (buf, &local_error);
1721 ret = g_variant_new_byte (v);
1725 case 'n': /* G_VARIANT_TYPE_INT16 */
1726 ensure_input_padding (buf, 2);
1730 v = g_memory_buffer_read_int16 (buf, &local_error);
1733 ret = g_variant_new_int16 (v);
1737 case 'q': /* G_VARIANT_TYPE_UINT16 */
1738 ensure_input_padding (buf, 2);
1742 v = g_memory_buffer_read_uint16 (buf, &local_error);
1745 ret = g_variant_new_uint16 (v);
1749 case 'i': /* G_VARIANT_TYPE_INT32 */
1750 ensure_input_padding (buf, 4);
1754 v = g_memory_buffer_read_int32 (buf, &local_error);
1757 ret = g_variant_new_int32 (v);
1761 case 'u': /* G_VARIANT_TYPE_UINT32 */
1762 ensure_input_padding (buf, 4);
1766 v = g_memory_buffer_read_uint32 (buf, &local_error);
1769 ret = g_variant_new_uint32 (v);
1773 case 'x': /* G_VARIANT_TYPE_INT64 */
1774 ensure_input_padding (buf, 8);
1778 v = g_memory_buffer_read_int64 (buf, &local_error);
1781 ret = g_variant_new_int64 (v);
1785 case 't': /* G_VARIANT_TYPE_UINT64 */
1786 ensure_input_padding (buf, 8);
1790 v = g_memory_buffer_read_uint64 (buf, &local_error);
1793 ret = g_variant_new_uint64 (v);
1797 case 'd': /* G_VARIANT_TYPE_DOUBLE */
1798 ensure_input_padding (buf, 8);
1805 G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
1806 u.v_uint64 = g_memory_buffer_read_uint64 (buf, &local_error);
1809 ret = g_variant_new_double (u.v_double);
1813 case 's': /* G_VARIANT_TYPE_STRING */
1814 ensure_input_padding (buf, 4);
1819 len = g_memory_buffer_read_uint32 (buf, &local_error);
1822 v = read_string (buf, (gsize) len, &local_error);
1825 ret = g_variant_new_string (v);
1829 case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
1830 ensure_input_padding (buf, 4);
1835 len = g_memory_buffer_read_uint32 (buf, &local_error);
1838 v = read_string (buf, (gsize) len, &local_error);
1841 if (!g_variant_is_object_path (v))
1843 g_set_error (&local_error,
1845 G_IO_ERROR_INVALID_ARGUMENT,
1846 _("Parsed value “%s” is not a valid D-Bus object path"),
1850 ret = g_variant_new_object_path (v);
1854 case 'g': /* G_VARIANT_TYPE_SIGNATURE */
1859 len = g_memory_buffer_read_byte (buf, &local_error);
1862 v = read_string (buf, (gsize) len, &local_error);
1865 if (!g_variant_is_signature (v))
1867 g_set_error (&local_error,
1869 G_IO_ERROR_INVALID_ARGUMENT,
1870 _("Parsed value “%s” is not a valid D-Bus signature"),
1874 ret = g_variant_new_signature (v);
1878 case 'h': /* G_VARIANT_TYPE_HANDLE */
1879 ensure_input_padding (buf, 4);
1883 v = g_memory_buffer_read_int32 (buf, &local_error);
1886 ret = g_variant_new_handle (v);
1890 case 'a': /* G_VARIANT_TYPE_ARRAY */
1891 ensure_input_padding (buf, 4);
1893 /* If we are only aligning for this array type, it is the child type of
1894 * another array, which is empty. So, we do not need to add padding for
1895 * this nonexistent array's elements: we only need to align for this
1896 * array itself (4 bytes). See
1897 * <https://bugzilla.gnome.org/show_bug.cgi?id=673612>.
1902 const GVariantType *element_type;
1905 array_len = g_memory_buffer_read_uint32 (buf, &local_error);
1909 #ifdef DEBUG_SERIALIZER
1911 g_print (": array spans 0x%04x bytes\n", array_len);
1912 #endif /* DEBUG_SERIALIZER */
1914 if (array_len > (2<<26))
1916 /* G_GUINT32_FORMAT doesn't work with gettext, so use u */
1917 g_set_error (&local_error,
1919 G_IO_ERROR_INVALID_ARGUMENT,
1920 g_dngettext (GETTEXT_PACKAGE,
1921 "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB).",
1922 "Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB).",
1928 element_type = g_variant_type_element (type);
1929 fixed_size = get_type_fixed_size (element_type);
1931 /* Fast-path the cases like 'ay', etc. */
1932 if (fixed_size != 0)
1934 gconstpointer array_data;
1936 if (array_len % fixed_size != 0)
1938 g_set_error (&local_error,
1940 G_IO_ERROR_INVALID_ARGUMENT,
1941 _("Encountered array of type “a%c”, expected to have a length a multiple "
1942 "of %u bytes, but found to be %u bytes in length"),
1943 g_variant_type_peek_string (element_type)[0], fixed_size, array_len);
1949 /* If we had recursed into parse_value_from_blob() again to
1950 * parse the array values, this would have been emitted. */
1951 g_set_error_literal (&local_error,
1953 G_IO_ERROR_INVALID_ARGUMENT,
1954 _("Value nested too deeply"));
1958 ensure_input_padding (buf, fixed_size);
1959 array_data = read_bytes (buf, array_len, &local_error);
1960 if (array_data == NULL)
1963 ret = g_variant_new_fixed_array (element_type, array_data, array_len / fixed_size, fixed_size);
1965 if (g_memory_buffer_is_byteswapped (buf))
1967 GVariant *tmp = g_variant_ref_sink (ret);
1968 ret = g_variant_byteswap (tmp);
1969 g_variant_unref (tmp);
1974 GVariantBuilder builder;
1978 g_variant_builder_init (&builder, type);
1982 GVariant *item G_GNUC_UNUSED /* when compiling with G_DISABLE_ASSERT */;
1983 item = parse_value_from_blob (buf,
1989 g_assert (item == NULL);
1994 target = offset + array_len;
1995 while (offset < target)
1998 item = parse_value_from_blob (buf,
2006 g_variant_builder_clear (&builder);
2009 g_variant_builder_add_value (&builder, item);
2010 g_variant_unref (item);
2012 /* Array elements must not be zero-length. There are no
2013 * valid zero-length serialisations of any types which
2014 * can be array elements in the D-Bus wire format, so this
2015 * assertion should always hold.
2017 * See https://gitlab.gnome.org/GNOME/glib/-/issues/2557
2019 g_assert (buf->pos > (gsize) offset);
2025 ret = g_variant_builder_end (&builder);
2031 if (g_variant_type_is_dict_entry (type))
2033 const GVariantType *key_type;
2034 const GVariantType *value_type;
2038 ensure_input_padding (buf, 8);
2040 #ifdef DEBUG_SERIALIZER
2043 #endif /* DEBUG_SERIALIZER */
2047 key_type = g_variant_type_key (type);
2048 key = parse_value_from_blob (buf,
2056 value_type = g_variant_type_value (type);
2057 value = parse_value_from_blob (buf,
2065 g_variant_unref (key);
2068 ret = g_variant_new_dict_entry (key, value);
2069 g_variant_unref (key);
2070 g_variant_unref (value);
2073 else if (g_variant_type_is_tuple (type))
2075 ensure_input_padding (buf, 8);
2077 #ifdef DEBUG_SERIALIZER
2080 #endif /* DEBUG_SERIALIZER */
2084 const GVariantType *element_type;
2085 GVariantBuilder builder;
2087 g_variant_builder_init (&builder, type);
2088 element_type = g_variant_type_first (type);
2091 g_variant_builder_clear (&builder);
2092 g_set_error_literal (&local_error,
2094 G_IO_ERROR_INVALID_ARGUMENT,
2095 _("Empty structures (tuples) are not allowed in D-Bus"));
2099 while (element_type != NULL)
2102 item = parse_value_from_blob (buf,
2110 g_variant_builder_clear (&builder);
2113 g_variant_builder_add_value (&builder, item);
2114 g_variant_unref (item);
2116 element_type = g_variant_type_next (element_type);
2118 ret = g_variant_builder_end (&builder);
2121 else if (g_variant_type_is_variant (type))
2123 #ifdef DEBUG_SERIALIZER
2126 #endif /* DEBUG_SERIALIZER */
2132 GVariantType *variant_type;
2135 siglen = g_memory_buffer_read_byte (buf, &local_error);
2138 sig = read_string (buf, (gsize) siglen, &local_error);
2141 if (!g_variant_is_signature (sig) ||
2142 !g_variant_type_string_is_valid (sig))
2144 /* A D-Bus signature can contain zero or more complete types,
2145 * but a GVariant has to be exactly one complete type. */
2146 g_set_error (&local_error,
2148 G_IO_ERROR_INVALID_ARGUMENT,
2149 _("Parsed value “%s” for variant is not a valid D-Bus signature"),
2154 if (max_depth <= g_variant_type_string_get_depth_ (sig))
2156 /* Catch the type nesting being too deep without having to
2157 * parse the data. We don’t have to check this for static
2158 * container types (like arrays and tuples, above) because
2159 * the g_variant_type_string_is_valid() check performed before
2160 * the initial parse_value_from_blob() call should check the
2161 * static type nesting. */
2162 g_set_error_literal (&local_error,
2164 G_IO_ERROR_INVALID_ARGUMENT,
2165 _("Value nested too deeply"));
2169 variant_type = g_variant_type_new (sig);
2170 value = parse_value_from_blob (buf,
2176 g_variant_type_free (variant_type);
2179 ret = g_variant_new_variant (value);
2180 g_variant_unref (value);
2186 s = g_variant_type_dup_string (type);
2187 g_set_error (&local_error,
2189 G_IO_ERROR_INVALID_ARGUMENT,
2190 _("Error deserializing GVariant with type string “%s” from the D-Bus wire format"),
2198 g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
2200 #ifdef DEBUG_SERIALIZER
2206 if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
2208 s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
2212 s = g_variant_print (ret, FALSE);
2214 g_print (": %s\n", s);
2218 #endif /* DEBUG_SERIALIZER */
2220 /* sink the reference, if floating */
2222 g_variant_take_ref (ret);
2226 #ifdef DEBUG_SERIALIZER
2228 "%*sFAILURE: %s (%s, %d)\n",
2230 local_error->message,
2231 g_quark_to_string (local_error->domain),
2233 #endif /* DEBUG_SERIALIZER */
2234 g_propagate_error (error, local_error);
2238 /* ---------------------------------------------------------------------------------------------------- */
2240 /* message_header must be at least 16 bytes */
2243 * g_dbus_message_bytes_needed:
2244 * @blob: (array length=blob_len) (element-type guint8): A blob representing a binary D-Bus message.
2245 * @blob_len: The length of @blob (must be at least 16).
2246 * @error: Return location for error or %NULL.
2248 * Utility function to calculate how many bytes are needed to
2249 * completely deserialize the D-Bus message stored at @blob.
2251 * Returns: Number of bytes needed or -1 if @error is set (e.g. if
2252 * @blob contains invalid data or not enough data is available to
2253 * determine the size).
2258 g_dbus_message_bytes_needed (guchar *blob,
2266 g_return_val_if_fail (blob != NULL, -1);
2267 g_return_val_if_fail (error == NULL || *error == NULL, -1);
2268 g_return_val_if_fail (blob_len >= 16, -1);
2272 /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
2273 ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
2274 /* round up so it's a multiple of 8 */
2275 ret = 8 * ((ret + 7)/8);
2276 /* finally add the body size */
2277 ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
2279 else if (blob[0] == 'B')
2281 /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
2282 ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
2283 /* round up so it's a multiple of 8 */
2284 ret = 8 * ((ret + 7)/8);
2285 /* finally add the body size */
2286 ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
2292 G_IO_ERROR_INVALID_ARGUMENT,
2293 "Unable to determine message blob length - given blob is malformed");
2300 G_IO_ERROR_INVALID_ARGUMENT,
2301 "Blob indicates that message exceeds maximum message length (128MiB)");
2308 /* ---------------------------------------------------------------------------------------------------- */
2311 * g_dbus_message_new_from_blob:
2312 * @blob: (array length=blob_len) (element-type guint8): A blob representing a binary D-Bus message.
2313 * @blob_len: The length of @blob.
2314 * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2315 * @error: Return location for error or %NULL.
2317 * Creates a new #GDBusMessage from the data stored at @blob. The byte
2318 * order that the message was in can be retrieved using
2319 * g_dbus_message_get_byte_order().
2321 * If the @blob cannot be parsed, contains invalid fields, or contains invalid
2322 * headers, %G_IO_ERROR_INVALID_ARGUMENT will be returned.
2324 * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
2330 g_dbus_message_new_from_blob (guchar *blob,
2332 GDBusCapabilityFlags capabilities,
2335 GError *local_error = NULL;
2337 GDBusMessage *message;
2339 guchar major_protocol_version;
2340 guint32 message_body_len;
2344 GVariant *signature;
2346 /* TODO: check against @capabilities */
2348 g_return_val_if_fail (blob != NULL, NULL);
2349 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2351 message = g_dbus_message_new ();
2353 memset (&mbuf, 0, sizeof (mbuf));
2354 mbuf.data = (gchar *)blob;
2355 mbuf.len = mbuf.valid_len = blob_len;
2357 endianness = g_memory_buffer_read_byte (&mbuf, &local_error);
2364 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2365 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
2368 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2369 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
2372 g_set_error (&local_error,
2374 G_IO_ERROR_INVALID_ARGUMENT,
2375 _("Invalid endianness value. Expected 0x6c (“l”) or 0x42 (“B”) but found value 0x%02x"),
2380 message->type = g_memory_buffer_read_byte (&mbuf, &local_error);
2383 message->flags = g_memory_buffer_read_byte (&mbuf, &local_error);
2386 major_protocol_version = g_memory_buffer_read_byte (&mbuf, &local_error);
2389 if (major_protocol_version != 1)
2391 g_set_error (&local_error,
2393 G_IO_ERROR_INVALID_ARGUMENT,
2394 _("Invalid major protocol version. Expected 1 but found %d"),
2395 major_protocol_version);
2398 message_body_len = g_memory_buffer_read_uint32 (&mbuf, &local_error);
2401 message->serial = g_memory_buffer_read_uint32 (&mbuf, &local_error);
2405 #ifdef DEBUG_SERIALIZER
2406 g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2409 s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
2410 g_print ("%s\n", s);
2413 #endif /* DEBUG_SERIALIZER */
2415 #ifdef DEBUG_SERIALIZER
2416 g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2417 #endif /* DEBUG_SERIALIZER */
2418 headers = parse_value_from_blob (&mbuf,
2419 G_VARIANT_TYPE ("a{yv}"),
2420 G_DBUS_MAX_TYPE_DEPTH + 2 /* for the a{yv} */,
2424 if (headers == NULL)
2426 g_variant_iter_init (&iter, headers);
2427 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2429 guchar header_field;
2431 g_variant_get (item,
2435 g_dbus_message_set_header (message, header_field, value);
2436 g_variant_unref (value);
2437 g_variant_unref (item);
2439 g_variant_unref (headers);
2441 signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2442 if (signature != NULL)
2444 const gchar *signature_str;
2445 gsize signature_str_len;
2447 if (!g_variant_is_of_type (signature, G_VARIANT_TYPE_SIGNATURE))
2449 g_set_error_literal (&local_error,
2451 G_IO_ERROR_INVALID_ARGUMENT,
2452 _("Signature header found but is not of type signature"));
2456 signature_str = g_variant_get_string (signature, &signature_str_len);
2458 /* signature but no body */
2459 if (message_body_len == 0 && signature_str_len > 0)
2461 g_set_error (&local_error,
2463 G_IO_ERROR_INVALID_ARGUMENT,
2464 _("Signature header with signature “%s” found but message body is empty"),
2468 else if (signature_str_len > 0)
2470 GVariantType *variant_type;
2471 gchar *tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2473 if (!g_variant_is_signature (signature_str) ||
2474 !g_variant_type_string_is_valid (tupled_signature_str))
2476 g_set_error (&local_error,
2478 G_IO_ERROR_INVALID_ARGUMENT,
2479 _("Parsed value “%s” is not a valid D-Bus signature (for body)"),
2481 g_free (tupled_signature_str);
2485 variant_type = g_variant_type_new (tupled_signature_str);
2486 g_free (tupled_signature_str);
2487 #ifdef DEBUG_SERIALIZER
2488 g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2489 #endif /* DEBUG_SERIALIZER */
2490 message->body = parse_value_from_blob (&mbuf,
2492 G_DBUS_MAX_TYPE_DEPTH + 1 /* for the surrounding tuple */,
2496 g_variant_type_free (variant_type);
2498 if (message->body != NULL &&
2499 g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE) &&
2500 g_variant_n_children (message->body) > 0)
2501 message->arg0_cache = g_variant_get_child_value (message->body, 0);
2503 message->arg0_cache = NULL;
2505 if (message->body == NULL)
2511 /* no signature, this is only OK if the body is empty */
2512 if (message_body_len != 0)
2514 /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
2515 g_set_error (&local_error,
2517 G_IO_ERROR_INVALID_ARGUMENT,
2518 g_dngettext (GETTEXT_PACKAGE,
2519 "No signature header in message but the message body is %u byte",
2520 "No signature header in message but the message body is %u bytes",
2527 if (!validate_headers (message, &local_error))
2529 g_prefix_error (&local_error, _("Cannot deserialize message: "));
2536 g_clear_object (&message);
2537 g_propagate_error (error, local_error);
2541 /* ---------------------------------------------------------------------------------------------------- */
2544 ensure_output_padding (GMemoryBuffer *mbuf,
2548 gsize wanted_offset;
2549 gsize padding_needed;
2553 wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
2554 padding_needed = wanted_offset - offset;
2556 for (n = 0; n < padding_needed; n++)
2557 g_memory_buffer_put_byte (mbuf, '\0');
2559 return padding_needed;
2562 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
2564 append_value_to_blob (GVariant *value,
2565 const GVariantType *type,
2566 GMemoryBuffer *mbuf,
2567 gsize *out_padding_added,
2570 gsize padding_added;
2571 const gchar *type_string;
2573 type_string = g_variant_type_peek_string (type);
2577 switch (type_string[0])
2579 case 'b': /* G_VARIANT_TYPE_BOOLEAN */
2580 padding_added = ensure_output_padding (mbuf, 4);
2583 gboolean v = g_variant_get_boolean (value);
2584 g_memory_buffer_put_uint32 (mbuf, v);
2588 case 'y': /* G_VARIANT_TYPE_BYTE */
2591 guint8 v = g_variant_get_byte (value);
2592 g_memory_buffer_put_byte (mbuf, v);
2596 case 'n': /* G_VARIANT_TYPE_INT16 */
2597 padding_added = ensure_output_padding (mbuf, 2);
2600 gint16 v = g_variant_get_int16 (value);
2601 g_memory_buffer_put_int16 (mbuf, v);
2605 case 'q': /* G_VARIANT_TYPE_UINT16 */
2606 padding_added = ensure_output_padding (mbuf, 2);
2609 guint16 v = g_variant_get_uint16 (value);
2610 g_memory_buffer_put_uint16 (mbuf, v);
2614 case 'i': /* G_VARIANT_TYPE_INT32 */
2615 padding_added = ensure_output_padding (mbuf, 4);
2618 gint32 v = g_variant_get_int32 (value);
2619 g_memory_buffer_put_int32 (mbuf, v);
2623 case 'u': /* G_VARIANT_TYPE_UINT32 */
2624 padding_added = ensure_output_padding (mbuf, 4);
2627 guint32 v = g_variant_get_uint32 (value);
2628 g_memory_buffer_put_uint32 (mbuf, v);
2632 case 'x': /* G_VARIANT_TYPE_INT64 */
2633 padding_added = ensure_output_padding (mbuf, 8);
2636 gint64 v = g_variant_get_int64 (value);
2637 g_memory_buffer_put_int64 (mbuf, v);
2641 case 't': /* G_VARIANT_TYPE_UINT64 */
2642 padding_added = ensure_output_padding (mbuf, 8);
2645 guint64 v = g_variant_get_uint64 (value);
2646 g_memory_buffer_put_uint64 (mbuf, v);
2650 case 'd': /* G_VARIANT_TYPE_DOUBLE */
2651 padding_added = ensure_output_padding (mbuf, 8);
2658 G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
2659 u.v_double = g_variant_get_double (value);
2660 g_memory_buffer_put_uint64 (mbuf, u.v_uint64);
2664 case 's': /* G_VARIANT_TYPE_STRING */
2665 padding_added = ensure_output_padding (mbuf, 4);
2670 #ifndef G_DISABLE_ASSERT
2674 v = g_variant_get_string (value, &len);
2675 g_assert (g_utf8_validate (v, -1, &end) && (end == v + len));
2676 g_memory_buffer_put_uint32 (mbuf, len);
2677 g_memory_buffer_put_string (mbuf, v);
2678 g_memory_buffer_put_byte (mbuf, '\0');
2682 case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
2683 padding_added = ensure_output_padding (mbuf, 4);
2687 const gchar *v = g_variant_get_string (value, &len);
2688 g_assert (g_variant_is_object_path (v));
2689 g_memory_buffer_put_uint32 (mbuf, len);
2690 g_memory_buffer_put_string (mbuf, v);
2691 g_memory_buffer_put_byte (mbuf, '\0');
2695 case 'g': /* G_VARIANT_TYPE_SIGNATURE */
2699 const gchar *v = g_variant_get_string (value, &len);
2700 g_assert (g_variant_is_signature (v));
2701 g_memory_buffer_put_byte (mbuf, len);
2702 g_memory_buffer_put_string (mbuf, v);
2703 g_memory_buffer_put_byte (mbuf, '\0');
2707 case 'h': /* G_VARIANT_TYPE_HANDLE */
2708 padding_added = ensure_output_padding (mbuf, 4);
2711 gint32 v = g_variant_get_handle (value);
2712 g_memory_buffer_put_int32 (mbuf, v);
2716 case 'a': /* G_VARIANT_TYPE_ARRAY */
2718 const GVariantType *element_type;
2721 goffset array_len_offset;
2722 goffset array_payload_begin_offset;
2727 padding_added = ensure_output_padding (mbuf, 4);
2730 /* array length - will be filled in later */
2731 array_len_offset = mbuf->valid_len;
2732 g_memory_buffer_put_uint32 (mbuf, 0xF00DFACE);
2734 /* From the D-Bus spec:
2736 * "A UINT32 giving the length of the array data in bytes,
2737 * followed by alignment padding to the alignment boundary of
2738 * the array element type, followed by each array element. The
2739 * array length is from the end of the alignment padding to
2740 * the end of the last element, i.e. it does not include the
2741 * padding after the length, or any padding after the last
2744 * Thus, we need to count how much padding the first element
2745 * contributes and subtract that from the array length.
2747 array_payload_begin_offset = mbuf->valid_len;
2749 element_type = g_variant_type_element (type);
2750 fixed_size = get_type_fixed_size (element_type);
2752 if (g_variant_n_children (value) == 0)
2754 gsize padding_added_for_item;
2755 if (!append_value_to_blob (NULL,
2758 &padding_added_for_item,
2761 array_payload_begin_offset += padding_added_for_item;
2763 else if (fixed_size != 0)
2765 GVariant *use_value;
2767 if (g_memory_buffer_is_byteswapped (mbuf))
2768 use_value = g_variant_byteswap (value);
2770 use_value = g_variant_ref (value);
2772 array_payload_begin_offset += ensure_output_padding (mbuf, fixed_size);
2774 array_len = g_variant_get_size (use_value);
2775 g_memory_buffer_write (mbuf, g_variant_get_data (use_value), array_len);
2776 g_variant_unref (use_value);
2782 g_variant_iter_init (&iter, value);
2783 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2785 gsize padding_added_for_item;
2786 if (!append_value_to_blob (item,
2787 g_variant_get_type (item),
2789 &padding_added_for_item,
2792 g_variant_unref (item);
2795 g_variant_unref (item);
2798 array_payload_begin_offset += padding_added_for_item;
2804 cur_offset = mbuf->valid_len;
2805 array_len = cur_offset - array_payload_begin_offset;
2806 mbuf->pos = array_len_offset;
2808 g_memory_buffer_put_uint32 (mbuf, array_len);
2809 mbuf->pos = cur_offset;
2815 if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
2817 if (!g_variant_type_first (type))
2819 g_set_error_literal (error,
2821 G_IO_ERROR_INVALID_ARGUMENT,
2822 _("Empty structures (tuples) are not allowed in D-Bus"));
2826 padding_added = ensure_output_padding (mbuf, 8);
2831 g_variant_iter_init (&iter, value);
2832 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2834 if (!append_value_to_blob (item,
2835 g_variant_get_type (item),
2840 g_variant_unref (item);
2843 g_variant_unref (item);
2847 else if (g_variant_type_is_variant (type))
2852 const gchar *signature;
2853 child = g_variant_get_child_value (value, 0);
2854 signature = g_variant_get_type_string (child);
2855 g_memory_buffer_put_byte (mbuf, strlen (signature));
2856 g_memory_buffer_put_string (mbuf, signature);
2857 g_memory_buffer_put_byte (mbuf, '\0');
2858 if (!append_value_to_blob (child,
2859 g_variant_get_type (child),
2864 g_variant_unref (child);
2867 g_variant_unref (child);
2874 G_IO_ERROR_INVALID_ARGUMENT,
2875 _("Error serializing GVariant with type string “%s” to the D-Bus wire format"),
2876 g_variant_get_type_string (value));
2882 if (out_padding_added != NULL)
2883 *out_padding_added = padding_added;
2892 append_body_to_blob (GVariant *value,
2893 GMemoryBuffer *mbuf,
2899 if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
2903 G_IO_ERROR_INVALID_ARGUMENT,
2904 "Expected a tuple for the body of the GDBusMessage.");
2908 g_variant_iter_init (&iter, value);
2909 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2911 if (!append_value_to_blob (item,
2912 g_variant_get_type (item),
2917 g_variant_unref (item);
2920 g_variant_unref (item);
2928 /* ---------------------------------------------------------------------------------------------------- */
2931 * g_dbus_message_to_blob:
2932 * @message: A #GDBusMessage.
2933 * @out_size: Return location for size of generated blob.
2934 * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2935 * @error: Return location for error.
2937 * Serializes @message to a blob. The byte order returned by
2938 * g_dbus_message_get_byte_order() will be used.
2940 * Returns: (array length=out_size) (transfer full): A pointer to a
2941 * valid binary D-Bus message of @out_size bytes generated by @message
2942 * or %NULL if @error is set. Free with g_free().
2947 g_dbus_message_to_blob (GDBusMessage *message,
2949 GDBusCapabilityFlags capabilities,
2955 goffset body_len_offset;
2956 goffset body_start_offset;
2958 GVariant *header_fields;
2959 GVariantBuilder builder;
2960 GHashTableIter hash_iter;
2962 GVariant *header_value;
2963 GVariant *signature;
2964 const gchar *signature_str;
2965 gint num_fds_in_message;
2966 gint num_fds_according_to_header;
2968 /* TODO: check against @capabilities */
2972 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2973 g_return_val_if_fail (out_size != NULL, NULL);
2974 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2976 memset (&mbuf, 0, sizeof (mbuf));
2977 mbuf.len = MIN_ARRAY_SIZE;
2978 mbuf.data = g_malloc (mbuf.len);
2980 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN;
2981 switch (message->byte_order)
2983 case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
2984 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2986 case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
2987 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2992 g_memory_buffer_put_byte (&mbuf, (guchar) message->byte_order);
2993 g_memory_buffer_put_byte (&mbuf, message->type);
2994 g_memory_buffer_put_byte (&mbuf, message->flags);
2995 g_memory_buffer_put_byte (&mbuf, 1); /* major protocol version */
2996 body_len_offset = mbuf.valid_len;
2997 /* body length - will be filled in later */
2998 g_memory_buffer_put_uint32 (&mbuf, 0xF00DFACE);
2999 g_memory_buffer_put_uint32 (&mbuf, message->serial);
3001 num_fds_in_message = 0;
3003 if (message->fd_list != NULL)
3004 num_fds_in_message = g_unix_fd_list_get_length (message->fd_list);
3006 num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
3007 if (num_fds_in_message != num_fds_according_to_header)
3011 G_IO_ERROR_INVALID_ARGUMENT,
3012 _("Number of file descriptors in message (%d) differs from header field (%d)"),
3014 num_fds_according_to_header);
3018 if (!validate_headers (message, error))
3020 g_prefix_error (error, _("Cannot serialize message: "));
3024 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
3025 g_hash_table_iter_init (&hash_iter, message->headers);
3026 while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
3028 g_variant_builder_add (&builder,
3030 (guchar) GPOINTER_TO_UINT (key),
3033 header_fields = g_variant_builder_end (&builder);
3035 if (!append_value_to_blob (header_fields,
3036 g_variant_get_type (header_fields),
3041 g_variant_unref (header_fields);
3044 g_variant_unref (header_fields);
3046 /* header size must be a multiple of 8 */
3047 ensure_output_padding (&mbuf, 8);
3049 body_start_offset = mbuf.valid_len;
3051 signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
3053 if (signature != NULL && !g_variant_is_of_type (signature, G_VARIANT_TYPE_SIGNATURE))
3055 g_set_error_literal (error,
3057 G_IO_ERROR_INVALID_ARGUMENT,
3058 _("Signature header found but is not of type signature"));
3062 signature_str = NULL;
3063 if (signature != NULL)
3064 signature_str = g_variant_get_string (signature, NULL);
3065 if (message->body != NULL)
3067 gchar *tupled_signature_str;
3068 if (signature == NULL)
3072 G_IO_ERROR_INVALID_ARGUMENT,
3073 _("Message body has signature “%s” but there is no signature header"),
3074 g_variant_get_type_string (message->body));
3077 tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
3078 if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
3082 G_IO_ERROR_INVALID_ARGUMENT,
3083 _("Message body has type signature “%s” but signature in the header field is “%s”"),
3084 g_variant_get_type_string (message->body), tupled_signature_str);
3085 g_free (tupled_signature_str);
3088 g_free (tupled_signature_str);
3089 if (!append_body_to_blob (message->body, &mbuf, error))
3094 if (signature != NULL && strlen (signature_str) > 0)
3098 G_IO_ERROR_INVALID_ARGUMENT,
3099 _("Message body is empty but signature in the header field is “(%s)”"),
3105 /* OK, we're done writing the message - set the body length */
3106 size = mbuf.valid_len;
3107 body_size = size - body_start_offset;
3109 mbuf.pos = body_len_offset;
3111 g_memory_buffer_put_uint32 (&mbuf, body_size);
3114 ret = (guchar *)mbuf.data;
3123 /* ---------------------------------------------------------------------------------------------------- */
3126 get_uint32_header (GDBusMessage *message,
3127 GDBusMessageHeaderField header_field)
3133 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3134 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
3135 ret = g_variant_get_uint32 (value);
3140 static const gchar *
3141 get_string_header (GDBusMessage *message,
3142 GDBusMessageHeaderField header_field)
3148 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3149 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
3150 ret = g_variant_get_string (value, NULL);
3155 static const gchar *
3156 get_object_path_header (GDBusMessage *message,
3157 GDBusMessageHeaderField header_field)
3163 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3164 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
3165 ret = g_variant_get_string (value, NULL);
3170 static const gchar *
3171 get_signature_header (GDBusMessage *message,
3172 GDBusMessageHeaderField header_field)
3178 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3179 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
3180 ret = g_variant_get_string (value, NULL);
3185 /* ---------------------------------------------------------------------------------------------------- */
3188 set_uint32_header (GDBusMessage *message,
3189 GDBusMessageHeaderField header_field,
3192 g_dbus_message_set_header (message,
3194 g_variant_new_uint32 (value));
3198 set_string_header (GDBusMessage *message,
3199 GDBusMessageHeaderField header_field,
3202 g_dbus_message_set_header (message,
3204 value == NULL ? NULL : g_variant_new_string (value));
3208 set_object_path_header (GDBusMessage *message,
3209 GDBusMessageHeaderField header_field,
3212 g_dbus_message_set_header (message,
3214 value == NULL ? NULL : g_variant_new_object_path (value));
3218 set_signature_header (GDBusMessage *message,
3219 GDBusMessageHeaderField header_field,
3222 g_dbus_message_set_header (message,
3224 value == NULL ? NULL : g_variant_new_signature (value));
3227 /* ---------------------------------------------------------------------------------------------------- */
3230 * g_dbus_message_get_reply_serial:
3231 * @message: A #GDBusMessage.
3233 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
3235 * Returns: The value.
3240 g_dbus_message_get_reply_serial (GDBusMessage *message)
3242 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3243 return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
3247 * g_dbus_message_set_reply_serial:
3248 * @message: A #GDBusMessage.
3249 * @value: The value to set.
3251 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
3256 g_dbus_message_set_reply_serial (GDBusMessage *message,
3259 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3260 set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
3263 /* ---------------------------------------------------------------------------------------------------- */
3266 * g_dbus_message_get_interface:
3267 * @message: A #GDBusMessage.
3269 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
3271 * Returns: (nullable): The value.
3276 g_dbus_message_get_interface (GDBusMessage *message)
3278 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3279 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
3283 * g_dbus_message_set_interface:
3284 * @message: A #GDBusMessage.
3285 * @value: (nullable): The value to set.
3287 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
3292 g_dbus_message_set_interface (GDBusMessage *message,
3295 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3296 g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
3297 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
3300 /* ---------------------------------------------------------------------------------------------------- */
3303 * g_dbus_message_get_member:
3304 * @message: A #GDBusMessage.
3306 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
3308 * Returns: (nullable): The value.
3313 g_dbus_message_get_member (GDBusMessage *message)
3315 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3316 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
3320 * g_dbus_message_set_member:
3321 * @message: A #GDBusMessage.
3322 * @value: (nullable): The value to set.
3324 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
3329 g_dbus_message_set_member (GDBusMessage *message,
3332 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3333 g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
3334 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
3337 /* ---------------------------------------------------------------------------------------------------- */
3340 * g_dbus_message_get_path:
3341 * @message: A #GDBusMessage.
3343 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
3345 * Returns: (nullable): The value.
3350 g_dbus_message_get_path (GDBusMessage *message)
3352 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3353 return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
3357 * g_dbus_message_set_path:
3358 * @message: A #GDBusMessage.
3359 * @value: (nullable): The value to set.
3361 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
3366 g_dbus_message_set_path (GDBusMessage *message,
3369 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3370 g_return_if_fail (value == NULL || g_variant_is_object_path (value));
3371 set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
3374 /* ---------------------------------------------------------------------------------------------------- */
3377 * g_dbus_message_get_sender:
3378 * @message: A #GDBusMessage.
3380 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3382 * Returns: (nullable): The value.
3387 g_dbus_message_get_sender (GDBusMessage *message)
3389 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3390 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
3394 * g_dbus_message_set_sender:
3395 * @message: A #GDBusMessage.
3396 * @value: (nullable): The value to set.
3398 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3403 g_dbus_message_set_sender (GDBusMessage *message,
3406 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3407 g_return_if_fail (value == NULL || g_dbus_is_name (value));
3408 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
3411 /* ---------------------------------------------------------------------------------------------------- */
3414 * g_dbus_message_get_destination:
3415 * @message: A #GDBusMessage.
3417 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3419 * Returns: (nullable): The value.
3424 g_dbus_message_get_destination (GDBusMessage *message)
3426 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3427 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
3431 * g_dbus_message_set_destination:
3432 * @message: A #GDBusMessage.
3433 * @value: (nullable): The value to set.
3435 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3440 g_dbus_message_set_destination (GDBusMessage *message,
3443 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3444 g_return_if_fail (value == NULL || g_dbus_is_name (value));
3445 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
3448 /* ---------------------------------------------------------------------------------------------------- */
3451 * g_dbus_message_get_error_name:
3452 * @message: A #GDBusMessage.
3454 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3456 * Returns: (nullable): The value.
3461 g_dbus_message_get_error_name (GDBusMessage *message)
3463 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3464 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
3468 * g_dbus_message_set_error_name:
3469 * @message: (nullable): A #GDBusMessage.
3470 * @value: The value to set.
3472 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3477 g_dbus_message_set_error_name (GDBusMessage *message,
3480 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3481 g_return_if_fail (value == NULL || g_dbus_is_error_name (value));
3482 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
3485 /* ---------------------------------------------------------------------------------------------------- */
3488 * g_dbus_message_get_signature:
3489 * @message: A #GDBusMessage.
3491 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3493 * This will always be non-%NULL, but may be an empty string.
3495 * Returns: (not nullable): The value.
3500 g_dbus_message_get_signature (GDBusMessage *message)
3503 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3504 ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
3511 * g_dbus_message_set_signature:
3512 * @message: A #GDBusMessage.
3513 * @value: (nullable): The value to set.
3515 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3520 g_dbus_message_set_signature (GDBusMessage *message,
3523 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3524 g_return_if_fail (value == NULL || g_variant_is_signature (value));
3525 set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
3528 /* ---------------------------------------------------------------------------------------------------- */
3531 * g_dbus_message_get_arg0:
3532 * @message: A #GDBusMessage.
3534 * Convenience to get the first item in the body of @message.
3536 * See [method@Gio.DBusMessage.get_arg0_path] for returning object-path-typed
3539 * Returns: (nullable): The string item or %NULL if the first item in the body of
3540 * @message is not a string.
3545 g_dbus_message_get_arg0 (GDBusMessage *message)
3547 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3549 if (message->arg0_cache != NULL &&
3550 g_variant_is_of_type (message->arg0_cache, G_VARIANT_TYPE_STRING))
3551 return g_variant_get_string (message->arg0_cache, NULL);
3557 * g_dbus_message_get_arg0_path:
3558 * @message: A `GDBusMessage`.
3560 * Convenience to get the first item in the body of @message.
3562 * See [method@Gio.DBusMessage.get_arg0] for returning string-typed arg0 values.
3564 * Returns: (nullable): The object path item or `NULL` if the first item in the
3565 * body of @message is not an object path.
3570 g_dbus_message_get_arg0_path (GDBusMessage *message)
3572 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3574 if (message->arg0_cache != NULL &&
3575 g_variant_is_of_type (message->arg0_cache, G_VARIANT_TYPE_OBJECT_PATH))
3576 return g_variant_get_string (message->arg0_cache, NULL);
3581 /* ---------------------------------------------------------------------------------------------------- */
3584 * g_dbus_message_get_num_unix_fds:
3585 * @message: A #GDBusMessage.
3587 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3589 * Returns: The value.
3594 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
3596 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3597 return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
3601 * g_dbus_message_set_num_unix_fds:
3602 * @message: A #GDBusMessage.
3603 * @value: The value to set.
3605 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3610 g_dbus_message_set_num_unix_fds (GDBusMessage *message,
3613 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3614 set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
3617 /* ---------------------------------------------------------------------------------------------------- */
3620 * g_dbus_message_to_gerror:
3621 * @message: A #GDBusMessage.
3622 * @error: The #GError to set.
3624 * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
3625 * nothing and returns %FALSE.
3627 * Otherwise this method encodes the error in @message as a #GError
3628 * using g_dbus_error_set_dbus_error() using the information in the
3629 * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
3630 * well as the first string item in @message's body.
3632 * Returns: %TRUE if @error was set, %FALSE otherwise.
3637 g_dbus_message_to_gerror (GDBusMessage *message,
3641 const gchar *error_name;
3643 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3646 if (message->type != G_DBUS_MESSAGE_TYPE_ERROR)
3649 error_name = g_dbus_message_get_error_name (message);
3650 if (error_name != NULL)
3654 body = g_dbus_message_get_body (message);
3656 if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
3658 const gchar *error_message;
3659 g_variant_get (body, "(&s)", &error_message);
3660 g_dbus_error_set_dbus_error (error,
3667 /* these two situations are valid, yet pretty rare */
3670 g_dbus_error_set_dbus_error (error,
3673 _("Error return with body of type “%s”"),
3674 g_variant_get_type_string (body));
3678 g_dbus_error_set_dbus_error (error,
3681 _("Error return with empty body"));
3687 /* TODO: this shouldn't happen - should check this at message serialization
3688 * time and disconnect the peer.
3693 "Error return without error-name header!");
3702 /* ---------------------------------------------------------------------------------------------------- */
3705 flags_to_string (GType flags_type, guint value)
3711 klass = g_type_class_ref (flags_type);
3712 s = g_string_new (NULL);
3713 for (n = 0; n < 32; n++)
3715 if ((value & (1<<n)) != 0)
3717 GFlagsValue *flags_value;
3718 flags_value = g_flags_get_first_value (klass, (1<<n));
3720 g_string_append_c (s, ',');
3721 if (flags_value != NULL)
3722 g_string_append (s, flags_value->value_nick);
3724 g_string_append_printf (s, "unknown (bit %d)", n);
3728 g_string_append (s, "none");
3729 g_type_class_unref (klass);
3730 return g_string_free (s, FALSE);
3734 _sort_keys_func (gconstpointer a,
3740 ia = GPOINTER_TO_INT (a);
3741 ib = GPOINTER_TO_INT (b);
3747 * g_dbus_message_print:
3748 * @message: A #GDBusMessage.
3749 * @indent: Indentation level.
3751 * Produces a human-readable multi-line description of @message.
3753 * The contents of the description has no ABI guarantees, the contents
3754 * and formatting is subject to change at any time. Typical output
3755 * looks something like this:
3762 * path -> objectpath '/org/gtk/GDBus/TestObject'
3763 * interface -> 'org.gtk.GDBus.TestInterface'
3764 * member -> 'GimmeStdout'
3765 * destination -> ':1.146'
3767 * UNIX File Descriptors:
3772 * Type: method-return
3773 * Flags: no-reply-expected
3777 * reply-serial -> uint32 4
3778 * destination -> ':1.159'
3779 * sender -> ':1.146'
3780 * num-unix-fds -> uint32 1
3782 * UNIX File Descriptors:
3783 * fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
3786 * Returns: (not nullable): A string that should be freed with [func@GLib.free].
3791 g_dbus_message_print (GDBusMessage *message,
3799 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3801 str = g_string_new (NULL);
3803 s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->type);
3804 g_string_append_printf (str, "%*sType: %s\n", indent, "", s);
3806 s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->flags);
3807 g_string_append_printf (str, "%*sFlags: %s\n", indent, "", s);
3809 g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->major_protocol_version);
3810 g_string_append_printf (str, "%*sSerial: %d\n", indent, "", message->serial);
3812 g_string_append_printf (str, "%*sHeaders:\n", indent, "");
3813 keys = g_hash_table_get_keys (message->headers);
3814 keys = g_list_sort (keys, _sort_keys_func);
3817 for (l = keys; l != NULL; l = l->next)
3819 gint key = GPOINTER_TO_INT (l->data);
3823 value = g_hash_table_lookup (message->headers, l->data);
3824 g_assert (value != NULL);
3826 s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
3827 value_str = g_variant_print (value, TRUE);
3828 g_string_append_printf (str, "%*s %s -> %s\n", indent, "", s, value_str);
3835 g_string_append_printf (str, "%*s (none)\n", indent, "");
3838 g_string_append_printf (str, "%*sBody: ", indent, "");
3839 if (message->body != NULL)
3841 g_variant_print_string (message->body,
3847 g_string_append (str, "()");
3849 g_string_append (str, "\n");
3851 g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
3852 if (message->fd_list != NULL)
3858 fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3861 for (n = 0; n < num_fds; n++)
3864 struct stat statbuf;
3865 fs = g_string_new (NULL);
3866 if (fstat (fds[n], &statbuf) == 0)
3868 #ifndef MAJOR_MINOR_NOT_FOUND
3869 g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
3870 (gint) major (statbuf.st_dev), (gint) minor (statbuf.st_dev));
3872 g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
3873 (guint) statbuf.st_mode);
3874 g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3875 (guint64) statbuf.st_ino);
3876 g_string_append_printf (fs, "%s" "uid=%u", fs->len > 0 ? "," : "",
3877 (guint) statbuf.st_uid);
3878 g_string_append_printf (fs, "%s" "gid=%u", fs->len > 0 ? "," : "",
3879 (guint) statbuf.st_gid);
3880 #ifndef MAJOR_MINOR_NOT_FOUND
3881 g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
3882 (gint) major (statbuf.st_rdev), (gint) minor (statbuf.st_rdev));
3884 g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3885 (guint64) statbuf.st_size);
3886 g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3887 (guint64) statbuf.st_atime);
3888 g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3889 (guint64) statbuf.st_mtime);
3890 g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3891 (guint64) statbuf.st_ctime);
3896 g_string_append_printf (fs, "(fstat failed: %s)", g_strerror (errsv));
3898 g_string_append_printf (str, "%*s fd %d: %s\n", indent, "", fds[n], fs->str);
3899 g_string_free (fs, TRUE);
3904 g_string_append_printf (str, "%*s (empty)\n", indent, "");
3909 g_string_append_printf (str, "%*s (none)\n", indent, "");
3913 return g_string_free (str, FALSE);
3917 * g_dbus_message_get_locked:
3918 * @message: A #GDBusMessage.
3920 * Checks whether @message is locked. To monitor changes to this
3921 * value, conncet to the #GObject::notify signal to listen for changes
3922 * on the #GDBusMessage:locked property.
3924 * Returns: %TRUE if @message is locked, %FALSE otherwise.
3929 g_dbus_message_get_locked (GDBusMessage *message)
3931 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3932 return message->locked;
3936 * g_dbus_message_lock:
3937 * @message: A #GDBusMessage.
3939 * If @message is locked, does nothing. Otherwise locks the message.
3944 g_dbus_message_lock (GDBusMessage *message)
3946 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3948 if (message->locked)
3951 message->locked = TRUE;
3952 g_object_notify (G_OBJECT (message), "locked");
3959 * g_dbus_message_copy:
3960 * @message: A #GDBusMessage.
3961 * @error: Return location for error or %NULL.
3963 * Copies @message. The copy is a deep copy and the returned
3964 * #GDBusMessage is completely identical except that it is guaranteed
3967 * This operation can fail if e.g. @message contains file descriptors
3968 * and the per-process or system-wide open files limit is reached.
3970 * Returns: (transfer full): A new #GDBusMessage or %NULL if @error is set.
3971 * Free with g_object_unref().
3976 g_dbus_message_copy (GDBusMessage *message,
3980 GHashTableIter iter;
3981 gpointer header_key;
3982 GVariant *header_value;
3984 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3985 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
3987 ret = g_dbus_message_new ();
3988 ret->type = message->type;
3989 ret->flags = message->flags;
3990 ret->byte_order = message->byte_order;
3991 ret->major_protocol_version = message->major_protocol_version;
3992 ret->serial = message->serial;
3995 if (message->fd_list != NULL)
4001 ret->fd_list = g_unix_fd_list_new ();
4002 fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
4003 for (n = 0; n < num_fds; n++)
4005 if (g_unix_fd_list_append (ret->fd_list,
4009 g_object_unref (ret);
4017 /* see https://bugzilla.gnome.org/show_bug.cgi?id=624546#c8 for why it's fine
4018 * to just ref (as opposed to deep-copying) the GVariant instances
4020 ret->body = message->body != NULL ? g_variant_ref (message->body) : NULL;
4021 ret->arg0_cache = message->arg0_cache != NULL ? g_variant_ref (message->arg0_cache) : NULL;
4022 g_hash_table_iter_init (&iter, message->headers);
4023 while (g_hash_table_iter_next (&iter, &header_key, (gpointer) &header_value))
4024 g_hash_table_insert (ret->headers, header_key, g_variant_ref (header_value));
4033 g_dbus_message_init_header_iter (GDBusMessage *message,
4034 GHashTableIter *iter)
4036 g_hash_table_iter_init (iter, message->headers);