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 */
28 #include <sys/types.h>
32 #include <sys/mkdev.h>
33 #elif MAJOR_IN_SYSMACROS
34 #include <sys/sysmacros.h>
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"
49 #include "gdbusprivate.h"
53 #include "gunixfdlist.h"
58 typedef struct _GMemoryBuffer GMemoryBuffer;
65 GDataStreamByteOrder byte_order;
69 g_memory_buffer_is_byteswapped (GMemoryBuffer *mbuf)
71 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
72 return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
74 return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
79 g_memory_buffer_read_byte (GMemoryBuffer *mbuf)
81 if (mbuf->pos >= mbuf->valid_len)
83 return mbuf->data [mbuf->pos++];
87 g_memory_buffer_read_int16 (GMemoryBuffer *mbuf)
91 if (mbuf->pos > mbuf->valid_len - 2)
93 mbuf->pos = mbuf->valid_len;
97 memcpy (&v, mbuf->data + mbuf->pos, 2);
100 if (g_memory_buffer_is_byteswapped (mbuf))
101 v = GUINT16_SWAP_LE_BE (v);
107 g_memory_buffer_read_uint16 (GMemoryBuffer *mbuf)
111 if (mbuf->pos > mbuf->valid_len - 2)
113 mbuf->pos = mbuf->valid_len;
117 memcpy (&v, mbuf->data + mbuf->pos, 2);
120 if (g_memory_buffer_is_byteswapped (mbuf))
121 v = GUINT16_SWAP_LE_BE (v);
127 g_memory_buffer_read_int32 (GMemoryBuffer *mbuf)
131 if (mbuf->pos > mbuf->valid_len - 4)
133 mbuf->pos = mbuf->valid_len;
137 memcpy (&v, mbuf->data + mbuf->pos, 4);
140 if (g_memory_buffer_is_byteswapped (mbuf))
141 v = GUINT32_SWAP_LE_BE (v);
147 g_memory_buffer_read_uint32 (GMemoryBuffer *mbuf)
151 if (mbuf->pos > mbuf->valid_len - 4)
153 mbuf->pos = mbuf->valid_len;
157 memcpy (&v, mbuf->data + mbuf->pos, 4);
160 if (g_memory_buffer_is_byteswapped (mbuf))
161 v = GUINT32_SWAP_LE_BE (v);
167 g_memory_buffer_read_int64 (GMemoryBuffer *mbuf)
171 if (mbuf->pos > mbuf->valid_len - 8)
173 mbuf->pos = mbuf->valid_len;
177 memcpy (&v, mbuf->data + mbuf->pos, 8);
180 if (g_memory_buffer_is_byteswapped (mbuf))
181 v = GUINT64_SWAP_LE_BE (v);
187 g_memory_buffer_read_uint64 (GMemoryBuffer *mbuf)
191 if (mbuf->pos > mbuf->valid_len - 8)
193 mbuf->pos = mbuf->valid_len;
197 memcpy (&v, mbuf->data + mbuf->pos, 8);
200 if (g_memory_buffer_is_byteswapped (mbuf))
201 v = GUINT64_SWAP_LE_BE (v);
206 #define MIN_ARRAY_SIZE 128
209 g_nearest_pow (gsize num)
213 while (n < num && n > 0)
220 array_resize (GMemoryBuffer *mbuf,
226 if (mbuf->len == size)
230 data = g_realloc (mbuf->data, size);
233 memset ((guint8 *)data + len, 0, size - len);
238 if (mbuf->len < mbuf->valid_len)
239 mbuf->valid_len = mbuf->len;
243 g_memory_buffer_write (GMemoryBuffer *mbuf,
253 /* Check for address space overflow, but only if the buffer is resizable.
254 Otherwise we just do a short write and don't worry. */
255 if (mbuf->pos + count < mbuf->pos)
258 if (mbuf->pos + count > mbuf->len)
260 /* At least enought to fit the write, rounded up
261 for greater than linear growth.
262 TODO: This wastes a lot of memory at large buffer sizes.
263 Figure out a more rational allocation strategy. */
264 new_size = g_nearest_pow (mbuf->pos + count);
265 /* Check for overflow again. We have checked if
266 pos + count > G_MAXSIZE, but now check if g_nearest_pow () has
271 new_size = MAX (new_size, MIN_ARRAY_SIZE);
272 array_resize (mbuf, new_size);
275 dest = (guint8 *)mbuf->data + mbuf->pos;
276 memcpy (dest, buffer, count);
279 if (mbuf->pos > mbuf->valid_len)
280 mbuf->valid_len = mbuf->pos;
286 g_memory_buffer_put_byte (GMemoryBuffer *mbuf,
289 return g_memory_buffer_write (mbuf, &data, 1);
293 g_memory_buffer_put_int16 (GMemoryBuffer *mbuf,
296 switch (mbuf->byte_order)
298 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
299 data = GINT16_TO_BE (data);
301 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
302 data = GINT16_TO_LE (data);
304 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
309 return g_memory_buffer_write (mbuf, &data, 2);
313 g_memory_buffer_put_uint16 (GMemoryBuffer *mbuf,
316 switch (mbuf->byte_order)
318 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
319 data = GUINT16_TO_BE (data);
321 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
322 data = GUINT16_TO_LE (data);
324 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
329 return g_memory_buffer_write (mbuf, &data, 2);
333 g_memory_buffer_put_int32 (GMemoryBuffer *mbuf,
336 switch (mbuf->byte_order)
338 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
339 data = GINT32_TO_BE (data);
341 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
342 data = GINT32_TO_LE (data);
344 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
349 return g_memory_buffer_write (mbuf, &data, 4);
353 g_memory_buffer_put_uint32 (GMemoryBuffer *mbuf,
356 switch (mbuf->byte_order)
358 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
359 data = GUINT32_TO_BE (data);
361 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
362 data = GUINT32_TO_LE (data);
364 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
369 return g_memory_buffer_write (mbuf, &data, 4);
373 g_memory_buffer_put_int64 (GMemoryBuffer *mbuf,
376 switch (mbuf->byte_order)
378 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
379 data = GINT64_TO_BE (data);
381 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
382 data = GINT64_TO_LE (data);
384 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
389 return g_memory_buffer_write (mbuf, &data, 8);
393 g_memory_buffer_put_uint64 (GMemoryBuffer *mbuf,
396 switch (mbuf->byte_order)
398 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
399 data = GUINT64_TO_BE (data);
401 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
402 data = GUINT64_TO_LE (data);
404 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
409 return g_memory_buffer_write (mbuf, &data, 8);
413 g_memory_buffer_put_string (GMemoryBuffer *mbuf,
416 g_return_val_if_fail (str != NULL, FALSE);
418 return g_memory_buffer_write (mbuf, str, strlen (str));
423 * SECTION:gdbusmessage
424 * @short_description: D-Bus Message
425 * @include: gio/gio.h
427 * A type for representing D-Bus messages that can be sent or received
428 * on a #GDBusConnection.
431 typedef struct _GDBusMessageClass GDBusMessageClass;
436 * Class structure for #GDBusMessage.
440 struct _GDBusMessageClass
443 GObjectClass parent_class;
449 * The #GDBusMessage structure contains only private data and should
450 * only be accessed using the provided API.
457 GObject parent_instance;
459 GDBusMessageType type;
460 GDBusMessageFlags flags;
462 GDBusMessageByteOrder byte_order;
463 guchar major_protocol_version;
468 GUnixFDList *fd_list;
478 G_DEFINE_TYPE (GDBusMessage, g_dbus_message, G_TYPE_OBJECT);
481 g_dbus_message_finalize (GObject *object)
483 GDBusMessage *message = G_DBUS_MESSAGE (object);
485 if (message->headers != NULL)
486 g_hash_table_unref (message->headers);
487 if (message->body != NULL)
488 g_variant_unref (message->body);
490 if (message->fd_list != NULL)
491 g_object_unref (message->fd_list);
494 if (G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize != NULL)
495 G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize (object);
499 g_dbus_message_get_property (GObject *object,
504 GDBusMessage *message = G_DBUS_MESSAGE (object);
509 g_value_set_boolean (value, g_dbus_message_get_locked (message));
513 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
519 g_dbus_message_class_init (GDBusMessageClass *klass)
521 GObjectClass *gobject_class;
523 gobject_class = G_OBJECT_CLASS (klass);
524 gobject_class->finalize = g_dbus_message_finalize;
525 gobject_class->get_property = g_dbus_message_get_property;
528 * GDBusConnection:locked:
530 * A boolean specifying whether the message is locked.
534 g_object_class_install_property (gobject_class,
536 g_param_spec_boolean ("locked",
538 P_("Whether the message is locked"),
541 G_PARAM_STATIC_NAME |
542 G_PARAM_STATIC_BLURB |
543 G_PARAM_STATIC_NICK));
547 g_dbus_message_init (GDBusMessage *message)
549 /* Any D-Bus implementation is supposed to handle both Big and
550 * Little Endian encodings and the Endianness is part of the D-Bus
551 * message - we prefer to use Big Endian (since it's Network Byte
552 * Order and just easier to read for humans) but if the machine is
553 * Little Endian we use that for performance reasons.
555 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
556 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
558 /* this could also be G_PDP_ENDIAN */
559 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
561 message->headers = g_hash_table_new_full (g_direct_hash,
564 (GDestroyNotify) g_variant_unref);
568 * g_dbus_message_new:
570 * Creates a new empty #GDBusMessage.
572 * Returns: A #GDBusMessage. Free with g_object_unref().
577 g_dbus_message_new (void)
579 return g_object_new (G_TYPE_DBUS_MESSAGE, NULL);
583 * g_dbus_message_new_method_call:
584 * @name: (allow-none): A valid D-Bus name or %NULL.
585 * @path: A valid object path.
586 * @interface_: (allow-none): A valid D-Bus interface name or %NULL.
587 * @method: A valid method name.
589 * Creates a new #GDBusMessage for a method call.
591 * Returns: A #GDBusMessage. Free with g_object_unref().
596 g_dbus_message_new_method_call (const gchar *name,
598 const gchar *interface_,
601 GDBusMessage *message;
603 g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
604 g_return_val_if_fail (g_variant_is_object_path (path), NULL);
605 g_return_val_if_fail (g_dbus_is_member_name (method), NULL);
606 g_return_val_if_fail (interface_ == NULL || g_dbus_is_interface_name (interface_), NULL);
608 message = g_dbus_message_new ();
609 message->type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
612 g_dbus_message_set_destination (message, name);
613 g_dbus_message_set_path (message, path);
614 g_dbus_message_set_member (message, method);
615 if (interface_ != NULL)
616 g_dbus_message_set_interface (message, interface_);
622 * g_dbus_message_new_signal:
623 * @path: A valid object path.
624 * @interface_: A valid D-Bus interface name.
625 * @signal: A valid signal name.
627 * Creates a new #GDBusMessage for a signal emission.
629 * Returns: A #GDBusMessage. Free with g_object_unref().
634 g_dbus_message_new_signal (const gchar *path,
635 const gchar *interface_,
638 GDBusMessage *message;
640 g_return_val_if_fail (g_variant_is_object_path (path), NULL);
641 g_return_val_if_fail (g_dbus_is_member_name (signal), NULL);
642 g_return_val_if_fail (g_dbus_is_interface_name (interface_), NULL);
644 message = g_dbus_message_new ();
645 message->type = G_DBUS_MESSAGE_TYPE_SIGNAL;
646 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
648 g_dbus_message_set_path (message, path);
649 g_dbus_message_set_member (message, signal);
650 g_dbus_message_set_interface (message, interface_);
657 * g_dbus_message_new_method_reply:
658 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
659 * create a reply message to.
661 * Creates a new #GDBusMessage that is a reply to @method_call_message.
663 * Returns: (transfer full): #GDBusMessage. Free with g_object_unref().
668 g_dbus_message_new_method_reply (GDBusMessage *method_call_message)
670 GDBusMessage *message;
673 g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
674 g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
675 g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
677 message = g_dbus_message_new ();
678 message->type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
679 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
680 /* reply with same endianness */
681 message->byte_order = method_call_message->byte_order;
683 g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
684 sender = g_dbus_message_get_sender (method_call_message);
686 g_dbus_message_set_destination (message, sender);
692 * g_dbus_message_new_method_error:
693 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
694 * create a reply message to.
695 * @error_name: A valid D-Bus error name.
696 * @error_message_format: The D-Bus error message in a printf() format.
697 * @...: Arguments for @error_message_format.
699 * Creates a new #GDBusMessage that is an error reply to @method_call_message.
701 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
706 g_dbus_message_new_method_error (GDBusMessage *method_call_message,
707 const gchar *error_name,
708 const gchar *error_message_format,
714 va_start (var_args, error_message_format);
715 ret = g_dbus_message_new_method_error_valist (method_call_message,
717 error_message_format,
725 * g_dbus_message_new_method_error_literal:
726 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
727 * create a reply message to.
728 * @error_name: A valid D-Bus error name.
729 * @error_message: The D-Bus error message.
731 * Creates a new #GDBusMessage that is an error reply to @method_call_message.
733 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
738 g_dbus_message_new_method_error_literal (GDBusMessage *method_call_message,
739 const gchar *error_name,
740 const gchar *error_message)
742 GDBusMessage *message;
745 g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
746 g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
747 g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
748 g_return_val_if_fail (g_dbus_is_name (error_name), NULL);
749 g_return_val_if_fail (error_message != NULL, NULL);
751 message = g_dbus_message_new ();
752 message->type = G_DBUS_MESSAGE_TYPE_ERROR;
753 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
754 /* reply with same endianness */
755 message->byte_order = method_call_message->byte_order;
757 g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
758 g_dbus_message_set_error_name (message, error_name);
759 g_dbus_message_set_body (message, g_variant_new ("(s)", error_message));
761 sender = g_dbus_message_get_sender (method_call_message);
763 g_dbus_message_set_destination (message, sender);
769 * g_dbus_message_new_method_error_valist:
770 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
771 * create a reply message to.
772 * @error_name: A valid D-Bus error name.
773 * @error_message_format: The D-Bus error message in a printf() format.
774 * @var_args: Arguments for @error_message_format.
776 * Like g_dbus_message_new_method_error() but intended for language bindings.
778 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
784 g_dbus_message_new_method_error_valist (GDBusMessage *method_call_message,
785 const gchar *error_name,
786 const gchar *error_message_format,
790 gchar *error_message;
791 error_message = g_strdup_vprintf (error_message_format, var_args);
792 ret = g_dbus_message_new_method_error_literal (method_call_message,
795 g_free (error_message);
799 /* ---------------------------------------------------------------------------------------------------- */
802 * g_dbus_message_get_byte_order:
803 * @message: A #GDBusMessage.
805 * Gets the byte order of @message.
807 * Returns: The byte order.
809 GDBusMessageByteOrder
810 g_dbus_message_get_byte_order (GDBusMessage *message)
812 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), (GDBusMessageByteOrder) 0);
813 return message->byte_order;
817 * g_dbus_message_set_byte_order:
818 * @message: A #GDBusMessage.
819 * @byte_order: The byte order.
821 * Sets the byte order of @message.
824 g_dbus_message_set_byte_order (GDBusMessage *message,
825 GDBusMessageByteOrder byte_order)
827 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
831 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
835 message->byte_order = byte_order;
838 /* ---------------------------------------------------------------------------------------------------- */
840 /* TODO: need GI annotations to specify that any guchar value goes for the type */
843 * g_dbus_message_get_message_type:
844 * @message: A #GDBusMessage.
846 * Gets the type of @message.
848 * Returns: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
853 g_dbus_message_get_message_type (GDBusMessage *message)
855 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_TYPE_INVALID);
856 return message->type;
860 * g_dbus_message_set_message_type:
861 * @message: A #GDBusMessage.
862 * @type: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
864 * Sets @message to be of @type.
869 g_dbus_message_set_message_type (GDBusMessage *message,
870 GDBusMessageType type)
872 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
873 g_return_if_fail (type >=0 && type < 256);
877 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
881 message->type = type;
884 /* ---------------------------------------------------------------------------------------------------- */
886 /* TODO: need GI annotations to specify that any guchar value goes for flags */
889 * g_dbus_message_get_flags:
890 * @message: A #GDBusMessage.
892 * Gets the flags for @message.
894 * Returns: Flags that are set (typically values from the #GDBusMessageFlags enumeration bitwise ORed together).
899 g_dbus_message_get_flags (GDBusMessage *message)
901 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_FLAGS_NONE);
902 return message->flags;
906 * g_dbus_message_set_flags:
907 * @message: A #GDBusMessage.
908 * @flags: Flags for @message that are set (typically values from the #GDBusMessageFlags
909 * enumeration bitwise ORed together).
911 * Sets the flags to set on @message.
916 g_dbus_message_set_flags (GDBusMessage *message,
917 GDBusMessageFlags flags)
919 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
920 g_return_if_fail (flags >=0 && flags < 256);
924 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
928 message->flags = flags;
931 /* ---------------------------------------------------------------------------------------------------- */
934 * g_dbus_message_get_serial:
935 * @message: A #GDBusMessage.
937 * Gets the serial for @message.
939 * Returns: A #guint32.
944 g_dbus_message_get_serial (GDBusMessage *message)
946 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
947 return message->serial;
951 * g_dbus_message_set_serial:
952 * @message: A #GDBusMessage.
953 * @serial: A #guint32.
955 * Sets the serial for @message.
960 g_dbus_message_set_serial (GDBusMessage *message,
963 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
967 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
971 message->serial = serial;
974 /* ---------------------------------------------------------------------------------------------------- */
977 * _g_dbus_message_get_protocol_ver:
978 * To remove - more info [1]
979 * [1] https://bugzilla.gnome.org/show_bug.cgi?id=721861
982 _g_dbus_message_get_protocol_ver (GDBusMessage *message)
984 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
985 return message->major_protocol_version;
989 * _g_dbus_message_set_protocol_ver:
990 * To remove - more info [1]
991 * [1] https://bugzilla.gnome.org/show_bug.cgi?id=721861
994 _g_dbus_message_set_protocol_ver (GDBusMessage *message,
995 guint32 protocol_ver)
997 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1001 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1005 message->major_protocol_version = protocol_ver;
1008 /* TODO: need GI annotations to specify that any guchar value goes for header_field */
1011 * g_dbus_message_get_header:
1012 * @message: A #GDBusMessage.
1013 * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1015 * Gets a header field on @message.
1017 * Returns: A #GVariant with the value if the header was found, %NULL
1018 * otherwise. Do not free, it is owned by @message.
1023 g_dbus_message_get_header (GDBusMessage *message,
1024 GDBusMessageHeaderField header_field)
1026 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1027 g_return_val_if_fail (header_field >=0 && header_field < 256, NULL);
1028 return g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
1032 * g_dbus_message_set_header:
1033 * @message: A #GDBusMessage.
1034 * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1035 * @value: (allow-none): A #GVariant to set the header field or %NULL to clear the header field.
1037 * Sets a header field on @message.
1039 * If @value is floating, @message assumes ownership of @value.
1044 g_dbus_message_set_header (GDBusMessage *message,
1045 GDBusMessageHeaderField header_field,
1048 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1049 g_return_if_fail (header_field >=0 && header_field < 256);
1051 if (message->locked)
1053 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1059 g_hash_table_remove (message->headers, GUINT_TO_POINTER (header_field));
1063 g_hash_table_insert (message->headers, GUINT_TO_POINTER (header_field), g_variant_ref_sink (value));
1068 * g_dbus_message_get_header_fields:
1069 * @message: A #GDBusMessage.
1071 * Gets an array of all header fields on @message that are set.
1073 * Returns: (array zero-terminated=1): An array of header fields
1074 * terminated by %G_DBUS_MESSAGE_HEADER_FIELD_INVALID. Each element
1075 * is a #guchar. Free with g_free().
1080 g_dbus_message_get_header_fields (GDBusMessage *message)
1088 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1090 keys = g_hash_table_get_keys (message->headers);
1091 num_keys = g_list_length (keys);
1092 ret = g_new (guchar, num_keys + 1);
1093 for (l = keys, n = 0; l != NULL; l = l->next, n++)
1094 ret[n] = GPOINTER_TO_UINT (l->data);
1095 g_assert (n == num_keys);
1096 ret[n] = G_DBUS_MESSAGE_HEADER_FIELD_INVALID;
1102 /* ---------------------------------------------------------------------------------------------------- */
1105 * g_dbus_message_get_body:
1106 * @message: A #GDBusMessage.
1108 * Gets the body of a message.
1110 * Returns: (transfer none): A #GVariant or %NULL if the body is
1111 * empty. Do not free, it is owned by @message.
1116 g_dbus_message_get_body (GDBusMessage *message)
1118 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1119 return message->body;
1123 * g_dbus_message_set_body:
1124 * @message: A #GDBusMessage.
1125 * @body: Either %NULL or a #GVariant that is a tuple.
1127 * Sets the body @message. As a side-effect the
1128 * %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field is set to the
1129 * type string of @body (or cleared if @body is %NULL).
1131 * If @body is floating, @message assumes ownership of @body.
1136 g_dbus_message_set_body (GDBusMessage *message,
1139 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1140 g_return_if_fail ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE));
1142 if (message->locked)
1144 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1148 if (message->body != NULL)
1149 g_variant_unref (message->body);
1152 message->body = NULL;
1153 g_dbus_message_set_signature (message, NULL);
1157 const gchar *type_string;
1158 gsize type_string_len;
1161 message->body = g_variant_ref_sink (body);
1163 type_string = g_variant_get_type_string (body);
1164 type_string_len = strlen (type_string);
1165 g_assert (type_string_len >= 2);
1166 signature = g_strndup (type_string + 1, type_string_len - 2);
1167 g_dbus_message_set_signature (message, signature);
1172 /* ---------------------------------------------------------------------------------------------------- */
1176 * g_dbus_message_get_unix_fd_list:
1177 * @message: A #GDBusMessage.
1179 * Gets the UNIX file descriptors associated with @message, if any.
1181 * This method is only available on UNIX.
1183 * Returns: (transfer none):A #GUnixFDList or %NULL if no file descriptors are
1184 * associated. Do not free, this object is owned by @message.
1189 g_dbus_message_get_unix_fd_list (GDBusMessage *message)
1191 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1192 return message->fd_list;
1196 * g_dbus_message_set_unix_fd_list:
1197 * @message: A #GDBusMessage.
1198 * @fd_list: (allow-none): A #GUnixFDList or %NULL.
1200 * Sets the UNIX file descriptors associated with @message. As a
1201 * side-effect the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header
1202 * field is set to the number of fds in @fd_list (or cleared if
1203 * @fd_list is %NULL).
1205 * This method is only available on UNIX.
1210 g_dbus_message_set_unix_fd_list (GDBusMessage *message,
1211 GUnixFDList *fd_list)
1213 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1214 g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
1216 if (message->locked)
1218 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1222 if (message->fd_list != NULL)
1223 g_object_unref (message->fd_list);
1224 if (fd_list != NULL)
1226 message->fd_list = g_object_ref (fd_list);
1227 g_dbus_message_set_num_unix_fds (message, g_unix_fd_list_get_length (fd_list));
1231 message->fd_list = NULL;
1232 g_dbus_message_set_num_unix_fds (message, 0);
1237 /* ---------------------------------------------------------------------------------------------------- */
1240 get_type_fixed_size (const GVariantType *type)
1242 /* NB: we do not treat 'b' as fixed-size here because GVariant and
1243 * D-Bus disagree about the size.
1245 switch (*g_variant_type_peek_string (type))
1251 case 'i': case 'u': case 'h':
1253 case 'x': case 't': case 'd':
1261 validate_headers (GDBusMessage *message,
1266 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1267 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1271 switch (message->type)
1273 case G_DBUS_MESSAGE_TYPE_INVALID:
1274 g_set_error_literal (error,
1276 G_IO_ERROR_INVALID_ARGUMENT,
1277 _("type is INVALID"));
1281 case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
1282 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1283 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1285 g_set_error_literal (error,
1287 G_IO_ERROR_INVALID_ARGUMENT,
1288 _("METHOD_CALL message: PATH or MEMBER header field is missing"));
1293 case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
1294 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1296 g_set_error_literal (error,
1298 G_IO_ERROR_INVALID_ARGUMENT,
1299 _("METHOD_RETURN message: REPLY_SERIAL header field is missing"));
1304 case G_DBUS_MESSAGE_TYPE_ERROR:
1305 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME) == NULL ||
1306 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1308 g_set_error_literal (error,
1310 G_IO_ERROR_INVALID_ARGUMENT,
1311 _("ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing"));
1316 case G_DBUS_MESSAGE_TYPE_SIGNAL:
1317 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1318 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE) == NULL ||
1319 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1321 g_set_error_literal (error,
1323 G_IO_ERROR_INVALID_ARGUMENT,
1324 _("SIGNAL message: PATH, INTERFACE or MEMBER header field is missing"));
1327 if (g_strcmp0 (g_dbus_message_get_path (message), "/org/freedesktop/DBus/Local") == 0)
1329 g_set_error_literal (error,
1331 G_IO_ERROR_INVALID_ARGUMENT,
1332 _("SIGNAL message: The PATH header field is using the reserved value /org/freedesktop/DBus/Local"));
1335 if (g_strcmp0 (g_dbus_message_get_interface (message), "org.freedesktop.DBus.Local") == 0)
1337 g_set_error_literal (error,
1339 G_IO_ERROR_INVALID_ARGUMENT,
1340 _("SIGNAL message: The INTERFACE header field is using the reserved value org.freedesktop.DBus.Local"));
1346 /* hitherto unknown type - nothing to check */
1353 g_assert (ret || (error == NULL || *error != NULL));
1357 /* ---------------------------------------------------------------------------------------------------- */
1360 ensure_input_padding (GMemoryBuffer *buf,
1364 gsize wanted_offset;
1367 wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1368 buf->pos = wanted_offset;
1372 static const gchar *
1373 read_string (GMemoryBuffer *mbuf,
1378 const gchar *end_valid;
1380 if G_UNLIKELY (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1382 mbuf->pos = mbuf->valid_len;
1383 /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1386 G_IO_ERROR_INVALID_ARGUMENT,
1387 g_dngettext (GETTEXT_PACKAGE,
1388 "Wanted to read %lu byte but only got %lu",
1389 "Wanted to read %lu bytes but only got %lu",
1392 (gulong)(mbuf->valid_len - mbuf->pos));
1396 if G_UNLIKELY (mbuf->data[mbuf->pos + len] != '\0')
1398 str = g_strndup (mbuf->data + mbuf->pos, len);
1401 G_IO_ERROR_INVALID_ARGUMENT,
1402 _("Expected NUL byte after the string '%s' but found byte %d"),
1403 str, mbuf->data[mbuf->pos + len]);
1405 mbuf->pos += len + 1;
1409 str = mbuf->data + mbuf->pos;
1410 mbuf->pos += len + 1;
1412 if G_UNLIKELY (!g_utf8_validate (str, -1, &end_valid))
1416 offset = (gint) (end_valid - str);
1417 valid_str = g_strndup (str, offset);
1420 G_IO_ERROR_INVALID_ARGUMENT,
1421 _("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
1422 "The valid UTF-8 string up until that point was '%s'"),
1433 static gconstpointer
1434 read_bytes (GMemoryBuffer *mbuf,
1438 gconstpointer result;
1440 if G_UNLIKELY (mbuf->pos + len > mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1442 mbuf->pos = mbuf->valid_len;
1443 /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1446 G_IO_ERROR_INVALID_ARGUMENT,
1447 g_dngettext (GETTEXT_PACKAGE,
1448 "Wanted to read %lu byte but only got %lu",
1449 "Wanted to read %lu bytes but only got %lu",
1452 (gulong)(mbuf->valid_len - mbuf->pos));
1456 result = mbuf->data + mbuf->pos;
1462 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
1464 /* returns a non-floating GVariant! */
1466 parse_value_from_blob (GMemoryBuffer *buf,
1467 const GVariantType *type,
1468 gboolean just_align,
1473 GError *local_error;
1475 const gchar *type_string;
1477 type_string = g_variant_type_peek_string (type);
1479 #ifdef DEBUG_SERIALIZER
1482 s = g_variant_type_dup_string (type);
1483 g_print ("%*s%s type %s from offset 0x%04x",
1485 just_align ? "Aligning" : "Reading",
1487 (gint) g_seekable_tell (G_SEEKABLE (buf)));
1490 #endif /* DEBUG_SERIALIZER */
1496 switch (type_string[0])
1498 case 'b': /* G_VARIANT_TYPE_BOOLEAN */
1499 ensure_input_padding (buf, 4);
1503 v = g_memory_buffer_read_uint32 (buf);
1504 ret = g_variant_new_boolean (v);
1508 case 'y': /* G_VARIANT_TYPE_BYTE */
1512 v = g_memory_buffer_read_byte (buf);
1513 ret = g_variant_new_byte (v);
1517 case 'n': /* G_VARIANT_TYPE_INT16 */
1518 ensure_input_padding (buf, 2);
1522 v = g_memory_buffer_read_int16 (buf);
1523 ret = g_variant_new_int16 (v);
1527 case 'q': /* G_VARIANT_TYPE_UINT16 */
1528 ensure_input_padding (buf, 2);
1532 v = g_memory_buffer_read_uint16 (buf);
1533 ret = g_variant_new_uint16 (v);
1537 case 'i': /* G_VARIANT_TYPE_INT32 */
1538 ensure_input_padding (buf, 4);
1542 v = g_memory_buffer_read_int32 (buf);
1543 ret = g_variant_new_int32 (v);
1547 case 'u': /* G_VARIANT_TYPE_UINT32 */
1548 ensure_input_padding (buf, 4);
1552 v = g_memory_buffer_read_uint32 (buf);
1553 ret = g_variant_new_uint32 (v);
1557 case 'x': /* G_VARIANT_TYPE_INT64 */
1558 ensure_input_padding (buf, 8);
1562 v = g_memory_buffer_read_int64 (buf);
1563 ret = g_variant_new_int64 (v);
1567 case 't': /* G_VARIANT_TYPE_UINT64 */
1568 ensure_input_padding (buf, 8);
1572 v = g_memory_buffer_read_uint64 (buf);
1573 ret = g_variant_new_uint64 (v);
1577 case 'd': /* G_VARIANT_TYPE_DOUBLE */
1578 ensure_input_padding (buf, 8);
1585 G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
1586 u.v_uint64 = g_memory_buffer_read_uint64 (buf);
1587 ret = g_variant_new_double (u.v_double);
1591 case 's': /* G_VARIANT_TYPE_STRING */
1592 ensure_input_padding (buf, 4);
1597 len = g_memory_buffer_read_uint32 (buf);
1598 v = read_string (buf, (gsize) len, &local_error);
1601 ret = g_variant_new_string (v);
1605 case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
1606 ensure_input_padding (buf, 4);
1611 len = g_memory_buffer_read_uint32 (buf);
1612 v = read_string (buf, (gsize) len, &local_error);
1615 if (!g_variant_is_object_path (v))
1617 g_set_error (&local_error,
1619 G_IO_ERROR_INVALID_ARGUMENT,
1620 _("Parsed value '%s' is not a valid D-Bus object path"),
1624 ret = g_variant_new_object_path (v);
1628 case 'g': /* G_VARIANT_TYPE_SIGNATURE */
1633 len = g_memory_buffer_read_byte (buf);
1634 v = read_string (buf, (gsize) len, &local_error);
1637 if (!g_variant_is_signature (v))
1639 g_set_error (&local_error,
1641 G_IO_ERROR_INVALID_ARGUMENT,
1642 _("Parsed value '%s' is not a valid D-Bus signature"),
1646 ret = g_variant_new_signature (v);
1650 case 'h': /* G_VARIANT_TYPE_HANDLE */
1651 ensure_input_padding (buf, 4);
1655 v = g_memory_buffer_read_int32 (buf);
1656 ret = g_variant_new_handle (v);
1660 case 'a': /* G_VARIANT_TYPE_ARRAY */
1661 ensure_input_padding (buf, 4);
1663 /* If we are only aligning for this array type, it is the child type of
1664 * another array, which is empty. So, we do not need to add padding for
1665 * this nonexistent array's elements: we only need to align for this
1666 * array itself (4 bytes). See
1667 * <https://bugzilla.gnome.org/show_bug.cgi?id=673612>.
1672 const GVariantType *element_type;
1675 array_len = g_memory_buffer_read_uint32 (buf);
1678 #ifdef DEBUG_SERIALIZER
1679 g_print (": array spans 0x%04x bytes\n", array_len);
1680 #endif /* DEBUG_SERIALIZER */
1682 if (array_len > (2<<26))
1684 /* G_GUINT32_FORMAT doesn't work with gettext, so use u */
1685 g_set_error (&local_error,
1687 G_IO_ERROR_INVALID_ARGUMENT,
1688 g_dngettext (GETTEXT_PACKAGE,
1689 "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB).",
1690 "Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB).",
1696 element_type = g_variant_type_element (type);
1697 fixed_size = get_type_fixed_size (element_type);
1699 /* Fast-path the cases like 'ay', etc. */
1700 if (fixed_size != 0)
1702 gconstpointer array_data;
1704 if (array_len % fixed_size != 0)
1706 g_set_error (&local_error,
1708 G_IO_ERROR_INVALID_ARGUMENT,
1709 _("Encountered array of type 'a%c', expected to have a length a multiple "
1710 "of %u bytes, but found to be %u bytes in length"),
1711 g_variant_type_peek_string (element_type)[0], fixed_size, array_len);
1715 ensure_input_padding (buf, fixed_size);
1716 array_data = read_bytes (buf, array_len, &local_error);
1717 if (array_data == NULL)
1720 ret = g_variant_new_fixed_array (element_type, array_data, array_len / fixed_size, fixed_size);
1722 if (g_memory_buffer_is_byteswapped (buf))
1724 GVariant *tmp = g_variant_ref_sink (ret);
1725 ret = g_variant_byteswap (tmp);
1726 g_variant_unref (tmp);
1731 GVariantBuilder builder;
1735 g_variant_builder_init (&builder, type);
1740 item = parse_value_from_blob (buf,
1745 g_assert (item == NULL);
1750 target = offset + array_len;
1751 while (offset < target)
1754 item = parse_value_from_blob (buf,
1761 g_variant_builder_clear (&builder);
1764 g_variant_builder_add_value (&builder, item);
1765 g_variant_unref (item);
1770 ret = g_variant_builder_end (&builder);
1776 if (g_variant_type_is_dict_entry (type))
1778 const GVariantType *key_type;
1779 const GVariantType *value_type;
1783 ensure_input_padding (buf, 8);
1786 #ifdef DEBUG_SERIALIZER
1788 #endif /* DEBUG_SERIALIZER */
1792 key_type = g_variant_type_key (type);
1793 key = parse_value_from_blob (buf,
1800 value_type = g_variant_type_value (type);
1801 value = parse_value_from_blob (buf,
1808 g_variant_unref (key);
1811 ret = g_variant_new_dict_entry (key, value);
1812 g_variant_unref (key);
1813 g_variant_unref (value);
1816 else if (g_variant_type_is_tuple (type))
1818 ensure_input_padding (buf, 8);
1821 #ifdef DEBUG_SERIALIZER
1823 #endif /* DEBUG_SERIALIZER */
1827 const GVariantType *element_type;
1828 GVariantBuilder builder;
1830 g_variant_builder_init (&builder, type);
1831 element_type = g_variant_type_first (type);
1832 while (element_type != NULL)
1835 item = parse_value_from_blob (buf,
1842 g_variant_builder_clear (&builder);
1845 g_variant_builder_add_value (&builder, item);
1846 g_variant_unref (item);
1848 element_type = g_variant_type_next (element_type);
1850 ret = g_variant_builder_end (&builder);
1853 else if (g_variant_type_is_variant (type))
1856 #ifdef DEBUG_SERIALIZER
1858 #endif /* DEBUG_SERIALIZER */
1864 GVariantType *variant_type;
1867 siglen = g_memory_buffer_read_byte (buf);
1868 sig = read_string (buf, (gsize) siglen, &local_error);
1871 if (!g_variant_is_signature (sig))
1873 g_set_error (&local_error,
1875 G_IO_ERROR_INVALID_ARGUMENT,
1876 _("Parsed value '%s' for variant is not a valid D-Bus signature"),
1880 variant_type = g_variant_type_new (sig);
1881 value = parse_value_from_blob (buf,
1886 g_variant_type_free (variant_type);
1889 ret = g_variant_new_variant (value);
1890 g_variant_unref (value);
1896 s = g_variant_type_dup_string (type);
1897 g_set_error (&local_error,
1899 G_IO_ERROR_INVALID_ARGUMENT,
1900 _("Error deserializing GVariant with type string '%s' from the D-Bus wire format"),
1908 g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
1910 #ifdef DEBUG_SERIALIZER
1916 if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1918 s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
1922 s = g_variant_print (ret, FALSE);
1924 g_print (": %s\n", s);
1929 is_leaf = is_leaf; /* To avoid -Wunused-but-set-variable */
1930 #endif /* DEBUG_SERIALIZER */
1932 /* sink the reference, if floating */
1934 g_variant_take_ref (ret);
1938 #ifdef DEBUG_SERIALIZER
1940 "%*sFAILURE: %s (%s, %d)\n",
1942 local_error->message,
1943 g_quark_to_string (local_error->domain),
1945 #endif /* DEBUG_SERIALIZER */
1946 g_propagate_error (error, local_error);
1950 /* ---------------------------------------------------------------------------------------------------- */
1952 /* message_header must be at least 16 bytes */
1955 * g_dbus_message_bytes_needed:
1956 * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1957 * @blob_len: The length of @blob (must be at least 16).
1958 * @error: Return location for error or %NULL.
1960 * Utility function to calculate how many bytes are needed to
1961 * completely deserialize the D-Bus message stored at @blob.
1963 * Returns: Number of bytes needed or -1 if @error is set (e.g. if
1964 * @blob contains invalid data or not enough data is available to
1965 * determine the size).
1970 g_dbus_message_bytes_needed (guchar *blob,
1978 g_return_val_if_fail (blob != NULL, -1);
1979 g_return_val_if_fail (error == NULL || *error == NULL, -1);
1980 g_return_val_if_fail (blob_len >= 16, -1);
1984 /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1985 ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
1986 /* round up so it's a multiple of 8 */
1987 ret = 8 * ((ret + 7)/8);
1988 /* finally add the body size */
1989 ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
1991 else if (blob[0] == 'B')
1993 /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1994 ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
1995 /* round up so it's a multiple of 8 */
1996 ret = 8 * ((ret + 7)/8);
1997 /* finally add the body size */
1998 ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
2004 G_IO_ERROR_INVALID_ARGUMENT,
2005 "Unable to determine message blob length - given blob is malformed");
2012 G_IO_ERROR_INVALID_ARGUMENT,
2013 "Blob indicates that message exceeds maximum message length (128MiB)");
2020 /* ---------------------------------------------------------------------------------------------------- */
2023 * g_dbus_message_new_from_blob:
2024 * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
2025 * @blob_len: The length of @blob.
2026 * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2027 * @error: Return location for error or %NULL.
2029 * Creates a new #GDBusMessage from the data stored at @blob. The byte
2030 * order that the message was in can be retrieved using
2031 * g_dbus_message_get_byte_order().
2033 * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
2039 g_dbus_message_new_from_blob (guchar *blob,
2041 GDBusCapabilityFlags capabilities,
2046 GDBusMessage *message;
2048 guchar major_protocol_version;
2049 guint32 message_body_len;
2053 GVariant *signature;
2055 /* TODO: check against @capabilities */
2059 g_return_val_if_fail (blob != NULL, NULL);
2060 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2061 g_return_val_if_fail (blob_len >= 12, NULL);
2063 message = g_dbus_message_new ();
2065 memset (&mbuf, 0, sizeof (mbuf));
2066 mbuf.data = (gchar *)blob;
2067 mbuf.len = mbuf.valid_len = blob_len;
2069 endianness = g_memory_buffer_read_byte (&mbuf);
2073 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2074 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
2077 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2078 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
2083 G_IO_ERROR_INVALID_ARGUMENT,
2084 _("Invalid endianness value. Expected 0x6c ('l') or 0x42 ('B') but found value 0x%02x"),
2089 message->type = g_memory_buffer_read_byte (&mbuf);
2090 message->flags = g_memory_buffer_read_byte (&mbuf);
2091 major_protocol_version = g_memory_buffer_read_byte (&mbuf);
2092 if (major_protocol_version != 1)
2096 G_IO_ERROR_INVALID_ARGUMENT,
2097 _("Invalid major protocol version. Expected 1 but found %d"),
2098 major_protocol_version);
2101 message_body_len = g_memory_buffer_read_uint32 (&mbuf);
2102 message->serial = g_memory_buffer_read_uint32 (&mbuf);
2104 #ifdef DEBUG_SERIALIZER
2105 g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2108 s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
2109 g_print ("%s\n", s);
2112 #endif /* DEBUG_SERIALIZER */
2114 #ifdef DEBUG_SERIALIZER
2115 g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2116 #endif /* DEBUG_SERIALIZER */
2117 headers = parse_value_from_blob (&mbuf,
2118 G_VARIANT_TYPE ("a{yv}"),
2122 if (headers == NULL)
2124 g_variant_iter_init (&iter, headers);
2125 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2127 guchar header_field;
2129 g_variant_get (item,
2133 g_dbus_message_set_header (message, header_field, value);
2134 g_variant_unref (value);
2135 g_variant_unref (item);
2137 g_variant_unref (headers);
2139 signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2140 if (signature != NULL)
2142 const gchar *signature_str;
2143 gsize signature_str_len;
2145 signature_str = g_variant_get_string (signature, &signature_str_len);
2147 /* signature but no body */
2148 if (message_body_len == 0 && signature_str_len > 0)
2152 G_IO_ERROR_INVALID_ARGUMENT,
2153 _("Signature header with signature '%s' found but message body is empty"),
2157 else if (signature_str_len > 0)
2159 GVariantType *variant_type;
2160 gchar *tupled_signature_str;
2162 if (!g_variant_is_signature (signature_str))
2166 G_IO_ERROR_INVALID_ARGUMENT,
2167 _("Parsed value '%s' is not a valid D-Bus signature (for body)"),
2171 tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2172 variant_type = g_variant_type_new (tupled_signature_str);
2173 g_free (tupled_signature_str);
2174 #ifdef DEBUG_SERIALIZER
2175 g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2176 #endif /* DEBUG_SERIALIZER */
2177 message->body = parse_value_from_blob (&mbuf,
2182 g_variant_type_free (variant_type);
2183 if (message->body == NULL)
2189 /* no signature, this is only OK if the body is empty */
2190 if (message_body_len != 0)
2192 /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
2195 G_IO_ERROR_INVALID_ARGUMENT,
2196 g_dngettext (GETTEXT_PACKAGE,
2197 "No signature header in message but the message body is %u byte",
2198 "No signature header in message but the message body is %u bytes",
2205 if (!validate_headers (message, error))
2207 g_prefix_error (error, _("Cannot deserialize message: "));
2220 if (message != NULL)
2221 g_object_unref (message);
2226 /* ---------------------------------------------------------------------------------------------------- */
2229 * _g_dbus_message_new_from_kdbus_items:
2231 * Single kdbus message may contain zero, one or more items
2232 * (PAYLOAD_VEC or PAYLOAD_MEMFD), so we need this function
2233 * (only for kdbus transport purposes) to parse them to GDBusMessage.
2234 * kdbus_msg_items list contain list of pointer + data pair for each received item.
2236 * TODO: Add support for two and more items
2240 _g_dbus_message_new_from_kdbus_items (GSList *kdbus_msg_items,
2245 GDBusMessage *message;
2247 guchar major_protocol_version;
2248 guint32 message_body_len;
2249 guint32 message_headers_len;
2253 GVariant *signature;
2257 g_return_val_if_fail (kdbus_msg_items != NULL, NULL);
2258 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2260 message = g_dbus_message_new ();
2261 memset (&mbuf, 0, sizeof (mbuf));
2265 * message header in its entirety must be contained in a first single item
2267 mbuf.data = ((msg_part*)kdbus_msg_items->data)->data;
2268 mbuf.len = mbuf.valid_len = ((msg_part*)kdbus_msg_items->data)->size;
2270 endianness = g_memory_buffer_read_byte (&mbuf);
2274 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2275 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
2278 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2279 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
2284 G_IO_ERROR_INVALID_ARGUMENT,
2285 _("Invalid endianness value. Expected 0x6c ('l') or 0x42 ('B') but found value 0x%02x"),
2290 message->type = g_memory_buffer_read_byte (&mbuf);
2291 message->flags = g_memory_buffer_read_byte (&mbuf);
2292 major_protocol_version = g_memory_buffer_read_byte (&mbuf);
2294 if (major_protocol_version != 2)
2298 G_IO_ERROR_INVALID_ARGUMENT,
2299 _("Invalid major protocol version. Expected 2 but found %d"),
2300 major_protocol_version);
2304 message_body_len = g_memory_buffer_read_uint32 (&mbuf);
2305 message->serial = g_memory_buffer_read_uint32 (&mbuf);
2307 message_headers_len = g_memory_buffer_read_uint32 (&mbuf);
2308 headers = g_variant_new_from_data (G_VARIANT_TYPE ("a{yv}"),
2309 mbuf.data + mbuf.pos,
2310 message_headers_len,
2314 mbuf.pos += message_headers_len;
2316 if (headers == NULL)
2318 g_variant_iter_init (&iter, headers);
2319 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2321 guchar header_field;
2323 g_variant_get (item,
2327 g_dbus_message_set_header (message, header_field, value);
2328 g_variant_unref (value);
2329 g_variant_unref (item);
2331 g_variant_unref (headers);
2333 signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2334 if (signature != NULL)
2336 const gchar *signature_str;
2337 gsize signature_str_len;
2339 signature_str = g_variant_get_string (signature, &signature_str_len);
2341 if (signature_str_len > 0)
2343 GVariantType *variant_type;
2344 gchar *tupled_signature_str;
2349 if (!g_variant_is_signature (signature_str))
2353 G_IO_ERROR_INVALID_ARGUMENT,
2354 _("Parsed value '%s' is not a valid D-Bus signature (for body)"),
2358 tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2359 variant_type = g_variant_type_new (tupled_signature_str);
2360 g_free (tupled_signature_str);
2366 if (g_slist_length(kdbus_msg_items) == 1)
2368 /* if kdbus_msg_items has only one element, head and body are
2369 contained in a single PAYLOAD_VEC item */
2370 ensure_input_padding (&mbuf,8);
2371 data = mbuf.data + mbuf.pos;
2372 size = message_body_len;
2374 else if (g_slist_length(kdbus_msg_items) > 1)
2376 /* message consists two or more items
2377 TODO: Add support for three and more items */
2378 data = ((msg_part*)g_slist_next(kdbus_msg_items)->data)->data;
2379 size = ((msg_part*)g_slist_next(kdbus_msg_items)->data)->size;
2385 G_IO_ERROR_INVALID_ARGUMENT,
2386 _("[KDBUS] Received message is not valid"));
2390 message->body = g_variant_new_from_data (variant_type,
2397 g_variant_type_free (variant_type);
2398 if (message->body == NULL)
2404 /* no signature, this is only OK if the body is empty */
2405 if (message_body_len != 0)
2407 /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
2410 G_IO_ERROR_INVALID_ARGUMENT,
2411 g_dngettext (GETTEXT_PACKAGE,
2412 "No signature header in message but the message body is %u byte",
2413 "No signature header in message but the message body is %u bytes",
2420 if (!validate_headers (message, error))
2422 g_prefix_error (error, _("Cannot deserialize message: "));
2435 if (message != NULL)
2436 g_object_unref (message);
2442 ensure_output_padding (GMemoryBuffer *mbuf,
2446 gsize wanted_offset;
2447 gsize padding_needed;
2451 wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
2452 padding_needed = wanted_offset - offset;
2454 for (n = 0; n < padding_needed; n++)
2455 g_memory_buffer_put_byte (mbuf, '\0');
2457 return padding_needed;
2460 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
2462 append_value_to_blob (GVariant *value,
2463 const GVariantType *type,
2464 GMemoryBuffer *mbuf,
2465 gsize *out_padding_added,
2468 gsize padding_added;
2469 const gchar *type_string;
2471 type_string = g_variant_type_peek_string (type);
2475 switch (type_string[0])
2477 case 'b': /* G_VARIANT_TYPE_BOOLEAN */
2478 padding_added = ensure_output_padding (mbuf, 4);
2481 gboolean v = g_variant_get_boolean (value);
2482 g_memory_buffer_put_uint32 (mbuf, v);
2486 case 'y': /* G_VARIANT_TYPE_BYTE */
2489 guint8 v = g_variant_get_byte (value);
2490 g_memory_buffer_put_byte (mbuf, v);
2494 case 'n': /* G_VARIANT_TYPE_INT16 */
2495 padding_added = ensure_output_padding (mbuf, 2);
2498 gint16 v = g_variant_get_int16 (value);
2499 g_memory_buffer_put_int16 (mbuf, v);
2503 case 'q': /* G_VARIANT_TYPE_UINT16 */
2504 padding_added = ensure_output_padding (mbuf, 2);
2507 guint16 v = g_variant_get_uint16 (value);
2508 g_memory_buffer_put_uint16 (mbuf, v);
2512 case 'i': /* G_VARIANT_TYPE_INT32 */
2513 padding_added = ensure_output_padding (mbuf, 4);
2516 gint32 v = g_variant_get_int32 (value);
2517 g_memory_buffer_put_int32 (mbuf, v);
2521 case 'u': /* G_VARIANT_TYPE_UINT32 */
2522 padding_added = ensure_output_padding (mbuf, 4);
2525 guint32 v = g_variant_get_uint32 (value);
2526 g_memory_buffer_put_uint32 (mbuf, v);
2530 case 'x': /* G_VARIANT_TYPE_INT64 */
2531 padding_added = ensure_output_padding (mbuf, 8);
2534 gint64 v = g_variant_get_int64 (value);
2535 g_memory_buffer_put_int64 (mbuf, v);
2539 case 't': /* G_VARIANT_TYPE_UINT64 */
2540 padding_added = ensure_output_padding (mbuf, 8);
2543 guint64 v = g_variant_get_uint64 (value);
2544 g_memory_buffer_put_uint64 (mbuf, v);
2548 case 'd': /* G_VARIANT_TYPE_DOUBLE */
2549 padding_added = ensure_output_padding (mbuf, 8);
2556 G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
2557 u.v_double = g_variant_get_double (value);
2558 g_memory_buffer_put_uint64 (mbuf, u.v_uint64);
2562 case 's': /* G_VARIANT_TYPE_STRING */
2563 padding_added = ensure_output_padding (mbuf, 4);
2569 v = g_variant_get_string (value, &len);
2570 g_assert (g_utf8_validate (v, -1, &end) && (end == v + len));
2571 g_memory_buffer_put_uint32 (mbuf, len);
2572 g_memory_buffer_put_string (mbuf, v);
2573 g_memory_buffer_put_byte (mbuf, '\0');
2577 case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
2578 padding_added = ensure_output_padding (mbuf, 4);
2582 const gchar *v = g_variant_get_string (value, &len);
2583 g_assert (g_variant_is_object_path (v));
2584 g_memory_buffer_put_uint32 (mbuf, len);
2585 g_memory_buffer_put_string (mbuf, v);
2586 g_memory_buffer_put_byte (mbuf, '\0');
2590 case 'g': /* G_VARIANT_TYPE_SIGNATURE */
2594 const gchar *v = g_variant_get_string (value, &len);
2595 g_assert (g_variant_is_signature (v));
2596 g_memory_buffer_put_byte (mbuf, len);
2597 g_memory_buffer_put_string (mbuf, v);
2598 g_memory_buffer_put_byte (mbuf, '\0');
2602 case 'h': /* G_VARIANT_TYPE_HANDLE */
2603 padding_added = ensure_output_padding (mbuf, 4);
2606 gint32 v = g_variant_get_handle (value);
2607 g_memory_buffer_put_int32 (mbuf, v);
2611 case 'a': /* G_VARIANT_TYPE_ARRAY */
2613 const GVariantType *element_type;
2616 goffset array_len_offset;
2617 goffset array_payload_begin_offset;
2622 padding_added = ensure_output_padding (mbuf, 4);
2625 /* array length - will be filled in later */
2626 array_len_offset = mbuf->valid_len;
2627 g_memory_buffer_put_uint32 (mbuf, 0xF00DFACE);
2629 /* From the D-Bus spec:
2631 * "A UINT32 giving the length of the array data in bytes,
2632 * followed by alignment padding to the alignment boundary of
2633 * the array element type, followed by each array element. The
2634 * array length is from the end of the alignment padding to
2635 * the end of the last element, i.e. it does not include the
2636 * padding after the length, or any padding after the last
2639 * Thus, we need to count how much padding the first element
2640 * contributes and subtract that from the array length.
2642 array_payload_begin_offset = mbuf->valid_len;
2644 element_type = g_variant_type_element (type);
2645 fixed_size = get_type_fixed_size (element_type);
2647 if (g_variant_n_children (value) == 0)
2649 gsize padding_added_for_item;
2650 if (!append_value_to_blob (NULL,
2653 &padding_added_for_item,
2656 array_payload_begin_offset += padding_added_for_item;
2658 else if (fixed_size != 0)
2660 GVariant *use_value;
2662 if (g_memory_buffer_is_byteswapped (mbuf))
2663 use_value = g_variant_byteswap (value);
2665 use_value = g_variant_ref (value);
2667 array_payload_begin_offset += ensure_output_padding (mbuf, fixed_size);
2669 array_len = g_variant_get_size (use_value);
2670 g_memory_buffer_write (mbuf, g_variant_get_data (use_value), array_len);
2671 g_variant_unref (use_value);
2677 g_variant_iter_init (&iter, value);
2678 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2680 gsize padding_added_for_item;
2681 if (!append_value_to_blob (item,
2682 g_variant_get_type (item),
2684 &padding_added_for_item,
2687 g_variant_unref (item);
2690 g_variant_unref (item);
2693 array_payload_begin_offset += padding_added_for_item;
2699 cur_offset = mbuf->valid_len;
2700 array_len = cur_offset - array_payload_begin_offset;
2701 mbuf->pos = array_len_offset;
2703 g_memory_buffer_put_uint32 (mbuf, array_len);
2704 mbuf->pos = cur_offset;
2710 if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
2712 padding_added = ensure_output_padding (mbuf, 8);
2717 g_variant_iter_init (&iter, value);
2718 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2720 if (!append_value_to_blob (item,
2721 g_variant_get_type (item),
2726 g_variant_unref (item);
2729 g_variant_unref (item);
2733 else if (g_variant_type_is_variant (type))
2738 const gchar *signature;
2739 child = g_variant_get_child_value (value, 0);
2740 signature = g_variant_get_type_string (child);
2741 g_memory_buffer_put_byte (mbuf, strlen (signature));
2742 g_memory_buffer_put_string (mbuf, signature);
2743 g_memory_buffer_put_byte (mbuf, '\0');
2744 if (!append_value_to_blob (child,
2745 g_variant_get_type (child),
2750 g_variant_unref (child);
2753 g_variant_unref (child);
2760 G_IO_ERROR_INVALID_ARGUMENT,
2761 _("Error serializing GVariant with type string '%s' to the D-Bus wire format"),
2762 g_variant_get_type_string (value));
2768 if (out_padding_added != NULL)
2769 *out_padding_added = padding_added;
2778 append_body_to_blob (GVariant *value,
2779 GMemoryBuffer *mbuf,
2785 if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
2789 G_IO_ERROR_INVALID_ARGUMENT,
2790 "Expected a tuple for the body of the GDBusMessage.");
2794 g_variant_iter_init (&iter, value);
2795 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2797 if (!append_value_to_blob (item,
2798 g_variant_get_type (item),
2803 g_variant_unref (item);
2806 g_variant_unref (item);
2814 /* ---------------------------------------------------------------------------------------------------- */
2817 * g_dbus_message_to_blob() will be replaced by new function only for kdbus transport
2818 * purposes (this function will be able to create blob directly/unconditionally in memfd
2819 * object, without making copy)
2823 * g_dbus_message_to_blob:
2824 * @message: A #GDBusMessage.
2825 * @out_size: Return location for size of generated blob.
2826 * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2827 * @error: Return location for error.
2829 * Serializes @message to a blob. The byte order returned by
2830 * g_dbus_message_get_byte_order() will be used.
2832 * Returns: (array length=out_size) (transfer full): A pointer to a
2833 * valid binary D-Bus message of @out_size bytes generated by @message
2834 * or %NULL if @error is set. Free with g_free().
2839 g_dbus_message_to_blob (GDBusMessage *message,
2841 GDBusCapabilityFlags capabilities,
2847 goffset body_len_offset;
2848 goffset body_start_offset;
2850 gconstpointer message_body_data;
2851 gsize message_body_size;
2852 GVariant *header_fields;
2853 gsize header_fields_size;
2854 gconstpointer header_fields_data;
2855 GVariantBuilder builder;
2856 GHashTableIter hash_iter;
2858 GVariant *header_value;
2859 GVariant *signature;
2860 const gchar *signature_str;
2861 gint num_fds_in_message;
2862 gint num_fds_according_to_header;
2864 /* TODO: check against @capabilities */
2868 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2869 g_return_val_if_fail (out_size != NULL, NULL);
2870 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2872 /* temporary solution */
2873 if (!message->major_protocol_version)
2874 g_error ("message->major_protocol_version is not set");
2876 if (message->major_protocol_version != 1 && message->major_protocol_version != 2)
2880 G_IO_ERROR_INVALID_ARGUMENT,
2881 _("Invalid major protocol version. Expected 1 or 2 but found %d"),
2882 message->major_protocol_version);
2886 memset (&mbuf, 0, sizeof (mbuf));
2887 mbuf.len = MIN_ARRAY_SIZE;
2888 mbuf.data = g_malloc (mbuf.len);
2890 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN;
2891 switch (message->byte_order)
2893 case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
2894 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2896 case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
2897 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2902 g_memory_buffer_put_byte (&mbuf, (guchar) message->byte_order);
2903 g_memory_buffer_put_byte (&mbuf, message->type);
2904 g_memory_buffer_put_byte (&mbuf, message->flags);
2906 /* major protocol version */
2907 g_memory_buffer_put_byte (&mbuf, message->major_protocol_version);
2909 body_len_offset = mbuf.valid_len;
2910 /* body length - will be filled in later */
2911 g_memory_buffer_put_uint32 (&mbuf, 0xF00DFACE);
2912 g_memory_buffer_put_uint32 (&mbuf, message->serial);
2914 num_fds_in_message = 0;
2916 if (message->fd_list != NULL)
2917 num_fds_in_message = g_unix_fd_list_get_length (message->fd_list);
2919 num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
2920 if (num_fds_in_message != num_fds_according_to_header)
2924 G_IO_ERROR_INVALID_ARGUMENT,
2925 _("Message has %d file descriptors but the header field indicates %d file descriptors"),
2927 num_fds_according_to_header);
2931 if (!validate_headers (message, error))
2933 g_prefix_error (error, _("Cannot serialize message: "));
2937 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
2938 g_hash_table_iter_init (&hash_iter, message->headers);
2939 while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
2941 g_variant_builder_add (&builder,
2943 (guchar) GPOINTER_TO_UINT (key),
2946 header_fields = g_variant_builder_end (&builder);
2948 /* header - dbus1 marshaliling */
2949 if (message->major_protocol_version == 1)
2951 if (!append_value_to_blob (header_fields,
2952 g_variant_get_type (header_fields),
2957 g_variant_unref (header_fields);
2962 /* header - GVariant marshalling */
2963 else if (message->major_protocol_version == 2)
2965 header_fields_data = g_variant_get_data (header_fields);
2966 header_fields_size = g_variant_get_size (header_fields);
2968 g_memory_buffer_put_uint32 (&mbuf, header_fields_size);
2969 g_memory_buffer_write (&mbuf, header_fields_data, header_fields_size);
2972 g_variant_unref (header_fields);
2974 /* header size must be a multiple of 8 */
2975 ensure_output_padding (&mbuf, 8);
2977 body_start_offset = mbuf.valid_len;
2979 signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2980 signature_str = NULL;
2981 if (signature != NULL)
2982 signature_str = g_variant_get_string (signature, NULL);
2983 if (message->body != NULL)
2985 gchar *tupled_signature_str;
2986 tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2987 if (signature == NULL)
2991 G_IO_ERROR_INVALID_ARGUMENT,
2992 _("Message body has signature '%s' but there is no signature header"),
2994 g_free (tupled_signature_str);
2997 else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
3001 G_IO_ERROR_INVALID_ARGUMENT,
3002 _("Message body has type signature '%s' but signature in the header field is '%s'"),
3003 tupled_signature_str, g_variant_get_type_string (message->body));
3004 g_free (tupled_signature_str);
3007 g_free (tupled_signature_str);
3009 /* body - dbus1 marshaliling */
3010 if (message->major_protocol_version == 1)
3012 if (!append_body_to_blob (message->body, &mbuf, error))
3015 /* body - GVariant marshalling */
3016 else if (message->major_protocol_version == 2)
3018 message_body_data = g_variant_get_data (message->body);
3019 message_body_size = g_variant_get_size (message->body);
3021 g_memory_buffer_write (&mbuf, message_body_data, message_body_size);
3026 if (signature != NULL && strlen (signature_str) > 0)
3030 G_IO_ERROR_INVALID_ARGUMENT,
3031 _("Message body is empty but signature in the header field is '(%s)'"),
3037 /* OK, we're done writing the message - set the body length */
3038 size = mbuf.valid_len;
3039 body_size = size - body_start_offset;
3041 mbuf.pos = body_len_offset;
3043 g_memory_buffer_put_uint32 (&mbuf, body_size);
3046 ret = (guchar *)mbuf.data;
3052 /* ---------------------------------------------------------------------------------------------------- */
3055 get_uint32_header (GDBusMessage *message,
3056 GDBusMessageHeaderField header_field)
3062 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3063 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
3064 ret = g_variant_get_uint32 (value);
3069 static const gchar *
3070 get_string_header (GDBusMessage *message,
3071 GDBusMessageHeaderField header_field)
3077 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3078 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
3079 ret = g_variant_get_string (value, NULL);
3084 static const gchar *
3085 get_object_path_header (GDBusMessage *message,
3086 GDBusMessageHeaderField header_field)
3092 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3093 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
3094 ret = g_variant_get_string (value, NULL);
3099 static const gchar *
3100 get_signature_header (GDBusMessage *message,
3101 GDBusMessageHeaderField header_field)
3107 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
3108 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
3109 ret = g_variant_get_string (value, NULL);
3114 /* ---------------------------------------------------------------------------------------------------- */
3117 set_uint32_header (GDBusMessage *message,
3118 GDBusMessageHeaderField header_field,
3121 g_dbus_message_set_header (message,
3123 g_variant_new_uint32 (value));
3127 set_string_header (GDBusMessage *message,
3128 GDBusMessageHeaderField header_field,
3131 g_dbus_message_set_header (message,
3133 value == NULL ? NULL : g_variant_new_string (value));
3137 set_object_path_header (GDBusMessage *message,
3138 GDBusMessageHeaderField header_field,
3141 g_dbus_message_set_header (message,
3143 value == NULL ? NULL : g_variant_new_object_path (value));
3147 set_signature_header (GDBusMessage *message,
3148 GDBusMessageHeaderField header_field,
3151 g_dbus_message_set_header (message,
3153 value == NULL ? NULL : g_variant_new_signature (value));
3156 /* ---------------------------------------------------------------------------------------------------- */
3159 * g_dbus_message_get_reply_serial:
3160 * @message: A #GDBusMessage.
3162 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
3164 * Returns: The value.
3169 g_dbus_message_get_reply_serial (GDBusMessage *message)
3171 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3172 return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
3176 * g_dbus_message_set_reply_serial:
3177 * @message: A #GDBusMessage.
3178 * @value: The value to set.
3180 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
3185 g_dbus_message_set_reply_serial (GDBusMessage *message,
3188 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3189 set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
3192 /* ---------------------------------------------------------------------------------------------------- */
3195 * g_dbus_message_get_interface:
3196 * @message: A #GDBusMessage.
3198 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
3200 * Returns: The value.
3205 g_dbus_message_get_interface (GDBusMessage *message)
3207 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3208 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
3212 * g_dbus_message_set_interface:
3213 * @message: A #GDBusMessage.
3214 * @value: The value to set.
3216 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
3221 g_dbus_message_set_interface (GDBusMessage *message,
3224 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3225 g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
3226 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
3229 /* ---------------------------------------------------------------------------------------------------- */
3232 * g_dbus_message_get_member:
3233 * @message: A #GDBusMessage.
3235 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
3237 * Returns: The value.
3242 g_dbus_message_get_member (GDBusMessage *message)
3244 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3245 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
3249 * g_dbus_message_set_member:
3250 * @message: A #GDBusMessage.
3251 * @value: The value to set.
3253 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
3258 g_dbus_message_set_member (GDBusMessage *message,
3261 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3262 g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
3263 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
3266 /* ---------------------------------------------------------------------------------------------------- */
3269 * g_dbus_message_get_path:
3270 * @message: A #GDBusMessage.
3272 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
3274 * Returns: The value.
3279 g_dbus_message_get_path (GDBusMessage *message)
3281 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3282 return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
3286 * g_dbus_message_set_path:
3287 * @message: A #GDBusMessage.
3288 * @value: The value to set.
3290 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
3295 g_dbus_message_set_path (GDBusMessage *message,
3298 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3299 g_return_if_fail (value == NULL || g_variant_is_object_path (value));
3300 set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
3303 /* ---------------------------------------------------------------------------------------------------- */
3306 * g_dbus_message_get_sender:
3307 * @message: A #GDBusMessage.
3309 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3311 * Returns: The value.
3316 g_dbus_message_get_sender (GDBusMessage *message)
3318 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3319 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
3323 * g_dbus_message_set_sender:
3324 * @message: A #GDBusMessage.
3325 * @value: The value to set.
3327 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3332 g_dbus_message_set_sender (GDBusMessage *message,
3335 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3336 g_return_if_fail (value == NULL || g_dbus_is_name (value));
3337 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
3340 /* ---------------------------------------------------------------------------------------------------- */
3343 * g_dbus_message_get_destination:
3344 * @message: A #GDBusMessage.
3346 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3348 * Returns: The value.
3353 g_dbus_message_get_destination (GDBusMessage *message)
3355 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3356 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
3360 * g_dbus_message_set_destination:
3361 * @message: A #GDBusMessage.
3362 * @value: The value to set.
3364 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3369 g_dbus_message_set_destination (GDBusMessage *message,
3372 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3373 g_return_if_fail (value == NULL || g_dbus_is_name (value));
3374 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
3377 /* ---------------------------------------------------------------------------------------------------- */
3380 * g_dbus_message_get_error_name:
3381 * @message: A #GDBusMessage.
3383 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3385 * Returns: The value.
3390 g_dbus_message_get_error_name (GDBusMessage *message)
3392 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3393 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
3397 * g_dbus_message_set_error_name:
3398 * @message: A #GDBusMessage.
3399 * @value: The value to set.
3401 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3406 g_dbus_message_set_error_name (GDBusMessage *message,
3409 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3410 g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
3411 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
3414 /* ---------------------------------------------------------------------------------------------------- */
3417 * g_dbus_message_get_signature:
3418 * @message: A #GDBusMessage.
3420 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3422 * Returns: The value.
3427 g_dbus_message_get_signature (GDBusMessage *message)
3430 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3431 ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
3438 * g_dbus_message_set_signature:
3439 * @message: A #GDBusMessage.
3440 * @value: The value to set.
3442 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3447 g_dbus_message_set_signature (GDBusMessage *message,
3450 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3451 g_return_if_fail (value == NULL || g_variant_is_signature (value));
3452 set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
3455 /* ---------------------------------------------------------------------------------------------------- */
3458 * g_dbus_message_get_arg0:
3459 * @message: A #GDBusMessage.
3461 * Convenience to get the first item in the body of @message.
3463 * Returns: The string item or %NULL if the first item in the body of
3464 * @message is not a string.
3469 g_dbus_message_get_arg0 (GDBusMessage *message)
3473 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3477 if (message->body != NULL && g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE))
3480 item = g_variant_get_child_value (message->body, 0);
3481 if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING))
3482 ret = g_variant_get_string (item, NULL);
3483 g_variant_unref (item);
3489 /* ---------------------------------------------------------------------------------------------------- */
3492 * g_dbus_message_get_num_unix_fds:
3493 * @message: A #GDBusMessage.
3495 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3497 * Returns: The value.
3502 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
3504 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3505 return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
3509 * g_dbus_message_set_num_unix_fds:
3510 * @message: A #GDBusMessage.
3511 * @value: The value to set.
3513 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3518 g_dbus_message_set_num_unix_fds (GDBusMessage *message,
3521 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3522 set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
3525 /* ---------------------------------------------------------------------------------------------------- */
3528 * g_dbus_message_to_gerror:
3529 * @message: A #GDBusMessage.
3530 * @error: The #GError to set.
3532 * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
3533 * nothing and returns %FALSE.
3535 * Otherwise this method encodes the error in @message as a #GError
3536 * using g_dbus_error_set_dbus_error() using the information in the
3537 * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
3538 * well as the first string item in @message's body.
3540 * Returns: %TRUE if @error was set, %FALSE otherwise.
3545 g_dbus_message_to_gerror (GDBusMessage *message,
3549 const gchar *error_name;
3551 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3554 if (message->type != G_DBUS_MESSAGE_TYPE_ERROR)
3557 error_name = g_dbus_message_get_error_name (message);
3558 if (error_name != NULL)
3562 body = g_dbus_message_get_body (message);
3564 if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
3566 const gchar *error_message;
3567 g_variant_get (body, "(&s)", &error_message);
3568 g_dbus_error_set_dbus_error (error,
3575 /* these two situations are valid, yet pretty rare */
3578 g_dbus_error_set_dbus_error (error,
3581 _("Error return with body of type '%s'"),
3582 g_variant_get_type_string (body));
3586 g_dbus_error_set_dbus_error (error,
3589 _("Error return with empty body"));
3595 /* TOOD: this shouldn't happen - should check this at message serialization
3596 * time and disconnect the peer.
3601 "Error return without error-name header!");
3610 /* ---------------------------------------------------------------------------------------------------- */
3613 flags_to_string (GType flags_type, guint value)
3619 klass = g_type_class_ref (flags_type);
3620 s = g_string_new (NULL);
3621 for (n = 0; n < 32; n++)
3623 if ((value & (1<<n)) != 0)
3625 GFlagsValue *flags_value;
3626 flags_value = g_flags_get_first_value (klass, (1<<n));
3628 g_string_append_c (s, ',');
3629 if (flags_value != NULL)
3630 g_string_append (s, flags_value->value_nick);
3632 g_string_append_printf (s, "unknown (bit %d)", n);
3636 g_string_append (s, "none");
3637 g_type_class_unref (klass);
3638 return g_string_free (s, FALSE);
3642 _sort_keys_func (gconstpointer a,
3648 ia = GPOINTER_TO_INT (a);
3649 ib = GPOINTER_TO_INT (b);
3655 * g_dbus_message_print:
3656 * @message: A #GDBusMessage.
3657 * @indent: Indentation level.
3659 * Produces a human-readable multi-line description of @message.
3661 * The contents of the description has no ABI guarantees, the contents
3662 * and formatting is subject to change at any time. Typical output
3663 * looks something like this:
3670 * path -> objectpath '/org/gtk/GDBus/TestObject'
3671 * interface -> 'org.gtk.GDBus.TestInterface'
3672 * member -> 'GimmeStdout'
3673 * destination -> ':1.146'
3675 * UNIX File Descriptors:
3680 * Type: method-return
3681 * Flags: no-reply-expected
3685 * reply-serial -> uint32 4
3686 * destination -> ':1.159'
3687 * sender -> ':1.146'
3688 * num-unix-fds -> uint32 1
3690 * UNIX File Descriptors:
3691 * fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
3694 * Returns: A string that should be freed with g_free().
3699 g_dbus_message_print (GDBusMessage *message,
3707 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3709 str = g_string_new (NULL);
3711 s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->type);
3712 g_string_append_printf (str, "%*sType: %s\n", indent, "", s);
3714 s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->flags);
3715 g_string_append_printf (str, "%*sFlags: %s\n", indent, "", s);
3717 g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->major_protocol_version);
3718 g_string_append_printf (str, "%*sSerial: %d\n", indent, "", message->serial);
3720 g_string_append_printf (str, "%*sHeaders:\n", indent, "");
3721 keys = g_hash_table_get_keys (message->headers);
3722 keys = g_list_sort (keys, _sort_keys_func);
3725 for (l = keys; l != NULL; l = l->next)
3727 gint key = GPOINTER_TO_INT (l->data);
3731 value = g_hash_table_lookup (message->headers, l->data);
3732 g_assert (value != NULL);
3734 s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
3735 value_str = g_variant_print (value, TRUE);
3736 g_string_append_printf (str, "%*s %s -> %s\n", indent, "", s, value_str);
3743 g_string_append_printf (str, "%*s (none)\n", indent, "");
3745 g_string_append_printf (str, "%*sBody: ", indent, "");
3746 if (message->body != NULL)
3748 g_variant_print_string (message->body,
3754 g_string_append (str, "()");
3756 g_string_append (str, "\n");
3758 g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
3759 if (message->fd_list != NULL)
3765 fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3768 for (n = 0; n < num_fds; n++)
3771 struct stat statbuf;
3772 fs = g_string_new (NULL);
3773 if (fstat (fds[n], &statbuf) == 0)
3775 g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
3776 major (statbuf.st_dev), minor (statbuf.st_dev));
3777 g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
3779 g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3780 (guint64) statbuf.st_ino);
3781 g_string_append_printf (fs, "%s" "uid=%u", fs->len > 0 ? "," : "",
3782 (guint) statbuf.st_uid);
3783 g_string_append_printf (fs, "%s" "gid=%u", fs->len > 0 ? "," : "",
3784 (guint) statbuf.st_gid);
3785 g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
3786 major (statbuf.st_rdev), minor (statbuf.st_rdev));
3787 g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3788 (guint64) statbuf.st_size);
3789 g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3790 (guint64) statbuf.st_atime);
3791 g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3792 (guint64) statbuf.st_mtime);
3793 g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3794 (guint64) statbuf.st_ctime);
3798 g_string_append_printf (fs, "(fstat failed: %s)", strerror (errno));
3800 g_string_append_printf (str, "%*s fd %d: %s\n", indent, "", fds[n], fs->str);
3801 g_string_free (fs, TRUE);
3806 g_string_append_printf (str, "%*s (empty)\n", indent, "");
3811 g_string_append_printf (str, "%*s (none)\n", indent, "");
3815 return g_string_free (str, FALSE);
3819 * g_dbus_message_get_locked:
3820 * @message: A #GDBusMessage.
3822 * Checks whether @message is locked. To monitor changes to this
3823 * value, conncet to the #GObject::notify signal to listen for changes
3824 * on the #GDBusMessage:locked property.
3826 * Returns: %TRUE if @message is locked, %FALSE otherwise.
3831 g_dbus_message_get_locked (GDBusMessage *message)
3833 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3834 return message->locked;
3838 * g_dbus_message_lock:
3839 * @message: A #GDBusMessage.
3841 * If @message is locked, does nothing. Otherwise locks the message.
3846 g_dbus_message_lock (GDBusMessage *message)
3848 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3850 if (message->locked)
3853 message->locked = TRUE;
3854 g_object_notify (G_OBJECT (message), "locked");
3861 * g_dbus_message_copy:
3862 * @message: A #GDBusMessage.
3863 * @error: Return location for error or %NULL.
3865 * Copies @message. The copy is a deep copy and the returned
3866 * #GDBusMessage is completely identical except that it is guaranteed
3869 * This operation can fail if e.g. @message contains file descriptors
3870 * and the per-process or system-wide open files limit is reached.
3872 * Returns: (transfer full): A new #GDBusMessage or %NULL if @error is set.
3873 * Free with g_object_unref().
3878 g_dbus_message_copy (GDBusMessage *message,
3882 GHashTableIter iter;
3883 gpointer header_key;
3884 GVariant *header_value;
3886 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3887 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
3889 ret = g_dbus_message_new ();
3890 ret->type = message->type;
3891 ret->flags = message->flags;
3892 ret->byte_order = message->byte_order;
3893 ret->major_protocol_version = message->major_protocol_version;
3894 ret->serial = message->serial;
3897 if (message->fd_list != NULL)
3903 ret->fd_list = g_unix_fd_list_new ();
3904 fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3905 for (n = 0; n < num_fds; n++)
3907 if (g_unix_fd_list_append (ret->fd_list,
3911 g_object_unref (ret);
3919 /* see https://bugzilla.gnome.org/show_bug.cgi?id=624546#c8 for why it's fine
3920 * to just ref (as opposed to deep-copying) the GVariant instances
3922 ret->body = message->body != NULL ? g_variant_ref (message->body) : NULL;
3923 g_hash_table_iter_init (&iter, message->headers);
3924 while (g_hash_table_iter_next (&iter, &header_key, (gpointer) &header_value))
3925 g_hash_table_insert (ret->headers, header_key, g_variant_ref (header_value));