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 int 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 DBusString body; /**< Body network data. */
97 char byte_order; /**< Message byte order. */
99 DBusCounter *size_counter; /**< Counter for the size of the message, or #NULL */
100 long size_counter_delta; /**< Size we incremented the size counter by. */
102 unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
106 * @brief Internals of DBusMessageIter
108 * Object representing a position in a message. All fields are internal.
110 struct DBusMessageIter
112 int refcount; /**< Reference count */
114 int pos; /**< Current position in the string */
116 DBusMessage *message; /**< Message used */
120 * Gets the data to be sent over the network for this message.
121 * The header and then the body should be written out.
122 * This function is guaranteed to always return the same
123 * data once a message is locked (with _dbus_message_lock()).
125 * @param message the message.
126 * @param header return location for message header data.
127 * @param body return location for message body data.
130 _dbus_message_get_network_data (DBusMessage *message,
131 const DBusString **header,
132 const DBusString **body)
134 _dbus_assert (message->locked);
136 *header = &message->header;
137 *body = &message->body;
141 adjust_field_offsets (DBusMessage *message,
151 while (i < FIELD_LAST)
153 if (message->header_fields[i].offset > offsets_after)
154 message->header_fields[i].offset += delta;
161 get_string_field (DBusMessage *message,
165 int offset = message->header_fields[field].offset;
171 /* offset points to string length, string data follows it */
172 /* FIXME _dbus_demarshal_const_string() that returned
173 * a reference to the string plus its len might be nice.
177 *len = _dbus_demarshal_uint32 (&message->header,
182 _dbus_string_get_const_data (&message->header,
185 return data + (offset + 4);
189 get_int_field (DBusMessage *message,
192 int offset = message->header_fields[field].offset;
195 return -1; /* useless if -1 is a valid value of course */
197 return _dbus_demarshal_int32 (&message->header,
204 append_int_field (DBusMessage *message,
211 _dbus_assert (!message->locked);
213 orig_len = _dbus_string_get_length (&message->header);
215 if (!_dbus_string_align_length (&message->header, 4))
218 if (!_dbus_string_append_len (&message->header, name, 4))
221 if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
224 if (!_dbus_string_align_length (&message->header, 4))
227 message->header_fields[FIELD_REPLY_SERIAL].offset =
228 _dbus_string_get_length (&message->header);
230 if (!_dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER,
237 message->header_fields[field].offset = -1;
238 _dbus_string_set_length (&message->header, orig_len);
243 append_string_field (DBusMessage *message,
250 _dbus_assert (!message->locked);
252 orig_len = _dbus_string_get_length (&message->header);
254 if (!_dbus_string_align_length (&message->header, 4))
257 if (!_dbus_string_append_len (&message->header, name, 4))
260 if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_STRING))
263 if (!_dbus_string_align_length (&message->header, 4))
266 message->header_fields[field].offset =
267 _dbus_string_get_length (&message->header);
269 if (!_dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER,
276 message->header_fields[field].offset = -1;
277 _dbus_string_set_length (&message->header, orig_len);
282 delete_int_field (DBusMessage *message,
285 int offset = message->header_fields[field].offset;
287 _dbus_assert (!message->locked);
288 _dbus_assert (field_is_named[field]);
293 /* The field typecode and name take up 8 bytes */
294 _dbus_string_delete (&message->header,
298 message->header_fields[field].offset = -1;
300 adjust_field_offsets (message,
306 delete_string_field (DBusMessage *message,
309 int offset = message->header_fields[field].offset;
313 _dbus_assert (!message->locked);
314 _dbus_assert (field_is_named[field]);
319 get_string_field (message, field, &len);
321 /* The field typecode and name take up 8 bytes, and the nul
322 * termination is 1 bytes, string length integer is 4 bytes
324 delete_len = 8 + 4 + 1 + len;
326 _dbus_string_delete (&message->header,
330 message->header_fields[field].offset = -1;
332 adjust_field_offsets (message,
338 set_int_field (DBusMessage *message,
342 int offset = message->header_fields[field].offset;
344 _dbus_assert (!message->locked);
348 /* need to append the field */
352 case FIELD_REPLY_SERIAL:
353 return append_int_field (message, field,
354 DBUS_HEADER_FIELD_REPLY,
357 _dbus_assert_not_reached ("appending an int field we don't support appending");
363 _dbus_marshal_set_int32 (&message->header,
372 set_string_field (DBusMessage *message,
376 int offset = message->header_fields[field].offset;
378 _dbus_assert (!message->locked);
379 _dbus_assert (value != NULL);
383 /* need to append the field */
388 return append_string_field (message, field,
389 DBUS_HEADER_FIELD_SENDER,
392 _dbus_assert_not_reached ("appending a string field we don't support appending");
402 old_len = _dbus_string_get_length (&message->header);
404 _dbus_string_init_const_len (&v, value,
405 strlen (value) + 1); /* include nul */
406 if (!_dbus_marshal_set_string (&message->header,
411 new_len = _dbus_string_get_length (&message->header);
413 adjust_field_offsets (message,
422 * Sets the client serial of a message.
423 * This can only be done once on a message.
425 * @todo client_serial should be called simply
426 * "serial"; it's in outgoing messages for both
427 * the client and the server, it's only client-specific
428 * in the message bus case. It's more like origin_serial
431 * @param message the message
432 * @param client_serial the client serial
435 _dbus_message_set_client_serial (DBusMessage *message,
436 dbus_int32_t client_serial)
438 _dbus_assert (!message->locked);
439 _dbus_assert (_dbus_message_get_client_serial (message) < 0);
441 set_int_field (message, FIELD_CLIENT_SERIAL,
446 * Sets the reply serial of a message (the client serial
447 * of the message this is a reply to).
449 * @param message the message
450 * @param reply_serial the client serial
451 * @returns #FALSE if not enough memory
454 _dbus_message_set_reply_serial (DBusMessage *message,
455 dbus_int32_t reply_serial)
457 _dbus_assert (!message->locked);
459 return set_int_field (message, FIELD_REPLY_SERIAL,
464 * Returns the client serial of a message or
465 * -1 if none has been specified.
467 * @todo see note in _dbus_message_set_client_serial()
468 * about how client_serial is a misnomer
470 * @todo this function should be public, after renaming it.
472 * @param message the message
473 * @returns the client serial
476 _dbus_message_get_client_serial (DBusMessage *message)
478 return get_int_field (message, FIELD_CLIENT_SERIAL);
482 * Returns the serial that the message is
483 * a reply to or -1 if none.
485 * @param message the message
486 * @returns the reply serial
489 _dbus_message_get_reply_serial (DBusMessage *message)
491 return get_int_field (message, FIELD_REPLY_SERIAL);
495 * Adds a counter to be incremented immediately with the
496 * size of this message, and decremented by the size
497 * of this message when this message if finalized.
499 * @param message the message
500 * @param counter the counter
503 _dbus_message_add_size_counter (DBusMessage *message,
504 DBusCounter *counter)
506 _dbus_assert (message->size_counter == NULL); /* If this fails we may need to keep a list of
507 * counters instead of just one
510 message->size_counter = counter;
511 _dbus_counter_ref (message->size_counter);
513 /* When we can change message size, we may want to
514 * update this each time we do so, or we may want to
515 * just KISS like this.
517 message->size_counter_delta =
518 _dbus_string_get_length (&message->header) +
519 _dbus_string_get_length (&message->body);
521 _dbus_verbose ("message has size %ld\n",
522 message->size_counter_delta);
524 _dbus_counter_adjust (message->size_counter, message->size_counter_delta);
528 dbus_message_create_header (DBusMessage *message,
532 if (!_dbus_string_append_byte (&message->header, DBUS_COMPILER_BYTE_ORDER))
535 if (!_dbus_string_append_len (&message->header, "\0\0\0", 3))
538 message->header_fields[FIELD_HEADER_LENGTH].offset = 4;
539 if (!_dbus_marshal_int32 (&message->header, message->byte_order, 0))
542 message->header_fields[FIELD_BODY_LENGTH].offset = 8;
543 if (!_dbus_marshal_int32 (&message->header, message->byte_order, 0))
546 message->header_fields[FIELD_CLIENT_SERIAL].offset = 12;
547 if (!_dbus_marshal_int32 (&message->header, message->byte_order, -1))
550 /* Marshal message service */
553 if (!append_string_field (message,
555 DBUS_HEADER_FIELD_SERVICE,
560 _dbus_assert (name != NULL);
561 if (!append_string_field (message,
563 DBUS_HEADER_FIELD_NAME,
571 * Locks a message. Allows checking that applications don't keep a
572 * reference to a message in the outgoing queue and change it
573 * underneath us. Messages are locked when they enter the outgoing
574 * queue (dbus_connection_send_message()), and the library complains
575 * if the message is modified while locked.
577 * @param message the message to lock.
580 _dbus_message_lock (DBusMessage *message)
582 if (!message->locked)
584 /* Fill in our lengths */
585 set_int_field (message,
587 _dbus_string_get_length (&message->header));
589 set_int_field (message,
591 _dbus_string_get_length (&message->body));
593 message->locked = TRUE;
600 * @defgroup DBusMessage DBusMessage
602 * @brief Message to be sent or received over a DBusConnection.
604 * A DBusMessage is the most basic unit of communication over a
605 * DBusConnection. A DBusConnection represents a stream of messages
606 * received from a remote application, and a stream of messages
607 * sent to a remote application.
613 * @typedef DBusMessage
615 * Opaque data type representing a message received from or to be
616 * sent to another application.
620 dbus_message_new_empty_header (void)
622 DBusMessage *message;
625 message = dbus_new0 (DBusMessage, 1);
629 message->refcount = 1;
630 message->byte_order = DBUS_COMPILER_BYTE_ORDER;
633 while (i < FIELD_LAST)
635 message->header_fields[i].offset = -1;
639 if (!_dbus_string_init (&message->header, _DBUS_INT_MAX))
645 if (!_dbus_string_init (&message->body, _DBUS_INT_MAX))
647 _dbus_string_free (&message->header);
657 * Constructs a new message. Returns #NULL if memory
658 * can't be allocated for the message.
660 * @todo use DBusString internally to store service and name.
662 * @param service service that the message should be sent to
663 * @param name name of the message
664 * @returns a new DBusMessage, free with dbus_message_unref()
665 * @see dbus_message_unref()
668 dbus_message_new (const char *service,
671 DBusMessage *message;
673 message = dbus_message_new_empty_header ();
677 if (!dbus_message_create_header (message, service, name))
679 dbus_message_unref (message);
687 * Constructs a message that is a reply to some other
688 * message. Returns #NULL if memory can't be allocated
691 * @param name the name of the message
692 * @param original_message the message which the created
693 * message is a reply to.
694 * @returns a new DBusMessage, free with dbus_message_unref()
695 * @see dbus_message_new(), dbus_message_unref()
698 dbus_message_new_reply (const char *name,
699 DBusMessage *original_message)
701 DBusMessage *message;
704 sender = get_string_field (original_message,
707 _dbus_assert (sender != NULL);
709 message = dbus_message_new (sender, name);
714 if (!_dbus_message_set_reply_serial (message,
715 _dbus_message_get_client_serial (original_message)))
717 dbus_message_unref (message);
725 dbus_message_new_from_message (const DBusMessage *message)
730 retval = dbus_new0 (DBusMessage, 1);
734 retval->refcount = 1;
735 retval->byte_order = message->byte_order;
737 if (!_dbus_string_init (&retval->header, _DBUS_INT_MAX))
743 if (!_dbus_string_init (&retval->body, _DBUS_INT_MAX))
745 _dbus_string_free (&retval->header);
750 if (!_dbus_string_copy (&message->header, 0,
753 _dbus_string_free (&retval->header);
754 _dbus_string_free (&retval->body);
760 if (!_dbus_string_copy (&message->body, 0,
763 _dbus_string_free (&retval->header);
764 _dbus_string_free (&retval->body);
770 for (i = 0; i < FIELD_LAST; i++)
772 retval->header_fields[i].offset = message->header_fields[i].offset;
780 * Increments the reference count of a DBusMessage.
782 * @param message The message
783 * @see dbus_message_unref
786 dbus_message_ref (DBusMessage *message)
788 _dbus_assert (message->refcount > 0);
790 message->refcount += 1;
794 * Decrements the reference count of a DBusMessage.
796 * @param message The message
797 * @see dbus_message_ref
800 dbus_message_unref (DBusMessage *message)
802 _dbus_assert (message->refcount > 0);
804 message->refcount -= 1;
805 if (message->refcount == 0)
807 if (message->size_counter != NULL)
809 _dbus_counter_adjust (message->size_counter,
810 - message->size_counter_delta);
811 _dbus_counter_unref (message->size_counter);
814 _dbus_string_free (&message->header);
815 _dbus_string_free (&message->body);
822 * Gets the name of a message.
824 * @param message the message
825 * @returns the message name (should not be freed)
828 dbus_message_get_name (DBusMessage *message)
830 return get_string_field (message, FIELD_NAME, NULL);
834 * Gets the destination service of a message.
836 * @param message the message
837 * @returns the message destination service (should not be freed)
840 dbus_message_get_service (DBusMessage *message)
842 return get_string_field (message, FIELD_SERVICE, NULL);
846 * Appends fields to a message given a variable argument
847 * list. The variable argument list should contain the type
848 * of the field followed by the value to add.
849 * The list is terminated with 0.
851 * @param message the message
852 * @param first_field_type type of the first field
853 * @param ... value of first field, list of additional type-value pairs
854 * @returns #TRUE on success
857 dbus_message_append_fields (DBusMessage *message,
858 int first_field_type,
864 va_start (var_args, first_field_type);
865 retval = dbus_message_append_fields_valist (message,
874 * This function takes a va_list for use by language bindings
876 * @see dbus_message_append_fields.
877 * @param message the message
878 * @param first_field_type type of first field
879 * @param var_args value of first field, then list of type/value pairs
880 * @returns #TRUE on success
883 dbus_message_append_fields_valist (DBusMessage *message,
884 int first_field_type,
889 old_len = _dbus_string_get_length (&message->body);
891 type = first_field_type;
897 case DBUS_TYPE_INT32:
898 if (!dbus_message_append_int32 (message, va_arg (var_args, dbus_int32_t)))
901 case DBUS_TYPE_UINT32:
902 if (!dbus_message_append_uint32 (message, va_arg (var_args, dbus_uint32_t)))
905 case DBUS_TYPE_DOUBLE:
906 if (!dbus_message_append_double (message, va_arg (var_args, double)))
909 case DBUS_TYPE_STRING:
910 if (!dbus_message_append_string (message, va_arg (var_args, const char *)))
913 case DBUS_TYPE_BYTE_ARRAY:
918 data = va_arg (var_args, unsigned char *);
919 len = va_arg (var_args, int);
921 if (!dbus_message_append_byte_array (message, data, len))
925 case DBUS_TYPE_STRING_ARRAY:
930 data = va_arg (var_args, const char **);
931 len = va_arg (var_args, int);
933 if (!dbus_message_append_string_array (message, data, len))
939 _dbus_warn ("Unknown field type %d\n", type);
942 type = va_arg (var_args, int);
948 _dbus_string_set_length (&message->body, old_len);
953 * Appends a 32 bit signed integer to the message.
955 * @param message the message
956 * @param value the integer value
957 * @returns #TRUE on success
960 dbus_message_append_int32 (DBusMessage *message,
963 _dbus_assert (!message->locked);
965 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
967 _dbus_string_shorten (&message->body, 1);
971 return _dbus_marshal_int32 (&message->body,
972 DBUS_COMPILER_BYTE_ORDER, value);
976 * Appends a 32 bit unsigned integer to the message.
978 * @param message the message
979 * @param value the integer value
980 * @returns #TRUE on success
983 dbus_message_append_uint32 (DBusMessage *message,
986 _dbus_assert (!message->locked);
988 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
990 _dbus_string_shorten (&message->body, 1);
994 return _dbus_marshal_uint32 (&message->body,
995 DBUS_COMPILER_BYTE_ORDER, value);
999 * Appends a double value to the message.
1001 * @param message the message
1002 * @param value the double value
1003 * @returns #TRUE on success
1006 dbus_message_append_double (DBusMessage *message,
1009 _dbus_assert (!message->locked);
1011 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
1013 _dbus_string_shorten (&message->body, 1);
1017 return _dbus_marshal_double (&message->body,
1018 DBUS_COMPILER_BYTE_ORDER, value);
1022 * Appends a UTF-8 string to the message.
1024 * @param message the message
1025 * @param value the string
1026 * @returns #TRUE on success
1029 dbus_message_append_string (DBusMessage *message,
1032 _dbus_assert (!message->locked);
1034 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
1036 _dbus_string_shorten (&message->body, 1);
1040 return _dbus_marshal_string (&message->body,
1041 DBUS_COMPILER_BYTE_ORDER, value);
1045 * Appends a byte array to the message.
1047 * @param message the message
1048 * @param value the array
1049 * @param len the length of the array
1050 * @returns #TRUE on success
1053 dbus_message_append_byte_array (DBusMessage *message,
1054 unsigned const char *value,
1057 _dbus_assert (!message->locked);
1059 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
1061 _dbus_string_shorten (&message->body, 1);
1065 return _dbus_marshal_byte_array (&message->body,
1066 DBUS_COMPILER_BYTE_ORDER, value, len);
1070 * Appends a string array to the message.
1072 * @param message the message
1073 * @param value the array
1074 * @param len the length of the array
1075 * @returns #TRUE on success
1078 dbus_message_append_string_array (DBusMessage *message,
1082 _dbus_assert (!message->locked);
1084 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING_ARRAY))
1086 _dbus_string_shorten (&message->body, 1);
1090 return _dbus_marshal_string_array (&message->body,
1091 DBUS_COMPILER_BYTE_ORDER, value, len);
1095 * Gets fields from a message given a variable argument list.
1096 * The variable argument list should contain the type of the
1097 * field followed by a pointer to where the value should be
1098 * stored. The list is terminated with 0.
1100 * @todo rename get_args to avoid confusion with header fields
1102 * @param message the message
1103 * @param first_field_type the first field type
1104 * @param ... location for first field value, then list of type-location pairs
1105 * @returns result code
1108 dbus_message_get_fields (DBusMessage *message,
1109 int first_field_type,
1112 DBusResultCode retval;
1115 va_start (var_args, first_field_type);
1116 retval = dbus_message_get_fields_valist (message, first_field_type, var_args);
1123 * This function takes a va_list for use by language bindings
1125 * @todo this function (or some lower-level non-convenience function)
1126 * needs better error handling; should allow the application to
1127 * distinguish between out of memory, and bad data from the remote
1128 * app. It also needs to not leak a bunch of args when it gets
1129 * to the arg that's bad, as that would be a security hole
1130 * (allow one app to force another to leak memory)
1132 * @todo We need to free the field data when an error occurs.
1134 * @todo rename get_args_valist to avoid confusion with header fields
1136 * @see dbus_message_get_fields
1137 * @param message the message
1138 * @param first_field_type type of the first field
1139 * @param var_args return location for first field, followed by list of type/location pairs
1140 * @returns result code
1143 dbus_message_get_fields_valist (DBusMessage *message,
1144 int first_field_type,
1147 int spec_type, msg_type, i;
1148 DBusMessageIter *iter;
1150 iter = dbus_message_get_fields_iter (message);
1153 return DBUS_RESULT_NO_MEMORY;
1155 spec_type = first_field_type;
1158 while (spec_type != 0)
1160 msg_type = dbus_message_iter_get_field_type (iter);
1162 if (msg_type != spec_type)
1164 _dbus_verbose ("Field %d is specified to be of type \"%s\", but "
1165 "is actually of type \"%s\"\n", i,
1166 _dbus_type_to_string (spec_type),
1167 _dbus_type_to_string (msg_type));
1168 dbus_message_iter_unref (iter);
1170 return DBUS_RESULT_INVALID_FIELDS;
1175 case DBUS_TYPE_INT32:
1179 ptr = va_arg (var_args, dbus_int32_t *);
1181 *ptr = dbus_message_iter_get_int32 (iter);
1184 case DBUS_TYPE_UINT32:
1188 ptr = va_arg (var_args, dbus_uint32_t *);
1190 *ptr = dbus_message_iter_get_uint32 (iter);
1194 case DBUS_TYPE_DOUBLE:
1198 ptr = va_arg (var_args, double *);
1200 *ptr = dbus_message_iter_get_double (iter);
1204 case DBUS_TYPE_STRING:
1208 ptr = va_arg (var_args, char **);
1210 *ptr = dbus_message_iter_get_string (iter);
1213 return DBUS_RESULT_NO_MEMORY;
1218 case DBUS_TYPE_BYTE_ARRAY:
1220 unsigned char **ptr;
1223 ptr = va_arg (var_args, unsigned char **);
1224 len = va_arg (var_args, int *);
1226 *ptr = dbus_message_iter_get_byte_array (iter, len);
1229 return DBUS_RESULT_NO_MEMORY;
1233 case DBUS_TYPE_STRING_ARRAY:
1238 ptr = va_arg (var_args, char ***);
1239 len = va_arg (var_args, int *);
1241 *ptr = dbus_message_iter_get_string_array (iter, len);
1244 return DBUS_RESULT_NO_MEMORY;
1249 _dbus_warn ("Unknown field type %d\n", spec_type);
1252 spec_type = va_arg (var_args, int);
1253 if (spec_type != 0 && !dbus_message_iter_next (iter))
1255 _dbus_verbose ("More fields than exist in the message were specified or field is corrupt\n");
1257 dbus_message_iter_unref (iter);
1258 return DBUS_RESULT_INVALID_FIELDS;
1263 dbus_message_iter_unref (iter);
1264 return DBUS_RESULT_SUCCESS;
1268 * Returns a DBusMessageIter representing the fields of the
1269 * message passed in.
1271 * @todo IMO the message iter should follow the GtkTextIter pattern,
1272 * a static object with a "stamp" value used to detect invalid
1273 * iter uses (uninitialized or after changing the message).
1274 * ref/unref is kind of annoying to deal with, and slower too.
1275 * This implies not ref'ing the message from the iter.
1277 * @todo rename get_args_iter to avoid confusion with header fields
1279 * @param message the message
1280 * @returns a new iter.
1283 dbus_message_get_fields_iter (DBusMessage *message)
1285 DBusMessageIter *iter;
1287 iter = dbus_new (DBusMessageIter, 1);
1289 dbus_message_ref (message);
1292 iter->message = message;
1299 * Increments the reference count of a DBusMessageIter.
1301 * @param iter the message iter
1302 * @see dbus_message_iter_unref
1305 dbus_message_iter_ref (DBusMessageIter *iter)
1307 _dbus_assert (iter->refcount > 0);
1309 iter->refcount += 1;
1313 * Decrements the reference count of a DBusMessageIter.
1315 * @param iter The message iter
1316 * @see dbus_message_iter_ref
1319 dbus_message_iter_unref (DBusMessageIter *iter)
1321 _dbus_assert (iter->refcount > 0);
1323 iter->refcount -= 1;
1325 if (iter->refcount == 0)
1327 dbus_message_unref (iter->message);
1334 * Checks if an iterator has any more fields.
1336 * @param iter the message iter
1337 * @returns #TRUE if there are more fields
1341 dbus_message_iter_has_next (DBusMessageIter *iter)
1345 if (!_dbus_marshal_get_field_end_pos (&iter->message->body,
1346 iter->message->byte_order,
1347 iter->pos, &end_pos))
1350 if (end_pos >= _dbus_string_get_length (&iter->message->body))
1357 * Moves the iterator to the next field.
1359 * @param iter The message iter
1360 * @returns #TRUE if the iterator was moved to the next field
1363 dbus_message_iter_next (DBusMessageIter *iter)
1367 if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
1368 iter->pos, &end_pos))
1371 if (end_pos >= _dbus_string_get_length (&iter->message->body))
1374 iter->pos = end_pos;
1380 * Returns the field type of the field that the
1381 * message iterator points at.
1383 * @param iter the message iter
1384 * @returns the field type
1387 dbus_message_iter_get_field_type (DBusMessageIter *iter)
1391 if (iter->pos >= _dbus_string_get_length (&iter->message->body))
1392 return DBUS_TYPE_INVALID;
1394 _dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
1396 if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING_ARRAY)
1399 return DBUS_TYPE_INVALID;
1403 * Returns the string value that an iterator may point to.
1404 * Note that you need to check that the iterator points to
1405 * a string value before using this function.
1407 * @see dbus_message_iter_get_field_type
1408 * @param iter the message iter
1409 * @returns the string
1412 dbus_message_iter_get_string (DBusMessageIter *iter)
1414 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_STRING);
1416 return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
1417 iter->pos + 1, NULL);
1421 * Returns the 32 bit signed integer value that an iterator may point to.
1422 * Note that you need to check that the iterator points to
1423 * a string value before using this function.
1425 * @see dbus_message_iter_get_field_type
1426 * @param iter the message iter
1427 * @returns the integer
1430 dbus_message_iter_get_int32 (DBusMessageIter *iter)
1432 return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
1433 iter->pos + 1, NULL);
1437 * Returns the 32 bit unsigned integer value that an iterator may point to.
1438 * Note that you need to check that the iterator points to
1439 * a string value before using this function.
1441 * @see dbus_message_iter_get_field_type
1442 * @param iter the message iter
1443 * @returns the integer
1446 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
1448 return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
1449 iter->pos + 1, NULL);
1453 * Returns the double value that an iterator may point to.
1454 * Note that you need to check that the iterator points to
1455 * a string value before using this function.
1457 * @see dbus_message_iter_get_field_type
1458 * @param iter the message iter
1459 * @returns the double
1462 dbus_message_iter_get_double (DBusMessageIter *iter)
1464 return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
1465 iter->pos + 1, NULL);
1469 * Returns the byte array that the iterator may point to.
1470 * Note that you need to check that the iterator points
1471 * to a byte array prior to using this function.
1473 * @todo this function should probably take "unsigned char **" as
1474 * an out param argument, and return boolean or result code.
1476 * @param iter the iterator
1477 * @param len return location for length of byte array
1478 * @returns the byte array
1481 dbus_message_iter_get_byte_array (DBusMessageIter *iter,
1484 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_BYTE_ARRAY);
1486 return _dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
1487 iter->pos + 1, NULL, len);
1491 * Returns the string array that the iterator may point to.
1492 * Note that you need to check that the iterator points
1493 * to a byte array prior to using this function.
1495 * @todo this function should probably take "char **" as
1496 * an out param argument, and return boolean or result code.
1498 * @param iter the iterator
1499 * @param len return location for length of byte array
1500 * @returns the byte array
1503 dbus_message_iter_get_string_array (DBusMessageIter *iter,
1506 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_STRING_ARRAY);
1508 return _dbus_demarshal_string_array (&iter->message->body, iter->message->byte_order,
1509 iter->pos + 1, NULL, len);
1513 * Sets the message sender.
1515 * @todo implement #NULL sender to unset
1517 * @param message the message
1518 * @param sender the sender
1519 * @returns #FALSE if not enough memory
1522 dbus_message_set_sender (DBusMessage *message,
1525 _dbus_assert (!message->locked);
1529 delete_string_field (message, FIELD_SENDER);
1534 return set_string_field (message,
1541 * Gets the service which originated this message,
1542 * or #NULL if unknown or inapplicable.
1544 * @param message the message
1545 * @returns the service name or #NULL
1548 dbus_message_get_sender (DBusMessage *message)
1550 return get_string_field (message, FIELD_SENDER, NULL);
1556 * @addtogroup DBusMessageInternals
1561 * @typedef DBusMessageLoader
1563 * The DBusMessageLoader object encapsulates the process of converting
1564 * a byte stream into a series of DBusMessage. It buffers the incoming
1565 * bytes as efficiently as possible, and generates a queue of
1566 * messages. DBusMessageLoader is typically used as part of a
1567 * DBusTransport implementation. The DBusTransport then hands off
1568 * the loaded messages to a DBusConnection, making the messages
1569 * visible to the application.
1574 * Implementation details of DBusMessageLoader.
1575 * All members are private.
1577 struct DBusMessageLoader
1579 int refcount; /**< Reference count. */
1581 DBusString data; /**< Buffered data */
1583 DBusList *messages; /**< Complete messages. */
1585 long max_message_size; /**< Maximum size of a message */
1587 unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
1589 unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
1593 * The initial buffer size of the message loader.
1595 * @todo this should be based on min header size plus some average
1596 * body size, or something. Or rather, the min header size only, if we
1597 * want to try to read only the header, store that in a DBusMessage,
1598 * then read only the body and store that, etc., depends on
1599 * how we optimize _dbus_message_loader_get_buffer() and what
1600 * the exact message format is.
1602 #define INITIAL_LOADER_DATA_LEN 32
1605 * Creates a new message loader. Returns #NULL if memory can't
1608 * @returns new loader, or #NULL.
1611 _dbus_message_loader_new (void)
1613 DBusMessageLoader *loader;
1615 loader = dbus_new0 (DBusMessageLoader, 1);
1619 loader->refcount = 1;
1621 /* Try to cap message size at something that won't *totally* hose
1622 * the system if we have a couple of them.
1624 loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
1626 if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
1632 /* preallocate the buffer for speed, ignore failure */
1633 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
1634 _dbus_string_set_length (&loader->data, 0);
1640 * Increments the reference count of the loader.
1642 * @param loader the loader.
1645 _dbus_message_loader_ref (DBusMessageLoader *loader)
1647 loader->refcount += 1;
1651 * Decrements the reference count of the loader and finalizes the
1652 * loader when the count reaches zero.
1654 * @param loader the loader.
1657 _dbus_message_loader_unref (DBusMessageLoader *loader)
1659 loader->refcount -= 1;
1660 if (loader->refcount == 0)
1662 _dbus_list_foreach (&loader->messages,
1663 (DBusForeachFunction) dbus_message_unref,
1665 _dbus_list_clear (&loader->messages);
1666 _dbus_string_free (&loader->data);
1672 * Gets the buffer to use for reading data from the network. Network
1673 * data is read directly into an allocated buffer, which is then used
1674 * in the DBusMessage, to avoid as many extra memcpy's as possible.
1675 * The buffer must always be returned immediately using
1676 * _dbus_message_loader_return_buffer(), even if no bytes are
1677 * successfully read.
1679 * @todo this function can be a lot more clever. For example
1680 * it can probably always return a buffer size to read exactly
1681 * the body of the next message, thus avoiding any memory wastage
1684 * @param loader the message loader.
1685 * @param buffer the buffer
1688 _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
1689 DBusString **buffer)
1691 _dbus_assert (!loader->buffer_outstanding);
1693 *buffer = &loader->data;
1695 loader->buffer_outstanding = TRUE;
1699 * The smallest header size that can occur.
1700 * (It won't be valid)
1702 #define DBUS_MINIMUM_HEADER_SIZE 16
1704 /** Pack four characters as in "abcd" into a uint32 */
1705 #define FOUR_CHARS_TO_UINT32(a, b, c, d) \
1706 ((((dbus_uint32_t)a) << 24) | \
1707 (((dbus_uint32_t)b) << 16) | \
1708 (((dbus_uint32_t)c) << 8) | \
1711 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
1712 #define DBUS_HEADER_FIELD_NAME_AS_UINT32 \
1713 FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
1715 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
1716 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
1717 FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
1719 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
1720 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32 \
1721 FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
1723 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
1724 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32 \
1725 FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
1728 /* FIXME should be using DBusString for the stuff we demarshal. char*
1729 * evil. Also, out of memory handling here seems suboptimal.
1730 * Should probably report it as a distinct error from "corrupt message,"
1731 * so we can postpone parsing this message. Also, we aren't
1732 * checking for demarshal failure everywhere.
1735 decode_header_data (DBusString *data,
1738 HeaderField fields[FIELD_LAST])
1744 if (header_len < 16)
1748 while (i < FIELD_LAST)
1750 fields[i].offset = -1;
1754 fields[FIELD_HEADER_LENGTH].offset = 4;
1755 fields[FIELD_BODY_LENGTH].offset = 8;
1756 fields[FIELD_CLIENT_SERIAL].offset = 12;
1758 /* Now handle the fields */
1760 while (pos < header_len)
1762 pos = _DBUS_ALIGN_VALUE (pos, 4);
1764 if ((pos + 4) > header_len)
1767 _dbus_string_get_const_data_len (data, &field, pos, 4);
1770 _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
1772 /* I believe FROM_BE is right, but if not we'll find out
1775 switch (DBUS_UINT32_FROM_BE (*(int*)field))
1777 case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
1778 if (fields[FIELD_SERVICE].offset >= 0)
1780 _dbus_verbose ("%s field provided twice\n",
1781 DBUS_HEADER_FIELD_SERVICE);
1785 fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
1786 _dbus_verbose ("Found service name at offset %d\n",
1787 fields[FIELD_SERVICE].offset);
1790 case DBUS_HEADER_FIELD_NAME_AS_UINT32:
1791 if (fields[FIELD_NAME].offset >= 0)
1793 _dbus_verbose ("%s field provided twice\n",
1794 DBUS_HEADER_FIELD_NAME);
1798 fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
1800 _dbus_verbose ("Found message name at offset %d\n",
1801 fields[FIELD_NAME].offset);
1803 case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
1804 if (fields[FIELD_SENDER].offset >= 0)
1806 _dbus_verbose ("%s field provided twice\n",
1807 DBUS_HEADER_FIELD_SENDER);
1811 fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
1813 _dbus_verbose ("Found sender name at offset %d\n",
1814 fields[FIELD_NAME].offset);
1817 case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
1818 if (fields[FIELD_REPLY_SERIAL].offset >= 0)
1820 _dbus_verbose ("%s field provided twice\n",
1821 DBUS_HEADER_FIELD_REPLY);
1825 fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
1827 _dbus_verbose ("Found reply serial at offset %d\n",
1828 fields[FIELD_REPLY_SERIAL].offset);
1832 _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c\n",
1833 field[0], field[1], field[2], field[3]);
1836 /* This function has to validate the fields */
1837 if (!_dbus_marshal_get_field_end_pos (data, byte_order, pos, &new_pos))
1840 if (new_pos > header_len)
1850 * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
1851 * indicating to the loader how many bytes of the buffer were filled
1852 * in. This function must always be called, even if no bytes were
1853 * successfully read.
1855 * @param loader the loader.
1856 * @param buffer the buffer.
1857 * @param bytes_read number of bytes that were read into the buffer.
1860 _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
1864 _dbus_assert (loader->buffer_outstanding);
1865 _dbus_assert (buffer == &loader->data);
1867 loader->buffer_outstanding = FALSE;
1869 if (loader->corrupted)
1872 while (_dbus_string_get_length (&loader->data) >= 16)
1874 DBusMessage *message;
1875 const char *header_data;
1876 int byte_order, header_len, body_len;
1878 _dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
1880 _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
1882 byte_order = header_data[0];
1884 if (byte_order != DBUS_LITTLE_ENDIAN &&
1885 byte_order != DBUS_BIG_ENDIAN)
1887 _dbus_verbose ("Message with bad byte order '%c' received\n",
1889 loader->corrupted = TRUE;
1893 header_len = _dbus_unpack_int32 (byte_order, header_data + 4);
1894 body_len = _dbus_unpack_int32 (byte_order, header_data + 8);
1896 if (header_len + body_len > loader->max_message_size)
1898 _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %d\n",
1899 header_len, body_len, loader->max_message_size);
1900 loader->corrupted = TRUE;
1904 if (_dbus_string_get_length (&loader->data) >= header_len + body_len)
1906 HeaderField fields[FIELD_LAST];
1909 /* FIXME right now if this doesn't have enough memory, the
1910 * loader becomes corrupted. Instead we should just not
1911 * parse this message for now.
1913 if (!decode_header_data (&loader->data, header_len, byte_order,
1916 loader->corrupted = TRUE;
1920 message = dbus_message_new_empty_header ();
1921 if (message == NULL)
1922 break; /* ugh, postpone this I guess. */
1924 /* Copy in the offsets we found */
1926 while (i < FIELD_LAST)
1928 message->header_fields[i] = fields[i];
1932 if (!_dbus_list_append (&loader->messages, message))
1934 dbus_message_unref (message);
1938 _dbus_assert (_dbus_string_get_length (&message->header) == 0);
1939 _dbus_assert (_dbus_string_get_length (&message->body) == 0);
1941 _dbus_assert (_dbus_string_get_length (&loader->data) >=
1942 (header_len + body_len));
1944 if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
1946 _dbus_list_remove_last (&loader->messages, message);
1947 dbus_message_unref (message);
1951 if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
1955 /* put the header back, we'll try again later */
1956 result = _dbus_string_copy_len (&message->header, 0, header_len,
1958 _dbus_assert (result); /* because DBusString never reallocs smaller */
1960 _dbus_list_remove_last (&loader->messages, message);
1961 dbus_message_unref (message);
1965 _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
1966 _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
1968 _dbus_verbose ("Loaded message %p\n", message);
1976 * Pops a loaded message (passing ownership of the message
1977 * to the caller). Returns #NULL if no messages have been
1980 * @param loader the loader.
1981 * @returns the next message, or #NULL if none.
1984 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
1986 return _dbus_list_pop_first (&loader->messages);
1991 * Checks whether the loader is confused due to bad data.
1992 * If messages are received that are invalid, the
1993 * loader gets confused and gives up permanently.
1994 * This state is called "corrupted."
1996 * @param loader the loader
1997 * @returns #TRUE if the loader is hosed.
2000 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
2002 return loader->corrupted;
2006 * Sets the maximum size message we allow.
2008 * @param loader the loader
2009 * @param size the max message size in bytes
2012 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader,
2015 loader->max_message_size = size;
2019 * Gets the maximum allowed message size in bytes.
2021 * @param loader the loader
2022 * @returns max size in bytes
2025 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader)
2027 return loader->max_message_size;
2031 #ifdef DBUS_BUILD_TESTS
2032 #include "dbus-test.h"
2036 message_iter_test (DBusMessage *message)
2038 DBusMessageIter *iter;
2041 iter = dbus_message_get_fields_iter (message);
2044 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_STRING)
2045 _dbus_assert_not_reached ("Field type isn't string");
2047 str = dbus_message_iter_get_string (iter);
2048 if (strcmp (str, "Test string") != 0)
2049 _dbus_assert_not_reached ("Strings differ");
2052 if (!dbus_message_iter_next (iter))
2053 _dbus_assert_not_reached ("Reached end of fields");
2055 /* Signed integer tests */
2056 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_INT32)
2057 _dbus_assert_not_reached ("Field type isn't int32");
2059 if (dbus_message_iter_get_int32 (iter) != -0x12345678)
2060 _dbus_assert_not_reached ("Signed integers differ");
2062 if (!dbus_message_iter_next (iter))
2063 _dbus_assert_not_reached ("Reached end of fields");
2065 /* Unsigned integer tests */
2066 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_UINT32)
2067 _dbus_assert_not_reached ("Field type isn't int32");
2069 if (dbus_message_iter_get_int32 (iter) != 0xedd1e)
2070 _dbus_assert_not_reached ("Unsigned integers differ");
2072 if (!dbus_message_iter_next (iter))
2073 _dbus_assert_not_reached ("Reached end of fields");
2076 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_DOUBLE)
2077 _dbus_assert_not_reached ("Field type isn't double");
2079 if (dbus_message_iter_get_double (iter) != 3.14159)
2080 _dbus_assert_not_reached ("Doubles differ");
2082 if (dbus_message_iter_next (iter))
2083 _dbus_assert_not_reached ("Didn't reach end of fields");
2085 dbus_message_iter_unref (iter);
2089 check_message_handling (DBusMessage *message)
2091 DBusMessageIter *iter;
2094 dbus_int32_t client_serial;
2099 client_serial = _dbus_message_get_client_serial (message);
2101 /* can't use set_client_serial due to the assertions at the start of it */
2102 set_int_field (message, FIELD_CLIENT_SERIAL,
2105 if (client_serial != _dbus_message_get_client_serial (message))
2107 _dbus_warn ("get/set cycle for client_serial did not succeed\n");
2111 /* If we implement message_set_field (message, n, value)
2112 * then we would want to test it here
2115 iter = dbus_message_get_fields_iter (message);
2116 while ((type = dbus_message_iter_get_field_type (iter)) != DBUS_TYPE_INVALID)
2120 case DBUS_TYPE_STRING:
2123 str = dbus_message_iter_get_string (iter);
2129 if (!dbus_message_iter_next (iter))
2137 dbus_message_iter_unref (iter);
2143 check_have_valid_message (DBusMessageLoader *loader)
2145 DBusMessage *message;
2151 if (_dbus_message_loader_get_is_corrupted (loader))
2153 _dbus_warn ("loader corrupted on message that was expected to be valid\n");
2157 message = _dbus_message_loader_pop_message (loader);
2158 if (message == NULL)
2160 _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
2164 if (_dbus_string_get_length (&loader->data) > 0)
2166 _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
2170 /* Verify that we're able to properly deal with the message.
2171 * For example, this would detect improper handling of messages
2172 * in nonstandard byte order.
2174 if (!check_message_handling (message))
2181 dbus_message_unref (message);
2186 check_invalid_message (DBusMessageLoader *loader)
2192 if (!_dbus_message_loader_get_is_corrupted (loader))
2194 _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
2205 check_incomplete_message (DBusMessageLoader *loader)
2207 DBusMessage *message;
2213 if (_dbus_message_loader_get_is_corrupted (loader))
2215 _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
2219 message = _dbus_message_loader_pop_message (loader);
2220 if (message != NULL)
2222 _dbus_warn ("loaded message that was expected to be incomplete\n");
2230 dbus_message_unref (message);
2239 } ExpectedMessageValidity;
2242 check_loader_results (DBusMessageLoader *loader,
2243 ExpectedMessageValidity validity)
2248 return check_have_valid_message (loader);
2249 case MESSAGE_INVALID:
2250 return check_invalid_message (loader);
2251 case MESSAGE_INCOMPLETE:
2252 return check_incomplete_message (loader);
2255 _dbus_assert_not_reached ("bad ExpectedMessageValidity");
2260 try_message (const DBusString *filename,
2261 ExpectedMessageValidity validity)
2264 DBusMessageLoader *loader;
2268 const char *filename_c;
2270 _dbus_string_get_const_data (filename, &filename_c);
2272 if (!_dbus_string_ends_with_c_str (filename, ".message"))
2274 _dbus_verbose ("Skipping non-.message file %s\n",
2281 _dbus_string_get_const_data (filename, &s);
2282 printf (" %s\n", s);
2285 _dbus_verbose (" expecting %s\n",
2286 validity == MESSAGE_VALID ? "valid" :
2287 (validity == MESSAGE_INVALID ? "invalid" : "incomplete"));
2292 if (!_dbus_string_init (&data, _DBUS_INT_MAX))
2293 _dbus_assert_not_reached ("could not allocate string\n");
2295 if (!_dbus_message_data_load (&data, filename))
2298 _dbus_string_get_const_data (filename, &s);
2299 _dbus_warn ("Could not load message file %s\n", s);
2303 /* Write the data one byte at a time */
2305 loader = _dbus_message_loader_new ();
2307 len = _dbus_string_get_length (&data);
2308 for (i = 0; i < len; i++)
2312 _dbus_message_loader_get_buffer (loader, &buffer);
2313 _dbus_string_append_byte (buffer,
2314 _dbus_string_get_byte (&data, i));
2315 _dbus_message_loader_return_buffer (loader, buffer, 1);
2318 if (!check_loader_results (loader, validity))
2321 _dbus_message_loader_unref (loader);
2324 /* Write the data all at once */
2326 loader = _dbus_message_loader_new ();
2331 _dbus_message_loader_get_buffer (loader, &buffer);
2332 _dbus_string_copy (&data, 0, buffer,
2333 _dbus_string_get_length (buffer));
2334 _dbus_message_loader_return_buffer (loader, buffer, 1);
2337 if (!check_loader_results (loader, validity))
2340 _dbus_message_loader_unref (loader);
2343 /* Write the data 2 bytes at a time */
2345 loader = _dbus_message_loader_new ();
2347 len = _dbus_string_get_length (&data);
2348 for (i = 0; i < len; i += 2)
2352 _dbus_message_loader_get_buffer (loader, &buffer);
2353 _dbus_string_append_byte (buffer,
2354 _dbus_string_get_byte (&data, i));
2356 _dbus_string_append_byte (buffer,
2357 _dbus_string_get_byte (&data, i+1));
2358 _dbus_message_loader_return_buffer (loader, buffer, 1);
2361 if (!check_loader_results (loader, validity))
2364 _dbus_message_loader_unref (loader);
2374 if (_dbus_string_get_length (&data) > 0)
2375 _dbus_verbose_bytes_of_string (&data, 0,
2376 _dbus_string_get_length (&data));
2378 _dbus_string_get_const_data (filename, &s);
2379 _dbus_warn ("Failed message loader test on %s\n",
2384 _dbus_message_loader_unref (loader);
2385 _dbus_string_free (&data);
2391 process_test_subdir (const DBusString *test_base_dir,
2393 ExpectedMessageValidity validity)
2395 DBusString test_directory;
2396 DBusString filename;
2399 DBusResultCode result;
2404 if (!_dbus_string_init (&test_directory, _DBUS_INT_MAX))
2405 _dbus_assert_not_reached ("didn't allocate test_directory\n");
2407 _dbus_string_init_const (&filename, subdir);
2409 if (!_dbus_string_copy (test_base_dir, 0,
2410 &test_directory, 0))
2411 _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
2413 if (!_dbus_concat_dir_and_file (&test_directory, &filename))
2414 _dbus_assert_not_reached ("could't allocate full path");
2416 _dbus_string_free (&filename);
2417 if (!_dbus_string_init (&filename, _DBUS_INT_MAX))
2418 _dbus_assert_not_reached ("didn't allocate filename string\n");
2420 dir = _dbus_directory_open (&test_directory, &result);
2424 _dbus_string_get_const_data (&test_directory, &s);
2425 _dbus_warn ("Could not open %s: %s\n", s,
2426 dbus_result_to_string (result));
2430 printf ("Testing:\n");
2432 result = DBUS_RESULT_SUCCESS;
2433 while (_dbus_directory_get_next_file (dir, &filename, &result))
2435 DBusString full_path;
2437 if (!_dbus_string_init (&full_path, _DBUS_INT_MAX))
2438 _dbus_assert_not_reached ("couldn't init string");
2440 if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
2441 _dbus_assert_not_reached ("couldn't copy dir to full_path");
2443 if (!_dbus_concat_dir_and_file (&full_path, &filename))
2444 _dbus_assert_not_reached ("couldn't concat file to dir");
2446 if (!try_message (&full_path, validity))
2448 _dbus_string_free (&full_path);
2452 _dbus_string_free (&full_path);
2455 if (result != DBUS_RESULT_SUCCESS)
2458 _dbus_string_get_const_data (&test_directory, &s);
2459 _dbus_warn ("Could not get next file in %s: %s\n",
2460 s, dbus_result_to_string (result));
2469 _dbus_directory_close (dir);
2470 _dbus_string_free (&test_directory);
2471 _dbus_string_free (&filename);
2478 * @ingroup DBusMessageInternals
2479 * Unit test for DBusMessage.
2481 * @returns #TRUE on success.
2484 _dbus_message_test (const char *test_data_dir)
2486 DBusMessage *message;
2487 DBusMessageLoader *loader;
2490 dbus_int32_t our_int;
2493 DBusString test_directory;
2496 /* Test the vararg functions */
2497 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
2498 _dbus_message_set_client_serial (message, 1);
2499 dbus_message_append_fields (message,
2500 DBUS_TYPE_INT32, -0x12345678,
2501 DBUS_TYPE_STRING, "Test string",
2502 DBUS_TYPE_DOUBLE, 3.14159,
2504 _dbus_verbose_bytes_of_string (&message->header, 0,
2505 _dbus_string_get_length (&message->header));
2506 _dbus_verbose_bytes_of_string (&message->body, 0,
2507 _dbus_string_get_length (&message->body));
2509 if (dbus_message_get_fields (message,
2510 DBUS_TYPE_INT32, &our_int,
2511 DBUS_TYPE_STRING, &our_str,
2512 DBUS_TYPE_DOUBLE, &our_double,
2513 0) != DBUS_RESULT_SUCCESS)
2514 _dbus_assert_not_reached ("Could not get fields");
2516 if (our_int != -0x12345678)
2517 _dbus_assert_not_reached ("integers differ!");
2519 if (our_double != 3.14159)
2520 _dbus_assert_not_reached ("doubles differ!");
2522 if (strcmp (our_str, "Test string") != 0)
2523 _dbus_assert_not_reached ("strings differ!");
2525 dbus_free (our_str);
2526 dbus_message_unref (message);
2528 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
2529 _dbus_message_set_client_serial (message, 1);
2530 _dbus_message_set_reply_serial (message, 0x12345678);
2532 dbus_message_append_string (message, "Test string");
2533 dbus_message_append_int32 (message, -0x12345678);
2534 dbus_message_append_uint32 (message, 0xedd1e);
2535 dbus_message_append_double (message, 3.14159);
2537 message_iter_test (message);
2539 /* Message loader test */
2540 _dbus_message_lock (message);
2541 loader = _dbus_message_loader_new ();
2543 /* Write the header data one byte at a time */
2544 _dbus_string_get_const_data (&message->header, &data);
2545 for (i = 0; i < _dbus_string_get_length (&message->header); i++)
2549 _dbus_message_loader_get_buffer (loader, &buffer);
2550 _dbus_string_append_byte (buffer, data[i]);
2551 _dbus_message_loader_return_buffer (loader, buffer, 1);
2554 /* Write the body data one byte at a time */
2555 _dbus_string_get_const_data (&message->body, &data);
2556 for (i = 0; i < _dbus_string_get_length (&message->body); i++)
2560 _dbus_message_loader_get_buffer (loader, &buffer);
2561 _dbus_string_append_byte (buffer, data[i]);
2562 _dbus_message_loader_return_buffer (loader, buffer, 1);
2565 dbus_message_unref (message);
2567 /* Now pop back the message */
2568 if (_dbus_message_loader_get_is_corrupted (loader))
2569 _dbus_assert_not_reached ("message loader corrupted");
2571 message = _dbus_message_loader_pop_message (loader);
2573 _dbus_assert_not_reached ("received a NULL message");
2575 if (_dbus_message_get_reply_serial (message) != 0x12345678)
2576 _dbus_assert_not_reached ("reply serial fields differ");
2578 message_iter_test (message);
2580 dbus_message_unref (message);
2581 _dbus_message_loader_unref (loader);
2583 /* Now load every message in test_data_dir if we have one */
2584 if (test_data_dir == NULL)
2589 _dbus_string_init_const (&test_directory, test_data_dir);
2591 if (!process_test_subdir (&test_directory, "valid-messages",
2594 if (!process_test_subdir (&test_directory, "invalid-messages",
2598 if (!process_test_subdir (&test_directory, "incomplete-messages",
2599 MESSAGE_INCOMPLETE))
2606 _dbus_string_free (&test_directory);
2611 #endif /* DBUS_BUILD_TESTS */