Merge branch 'gbytes-compare-docs' into 'master'
[glib.git] / gio / gdbusmessage.c
blob68122387b72cf161d1cbe9aeeadbfaf4fe1ab846
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.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: David Zeuthen <davidz@redhat.com>
21 /* Uncomment to debug serializer code */
22 /* #define DEBUG_SERIALIZER */
24 #include "config.h"
26 #include <string.h>
27 #include <errno.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
31 #if MAJOR_IN_MKDEV
32 #include <sys/mkdev.h>
33 #elif MAJOR_IN_SYSMACROS
34 #include <sys/sysmacros.h>
35 #elif MAJOR_IN_TYPES
36 #include <sys/types.h>
37 #else
38 #define MAJOR_MINOR_NOT_FOUND 1
39 #endif
41 #include "gdbusutils.h"
42 #include "gdbusmessage.h"
43 #include "gdbuserror.h"
44 #include "gioenumtypes.h"
45 #include "ginputstream.h"
46 #include "gdatainputstream.h"
47 #include "gmemoryinputstream.h"
48 #include "goutputstream.h"
49 #include "gdataoutputstream.h"
50 #include "gmemoryoutputstream.h"
51 #include "gseekable.h"
52 #include "gioerror.h"
53 #include "gdbusprivate.h"
55 #ifdef G_OS_UNIX
56 #include "gunixfdlist.h"
57 #endif
59 #include "glibintl.h"
61 typedef struct _GMemoryBuffer GMemoryBuffer;
62 struct _GMemoryBuffer
64 gsize len;
65 gsize valid_len;
66 gsize pos;
67 gchar *data;
68 GDataStreamByteOrder byte_order;
71 static gboolean
72 g_memory_buffer_is_byteswapped (GMemoryBuffer *mbuf)
74 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
75 return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
76 #else
77 return mbuf->byte_order == G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
78 #endif
81 static guchar
82 g_memory_buffer_read_byte (GMemoryBuffer *mbuf)
84 if (mbuf->pos >= mbuf->valid_len)
85 return 0;
86 return mbuf->data [mbuf->pos++];
89 static gint16
90 g_memory_buffer_read_int16 (GMemoryBuffer *mbuf)
92 gint16 v;
94 if (mbuf->pos > mbuf->valid_len - 2)
96 mbuf->pos = mbuf->valid_len;
97 return 0;
100 memcpy (&v, mbuf->data + mbuf->pos, 2);
101 mbuf->pos += 2;
103 if (g_memory_buffer_is_byteswapped (mbuf))
104 v = GUINT16_SWAP_LE_BE (v);
106 return v;
109 static guint16
110 g_memory_buffer_read_uint16 (GMemoryBuffer *mbuf)
112 guint16 v;
114 if (mbuf->pos > mbuf->valid_len - 2)
116 mbuf->pos = mbuf->valid_len;
117 return 0;
120 memcpy (&v, mbuf->data + mbuf->pos, 2);
121 mbuf->pos += 2;
123 if (g_memory_buffer_is_byteswapped (mbuf))
124 v = GUINT16_SWAP_LE_BE (v);
126 return v;
129 static gint32
130 g_memory_buffer_read_int32 (GMemoryBuffer *mbuf)
132 gint32 v;
134 if (mbuf->pos > mbuf->valid_len - 4)
136 mbuf->pos = mbuf->valid_len;
137 return 0;
140 memcpy (&v, mbuf->data + mbuf->pos, 4);
141 mbuf->pos += 4;
143 if (g_memory_buffer_is_byteswapped (mbuf))
144 v = GUINT32_SWAP_LE_BE (v);
146 return v;
149 static guint32
150 g_memory_buffer_read_uint32 (GMemoryBuffer *mbuf)
152 guint32 v;
154 if (mbuf->pos > mbuf->valid_len - 4)
156 mbuf->pos = mbuf->valid_len;
157 return 0;
160 memcpy (&v, mbuf->data + mbuf->pos, 4);
161 mbuf->pos += 4;
163 if (g_memory_buffer_is_byteswapped (mbuf))
164 v = GUINT32_SWAP_LE_BE (v);
166 return v;
169 static gint64
170 g_memory_buffer_read_int64 (GMemoryBuffer *mbuf)
172 gint64 v;
174 if (mbuf->pos > mbuf->valid_len - 8)
176 mbuf->pos = mbuf->valid_len;
177 return 0;
180 memcpy (&v, mbuf->data + mbuf->pos, 8);
181 mbuf->pos += 8;
183 if (g_memory_buffer_is_byteswapped (mbuf))
184 v = GUINT64_SWAP_LE_BE (v);
186 return v;
189 static guint64
190 g_memory_buffer_read_uint64 (GMemoryBuffer *mbuf)
192 guint64 v;
194 if (mbuf->pos > mbuf->valid_len - 8)
196 mbuf->pos = mbuf->valid_len;
197 return 0;
200 memcpy (&v, mbuf->data + mbuf->pos, 8);
201 mbuf->pos += 8;
203 if (g_memory_buffer_is_byteswapped (mbuf))
204 v = GUINT64_SWAP_LE_BE (v);
206 return v;
209 #define MIN_ARRAY_SIZE 128
211 static gsize
212 g_nearest_pow (gsize num)
214 gsize n = 1;
216 while (n < num && n > 0)
217 n <<= 1;
219 return n;
222 static void
223 array_resize (GMemoryBuffer *mbuf,
224 gsize size)
226 gpointer data;
227 gsize len;
229 if (mbuf->len == size)
230 return;
232 len = mbuf->len;
233 data = g_realloc (mbuf->data, size);
235 if (size > len)
236 memset ((guint8 *)data + len, 0, size - len);
238 mbuf->data = data;
239 mbuf->len = size;
241 if (mbuf->len < mbuf->valid_len)
242 mbuf->valid_len = mbuf->len;
245 static gboolean
246 g_memory_buffer_write (GMemoryBuffer *mbuf,
247 const void *buffer,
248 gsize count)
250 guint8 *dest;
251 gsize new_size;
253 if (count == 0)
254 return TRUE;
256 /* Check for address space overflow, but only if the buffer is resizable.
257 Otherwise we just do a short write and don't worry. */
258 if (mbuf->pos + count < mbuf->pos)
259 return FALSE;
261 if (mbuf->pos + count > mbuf->len)
263 /* At least enought to fit the write, rounded up
264 for greater than linear growth.
265 TODO: This wastes a lot of memory at large buffer sizes.
266 Figure out a more rational allocation strategy. */
267 new_size = g_nearest_pow (mbuf->pos + count);
268 /* Check for overflow again. We have checked if
269 pos + count > G_MAXSIZE, but now check if g_nearest_pow () has
270 overflowed */
271 if (new_size == 0)
272 return FALSE;
274 new_size = MAX (new_size, MIN_ARRAY_SIZE);
275 array_resize (mbuf, new_size);
278 dest = (guint8 *)mbuf->data + mbuf->pos;
279 memcpy (dest, buffer, count);
280 mbuf->pos += count;
282 if (mbuf->pos > mbuf->valid_len)
283 mbuf->valid_len = mbuf->pos;
285 return TRUE;
288 static gboolean
289 g_memory_buffer_put_byte (GMemoryBuffer *mbuf,
290 guchar data)
292 return g_memory_buffer_write (mbuf, &data, 1);
295 static gboolean
296 g_memory_buffer_put_int16 (GMemoryBuffer *mbuf,
297 gint16 data)
299 switch (mbuf->byte_order)
301 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
302 data = GINT16_TO_BE (data);
303 break;
304 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
305 data = GINT16_TO_LE (data);
306 break;
307 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
308 default:
309 break;
312 return g_memory_buffer_write (mbuf, &data, 2);
315 static gboolean
316 g_memory_buffer_put_uint16 (GMemoryBuffer *mbuf,
317 guint16 data)
319 switch (mbuf->byte_order)
321 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
322 data = GUINT16_TO_BE (data);
323 break;
324 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
325 data = GUINT16_TO_LE (data);
326 break;
327 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
328 default:
329 break;
332 return g_memory_buffer_write (mbuf, &data, 2);
335 static gboolean
336 g_memory_buffer_put_int32 (GMemoryBuffer *mbuf,
337 gint32 data)
339 switch (mbuf->byte_order)
341 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
342 data = GINT32_TO_BE (data);
343 break;
344 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
345 data = GINT32_TO_LE (data);
346 break;
347 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
348 default:
349 break;
352 return g_memory_buffer_write (mbuf, &data, 4);
355 static gboolean
356 g_memory_buffer_put_uint32 (GMemoryBuffer *mbuf,
357 guint32 data)
359 switch (mbuf->byte_order)
361 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
362 data = GUINT32_TO_BE (data);
363 break;
364 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
365 data = GUINT32_TO_LE (data);
366 break;
367 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
368 default:
369 break;
372 return g_memory_buffer_write (mbuf, &data, 4);
375 static gboolean
376 g_memory_buffer_put_int64 (GMemoryBuffer *mbuf,
377 gint64 data)
379 switch (mbuf->byte_order)
381 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
382 data = GINT64_TO_BE (data);
383 break;
384 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
385 data = GINT64_TO_LE (data);
386 break;
387 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
388 default:
389 break;
392 return g_memory_buffer_write (mbuf, &data, 8);
395 static gboolean
396 g_memory_buffer_put_uint64 (GMemoryBuffer *mbuf,
397 guint64 data)
399 switch (mbuf->byte_order)
401 case G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN:
402 data = GUINT64_TO_BE (data);
403 break;
404 case G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN:
405 data = GUINT64_TO_LE (data);
406 break;
407 case G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN:
408 default:
409 break;
412 return g_memory_buffer_write (mbuf, &data, 8);
415 static gboolean
416 g_memory_buffer_put_string (GMemoryBuffer *mbuf,
417 const char *str)
419 g_return_val_if_fail (str != NULL, FALSE);
421 return g_memory_buffer_write (mbuf, str, strlen (str));
426 * SECTION:gdbusmessage
427 * @short_description: D-Bus Message
428 * @include: gio/gio.h
430 * A type for representing D-Bus messages that can be sent or received
431 * on a #GDBusConnection.
434 typedef struct _GDBusMessageClass GDBusMessageClass;
437 * GDBusMessageClass:
439 * Class structure for #GDBusMessage.
441 * Since: 2.26
443 struct _GDBusMessageClass
445 /*< private >*/
446 GObjectClass parent_class;
450 * GDBusMessage:
452 * The #GDBusMessage structure contains only private data and should
453 * only be accessed using the provided API.
455 * Since: 2.26
457 struct _GDBusMessage
459 /*< private >*/
460 GObject parent_instance;
462 GDBusMessageType type;
463 GDBusMessageFlags flags;
464 gboolean locked;
465 GDBusMessageByteOrder byte_order;
466 guchar major_protocol_version;
467 guint32 serial;
468 GHashTable *headers;
469 GVariant *body;
470 #ifdef G_OS_UNIX
471 GUnixFDList *fd_list;
472 #endif
475 enum
477 PROP_0,
478 PROP_LOCKED
481 G_DEFINE_TYPE (GDBusMessage, g_dbus_message, G_TYPE_OBJECT)
483 static void
484 g_dbus_message_finalize (GObject *object)
486 GDBusMessage *message = G_DBUS_MESSAGE (object);
488 if (message->headers != NULL)
489 g_hash_table_unref (message->headers);
490 if (message->body != NULL)
491 g_variant_unref (message->body);
492 #ifdef G_OS_UNIX
493 if (message->fd_list != NULL)
494 g_object_unref (message->fd_list);
495 #endif
497 if (G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize != NULL)
498 G_OBJECT_CLASS (g_dbus_message_parent_class)->finalize (object);
501 static void
502 g_dbus_message_get_property (GObject *object,
503 guint prop_id,
504 GValue *value,
505 GParamSpec *pspec)
507 GDBusMessage *message = G_DBUS_MESSAGE (object);
509 switch (prop_id)
511 case PROP_LOCKED:
512 g_value_set_boolean (value, g_dbus_message_get_locked (message));
513 break;
515 default:
516 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
517 break;
521 static void
522 g_dbus_message_class_init (GDBusMessageClass *klass)
524 GObjectClass *gobject_class;
526 gobject_class = G_OBJECT_CLASS (klass);
527 gobject_class->finalize = g_dbus_message_finalize;
528 gobject_class->get_property = g_dbus_message_get_property;
531 * GDBusConnection:locked:
533 * A boolean specifying whether the message is locked.
535 * Since: 2.26
537 g_object_class_install_property (gobject_class,
538 PROP_LOCKED,
539 g_param_spec_boolean ("locked",
540 P_("Locked"),
541 P_("Whether the message is locked"),
542 FALSE,
543 G_PARAM_READABLE |
544 G_PARAM_STATIC_NAME |
545 G_PARAM_STATIC_BLURB |
546 G_PARAM_STATIC_NICK));
549 static void
550 g_dbus_message_init (GDBusMessage *message)
552 /* Any D-Bus implementation is supposed to handle both Big and
553 * Little Endian encodings and the Endianness is part of the D-Bus
554 * message - we prefer to use Big Endian (since it's Network Byte
555 * Order and just easier to read for humans) but if the machine is
556 * Little Endian we use that for performance reasons.
558 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
559 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
560 #else
561 /* this could also be G_PDP_ENDIAN */
562 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
563 #endif
564 message->headers = g_hash_table_new_full (g_direct_hash,
565 g_direct_equal,
566 NULL,
567 (GDestroyNotify) g_variant_unref);
571 * g_dbus_message_new:
573 * Creates a new empty #GDBusMessage.
575 * Returns: A #GDBusMessage. Free with g_object_unref().
577 * Since: 2.26
579 GDBusMessage *
580 g_dbus_message_new (void)
582 return g_object_new (G_TYPE_DBUS_MESSAGE, NULL);
586 * g_dbus_message_new_method_call:
587 * @name: (nullable): A valid D-Bus name or %NULL.
588 * @path: A valid object path.
589 * @interface_: (nullable): A valid D-Bus interface name or %NULL.
590 * @method: A valid method name.
592 * Creates a new #GDBusMessage for a method call.
594 * Returns: A #GDBusMessage. Free with g_object_unref().
596 * Since: 2.26
598 GDBusMessage *
599 g_dbus_message_new_method_call (const gchar *name,
600 const gchar *path,
601 const gchar *interface_,
602 const gchar *method)
604 GDBusMessage *message;
606 g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
607 g_return_val_if_fail (g_variant_is_object_path (path), NULL);
608 g_return_val_if_fail (g_dbus_is_member_name (method), NULL);
609 g_return_val_if_fail (interface_ == NULL || g_dbus_is_interface_name (interface_), NULL);
611 message = g_dbus_message_new ();
612 message->type = G_DBUS_MESSAGE_TYPE_METHOD_CALL;
614 if (name != NULL)
615 g_dbus_message_set_destination (message, name);
616 g_dbus_message_set_path (message, path);
617 g_dbus_message_set_member (message, method);
618 if (interface_ != NULL)
619 g_dbus_message_set_interface (message, interface_);
621 return message;
625 * g_dbus_message_new_signal:
626 * @path: A valid object path.
627 * @interface_: A valid D-Bus interface name.
628 * @signal: A valid signal name.
630 * Creates a new #GDBusMessage for a signal emission.
632 * Returns: A #GDBusMessage. Free with g_object_unref().
634 * Since: 2.26
636 GDBusMessage *
637 g_dbus_message_new_signal (const gchar *path,
638 const gchar *interface_,
639 const gchar *signal)
641 GDBusMessage *message;
643 g_return_val_if_fail (g_variant_is_object_path (path), NULL);
644 g_return_val_if_fail (g_dbus_is_member_name (signal), NULL);
645 g_return_val_if_fail (g_dbus_is_interface_name (interface_), NULL);
647 message = g_dbus_message_new ();
648 message->type = G_DBUS_MESSAGE_TYPE_SIGNAL;
649 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
651 g_dbus_message_set_path (message, path);
652 g_dbus_message_set_member (message, signal);
653 g_dbus_message_set_interface (message, interface_);
655 return message;
660 * g_dbus_message_new_method_reply:
661 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
662 * create a reply message to.
664 * Creates a new #GDBusMessage that is a reply to @method_call_message.
666 * Returns: (transfer full): #GDBusMessage. Free with g_object_unref().
668 * Since: 2.26
670 GDBusMessage *
671 g_dbus_message_new_method_reply (GDBusMessage *method_call_message)
673 GDBusMessage *message;
674 const gchar *sender;
676 g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
677 g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
678 g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
680 message = g_dbus_message_new ();
681 message->type = G_DBUS_MESSAGE_TYPE_METHOD_RETURN;
682 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
683 /* reply with same endianness */
684 message->byte_order = method_call_message->byte_order;
686 g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
687 sender = g_dbus_message_get_sender (method_call_message);
688 if (sender != NULL)
689 g_dbus_message_set_destination (message, sender);
691 return message;
695 * g_dbus_message_new_method_error:
696 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
697 * create a reply message to.
698 * @error_name: A valid D-Bus error name.
699 * @error_message_format: The D-Bus error message in a printf() format.
700 * @...: Arguments for @error_message_format.
702 * Creates a new #GDBusMessage that is an error reply to @method_call_message.
704 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
706 * Since: 2.26
708 GDBusMessage *
709 g_dbus_message_new_method_error (GDBusMessage *method_call_message,
710 const gchar *error_name,
711 const gchar *error_message_format,
712 ...)
714 GDBusMessage *ret;
715 va_list var_args;
717 va_start (var_args, error_message_format);
718 ret = g_dbus_message_new_method_error_valist (method_call_message,
719 error_name,
720 error_message_format,
721 var_args);
722 va_end (var_args);
724 return ret;
728 * g_dbus_message_new_method_error_literal:
729 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
730 * create a reply message to.
731 * @error_name: A valid D-Bus error name.
732 * @error_message: The D-Bus error message.
734 * Creates a new #GDBusMessage that is an error reply to @method_call_message.
736 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
738 * Since: 2.26
740 GDBusMessage *
741 g_dbus_message_new_method_error_literal (GDBusMessage *method_call_message,
742 const gchar *error_name,
743 const gchar *error_message)
745 GDBusMessage *message;
746 const gchar *sender;
748 g_return_val_if_fail (G_IS_DBUS_MESSAGE (method_call_message), NULL);
749 g_return_val_if_fail (g_dbus_message_get_message_type (method_call_message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL, NULL);
750 g_return_val_if_fail (g_dbus_message_get_serial (method_call_message) != 0, NULL);
751 g_return_val_if_fail (g_dbus_is_name (error_name), NULL);
752 g_return_val_if_fail (error_message != NULL, NULL);
754 message = g_dbus_message_new ();
755 message->type = G_DBUS_MESSAGE_TYPE_ERROR;
756 message->flags = G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED;
757 /* reply with same endianness */
758 message->byte_order = method_call_message->byte_order;
760 g_dbus_message_set_reply_serial (message, g_dbus_message_get_serial (method_call_message));
761 g_dbus_message_set_error_name (message, error_name);
762 g_dbus_message_set_body (message, g_variant_new ("(s)", error_message));
764 sender = g_dbus_message_get_sender (method_call_message);
765 if (sender != NULL)
766 g_dbus_message_set_destination (message, sender);
768 return message;
772 * g_dbus_message_new_method_error_valist:
773 * @method_call_message: A message of type %G_DBUS_MESSAGE_TYPE_METHOD_CALL to
774 * create a reply message to.
775 * @error_name: A valid D-Bus error name.
776 * @error_message_format: The D-Bus error message in a printf() format.
777 * @var_args: Arguments for @error_message_format.
779 * Like g_dbus_message_new_method_error() but intended for language bindings.
781 * Returns: (transfer full): A #GDBusMessage. Free with g_object_unref().
783 * Since: 2.26
785 G_GNUC_PRINTF(3, 0)
786 GDBusMessage *
787 g_dbus_message_new_method_error_valist (GDBusMessage *method_call_message,
788 const gchar *error_name,
789 const gchar *error_message_format,
790 va_list var_args)
792 GDBusMessage *ret;
793 gchar *error_message;
794 error_message = g_strdup_vprintf (error_message_format, var_args);
795 ret = g_dbus_message_new_method_error_literal (method_call_message,
796 error_name,
797 error_message);
798 g_free (error_message);
799 return ret;
802 /* ---------------------------------------------------------------------------------------------------- */
805 * g_dbus_message_get_byte_order:
806 * @message: A #GDBusMessage.
808 * Gets the byte order of @message.
810 * Returns: The byte order.
812 GDBusMessageByteOrder
813 g_dbus_message_get_byte_order (GDBusMessage *message)
815 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), (GDBusMessageByteOrder) 0);
816 return message->byte_order;
820 * g_dbus_message_set_byte_order:
821 * @message: A #GDBusMessage.
822 * @byte_order: The byte order.
824 * Sets the byte order of @message.
826 void
827 g_dbus_message_set_byte_order (GDBusMessage *message,
828 GDBusMessageByteOrder byte_order)
830 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
832 if (message->locked)
834 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
835 return;
838 message->byte_order = byte_order;
841 /* ---------------------------------------------------------------------------------------------------- */
843 /* TODO: need GI annotations to specify that any guchar value goes for the type */
846 * g_dbus_message_get_message_type:
847 * @message: A #GDBusMessage.
849 * Gets the type of @message.
851 * Returns: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
853 * Since: 2.26
855 GDBusMessageType
856 g_dbus_message_get_message_type (GDBusMessage *message)
858 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_TYPE_INVALID);
859 return message->type;
863 * g_dbus_message_set_message_type:
864 * @message: A #GDBusMessage.
865 * @type: A 8-bit unsigned integer (typically a value from the #GDBusMessageType enumeration).
867 * Sets @message to be of @type.
869 * Since: 2.26
871 void
872 g_dbus_message_set_message_type (GDBusMessage *message,
873 GDBusMessageType type)
875 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
876 g_return_if_fail (type >=0 && type < 256);
878 if (message->locked)
880 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
881 return;
884 message->type = type;
887 /* ---------------------------------------------------------------------------------------------------- */
889 /* TODO: need GI annotations to specify that any guchar value goes for flags */
892 * g_dbus_message_get_flags:
893 * @message: A #GDBusMessage.
895 * Gets the flags for @message.
897 * Returns: Flags that are set (typically values from the #GDBusMessageFlags enumeration bitwise ORed together).
899 * Since: 2.26
901 GDBusMessageFlags
902 g_dbus_message_get_flags (GDBusMessage *message)
904 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), G_DBUS_MESSAGE_FLAGS_NONE);
905 return message->flags;
909 * g_dbus_message_set_flags:
910 * @message: A #GDBusMessage.
911 * @flags: Flags for @message that are set (typically values from the #GDBusMessageFlags
912 * enumeration bitwise ORed together).
914 * Sets the flags to set on @message.
916 * Since: 2.26
918 void
919 g_dbus_message_set_flags (GDBusMessage *message,
920 GDBusMessageFlags flags)
922 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
923 g_return_if_fail (flags >=0 && flags < 256);
925 if (message->locked)
927 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
928 return;
931 message->flags = flags;
934 /* ---------------------------------------------------------------------------------------------------- */
937 * g_dbus_message_get_serial:
938 * @message: A #GDBusMessage.
940 * Gets the serial for @message.
942 * Returns: A #guint32.
944 * Since: 2.26
946 guint32
947 g_dbus_message_get_serial (GDBusMessage *message)
949 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
950 return message->serial;
954 * g_dbus_message_set_serial:
955 * @message: A #GDBusMessage.
956 * @serial: A #guint32.
958 * Sets the serial for @message.
960 * Since: 2.26
962 void
963 g_dbus_message_set_serial (GDBusMessage *message,
964 guint32 serial)
966 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
968 if (message->locked)
970 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
971 return;
974 message->serial = serial;
977 /* ---------------------------------------------------------------------------------------------------- */
979 /* TODO: need GI annotations to specify that any guchar value goes for header_field */
982 * g_dbus_message_get_header:
983 * @message: A #GDBusMessage.
984 * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
986 * Gets a header field on @message.
988 * Returns: A #GVariant with the value if the header was found, %NULL
989 * otherwise. Do not free, it is owned by @message.
991 * Since: 2.26
993 GVariant *
994 g_dbus_message_get_header (GDBusMessage *message,
995 GDBusMessageHeaderField header_field)
997 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
998 g_return_val_if_fail (header_field >=0 && header_field < 256, NULL);
999 return g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
1003 * g_dbus_message_set_header:
1004 * @message: A #GDBusMessage.
1005 * @header_field: A 8-bit unsigned integer (typically a value from the #GDBusMessageHeaderField enumeration)
1006 * @value: (nullable): A #GVariant to set the header field or %NULL to clear the header field.
1008 * Sets a header field on @message.
1010 * If @value is floating, @message assumes ownership of @value.
1012 * Since: 2.26
1014 void
1015 g_dbus_message_set_header (GDBusMessage *message,
1016 GDBusMessageHeaderField header_field,
1017 GVariant *value)
1019 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1020 g_return_if_fail (header_field >=0 && header_field < 256);
1022 if (message->locked)
1024 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1025 return;
1028 if (value == NULL)
1030 g_hash_table_remove (message->headers, GUINT_TO_POINTER (header_field));
1032 else
1034 g_hash_table_insert (message->headers, GUINT_TO_POINTER (header_field), g_variant_ref_sink (value));
1039 * g_dbus_message_get_header_fields:
1040 * @message: A #GDBusMessage.
1042 * Gets an array of all header fields on @message that are set.
1044 * Returns: (array zero-terminated=1): An array of header fields
1045 * terminated by %G_DBUS_MESSAGE_HEADER_FIELD_INVALID. Each element
1046 * is a #guchar. Free with g_free().
1048 * Since: 2.26
1050 guchar *
1051 g_dbus_message_get_header_fields (GDBusMessage *message)
1053 GList *keys;
1054 guchar *ret;
1055 guint num_keys;
1056 GList *l;
1057 guint n;
1059 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1061 keys = g_hash_table_get_keys (message->headers);
1062 num_keys = g_list_length (keys);
1063 ret = g_new (guchar, num_keys + 1);
1064 for (l = keys, n = 0; l != NULL; l = l->next, n++)
1065 ret[n] = GPOINTER_TO_UINT (l->data);
1066 g_assert (n == num_keys);
1067 ret[n] = G_DBUS_MESSAGE_HEADER_FIELD_INVALID;
1068 g_list_free (keys);
1070 return ret;
1073 /* ---------------------------------------------------------------------------------------------------- */
1076 * g_dbus_message_get_body:
1077 * @message: A #GDBusMessage.
1079 * Gets the body of a message.
1081 * Returns: (transfer none): A #GVariant or %NULL if the body is
1082 * empty. Do not free, it is owned by @message.
1084 * Since: 2.26
1086 GVariant *
1087 g_dbus_message_get_body (GDBusMessage *message)
1089 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1090 return message->body;
1094 * g_dbus_message_set_body:
1095 * @message: A #GDBusMessage.
1096 * @body: Either %NULL or a #GVariant that is a tuple.
1098 * Sets the body @message. As a side-effect the
1099 * %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field is set to the
1100 * type string of @body (or cleared if @body is %NULL).
1102 * If @body is floating, @message assumes ownership of @body.
1104 * Since: 2.26
1106 void
1107 g_dbus_message_set_body (GDBusMessage *message,
1108 GVariant *body)
1110 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1111 g_return_if_fail ((body == NULL) || g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE));
1113 if (message->locked)
1115 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1116 return;
1119 if (message->body != NULL)
1120 g_variant_unref (message->body);
1121 if (body == NULL)
1123 message->body = NULL;
1124 g_dbus_message_set_signature (message, NULL);
1126 else
1128 const gchar *type_string;
1129 gsize type_string_len;
1130 gchar *signature;
1132 message->body = g_variant_ref_sink (body);
1134 type_string = g_variant_get_type_string (body);
1135 type_string_len = strlen (type_string);
1136 g_assert (type_string_len >= 2);
1137 signature = g_strndup (type_string + 1, type_string_len - 2);
1138 g_dbus_message_set_signature (message, signature);
1139 g_free (signature);
1143 /* ---------------------------------------------------------------------------------------------------- */
1145 #ifdef G_OS_UNIX
1147 * g_dbus_message_get_unix_fd_list:
1148 * @message: A #GDBusMessage.
1150 * Gets the UNIX file descriptors associated with @message, if any.
1152 * This method is only available on UNIX.
1154 * Returns: (transfer none):A #GUnixFDList or %NULL if no file descriptors are
1155 * associated. Do not free, this object is owned by @message.
1157 * Since: 2.26
1159 GUnixFDList *
1160 g_dbus_message_get_unix_fd_list (GDBusMessage *message)
1162 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
1163 return message->fd_list;
1167 * g_dbus_message_set_unix_fd_list:
1168 * @message: A #GDBusMessage.
1169 * @fd_list: (nullable): A #GUnixFDList or %NULL.
1171 * Sets the UNIX file descriptors associated with @message. As a
1172 * side-effect the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header
1173 * field is set to the number of fds in @fd_list (or cleared if
1174 * @fd_list is %NULL).
1176 * This method is only available on UNIX.
1178 * Since: 2.26
1180 void
1181 g_dbus_message_set_unix_fd_list (GDBusMessage *message,
1182 GUnixFDList *fd_list)
1184 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
1185 g_return_if_fail (fd_list == NULL || G_IS_UNIX_FD_LIST (fd_list));
1187 if (message->locked)
1189 g_warning ("%s: Attempted to modify a locked message", G_STRFUNC);
1190 return;
1193 if (message->fd_list != NULL)
1194 g_object_unref (message->fd_list);
1195 if (fd_list != NULL)
1197 message->fd_list = g_object_ref (fd_list);
1198 g_dbus_message_set_num_unix_fds (message, g_unix_fd_list_get_length (fd_list));
1200 else
1202 message->fd_list = NULL;
1203 g_dbus_message_set_num_unix_fds (message, 0);
1206 #endif
1208 /* ---------------------------------------------------------------------------------------------------- */
1210 static guint
1211 get_type_fixed_size (const GVariantType *type)
1213 /* NB: we do not treat 'b' as fixed-size here because GVariant and
1214 * D-Bus disagree about the size.
1216 switch (*g_variant_type_peek_string (type))
1218 case 'y':
1219 return 1;
1220 case 'n': case 'q':
1221 return 2;
1222 case 'i': case 'u': case 'h':
1223 return 4;
1224 case 'x': case 't': case 'd':
1225 return 8;
1226 default:
1227 return 0;
1231 static gboolean
1232 validate_headers (GDBusMessage *message,
1233 GError **error)
1235 gboolean ret;
1237 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
1238 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
1240 ret = FALSE;
1242 switch (message->type)
1244 case G_DBUS_MESSAGE_TYPE_INVALID:
1245 g_set_error_literal (error,
1246 G_IO_ERROR,
1247 G_IO_ERROR_INVALID_ARGUMENT,
1248 _("type is INVALID"));
1249 goto out;
1250 break;
1252 case G_DBUS_MESSAGE_TYPE_METHOD_CALL:
1253 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1254 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1256 g_set_error_literal (error,
1257 G_IO_ERROR,
1258 G_IO_ERROR_INVALID_ARGUMENT,
1259 _("METHOD_CALL message: PATH or MEMBER header field is missing"));
1260 goto out;
1262 break;
1264 case G_DBUS_MESSAGE_TYPE_METHOD_RETURN:
1265 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1267 g_set_error_literal (error,
1268 G_IO_ERROR,
1269 G_IO_ERROR_INVALID_ARGUMENT,
1270 _("METHOD_RETURN message: REPLY_SERIAL header field is missing"));
1271 goto out;
1273 break;
1275 case G_DBUS_MESSAGE_TYPE_ERROR:
1276 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME) == NULL ||
1277 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL) == NULL)
1279 g_set_error_literal (error,
1280 G_IO_ERROR,
1281 G_IO_ERROR_INVALID_ARGUMENT,
1282 _("ERROR message: REPLY_SERIAL or ERROR_NAME header field is missing"));
1283 goto out;
1285 break;
1287 case G_DBUS_MESSAGE_TYPE_SIGNAL:
1288 if (g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH) == NULL ||
1289 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE) == NULL ||
1290 g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER) == NULL)
1292 g_set_error_literal (error,
1293 G_IO_ERROR,
1294 G_IO_ERROR_INVALID_ARGUMENT,
1295 _("SIGNAL message: PATH, INTERFACE or MEMBER header field is missing"));
1296 goto out;
1298 if (g_strcmp0 (g_dbus_message_get_path (message), "/org/freedesktop/DBus/Local") == 0)
1300 g_set_error_literal (error,
1301 G_IO_ERROR,
1302 G_IO_ERROR_INVALID_ARGUMENT,
1303 _("SIGNAL message: The PATH header field is using the reserved value /org/freedesktop/DBus/Local"));
1304 goto out;
1306 if (g_strcmp0 (g_dbus_message_get_interface (message), "org.freedesktop.DBus.Local") == 0)
1308 g_set_error_literal (error,
1309 G_IO_ERROR,
1310 G_IO_ERROR_INVALID_ARGUMENT,
1311 _("SIGNAL message: The INTERFACE header field is using the reserved value org.freedesktop.DBus.Local"));
1312 goto out;
1314 break;
1316 default:
1317 /* hitherto unknown type - nothing to check */
1318 break;
1321 ret = TRUE;
1323 out:
1324 g_assert (ret || (error == NULL || *error != NULL));
1325 return ret;
1328 /* ---------------------------------------------------------------------------------------------------- */
1330 static gboolean
1331 ensure_input_padding (GMemoryBuffer *buf,
1332 gsize padding_size)
1334 gsize offset;
1335 gsize wanted_offset;
1337 offset = buf->pos;
1338 wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
1339 buf->pos = wanted_offset;
1340 return TRUE;
1343 static const gchar *
1344 read_string (GMemoryBuffer *mbuf,
1345 gsize len,
1346 GError **error)
1348 gchar *str;
1349 const gchar *end_valid;
1351 if G_UNLIKELY (mbuf->pos + len >= mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1353 mbuf->pos = mbuf->valid_len;
1354 /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1355 g_set_error (error,
1356 G_IO_ERROR,
1357 G_IO_ERROR_INVALID_ARGUMENT,
1358 g_dngettext (GETTEXT_PACKAGE,
1359 "Wanted to read %lu byte but only got %lu",
1360 "Wanted to read %lu bytes but only got %lu",
1361 (gulong)len),
1362 (gulong)len,
1363 (gulong)(mbuf->valid_len - mbuf->pos));
1364 return NULL;
1367 if G_UNLIKELY (mbuf->data[mbuf->pos + len] != '\0')
1369 str = g_strndup (mbuf->data + mbuf->pos, len);
1370 g_set_error (error,
1371 G_IO_ERROR,
1372 G_IO_ERROR_INVALID_ARGUMENT,
1373 _("Expected NUL byte after the string “%s” but found byte %d"),
1374 str, mbuf->data[mbuf->pos + len]);
1375 g_free (str);
1376 mbuf->pos += len + 1;
1377 return NULL;
1380 str = mbuf->data + mbuf->pos;
1381 mbuf->pos += len + 1;
1383 if G_UNLIKELY (!g_utf8_validate (str, -1, &end_valid))
1385 gint offset;
1386 gchar *valid_str;
1387 offset = (gint) (end_valid - str);
1388 valid_str = g_strndup (str, offset);
1389 g_set_error (error,
1390 G_IO_ERROR,
1391 G_IO_ERROR_INVALID_ARGUMENT,
1392 _("Expected valid UTF-8 string but found invalid bytes at byte offset %d (length of string is %d). "
1393 "The valid UTF-8 string up until that point was “%s”"),
1394 offset,
1395 (gint) len,
1396 valid_str);
1397 g_free (valid_str);
1398 return NULL;
1401 return str;
1404 static gconstpointer
1405 read_bytes (GMemoryBuffer *mbuf,
1406 gsize len,
1407 GError **error)
1409 gconstpointer result;
1411 if G_UNLIKELY (mbuf->pos + len > mbuf->valid_len || mbuf->pos + len < mbuf->pos)
1413 mbuf->pos = mbuf->valid_len;
1414 /* G_GSIZE_FORMAT doesn't work with gettext, so we use %lu */
1415 g_set_error (error,
1416 G_IO_ERROR,
1417 G_IO_ERROR_INVALID_ARGUMENT,
1418 g_dngettext (GETTEXT_PACKAGE,
1419 "Wanted to read %lu byte but only got %lu",
1420 "Wanted to read %lu bytes but only got %lu",
1421 (gulong)len),
1422 (gulong)len,
1423 (gulong)(mbuf->valid_len - mbuf->pos));
1424 return NULL;
1427 result = mbuf->data + mbuf->pos;
1428 mbuf->pos += len;
1430 return result;
1433 /* if just_align==TRUE, don't read a value, just align the input stream wrt padding */
1435 /* returns a non-floating GVariant! */
1436 static GVariant *
1437 parse_value_from_blob (GMemoryBuffer *buf,
1438 const GVariantType *type,
1439 gboolean just_align,
1440 guint indent,
1441 GError **error)
1443 GVariant *ret;
1444 GError *local_error;
1445 #ifdef DEBUG_SERIALIZER
1446 gboolean is_leaf;
1447 #endif /* DEBUG_SERIALIZER */
1448 const gchar *type_string;
1450 type_string = g_variant_type_peek_string (type);
1452 #ifdef DEBUG_SERIALIZER
1454 gchar *s;
1455 s = g_variant_type_dup_string (type);
1456 g_print ("%*s%s type %s from offset 0x%04x",
1457 indent, "",
1458 just_align ? "Aligning" : "Reading",
1460 (gint) buf->pos);
1461 g_free (s);
1463 #endif /* DEBUG_SERIALIZER */
1465 ret = NULL;
1467 #ifdef DEBUG_SERIALIZER
1468 is_leaf = TRUE;
1469 #endif /* DEBUG_SERIALIZER */
1470 local_error = NULL;
1471 switch (type_string[0])
1473 case 'b': /* G_VARIANT_TYPE_BOOLEAN */
1474 ensure_input_padding (buf, 4);
1475 if (!just_align)
1477 gboolean v;
1478 v = g_memory_buffer_read_uint32 (buf);
1479 ret = g_variant_new_boolean (v);
1481 break;
1483 case 'y': /* G_VARIANT_TYPE_BYTE */
1484 if (!just_align)
1486 guchar v;
1487 v = g_memory_buffer_read_byte (buf);
1488 ret = g_variant_new_byte (v);
1490 break;
1492 case 'n': /* G_VARIANT_TYPE_INT16 */
1493 ensure_input_padding (buf, 2);
1494 if (!just_align)
1496 gint16 v;
1497 v = g_memory_buffer_read_int16 (buf);
1498 ret = g_variant_new_int16 (v);
1500 break;
1502 case 'q': /* G_VARIANT_TYPE_UINT16 */
1503 ensure_input_padding (buf, 2);
1504 if (!just_align)
1506 guint16 v;
1507 v = g_memory_buffer_read_uint16 (buf);
1508 ret = g_variant_new_uint16 (v);
1510 break;
1512 case 'i': /* G_VARIANT_TYPE_INT32 */
1513 ensure_input_padding (buf, 4);
1514 if (!just_align)
1516 gint32 v;
1517 v = g_memory_buffer_read_int32 (buf);
1518 ret = g_variant_new_int32 (v);
1520 break;
1522 case 'u': /* G_VARIANT_TYPE_UINT32 */
1523 ensure_input_padding (buf, 4);
1524 if (!just_align)
1526 guint32 v;
1527 v = g_memory_buffer_read_uint32 (buf);
1528 ret = g_variant_new_uint32 (v);
1530 break;
1532 case 'x': /* G_VARIANT_TYPE_INT64 */
1533 ensure_input_padding (buf, 8);
1534 if (!just_align)
1536 gint64 v;
1537 v = g_memory_buffer_read_int64 (buf);
1538 ret = g_variant_new_int64 (v);
1540 break;
1542 case 't': /* G_VARIANT_TYPE_UINT64 */
1543 ensure_input_padding (buf, 8);
1544 if (!just_align)
1546 guint64 v;
1547 v = g_memory_buffer_read_uint64 (buf);
1548 ret = g_variant_new_uint64 (v);
1550 break;
1552 case 'd': /* G_VARIANT_TYPE_DOUBLE */
1553 ensure_input_padding (buf, 8);
1554 if (!just_align)
1556 union {
1557 guint64 v_uint64;
1558 gdouble v_double;
1559 } u;
1560 G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
1561 u.v_uint64 = g_memory_buffer_read_uint64 (buf);
1562 ret = g_variant_new_double (u.v_double);
1564 break;
1566 case 's': /* G_VARIANT_TYPE_STRING */
1567 ensure_input_padding (buf, 4);
1568 if (!just_align)
1570 guint32 len;
1571 const gchar *v;
1572 len = g_memory_buffer_read_uint32 (buf);
1573 v = read_string (buf, (gsize) len, &local_error);
1574 if (v == NULL)
1575 goto fail;
1576 ret = g_variant_new_string (v);
1578 break;
1580 case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
1581 ensure_input_padding (buf, 4);
1582 if (!just_align)
1584 guint32 len;
1585 const gchar *v;
1586 len = g_memory_buffer_read_uint32 (buf);
1587 v = read_string (buf, (gsize) len, &local_error);
1588 if (v == NULL)
1589 goto fail;
1590 if (!g_variant_is_object_path (v))
1592 g_set_error (&local_error,
1593 G_IO_ERROR,
1594 G_IO_ERROR_INVALID_ARGUMENT,
1595 _("Parsed value “%s” is not a valid D-Bus object path"),
1597 goto fail;
1599 ret = g_variant_new_object_path (v);
1601 break;
1603 case 'g': /* G_VARIANT_TYPE_SIGNATURE */
1604 if (!just_align)
1606 guchar len;
1607 const gchar *v;
1608 len = g_memory_buffer_read_byte (buf);
1609 v = read_string (buf, (gsize) len, &local_error);
1610 if (v == NULL)
1611 goto fail;
1612 if (!g_variant_is_signature (v))
1614 g_set_error (&local_error,
1615 G_IO_ERROR,
1616 G_IO_ERROR_INVALID_ARGUMENT,
1617 _("Parsed value “%s” is not a valid D-Bus signature"),
1619 goto fail;
1621 ret = g_variant_new_signature (v);
1623 break;
1625 case 'h': /* G_VARIANT_TYPE_HANDLE */
1626 ensure_input_padding (buf, 4);
1627 if (!just_align)
1629 gint32 v;
1630 v = g_memory_buffer_read_int32 (buf);
1631 ret = g_variant_new_handle (v);
1633 break;
1635 case 'a': /* G_VARIANT_TYPE_ARRAY */
1636 ensure_input_padding (buf, 4);
1638 /* If we are only aligning for this array type, it is the child type of
1639 * another array, which is empty. So, we do not need to add padding for
1640 * this nonexistent array's elements: we only need to align for this
1641 * array itself (4 bytes). See
1642 * <https://bugzilla.gnome.org/show_bug.cgi?id=673612>.
1644 if (!just_align)
1646 guint32 array_len;
1647 const GVariantType *element_type;
1648 guint fixed_size;
1650 array_len = g_memory_buffer_read_uint32 (buf);
1652 #ifdef DEBUG_SERIALIZER
1653 is_leaf = FALSE;
1654 g_print (": array spans 0x%04x bytes\n", array_len);
1655 #endif /* DEBUG_SERIALIZER */
1657 if (array_len > (2<<26))
1659 /* G_GUINT32_FORMAT doesn't work with gettext, so use u */
1660 g_set_error (&local_error,
1661 G_IO_ERROR,
1662 G_IO_ERROR_INVALID_ARGUMENT,
1663 g_dngettext (GETTEXT_PACKAGE,
1664 "Encountered array of length %u byte. Maximum length is 2<<26 bytes (64 MiB).",
1665 "Encountered array of length %u bytes. Maximum length is 2<<26 bytes (64 MiB).",
1666 array_len),
1667 array_len);
1668 goto fail;
1671 element_type = g_variant_type_element (type);
1672 fixed_size = get_type_fixed_size (element_type);
1674 /* Fast-path the cases like 'ay', etc. */
1675 if (fixed_size != 0)
1677 gconstpointer array_data;
1679 if (array_len % fixed_size != 0)
1681 g_set_error (&local_error,
1682 G_IO_ERROR,
1683 G_IO_ERROR_INVALID_ARGUMENT,
1684 _("Encountered array of type “a%c”, expected to have a length a multiple "
1685 "of %u bytes, but found to be %u bytes in length"),
1686 g_variant_type_peek_string (element_type)[0], fixed_size, array_len);
1687 goto fail;
1690 ensure_input_padding (buf, fixed_size);
1691 array_data = read_bytes (buf, array_len, &local_error);
1692 if (array_data == NULL)
1693 goto fail;
1695 ret = g_variant_new_fixed_array (element_type, array_data, array_len / fixed_size, fixed_size);
1697 if (g_memory_buffer_is_byteswapped (buf))
1699 GVariant *tmp = g_variant_ref_sink (ret);
1700 ret = g_variant_byteswap (tmp);
1701 g_variant_unref (tmp);
1704 else
1706 GVariantBuilder builder;
1707 goffset offset;
1708 goffset target;
1710 g_variant_builder_init (&builder, type);
1712 if (array_len == 0)
1714 GVariant *item;
1715 item = parse_value_from_blob (buf,
1716 element_type,
1717 TRUE,
1718 indent + 2,
1719 NULL);
1720 g_assert (item == NULL);
1722 else
1724 offset = buf->pos;
1725 target = offset + array_len;
1726 while (offset < target)
1728 GVariant *item;
1729 item = parse_value_from_blob (buf,
1730 element_type,
1731 FALSE,
1732 indent + 2,
1733 &local_error);
1734 if (item == NULL)
1736 g_variant_builder_clear (&builder);
1737 goto fail;
1739 g_variant_builder_add_value (&builder, item);
1740 g_variant_unref (item);
1741 offset = buf->pos;
1745 ret = g_variant_builder_end (&builder);
1748 break;
1750 default:
1751 if (g_variant_type_is_dict_entry (type))
1753 const GVariantType *key_type;
1754 const GVariantType *value_type;
1755 GVariant *key;
1756 GVariant *value;
1758 ensure_input_padding (buf, 8);
1760 #ifdef DEBUG_SERIALIZER
1761 is_leaf = FALSE;
1762 g_print ("\n");
1763 #endif /* DEBUG_SERIALIZER */
1765 if (!just_align)
1767 key_type = g_variant_type_key (type);
1768 key = parse_value_from_blob (buf,
1769 key_type,
1770 FALSE,
1771 indent + 2,
1772 &local_error);
1773 if (key == NULL)
1774 goto fail;
1775 value_type = g_variant_type_value (type);
1776 value = parse_value_from_blob (buf,
1777 value_type,
1778 FALSE,
1779 indent + 2,
1780 &local_error);
1781 if (value == NULL)
1783 g_variant_unref (key);
1784 goto fail;
1786 ret = g_variant_new_dict_entry (key, value);
1787 g_variant_unref (key);
1788 g_variant_unref (value);
1791 else if (g_variant_type_is_tuple (type))
1793 ensure_input_padding (buf, 8);
1795 #ifdef DEBUG_SERIALIZER
1796 is_leaf = FALSE;
1797 g_print ("\n");
1798 #endif /* DEBUG_SERIALIZER */
1800 if (!just_align)
1802 const GVariantType *element_type;
1803 GVariantBuilder builder;
1805 g_variant_builder_init (&builder, type);
1806 element_type = g_variant_type_first (type);
1807 while (element_type != NULL)
1809 GVariant *item;
1810 item = parse_value_from_blob (buf,
1811 element_type,
1812 FALSE,
1813 indent + 2,
1814 &local_error);
1815 if (item == NULL)
1817 g_variant_builder_clear (&builder);
1818 goto fail;
1820 g_variant_builder_add_value (&builder, item);
1821 g_variant_unref (item);
1823 element_type = g_variant_type_next (element_type);
1825 ret = g_variant_builder_end (&builder);
1828 else if (g_variant_type_is_variant (type))
1830 #ifdef DEBUG_SERIALIZER
1831 is_leaf = FALSE;
1832 g_print ("\n");
1833 #endif /* DEBUG_SERIALIZER */
1835 if (!just_align)
1837 guchar siglen;
1838 const gchar *sig;
1839 GVariantType *variant_type;
1840 GVariant *value;
1842 siglen = g_memory_buffer_read_byte (buf);
1843 sig = read_string (buf, (gsize) siglen, &local_error);
1844 if (sig == NULL)
1845 goto fail;
1846 if (!g_variant_is_signature (sig))
1848 g_set_error (&local_error,
1849 G_IO_ERROR,
1850 G_IO_ERROR_INVALID_ARGUMENT,
1851 _("Parsed value “%s” for variant is not a valid D-Bus signature"),
1852 sig);
1853 goto fail;
1855 variant_type = g_variant_type_new (sig);
1856 value = parse_value_from_blob (buf,
1857 variant_type,
1858 FALSE,
1859 indent + 2,
1860 &local_error);
1861 g_variant_type_free (variant_type);
1862 if (value == NULL)
1863 goto fail;
1864 ret = g_variant_new_variant (value);
1865 g_variant_unref (value);
1868 else
1870 gchar *s;
1871 s = g_variant_type_dup_string (type);
1872 g_set_error (&local_error,
1873 G_IO_ERROR,
1874 G_IO_ERROR_INVALID_ARGUMENT,
1875 _("Error deserializing GVariant with type string “%s” from the D-Bus wire format"),
1877 g_free (s);
1878 goto fail;
1880 break;
1883 g_assert ((just_align && ret == NULL) || (!just_align && ret != NULL));
1885 #ifdef DEBUG_SERIALIZER
1886 if (ret != NULL)
1888 if (is_leaf)
1890 gchar *s;
1891 if (g_variant_type_equal (type, G_VARIANT_TYPE_BYTE))
1893 s = g_strdup_printf ("0x%02x '%c'", g_variant_get_byte (ret), g_variant_get_byte (ret));
1895 else
1897 s = g_variant_print (ret, FALSE);
1899 g_print (": %s\n", s);
1900 g_free (s);
1903 #endif /* DEBUG_SERIALIZER */
1905 /* sink the reference, if floating */
1906 if (ret != NULL)
1907 g_variant_take_ref (ret);
1908 return ret;
1910 fail:
1911 #ifdef DEBUG_SERIALIZER
1912 g_print ("\n"
1913 "%*sFAILURE: %s (%s, %d)\n",
1914 indent, "",
1915 local_error->message,
1916 g_quark_to_string (local_error->domain),
1917 local_error->code);
1918 #endif /* DEBUG_SERIALIZER */
1919 g_propagate_error (error, local_error);
1920 return NULL;
1923 /* ---------------------------------------------------------------------------------------------------- */
1925 /* message_header must be at least 16 bytes */
1928 * g_dbus_message_bytes_needed:
1929 * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1930 * @blob_len: The length of @blob (must be at least 16).
1931 * @error: Return location for error or %NULL.
1933 * Utility function to calculate how many bytes are needed to
1934 * completely deserialize the D-Bus message stored at @blob.
1936 * Returns: Number of bytes needed or -1 if @error is set (e.g. if
1937 * @blob contains invalid data or not enough data is available to
1938 * determine the size).
1940 * Since: 2.26
1942 gssize
1943 g_dbus_message_bytes_needed (guchar *blob,
1944 gsize blob_len,
1945 GError **error)
1947 gssize ret;
1949 ret = -1;
1951 g_return_val_if_fail (blob != NULL, -1);
1952 g_return_val_if_fail (error == NULL || *error == NULL, -1);
1953 g_return_val_if_fail (blob_len >= 16, -1);
1955 if (blob[0] == 'l')
1957 /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1958 ret = 12 + 4 + GUINT32_FROM_LE (((guint32 *) blob)[3]);
1959 /* round up so it's a multiple of 8 */
1960 ret = 8 * ((ret + 7)/8);
1961 /* finally add the body size */
1962 ret += GUINT32_FROM_LE (((guint32 *) blob)[1]);
1964 else if (blob[0] == 'B')
1966 /* core header (12 bytes) + ARRAY of STRUCT of (BYTE,VARIANT) */
1967 ret = 12 + 4 + GUINT32_FROM_BE (((guint32 *) blob)[3]);
1968 /* round up so it's a multiple of 8 */
1969 ret = 8 * ((ret + 7)/8);
1970 /* finally add the body size */
1971 ret += GUINT32_FROM_BE (((guint32 *) blob)[1]);
1973 else
1975 g_set_error (error,
1976 G_IO_ERROR,
1977 G_IO_ERROR_INVALID_ARGUMENT,
1978 "Unable to determine message blob length - given blob is malformed");
1981 if (ret > (2<<27))
1983 g_set_error (error,
1984 G_IO_ERROR,
1985 G_IO_ERROR_INVALID_ARGUMENT,
1986 "Blob indicates that message exceeds maximum message length (128MiB)");
1987 ret = -1;
1990 return ret;
1993 /* ---------------------------------------------------------------------------------------------------- */
1996 * g_dbus_message_new_from_blob:
1997 * @blob: (array length=blob_len) (element-type guint8): A blob represent a binary D-Bus message.
1998 * @blob_len: The length of @blob.
1999 * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2000 * @error: Return location for error or %NULL.
2002 * Creates a new #GDBusMessage from the data stored at @blob. The byte
2003 * order that the message was in can be retrieved using
2004 * g_dbus_message_get_byte_order().
2006 * Returns: A new #GDBusMessage or %NULL if @error is set. Free with
2007 * g_object_unref().
2009 * Since: 2.26
2011 GDBusMessage *
2012 g_dbus_message_new_from_blob (guchar *blob,
2013 gsize blob_len,
2014 GDBusCapabilityFlags capabilities,
2015 GError **error)
2017 gboolean ret;
2018 GMemoryBuffer mbuf;
2019 GDBusMessage *message;
2020 guchar endianness;
2021 guchar major_protocol_version;
2022 guint32 message_body_len;
2023 GVariant *headers;
2024 GVariant *item;
2025 GVariantIter iter;
2026 GVariant *signature;
2028 /* TODO: check against @capabilities */
2030 ret = FALSE;
2032 g_return_val_if_fail (blob != NULL, NULL);
2033 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2034 g_return_val_if_fail (blob_len >= 12, NULL);
2036 message = g_dbus_message_new ();
2038 memset (&mbuf, 0, sizeof (mbuf));
2039 mbuf.data = (gchar *)blob;
2040 mbuf.len = mbuf.valid_len = blob_len;
2042 endianness = g_memory_buffer_read_byte (&mbuf);
2043 switch (endianness)
2045 case 'l':
2046 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2047 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN;
2048 break;
2049 case 'B':
2050 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2051 message->byte_order = G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN;
2052 break;
2053 default:
2054 g_set_error (error,
2055 G_IO_ERROR,
2056 G_IO_ERROR_INVALID_ARGUMENT,
2057 _("Invalid endianness value. Expected 0x6c (“l”) or 0x42 (“B”) but found value 0x%02x"),
2058 endianness);
2059 goto out;
2062 message->type = g_memory_buffer_read_byte (&mbuf);
2063 message->flags = g_memory_buffer_read_byte (&mbuf);
2064 major_protocol_version = g_memory_buffer_read_byte (&mbuf);
2065 if (major_protocol_version != 1)
2067 g_set_error (error,
2068 G_IO_ERROR,
2069 G_IO_ERROR_INVALID_ARGUMENT,
2070 _("Invalid major protocol version. Expected 1 but found %d"),
2071 major_protocol_version);
2072 goto out;
2074 message_body_len = g_memory_buffer_read_uint32 (&mbuf);
2075 message->serial = g_memory_buffer_read_uint32 (&mbuf);
2077 #ifdef DEBUG_SERIALIZER
2078 g_print ("Parsing blob (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2080 gchar *s;
2081 s = _g_dbus_hexdump ((const gchar *) blob, blob_len, 2);
2082 g_print ("%s\n", s);
2083 g_free (s);
2085 #endif /* DEBUG_SERIALIZER */
2087 #ifdef DEBUG_SERIALIZER
2088 g_print ("Parsing headers (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2089 #endif /* DEBUG_SERIALIZER */
2090 headers = parse_value_from_blob (&mbuf,
2091 G_VARIANT_TYPE ("a{yv}"),
2092 FALSE,
2094 error);
2095 if (headers == NULL)
2096 goto out;
2097 g_variant_iter_init (&iter, headers);
2098 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2100 guchar header_field;
2101 GVariant *value;
2102 g_variant_get (item,
2103 "{yv}",
2104 &header_field,
2105 &value);
2106 g_dbus_message_set_header (message, header_field, value);
2107 g_variant_unref (value);
2108 g_variant_unref (item);
2110 g_variant_unref (headers);
2112 signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2113 if (signature != NULL)
2115 const gchar *signature_str;
2116 gsize signature_str_len;
2118 signature_str = g_variant_get_string (signature, &signature_str_len);
2120 /* signature but no body */
2121 if (message_body_len == 0 && signature_str_len > 0)
2123 g_set_error (error,
2124 G_IO_ERROR,
2125 G_IO_ERROR_INVALID_ARGUMENT,
2126 _("Signature header with signature “%s” found but message body is empty"),
2127 signature_str);
2128 goto out;
2130 else if (signature_str_len > 0)
2132 GVariantType *variant_type;
2133 gchar *tupled_signature_str;
2135 if (!g_variant_is_signature (signature_str))
2137 g_set_error (error,
2138 G_IO_ERROR,
2139 G_IO_ERROR_INVALID_ARGUMENT,
2140 _("Parsed value “%s” is not a valid D-Bus signature (for body)"),
2141 signature_str);
2142 goto out;
2144 tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2145 variant_type = g_variant_type_new (tupled_signature_str);
2146 g_free (tupled_signature_str);
2147 #ifdef DEBUG_SERIALIZER
2148 g_print ("Parsing body (blob_len = 0x%04x bytes)\n", (gint) blob_len);
2149 #endif /* DEBUG_SERIALIZER */
2150 message->body = parse_value_from_blob (&mbuf,
2151 variant_type,
2152 FALSE,
2154 error);
2155 g_variant_type_free (variant_type);
2156 if (message->body == NULL)
2157 goto out;
2160 else
2162 /* no signature, this is only OK if the body is empty */
2163 if (message_body_len != 0)
2165 /* G_GUINT32_FORMAT doesn't work with gettext, just use %u */
2166 g_set_error (error,
2167 G_IO_ERROR,
2168 G_IO_ERROR_INVALID_ARGUMENT,
2169 g_dngettext (GETTEXT_PACKAGE,
2170 "No signature header in message but the message body is %u byte",
2171 "No signature header in message but the message body is %u bytes",
2172 message_body_len),
2173 message_body_len);
2174 goto out;
2178 if (!validate_headers (message, error))
2180 g_prefix_error (error, _("Cannot deserialize message: "));
2181 goto out;
2184 ret = TRUE;
2186 out:
2187 if (ret)
2189 return message;
2191 else
2193 if (message != NULL)
2194 g_object_unref (message);
2195 return NULL;
2199 /* ---------------------------------------------------------------------------------------------------- */
2201 static gsize
2202 ensure_output_padding (GMemoryBuffer *mbuf,
2203 gsize padding_size)
2205 gsize offset;
2206 gsize wanted_offset;
2207 gsize padding_needed;
2208 guint n;
2210 offset = mbuf->pos;
2211 wanted_offset = ((offset + padding_size - 1) / padding_size) * padding_size;
2212 padding_needed = wanted_offset - offset;
2214 for (n = 0; n < padding_needed; n++)
2215 g_memory_buffer_put_byte (mbuf, '\0');
2217 return padding_needed;
2220 /* note that value can be NULL for e.g. empty arrays - type is never NULL */
2221 static gboolean
2222 append_value_to_blob (GVariant *value,
2223 const GVariantType *type,
2224 GMemoryBuffer *mbuf,
2225 gsize *out_padding_added,
2226 GError **error)
2228 gsize padding_added;
2229 const gchar *type_string;
2231 type_string = g_variant_type_peek_string (type);
2233 padding_added = 0;
2235 switch (type_string[0])
2237 case 'b': /* G_VARIANT_TYPE_BOOLEAN */
2238 padding_added = ensure_output_padding (mbuf, 4);
2239 if (value != NULL)
2241 gboolean v = g_variant_get_boolean (value);
2242 g_memory_buffer_put_uint32 (mbuf, v);
2244 break;
2246 case 'y': /* G_VARIANT_TYPE_BYTE */
2247 if (value != NULL)
2249 guint8 v = g_variant_get_byte (value);
2250 g_memory_buffer_put_byte (mbuf, v);
2252 break;
2254 case 'n': /* G_VARIANT_TYPE_INT16 */
2255 padding_added = ensure_output_padding (mbuf, 2);
2256 if (value != NULL)
2258 gint16 v = g_variant_get_int16 (value);
2259 g_memory_buffer_put_int16 (mbuf, v);
2261 break;
2263 case 'q': /* G_VARIANT_TYPE_UINT16 */
2264 padding_added = ensure_output_padding (mbuf, 2);
2265 if (value != NULL)
2267 guint16 v = g_variant_get_uint16 (value);
2268 g_memory_buffer_put_uint16 (mbuf, v);
2270 break;
2272 case 'i': /* G_VARIANT_TYPE_INT32 */
2273 padding_added = ensure_output_padding (mbuf, 4);
2274 if (value != NULL)
2276 gint32 v = g_variant_get_int32 (value);
2277 g_memory_buffer_put_int32 (mbuf, v);
2279 break;
2281 case 'u': /* G_VARIANT_TYPE_UINT32 */
2282 padding_added = ensure_output_padding (mbuf, 4);
2283 if (value != NULL)
2285 guint32 v = g_variant_get_uint32 (value);
2286 g_memory_buffer_put_uint32 (mbuf, v);
2288 break;
2290 case 'x': /* G_VARIANT_TYPE_INT64 */
2291 padding_added = ensure_output_padding (mbuf, 8);
2292 if (value != NULL)
2294 gint64 v = g_variant_get_int64 (value);
2295 g_memory_buffer_put_int64 (mbuf, v);
2297 break;
2299 case 't': /* G_VARIANT_TYPE_UINT64 */
2300 padding_added = ensure_output_padding (mbuf, 8);
2301 if (value != NULL)
2303 guint64 v = g_variant_get_uint64 (value);
2304 g_memory_buffer_put_uint64 (mbuf, v);
2306 break;
2308 case 'd': /* G_VARIANT_TYPE_DOUBLE */
2309 padding_added = ensure_output_padding (mbuf, 8);
2310 if (value != NULL)
2312 union {
2313 guint64 v_uint64;
2314 gdouble v_double;
2315 } u;
2316 G_STATIC_ASSERT (sizeof (gdouble) == sizeof (guint64));
2317 u.v_double = g_variant_get_double (value);
2318 g_memory_buffer_put_uint64 (mbuf, u.v_uint64);
2320 break;
2322 case 's': /* G_VARIANT_TYPE_STRING */
2323 padding_added = ensure_output_padding (mbuf, 4);
2324 if (value != NULL)
2326 gsize len;
2327 const gchar *v;
2328 const gchar *end;
2329 v = g_variant_get_string (value, &len);
2330 g_assert (g_utf8_validate (v, -1, &end) && (end == v + len));
2331 g_memory_buffer_put_uint32 (mbuf, len);
2332 g_memory_buffer_put_string (mbuf, v);
2333 g_memory_buffer_put_byte (mbuf, '\0');
2335 break;
2337 case 'o': /* G_VARIANT_TYPE_OBJECT_PATH */
2338 padding_added = ensure_output_padding (mbuf, 4);
2339 if (value != NULL)
2341 gsize len;
2342 const gchar *v = g_variant_get_string (value, &len);
2343 g_assert (g_variant_is_object_path (v));
2344 g_memory_buffer_put_uint32 (mbuf, len);
2345 g_memory_buffer_put_string (mbuf, v);
2346 g_memory_buffer_put_byte (mbuf, '\0');
2348 break;
2350 case 'g': /* G_VARIANT_TYPE_SIGNATURE */
2351 if (value != NULL)
2353 gsize len;
2354 const gchar *v = g_variant_get_string (value, &len);
2355 g_assert (g_variant_is_signature (v));
2356 g_memory_buffer_put_byte (mbuf, len);
2357 g_memory_buffer_put_string (mbuf, v);
2358 g_memory_buffer_put_byte (mbuf, '\0');
2360 break;
2362 case 'h': /* G_VARIANT_TYPE_HANDLE */
2363 padding_added = ensure_output_padding (mbuf, 4);
2364 if (value != NULL)
2366 gint32 v = g_variant_get_handle (value);
2367 g_memory_buffer_put_int32 (mbuf, v);
2369 break;
2371 case 'a': /* G_VARIANT_TYPE_ARRAY */
2373 const GVariantType *element_type;
2374 GVariant *item;
2375 GVariantIter iter;
2376 goffset array_len_offset;
2377 goffset array_payload_begin_offset;
2378 goffset cur_offset;
2379 gsize array_len;
2380 guint fixed_size;
2382 padding_added = ensure_output_padding (mbuf, 4);
2383 if (value != NULL)
2385 /* array length - will be filled in later */
2386 array_len_offset = mbuf->valid_len;
2387 g_memory_buffer_put_uint32 (mbuf, 0xF00DFACE);
2389 /* From the D-Bus spec:
2391 * "A UINT32 giving the length of the array data in bytes,
2392 * followed by alignment padding to the alignment boundary of
2393 * the array element type, followed by each array element. The
2394 * array length is from the end of the alignment padding to
2395 * the end of the last element, i.e. it does not include the
2396 * padding after the length, or any padding after the last
2397 * element."
2399 * Thus, we need to count how much padding the first element
2400 * contributes and subtract that from the array length.
2402 array_payload_begin_offset = mbuf->valid_len;
2404 element_type = g_variant_type_element (type);
2405 fixed_size = get_type_fixed_size (element_type);
2407 if (g_variant_n_children (value) == 0)
2409 gsize padding_added_for_item;
2410 if (!append_value_to_blob (NULL,
2411 element_type,
2412 mbuf,
2413 &padding_added_for_item,
2414 error))
2415 goto fail;
2416 array_payload_begin_offset += padding_added_for_item;
2418 else if (fixed_size != 0)
2420 GVariant *use_value;
2422 if (g_memory_buffer_is_byteswapped (mbuf))
2423 use_value = g_variant_byteswap (value);
2424 else
2425 use_value = g_variant_ref (value);
2427 array_payload_begin_offset += ensure_output_padding (mbuf, fixed_size);
2429 array_len = g_variant_get_size (use_value);
2430 g_memory_buffer_write (mbuf, g_variant_get_data (use_value), array_len);
2431 g_variant_unref (use_value);
2433 else
2435 guint n;
2436 n = 0;
2437 g_variant_iter_init (&iter, value);
2438 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2440 gsize padding_added_for_item;
2441 if (!append_value_to_blob (item,
2442 g_variant_get_type (item),
2443 mbuf,
2444 &padding_added_for_item,
2445 error))
2447 g_variant_unref (item);
2448 goto fail;
2450 g_variant_unref (item);
2451 if (n == 0)
2453 array_payload_begin_offset += padding_added_for_item;
2455 n++;
2459 cur_offset = mbuf->valid_len;
2460 array_len = cur_offset - array_payload_begin_offset;
2461 mbuf->pos = array_len_offset;
2463 g_memory_buffer_put_uint32 (mbuf, array_len);
2464 mbuf->pos = cur_offset;
2467 break;
2469 default:
2470 if (g_variant_type_is_dict_entry (type) || g_variant_type_is_tuple (type))
2472 padding_added = ensure_output_padding (mbuf, 8);
2473 if (value != NULL)
2475 GVariant *item;
2476 GVariantIter iter;
2477 g_variant_iter_init (&iter, value);
2478 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2480 if (!append_value_to_blob (item,
2481 g_variant_get_type (item),
2482 mbuf,
2483 NULL,
2484 error))
2486 g_variant_unref (item);
2487 goto fail;
2489 g_variant_unref (item);
2493 else if (g_variant_type_is_variant (type))
2495 if (value != NULL)
2497 GVariant *child;
2498 const gchar *signature;
2499 child = g_variant_get_child_value (value, 0);
2500 signature = g_variant_get_type_string (child);
2501 g_memory_buffer_put_byte (mbuf, strlen (signature));
2502 g_memory_buffer_put_string (mbuf, signature);
2503 g_memory_buffer_put_byte (mbuf, '\0');
2504 if (!append_value_to_blob (child,
2505 g_variant_get_type (child),
2506 mbuf,
2507 NULL,
2508 error))
2510 g_variant_unref (child);
2511 goto fail;
2513 g_variant_unref (child);
2516 else
2518 g_set_error (error,
2519 G_IO_ERROR,
2520 G_IO_ERROR_INVALID_ARGUMENT,
2521 _("Error serializing GVariant with type string “%s” to the D-Bus wire format"),
2522 g_variant_get_type_string (value));
2523 goto fail;
2525 break;
2528 if (out_padding_added != NULL)
2529 *out_padding_added = padding_added;
2531 return TRUE;
2533 fail:
2534 return FALSE;
2537 static gboolean
2538 append_body_to_blob (GVariant *value,
2539 GMemoryBuffer *mbuf,
2540 GError **error)
2542 GVariant *item;
2543 GVariantIter iter;
2545 if (!g_variant_is_of_type (value, G_VARIANT_TYPE_TUPLE))
2547 g_set_error (error,
2548 G_IO_ERROR,
2549 G_IO_ERROR_INVALID_ARGUMENT,
2550 "Expected a tuple for the body of the GDBusMessage.");
2551 goto fail;
2554 g_variant_iter_init (&iter, value);
2555 while ((item = g_variant_iter_next_value (&iter)) != NULL)
2557 if (!append_value_to_blob (item,
2558 g_variant_get_type (item),
2559 mbuf,
2560 NULL,
2561 error))
2563 g_variant_unref (item);
2564 goto fail;
2566 g_variant_unref (item);
2568 return TRUE;
2570 fail:
2571 return FALSE;
2574 /* ---------------------------------------------------------------------------------------------------- */
2577 * g_dbus_message_to_blob:
2578 * @message: A #GDBusMessage.
2579 * @out_size: Return location for size of generated blob.
2580 * @capabilities: A #GDBusCapabilityFlags describing what protocol features are supported.
2581 * @error: Return location for error.
2583 * Serializes @message to a blob. The byte order returned by
2584 * g_dbus_message_get_byte_order() will be used.
2586 * Returns: (array length=out_size) (transfer full): A pointer to a
2587 * valid binary D-Bus message of @out_size bytes generated by @message
2588 * or %NULL if @error is set. Free with g_free().
2590 * Since: 2.26
2592 guchar *
2593 g_dbus_message_to_blob (GDBusMessage *message,
2594 gsize *out_size,
2595 GDBusCapabilityFlags capabilities,
2596 GError **error)
2598 GMemoryBuffer mbuf;
2599 guchar *ret;
2600 gsize size;
2601 goffset body_len_offset;
2602 goffset body_start_offset;
2603 gsize body_size;
2604 GVariant *header_fields;
2605 GVariantBuilder builder;
2606 GHashTableIter hash_iter;
2607 gpointer key;
2608 GVariant *header_value;
2609 GVariant *signature;
2610 const gchar *signature_str;
2611 gint num_fds_in_message;
2612 gint num_fds_according_to_header;
2614 /* TODO: check against @capabilities */
2616 ret = NULL;
2618 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2619 g_return_val_if_fail (out_size != NULL, NULL);
2620 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
2622 memset (&mbuf, 0, sizeof (mbuf));
2623 mbuf.len = MIN_ARRAY_SIZE;
2624 mbuf.data = g_malloc (mbuf.len);
2626 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_HOST_ENDIAN;
2627 switch (message->byte_order)
2629 case G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN:
2630 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_BIG_ENDIAN;
2631 break;
2632 case G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN:
2633 mbuf.byte_order = G_DATA_STREAM_BYTE_ORDER_LITTLE_ENDIAN;
2634 break;
2637 /* Core header */
2638 g_memory_buffer_put_byte (&mbuf, (guchar) message->byte_order);
2639 g_memory_buffer_put_byte (&mbuf, message->type);
2640 g_memory_buffer_put_byte (&mbuf, message->flags);
2641 g_memory_buffer_put_byte (&mbuf, 1); /* major protocol version */
2642 body_len_offset = mbuf.valid_len;
2643 /* body length - will be filled in later */
2644 g_memory_buffer_put_uint32 (&mbuf, 0xF00DFACE);
2645 g_memory_buffer_put_uint32 (&mbuf, message->serial);
2647 num_fds_in_message = 0;
2648 #ifdef G_OS_UNIX
2649 if (message->fd_list != NULL)
2650 num_fds_in_message = g_unix_fd_list_get_length (message->fd_list);
2651 #endif
2652 num_fds_according_to_header = g_dbus_message_get_num_unix_fds (message);
2653 if (num_fds_in_message != num_fds_according_to_header)
2655 g_set_error (error,
2656 G_IO_ERROR,
2657 G_IO_ERROR_INVALID_ARGUMENT,
2658 _("Number of file descriptors in message (%d) differs from header field (%d)"),
2659 num_fds_in_message,
2660 num_fds_according_to_header);
2661 goto out;
2664 if (!validate_headers (message, error))
2666 g_prefix_error (error, _("Cannot serialize message: "));
2667 goto out;
2670 g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{yv}"));
2671 g_hash_table_iter_init (&hash_iter, message->headers);
2672 while (g_hash_table_iter_next (&hash_iter, &key, (gpointer) &header_value))
2674 g_variant_builder_add (&builder,
2675 "{yv}",
2676 (guchar) GPOINTER_TO_UINT (key),
2677 header_value);
2679 header_fields = g_variant_builder_end (&builder);
2681 if (!append_value_to_blob (header_fields,
2682 g_variant_get_type (header_fields),
2683 &mbuf,
2684 NULL,
2685 error))
2687 g_variant_unref (header_fields);
2688 goto out;
2690 g_variant_unref (header_fields);
2692 /* header size must be a multiple of 8 */
2693 ensure_output_padding (&mbuf, 8);
2695 body_start_offset = mbuf.valid_len;
2697 signature = g_dbus_message_get_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
2698 signature_str = NULL;
2699 if (signature != NULL)
2700 signature_str = g_variant_get_string (signature, NULL);
2701 if (message->body != NULL)
2703 gchar *tupled_signature_str;
2704 tupled_signature_str = g_strdup_printf ("(%s)", signature_str);
2705 if (signature == NULL)
2707 g_set_error (error,
2708 G_IO_ERROR,
2709 G_IO_ERROR_INVALID_ARGUMENT,
2710 _("Message body has signature “%s” but there is no signature header"),
2711 signature_str);
2712 g_free (tupled_signature_str);
2713 goto out;
2715 else if (g_strcmp0 (tupled_signature_str, g_variant_get_type_string (message->body)) != 0)
2717 g_set_error (error,
2718 G_IO_ERROR,
2719 G_IO_ERROR_INVALID_ARGUMENT,
2720 _("Message body has type signature “%s” but signature in the header field is “%s”"),
2721 tupled_signature_str, g_variant_get_type_string (message->body));
2722 g_free (tupled_signature_str);
2723 goto out;
2725 g_free (tupled_signature_str);
2726 if (!append_body_to_blob (message->body, &mbuf, error))
2727 goto out;
2729 else
2731 if (signature != NULL && strlen (signature_str) > 0)
2733 g_set_error (error,
2734 G_IO_ERROR,
2735 G_IO_ERROR_INVALID_ARGUMENT,
2736 _("Message body is empty but signature in the header field is “(%s)”"),
2737 signature_str);
2738 goto out;
2742 /* OK, we're done writing the message - set the body length */
2743 size = mbuf.valid_len;
2744 body_size = size - body_start_offset;
2746 mbuf.pos = body_len_offset;
2748 g_memory_buffer_put_uint32 (&mbuf, body_size);
2750 *out_size = size;
2751 ret = (guchar *)mbuf.data;
2753 out:
2754 if (ret == NULL)
2755 g_free (mbuf.data);
2757 return ret;
2760 /* ---------------------------------------------------------------------------------------------------- */
2762 static guint32
2763 get_uint32_header (GDBusMessage *message,
2764 GDBusMessageHeaderField header_field)
2766 GVariant *value;
2767 guint32 ret;
2769 ret = 0;
2770 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2771 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
2772 ret = g_variant_get_uint32 (value);
2774 return ret;
2777 static const gchar *
2778 get_string_header (GDBusMessage *message,
2779 GDBusMessageHeaderField header_field)
2781 GVariant *value;
2782 const gchar *ret;
2784 ret = NULL;
2785 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2786 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
2787 ret = g_variant_get_string (value, NULL);
2789 return ret;
2792 static const gchar *
2793 get_object_path_header (GDBusMessage *message,
2794 GDBusMessageHeaderField header_field)
2796 GVariant *value;
2797 const gchar *ret;
2799 ret = NULL;
2800 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2801 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_OBJECT_PATH))
2802 ret = g_variant_get_string (value, NULL);
2804 return ret;
2807 static const gchar *
2808 get_signature_header (GDBusMessage *message,
2809 GDBusMessageHeaderField header_field)
2811 GVariant *value;
2812 const gchar *ret;
2814 ret = NULL;
2815 value = g_hash_table_lookup (message->headers, GUINT_TO_POINTER (header_field));
2816 if (value != NULL && g_variant_is_of_type (value, G_VARIANT_TYPE_SIGNATURE))
2817 ret = g_variant_get_string (value, NULL);
2819 return ret;
2822 /* ---------------------------------------------------------------------------------------------------- */
2824 static void
2825 set_uint32_header (GDBusMessage *message,
2826 GDBusMessageHeaderField header_field,
2827 guint32 value)
2829 g_dbus_message_set_header (message,
2830 header_field,
2831 g_variant_new_uint32 (value));
2834 static void
2835 set_string_header (GDBusMessage *message,
2836 GDBusMessageHeaderField header_field,
2837 const gchar *value)
2839 g_dbus_message_set_header (message,
2840 header_field,
2841 value == NULL ? NULL : g_variant_new_string (value));
2844 static void
2845 set_object_path_header (GDBusMessage *message,
2846 GDBusMessageHeaderField header_field,
2847 const gchar *value)
2849 g_dbus_message_set_header (message,
2850 header_field,
2851 value == NULL ? NULL : g_variant_new_object_path (value));
2854 static void
2855 set_signature_header (GDBusMessage *message,
2856 GDBusMessageHeaderField header_field,
2857 const gchar *value)
2859 g_dbus_message_set_header (message,
2860 header_field,
2861 value == NULL ? NULL : g_variant_new_signature (value));
2864 /* ---------------------------------------------------------------------------------------------------- */
2867 * g_dbus_message_get_reply_serial:
2868 * @message: A #GDBusMessage.
2870 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2872 * Returns: The value.
2874 * Since: 2.26
2876 guint32
2877 g_dbus_message_get_reply_serial (GDBusMessage *message)
2879 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
2880 return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL);
2884 * g_dbus_message_set_reply_serial:
2885 * @message: A #GDBusMessage.
2886 * @value: The value to set.
2888 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL header field.
2890 * Since: 2.26
2892 void
2893 g_dbus_message_set_reply_serial (GDBusMessage *message,
2894 guint32 value)
2896 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2897 set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_REPLY_SERIAL, value);
2900 /* ---------------------------------------------------------------------------------------------------- */
2903 * g_dbus_message_get_interface:
2904 * @message: A #GDBusMessage.
2906 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2908 * Returns: The value.
2910 * Since: 2.26
2912 const gchar *
2913 g_dbus_message_get_interface (GDBusMessage *message)
2915 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2916 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE);
2920 * g_dbus_message_set_interface:
2921 * @message: A #GDBusMessage.
2922 * @value: The value to set.
2924 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE header field.
2926 * Since: 2.26
2928 void
2929 g_dbus_message_set_interface (GDBusMessage *message,
2930 const gchar *value)
2932 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2933 g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
2934 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_INTERFACE, value);
2937 /* ---------------------------------------------------------------------------------------------------- */
2940 * g_dbus_message_get_member:
2941 * @message: A #GDBusMessage.
2943 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2945 * Returns: The value.
2947 * Since: 2.26
2949 const gchar *
2950 g_dbus_message_get_member (GDBusMessage *message)
2952 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2953 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER);
2957 * g_dbus_message_set_member:
2958 * @message: A #GDBusMessage.
2959 * @value: The value to set.
2961 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_MEMBER header field.
2963 * Since: 2.26
2965 void
2966 g_dbus_message_set_member (GDBusMessage *message,
2967 const gchar *value)
2969 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
2970 g_return_if_fail (value == NULL || g_dbus_is_member_name (value));
2971 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_MEMBER, value);
2974 /* ---------------------------------------------------------------------------------------------------- */
2977 * g_dbus_message_get_path:
2978 * @message: A #GDBusMessage.
2980 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
2982 * Returns: The value.
2984 * Since: 2.26
2986 const gchar *
2987 g_dbus_message_get_path (GDBusMessage *message)
2989 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
2990 return get_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH);
2994 * g_dbus_message_set_path:
2995 * @message: A #GDBusMessage.
2996 * @value: The value to set.
2998 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_PATH header field.
3000 * Since: 2.26
3002 void
3003 g_dbus_message_set_path (GDBusMessage *message,
3004 const gchar *value)
3006 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3007 g_return_if_fail (value == NULL || g_variant_is_object_path (value));
3008 set_object_path_header (message, G_DBUS_MESSAGE_HEADER_FIELD_PATH, value);
3011 /* ---------------------------------------------------------------------------------------------------- */
3014 * g_dbus_message_get_sender:
3015 * @message: A #GDBusMessage.
3017 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3019 * Returns: The value.
3021 * Since: 2.26
3023 const gchar *
3024 g_dbus_message_get_sender (GDBusMessage *message)
3026 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3027 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER);
3031 * g_dbus_message_set_sender:
3032 * @message: A #GDBusMessage.
3033 * @value: The value to set.
3035 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SENDER header field.
3037 * Since: 2.26
3039 void
3040 g_dbus_message_set_sender (GDBusMessage *message,
3041 const gchar *value)
3043 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3044 g_return_if_fail (value == NULL || g_dbus_is_name (value));
3045 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SENDER, value);
3048 /* ---------------------------------------------------------------------------------------------------- */
3051 * g_dbus_message_get_destination:
3052 * @message: A #GDBusMessage.
3054 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3056 * Returns: The value.
3058 * Since: 2.26
3060 const gchar *
3061 g_dbus_message_get_destination (GDBusMessage *message)
3063 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3064 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION);
3068 * g_dbus_message_set_destination:
3069 * @message: A #GDBusMessage.
3070 * @value: The value to set.
3072 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION header field.
3074 * Since: 2.26
3076 void
3077 g_dbus_message_set_destination (GDBusMessage *message,
3078 const gchar *value)
3080 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3081 g_return_if_fail (value == NULL || g_dbus_is_name (value));
3082 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_DESTINATION, value);
3085 /* ---------------------------------------------------------------------------------------------------- */
3088 * g_dbus_message_get_error_name:
3089 * @message: A #GDBusMessage.
3091 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3093 * Returns: The value.
3095 * Since: 2.26
3097 const gchar *
3098 g_dbus_message_get_error_name (GDBusMessage *message)
3100 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3101 return get_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME);
3105 * g_dbus_message_set_error_name:
3106 * @message: A #GDBusMessage.
3107 * @value: The value to set.
3109 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field.
3111 * Since: 2.26
3113 void
3114 g_dbus_message_set_error_name (GDBusMessage *message,
3115 const gchar *value)
3117 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3118 g_return_if_fail (value == NULL || g_dbus_is_interface_name (value));
3119 set_string_header (message, G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME, value);
3122 /* ---------------------------------------------------------------------------------------------------- */
3125 * g_dbus_message_get_signature:
3126 * @message: A #GDBusMessage.
3128 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3130 * Returns: The value.
3132 * Since: 2.26
3134 const gchar *
3135 g_dbus_message_get_signature (GDBusMessage *message)
3137 const gchar *ret;
3138 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3139 ret = get_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE);
3140 if (ret == NULL)
3141 ret = "";
3142 return ret;
3146 * g_dbus_message_set_signature:
3147 * @message: A #GDBusMessage.
3148 * @value: The value to set.
3150 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE header field.
3152 * Since: 2.26
3154 void
3155 g_dbus_message_set_signature (GDBusMessage *message,
3156 const gchar *value)
3158 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3159 g_return_if_fail (value == NULL || g_variant_is_signature (value));
3160 set_signature_header (message, G_DBUS_MESSAGE_HEADER_FIELD_SIGNATURE, value);
3163 /* ---------------------------------------------------------------------------------------------------- */
3166 * g_dbus_message_get_arg0:
3167 * @message: A #GDBusMessage.
3169 * Convenience to get the first item in the body of @message.
3171 * Returns: The string item or %NULL if the first item in the body of
3172 * @message is not a string.
3174 * Since: 2.26
3176 const gchar *
3177 g_dbus_message_get_arg0 (GDBusMessage *message)
3179 const gchar *ret;
3181 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3183 ret = NULL;
3185 if (message->body != NULL && g_variant_is_of_type (message->body, G_VARIANT_TYPE_TUPLE))
3187 GVariant *item;
3188 item = g_variant_get_child_value (message->body, 0);
3189 if (g_variant_is_of_type (item, G_VARIANT_TYPE_STRING))
3190 ret = g_variant_get_string (item, NULL);
3191 g_variant_unref (item);
3194 return ret;
3197 /* ---------------------------------------------------------------------------------------------------- */
3200 * g_dbus_message_get_num_unix_fds:
3201 * @message: A #GDBusMessage.
3203 * Convenience getter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3205 * Returns: The value.
3207 * Since: 2.26
3209 guint32
3210 g_dbus_message_get_num_unix_fds (GDBusMessage *message)
3212 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), 0);
3213 return get_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS);
3217 * g_dbus_message_set_num_unix_fds:
3218 * @message: A #GDBusMessage.
3219 * @value: The value to set.
3221 * Convenience setter for the %G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS header field.
3223 * Since: 2.26
3225 void
3226 g_dbus_message_set_num_unix_fds (GDBusMessage *message,
3227 guint32 value)
3229 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3230 set_uint32_header (message, G_DBUS_MESSAGE_HEADER_FIELD_NUM_UNIX_FDS, value);
3233 /* ---------------------------------------------------------------------------------------------------- */
3236 * g_dbus_message_to_gerror:
3237 * @message: A #GDBusMessage.
3238 * @error: The #GError to set.
3240 * If @message is not of type %G_DBUS_MESSAGE_TYPE_ERROR does
3241 * nothing and returns %FALSE.
3243 * Otherwise this method encodes the error in @message as a #GError
3244 * using g_dbus_error_set_dbus_error() using the information in the
3245 * %G_DBUS_MESSAGE_HEADER_FIELD_ERROR_NAME header field of @message as
3246 * well as the first string item in @message's body.
3248 * Returns: %TRUE if @error was set, %FALSE otherwise.
3250 * Since: 2.26
3252 gboolean
3253 g_dbus_message_to_gerror (GDBusMessage *message,
3254 GError **error)
3256 gboolean ret;
3257 const gchar *error_name;
3259 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3261 ret = FALSE;
3262 if (message->type != G_DBUS_MESSAGE_TYPE_ERROR)
3263 goto out;
3265 error_name = g_dbus_message_get_error_name (message);
3266 if (error_name != NULL)
3268 GVariant *body;
3270 body = g_dbus_message_get_body (message);
3272 if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE ("(s)")))
3274 const gchar *error_message;
3275 g_variant_get (body, "(&s)", &error_message);
3276 g_dbus_error_set_dbus_error (error,
3277 error_name,
3278 error_message,
3279 NULL);
3281 else
3283 /* these two situations are valid, yet pretty rare */
3284 if (body != NULL)
3286 g_dbus_error_set_dbus_error (error,
3287 error_name,
3289 _("Error return with body of type “%s”"),
3290 g_variant_get_type_string (body));
3292 else
3294 g_dbus_error_set_dbus_error (error,
3295 error_name,
3297 _("Error return with empty body"));
3301 else
3303 /* TOOD: this shouldn't happen - should check this at message serialization
3304 * time and disconnect the peer.
3306 g_set_error (error,
3307 G_IO_ERROR,
3308 G_IO_ERROR_FAILED,
3309 "Error return without error-name header!");
3312 ret = TRUE;
3314 out:
3315 return ret;
3318 /* ---------------------------------------------------------------------------------------------------- */
3320 static gchar *
3321 flags_to_string (GType flags_type, guint value)
3323 GString *s;
3324 GFlagsClass *klass;
3325 guint n;
3327 klass = g_type_class_ref (flags_type);
3328 s = g_string_new (NULL);
3329 for (n = 0; n < 32; n++)
3331 if ((value & (1<<n)) != 0)
3333 GFlagsValue *flags_value;
3334 flags_value = g_flags_get_first_value (klass, (1<<n));
3335 if (s->len > 0)
3336 g_string_append_c (s, ',');
3337 if (flags_value != NULL)
3338 g_string_append (s, flags_value->value_nick);
3339 else
3340 g_string_append_printf (s, "unknown (bit %d)", n);
3343 if (s->len == 0)
3344 g_string_append (s, "none");
3345 g_type_class_unref (klass);
3346 return g_string_free (s, FALSE);
3349 static gint
3350 _sort_keys_func (gconstpointer a,
3351 gconstpointer b)
3353 gint ia;
3354 gint ib;
3356 ia = GPOINTER_TO_INT (a);
3357 ib = GPOINTER_TO_INT (b);
3359 return ia - ib;
3363 * g_dbus_message_print:
3364 * @message: A #GDBusMessage.
3365 * @indent: Indentation level.
3367 * Produces a human-readable multi-line description of @message.
3369 * The contents of the description has no ABI guarantees, the contents
3370 * and formatting is subject to change at any time. Typical output
3371 * looks something like this:
3372 * |[
3373 * Type: method-call
3374 * Flags: none
3375 * Version: 0
3376 * Serial: 4
3377 * Headers:
3378 * path -> objectpath '/org/gtk/GDBus/TestObject'
3379 * interface -> 'org.gtk.GDBus.TestInterface'
3380 * member -> 'GimmeStdout'
3381 * destination -> ':1.146'
3382 * Body: ()
3383 * UNIX File Descriptors:
3384 * (none)
3385 * ]|
3386 * or
3387 * |[
3388 * Type: method-return
3389 * Flags: no-reply-expected
3390 * Version: 0
3391 * Serial: 477
3392 * Headers:
3393 * reply-serial -> uint32 4
3394 * destination -> ':1.159'
3395 * sender -> ':1.146'
3396 * num-unix-fds -> uint32 1
3397 * Body: ()
3398 * UNIX File Descriptors:
3399 * fd 12: dev=0:10,mode=020620,ino=5,uid=500,gid=5,rdev=136:2,size=0,atime=1273085037,mtime=1273085851,ctime=1272982635
3400 * ]|
3402 * Returns: A string that should be freed with g_free().
3404 * Since: 2.26
3406 gchar *
3407 g_dbus_message_print (GDBusMessage *message,
3408 guint indent)
3410 GString *str;
3411 gchar *s;
3412 GList *keys;
3413 GList *l;
3415 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3417 str = g_string_new (NULL);
3419 s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_TYPE, message->type);
3420 g_string_append_printf (str, "%*sType: %s\n", indent, "", s);
3421 g_free (s);
3422 s = flags_to_string (G_TYPE_DBUS_MESSAGE_FLAGS, message->flags);
3423 g_string_append_printf (str, "%*sFlags: %s\n", indent, "", s);
3424 g_free (s);
3425 g_string_append_printf (str, "%*sVersion: %d\n", indent, "", message->major_protocol_version);
3426 g_string_append_printf (str, "%*sSerial: %d\n", indent, "", message->serial);
3428 g_string_append_printf (str, "%*sHeaders:\n", indent, "");
3429 keys = g_hash_table_get_keys (message->headers);
3430 keys = g_list_sort (keys, _sort_keys_func);
3431 if (keys != NULL)
3433 for (l = keys; l != NULL; l = l->next)
3435 gint key = GPOINTER_TO_INT (l->data);
3436 GVariant *value;
3437 gchar *value_str;
3439 value = g_hash_table_lookup (message->headers, l->data);
3440 g_assert (value != NULL);
3442 s = _g_dbus_enum_to_string (G_TYPE_DBUS_MESSAGE_HEADER_FIELD, key);
3443 value_str = g_variant_print (value, TRUE);
3444 g_string_append_printf (str, "%*s %s -> %s\n", indent, "", s, value_str);
3445 g_free (s);
3446 g_free (value_str);
3449 else
3451 g_string_append_printf (str, "%*s (none)\n", indent, "");
3453 g_list_free (keys);
3454 g_string_append_printf (str, "%*sBody: ", indent, "");
3455 if (message->body != NULL)
3457 g_variant_print_string (message->body,
3458 str,
3459 TRUE);
3461 else
3463 g_string_append (str, "()");
3465 g_string_append (str, "\n");
3466 #ifdef G_OS_UNIX
3467 g_string_append_printf (str, "%*sUNIX File Descriptors:\n", indent, "");
3468 if (message->fd_list != NULL)
3470 gint num_fds;
3471 const gint *fds;
3472 gint n;
3474 fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3475 if (num_fds > 0)
3477 for (n = 0; n < num_fds; n++)
3479 GString *fs;
3480 struct stat statbuf;
3481 fs = g_string_new (NULL);
3482 if (fstat (fds[n], &statbuf) == 0)
3484 #ifndef MAJOR_MINOR_NOT_FOUND
3485 g_string_append_printf (fs, "%s" "dev=%d:%d", fs->len > 0 ? "," : "",
3486 (gint) major (statbuf.st_dev), (gint) minor (statbuf.st_dev));
3487 #endif
3488 g_string_append_printf (fs, "%s" "mode=0%o", fs->len > 0 ? "," : "",
3489 (guint) statbuf.st_mode);
3490 g_string_append_printf (fs, "%s" "ino=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3491 (guint64) statbuf.st_ino);
3492 g_string_append_printf (fs, "%s" "uid=%u", fs->len > 0 ? "," : "",
3493 (guint) statbuf.st_uid);
3494 g_string_append_printf (fs, "%s" "gid=%u", fs->len > 0 ? "," : "",
3495 (guint) statbuf.st_gid);
3496 #ifndef MAJOR_MINOR_NOT_FOUND
3497 g_string_append_printf (fs, "%s" "rdev=%d:%d", fs->len > 0 ? "," : "",
3498 (gint) major (statbuf.st_rdev), (gint) minor (statbuf.st_rdev));
3499 #endif
3500 g_string_append_printf (fs, "%s" "size=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3501 (guint64) statbuf.st_size);
3502 g_string_append_printf (fs, "%s" "atime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3503 (guint64) statbuf.st_atime);
3504 g_string_append_printf (fs, "%s" "mtime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3505 (guint64) statbuf.st_mtime);
3506 g_string_append_printf (fs, "%s" "ctime=%" G_GUINT64_FORMAT, fs->len > 0 ? "," : "",
3507 (guint64) statbuf.st_ctime);
3509 else
3511 int errsv = errno;
3512 g_string_append_printf (fs, "(fstat failed: %s)", g_strerror (errsv));
3514 g_string_append_printf (str, "%*s fd %d: %s\n", indent, "", fds[n], fs->str);
3515 g_string_free (fs, TRUE);
3518 else
3520 g_string_append_printf (str, "%*s (empty)\n", indent, "");
3523 else
3525 g_string_append_printf (str, "%*s (none)\n", indent, "");
3527 #endif
3529 return g_string_free (str, FALSE);
3533 * g_dbus_message_get_locked:
3534 * @message: A #GDBusMessage.
3536 * Checks whether @message is locked. To monitor changes to this
3537 * value, conncet to the #GObject::notify signal to listen for changes
3538 * on the #GDBusMessage:locked property.
3540 * Returns: %TRUE if @message is locked, %FALSE otherwise.
3542 * Since: 2.26
3544 gboolean
3545 g_dbus_message_get_locked (GDBusMessage *message)
3547 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), FALSE);
3548 return message->locked;
3552 * g_dbus_message_lock:
3553 * @message: A #GDBusMessage.
3555 * If @message is locked, does nothing. Otherwise locks the message.
3557 * Since: 2.26
3559 void
3560 g_dbus_message_lock (GDBusMessage *message)
3562 g_return_if_fail (G_IS_DBUS_MESSAGE (message));
3564 if (message->locked)
3565 goto out;
3567 message->locked = TRUE;
3568 g_object_notify (G_OBJECT (message), "locked");
3570 out:
3575 * g_dbus_message_copy:
3576 * @message: A #GDBusMessage.
3577 * @error: Return location for error or %NULL.
3579 * Copies @message. The copy is a deep copy and the returned
3580 * #GDBusMessage is completely identical except that it is guaranteed
3581 * to not be locked.
3583 * This operation can fail if e.g. @message contains file descriptors
3584 * and the per-process or system-wide open files limit is reached.
3586 * Returns: (transfer full): A new #GDBusMessage or %NULL if @error is set.
3587 * Free with g_object_unref().
3589 * Since: 2.26
3591 GDBusMessage *
3592 g_dbus_message_copy (GDBusMessage *message,
3593 GError **error)
3595 GDBusMessage *ret;
3596 GHashTableIter iter;
3597 gpointer header_key;
3598 GVariant *header_value;
3600 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
3601 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
3603 ret = g_dbus_message_new ();
3604 ret->type = message->type;
3605 ret->flags = message->flags;
3606 ret->byte_order = message->byte_order;
3607 ret->major_protocol_version = message->major_protocol_version;
3608 ret->serial = message->serial;
3610 #ifdef G_OS_UNIX
3611 if (message->fd_list != NULL)
3613 gint n;
3614 gint num_fds;
3615 const gint *fds;
3617 ret->fd_list = g_unix_fd_list_new ();
3618 fds = g_unix_fd_list_peek_fds (message->fd_list, &num_fds);
3619 for (n = 0; n < num_fds; n++)
3621 if (g_unix_fd_list_append (ret->fd_list,
3622 fds[n],
3623 error) == -1)
3625 g_object_unref (ret);
3626 ret = NULL;
3627 goto out;
3631 #endif
3633 /* see https://bugzilla.gnome.org/show_bug.cgi?id=624546#c8 for why it's fine
3634 * to just ref (as opposed to deep-copying) the GVariant instances
3636 ret->body = message->body != NULL ? g_variant_ref (message->body) : NULL;
3637 g_hash_table_iter_init (&iter, message->headers);
3638 while (g_hash_table_iter_next (&iter, &header_key, (gpointer) &header_value))
3639 g_hash_table_insert (ret->headers, header_key, g_variant_ref (header_value));
3641 #ifdef G_OS_UNIX
3642 out:
3643 #endif
3644 return ret;