1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-message.c DBusMessage object
4 * Copyright (C) 2002 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"
34 * @defgroup DBusMessageInternals DBusMessage implementation details
35 * @ingroup DBusInternals
36 * @brief DBusMessage private implementation details.
38 * The guts of DBusMessage and its methods.
44 * The largest-length message we allow
46 * @todo match this up with whatever the protocol spec says.
48 #define _DBUS_MAX_MESSAGE_LENGTH (_DBUS_INT_MAX/16)
51 * @brief Internals of DBusMessage
53 * Object representing a message received from or to be sent to
54 * another application. This is an opaque object, all members
59 int refcount; /**< Reference count */
61 DBusString header; /**< Header network data, stored
62 * separately from body so we can
63 * independently realloc it.
66 DBusString body; /**< Body network data. */
68 char byte_order; /**< Message byte order. */
70 char *name; /**< Message name. */
71 char *service; /**< Message destination service. */
73 dbus_int32_t client_serial; /**< Client serial or -1 if not set */
74 dbus_int32_t reply_serial; /**< Reply serial or -1 if not set */
76 unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
80 * @brief Internals of DBusMessageIter
82 * Object representing a position in a message. All fields are internal.
84 struct DBusMessageIter
86 int refcount; /**< Reference count */
88 int pos; /**< Current position in the string */
90 DBusMessage *message; /**< Message used */
94 * Gets the data to be sent over the network for this message.
95 * The header and then the body should be written out.
96 * This function is guaranteed to always return the same
97 * data once a message is locked (with _dbus_message_lock()).
99 * @param message the message.
100 * @param header return location for message header data.
101 * @param body return location for message body data.
104 _dbus_message_get_network_data (DBusMessage *message,
105 const DBusString **header,
106 const DBusString **body)
108 _dbus_assert (message->locked);
110 *header = &message->header;
111 *body = &message->body;
115 * Sets the client serial of a message.
116 * This can only be done once on a message.
118 * @param message the message
119 * @param client_serial the client serial
122 _dbus_message_set_client_serial (DBusMessage *message,
123 dbus_int32_t client_serial)
125 _dbus_assert (message->client_serial == -1);
127 message->client_serial = client_serial;
131 dbus_message_write_header (DBusMessage *message)
135 _dbus_assert (message->client_serial != -1);
137 _dbus_string_append_byte (&message->header, DBUS_COMPILER_BYTE_ORDER);
138 _dbus_string_append_len (&message->header, "\0\0\0", 3);
140 /* We just lengthen the string here and pack in the real length later */
141 _dbus_string_lengthen (&message->header, 4);
143 _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER,
144 _dbus_string_get_length (&message->body));
146 /* Marshal client serial */
147 _dbus_assert (message->client_serial >= 0);
148 _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER,
149 message->client_serial);
151 /* Marshal message service */
152 if (message->service)
154 _dbus_string_align_length (&message->header, 4);
155 _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_SERVICE, 4);
156 _dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
158 _dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER,
162 /* Marshal message name */
163 _dbus_assert (message->name != NULL);
164 _dbus_string_align_length (&message->header, 4);
165 _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_NAME, 4);
166 _dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
168 _dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER, message->name);
170 /* Marshal reply serial */
171 if (message->reply_serial != -1)
173 _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_REPLY, 4);
175 _dbus_string_append_byte (&message->header, DBUS_TYPE_INT32);
176 _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER,
177 message->reply_serial);
180 /* Fill in the length */
181 _dbus_string_get_data_len (&message->header, &len_data, 4, 4);
182 _dbus_pack_int32 (_dbus_string_get_length (&message->header),
183 DBUS_COMPILER_BYTE_ORDER, len_data);
187 * Locks a message. Allows checking that applications don't keep a
188 * reference to a message in the outgoing queue and change it
189 * underneath us. Messages are locked when they enter the outgoing
190 * queue (dbus_connection_send_message()), and the library complains
191 * if the message is modified while locked.
193 * @param message the message to lock.
196 _dbus_message_lock (DBusMessage *message)
198 if (!message->locked)
199 dbus_message_write_header (message);
201 message->locked = TRUE;
207 * @defgroup DBusMessage DBusMessage
209 * @brief Message to be sent or received over a DBusConnection.
211 * A DBusMessage is the most basic unit of communication over a
212 * DBusConnection. A DBusConnection represents a stream of messages
213 * received from a remote application, and a stream of messages
214 * sent to a remote application.
220 * @typedef DBusMessage
222 * Opaque data type representing a message received from or to be
223 * sent to another application.
227 * Constructs a new message. Returns #NULL if memory
228 * can't be allocated for the message.
230 * @todo use DBusString internally to store service and name.
232 * @param service service that the message should be sent to
233 * @param name name of the message
234 * @returns a new DBusMessage, free with dbus_message_unref()
235 * @see dbus_message_unref()
238 dbus_message_new (const char *service,
241 DBusMessage *message;
243 message = dbus_new0 (DBusMessage, 1);
247 message->refcount = 1;
248 message->byte_order = DBUS_COMPILER_BYTE_ORDER;
250 message->service = _dbus_strdup (service);
251 message->name = _dbus_strdup (name);
253 message->client_serial = -1;
254 message->reply_serial = -1;
256 if (!_dbus_string_init (&message->header, _DBUS_MAX_MESSAGE_LENGTH))
258 dbus_free (message->service);
259 dbus_free (message->name);
264 if (!_dbus_string_init (&message->body, _DBUS_MAX_MESSAGE_LENGTH))
266 dbus_free (message->service);
267 dbus_free (message->name);
268 _dbus_string_free (&message->header);
278 * Increments the reference count of a DBusMessage.
280 * @param message The message
281 * @see dbus_message_unref
284 dbus_message_ref (DBusMessage *message)
286 _dbus_assert (message->refcount > 0);
288 message->refcount += 1;
292 * Decrements the reference count of a DBusMessage.
294 * @param message The message
295 * @see dbus_message_ref
298 dbus_message_unref (DBusMessage *message)
300 _dbus_assert (message->refcount > 0);
302 message->refcount -= 1;
303 if (message->refcount == 0)
305 _dbus_string_free (&message->header);
306 _dbus_string_free (&message->body);
308 dbus_free (message->service);
309 dbus_free (message->name);
315 * Gets the name of a message.
317 * @param message the message
318 * @returns the message name (should not be freed)
321 dbus_message_get_name (DBusMessage *message)
323 return message->name;
327 * Appends fields to a message given a variable argument
328 * list. The variable argument list should contain the type
329 * of the field followed by the value to add.
330 * The list is terminated with 0.
332 * @param message the message
333 * @param type of the first field
334 * @param ... value of first field, list of additional type-value pairs
335 * @returns #TRUE on success
338 dbus_message_append_fields (DBusMessage *message,
339 int first_field_type,
345 va_start (var_args, first_field_type);
346 retval = dbus_message_append_fields_valist (message,
355 * This function takes a va_list for use by language bindings
357 * @see dbus_message_append_fields.
358 * @param message the message
359 * @param first_field_type type of first field
360 * @param var_args value of first field, then list of type/value pairs
361 * @returns #TRUE on success
364 dbus_message_append_fields_valist (DBusMessage *message,
365 int first_field_type,
370 old_len = _dbus_string_get_length (&message->body);
372 type = first_field_type;
378 case DBUS_TYPE_INT32:
379 if (!dbus_message_append_int32 (message, va_arg (var_args, dbus_int32_t)))
382 case DBUS_TYPE_UINT32:
383 if (!dbus_message_append_uint32 (message, va_arg (var_args, dbus_uint32_t)))
386 case DBUS_TYPE_DOUBLE:
387 if (!dbus_message_append_double (message, va_arg (var_args, double)))
390 case DBUS_TYPE_STRING:
391 if (!dbus_message_append_string (message, va_arg (var_args, const char *)))
394 case DBUS_TYPE_BYTE_ARRAY:
399 data = va_arg (var_args, unsigned char *);
400 len = va_arg (var_args, int);
402 if (!dbus_message_append_byte_array (message, data, len))
407 _dbus_warn ("Unknown field type %d\n", type);
410 type = va_arg (var_args, int);
416 _dbus_string_set_length (&message->body, old_len);
421 * Appends a 32 bit signed integer to the message.
423 * @param message the message
424 * @param value the integer value
425 * @returns #TRUE on success
428 dbus_message_append_int32 (DBusMessage *message,
431 _dbus_assert (!message->locked);
433 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
435 _dbus_string_shorten (&message->body, 1);
439 return _dbus_marshal_int32 (&message->body,
440 DBUS_COMPILER_BYTE_ORDER, value);
444 * Appends a 32 bit unsigned integer to the message.
446 * @param message the message
447 * @param value the integer value
448 * @returns #TRUE on success
451 dbus_message_append_uint32 (DBusMessage *message,
454 _dbus_assert (!message->locked);
456 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
458 _dbus_string_shorten (&message->body, 1);
462 return _dbus_marshal_uint32 (&message->body,
463 DBUS_COMPILER_BYTE_ORDER, value);
467 * Appends a double value to the message.
469 * @param message the message
470 * @param value the double value
471 * @returns #TRUE on success
474 dbus_message_append_double (DBusMessage *message,
477 _dbus_assert (!message->locked);
479 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
481 _dbus_string_shorten (&message->body, 1);
485 return _dbus_marshal_double (&message->body,
486 DBUS_COMPILER_BYTE_ORDER, value);
490 * Appends a UTF-8 string to the message.
492 * @param message the message
493 * @param value the string
494 * @returns #TRUE on success
497 dbus_message_append_string (DBusMessage *message,
500 _dbus_assert (!message->locked);
502 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
504 _dbus_string_shorten (&message->body, 1);
508 return _dbus_marshal_string (&message->body,
509 DBUS_COMPILER_BYTE_ORDER, value);
513 * Appends a byte array to the message.
515 * @param message the message
516 * @param value the array
517 * @param len the length of the array
518 * @returns #TRUE on success
521 dbus_message_append_byte_array (DBusMessage *message,
522 unsigned const char *value,
525 _dbus_assert (!message->locked);
527 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
529 _dbus_string_shorten (&message->body, 1);
533 return _dbus_marshal_byte_array (&message->body,
534 DBUS_COMPILER_BYTE_ORDER, value, len);
538 * Gets fields from a message given a variable argument list.
539 * The variable argument list should contain the type of the
540 * field followed by a pointer to where the value should be
541 * stored. The list is terminated with 0.
543 * @param message the message
544 * @param first_field_type the first field type
545 * @param ... location for first field value, then list of type-location pairs
546 * @returns #TRUE on success
549 dbus_message_get_fields (DBusMessage *message,
550 int first_field_type,
556 va_start (var_args, first_field_type);
557 retval = dbus_message_get_fields_valist (message, first_field_type, var_args);
564 * This function takes a va_list for use by language bindings
566 * @todo this function (or some lower-level non-convenience function)
567 * needs better error handling; should allow the application to
568 * distinguish between out of memory, and bad data from the remote
569 * app. It also needs to not leak a bunch of args when it gets
570 * to the arg that's bad, as that would be a security hole
571 * (allow one app to force another to leak memory)
573 * @see dbus_message_get_fields
574 * @param message the message
575 * @param first_field_type type of the first field
576 * @param var_args return location for first field, followed by list of type/location pairs
577 * @returns #TRUE on success
580 dbus_message_get_fields_valist (DBusMessage *message,
581 int first_field_type,
584 int spec_type, msg_type, i;
585 DBusMessageIter *iter;
587 iter = dbus_message_get_fields_iter (message);
592 spec_type = first_field_type;
595 while (spec_type != 0)
597 msg_type = dbus_message_iter_get_field_type (iter);
599 if (msg_type != spec_type)
601 _dbus_warn ("Field %d is specified to be of type \"%s\", but "
602 "is actually of type \"%s\"\n", i,
603 _dbus_type_to_string (spec_type),
604 _dbus_type_to_string (msg_type));
605 dbus_message_iter_unref (iter);
612 case DBUS_TYPE_INT32:
616 ptr = va_arg (var_args, dbus_int32_t *);
618 *ptr = dbus_message_iter_get_int32 (iter);
621 case DBUS_TYPE_UINT32:
625 ptr = va_arg (var_args, dbus_uint32_t *);
627 *ptr = dbus_message_iter_get_uint32 (iter);
631 case DBUS_TYPE_DOUBLE:
635 ptr = va_arg (var_args, double *);
637 *ptr = dbus_message_iter_get_double (iter);
641 case DBUS_TYPE_STRING:
645 ptr = va_arg (var_args, char **);
647 *ptr = dbus_message_iter_get_string (iter);
651 case DBUS_TYPE_BYTE_ARRAY:
656 ptr = va_arg (var_args, char **);
657 len = va_arg (var_args, int *);
659 *ptr = dbus_message_iter_get_byte_array (iter, len);
663 _dbus_warn ("Unknown field type %d\n", spec_type);
666 spec_type = va_arg (var_args, int);
667 if (spec_type != 0 && !dbus_message_iter_next (iter))
669 _dbus_warn ("More fields than exist in the message were specified\n");
671 dbus_message_iter_unref (iter);
677 dbus_message_iter_unref (iter);
682 * Returns a DBusMessageIter representing the fields of the
685 * @todo IMO the message iter should follow the GtkTextIter pattern,
686 * a static object with a "stamp" value used to detect invalid
687 * iter uses (uninitialized or after changing the message).
688 * ref/unref is kind of annoying to deal with, and slower too.
689 * This implies not ref'ing the message from the iter.
691 * @param message the message
692 * @returns a new iter.
695 dbus_message_get_fields_iter (DBusMessage *message)
697 DBusMessageIter *iter;
699 iter = dbus_new (DBusMessageIter, 1);
701 dbus_message_ref (message);
704 iter->message = message;
711 * Increments the reference count of a DBusMessageIter.
713 * @param iter the message iter
714 * @see dbus_message_iter_unref
717 dbus_message_iter_ref (DBusMessageIter *iter)
719 _dbus_assert (iter->refcount > 0);
725 * Decrements the reference count of a DBusMessageIter.
727 * @param iter The message iter
728 * @see dbus_message_iter_ref
731 dbus_message_iter_unref (DBusMessageIter *iter)
733 _dbus_assert (iter->refcount > 0);
737 if (iter->refcount == 0)
739 dbus_message_unref (iter->message);
746 * Checks if an iterator has any more fields.
748 * @param iter the message iter
749 * @returns #TRUE if there are more fields
753 dbus_message_iter_has_next (DBusMessageIter *iter)
757 if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
758 iter->pos, &end_pos))
761 if (end_pos >= _dbus_string_get_length (&iter->message->body))
768 * Moves the iterator to the next field.
770 * @param iter The message iter
771 * @returns #TRUE if the iterator was moved to the next field
774 dbus_message_iter_next (DBusMessageIter *iter)
778 if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
779 iter->pos, &end_pos))
782 if (end_pos >= _dbus_string_get_length (&iter->message->body))
791 * Returns the field type of the field that the
792 * message iterator points at.
794 * @param iter the message iter
795 * @returns the field type
798 dbus_message_iter_get_field_type (DBusMessageIter *iter)
802 if (iter->pos >= _dbus_string_get_length (&iter->message->body))
803 return DBUS_TYPE_INVALID;
805 _dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
807 if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING)
810 return DBUS_TYPE_INVALID;
814 * Returns the string value that an iterator may point to.
815 * Note that you need to check that the iterator points to
816 * a string value before using this function.
818 * @see dbus_message_iter_get_field_type
819 * @param iter the message iter
820 * @returns the string
823 dbus_message_iter_get_string (DBusMessageIter *iter)
825 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_STRING);
827 return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
828 iter->pos + 1, NULL);
832 * Returns the 32 bit signed integer value that an iterator may point to.
833 * Note that you need to check that the iterator points to
834 * a string value before using this function.
836 * @see dbus_message_iter_get_field_type
837 * @param iter the message iter
838 * @returns the integer
841 dbus_message_iter_get_int32 (DBusMessageIter *iter)
843 return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
844 iter->pos + 1, NULL);
848 * Returns the 32 bit unsigned integer value that an iterator may point to.
849 * Note that you need to check that the iterator points to
850 * a string value before using this function.
852 * @see dbus_message_iter_get_field_type
853 * @param iter the message iter
854 * @returns the integer
857 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
859 return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
860 iter->pos + 1, NULL);
864 * Returns the double value that an iterator may point to.
865 * Note that you need to check that the iterator points to
866 * a string value before using this function.
868 * @see dbus_message_iter_get_field_type
869 * @param iter the message iter
870 * @returns the double
873 dbus_message_iter_get_double (DBusMessageIter *iter)
875 return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
876 iter->pos + 1, NULL);
880 dbus_message_iter_get_byte_array (DBusMessageIter *iter, int *len)
882 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_BYTE_ARRAY);
884 return _dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
885 iter->pos + 1, NULL, len);
891 * @addtogroup DBusMessageInternals
896 * @typedef DBusMessageLoader
898 * The DBusMessageLoader object encapsulates the process of converting
899 * a byte stream into a series of DBusMessage. It buffers the incoming
900 * bytes as efficiently as possible, and generates a queue of
901 * messages. DBusMessageLoader is typically used as part of a
902 * DBusTransport implementation. The DBusTransport then hands off
903 * the loaded messages to a DBusConnection, making the messages
904 * visible to the application.
909 * Implementation details of DBusMessageLoader.
910 * All members are private.
912 struct DBusMessageLoader
914 int refcount; /**< Reference count. */
916 DBusString data; /**< Buffered data */
918 DBusList *messages; /**< Complete messages. */
920 unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
922 unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
926 * The initial buffer size of the message loader.
928 * @todo this should be based on min header size plus some average
929 * body size, or something. Or rather, the min header size only, if we
930 * want to try to read only the header, store that in a DBusMessage,
931 * then read only the body and store that, etc., depends on
932 * how we optimize _dbus_message_loader_get_buffer() and what
933 * the exact message format is.
935 #define INITIAL_LOADER_DATA_LEN 32
938 * Creates a new message loader. Returns #NULL if memory can't
941 * @returns new loader, or #NULL.
944 _dbus_message_loader_new (void)
946 DBusMessageLoader *loader;
948 loader = dbus_new0 (DBusMessageLoader, 1);
952 loader->refcount = 1;
954 if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
960 /* preallocate the buffer for speed, ignore failure */
961 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
962 _dbus_string_set_length (&loader->data, 0);
968 * Increments the reference count of the loader.
970 * @param loader the loader.
973 _dbus_message_loader_ref (DBusMessageLoader *loader)
975 loader->refcount += 1;
979 * Decrements the reference count of the loader and finalizes the
980 * loader when the count reaches zero.
982 * @param loader the loader.
985 _dbus_message_loader_unref (DBusMessageLoader *loader)
987 loader->refcount -= 1;
988 if (loader->refcount == 0)
990 _dbus_list_foreach (&loader->messages,
991 (DBusForeachFunction) dbus_message_unref,
993 _dbus_list_clear (&loader->messages);
994 _dbus_string_free (&loader->data);
1000 * Gets the buffer to use for reading data from the network. Network
1001 * data is read directly into an allocated buffer, which is then used
1002 * in the DBusMessage, to avoid as many extra memcpy's as possible.
1003 * The buffer must always be returned immediately using
1004 * _dbus_message_loader_return_buffer(), even if no bytes are
1005 * successfully read.
1007 * @todo this function can be a lot more clever. For example
1008 * it can probably always return a buffer size to read exactly
1009 * the body of the next message, thus avoiding any memory wastage
1012 * @param loader the message loader.
1013 * @param buffer the buffer
1016 _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
1017 DBusString **buffer)
1019 _dbus_assert (!loader->buffer_outstanding);
1021 *buffer = &loader->data;
1023 loader->buffer_outstanding = TRUE;
1027 * The smallest header size that can occur.
1028 * (It won't be valid)
1030 #define DBUS_MINIMUM_HEADER_SIZE 16
1032 /** Pack four characters as in "abcd" into a uint32 */
1033 #define FOUR_CHARS_TO_UINT32(a, b, c, d) \
1034 ((((dbus_uint32_t)a) << 24) | \
1035 (((dbus_uint32_t)b) << 16) | \
1036 (((dbus_uint32_t)c) << 8) | \
1039 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
1040 #define DBUS_HEADER_FIELD_NAME_AS_UINT32 \
1041 FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
1043 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
1044 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
1045 FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
1047 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
1048 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32 \
1049 FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
1051 /* FIXME should be using DBusString for the stuff we demarshal. char*
1052 * evil. Also, out of memory handling here seems suboptimal.
1053 * Should probably report it as a distinct error from "corrupt message,"
1054 * so we can postpone parsing this message. Also, we aren't
1055 * checking for demarshal failure everywhere.
1058 decode_header_data (DBusString *data,
1061 dbus_int32_t *client_serial,
1068 /* First demarshal the client serial */
1069 *client_serial = _dbus_demarshal_int32 (data, byte_order, 12, &pos);
1074 /* Now handle the fields */
1075 while (pos < header_len)
1077 pos = _DBUS_ALIGN_VALUE (pos, 4);
1079 if ((pos + 4) > header_len)
1082 _dbus_string_get_const_data_len (data, &field, pos, 4);
1085 _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
1087 /* I believe FROM_BE is right, but if not we'll find out
1090 switch (DBUS_UINT32_FROM_BE (*(int*)field))
1092 case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
1093 if (*service != NULL)
1095 _dbus_verbose ("%s field provided twice\n",
1096 DBUS_HEADER_FIELD_SERVICE);
1100 *service = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
1101 /* FIXME check for demarshal failure SECURITY */
1103 case DBUS_HEADER_FIELD_NAME_AS_UINT32:
1106 _dbus_verbose ("%s field provided twice\n",
1107 DBUS_HEADER_FIELD_NAME);
1111 *name = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
1112 /* FIXME check for demarshal failure SECURITY */
1115 _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c\n",
1116 field[0], field[1], field[2], field[3]);
1118 if (!_dbus_marshal_get_field_end_pos (data, byte_order, pos, &new_pos))
1122 if (new_pos > header_len)
1131 dbus_free (*service);
1137 * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
1138 * indicating to the loader how many bytes of the buffer were filled
1139 * in. This function must always be called, even if no bytes were
1140 * successfully read.
1142 * @param loader the loader.
1143 * @param buffer the buffer.
1144 * @param bytes_read number of bytes that were read into the buffer.
1147 _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
1151 _dbus_assert (loader->buffer_outstanding);
1152 _dbus_assert (buffer == &loader->data);
1154 loader->buffer_outstanding = FALSE;
1156 if (loader->corrupted)
1159 while (_dbus_string_get_length (&loader->data) >= 16)
1161 DBusMessage *message;
1162 const char *header_data;
1163 int byte_order, header_len, body_len;
1165 _dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
1167 _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
1169 byte_order = header_data[0];
1171 if (byte_order != DBUS_LITTLE_ENDIAN &&
1172 byte_order != DBUS_BIG_ENDIAN)
1174 _dbus_verbose ("Message with bad byte order '%c' received\n",
1176 loader->corrupted = TRUE;
1180 header_len = _dbus_unpack_int32 (byte_order, header_data + 4);
1181 body_len = _dbus_unpack_int32 (byte_order, header_data + 8);
1183 if (header_len + body_len > _DBUS_MAX_MESSAGE_LENGTH)
1185 _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %d\n",
1186 header_len, body_len, _DBUS_MAX_MESSAGE_LENGTH);
1187 loader->corrupted = TRUE;
1191 if (_dbus_string_get_length (&loader->data) >= header_len + body_len)
1193 dbus_int32_t client_serial;
1194 char *service, *name;
1196 /* FIXME right now if this doesn't have enough memory, the
1197 * loader becomes corrupted. Instead we should just not
1198 * parse this message for now.
1200 if (!decode_header_data (&loader->data, header_len, byte_order,
1201 &client_serial, &service, &name))
1203 loader->corrupted = TRUE;
1207 message = dbus_message_new (service, name);
1208 dbus_free (service);
1211 if (message == NULL)
1212 break; /* ugh, postpone this I guess. */
1214 _dbus_string_copy (&loader->data, header_len, &message->body, 0);
1215 _dbus_message_set_client_serial (message, client_serial);
1217 _dbus_list_append (&loader->messages, message);
1218 _dbus_string_delete (&loader->data, 0, header_len + body_len);
1220 _dbus_verbose ("Loaded message %p\n", message);
1228 * Pops a loaded message (passing ownership of the message
1229 * to the caller). Returns #NULL if no messages have been
1232 * @param loader the loader.
1233 * @returns the next message, or #NULL if none.
1236 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
1238 return _dbus_list_pop_first (&loader->messages);
1243 * Checks whether the loader is confused due to bad data.
1244 * If messages are received that are invalid, the
1245 * loader gets confused and gives up permanently.
1246 * This state is called "corrupted."
1248 * @param loader the loader
1249 * @returns #TRUE if the loader is hosed.
1252 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
1254 return loader->corrupted;
1258 #ifdef DBUS_BUILD_TESTS
1259 #include "dbus-test.h"
1263 message_iter_test (DBusMessage *message)
1265 DBusMessageIter *iter;
1268 iter = dbus_message_get_fields_iter (message);
1271 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_STRING)
1272 _dbus_assert_not_reached ("Field type isn't string");
1274 str = dbus_message_iter_get_string (iter);
1275 if (strcmp (str, "Test string") != 0)
1276 _dbus_assert_not_reached ("Strings differ");
1279 if (!dbus_message_iter_next (iter))
1280 _dbus_assert_not_reached ("Reached end of fields");
1282 /* Signed integer tests */
1283 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_INT32)
1284 _dbus_assert_not_reached ("Field type isn't int32");
1286 if (dbus_message_iter_get_int32 (iter) != -0x12345678)
1287 _dbus_assert_not_reached ("Signed integers differ");
1289 if (!dbus_message_iter_next (iter))
1290 _dbus_assert_not_reached ("Reached end of fields");
1292 /* Unsigned integer tests */
1293 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_UINT32)
1294 _dbus_assert_not_reached ("Field type isn't int32");
1296 if (dbus_message_iter_get_int32 (iter) != 0xedd1e)
1297 _dbus_assert_not_reached ("Unsigned integers differ");
1299 if (!dbus_message_iter_next (iter))
1300 _dbus_assert_not_reached ("Reached end of fields");
1303 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_DOUBLE)
1304 _dbus_assert_not_reached ("Field type isn't double");
1306 if (dbus_message_iter_get_double (iter) != 3.14159)
1307 _dbus_assert_not_reached ("Doubles differ");
1309 if (dbus_message_iter_next (iter))
1310 _dbus_assert_not_reached ("Didn't reach end of fields");
1312 dbus_message_iter_unref (iter);
1316 * @ingroup DBusMessageInternals
1317 * Unit test for DBusMessage.
1319 * @returns #TRUE on success.
1322 _dbus_message_test (void)
1324 DBusMessage *message;
1325 DBusMessageLoader *loader;
1328 dbus_int32_t our_int;
1332 /* Test the vararg functions */
1333 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
1334 message->client_serial = 1;
1335 dbus_message_append_fields (message,
1336 DBUS_TYPE_INT32, -0x12345678,
1337 DBUS_TYPE_STRING, "Test string",
1338 DBUS_TYPE_DOUBLE, 3.14159,
1341 if (!dbus_message_get_fields (message,
1342 DBUS_TYPE_INT32, &our_int,
1343 DBUS_TYPE_STRING, &our_str,
1344 DBUS_TYPE_DOUBLE, &our_double,
1346 _dbus_assert_not_reached ("Could not get fields");
1348 if (our_int != -0x12345678)
1349 _dbus_assert_not_reached ("integers differ!");
1351 if (our_double != 3.14159)
1352 _dbus_assert_not_reached ("doubles differ!");
1354 if (strcmp (our_str, "Test string") != 0)
1355 _dbus_assert_not_reached ("strings differ!");
1357 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
1358 message->client_serial = 1;
1359 dbus_message_append_string (message, "Test string");
1360 dbus_message_append_int32 (message, -0x12345678);
1361 dbus_message_append_uint32 (message, 0xedd1e);
1362 dbus_message_append_double (message, 3.14159);
1364 message_iter_test (message);
1366 /* Message loader test */
1367 _dbus_message_lock (message);
1368 loader = _dbus_message_loader_new ();
1370 /* Write the header data one byte at a time */
1371 _dbus_string_get_const_data (&message->header, &data);
1372 for (i = 0; i < _dbus_string_get_length (&message->header); i++)
1376 _dbus_message_loader_get_buffer (loader, &buffer);
1377 _dbus_string_append_byte (buffer, data[i]);
1378 _dbus_message_loader_return_buffer (loader, buffer, 1);
1381 /* Write the body data one byte at a time */
1382 _dbus_string_get_const_data (&message->body, &data);
1383 for (i = 0; i < _dbus_string_get_length (&message->body); i++)
1387 _dbus_message_loader_get_buffer (loader, &buffer);
1388 _dbus_string_append_byte (buffer, data[i]);
1389 _dbus_message_loader_return_buffer (loader, buffer, 1);
1392 dbus_message_unref (message);
1394 /* Now pop back the message */
1395 if (_dbus_message_loader_get_is_corrupted (loader))
1396 _dbus_assert_not_reached ("message loader corrupted");
1398 message = _dbus_message_loader_pop_message (loader);
1400 _dbus_assert_not_reached ("received a NULL message");
1402 message_iter_test (message);
1404 dbus_message_unref (message);
1405 _dbus_message_loader_unref (loader);
1410 #endif /* DBUS_BUILD_TESTS */