1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-message.c DBusMessage object
4 * Copyright (C) 2002, 2003 Red Hat Inc.
5 * Copyright (C) 2002, 2003 CodeFactory AB
7 * Licensed under the Academic Free License version 1.2
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "dbus-internals.h"
26 #include "dbus-marshal.h"
27 #include "dbus-message.h"
28 #include "dbus-message-internal.h"
29 #include "dbus-memory.h"
30 #include "dbus-list.h"
31 #include "dbus-message-builder.h"
35 * @defgroup DBusMessageInternals DBusMessage implementation details
36 * @ingroup DBusInternals
37 * @brief DBusMessage private implementation details.
39 * The guts of DBusMessage and its methods.
57 static dbus_bool_t field_is_named[FIELD_LAST] =
59 FALSE, /* FIELD_HEADER_LENGTH */
60 FALSE, /* FIELD_BODY_LENGTH */
61 FALSE, /* FIELD_CLIENT_SERIAL */
62 TRUE, /* FIELD_NAME */
63 TRUE, /* FIELD_SERVICE */
64 TRUE, /* FIELD_SENDER */
65 TRUE /* FIELD_REPLY_SERIAL */
70 int offset; /**< Offset to start of field (location of name of field
76 * @brief Internals of DBusMessage
78 * Object representing a message received from or to be sent to
79 * another application. This is an opaque object, all members
84 dbus_atomic_t refcount; /**< Reference count */
86 DBusString header; /**< Header network data, stored
87 * separately from body so we can
88 * independently realloc it.
91 HeaderField header_fields[FIELD_LAST]; /**< Track the location
92 * of each field in "header"
95 dbus_int32_t client_serial; /**< Cached client serial value for speed */
96 dbus_int32_t reply_serial; /**< Cached reply serial value for speed */
98 int header_padding; /**< bytes of alignment in header */
100 DBusString body; /**< Body network data. */
102 char byte_order; /**< Message byte order. */
104 DBusCounter *size_counter; /**< Counter for the size of the message, or #NULL */
105 long size_counter_delta; /**< Size we incremented the size counter by. */
107 dbus_uint32_t changed_stamp;
109 unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
113 DBUS_MESSAGE_ITER_TYPE_MESSAGE,
114 DBUS_MESSAGE_ITER_TYPE_ARRAY,
115 DBUS_MESSAGE_ITER_TYPE_DICT
118 typedef struct DBusMessageRealIter DBusMessageRealIter;
121 * @brief Internals of DBusMessageIter
123 * Object representing a position in a message. All fields are internal.
125 struct DBusMessageRealIter
127 DBusMessageRealIter *parent_iter; /**< parent iter, or NULL */
128 DBusMessage *message; /**< Message used */
129 dbus_uint32_t changed_stamp; /**< stamp to detect invalid iters */
131 /* This is an int instead of an enum to get a guaranteed size for the dummy: */
132 int type; /**< type of iter */
134 int pos; /**< Current position in the string */
135 int end; /**< position right after the container */
136 int container_type; /**< type of the items in the container (used for arrays) */
137 int container_start; /**< offset of the start of the container */
138 int container_length_pos; /**< offset of the length of the container */
139 int wrote_dict_key; /**< whether we wrote the dict key for the current dict element */
143 * Gets the data to be sent over the network for this message.
144 * The header and then the body should be written out.
145 * This function is guaranteed to always return the same
146 * data once a message is locked (with _dbus_message_lock()).
148 * @param message the message.
149 * @param header return location for message header data.
150 * @param body return location for message body data.
153 _dbus_message_get_network_data (DBusMessage *message,
154 const DBusString **header,
155 const DBusString **body)
157 _dbus_assert (message->locked);
159 *header = &message->header;
160 *body = &message->body;
164 clear_header_padding (DBusMessage *message)
166 _dbus_string_shorten (&message->header,
167 message->header_padding);
168 message->header_padding = 0;
172 append_header_padding (DBusMessage *message)
175 old_len = _dbus_string_get_length (&message->header);
176 if (!_dbus_string_align_length (&message->header, 8))
179 message->header_padding = _dbus_string_get_length (&message->header) - old_len;
185 adjust_field_offsets (DBusMessage *message,
195 while (i < FIELD_LAST)
197 if (message->header_fields[i].offset > offsets_after)
198 message->header_fields[i].offset += delta;
205 get_string_field (DBusMessage *message,
212 offset = message->header_fields[field].offset;
214 _dbus_assert (field < FIELD_LAST);
219 /* offset points to string length, string data follows it */
220 /* FIXME _dbus_demarshal_const_string() that returned
221 * a reference to the string plus its len might be nice.
225 *len = _dbus_demarshal_uint32 (&message->header,
230 data = _dbus_string_get_const_data (&message->header);
232 return data + (offset + 4);
236 get_int_field (DBusMessage *message,
241 _dbus_assert (field < FIELD_LAST);
243 offset = message->header_fields[field].offset;
246 return -1; /* useless if -1 is a valid value of course */
248 return _dbus_demarshal_int32 (&message->header,
255 append_int_field (DBusMessage *message,
262 _dbus_assert (!message->locked);
264 clear_header_padding (message);
266 orig_len = _dbus_string_get_length (&message->header);
268 if (!_dbus_string_align_length (&message->header, 4))
271 if (!_dbus_string_append_len (&message->header, name, 4))
274 if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
277 if (!_dbus_string_align_length (&message->header, 4))
280 message->header_fields[FIELD_REPLY_SERIAL].offset =
281 _dbus_string_get_length (&message->header);
283 if (!_dbus_marshal_int32 (&message->header, message->byte_order,
287 if (!append_header_padding (message))
293 message->header_fields[field].offset = -1;
294 _dbus_string_set_length (&message->header, orig_len);
296 /* this must succeed because it was allocated on function entry and
297 * DBusString doesn't ever realloc smaller
299 if (!append_header_padding (message))
300 _dbus_assert_not_reached ("failed to reappend header padding");
305 append_string_field (DBusMessage *message,
312 _dbus_assert (!message->locked);
314 clear_header_padding (message);
316 orig_len = _dbus_string_get_length (&message->header);
318 if (!_dbus_string_align_length (&message->header, 4))
321 if (!_dbus_string_append_len (&message->header, name, 4))
324 if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_STRING))
327 if (!_dbus_string_align_length (&message->header, 4))
330 message->header_fields[field].offset =
331 _dbus_string_get_length (&message->header);
333 if (!_dbus_marshal_string (&message->header, message->byte_order,
337 if (!append_header_padding (message))
343 message->header_fields[field].offset = -1;
344 _dbus_string_set_length (&message->header, orig_len);
346 /* this must succeed because it was allocated on function entry and
347 * DBusString doesn't ever realloc smaller
349 if (!append_header_padding (message))
350 _dbus_assert_not_reached ("failed to reappend header padding");
355 #ifdef DBUS_BUILD_TESTS
356 /* This isn't used, but building it when tests are enabled just to
357 * keep it compiling if we need it in future
360 delete_int_field (DBusMessage *message,
363 int offset = message->header_fields[field].offset;
365 _dbus_assert (!message->locked);
366 _dbus_assert (field_is_named[field]);
371 clear_header_padding (message);
373 /* The field typecode and name take up 8 bytes */
374 _dbus_string_delete (&message->header,
378 message->header_fields[field].offset = -1;
380 adjust_field_offsets (message,
384 append_header_padding (message);
389 delete_string_field (DBusMessage *message,
392 int offset = message->header_fields[field].offset;
396 _dbus_assert (!message->locked);
397 _dbus_assert (field_is_named[field]);
402 clear_header_padding (message);
404 get_string_field (message, field, &len);
406 /* The field typecode and name take up 8 bytes, and the nul
407 * termination is 1 bytes, string length integer is 4 bytes
409 delete_len = 8 + 4 + 1 + len;
411 _dbus_string_delete (&message->header,
415 message->header_fields[field].offset = -1;
417 adjust_field_offsets (message,
421 append_header_padding (message);
425 set_int_field (DBusMessage *message,
429 int offset = message->header_fields[field].offset;
431 _dbus_assert (!message->locked);
435 /* need to append the field */
439 case FIELD_REPLY_SERIAL:
440 return append_int_field (message, field,
441 DBUS_HEADER_FIELD_REPLY,
444 _dbus_assert_not_reached ("appending an int field we don't support appending");
450 _dbus_marshal_set_int32 (&message->header,
459 set_uint_field (DBusMessage *message,
463 int offset = message->header_fields[field].offset;
465 _dbus_assert (!message->locked);
469 /* need to append the field */
474 _dbus_assert_not_reached ("appending a uint field we don't support appending");
480 _dbus_marshal_set_uint32 (&message->header,
489 set_string_field (DBusMessage *message,
493 int offset = message->header_fields[field].offset;
495 _dbus_assert (!message->locked);
496 _dbus_assert (value != NULL);
500 /* need to append the field */
505 return append_string_field (message, field,
506 DBUS_HEADER_FIELD_SENDER,
509 _dbus_assert_not_reached ("appending a string field we don't support appending");
520 clear_header_padding (message);
522 old_len = _dbus_string_get_length (&message->header);
524 len = strlen (value);
526 _dbus_string_init_const_len (&v, value,
527 len + 1); /* include nul */
528 if (!_dbus_marshal_set_string (&message->header,
534 new_len = _dbus_string_get_length (&message->header);
536 adjust_field_offsets (message,
540 if (!append_header_padding (message))
546 /* this must succeed because it was allocated on function entry and
547 * DBusString doesn't ever realloc smaller
549 if (!append_header_padding (message))
550 _dbus_assert_not_reached ("failed to reappend header padding");
557 * Sets the serial number of a message.
558 * This can only be done once on a message.
560 * @param message the message
561 * @param serial the serial
564 _dbus_message_set_serial (DBusMessage *message,
567 _dbus_assert (!message->locked);
568 _dbus_assert (dbus_message_get_serial (message) < 0);
570 set_int_field (message, FIELD_CLIENT_SERIAL,
572 message->client_serial = serial;
576 * Sets the reply serial of a message (the client serial
577 * of the message this is a reply to).
579 * @param message the message
580 * @param reply_serial the client serial
581 * @returns #FALSE if not enough memory
584 dbus_message_set_reply_serial (DBusMessage *message,
585 dbus_int32_t reply_serial)
587 _dbus_assert (!message->locked);
589 if (set_int_field (message, FIELD_REPLY_SERIAL,
592 message->reply_serial = reply_serial;
600 * Returns the serial of a message or -1 if none has been specified.
601 * The message's serial number is provided by the application sending
602 * the message and is used to identify replies to this message.
604 * @param message the message
605 * @returns the client serial
608 dbus_message_get_serial (DBusMessage *message)
610 return message->client_serial;
614 * Returns the serial that the message is
615 * a reply to or -1 if none.
617 * @param message the message
618 * @returns the reply serial
621 dbus_message_get_reply_serial (DBusMessage *message)
623 return message->reply_serial;
627 * Adds a counter to be incremented immediately with the
628 * size of this message, and decremented by the size
629 * of this message when this message if finalized.
631 * @param message the message
632 * @param counter the counter
635 _dbus_message_add_size_counter (DBusMessage *message,
636 DBusCounter *counter)
638 _dbus_assert (message->size_counter == NULL); /* If this fails we may need to keep a list of
639 * counters instead of just one
642 message->size_counter = counter;
643 _dbus_counter_ref (message->size_counter);
645 /* When we can change message size, we may want to
646 * update this each time we do so, or we may want to
647 * just KISS like this.
649 message->size_counter_delta =
650 _dbus_string_get_length (&message->header) +
651 _dbus_string_get_length (&message->body);
654 _dbus_verbose ("message has size %ld\n",
655 message->size_counter_delta);
658 _dbus_counter_adjust (message->size_counter, message->size_counter_delta);
662 dbus_message_create_header (DBusMessage *message,
668 if (!_dbus_string_append_byte (&message->header, message->byte_order))
672 if (!_dbus_string_append_byte (&message->header, flags))
675 if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
678 if (!_dbus_string_append_byte (&message->header, 0))
681 message->header_fields[FIELD_HEADER_LENGTH].offset = 4;
682 if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
685 message->header_fields[FIELD_BODY_LENGTH].offset = 8;
686 if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
689 message->header_fields[FIELD_CLIENT_SERIAL].offset = 12;
690 if (!_dbus_marshal_int32 (&message->header, message->byte_order, -1))
693 /* Marshal message service */
696 if (!append_string_field (message,
698 DBUS_HEADER_FIELD_SERVICE,
703 _dbus_assert (name != NULL);
704 if (!append_string_field (message,
706 DBUS_HEADER_FIELD_NAME,
714 * Locks a message. Allows checking that applications don't keep a
715 * reference to a message in the outgoing queue and change it
716 * underneath us. Messages are locked when they enter the outgoing
717 * queue (dbus_connection_send_message()), and the library complains
718 * if the message is modified while locked.
720 * @param message the message to lock.
723 _dbus_message_lock (DBusMessage *message)
725 if (!message->locked)
727 /* Fill in our lengths */
728 set_uint_field (message,
730 _dbus_string_get_length (&message->header));
732 set_uint_field (message,
734 _dbus_string_get_length (&message->body));
736 message->locked = TRUE;
743 * @defgroup DBusMessage DBusMessage
745 * @brief Message to be sent or received over a DBusConnection.
747 * A DBusMessage is the most basic unit of communication over a
748 * DBusConnection. A DBusConnection represents a stream of messages
749 * received from a remote application, and a stream of messages
750 * sent to a remote application.
756 * @typedef DBusMessage
758 * Opaque data type representing a message received from or to be
759 * sent to another application.
763 dbus_message_new_empty_header (void)
765 DBusMessage *message;
768 message = dbus_new0 (DBusMessage, 1);
772 message->refcount = 1;
773 message->byte_order = DBUS_COMPILER_BYTE_ORDER;
774 message->client_serial = -1;
775 message->reply_serial = -1;
778 while (i < FIELD_LAST)
780 message->header_fields[i].offset = -1;
784 if (!_dbus_string_init (&message->header))
790 if (!_dbus_string_init (&message->body))
792 _dbus_string_free (&message->header);
802 * Constructs a new message. Returns #NULL if memory can't be
803 * allocated for the message. The service may be #NULL in which case
804 * no service is set; this is appropriate when using D-BUS in a
805 * peer-to-peer context (no message bus).
807 * @todo reverse the arguments, first 'name' then 'service'
808 * as 'name' is more fundamental
810 * @param service service that the message should be sent to or #NULL
811 * @param name name of the message
812 * @returns a new DBusMessage, free with dbus_message_unref()
813 * @see dbus_message_unref()
816 dbus_message_new (const char *service,
819 DBusMessage *message;
821 message = dbus_message_new_empty_header ();
825 if (!dbus_message_create_header (message, service, name))
827 dbus_message_unref (message);
835 * Constructs a message that is a reply to some other
836 * message. Returns #NULL if memory can't be allocated
839 * @param original_message the message which the created
840 * message is a reply to.
841 * @returns a new DBusMessage, free with dbus_message_unref()
842 * @see dbus_message_new(), dbus_message_unref()
845 dbus_message_new_reply (DBusMessage *original_message)
847 DBusMessage *message;
848 const char *sender, *name;
850 sender = get_string_field (original_message,
852 name = get_string_field (original_message,
855 /* sender is allowed to be null here in peer-to-peer case */
857 message = dbus_message_new (sender, name);
862 if (!dbus_message_set_reply_serial (message,
863 dbus_message_get_serial (original_message)))
865 dbus_message_unref (message);
873 * Creates a new message that is an error reply to a certain message.
875 * @param original_message the original message
876 * @param error_name the error name
877 * @param error_message the error message string
878 * @returns a new error message
881 dbus_message_new_error_reply (DBusMessage *original_message,
882 const char *error_name,
883 const char *error_message)
885 DBusMessage *message;
887 DBusMessageIter iter;
889 sender = get_string_field (original_message,
892 _dbus_assert (sender != NULL);
894 message = dbus_message_new (sender, error_name);
899 if (!dbus_message_set_reply_serial (message,
900 dbus_message_get_serial (original_message)))
902 dbus_message_unref (message);
906 dbus_message_append_iter_init (message, &iter);
907 if (!dbus_message_iter_append_string (&iter, error_message))
909 dbus_message_unref (message);
913 dbus_message_set_is_error (message, TRUE);
919 * Creates a new message that is an exact replica of the message
920 * specified, except that its refcount is set to 1.
922 * @param message the message.
923 * @returns the new message.
926 dbus_message_copy (const DBusMessage *message)
931 retval = dbus_new0 (DBusMessage, 1);
935 retval->refcount = 1;
936 retval->byte_order = message->byte_order;
937 retval->client_serial = message->client_serial;
938 retval->reply_serial = message->reply_serial;
939 retval->header_padding = message->header_padding;
940 retval->locked = FALSE;
942 if (!_dbus_string_init (&retval->header))
948 if (!_dbus_string_init (&retval->body))
950 _dbus_string_free (&retval->header);
955 if (!_dbus_string_copy (&message->header, 0,
958 _dbus_string_free (&retval->header);
959 _dbus_string_free (&retval->body);
965 if (!_dbus_string_copy (&message->body, 0,
968 _dbus_string_free (&retval->header);
969 _dbus_string_free (&retval->body);
975 for (i = 0; i < FIELD_LAST; i++)
977 retval->header_fields[i].offset = message->header_fields[i].offset;
985 * Increments the reference count of a DBusMessage.
987 * @param message The message
988 * @see dbus_message_unref
991 dbus_message_ref (DBusMessage *message)
993 dbus_atomic_t refcount;
995 refcount = _dbus_atomic_inc (&message->refcount);
996 _dbus_assert (refcount > 1);
1000 * Decrements the reference count of a DBusMessage.
1002 * @param message The message
1003 * @see dbus_message_ref
1006 dbus_message_unref (DBusMessage *message)
1008 dbus_atomic_t refcount;
1010 refcount = _dbus_atomic_dec (&message->refcount);
1012 _dbus_assert (refcount >= 0);
1016 if (message->size_counter != NULL)
1018 _dbus_counter_adjust (message->size_counter,
1019 - message->size_counter_delta);
1020 _dbus_counter_unref (message->size_counter);
1023 _dbus_string_free (&message->header);
1024 _dbus_string_free (&message->body);
1026 dbus_free (message);
1031 * Gets the name of a message.
1033 * @param message the message
1034 * @returns the message name (should not be freed)
1037 dbus_message_get_name (DBusMessage *message)
1039 return get_string_field (message, FIELD_NAME, NULL);
1043 * Gets the destination service of a message.
1045 * @todo I think if we have set_sender/get_sender,
1046 * this function might be better named set_destination/
1047 * get_destination for clarity, as the sender
1048 * is also a service name.
1050 * @param message the message
1051 * @returns the message destination service (should not be freed)
1054 dbus_message_get_service (DBusMessage *message)
1056 return get_string_field (message, FIELD_SERVICE, NULL);
1060 * Appends fields to a message given a variable argument
1061 * list. The variable argument list should contain the type
1062 * of the argument followed by the value to add.
1063 * Array values are specified by a int typecode followed by a pointer
1064 * to the array followed by an int giving the length of the array.
1065 * The argument list must be terminated with 0.
1067 * This function doesn't support dicts or non-fundamental arrays.
1069 * @param message the message
1070 * @param first_arg_type type of the first argument
1071 * @param ... value of first argument, list of additional type-value pairs
1072 * @returns #TRUE on success
1075 dbus_message_append_args (DBusMessage *message,
1082 va_start (var_args, first_arg_type);
1083 retval = dbus_message_append_args_valist (message,
1092 * This function takes a va_list for use by language bindings
1094 * @todo: Shouldn't this function clean up the changes to the message
1097 * @see dbus_message_append_args.
1098 * @param message the message
1099 * @param first_arg_type type of first argument
1100 * @param var_args value of first argument, then list of type/value pairs
1101 * @returns #TRUE on success
1104 dbus_message_append_args_valist (DBusMessage *message,
1109 DBusMessageIter iter;
1111 old_len = _dbus_string_get_length (&message->body);
1113 type = first_arg_type;
1115 dbus_message_append_iter_init (message, &iter);
1122 if (!dbus_message_iter_append_nil (&iter))
1125 case DBUS_TYPE_BOOLEAN:
1126 if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
1129 case DBUS_TYPE_INT32:
1130 if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
1133 case DBUS_TYPE_UINT32:
1134 if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
1137 case DBUS_TYPE_DOUBLE:
1138 if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
1141 case DBUS_TYPE_STRING:
1142 if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
1145 case DBUS_TYPE_NAMED:
1148 unsigned char *data;
1151 name = va_arg (var_args, const char *);
1152 data = va_arg (var_args, unsigned char *);
1153 len = va_arg (var_args, int);
1155 if (!dbus_message_iter_append_named (&iter, name, data, len))
1159 case DBUS_TYPE_ARRAY:
1164 type = va_arg (var_args, int);
1165 data = va_arg (var_args, void *);
1166 len = va_arg (var_args, int);
1170 case DBUS_TYPE_BYTE:
1171 if (!dbus_message_iter_append_byte_array (&iter, (unsigned char *)data, len))
1174 case DBUS_TYPE_BOOLEAN:
1175 if (!dbus_message_iter_append_boolean_array (&iter, (unsigned char *)data, len))
1178 case DBUS_TYPE_INT32:
1179 if (!dbus_message_iter_append_int32_array (&iter, (dbus_int32_t *)data, len))
1182 case DBUS_TYPE_UINT32:
1183 if (!dbus_message_iter_append_uint32_array (&iter, (dbus_uint32_t *)data, len))
1186 case DBUS_TYPE_DOUBLE:
1187 if (!dbus_message_iter_append_double_array (&iter, (double *)data, len))
1190 case DBUS_TYPE_STRING:
1191 if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
1195 case DBUS_TYPE_ARRAY:
1196 case DBUS_TYPE_NAMED:
1197 case DBUS_TYPE_DICT:
1198 _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
1201 _dbus_warn ("Unknown field type %d\n", type);
1207 case DBUS_TYPE_DICT:
1208 _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
1211 _dbus_warn ("Unknown field type %d\n", type);
1215 type = va_arg (var_args, int);
1226 * Gets arguments from a message given a variable argument list.
1227 * The variable argument list should contain the type of the
1228 * argumen followed by a pointer to where the value should be
1229 * stored. The list is terminated with 0.
1231 * @param message the message
1232 * @param error error to be filled in on failure
1233 * @param first_arg_type the first argument type
1234 * @param ... location for first argument value, then list of type-location pairs
1235 * @returns #FALSE if the error was set
1238 dbus_message_get_args (DBusMessage *message,
1246 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1248 va_start (var_args, first_arg_type);
1249 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
1256 * This function takes a va_list for use by language bindings
1258 * @todo We need to free the argument data when an error occurs.
1260 * @see dbus_message_get_args
1261 * @param message the message
1262 * @param error error to be filled in
1263 * @param first_arg_type type of the first argument
1264 * @param var_args return location for first argument, followed by list of type/location pairs
1265 * @returns #FALSE if error was set
1268 dbus_message_get_args_valist (DBusMessage *message,
1273 DBusMessageIter iter;
1275 dbus_message_iter_init (message, &iter);
1276 return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
1280 * Gets arguments from a message iterator given a variable argument list.
1281 * The variable argument list should contain the type of the
1282 * argumen followed by a pointer to where the value should be
1283 * stored. The list is terminated with 0.
1285 * @param iter the message iterator
1286 * @param error error to be filled in on failure
1287 * @param first_arg_type the first argument type
1288 * @param ... location for first argument value, then list of type-location pairs
1289 * @returns #FALSE if the error was set
1292 dbus_message_iter_get_args (DBusMessageIter *iter,
1300 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1302 va_start (var_args, first_arg_type);
1303 retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
1310 * This function takes a va_list for use by language bindings
1312 * @todo this function (or some lower-level non-convenience function)
1313 * needs better error handling; should allow the application to
1314 * distinguish between out of memory, and bad data from the remote
1315 * app. It also needs to not leak a bunch of args when it gets
1316 * to the arg that's bad, as that would be a security hole
1317 * (allow one app to force another to leak memory)
1319 * @todo We need to free the argument data when an error occurs.
1321 * @see dbus_message_get_args
1322 * @param iter the message iter
1323 * @param error error to be filled in
1324 * @param first_arg_type type of the first argument
1325 * @param var_args return location for first argument, followed by list of type/location pairs
1326 * @returns #FALSE if error was set
1329 dbus_message_iter_get_args_valist (DBusMessageIter *iter,
1334 int spec_type, msg_type, i;
1337 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1341 spec_type = first_arg_type;
1344 while (spec_type != 0)
1346 msg_type = dbus_message_iter_get_arg_type (iter);
1348 if (msg_type != spec_type)
1350 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1351 "Argument %d is specified to be of type \"%s\", but "
1352 "is actually of type \"%s\"\n", i,
1353 _dbus_type_to_string (spec_type),
1354 _dbus_type_to_string (msg_type));
1363 case DBUS_TYPE_BYTE:
1367 ptr = va_arg (var_args, unsigned char *);
1369 *ptr = dbus_message_iter_get_byte (iter);
1372 case DBUS_TYPE_BOOLEAN:
1376 ptr = va_arg (var_args, dbus_bool_t *);
1378 *ptr = dbus_message_iter_get_boolean (iter);
1381 case DBUS_TYPE_INT32:
1385 ptr = va_arg (var_args, dbus_int32_t *);
1387 *ptr = dbus_message_iter_get_int32 (iter);
1390 case DBUS_TYPE_UINT32:
1394 ptr = va_arg (var_args, dbus_uint32_t *);
1396 *ptr = dbus_message_iter_get_uint32 (iter);
1400 case DBUS_TYPE_DOUBLE:
1404 ptr = va_arg (var_args, double *);
1406 *ptr = dbus_message_iter_get_double (iter);
1410 case DBUS_TYPE_STRING:
1414 ptr = va_arg (var_args, char **);
1416 *ptr = dbus_message_iter_get_string (iter);
1420 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1427 case DBUS_TYPE_NAMED:
1430 unsigned char **data;
1433 name = va_arg (var_args, char **);
1434 data = va_arg (var_args, unsigned char **);
1435 len = va_arg (var_args, int *);
1437 *name = dbus_message_iter_get_named (iter, data, len);
1440 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1445 case DBUS_TYPE_ARRAY:
1450 type = va_arg (var_args, int);
1451 data = va_arg (var_args, void *);
1452 len = va_arg (var_args, int *);
1454 if (dbus_message_iter_get_array_type (iter) != type)
1456 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1457 "Argument %d is specified to be of type \"array of %s\", but "
1458 "is actually of type \"array of %s\"\n", i,
1459 _dbus_type_to_string (type),
1460 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
1466 case DBUS_TYPE_BYTE:
1467 if (!dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len))
1469 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1473 case DBUS_TYPE_BOOLEAN:
1474 if (!dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len))
1476 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1480 case DBUS_TYPE_INT32:
1481 if (!dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len))
1483 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1487 case DBUS_TYPE_UINT32:
1488 if (!dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len))
1490 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1494 case DBUS_TYPE_DOUBLE:
1495 if (!dbus_message_iter_get_double_array (iter, (double **)data, len))
1497 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1501 case DBUS_TYPE_STRING:
1502 if (!dbus_message_iter_get_string_array (iter, (char ***)data, len))
1504 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1509 case DBUS_TYPE_ARRAY:
1510 case DBUS_TYPE_NAMED:
1511 case DBUS_TYPE_DICT:
1512 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
1513 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1516 _dbus_warn ("Unknown field type %d\n", type);
1517 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1522 case DBUS_TYPE_DICT:
1523 _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
1524 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1527 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1528 _dbus_warn ("Unknown field type %d\n", spec_type);
1532 spec_type = va_arg (var_args, int);
1533 if (spec_type != 0 && !dbus_message_iter_next (iter))
1535 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1536 "Message has only %d arguments, but more were expected", i);
1552 * Initializes a DBusMessageIter representing the arguments of the
1553 * message passed in.
1555 * @param message the message
1556 * @param _iter pointer to an iterator to initialize
1559 dbus_message_iter_init (DBusMessage *message,
1560 DBusMessageIter *iter)
1562 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1564 _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
1566 real->message = message;
1567 real->parent_iter = NULL;
1568 real->changed_stamp = message->changed_stamp;
1570 real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
1572 real->end = _dbus_string_get_length (&message->body);
1574 real->container_type = 0;
1575 real->container_start = 0;
1576 real->container_length_pos = 0;
1577 real->wrote_dict_key = 0;
1581 dbus_message_iter_check (DBusMessageRealIter *iter)
1583 if (iter->changed_stamp != iter->message->changed_stamp)
1584 _dbus_warn ("dbus iterator check failed: invalid iterator\n");
1585 if (iter->pos < 0 || iter->pos > iter->end)
1586 _dbus_warn ("dbus iterator check failed: invalid position\n");
1590 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
1597 case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
1598 data = _dbus_string_get_const_data_len (&iter->message->body,
1600 if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1603 *type = DBUS_TYPE_INVALID;
1605 return iter->pos + 1;
1607 case DBUS_MESSAGE_ITER_TYPE_ARRAY:
1608 *type = iter->container_type;
1612 case DBUS_MESSAGE_ITER_TYPE_DICT:
1613 /* Get the length of the string */
1614 len = _dbus_demarshal_uint32 (&iter->message->body,
1615 iter->message->byte_order,
1617 pos = pos + len + 1;
1618 data = _dbus_string_get_const_data_len (&iter->message->body,
1620 if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1623 *type = DBUS_TYPE_INVALID;
1626 _dbus_assert_not_reached ("Invalid iter type");
1629 *type = DBUS_TYPE_INVALID;
1635 * Checks if an iterator has any more fields.
1637 * @param iter the message iter
1638 * @returns #TRUE if there are more fields
1642 dbus_message_iter_has_next (DBusMessageIter *iter)
1644 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1648 dbus_message_iter_check (real);
1650 if (real->pos >= real->end)
1653 pos = dbus_message_iter_get_data_start (real, &type);
1655 if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
1656 real->message->byte_order,
1657 type, pos, &end_pos))
1660 if (end_pos >= real->end)
1667 * Moves the iterator to the next field.
1669 * @param _iter The message iter
1670 * @returns #TRUE if the iterator was moved to the next field
1673 dbus_message_iter_next (DBusMessageIter *iter)
1675 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1679 dbus_message_iter_check (real);
1681 pos = dbus_message_iter_get_data_start (real, &type);
1683 if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
1684 real->message->byte_order,
1685 type, pos, &end_pos))
1688 if (end_pos >= real->end)
1691 real->pos = end_pos;
1697 * Returns the argument type of the argument that the
1698 * message iterator points at.
1700 * @param iter the message iter
1701 * @returns the field type
1704 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
1706 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1709 dbus_message_iter_check (real);
1711 if (real->pos >= real->end)
1712 return DBUS_TYPE_INVALID;
1714 pos = dbus_message_iter_get_data_start (real, &type);
1720 * Returns the element type of the array that the
1721 * message iterator points at. Note that you need
1722 * to check that the iterator points to an array
1723 * prior to using this function.
1725 * @param iter the message iter
1726 * @returns the field type
1729 dbus_message_iter_get_array_type (DBusMessageIter *iter)
1731 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1735 dbus_message_iter_check (real);
1737 if (real->pos >= real->end)
1738 return DBUS_TYPE_INVALID;
1740 pos = dbus_message_iter_get_data_start (real, &type);
1742 _dbus_assert (type == DBUS_TYPE_ARRAY);
1744 data = _dbus_string_get_const_data_len (&real->message->body,
1747 if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1750 return DBUS_TYPE_INVALID;
1755 * Returns the string value that an iterator may point to.
1756 * Note that you need to check that the iterator points to
1757 * a string value before using this function.
1759 * @see dbus_message_iter_get_arg_type
1760 * @param iter the message iter
1761 * @returns the string
1764 dbus_message_iter_get_string (DBusMessageIter *iter)
1766 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1769 dbus_message_iter_check (real);
1771 pos = dbus_message_iter_get_data_start (real, &type);
1773 _dbus_assert (type == DBUS_TYPE_STRING);
1775 return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
1780 * Returns the name and data from a named type that an
1781 * iterator may point to. Note that you need to check that
1782 * the iterator points to a named type before using this
1785 * @see dbus_message_iter_get_arg_type
1786 * @param iter the message iter
1787 * @param value return location for data
1788 * @param len return location for length of data
1789 * @returns the named type name as a string
1793 dbus_message_iter_get_named (DBusMessageIter *iter,
1794 unsigned char **value,
1797 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1801 dbus_message_iter_check (real);
1803 pos = dbus_message_iter_get_data_start (real, &type);
1805 _dbus_assert (type == DBUS_TYPE_NAMED);
1807 name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
1813 if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
1814 pos + 1, NULL, value, len))
1824 * Returns the byte value that an iterator may point to.
1825 * Note that you need to check that the iterator points to
1826 * a byte value before using this function.
1828 * @see dbus_message_iter_get_arg_type
1829 * @param iter the message iter
1830 * @returns the byte value
1833 dbus_message_iter_get_byte (DBusMessageIter *iter)
1835 unsigned char value;
1836 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1839 dbus_message_iter_check (real);
1841 pos = dbus_message_iter_get_data_start (real, &type);
1843 _dbus_assert (type == DBUS_TYPE_BYTE);
1845 value = _dbus_string_get_byte (&real->message->body, pos);
1852 * Returns the boolean value that an iterator may point to.
1853 * Note that you need to check that the iterator points to
1854 * a boolean value before using this function.
1856 * @see dbus_message_iter_get_arg_type
1857 * @param iter the message iter
1858 * @returns the boolean value
1861 dbus_message_iter_get_boolean (DBusMessageIter *iter)
1863 unsigned char value;
1864 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1867 dbus_message_iter_check (real);
1869 pos = dbus_message_iter_get_data_start (real, &type);
1871 _dbus_assert (type == DBUS_TYPE_BOOLEAN);
1873 value = _dbus_string_get_byte (&real->message->body, pos);
1879 * Returns the 32 bit signed integer value that an iterator may point to.
1880 * Note that you need to check that the iterator points to
1881 * an integer value before using this function.
1883 * @see dbus_message_iter_get_arg_type
1884 * @param iter the message iter
1885 * @returns the integer
1888 dbus_message_iter_get_int32 (DBusMessageIter *iter)
1890 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1893 dbus_message_iter_check (real);
1895 pos = dbus_message_iter_get_data_start (real, &type);
1897 _dbus_assert (type == DBUS_TYPE_INT32);
1899 return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
1904 * Returns the 32 bit unsigned integer value that an iterator may point to.
1905 * Note that you need to check that the iterator points to
1906 * an unsigned integer value before using this function.
1908 * @see dbus_message_iter_get_arg_type
1909 * @param iter the message iter
1910 * @returns the integer
1913 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
1915 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1918 dbus_message_iter_check (real);
1920 pos = dbus_message_iter_get_data_start (real, &type);
1922 _dbus_assert (type == DBUS_TYPE_UINT32);
1924 return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
1929 * Returns the double value that an iterator may point to.
1930 * Note that you need to check that the iterator points to
1931 * a string value before using this function.
1933 * @see dbus_message_iter_get_arg_type
1934 * @param iter the message iter
1935 * @returns the double
1938 dbus_message_iter_get_double (DBusMessageIter *iter)
1940 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1943 dbus_message_iter_check (real);
1945 pos = dbus_message_iter_get_data_start (real, &type);
1947 _dbus_assert (type == DBUS_TYPE_DOUBLE);
1949 return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
1954 * Initializes an iterator for the array that the iterator
1955 * may point to. Note that you need to check that the iterator
1956 * points to an array prior to using this function.
1958 * The array element type is returned in array_type, and the array
1959 * iterator can only be used to get that type of data.
1961 * @param iter the iterator
1962 * @param array_iter pointer to an iterator to initialize
1963 * @param array_type gets set to the type of the array elements
1964 * @returns #TRUE on success
1967 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
1968 DBusMessageIter *array_iter,
1971 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1972 DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
1973 int type, pos, len_pos, len;
1977 dbus_message_iter_check (real);
1979 pos = dbus_message_iter_get_data_start (real, &type);
1981 _dbus_assert (type == DBUS_TYPE_ARRAY);
1983 data = _dbus_string_get_const_data_len (&real->message->body,
1986 if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1987 _array_type = *data;
1991 len_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t));
1992 len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
1995 array_real->parent_iter = real;
1996 array_real->message = real->message;
1997 array_real->changed_stamp = real->message->changed_stamp;
1999 array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
2000 array_real->pos = pos;
2001 array_real->end = pos + len;
2003 array_real->container_type = _array_type;
2004 array_real->container_start = pos;
2005 array_real->container_length_pos = len_pos;
2006 array_real->wrote_dict_key = 0;
2008 if (array_type != NULL)
2009 *array_type = _array_type;
2016 * Initializes an iterator for the dict that the iterator
2017 * may point to. Note that you need to check that the iterator
2018 * points to a dict prior to using this function.
2020 * @param iter the iterator
2021 * @param dict_iter pointer to an iterator to initialize
2022 * @returns #TRUE on success
2025 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
2026 DBusMessageIter *dict_iter)
2028 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2029 DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
2030 int type, pos, len_pos, len;
2032 dbus_message_iter_check (real);
2034 pos = dbus_message_iter_get_data_start (real, &type);
2036 _dbus_assert (type == DBUS_TYPE_DICT);
2038 len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
2039 len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
2042 dict_real->parent_iter = real;
2043 dict_real->message = real->message;
2044 dict_real->changed_stamp = real->message->changed_stamp;
2046 dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
2047 dict_real->pos = pos;
2048 dict_real->end = pos + len;
2050 dict_real->container_type = 0;
2051 dict_real->container_start = pos;
2052 dict_real->container_length_pos = len_pos;
2053 dict_real->wrote_dict_key = 0;
2059 * Returns the byte array that the iterator may point to.
2060 * Note that you need to check that the iterator points
2061 * to a byte array prior to using this function.
2063 * @param iter the iterator
2064 * @param value return location for array values
2065 * @param len return location for length of byte array
2066 * @returns #TRUE on success
2069 dbus_message_iter_get_byte_array (DBusMessageIter *iter,
2070 unsigned char **value,
2073 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2077 dbus_message_iter_check (real);
2079 pos = dbus_message_iter_get_data_start (real, &type);
2081 _dbus_assert (type == DBUS_TYPE_ARRAY);
2083 data = _dbus_string_get_const_data_len (&real->message->body,
2087 _dbus_assert (*data == DBUS_TYPE_BYTE);
2089 if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
2090 pos + 1, NULL, value, len))
2097 * Returns the boolean array that the iterator may point to. Note that
2098 * you need to check that the iterator points to an array of the
2099 * correct type prior to using this function.
2101 * @param iter the iterator
2102 * @param value return location for the array
2103 * @param len return location for the array length
2104 * @returns #TRUE on success
2107 dbus_message_iter_get_boolean_array (DBusMessageIter *iter,
2108 unsigned char **value,
2111 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2115 dbus_message_iter_check (real);
2117 pos = dbus_message_iter_get_data_start (real, &type);
2119 _dbus_assert (type == DBUS_TYPE_ARRAY);
2121 data = _dbus_string_get_const_data_len (&real->message->body,
2125 _dbus_assert (*data == DBUS_TYPE_BOOLEAN);
2127 if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
2128 pos + 1, NULL, value, len))
2135 * Returns the 32 bit signed integer array that the iterator may point
2136 * to. Note that you need to check that the iterator points to an
2137 * array of the correct type prior to using this function.
2139 * @param iter the iterator
2140 * @param value return location for the array
2141 * @param len return location for the array length
2142 * @returns #TRUE on success
2145 dbus_message_iter_get_int32_array (DBusMessageIter *iter,
2146 dbus_int32_t **value,
2149 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2153 dbus_message_iter_check (real);
2155 pos = dbus_message_iter_get_data_start (real, &type);
2157 _dbus_assert (type == DBUS_TYPE_ARRAY);
2159 data = _dbus_string_get_const_data_len (&real->message->body,
2163 _dbus_assert (*data == DBUS_TYPE_INT32);
2165 if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
2166 pos + 1, NULL, value, len))
2173 * Returns the 32 bit unsigned integer array that the iterator may point
2174 * to. Note that you need to check that the iterator points to an
2175 * array of the correct type prior to using this function.
2177 * @param iter the iterator
2178 * @param value return location for the array
2179 * @param len return location for the array length
2180 * @returns #TRUE on success
2183 dbus_message_iter_get_uint32_array (DBusMessageIter *iter,
2184 dbus_uint32_t **value,
2187 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2191 dbus_message_iter_check (real);
2193 pos = dbus_message_iter_get_data_start (real, &type);
2195 _dbus_assert (type == DBUS_TYPE_ARRAY);
2197 data = _dbus_string_get_const_data_len (&real->message->body,
2201 _dbus_assert (*data == DBUS_TYPE_UINT32);
2203 if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
2204 pos + 1, NULL, value, len))
2211 * Returns the double array that the iterator may point to. Note that
2212 * you need to check that the iterator points to an array of the
2213 * correct type prior to using this function.
2215 * @param iter the iterator
2216 * @param value return location for the array
2217 * @param len return location for the array length
2218 * @returns #TRUE on success
2221 dbus_message_iter_get_double_array (DBusMessageIter *iter,
2225 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2229 dbus_message_iter_check (real);
2231 pos = dbus_message_iter_get_data_start (real, &type);
2233 _dbus_assert (type == DBUS_TYPE_ARRAY);
2235 data = _dbus_string_get_const_data_len (&real->message->body,
2239 _dbus_assert (*data == DBUS_TYPE_DOUBLE);
2241 if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
2242 pos + 1, NULL, value, len))
2249 * Returns the string array that the iterator may point to.
2250 * Note that you need to check that the iterator points
2251 * to a byte array prior to using this function.
2253 * The returned value is a #NULL-terminated array of strings.
2254 * Each string is a separate malloc block, and the array
2255 * itself is a malloc block. You can free this type of
2256 * string array with dbus_free_string_array().
2258 * @param iter the iterator
2259 * @param value return location for string values
2260 * @param len return location for length of byte array
2261 * @returns #TRUE on success
2264 dbus_message_iter_get_string_array (DBusMessageIter *iter,
2268 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2272 dbus_message_iter_check (real);
2274 pos = dbus_message_iter_get_data_start (real, &type);
2276 _dbus_assert (type == DBUS_TYPE_ARRAY);
2278 data = _dbus_string_get_const_data_len (&real->message->body,
2282 _dbus_assert (*data == DBUS_TYPE_STRING);
2284 if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
2285 pos + 1, NULL, value, len))
2292 * Returns the key name fot the dict entry that an iterator
2293 * may point to. Note that you need to check that the iterator
2294 * points to a dict entry before using this function.
2296 * @see dbus_message_iter_init_dict_iterator
2297 * @param iter the message iter
2298 * @returns the key name
2301 dbus_message_iter_get_dict_key (DBusMessageIter *iter)
2303 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2305 dbus_message_iter_check (real);
2307 _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
2309 return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
2314 * Initializes a DBusMessageIter pointing to the end of the
2315 * message. This iterator can be used to append data to the
2318 * @param message the message
2319 * @param _iter pointer to an iterator to initialize
2322 dbus_message_append_iter_init (DBusMessage *message,
2323 DBusMessageIter *iter)
2325 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2327 real->message = message;
2328 real->parent_iter = NULL;
2329 real->changed_stamp = message->changed_stamp;
2331 real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
2332 real->end = _dbus_string_get_length (&real->message->body);
2333 real->pos = real->end;
2335 real->container_type = 0;
2336 real->container_length_pos = 0;
2337 real->wrote_dict_key = 0;
2341 dbus_message_iter_append_check (DBusMessageRealIter *iter)
2343 _dbus_assert (!iter->message->locked);
2345 if (iter->changed_stamp != iter->message->changed_stamp)
2346 _dbus_warn ("dbus iterator check failed: invalid iterator");
2348 if (iter->pos != iter->end)
2349 _dbus_warn ("dbus iterator check failed: can only append at end of message");
2351 if (iter->pos != _dbus_string_get_length (&iter->message->body))
2352 _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
2356 dbus_message_iter_append_type (DBusMessageRealIter *iter,
2361 case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
2362 if (!_dbus_string_append_byte (&iter->message->body, type))
2366 case DBUS_MESSAGE_ITER_TYPE_ARRAY:
2367 if (type != iter->container_type)
2369 _dbus_warn ("Appended element of wrong type for array\n");
2374 case DBUS_MESSAGE_ITER_TYPE_DICT:
2375 if (!iter->wrote_dict_key)
2377 _dbus_warn ("Appending dict data before key name\n");
2381 if (!_dbus_string_append_byte (&iter->message->body, type))
2387 _dbus_assert_not_reached ("Invalid iter type");
2395 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
2397 iter->changed_stamp = iter->message->changed_stamp;
2399 /* Set new end of iter */
2400 iter->end = _dbus_string_get_length (&iter->message->body);
2401 iter->pos = iter->end;
2403 /* Set container length */
2404 if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
2405 iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
2406 _dbus_marshal_set_uint32 (&iter->message->body,
2407 iter->message->byte_order,
2408 iter->container_length_pos,
2409 iter->end - iter->container_start);
2411 if (iter->parent_iter)
2412 dbus_message_iter_update_after_change (iter->parent_iter);
2416 dbus_message_iter_append_done (DBusMessageRealIter *iter)
2418 iter->message->changed_stamp++;
2419 dbus_message_iter_update_after_change (iter);
2420 iter->wrote_dict_key = FALSE;
2424 * Appends a nil value to the message
2426 * @param iter an iterator pointing to the end of the message
2427 * @returns #TRUE on success
2430 dbus_message_iter_append_nil (DBusMessageIter *iter)
2432 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2434 dbus_message_iter_append_check (real);
2436 if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
2439 dbus_message_iter_append_done (real);
2445 * Appends a boolean value to the message
2447 * @param iter an iterator pointing to the end of the message
2448 * @param value the boolean value
2449 * @returns #TRUE on success
2452 dbus_message_iter_append_boolean (DBusMessageIter *iter,
2455 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2457 dbus_message_iter_append_check (real);
2459 if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
2462 if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
2464 _dbus_string_set_length (&real->message->body, real->pos);
2468 dbus_message_iter_append_done (real);
2474 * Appends a byte to the message
2476 * @param iter an iterator pointing to the end of the message
2477 * @param value the byte value
2478 * @returns #TRUE on success
2481 dbus_message_iter_append_byte (DBusMessageIter *iter,
2482 unsigned char value)
2484 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2486 dbus_message_iter_append_check (real);
2488 if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
2491 if (!_dbus_string_append_byte (&real->message->body, value))
2493 _dbus_string_set_length (&real->message->body, real->pos);
2497 dbus_message_iter_append_done (real);
2504 * Appends a 32 bit signed integer to the message.
2506 * @param iter an iterator pointing to the end of the message
2507 * @param value the integer value
2508 * @returns #TRUE on success
2511 dbus_message_iter_append_int32 (DBusMessageIter *iter,
2514 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2516 dbus_message_iter_append_check (real);
2518 if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT32))
2521 if (!_dbus_marshal_int32 (&real->message->body, real->message->byte_order, value))
2523 _dbus_string_set_length (&real->message->body, real->pos);
2527 dbus_message_iter_append_done (real);
2533 * Appends a 32 bit unsigned integer to the message.
2535 * @param iter an iterator pointing to the end of the message
2536 * @param value the integer value
2537 * @returns #TRUE on success
2540 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
2541 dbus_uint32_t value)
2543 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2545 dbus_message_iter_append_check (real);
2547 if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
2550 if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
2552 _dbus_string_set_length (&real->message->body, real->pos);
2556 dbus_message_iter_append_done (real);
2562 * Appends a double value to the message.
2564 * @param iter an iterator pointing to the end of the message
2565 * @param value the double value
2566 * @returns #TRUE on success
2569 dbus_message_iter_append_double (DBusMessageIter *iter,
2572 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2574 dbus_message_iter_append_check (real);
2576 if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
2579 if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
2581 _dbus_string_set_length (&real->message->body, real->pos);
2585 dbus_message_iter_append_done (real);
2591 * Appends a UTF-8 string to the message.
2593 * @param iter an iterator pointing to the end of the message
2594 * @param value the string
2595 * @returns #TRUE on success
2598 dbus_message_iter_append_string (DBusMessageIter *iter,
2601 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2603 dbus_message_iter_append_check (real);
2605 if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
2608 if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
2610 _dbus_string_set_length (&real->message->body, real->pos);
2614 dbus_message_iter_append_done (real);
2620 * Appends a named type data chunk to the message.
2622 * @param iter an iterator pointing to the end of the message
2623 * @param name the name of the type
2625 * @returns #TRUE on success
2628 dbus_message_iter_append_named (DBusMessageIter *iter,
2630 const unsigned char *data,
2633 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2635 dbus_message_iter_append_check (real);
2637 if (!dbus_message_iter_append_type (real, DBUS_TYPE_NAMED))
2640 if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, data))
2642 _dbus_string_set_length (&real->message->body, real->pos);
2646 if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
2648 _dbus_string_set_length (&real->message->body, real->pos);
2652 dbus_message_iter_append_done (real);
2659 * Appends a dict key name to the message. The iterator used
2660 * must point to a dict.
2662 * @param iter an iterator pointing to the end of the message
2663 * @param value the string
2664 * @returns #TRUE on success
2667 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
2670 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2672 dbus_message_iter_append_check (real);
2673 _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
2675 if (real->wrote_dict_key)
2677 _dbus_warn ("Appendinging multiple dict key names\n");
2681 if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
2686 dbus_message_iter_append_done (real);
2687 real->wrote_dict_key = TRUE;
2693 * Appends an array to the message and initializes an iterator that
2694 * can be used to append to the array.
2696 * @param iter an iterator pointing to the end of the message
2697 * @param array_iter pointer to an iter that will be initialized
2698 * @param element_type the type of the array elements
2699 * @returns #TRUE on success
2702 dbus_message_iter_append_array (DBusMessageIter *iter,
2703 DBusMessageIter *array_iter,
2706 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2707 DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
2710 dbus_message_iter_append_check (real);
2712 if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2715 if (!_dbus_string_append_byte (&real->message->body, element_type))
2717 _dbus_string_set_length (&real->message->body, real->pos);
2721 len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
2723 /* Empty length for now, backfill later */
2724 if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
2726 _dbus_string_set_length (&real->message->body, real->pos);
2730 array_real->parent_iter = real;
2731 array_real->message = real->message;
2732 array_real->changed_stamp = real->message->changed_stamp;
2734 array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
2735 array_real->pos = _dbus_string_get_length (&real->message->body);
2736 array_real->end = array_real->end;
2738 array_real->container_type = element_type;
2739 array_real->container_start = array_real->pos;
2740 array_real->container_length_pos = len_pos;
2741 array_real->wrote_dict_key = 0;
2743 dbus_message_iter_append_done (array_real);
2749 * Appends a dict to the message and initializes an iterator that
2750 * can be used to append to the dict.
2752 * @param iter an iterator pointing to the end of the message
2753 * @param array_iter pointer to an iter that will be initialized
2754 * @param element_type the type of the array elements
2755 * @returns #TRUE on success
2758 dbus_message_iter_append_dict (DBusMessageIter *iter,
2759 DBusMessageIter *dict_iter)
2761 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2762 DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
2765 dbus_message_iter_append_check (real);
2767 if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
2770 len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
2772 /* Empty length for now, backfill later */
2773 if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
2775 _dbus_string_set_length (&real->message->body, real->pos);
2779 dict_real->parent_iter = real;
2780 dict_real->message = real->message;
2781 dict_real->changed_stamp = real->message->changed_stamp;
2783 dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
2784 dict_real->pos = _dbus_string_get_length (&real->message->body);
2785 dict_real->end = dict_real->end;
2787 dict_real->container_type = 0;
2788 dict_real->container_start = dict_real->pos;
2789 dict_real->container_length_pos = len_pos;
2790 dict_real->wrote_dict_key = 0;
2792 dbus_message_iter_append_done (dict_real);
2799 * Appends a boolean array to the message.
2801 * @param iter an iterator pointing to the end of the message
2802 * @param value the array
2803 * @param len the length of the array
2804 * @returns #TRUE on success
2807 dbus_message_iter_append_boolean_array (DBusMessageIter *iter,
2808 unsigned const char *value,
2811 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2813 dbus_message_iter_append_check (real);
2815 if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2818 if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BOOLEAN))
2820 _dbus_string_set_length (&real->message->body, real->pos);
2824 if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
2826 _dbus_string_set_length (&real->message->body, real->pos);
2830 dbus_message_iter_append_done (real);
2836 * Appends a 32 bit signed integer array to the message.
2838 * @param iter an iterator pointing to the end of the message
2839 * @param value the array
2840 * @param len the length of the array
2841 * @returns #TRUE on success
2844 dbus_message_iter_append_int32_array (DBusMessageIter *iter,
2845 const dbus_int32_t *value,
2848 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2850 dbus_message_iter_append_check (real);
2852 if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2855 if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_INT32))
2857 _dbus_string_set_length (&real->message->body, real->pos);
2861 if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
2863 _dbus_string_set_length (&real->message->body, real->pos);
2867 dbus_message_iter_append_done (real);
2873 * Appends a 32 bit unsigned integer array to the message.
2875 * @param iter an iterator pointing to the end of the message
2876 * @param value the array
2877 * @param len the length of the array
2878 * @returns #TRUE on success
2881 dbus_message_iter_append_uint32_array (DBusMessageIter *iter,
2882 const dbus_uint32_t *value,
2885 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2887 dbus_message_iter_append_check (real);
2889 if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2892 if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_UINT32))
2894 _dbus_string_set_length (&real->message->body, real->pos);
2898 if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
2900 _dbus_string_set_length (&real->message->body, real->pos);
2904 dbus_message_iter_append_done (real);
2910 * Appends a double array to the message.
2912 * @param iter an iterator pointing to the end of the message
2913 * @param value the array
2914 * @param len the length of the array
2915 * @returns #TRUE on success
2918 dbus_message_iter_append_double_array (DBusMessageIter *iter,
2919 const double *value,
2922 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2924 dbus_message_iter_append_check (real);
2926 if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2929 if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_DOUBLE))
2931 _dbus_string_set_length (&real->message->body, real->pos);
2935 if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
2937 _dbus_string_set_length (&real->message->body, real->pos);
2941 dbus_message_iter_append_done (real);
2947 * Appends a byte array to the message.
2949 * @param iter an iterator pointing to the end of the message
2950 * @param value the array
2951 * @param len the length of the array
2952 * @returns #TRUE on success
2955 dbus_message_iter_append_byte_array (DBusMessageIter *iter,
2956 unsigned const char *value,
2959 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2961 dbus_message_iter_append_check (real);
2963 if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2966 if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BYTE))
2968 _dbus_string_set_length (&real->message->body, real->pos);
2972 if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
2974 _dbus_string_set_length (&real->message->body, real->pos);
2978 dbus_message_iter_append_done (real);
2984 * Appends a string array to the message.
2986 * @param iter an iterator pointing to the end of the message
2987 * @param value the array
2988 * @param len the length of the array
2989 * @returns #TRUE on success
2992 dbus_message_iter_append_string_array (DBusMessageIter *iter,
2996 DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2998 dbus_message_iter_append_check (real);
3000 if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
3003 if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BYTE))
3005 _dbus_string_set_length (&real->message->body, real->pos);
3009 if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
3011 _dbus_string_set_length (&real->message->body, real->pos);
3015 dbus_message_iter_append_done (real);
3021 * Sets the message sender.
3023 * @param message the message
3024 * @param sender the sender
3025 * @returns #FALSE if not enough memory
3028 dbus_message_set_sender (DBusMessage *message,
3031 _dbus_assert (!message->locked);
3035 delete_string_field (message, FIELD_SENDER);
3040 return set_string_field (message,
3047 * Sets a flag indicating that the message is an error reply
3048 * message, i.e. an "exception" rather than a normal response.
3050 * @param message the message
3051 * @param is_error_reply #TRUE if this is an error message.
3054 dbus_message_set_is_error (DBusMessage *message,
3055 dbus_bool_t is_error_reply)
3059 _dbus_assert (!message->locked);
3061 header = _dbus_string_get_data_len (&message->header, 1, 1);
3064 *header |= DBUS_HEADER_FLAG_ERROR;
3066 *header &= ~DBUS_HEADER_FLAG_ERROR;
3070 * Returns #TRUE if the message is an error
3071 * reply to some previous message we sent.
3073 * @param message the message
3074 * @returns #TRUE if the message is an error
3077 dbus_message_get_is_error (DBusMessage *message)
3081 header = _dbus_string_get_const_data_len (&message->header, 1, 1);
3083 return (*header & DBUS_HEADER_FLAG_ERROR) != 0;
3087 * Gets the service which originated this message,
3088 * or #NULL if unknown or inapplicable.
3090 * @param message the message
3091 * @returns the service name or #NULL
3094 dbus_message_get_sender (DBusMessage *message)
3096 return get_string_field (message, FIELD_SENDER, NULL);
3100 * Checks whether the message has the given name.
3101 * If the message has no name or has a different
3102 * name, returns #FALSE.
3104 * @param message the message
3105 * @param name the name to check (must not be #NULL)
3107 * @returns #TRUE if the message has the given name
3110 dbus_message_name_is (DBusMessage *message,
3115 _dbus_assert (name != NULL);
3117 n = dbus_message_get_name (message);
3119 if (n && strcmp (n, name) == 0)
3126 * Checks whether the message was sent to the given service. If the
3127 * message has no service specified or has a different name, returns
3130 * @param message the message
3131 * @param service the service to check (must not be #NULL)
3133 * @returns #TRUE if the message has the given destination service
3136 dbus_message_service_is (DBusMessage *message,
3137 const char *service)
3141 _dbus_assert (service != NULL);
3143 s = dbus_message_get_service (message);
3145 if (s && strcmp (s, service) == 0)
3152 * Checks whether the message has the given service as its sender. If
3153 * the message has no sender specified or has a different sender,
3154 * returns #FALSE. Note that if a peer application owns multiple
3155 * services, its messages will have only one of those services as the
3156 * sender (usually the base service). So you can't use this
3157 * function to prove the sender didn't own service Foo, you can
3158 * only use it to prove that it did.
3160 * @param message the message
3161 * @param service the service to check (must not be #NULL)
3163 * @returns #TRUE if the message has the given origin service
3166 dbus_message_sender_is (DBusMessage *message,
3167 const char *service)
3171 _dbus_assert (service != NULL);
3173 s = dbus_message_get_sender (message);
3175 if (s && strcmp (s, service) == 0)
3182 * Sets a #DBusError based on the contents of the given
3183 * message. The error is only set if the message
3184 * is an error message, as in dbus_message_get_is_error().
3185 * The name of the error is set to the name of the message,
3186 * and the error message is set to the first argument
3187 * if the argument exists and is a string.
3189 * The return value indicates whether the error was set (the error is
3190 * set if and only if the message is an error message).
3191 * So you can check for an error reply and convert it to DBusError
3194 * @param error the error to set
3195 * @param message the message to set it from
3196 * @returns #TRUE if dbus_message_get_is_error() returns #TRUE for the message
3199 dbus_set_error_from_message (DBusError *error,
3200 DBusMessage *message)
3204 if (!dbus_message_get_is_error (message))
3208 dbus_message_get_args (message, NULL,
3209 DBUS_TYPE_STRING, &str,
3212 dbus_set_error (error, dbus_message_get_name (message),
3213 str ? "%s" : NULL, str);
3223 * @addtogroup DBusMessageInternals
3228 * @typedef DBusMessageLoader
3230 * The DBusMessageLoader object encapsulates the process of converting
3231 * a byte stream into a series of DBusMessage. It buffers the incoming
3232 * bytes as efficiently as possible, and generates a queue of
3233 * messages. DBusMessageLoader is typically used as part of a
3234 * DBusTransport implementation. The DBusTransport then hands off
3235 * the loaded messages to a DBusConnection, making the messages
3236 * visible to the application.
3238 * @todo write tests for break-loader that a) randomly delete header
3239 * fields and b) set string fields to zero-length and other funky
3244 /* we definitely use signed ints for sizes, so don't exceed
3245 * _DBUS_INT_MAX; and add 16 for paranoia, since a message
3246 * over 128M is pretty nuts anyhow.
3250 * The maximum sane message size.
3252 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
3255 * Implementation details of DBusMessageLoader.
3256 * All members are private.
3258 struct DBusMessageLoader
3260 int refcount; /**< Reference count. */
3262 DBusString data; /**< Buffered data */
3264 DBusList *messages; /**< Complete messages. */
3266 long max_message_size; /**< Maximum size of a message */
3268 unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
3270 unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
3274 * The initial buffer size of the message loader.
3276 * @todo this should be based on min header size plus some average
3277 * body size, or something. Or rather, the min header size only, if we
3278 * want to try to read only the header, store that in a DBusMessage,
3279 * then read only the body and store that, etc., depends on
3280 * how we optimize _dbus_message_loader_get_buffer() and what
3281 * the exact message format is.
3283 #define INITIAL_LOADER_DATA_LEN 32
3286 * Creates a new message loader. Returns #NULL if memory can't
3289 * @returns new loader, or #NULL.
3292 _dbus_message_loader_new (void)
3294 DBusMessageLoader *loader;
3296 loader = dbus_new0 (DBusMessageLoader, 1);
3300 loader->refcount = 1;
3302 /* Try to cap message size at something that won't *totally* hose
3303 * the system if we have a couple of them.
3305 loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
3307 if (!_dbus_string_init (&loader->data))
3313 /* preallocate the buffer for speed, ignore failure */
3314 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
3315 _dbus_string_set_length (&loader->data, 0);
3321 * Increments the reference count of the loader.
3323 * @param loader the loader.
3326 _dbus_message_loader_ref (DBusMessageLoader *loader)
3328 loader->refcount += 1;
3332 * Decrements the reference count of the loader and finalizes the
3333 * loader when the count reaches zero.
3335 * @param loader the loader.
3338 _dbus_message_loader_unref (DBusMessageLoader *loader)
3340 loader->refcount -= 1;
3341 if (loader->refcount == 0)
3343 _dbus_list_foreach (&loader->messages,
3344 (DBusForeachFunction) dbus_message_unref,
3346 _dbus_list_clear (&loader->messages);
3347 _dbus_string_free (&loader->data);
3353 * Gets the buffer to use for reading data from the network. Network
3354 * data is read directly into an allocated buffer, which is then used
3355 * in the DBusMessage, to avoid as many extra memcpy's as possible.
3356 * The buffer must always be returned immediately using
3357 * _dbus_message_loader_return_buffer(), even if no bytes are
3358 * successfully read.
3360 * @todo this function can be a lot more clever. For example
3361 * it can probably always return a buffer size to read exactly
3362 * the body of the next message, thus avoiding any memory wastage
3365 * @todo we need to enforce a max length on strings in header fields.
3367 * @param loader the message loader.
3368 * @param buffer the buffer
3371 _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
3372 DBusString **buffer)
3374 _dbus_assert (!loader->buffer_outstanding);
3376 *buffer = &loader->data;
3378 loader->buffer_outstanding = TRUE;
3382 * The smallest header size that can occur.
3383 * (It won't be valid)
3385 #define DBUS_MINIMUM_HEADER_SIZE 16
3387 /** Pack four characters as in "abcd" into a uint32 */
3388 #define FOUR_CHARS_TO_UINT32(a, b, c, d) \
3389 ((((dbus_uint32_t)a) << 24) | \
3390 (((dbus_uint32_t)b) << 16) | \
3391 (((dbus_uint32_t)c) << 8) | \
3394 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
3395 #define DBUS_HEADER_FIELD_NAME_AS_UINT32 \
3396 FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
3398 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
3399 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
3400 FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
3402 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
3403 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32 \
3404 FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
3406 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
3407 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32 \
3408 FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
3410 /* FIXME impose max length on name, srvc, sndr */
3412 decode_header_data (const DBusString *data,
3415 HeaderField fields[FIELD_LAST],
3416 int *message_padding)
3423 if (header_len < 16)
3427 while (i < FIELD_LAST)
3429 fields[i].offset = -1;
3433 fields[FIELD_HEADER_LENGTH].offset = 4;
3434 fields[FIELD_BODY_LENGTH].offset = 8;
3435 fields[FIELD_CLIENT_SERIAL].offset = 12;
3437 /* Now handle the named fields. A real named field is at least 4
3438 * bytes for the name, plus a type code (1 byte) plus padding. So
3439 * if we have less than 8 bytes left, it must be alignment padding,
3440 * not a field. While >= 8 bytes can't be entirely alignment
3444 while ((pos + 7) < header_len)
3446 pos = _DBUS_ALIGN_VALUE (pos, 4);
3448 if ((pos + 4) > header_len)
3451 field =_dbus_string_get_const_data_len (data, pos, 4);
3454 _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
3456 /* I believe FROM_BE is right, but if not we'll find out
3459 switch (DBUS_UINT32_FROM_BE (*(int*)field))
3461 case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
3462 if (fields[FIELD_SERVICE].offset >= 0)
3464 _dbus_verbose ("%s field provided twice\n",
3465 DBUS_HEADER_FIELD_SERVICE);
3469 fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3471 _dbus_verbose ("Found service name at offset %d\n",
3472 fields[FIELD_SERVICE].offset);
3476 case DBUS_HEADER_FIELD_NAME_AS_UINT32:
3477 if (fields[FIELD_NAME].offset >= 0)
3479 _dbus_verbose ("%s field provided twice\n",
3480 DBUS_HEADER_FIELD_NAME);
3484 fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3487 _dbus_verbose ("Found message name at offset %d\n",
3488 fields[FIELD_NAME].offset);
3491 case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
3492 if (fields[FIELD_SENDER].offset >= 0)
3494 _dbus_verbose ("%s field provided twice\n",
3495 DBUS_HEADER_FIELD_SENDER);
3499 fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3501 _dbus_verbose ("Found sender name at offset %d\n",
3502 fields[FIELD_NAME].offset);
3505 case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
3506 if (fields[FIELD_REPLY_SERIAL].offset >= 0)
3508 _dbus_verbose ("%s field provided twice\n",
3509 DBUS_HEADER_FIELD_REPLY);
3513 fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3515 _dbus_verbose ("Found reply serial at offset %d\n",
3516 fields[FIELD_REPLY_SERIAL].offset);
3520 _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c at offset %d\n",
3521 field[0], field[1], field[2], field[3], pos);
3524 if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
3526 _dbus_verbose ("Failed to validate type of named header field\n");
3530 if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, pos, &new_pos))
3532 _dbus_verbose ("Failed to validate argument to named header field\n");
3536 if (new_pos > header_len)
3538 _dbus_verbose ("Named header field tries to extend beyond header length\n");
3545 if (pos < header_len)
3547 /* Alignment padding, verify that it's nul */
3548 _dbus_assert ((header_len - pos) < 8);
3550 if (!_dbus_string_validate_nul (data,
3551 pos, (header_len - pos)))
3553 _dbus_verbose ("header alignment padding is not nul\n");
3558 if (fields[FIELD_NAME].offset < 0)
3560 _dbus_verbose ("No %s field provided\n",
3561 DBUS_HEADER_FIELD_NAME);
3565 if (message_padding)
3566 *message_padding = header_len - pos;
3572 * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
3573 * indicating to the loader how many bytes of the buffer were filled
3574 * in. This function must always be called, even if no bytes were
3575 * successfully read.
3577 * @param loader the loader.
3578 * @param buffer the buffer.
3579 * @param bytes_read number of bytes that were read into the buffer.
3582 _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
3586 _dbus_assert (loader->buffer_outstanding);
3587 _dbus_assert (buffer == &loader->data);
3589 loader->buffer_outstanding = FALSE;
3593 * Converts buffered data into messages.
3595 * @param loader the loader.
3596 * @returns #TRUE if we had enough memory to finish.
3599 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
3601 if (loader->corrupted)
3604 while (_dbus_string_get_length (&loader->data) >= 16)
3606 DBusMessage *message;
3607 const char *header_data;
3608 int byte_order, header_len, body_len, header_padding;
3609 dbus_uint32_t header_len_unsigned, body_len_unsigned;
3611 header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
3613 _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
3615 if (header_data[2] != DBUS_MAJOR_PROTOCOL_VERSION)
3617 _dbus_verbose ("Message has protocol version %d ours is %d\n",
3618 (int) header_data[2], DBUS_MAJOR_PROTOCOL_VERSION);
3619 loader->corrupted = TRUE;
3623 byte_order = header_data[0];
3625 if (byte_order != DBUS_LITTLE_ENDIAN &&
3626 byte_order != DBUS_BIG_ENDIAN)
3628 _dbus_verbose ("Message with bad byte order '%c' received\n",
3630 loader->corrupted = TRUE;
3634 header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
3635 body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
3637 if (header_len_unsigned < 16)
3639 _dbus_verbose ("Message had broken too-small header length %u\n",
3640 header_len_unsigned);
3641 loader->corrupted = TRUE;
3645 if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
3646 body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
3648 _dbus_verbose ("Header or body length too large (%u %u)\n",
3649 header_len_unsigned,
3651 loader->corrupted = TRUE;
3655 /* Now that we know the values are in signed range, get
3656 * rid of stupid unsigned, just causes bugs
3658 header_len = header_len_unsigned;
3659 body_len = body_len_unsigned;
3661 if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
3664 _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
3666 loader->corrupted = TRUE;
3670 if (header_len + body_len > loader->max_message_size)
3672 _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
3673 header_len, body_len, loader->max_message_size);
3674 loader->corrupted = TRUE;
3678 if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
3680 HeaderField fields[FIELD_LAST];
3685 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);
3687 if (!decode_header_data (&loader->data, header_len, byte_order,
3688 fields, &header_padding))
3690 _dbus_verbose ("Header was invalid\n");
3691 loader->corrupted = TRUE;
3695 next_arg = header_len;
3696 while (next_arg < (header_len + body_len))
3699 int prev = next_arg;
3701 if (!_dbus_marshal_validate_type (&loader->data, next_arg,
3704 _dbus_verbose ("invalid typecode at offset %d\n", prev);
3705 loader->corrupted = TRUE;
3709 if (!_dbus_marshal_validate_arg (&loader->data,
3716 _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
3717 loader->corrupted = TRUE;
3721 _dbus_assert (next_arg > prev);
3724 if (next_arg > (header_len + body_len))
3726 _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
3727 next_arg, header_len, body_len,
3728 header_len + body_len);
3729 loader->corrupted = TRUE;
3733 message = dbus_message_new_empty_header ();
3734 if (message == NULL)
3737 message->byte_order = byte_order;
3738 message->header_padding = header_padding;
3740 /* Copy in the offsets we found */
3742 while (i < FIELD_LAST)
3744 message->header_fields[i] = fields[i];
3748 if (!_dbus_list_append (&loader->messages, message))
3750 dbus_message_unref (message);
3754 _dbus_assert (_dbus_string_get_length (&message->header) == 0);
3755 _dbus_assert (_dbus_string_get_length (&message->body) == 0);
3757 _dbus_assert (_dbus_string_get_length (&loader->data) >=
3758 (header_len + body_len));
3760 if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
3762 _dbus_list_remove_last (&loader->messages, message);
3763 dbus_message_unref (message);
3767 if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
3771 /* put the header back, we'll try again later */
3772 result = _dbus_string_copy_len (&message->header, 0, header_len,
3774 _dbus_assert (result); /* because DBusString never reallocs smaller */
3776 _dbus_list_remove_last (&loader->messages, message);
3777 dbus_message_unref (message);
3781 _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
3782 _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
3784 /* Fill in caches */
3785 message->reply_serial = get_int_field (message,
3786 FIELD_REPLY_SERIAL);
3787 message->client_serial = get_int_field (message,
3788 FIELD_CLIENT_SERIAL);
3790 _dbus_verbose ("Loaded message %p\n", message);
3800 * Peeks at first loaded message, returns #NULL if no messages have
3803 * @param loader the loader.
3804 * @returns the next message, or #NULL if none.
3807 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
3809 if (loader->messages)
3810 return loader->messages->data;
3816 * Pops a loaded message (passing ownership of the message
3817 * to the caller). Returns #NULL if no messages have been
3820 * @param loader the loader.
3821 * @returns the next message, or #NULL if none.
3824 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
3826 return _dbus_list_pop_first (&loader->messages);
3830 * Pops a loaded message inside a list link (passing ownership of the
3831 * message and link to the caller). Returns #NULL if no messages have
3834 * @param loader the loader.
3835 * @returns the next message link, or #NULL if none.
3838 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
3840 return _dbus_list_pop_first_link (&loader->messages);
3844 * Checks whether the loader is confused due to bad data.
3845 * If messages are received that are invalid, the
3846 * loader gets confused and gives up permanently.
3847 * This state is called "corrupted."
3849 * @param loader the loader
3850 * @returns #TRUE if the loader is hosed.
3853 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
3855 return loader->corrupted;
3859 * Sets the maximum size message we allow.
3861 * @param loader the loader
3862 * @param size the max message size in bytes
3865 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader,
3868 if (size > MAX_SANE_MESSAGE_SIZE)
3870 _dbus_verbose ("clamping requested max message size %ld to %d\n",
3871 size, MAX_SANE_MESSAGE_SIZE);
3872 size = MAX_SANE_MESSAGE_SIZE;
3874 loader->max_message_size = size;
3878 * Gets the maximum allowed message size in bytes.
3880 * @param loader the loader
3881 * @returns max size in bytes
3884 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader)
3886 return loader->max_message_size;
3890 #ifdef DBUS_BUILD_TESTS
3891 #include "dbus-test.h"
3895 message_iter_test (DBusMessage *message)
3897 DBusMessageIter iter, dict, array;
3900 dbus_message_iter_init (message, &iter);
3903 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
3904 _dbus_assert_not_reached ("Argument type isn't string");
3906 str = dbus_message_iter_get_string (&iter);
3907 if (strcmp (str, "Test string") != 0)
3908 _dbus_assert_not_reached ("Strings differ");
3911 if (!dbus_message_iter_next (&iter))
3912 _dbus_assert_not_reached ("Reached end of arguments");
3914 /* Signed integer tests */
3915 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
3916 _dbus_assert_not_reached ("Argument type isn't int32");
3918 if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
3919 _dbus_assert_not_reached ("Signed integers differ");
3921 if (!dbus_message_iter_next (&iter))
3922 _dbus_assert_not_reached ("Reached end of fields");
3924 /* Unsigned integer tests */
3925 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
3926 _dbus_assert_not_reached ("Argument type isn't int32");
3928 if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
3929 _dbus_assert_not_reached ("Unsigned integers differ");
3931 if (!dbus_message_iter_next (&iter))
3932 _dbus_assert_not_reached ("Reached end of arguments");
3935 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
3936 _dbus_assert_not_reached ("Argument type isn't double");
3938 if (dbus_message_iter_get_double (&iter) != 3.14159)
3939 _dbus_assert_not_reached ("Doubles differ");
3941 if (!dbus_message_iter_next (&iter))
3942 _dbus_assert_not_reached ("Reached end of arguments");
3944 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
3945 _dbus_assert_not_reached ("Argument type not an array");
3947 if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_UINT32)
3948 _dbus_assert_not_reached ("Array type not uint32");
3951 if (!dbus_message_iter_init_array_iterator (&iter, &array, NULL))
3952 _dbus_assert_not_reached ("Array init failed");
3954 if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_UINT32)
3955 _dbus_assert_not_reached ("Argument type isn't int32");
3957 if (dbus_message_iter_get_uint32 (&array) != 0x12345678)
3958 _dbus_assert_not_reached ("Unsigned integers differ");
3960 if (!dbus_message_iter_next (&array))
3961 _dbus_assert_not_reached ("Reached end of arguments");
3963 if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_UINT32)
3964 _dbus_assert_not_reached ("Argument type isn't int32");
3966 if (dbus_message_iter_get_uint32 (&array) != 0x23456781)
3967 _dbus_assert_not_reached ("Unsigned integers differ");
3969 if (dbus_message_iter_next (&array))
3970 _dbus_assert_not_reached ("Didn't reach end of arguments");
3972 if (!dbus_message_iter_next (&iter))
3973 _dbus_assert_not_reached ("Reached end of arguments");
3975 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
3976 _dbus_assert_not_reached ("not dict type");
3978 if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
3979 _dbus_assert_not_reached ("dict iter failed");
3981 str = dbus_message_iter_get_dict_key (&dict);
3982 if (str == NULL || strcmp (str, "test") != 0)
3983 _dbus_assert_not_reached ("wrong dict key");
3986 if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
3987 _dbus_assert_not_reached ("wrong dict entry type");
3989 if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
3990 _dbus_assert_not_reached ("wrong dict entry value");
3992 if (dbus_message_iter_next (&dict))
3993 _dbus_assert_not_reached ("Didn't reach end of dict");
3995 if (!dbus_message_iter_next (&iter))
3996 _dbus_assert_not_reached ("Reached end of arguments");
3998 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
3999 _dbus_assert_not_reached ("wrong type after dict");
4001 if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
4002 _dbus_assert_not_reached ("wrong value after dict");
4004 if (dbus_message_iter_next (&iter))
4005 _dbus_assert_not_reached ("Didn't reach end of arguments");
4010 check_message_handling_type (DBusMessageIter *iter,
4013 DBusMessageIter child_iter;
4019 case DBUS_TYPE_BYTE:
4020 dbus_message_iter_get_byte (iter);
4022 case DBUS_TYPE_BOOLEAN:
4023 dbus_message_iter_get_boolean (iter);
4025 case DBUS_TYPE_INT32:
4026 dbus_message_iter_get_int32 (iter);
4028 case DBUS_TYPE_UINT32:
4029 dbus_message_iter_get_uint32 (iter);
4031 case DBUS_TYPE_DOUBLE:
4032 dbus_message_iter_get_double (iter);
4034 case DBUS_TYPE_STRING:
4037 str = dbus_message_iter_get_string (iter);
4040 _dbus_warn ("NULL string in message\n");
4046 case DBUS_TYPE_NAMED:
4049 unsigned char *data;
4052 name = dbus_message_iter_get_named (iter, &data, &len);
4055 _dbus_warn ("error reading name from named type\n");
4062 case DBUS_TYPE_ARRAY:
4066 if (!dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type))
4068 _dbus_warn ("Failed to init array iterator\n");
4072 while (dbus_message_iter_has_next (&child_iter))
4074 if (!check_message_handling_type (&child_iter, array_type))
4076 _dbus_warn ("error in array element\n");
4080 if (!dbus_message_iter_next (&child_iter))
4085 case DBUS_TYPE_DICT:
4090 if (!dbus_message_iter_init_dict_iterator (iter, &child_iter))
4092 _dbus_warn ("Failed to init dict iterator\n");
4096 while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
4098 key = dbus_message_iter_get_dict_key (&child_iter);
4101 _dbus_warn ("error reading dict key\n");
4106 if (!check_message_handling_type (&child_iter, entry_type))
4108 _dbus_warn ("error in dict value\n");
4112 if (!dbus_message_iter_next (&child_iter))
4119 _dbus_warn ("unknown type %d\n", type);
4128 check_message_handling (DBusMessage *message)
4130 DBusMessageIter iter;
4133 dbus_int32_t client_serial;
4137 client_serial = dbus_message_get_serial (message);
4139 /* can't use set_serial due to the assertions at the start of it */
4140 set_int_field (message, FIELD_CLIENT_SERIAL,
4143 if (client_serial != dbus_message_get_serial (message))
4145 _dbus_warn ("get/set cycle for client_serial did not succeed\n");
4149 /* If we implement message_set_arg (message, n, value)
4150 * then we would want to test it here
4153 dbus_message_iter_init (message, &iter);
4154 while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
4157 if (!check_message_handling_type (&iter, type))
4160 if (!dbus_message_iter_next (&iter))
4171 check_have_valid_message (DBusMessageLoader *loader)
4173 DBusMessage *message;
4179 if (!_dbus_message_loader_queue_messages (loader))
4180 _dbus_assert_not_reached ("no memory to queue messages");
4182 if (_dbus_message_loader_get_is_corrupted (loader))
4184 _dbus_warn ("loader corrupted on message that was expected to be valid\n");
4188 message = _dbus_message_loader_pop_message (loader);
4189 if (message == NULL)
4191 _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
4195 if (_dbus_string_get_length (&loader->data) > 0)
4197 _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
4201 /* Verify that we're able to properly deal with the message.
4202 * For example, this would detect improper handling of messages
4203 * in nonstandard byte order.
4205 if (!check_message_handling (message))
4212 dbus_message_unref (message);
4218 check_invalid_message (DBusMessageLoader *loader)
4224 if (!_dbus_message_loader_queue_messages (loader))
4225 _dbus_assert_not_reached ("no memory to queue messages");
4227 if (!_dbus_message_loader_get_is_corrupted (loader))
4229 _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
4240 check_incomplete_message (DBusMessageLoader *loader)
4242 DBusMessage *message;
4248 if (!_dbus_message_loader_queue_messages (loader))
4249 _dbus_assert_not_reached ("no memory to queue messages");
4251 if (_dbus_message_loader_get_is_corrupted (loader))
4253 _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
4257 message = _dbus_message_loader_pop_message (loader);
4258 if (message != NULL)
4260 _dbus_warn ("loaded message that was expected to be incomplete\n");
4268 dbus_message_unref (message);
4273 check_loader_results (DBusMessageLoader *loader,
4274 DBusMessageValidity validity)
4276 if (!_dbus_message_loader_queue_messages (loader))
4277 _dbus_assert_not_reached ("no memory to queue messages");
4281 case _DBUS_MESSAGE_VALID:
4282 return check_have_valid_message (loader);
4283 case _DBUS_MESSAGE_INVALID:
4284 return check_invalid_message (loader);
4285 case _DBUS_MESSAGE_INCOMPLETE:
4286 return check_incomplete_message (loader);
4287 case _DBUS_MESSAGE_UNKNOWN:
4291 _dbus_assert_not_reached ("bad DBusMessageValidity");
4297 * Loads the message in the given message file.
4299 * @param filename filename to load
4300 * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
4301 * @param data string to load message into
4302 * @returns #TRUE if the message was loaded
4305 dbus_internal_do_not_use_load_message_file (const DBusString *filename,
4317 _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
4318 dbus_error_init (&error);
4319 if (!_dbus_file_get_contents (data, filename, &error))
4321 _dbus_warn ("Could not load message file %s: %s\n",
4322 _dbus_string_get_const_data (filename),
4324 dbus_error_free (&error);
4330 if (!_dbus_message_data_load (data, filename))
4332 _dbus_warn ("Could not load message file %s\n",
4333 _dbus_string_get_const_data (filename));
4346 * Tries loading the message in the given message file
4347 * and verifies that DBusMessageLoader can handle it.
4349 * @param filename filename to load
4350 * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
4351 * @param expected_validity what the message has to be like to return #TRUE
4352 * @returns #TRUE if the message has the expected validity
4355 dbus_internal_do_not_use_try_message_file (const DBusString *filename,
4357 DBusMessageValidity expected_validity)
4364 if (!_dbus_string_init (&data))
4365 _dbus_assert_not_reached ("could not allocate string\n");
4367 if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
4371 retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
4377 if (_dbus_string_get_length (&data) > 0)
4378 _dbus_verbose_bytes_of_string (&data, 0,
4379 _dbus_string_get_length (&data));
4381 _dbus_warn ("Failed message loader test on %s\n",
4382 _dbus_string_get_const_data (filename));
4385 _dbus_string_free (&data);
4391 * Tries loading the given message data.
4394 * @param data the message data
4395 * @param expected_validity what the message has to be like to return #TRUE
4396 * @returns #TRUE if the message has the expected validity
4399 dbus_internal_do_not_use_try_message_data (const DBusString *data,
4400 DBusMessageValidity expected_validity)
4402 DBusMessageLoader *loader;
4410 /* Write the data one byte at a time */
4412 loader = _dbus_message_loader_new ();
4414 len = _dbus_string_get_length (data);
4415 for (i = 0; i < len; i++)
4419 _dbus_message_loader_get_buffer (loader, &buffer);
4420 _dbus_string_append_byte (buffer,
4421 _dbus_string_get_byte (data, i));
4422 _dbus_message_loader_return_buffer (loader, buffer, 1);
4425 if (!check_loader_results (loader, expected_validity))
4428 _dbus_message_loader_unref (loader);
4431 /* Write the data all at once */
4433 loader = _dbus_message_loader_new ();
4438 _dbus_message_loader_get_buffer (loader, &buffer);
4439 _dbus_string_copy (data, 0, buffer,
4440 _dbus_string_get_length (buffer));
4441 _dbus_message_loader_return_buffer (loader, buffer, 1);
4444 if (!check_loader_results (loader, expected_validity))
4447 _dbus_message_loader_unref (loader);
4450 /* Write the data 2 bytes at a time */
4452 loader = _dbus_message_loader_new ();
4454 len = _dbus_string_get_length (data);
4455 for (i = 0; i < len; i += 2)
4459 _dbus_message_loader_get_buffer (loader, &buffer);
4460 _dbus_string_append_byte (buffer,
4461 _dbus_string_get_byte (data, i));
4463 _dbus_string_append_byte (buffer,
4464 _dbus_string_get_byte (data, i+1));
4465 _dbus_message_loader_return_buffer (loader, buffer, 1);
4468 if (!check_loader_results (loader, expected_validity))
4471 _dbus_message_loader_unref (loader);
4479 _dbus_message_loader_unref (loader);
4485 process_test_subdir (const DBusString *test_base_dir,
4487 DBusMessageValidity validity,
4488 DBusForeachMessageFileFunc function,
4491 DBusString test_directory;
4492 DBusString filename;
4500 if (!_dbus_string_init (&test_directory))
4501 _dbus_assert_not_reached ("didn't allocate test_directory\n");
4503 _dbus_string_init_const (&filename, subdir);
4505 if (!_dbus_string_copy (test_base_dir, 0,
4506 &test_directory, 0))
4507 _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
4509 if (!_dbus_concat_dir_and_file (&test_directory, &filename))
4510 _dbus_assert_not_reached ("couldn't allocate full path");
4512 _dbus_string_free (&filename);
4513 if (!_dbus_string_init (&filename))
4514 _dbus_assert_not_reached ("didn't allocate filename string\n");
4516 dbus_error_init (&error);
4517 dir = _dbus_directory_open (&test_directory, &error);
4520 _dbus_warn ("Could not open %s: %s\n",
4521 _dbus_string_get_const_data (&test_directory),
4523 dbus_error_free (&error);
4527 printf ("Testing:\n");
4530 while (_dbus_directory_get_next_file (dir, &filename, &error))
4532 DBusString full_path;
4535 if (!_dbus_string_init (&full_path))
4536 _dbus_assert_not_reached ("couldn't init string");
4538 if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
4539 _dbus_assert_not_reached ("couldn't copy dir to full_path");
4541 if (!_dbus_concat_dir_and_file (&full_path, &filename))
4542 _dbus_assert_not_reached ("couldn't concat file to dir");
4544 if (_dbus_string_ends_with_c_str (&filename, ".message"))
4546 else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
4550 _dbus_verbose ("Skipping non-.message file %s\n",
4551 _dbus_string_get_const_data (&filename));
4552 _dbus_string_free (&full_path);
4557 _dbus_string_get_const_data (&filename));
4559 _dbus_verbose (" expecting %s\n",
4560 validity == _DBUS_MESSAGE_VALID ? "valid" :
4561 (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
4562 (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")));
4564 if (! (*function) (&full_path, is_raw, validity, user_data))
4566 _dbus_string_free (&full_path);
4570 _dbus_string_free (&full_path);
4573 if (dbus_error_is_set (&error))
4575 _dbus_warn ("Could not get next file in %s: %s\n",
4576 _dbus_string_get_const_data (&test_directory),
4578 dbus_error_free (&error);
4587 _dbus_directory_close (dir);
4588 _dbus_string_free (&test_directory);
4589 _dbus_string_free (&filename);
4595 * Runs the given function on every message file in the test suite.
4596 * The function should return #FALSE on test failure or fatal error.
4598 * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
4599 * @param func the function to run
4600 * @param user_data data for function
4601 * @returns #FALSE if there's a failure
4604 dbus_internal_do_not_use_foreach_message_file (const char *test_data_dir,
4605 DBusForeachMessageFileFunc func,
4608 DBusString test_directory;
4613 _dbus_string_init_const (&test_directory, test_data_dir);
4615 if (!process_test_subdir (&test_directory, "valid-messages",
4616 _DBUS_MESSAGE_VALID, func, user_data))
4619 if (!process_test_subdir (&test_directory, "invalid-messages",
4620 _DBUS_MESSAGE_INVALID, func, user_data))
4623 if (!process_test_subdir (&test_directory, "incomplete-messages",
4624 _DBUS_MESSAGE_INCOMPLETE, func, user_data))
4631 _dbus_string_free (&test_directory);
4637 verify_test_message (DBusMessage *message)
4639 dbus_int32_t our_int;
4642 dbus_bool_t our_bool;
4643 dbus_int32_t *our_int_array;
4644 int our_int_array_len;
4645 DBusMessageIter iter, dict;
4648 dbus_message_iter_init (message, &iter);
4650 dbus_error_init (&error);
4651 if (!dbus_message_iter_get_args (&iter, &error,
4652 DBUS_TYPE_INT32, &our_int,
4653 DBUS_TYPE_STRING, &our_str,
4654 DBUS_TYPE_DOUBLE, &our_double,
4655 DBUS_TYPE_BOOLEAN, &our_bool,
4656 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &our_int_array, &our_int_array_len,
4659 _dbus_verbose ("error: %s - %s\n", error.name, (error.message != NULL)?error.message: "no message");
4660 _dbus_assert_not_reached ("Could not get arguments");
4663 if (our_int != -0x12345678)
4664 _dbus_assert_not_reached ("integers differ!");
4666 if (our_double != 3.14159)
4667 _dbus_assert_not_reached ("doubles differ!");
4669 if (strcmp (our_str, "Test string") != 0)
4670 _dbus_assert_not_reached ("strings differ!");
4671 dbus_free (our_str);
4674 _dbus_assert_not_reached ("booleans differ");
4676 if (our_int_array_len != 4 ||
4677 our_int_array[0] != 0x12345678 ||
4678 our_int_array[1] != 0x23456781 ||
4679 our_int_array[2] != 0x34567812 ||
4680 our_int_array[3] != 0x45678123)
4681 _dbus_assert_not_reached ("array differ");
4682 dbus_free (our_int_array);
4684 if (!dbus_message_iter_next (&iter))
4685 _dbus_assert_not_reached ("Reached end of arguments");
4687 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
4688 _dbus_assert_not_reached ("not dict type");
4690 if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
4691 _dbus_assert_not_reached ("dict iter failed");
4693 our_str = dbus_message_iter_get_dict_key (&dict);
4694 if (our_str == NULL || strcmp (our_str, "test") != 0)
4695 _dbus_assert_not_reached ("wrong dict key");
4696 dbus_free (our_str);
4698 if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
4700 _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
4701 _dbus_assert_not_reached ("wrong dict entry type");
4704 if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
4705 _dbus_assert_not_reached ("wrong dict entry value");
4707 if (dbus_message_iter_next (&dict))
4708 _dbus_assert_not_reached ("Didn't reach end of dict");
4710 if (!dbus_message_iter_next (&iter))
4711 _dbus_assert_not_reached ("Reached end of arguments");
4713 if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
4714 _dbus_assert_not_reached ("wrong type after dict");
4716 if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
4717 _dbus_assert_not_reached ("wrong value after dict");
4719 if (dbus_message_iter_next (&iter))
4720 _dbus_assert_not_reached ("Didn't reach end of arguments");
4724 * @ingroup DBusMessageInternals
4725 * Unit test for DBusMessage.
4727 * @returns #TRUE on success.
4730 _dbus_message_test (const char *test_data_dir)
4732 DBusMessage *message;
4733 DBusMessageLoader *loader;
4734 DBusMessageIter iter, child_iter;
4740 const dbus_uint32_t our_int32_array[] = { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
4742 _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
4744 /* Test the vararg functions */
4745 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
4746 _dbus_message_set_serial (message, 1);
4747 dbus_message_append_args (message,
4748 DBUS_TYPE_INT32, -0x12345678,
4749 DBUS_TYPE_STRING, "Test string",
4750 DBUS_TYPE_DOUBLE, 3.14159,
4751 DBUS_TYPE_BOOLEAN, TRUE,
4752 DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_int32_array, 4,
4755 dbus_message_append_iter_init (message, &iter);
4756 dbus_message_iter_append_dict (&iter, &child_iter);
4757 dbus_message_iter_append_dict_key (&child_iter, "test");
4758 dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
4759 dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
4761 _dbus_verbose_bytes_of_string (&message->header, 0,
4762 _dbus_string_get_length (&message->header));
4763 _dbus_verbose_bytes_of_string (&message->body, 0,
4764 _dbus_string_get_length (&message->body));
4766 verify_test_message (message);
4768 copy = dbus_message_copy (message);
4770 _dbus_assert (message->client_serial == copy->client_serial);
4771 _dbus_assert (message->reply_serial == copy->reply_serial);
4772 _dbus_assert (message->header_padding == copy->header_padding);
4774 _dbus_assert (_dbus_string_get_length (&message->header) ==
4775 _dbus_string_get_length (©->header));
4777 _dbus_assert (_dbus_string_get_length (&message->body) ==
4778 _dbus_string_get_length (©->body));
4780 verify_test_message (copy);
4782 name1 = dbus_message_get_name (message);
4783 name2 = dbus_message_get_name (copy);
4785 _dbus_assert (strcmp (name1, name2) == 0);
4787 dbus_message_unref (message);
4788 dbus_message_unref (copy);
4790 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
4791 _dbus_message_set_serial (message, 1);
4792 dbus_message_set_reply_serial (message, 0x12345678);
4794 dbus_message_append_iter_init (message, &iter);
4795 dbus_message_iter_append_string (&iter, "Test string");
4796 dbus_message_iter_append_int32 (&iter, -0x12345678);
4797 dbus_message_iter_append_uint32 (&iter, 0xedd1e);
4798 dbus_message_iter_append_double (&iter, 3.14159);
4800 dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_UINT32);
4801 dbus_message_iter_append_uint32 (&child_iter, 0x12345678);
4802 dbus_message_iter_append_uint32 (&child_iter, 0x23456781);
4804 dbus_message_iter_append_dict (&iter, &child_iter);
4805 dbus_message_iter_append_dict_key (&child_iter, "test");
4806 dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
4807 dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
4809 message_iter_test (message);
4811 /* Message loader test */
4812 _dbus_message_lock (message);
4813 loader = _dbus_message_loader_new ();
4815 /* Write the header data one byte at a time */
4816 data = _dbus_string_get_const_data (&message->header);
4817 for (i = 0; i < _dbus_string_get_length (&message->header); i++)
4821 _dbus_message_loader_get_buffer (loader, &buffer);
4822 _dbus_string_append_byte (buffer, data[i]);
4823 _dbus_message_loader_return_buffer (loader, buffer, 1);
4826 /* Write the body data one byte at a time */
4827 data = _dbus_string_get_const_data (&message->body);
4828 for (i = 0; i < _dbus_string_get_length (&message->body); i++)
4832 _dbus_message_loader_get_buffer (loader, &buffer);
4833 _dbus_string_append_byte (buffer, data[i]);
4834 _dbus_message_loader_return_buffer (loader, buffer, 1);
4837 dbus_message_unref (message);
4839 /* Now pop back the message */
4840 if (!_dbus_message_loader_queue_messages (loader))
4841 _dbus_assert_not_reached ("no memory to queue messages");
4843 if (_dbus_message_loader_get_is_corrupted (loader))
4844 _dbus_assert_not_reached ("message loader corrupted");
4846 message = _dbus_message_loader_pop_message (loader);
4848 _dbus_assert_not_reached ("received a NULL message");
4850 if (dbus_message_get_reply_serial (message) != 0x12345678)
4851 _dbus_assert_not_reached ("reply serial fields differ");
4853 message_iter_test (message);
4855 dbus_message_unref (message);
4856 _dbus_message_loader_unref (loader);
4858 /* Now load every message in test_data_dir if we have one */
4859 if (test_data_dir == NULL)
4862 return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
4863 (DBusForeachMessageFileFunc)
4864 dbus_internal_do_not_use_try_message_file,
4868 #endif /* DBUS_BUILD_TESTS */