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. */
79 struct DBusMessageIter
81 int refcount; /**< Reference count */
83 int pos; /**< Current position in the string */
85 DBusMessage *message; /**< Message used */
89 * Gets the data to be sent over the network for this message.
90 * The header and then the body should be written out.
91 * This function is guaranteed to always return the same
92 * data once a message is locked (with _dbus_message_lock()).
94 * @param message the message.
95 * @param header return location for message header data.
96 * @param body return location for message body data.
99 _dbus_message_get_network_data (DBusMessage *message,
100 const DBusString **header,
101 const DBusString **body)
103 _dbus_assert (message->locked);
105 *header = &message->header;
106 *body = &message->body;
110 * Sets the client serial of a message.
111 * This can only be done once on a message.
113 * @param message the message
114 * @param client_serial the client serial
117 _dbus_message_set_client_serial (DBusMessage *message,
118 dbus_int32_t client_serial)
120 _dbus_assert (message->client_serial == -1);
122 message->client_serial = client_serial;
126 dbus_message_write_header (DBusMessage *message)
130 _dbus_assert (message->client_serial != -1);
132 _dbus_string_append_byte (&message->header, DBUS_COMPILER_BYTE_ORDER);
133 _dbus_string_append_len (&message->header, "\0\0\0", 3);
135 /* We just lengthen the string here and pack in the real length later */
136 _dbus_string_lengthen (&message->header, 4);
138 _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER, _dbus_string_get_length (&message->body));
140 /* Marshal client serial */
141 _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER, message->client_serial);
143 /* Marshal message service */
144 if (message->service)
146 _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_SERVICE, 4);
147 _dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
149 _dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER, message->service);
152 /* Marshal message name */
153 _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_NAME, 4);
154 _dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
156 _dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER, message->name);
158 /* Marshal reply serial */
159 if (message->reply_serial != -1)
161 _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_REPLY, 4);
163 _dbus_string_append_byte (&message->header, DBUS_TYPE_INT32);
164 _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER, message->reply_serial);
167 /* Fill in the length */
168 _dbus_string_get_data_len (&message->header, &header, 4, 4);
169 dbus_pack_int32 (_dbus_string_get_length (&message->header), DBUS_COMPILER_BYTE_ORDER, header);
173 * Locks a message. Allows checking that applications don't keep a
174 * reference to a message in the outgoing queue and change it
175 * underneath us. Messages are locked when they enter the outgoing
176 * queue (dbus_connection_send_message()), and the library complains
177 * if the message is modified while locked.
179 * @param message the message to lock.
182 _dbus_message_lock (DBusMessage *message)
184 if (!message->locked)
185 dbus_message_write_header (message);
187 message->locked = TRUE;
193 * @defgroup DBusMessage DBusMessage
195 * @brief Message to be sent or received over a DBusConnection.
197 * A DBusMessage is the most basic unit of communication over a
198 * DBusConnection. A DBusConnection represents a stream of messages
199 * received from a remote application, and a stream of messages
200 * sent to a remote application.
206 * @typedef DBusMessage
208 * Opaque data type representing a message received from or to be
209 * sent to another application.
213 * Constructs a new message. Returns #NULL if memory
214 * can't be allocated for the message.
216 * @param service service that the message should be sent to
218 * @param name name of the message
219 * @returns a new DBusMessage, free with dbus_message_unref()
220 * @see dbus_message_unref()
223 dbus_message_new (const char *service,
226 DBusMessage *message;
228 message = dbus_new0 (DBusMessage, 1);
232 message->refcount = 1;
233 message->byte_order = DBUS_COMPILER_BYTE_ORDER;
235 message->service = _dbus_strdup (service);
236 message->name = _dbus_strdup (name);
238 message->client_serial = -1;
239 message->reply_serial = -1;
241 if (!_dbus_string_init (&message->header, _DBUS_MAX_MESSAGE_LENGTH))
247 if (!_dbus_string_init (&message->body, _DBUS_MAX_MESSAGE_LENGTH))
249 _dbus_string_free (&message->header);
259 * Increments the reference count of a DBusMessage.
261 * @param message The message
262 * @see dbus_message_unref
265 dbus_message_ref (DBusMessage *message)
267 _dbus_assert (message->refcount > 0);
269 message->refcount += 1;
273 * Decrements the reference count of a DBusMessage.
275 * @param message The message
276 * @see dbus_message_ref
279 dbus_message_unref (DBusMessage *message)
281 _dbus_assert (message->refcount > 0);
283 message->refcount -= 1;
284 if (message->refcount == 0)
286 _dbus_string_free (&message->header);
287 _dbus_string_free (&message->body);
289 dbus_free (message->name);
295 * Gets the name of a message.
297 * @param message the message
298 * @returns the message name (should not be freed)
301 dbus_message_get_name (DBusMessage *message)
303 return message->name;
307 * Appends fields to a message given a variable argument
308 * list. The variable argument list should contain the type
309 * of the field followed by the value to add.
310 * The list is terminated with 0.
312 * @param message the message
313 * @param ... list of fields.
314 * @returns #TRUE on success
317 dbus_message_append_fields (DBusMessage *message,
323 va_start (var_args, message);
324 retval = dbus_message_append_fields_valist (message, var_args);
331 * This function takes a va_list for use by language bindings
333 * @see dbus_message_append_fields.
334 * @param message the message
335 * @param var_args list of type/value pairs
336 * @returns #TRUE on success
339 dbus_message_append_fields_valist (DBusMessage *message,
344 old_len = _dbus_string_get_length (&message->body);
346 type = va_arg (var_args, int);
352 case DBUS_TYPE_INT32:
353 if (!dbus_message_append_int32 (message, va_arg (var_args, dbus_int32_t)))
356 case DBUS_TYPE_UINT32:
357 if (!dbus_message_append_uint32 (message, va_arg (var_args, dbus_uint32_t)))
360 case DBUS_TYPE_DOUBLE:
361 if (!dbus_message_append_double (message, va_arg (var_args, double)))
364 case DBUS_TYPE_STRING:
365 if (!dbus_message_append_string (message, va_arg (var_args, const char *)))
368 case DBUS_TYPE_BYTE_ARRAY:
373 data = va_arg (var_args, unsigned char *);
374 len = va_arg (var_args, int);
376 if (!dbus_message_append_byte_array (message, data, len))
382 _dbus_warn ("Unknown field type %d\n", type);
385 type = va_arg (var_args, int);
391 _dbus_string_set_length (&message->body, old_len);
396 * Appends a 32 bit signed integer to the message.
398 * @param message the message
399 * @param value the integer value
400 * @returns #TRUE on success
403 dbus_message_append_int32 (DBusMessage *message,
406 _dbus_assert (!message->locked);
408 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
410 _dbus_string_shorten (&message->body, 1);
414 return _dbus_marshal_int32 (&message->body,
415 DBUS_COMPILER_BYTE_ORDER, value);
419 * Appends a 32 bit unsigned integer to the message.
421 * @param message the message
422 * @param value the integer value
423 * @returns #TRUE on success
426 dbus_message_append_uint32 (DBusMessage *message,
429 _dbus_assert (!message->locked);
431 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
433 _dbus_string_shorten (&message->body, 1);
437 return _dbus_marshal_uint32 (&message->body,
438 DBUS_COMPILER_BYTE_ORDER, value);
442 * Appends a double value to the message.
444 * @param message the message
445 * @param value the double value
446 * @returns #TRUE on success
449 dbus_message_append_double (DBusMessage *message,
452 _dbus_assert (!message->locked);
454 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
456 _dbus_string_shorten (&message->body, 1);
460 return _dbus_marshal_double (&message->body,
461 DBUS_COMPILER_BYTE_ORDER, value);
465 * Appends a UTF-8 string to the message.
467 * @param message the message
468 * @param value the string
469 * @returns #TRUE on success
472 dbus_message_append_string (DBusMessage *message,
475 _dbus_assert (!message->locked);
477 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
479 _dbus_string_shorten (&message->body, 1);
483 return _dbus_marshal_string (&message->body,
484 DBUS_COMPILER_BYTE_ORDER, value);
488 * Appends a byte array to the message.
490 * @param message the message
491 * @param value the array
492 * @param len the length of the array
493 * @returns #TRUE on success
496 dbus_message_append_byte_array (DBusMessage *message,
497 unsigned const char *value,
500 _dbus_assert (!message->locked);
502 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
504 _dbus_string_shorten (&message->body, 1);
508 return _dbus_marshal_byte_array (&message->body,
509 DBUS_COMPILER_BYTE_ORDER, value, len);
513 * Gets fields from a message given a variable argument list.
514 * The variable argument list should contain the type of the
515 * field followed by a pointer to where the value should be
516 * stored. The list is terminated with 0.
518 * @param message the message
519 * @param ... list of fields.
520 * @returns #TRUE on success
523 dbus_message_get_fields (DBusMessage *message,
529 va_start (var_args, message);
530 retval = dbus_message_get_fields_valist (message, var_args);
537 * This function takes a va_list for use by language bindings
539 * @see dbus_message_get_fields
540 * @param message the message
541 * @param var_args list of type/pointer pairs
542 * @returns #TRUE on success
545 dbus_message_get_fields_valist (DBusMessage *message,
548 int spec_type, msg_type, i;
549 DBusMessageIter *iter;
551 iter = dbus_message_get_fields_iter (message);
556 spec_type = va_arg (var_args, int);
559 while (spec_type != 0)
561 msg_type = dbus_message_iter_get_field_type (iter);
563 if (msg_type != spec_type)
565 _dbus_warn ("Field %d is specified to be of type \"%s\", but "
566 "is actually of type \"%s\"\n", i,
567 _dbus_type_to_string (spec_type),
568 _dbus_type_to_string (msg_type));
569 dbus_message_iter_unref (iter);
576 case DBUS_TYPE_INT32:
580 ptr = va_arg (var_args, dbus_int32_t *);
582 *ptr = dbus_message_iter_get_int32 (iter);
585 case DBUS_TYPE_UINT32:
589 ptr = va_arg (var_args, dbus_uint32_t *);
591 *ptr = dbus_message_iter_get_uint32 (iter);
595 case DBUS_TYPE_DOUBLE:
599 ptr = va_arg (var_args, double *);
601 *ptr = dbus_message_iter_get_double (iter);
605 case DBUS_TYPE_STRING:
609 ptr = va_arg (var_args, char **);
611 *ptr = dbus_message_iter_get_string (iter);
615 case DBUS_TYPE_BYTE_ARRAY:
620 ptr = va_arg (var_args, char **);
621 len = va_arg (var_args, int *);
623 *ptr = dbus_message_iter_get_byte_array (iter, len);
627 _dbus_warn ("Unknown field type %d\n", spec_type);
630 spec_type = va_arg (var_args, int);
631 if (spec_type != 0 && !dbus_message_iter_next (iter))
633 _dbus_warn ("More fields than exist in the message were specified\n");
635 dbus_message_iter_unref (iter);
641 dbus_message_iter_unref (iter);
646 * Returns a DBusMessageIter representing the fields of the
649 * @param message the message
650 * @returns a new iter.
653 dbus_message_get_fields_iter (DBusMessage *message)
655 DBusMessageIter *iter;
657 iter = dbus_new (DBusMessageIter, 1);
659 dbus_message_ref (message);
662 iter->message = message;
669 * Increments the reference count of a DBusMessageIter.
671 * @param iter the message iter
672 * @see dbus_message_iter_unref
675 dbus_message_iter_ref (DBusMessageIter *iter)
677 _dbus_assert (iter->refcount > 0);
683 * Decrements the reference count of a DBusMessageIter.
685 * @param iter The message iter
686 * @see dbus_message_iter_ref
689 dbus_message_iter_unref (DBusMessageIter *iter)
691 _dbus_assert (iter->refcount > 0);
695 if (iter->refcount == 0)
697 dbus_message_unref (iter->message);
704 * Checks if an iterator has any more fields.
706 * @param iter the message iter
707 * @returns #TRUE if there are more fields
711 dbus_message_iter_has_next (DBusMessageIter *iter)
715 if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
716 iter->pos, &end_pos))
719 if (end_pos >= _dbus_string_get_length (&iter->message->body))
726 * Moves the iterator to the next field.
728 * @param iter The message iter
729 * @returns #TRUE if the iterator was moved to the next field
732 dbus_message_iter_next (DBusMessageIter *iter)
736 if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
737 iter->pos, &end_pos))
740 if (end_pos >= _dbus_string_get_length (&iter->message->body))
749 * Returns the field type of the field that the
750 * message iterator points at.
752 * @param iter the message iter
753 * @returns the field type
756 dbus_message_iter_get_field_type (DBusMessageIter *iter)
760 if (iter->pos >= _dbus_string_get_length (&iter->message->body))
761 return DBUS_TYPE_INVALID;
763 _dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
765 if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING)
768 return DBUS_TYPE_INVALID;
772 * Returns the string value that an iterator may point to.
773 * Note that you need to check that the iterator points to
774 * a string value before using this function.
776 * @see dbus_message_iter_get_field_type
777 * @param iter the message iter
778 * @returns the string
781 dbus_message_iter_get_string (DBusMessageIter *iter)
783 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_STRING);
785 return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
786 iter->pos + 1, NULL);
790 * Returns the 32 bit signed integer value that an iterator may point to.
791 * Note that you need to check that the iterator points to
792 * a string value before using this function.
794 * @see dbus_message_iter_get_field_type
795 * @param iter the message iter
796 * @returns the integer
799 dbus_message_iter_get_int32 (DBusMessageIter *iter)
801 return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
802 iter->pos + 1, NULL);
806 * Returns the 32 bit unsigned integer value that an iterator may point to.
807 * Note that you need to check that the iterator points to
808 * a string value before using this function.
810 * @see dbus_message_iter_get_field_type
811 * @param iter the message iter
812 * @returns the integer
815 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
817 return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
818 iter->pos + 1, NULL);
822 * Returns the double value that an iterator may point to.
823 * Note that you need to check that the iterator points to
824 * a string value before using this function.
826 * @see dbus_message_iter_get_field_type
827 * @param iter the message iter
828 * @returns the double
831 dbus_message_iter_get_double (DBusMessageIter *iter)
833 return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
834 iter->pos + 1, NULL);
838 dbus_message_iter_get_byte_array (DBusMessageIter *iter, int *len)
840 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_BYTE_ARRAY);
842 return _dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
843 iter->pos + 1, NULL, len);
849 * @addtogroup DBusMessageInternals
854 * @typedef DBusMessageLoader
856 * The DBusMessageLoader object encapsulates the process of converting
857 * a byte stream into a series of DBusMessage. It buffers the incoming
858 * bytes as efficiently as possible, and generates a queue of
859 * messages. DBusMessageLoader is typically used as part of a
860 * DBusTransport implementation. The DBusTransport then hands off
861 * the loaded messages to a DBusConnection, making the messages
862 * visible to the application.
867 * Implementation details of DBusMessageLoader.
868 * All members are private.
870 struct DBusMessageLoader
872 int refcount; /**< Reference count. */
874 DBusString data; /**< Buffered data */
876 DBusList *messages; /**< Complete messages. */
878 unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
880 unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
884 * The initial buffer size of the message loader.
886 * @todo this should be based on min header size plus some average
887 * body size, or something. Or rather, the min header size only, if we
888 * want to try to read only the header, store that in a DBusMessage,
889 * then read only the body and store that, etc., depends on
890 * how we optimize _dbus_message_loader_get_buffer() and what
891 * the exact message format is.
893 #define INITIAL_LOADER_DATA_LEN 32
896 * Creates a new message loader. Returns #NULL if memory can't
899 * @returns new loader, or #NULL.
902 _dbus_message_loader_new (void)
904 DBusMessageLoader *loader;
906 loader = dbus_new0 (DBusMessageLoader, 1);
910 loader->refcount = 1;
912 if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
918 /* preallocate the buffer for speed, ignore failure */
919 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
920 _dbus_string_set_length (&loader->data, 0);
926 * Increments the reference count of the loader.
928 * @param loader the loader.
931 _dbus_message_loader_ref (DBusMessageLoader *loader)
933 loader->refcount += 1;
937 * Decrements the reference count of the loader and finalizes the
938 * loader when the count reaches zero.
940 * @param loader the loader.
943 _dbus_message_loader_unref (DBusMessageLoader *loader)
945 loader->refcount -= 1;
946 if (loader->refcount == 0)
948 _dbus_list_foreach (&loader->messages,
949 (DBusForeachFunction) dbus_message_unref,
951 _dbus_list_clear (&loader->messages);
952 _dbus_string_free (&loader->data);
958 * Gets the buffer to use for reading data from the network. Network
959 * data is read directly into an allocated buffer, which is then used
960 * in the DBusMessage, to avoid as many extra memcpy's as possible.
961 * The buffer must always be returned immediately using
962 * _dbus_message_loader_return_buffer(), even if no bytes are
965 * @todo this function can be a lot more clever. For example
966 * it can probably always return a buffer size to read exactly
967 * the body of the next message, thus avoiding any memory wastage
970 * @param loader the message loader.
971 * @param buffer the buffer
974 _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
977 _dbus_assert (!loader->buffer_outstanding);
979 *buffer = &loader->data;
981 loader->buffer_outstanding = TRUE;
985 * The smallest header size that can occur.
986 * (It won't be valid)
988 #define DBUS_MINIMUM_HEADER_SIZE 16
991 decode_header_data (DBusString *data,
994 dbus_int32_t *client_serial,
1001 /* First demarshal the client serial */
1002 *client_serial = _dbus_demarshal_int32 (data, byte_order, 12, &pos);
1007 /* Now handle the fields */
1008 while (pos < header_len)
1010 _dbus_string_get_const_data_len (data, &field, pos, 4);
1013 if (pos > header_len)
1016 if (strncmp (field, DBUS_HEADER_FIELD_SERVICE, 4) == 0)
1018 *service = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
1020 else if (strncmp (field, DBUS_HEADER_FIELD_NAME, 4) == 0)
1022 *name = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
1026 _dbus_verbose ("Encountered an unknown header field: %c%c%c%c\n",
1027 field[0], field[1], field[2], field[3]);
1029 if (!_dbus_marshal_get_field_end_pos (data, byte_order, pos, &new_pos))
1033 if (new_pos > header_len)
1044 * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
1045 * indicating to the loader how many bytes of the buffer were filled
1046 * in. This function must always be called, even if no bytes were
1047 * successfully read.
1049 * @param loader the loader.
1050 * @param buffer the buffer.
1051 * @param bytes_read number of bytes that were read into the buffer.
1054 _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
1058 _dbus_assert (loader->buffer_outstanding);
1059 _dbus_assert (buffer == &loader->data);
1061 loader->buffer_outstanding = FALSE;
1063 if (loader->corrupted)
1066 while (_dbus_string_get_length (&loader->data) >= 16)
1068 DBusMessage *message;
1069 const char *header_data;
1070 int byte_order, header_len, body_len;
1072 _dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
1073 byte_order = header_data[0];
1075 if (byte_order != DBUS_LITTLE_ENDIAN &&
1076 byte_order != DBUS_BIG_ENDIAN)
1078 loader->corrupted = TRUE;
1082 header_len = dbus_unpack_int32 (byte_order, header_data + 4);
1083 body_len = dbus_unpack_int32 (byte_order, header_data + 8);
1085 if (header_len + body_len > _DBUS_MAX_MESSAGE_LENGTH)
1087 loader->corrupted = TRUE;
1092 if (_dbus_string_get_length (&loader->data) >= header_len + body_len)
1094 dbus_int32_t client_serial;
1095 char *service, *name;
1097 if (!decode_header_data (&loader->data, header_len, byte_order,
1098 &client_serial, &service, &name))
1100 loader->corrupted = TRUE;
1105 message = dbus_message_new (service, name);
1106 dbus_free (service);
1109 if (message == NULL)
1110 break; /* ugh, postpone this I guess. */
1112 _dbus_string_copy (&loader->data, header_len, &message->body, 0);
1113 _dbus_message_set_client_serial (message, client_serial);
1115 _dbus_list_append (&loader->messages, message);
1116 _dbus_string_delete (&loader->data, 0, header_len + body_len);
1118 _dbus_verbose ("Loaded message %p\n", message);
1126 * Pops a loaded message (passing ownership of the message
1127 * to the caller). Returns #NULL if no messages have been
1130 * @param loader the loader.
1131 * @returns the next message, or #NULL if none.
1134 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
1136 return _dbus_list_pop_first (&loader->messages);
1141 * Checks whether the loader is confused due to bad data.
1142 * If messages are received that are invalid, the
1143 * loader gets confused and gives up permanently.
1144 * This state is called "corrupted."
1146 * @param loader the loader
1147 * @returns #TRUE if the loader is hosed.
1150 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
1152 return loader->corrupted;
1156 #ifdef DBUS_BUILD_TESTS
1157 #include "dbus-test.h"
1161 message_iter_test (DBusMessage *message)
1163 DBusMessageIter *iter;
1166 iter = dbus_message_get_fields_iter (message);
1169 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_STRING)
1170 _dbus_assert_not_reached ("Field type isn't string");
1172 str = dbus_message_iter_get_string (iter);
1173 if (strcmp (str, "Test string") != 0)
1174 _dbus_assert_not_reached ("Strings differ");
1177 if (!dbus_message_iter_next (iter))
1178 _dbus_assert_not_reached ("Reached end of fields");
1180 /* Signed integer tests */
1181 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_INT32)
1182 _dbus_assert_not_reached ("Field type isn't int32");
1184 if (dbus_message_iter_get_int32 (iter) != -0x12345678)
1185 _dbus_assert_not_reached ("Signed integers differ");
1187 if (!dbus_message_iter_next (iter))
1188 _dbus_assert_not_reached ("Reached end of fields");
1190 /* Unsigned integer tests */
1191 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_UINT32)
1192 _dbus_assert_not_reached ("Field type isn't int32");
1194 if (dbus_message_iter_get_int32 (iter) != 0xedd1e)
1195 _dbus_assert_not_reached ("Unsigned integers differ");
1197 if (!dbus_message_iter_next (iter))
1198 _dbus_assert_not_reached ("Reached end of fields");
1201 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_DOUBLE)
1202 _dbus_assert_not_reached ("Field type isn't double");
1204 if (dbus_message_iter_get_double (iter) != 3.14159)
1205 _dbus_assert_not_reached ("Doubles differ");
1207 if (dbus_message_iter_next (iter))
1208 _dbus_assert_not_reached ("Didn't reach end of fields");
1210 dbus_message_iter_unref (iter);
1214 * @ingroup DBusMessageInternals
1215 * Unit test for DBusMessage.
1217 * @returns #TRUE on success.
1220 _dbus_message_test (void)
1222 DBusMessage *message;
1223 DBusMessageLoader *loader;
1226 dbus_int32_t our_int;
1230 /* Test the vararg functions */
1231 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
1232 message->client_serial = 1;
1233 dbus_message_append_fields (message,
1234 DBUS_TYPE_INT32, -0x12345678,
1235 DBUS_TYPE_STRING, "Test string",
1236 DBUS_TYPE_DOUBLE, 3.14159,
1239 if (!dbus_message_get_fields (message,
1240 DBUS_TYPE_INT32, &our_int,
1241 DBUS_TYPE_STRING, &our_str,
1242 DBUS_TYPE_DOUBLE, &our_double,
1244 _dbus_assert_not_reached ("Could not get fields");
1246 if (our_int != -0x12345678)
1247 _dbus_assert_not_reached ("integers differ!");
1249 if (our_double != 3.14159)
1250 _dbus_assert_not_reached ("doubles differ!");
1252 if (strcmp (our_str, "Test string") != 0)
1253 _dbus_assert_not_reached ("strings differ!");
1255 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
1256 message->client_serial = 1;
1257 dbus_message_append_string (message, "Test string");
1258 dbus_message_append_int32 (message, -0x12345678);
1259 dbus_message_append_uint32 (message, 0xedd1e);
1260 dbus_message_append_double (message, 3.14159);
1262 message_iter_test (message);
1264 /* Message loader test */
1265 _dbus_message_lock (message);
1266 loader = _dbus_message_loader_new ();
1268 /* Write the header data one byte at a time */
1269 _dbus_string_get_const_data (&message->header, &data);
1270 for (i = 0; i < _dbus_string_get_length (&message->header); i++)
1274 _dbus_message_loader_get_buffer (loader, &buffer);
1275 _dbus_string_append_byte (buffer, data[i]);
1276 _dbus_message_loader_return_buffer (loader, buffer, 1);
1279 /* Write the body data one byte at a time */
1280 _dbus_string_get_const_data (&message->body, &data);
1281 for (i = 0; i < _dbus_string_get_length (&message->body); i++)
1285 _dbus_message_loader_get_buffer (loader, &buffer);
1286 _dbus_string_append_byte (buffer, data[i]);
1287 _dbus_message_loader_return_buffer (loader, buffer, 1);
1290 dbus_message_unref (message);
1292 /* Now pop back the message */
1293 if (_dbus_message_loader_get_is_corrupted (loader))
1294 _dbus_assert_not_reached ("message loader corrupted");
1296 message = _dbus_message_loader_pop_message (loader);
1298 _dbus_assert_not_reached ("received a NULL message");
1300 message_iter_test (message);
1302 dbus_message_unref (message);
1303 _dbus_message_loader_unref (loader);
1308 #endif /* DBUS_BUILD_TESTS */