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"
34 * @defgroup DBusMessageInternals DBusMessage implementation details
35 * @ingroup DBusInternals
36 * @brief DBusMessage private implementation details.
38 * The guts of DBusMessage and its methods.
58 int offset; /**< Offset to start of field (location of name of field
64 * @brief Internals of DBusMessage
66 * Object representing a message received from or to be sent to
67 * another application. This is an opaque object, all members
72 int refcount; /**< Reference count */
74 DBusString header; /**< Header network data, stored
75 * separately from body so we can
76 * independently realloc it.
79 HeaderField header_fields[FIELD_LAST]; /**< Track the location
80 * of each field in "header"
83 DBusString body; /**< Body network data. */
85 char byte_order; /**< Message byte order. */
87 DBusCounter *size_counter; /**< Counter for the size of the message, or #NULL */
88 long size_counter_delta; /**< Size we incremented the size counter by. */
90 unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
94 * @brief Internals of DBusMessageIter
96 * Object representing a position in a message. All fields are internal.
98 struct DBusMessageIter
100 int refcount; /**< Reference count */
102 int pos; /**< Current position in the string */
104 DBusMessage *message; /**< Message used */
108 * Gets the data to be sent over the network for this message.
109 * The header and then the body should be written out.
110 * This function is guaranteed to always return the same
111 * data once a message is locked (with _dbus_message_lock()).
113 * @param message the message.
114 * @param header return location for message header data.
115 * @param body return location for message body data.
118 _dbus_message_get_network_data (DBusMessage *message,
119 const DBusString **header,
120 const DBusString **body)
122 _dbus_assert (message->locked);
124 *header = &message->header;
125 *body = &message->body;
129 adjust_field_offsets (DBusMessage *message,
139 while (i < FIELD_LAST)
141 if (message->header_fields[i].offset > offsets_after)
142 message->header_fields[i].offset += delta;
149 get_string_field (DBusMessage *message,
153 int offset = message->header_fields[field].offset;
159 /* offset points to string length, string data follows it */
160 /* FIXME _dbus_demarshal_const_string() that returned
161 * a reference to the string plus its len might be nice.
165 *len = _dbus_demarshal_int32 (&message->header,
170 _dbus_string_get_const_data (&message->header,
173 return data + (offset + 4);
177 get_int_field (DBusMessage *message,
180 int offset = message->header_fields[field].offset;
183 return -1; /* useless if -1 is a valid value of course */
185 return _dbus_demarshal_int32 (&message->header,
192 append_int_field (DBusMessage *message,
199 _dbus_assert (!message->locked);
201 orig_len = _dbus_string_get_length (&message->header);
203 if (!_dbus_string_align_length (&message->header, 4))
206 if (!_dbus_string_append_len (&message->header, name, 4))
209 if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
212 if (!_dbus_string_align_length (&message->header, 4))
215 message->header_fields[FIELD_REPLY_SERIAL].offset =
216 _dbus_string_get_length (&message->header);
218 if (!_dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER,
225 message->header_fields[field].offset = -1;
226 _dbus_string_set_length (&message->header, orig_len);
231 append_string_field (DBusMessage *message,
238 _dbus_assert (!message->locked);
240 orig_len = _dbus_string_get_length (&message->header);
242 if (!_dbus_string_align_length (&message->header, 4))
245 if (!_dbus_string_append_len (&message->header, name, 4))
248 if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_STRING))
251 if (!_dbus_string_align_length (&message->header, 4))
254 message->header_fields[field].offset =
255 _dbus_string_get_length (&message->header);
257 if (!_dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER,
264 message->header_fields[field].offset = -1;
265 _dbus_string_set_length (&message->header, orig_len);
270 set_int_field (DBusMessage *message,
274 int offset = message->header_fields[field].offset;
276 _dbus_assert (!message->locked);
280 /* need to append the field */
284 case FIELD_REPLY_SERIAL:
285 return append_int_field (message, field,
286 DBUS_HEADER_FIELD_REPLY,
289 _dbus_assert_not_reached ("appending an int field we don't support appending");
295 _dbus_marshal_set_int32 (&message->header,
304 set_string_field (DBusMessage *message,
308 int offset = message->header_fields[field].offset;
310 _dbus_assert (!message->locked);
311 _dbus_assert (value != NULL);
315 /* need to append the field */
320 return append_string_field (message, field,
321 DBUS_HEADER_FIELD_SENDER,
324 _dbus_assert_not_reached ("appending a string field we don't support appending");
334 old_len = _dbus_string_get_length (&message->header);
336 _dbus_string_init_const_len (&v, value,
337 strlen (value) + 1); /* include nul */
338 if (!_dbus_marshal_set_string (&message->header,
343 new_len = _dbus_string_get_length (&message->header);
345 adjust_field_offsets (message,
354 * Sets the client serial of a message.
355 * This can only be done once on a message.
357 * @param message the message
358 * @param client_serial the client serial
361 _dbus_message_set_client_serial (DBusMessage *message,
362 dbus_int32_t client_serial)
364 _dbus_assert (!message->locked);
365 _dbus_assert (_dbus_message_get_client_serial (message) < 0);
367 set_int_field (message, FIELD_CLIENT_SERIAL,
372 * Sets the reply serial of a message (the client serial
373 * of the message this is a reply to).
375 * @param message the message
376 * @param reply_serial the client serial
377 * @returns #FALSE if not enough memory
380 _dbus_message_set_reply_serial (DBusMessage *message,
381 dbus_int32_t reply_serial)
383 _dbus_assert (!message->locked);
385 return set_int_field (message, FIELD_REPLY_SERIAL,
390 * Returns the client serial of a message or
391 * -1 if none has been specified.
393 * @param message the message
394 * @returns the client serial
397 _dbus_message_get_client_serial (DBusMessage *message)
399 return get_int_field (message, FIELD_CLIENT_SERIAL);
403 * Returns the serial that the message is
404 * a reply to or -1 if none.
406 * @param message the message
407 * @returns the reply serial
410 _dbus_message_get_reply_serial (DBusMessage *message)
412 return get_int_field (message, FIELD_REPLY_SERIAL);
416 * Adds a counter to be incremented immediately with the
417 * size of this message, and decremented by the size
418 * of this message when this message if finalized.
420 * @param message the message
421 * @param counter the counter
424 _dbus_message_add_size_counter (DBusMessage *message,
425 DBusCounter *counter)
427 _dbus_assert (message->size_counter == NULL); /* If this fails we may need to keep a list of
428 * counters instead of just one
431 message->size_counter = counter;
432 _dbus_counter_ref (message->size_counter);
434 /* When we can change message size, we may want to
435 * update this each time we do so, or we may want to
436 * just KISS like this.
438 message->size_counter_delta =
439 _dbus_string_get_length (&message->header) +
440 _dbus_string_get_length (&message->body);
442 _dbus_verbose ("message has size %ld\n",
443 message->size_counter_delta);
445 _dbus_counter_adjust (message->size_counter, message->size_counter_delta);
449 dbus_message_create_header (DBusMessage *message,
453 if (!_dbus_string_append_byte (&message->header, DBUS_COMPILER_BYTE_ORDER))
456 if (!_dbus_string_append_len (&message->header, "\0\0\0", 3))
459 message->header_fields[FIELD_HEADER_LENGTH].offset = 4;
460 if (!_dbus_marshal_int32 (&message->header, message->byte_order, 0))
463 message->header_fields[FIELD_BODY_LENGTH].offset = 8;
464 if (!_dbus_marshal_int32 (&message->header, message->byte_order, 0))
467 message->header_fields[FIELD_CLIENT_SERIAL].offset = 12;
468 if (!_dbus_marshal_int32 (&message->header, message->byte_order, -1))
471 /* Marshal message service */
474 if (!append_string_field (message,
476 DBUS_HEADER_FIELD_SERVICE,
481 _dbus_assert (name != NULL);
482 if (!append_string_field (message,
484 DBUS_HEADER_FIELD_NAME,
492 * Locks a message. Allows checking that applications don't keep a
493 * reference to a message in the outgoing queue and change it
494 * underneath us. Messages are locked when they enter the outgoing
495 * queue (dbus_connection_send_message()), and the library complains
496 * if the message is modified while locked.
498 * @param message the message to lock.
501 _dbus_message_lock (DBusMessage *message)
503 if (!message->locked)
505 /* Fill in our lengths */
506 set_int_field (message,
508 _dbus_string_get_length (&message->header));
510 set_int_field (message,
512 _dbus_string_get_length (&message->body));
514 message->locked = TRUE;
521 * @defgroup DBusMessage DBusMessage
523 * @brief Message to be sent or received over a DBusConnection.
525 * A DBusMessage is the most basic unit of communication over a
526 * DBusConnection. A DBusConnection represents a stream of messages
527 * received from a remote application, and a stream of messages
528 * sent to a remote application.
534 * @typedef DBusMessage
536 * Opaque data type representing a message received from or to be
537 * sent to another application.
541 dbus_message_new_empty_header (void)
543 DBusMessage *message;
546 message = dbus_new0 (DBusMessage, 1);
550 message->refcount = 1;
551 message->byte_order = DBUS_COMPILER_BYTE_ORDER;
554 while (i < FIELD_LAST)
556 message->header_fields[i].offset = -1;
560 if (!_dbus_string_init (&message->header, _DBUS_INT_MAX))
566 if (!_dbus_string_init (&message->body, _DBUS_INT_MAX))
568 _dbus_string_free (&message->header);
578 * Constructs a new message. Returns #NULL if memory
579 * can't be allocated for the message.
581 * @todo use DBusString internally to store service and name.
583 * @param service service that the message should be sent to
584 * @param name name of the message
585 * @returns a new DBusMessage, free with dbus_message_unref()
586 * @see dbus_message_unref()
589 dbus_message_new (const char *service,
592 DBusMessage *message;
594 message = dbus_message_new_empty_header ();
598 if (!dbus_message_create_header (message, service, name))
600 dbus_message_unref (message);
608 * Constructs a message that is a reply to some other
609 * message. Returns #NULL if memory can't be allocated
612 * @param name the name of the message
613 * @param original_message the message which the created
614 * message is a reply to.
615 * @returns a new DBusMessage, free with dbus_message_unref()
616 * @see dbus_message_new(), dbus_message_unref()
619 dbus_message_new_reply (const char *name,
620 DBusMessage *original_message)
622 DBusMessage *message;
625 sender = get_string_field (original_message,
628 _dbus_assert (sender != NULL);
630 message = dbus_message_new (sender, name);
635 if (!_dbus_message_set_reply_serial (message,
636 _dbus_message_get_client_serial (original_message)))
638 dbus_message_unref (message);
647 * Increments the reference count of a DBusMessage.
649 * @param message The message
650 * @see dbus_message_unref
653 dbus_message_ref (DBusMessage *message)
655 _dbus_assert (message->refcount > 0);
657 message->refcount += 1;
661 * Decrements the reference count of a DBusMessage.
663 * @param message The message
664 * @see dbus_message_ref
667 dbus_message_unref (DBusMessage *message)
669 _dbus_assert (message->refcount > 0);
671 message->refcount -= 1;
672 if (message->refcount == 0)
674 if (message->size_counter != NULL)
676 _dbus_counter_adjust (message->size_counter,
677 - message->size_counter_delta);
678 _dbus_counter_unref (message->size_counter);
681 _dbus_string_free (&message->header);
682 _dbus_string_free (&message->body);
689 * Gets the name of a message.
691 * @param message the message
692 * @returns the message name (should not be freed)
695 dbus_message_get_name (DBusMessage *message)
697 return get_string_field (message, FIELD_NAME, NULL);
701 * Gets the destination service of a message.
703 * @param message the message
704 * @returns the message destination service (should not be freed)
707 dbus_message_get_service (DBusMessage *message)
709 return get_string_field (message, FIELD_SERVICE, NULL);
713 * Appends fields to a message given a variable argument
714 * list. The variable argument list should contain the type
715 * of the field followed by the value to add.
716 * The list is terminated with 0.
718 * @param message the message
719 * @param first_field_type type of the first field
720 * @param ... value of first field, list of additional type-value pairs
721 * @returns #TRUE on success
724 dbus_message_append_fields (DBusMessage *message,
725 int first_field_type,
731 va_start (var_args, first_field_type);
732 retval = dbus_message_append_fields_valist (message,
741 * This function takes a va_list for use by language bindings
743 * @see dbus_message_append_fields.
744 * @param message the message
745 * @param first_field_type type of first field
746 * @param var_args value of first field, then list of type/value pairs
747 * @returns #TRUE on success
750 dbus_message_append_fields_valist (DBusMessage *message,
751 int first_field_type,
756 old_len = _dbus_string_get_length (&message->body);
758 type = first_field_type;
764 case DBUS_TYPE_INT32:
765 if (!dbus_message_append_int32 (message, va_arg (var_args, dbus_int32_t)))
768 case DBUS_TYPE_UINT32:
769 if (!dbus_message_append_uint32 (message, va_arg (var_args, dbus_uint32_t)))
772 case DBUS_TYPE_DOUBLE:
773 if (!dbus_message_append_double (message, va_arg (var_args, double)))
776 case DBUS_TYPE_STRING:
777 if (!dbus_message_append_string (message, va_arg (var_args, const char *)))
780 case DBUS_TYPE_BYTE_ARRAY:
785 data = va_arg (var_args, unsigned char *);
786 len = va_arg (var_args, int);
788 if (!dbus_message_append_byte_array (message, data, len))
792 case DBUS_TYPE_STRING_ARRAY:
797 data = va_arg (var_args, const char **);
798 len = va_arg (var_args, int);
800 if (!dbus_message_append_string_array (message, data, len))
806 _dbus_warn ("Unknown field type %d\n", type);
809 type = va_arg (var_args, int);
815 _dbus_string_set_length (&message->body, old_len);
820 * Appends a 32 bit signed integer to the message.
822 * @param message the message
823 * @param value the integer value
824 * @returns #TRUE on success
827 dbus_message_append_int32 (DBusMessage *message,
830 _dbus_assert (!message->locked);
832 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
834 _dbus_string_shorten (&message->body, 1);
838 return _dbus_marshal_int32 (&message->body,
839 DBUS_COMPILER_BYTE_ORDER, value);
843 * Appends a 32 bit unsigned integer to the message.
845 * @param message the message
846 * @param value the integer value
847 * @returns #TRUE on success
850 dbus_message_append_uint32 (DBusMessage *message,
853 _dbus_assert (!message->locked);
855 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
857 _dbus_string_shorten (&message->body, 1);
861 return _dbus_marshal_uint32 (&message->body,
862 DBUS_COMPILER_BYTE_ORDER, value);
866 * Appends a double value to the message.
868 * @param message the message
869 * @param value the double value
870 * @returns #TRUE on success
873 dbus_message_append_double (DBusMessage *message,
876 _dbus_assert (!message->locked);
878 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
880 _dbus_string_shorten (&message->body, 1);
884 return _dbus_marshal_double (&message->body,
885 DBUS_COMPILER_BYTE_ORDER, value);
889 * Appends a UTF-8 string to the message.
891 * @param message the message
892 * @param value the string
893 * @returns #TRUE on success
896 dbus_message_append_string (DBusMessage *message,
899 _dbus_assert (!message->locked);
901 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
903 _dbus_string_shorten (&message->body, 1);
907 return _dbus_marshal_string (&message->body,
908 DBUS_COMPILER_BYTE_ORDER, value);
912 * Appends a byte array to the message.
914 * @param message the message
915 * @param value the array
916 * @param len the length of the array
917 * @returns #TRUE on success
920 dbus_message_append_byte_array (DBusMessage *message,
921 unsigned const char *value,
924 _dbus_assert (!message->locked);
926 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
928 _dbus_string_shorten (&message->body, 1);
932 return _dbus_marshal_byte_array (&message->body,
933 DBUS_COMPILER_BYTE_ORDER, value, len);
937 * Appends a string array to the message.
939 * @param message the message
940 * @param value the array
941 * @param len the length of the array
942 * @returns #TRUE on success
945 dbus_message_append_string_array (DBusMessage *message,
949 _dbus_assert (!message->locked);
951 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING_ARRAY))
953 _dbus_string_shorten (&message->body, 1);
957 return _dbus_marshal_string_array (&message->body,
958 DBUS_COMPILER_BYTE_ORDER, value, len);
962 * Gets fields from a message given a variable argument list.
963 * The variable argument list should contain the type of the
964 * field followed by a pointer to where the value should be
965 * stored. The list is terminated with 0.
967 * @todo rename get_args to avoid confusion with header fields
969 * @param message the message
970 * @param first_field_type the first field type
971 * @param ... location for first field value, then list of type-location pairs
972 * @returns result code
975 dbus_message_get_fields (DBusMessage *message,
976 int first_field_type,
979 DBusResultCode retval;
982 va_start (var_args, first_field_type);
983 retval = dbus_message_get_fields_valist (message, first_field_type, var_args);
990 * This function takes a va_list for use by language bindings
992 * @todo this function (or some lower-level non-convenience function)
993 * needs better error handling; should allow the application to
994 * distinguish between out of memory, and bad data from the remote
995 * app. It also needs to not leak a bunch of args when it gets
996 * to the arg that's bad, as that would be a security hole
997 * (allow one app to force another to leak memory)
999 * @todo We need to free the field data when an error occurs.
1001 * @todo rename get_args_valist to avoid confusion with header fields
1003 * @see dbus_message_get_fields
1004 * @param message the message
1005 * @param first_field_type type of the first field
1006 * @param var_args return location for first field, followed by list of type/location pairs
1007 * @returns result code
1010 dbus_message_get_fields_valist (DBusMessage *message,
1011 int first_field_type,
1014 int spec_type, msg_type, i;
1015 DBusMessageIter *iter;
1017 iter = dbus_message_get_fields_iter (message);
1020 return DBUS_RESULT_NO_MEMORY;
1022 spec_type = first_field_type;
1025 while (spec_type != 0)
1027 msg_type = dbus_message_iter_get_field_type (iter);
1029 if (msg_type != spec_type)
1031 _dbus_verbose ("Field %d is specified to be of type \"%s\", but "
1032 "is actually of type \"%s\"\n", i,
1033 _dbus_type_to_string (spec_type),
1034 _dbus_type_to_string (msg_type));
1035 dbus_message_iter_unref (iter);
1037 return DBUS_RESULT_INVALID_FIELDS;
1042 case DBUS_TYPE_INT32:
1046 ptr = va_arg (var_args, dbus_int32_t *);
1048 *ptr = dbus_message_iter_get_int32 (iter);
1051 case DBUS_TYPE_UINT32:
1055 ptr = va_arg (var_args, dbus_uint32_t *);
1057 *ptr = dbus_message_iter_get_uint32 (iter);
1061 case DBUS_TYPE_DOUBLE:
1065 ptr = va_arg (var_args, double *);
1067 *ptr = dbus_message_iter_get_double (iter);
1071 case DBUS_TYPE_STRING:
1075 ptr = va_arg (var_args, char **);
1077 *ptr = dbus_message_iter_get_string (iter);
1080 return DBUS_RESULT_NO_MEMORY;
1085 case DBUS_TYPE_BYTE_ARRAY:
1087 unsigned char **ptr;
1090 ptr = va_arg (var_args, unsigned char **);
1091 len = va_arg (var_args, int *);
1093 *ptr = dbus_message_iter_get_byte_array (iter, len);
1096 return DBUS_RESULT_NO_MEMORY;
1100 case DBUS_TYPE_STRING_ARRAY:
1105 ptr = va_arg (var_args, char ***);
1106 len = va_arg (var_args, int *);
1108 *ptr = dbus_message_iter_get_string_array (iter, len);
1111 return DBUS_RESULT_NO_MEMORY;
1116 _dbus_warn ("Unknown field type %d\n", spec_type);
1119 spec_type = va_arg (var_args, int);
1120 if (spec_type != 0 && !dbus_message_iter_next (iter))
1122 _dbus_verbose ("More fields than exist in the message were specified or field is corrupt\n");
1124 dbus_message_iter_unref (iter);
1125 return DBUS_RESULT_INVALID_FIELDS;
1130 dbus_message_iter_unref (iter);
1131 return DBUS_RESULT_SUCCESS;
1135 * Returns a DBusMessageIter representing the fields of the
1136 * message passed in.
1138 * @todo IMO the message iter should follow the GtkTextIter pattern,
1139 * a static object with a "stamp" value used to detect invalid
1140 * iter uses (uninitialized or after changing the message).
1141 * ref/unref is kind of annoying to deal with, and slower too.
1142 * This implies not ref'ing the message from the iter.
1144 * @todo rename get_args_iter to avoid confusion with header fields
1146 * @param message the message
1147 * @returns a new iter.
1150 dbus_message_get_fields_iter (DBusMessage *message)
1152 DBusMessageIter *iter;
1154 iter = dbus_new (DBusMessageIter, 1);
1156 dbus_message_ref (message);
1159 iter->message = message;
1166 * Increments the reference count of a DBusMessageIter.
1168 * @param iter the message iter
1169 * @see dbus_message_iter_unref
1172 dbus_message_iter_ref (DBusMessageIter *iter)
1174 _dbus_assert (iter->refcount > 0);
1176 iter->refcount += 1;
1180 * Decrements the reference count of a DBusMessageIter.
1182 * @param iter The message iter
1183 * @see dbus_message_iter_ref
1186 dbus_message_iter_unref (DBusMessageIter *iter)
1188 _dbus_assert (iter->refcount > 0);
1190 iter->refcount -= 1;
1192 if (iter->refcount == 0)
1194 dbus_message_unref (iter->message);
1201 * Checks if an iterator has any more fields.
1203 * @param iter the message iter
1204 * @returns #TRUE if there are more fields
1208 dbus_message_iter_has_next (DBusMessageIter *iter)
1212 if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
1213 iter->pos, &end_pos))
1216 if (end_pos >= _dbus_string_get_length (&iter->message->body))
1223 * Moves the iterator to the next field.
1225 * @param iter The message iter
1226 * @returns #TRUE if the iterator was moved to the next field
1229 dbus_message_iter_next (DBusMessageIter *iter)
1233 if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
1234 iter->pos, &end_pos))
1237 if (end_pos >= _dbus_string_get_length (&iter->message->body))
1240 iter->pos = end_pos;
1246 * Returns the field type of the field that the
1247 * message iterator points at.
1249 * @param iter the message iter
1250 * @returns the field type
1253 dbus_message_iter_get_field_type (DBusMessageIter *iter)
1257 if (iter->pos >= _dbus_string_get_length (&iter->message->body))
1258 return DBUS_TYPE_INVALID;
1260 _dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
1262 if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING_ARRAY)
1265 return DBUS_TYPE_INVALID;
1269 * Returns the string value that an iterator may point to.
1270 * Note that you need to check that the iterator points to
1271 * a string value before using this function.
1273 * @see dbus_message_iter_get_field_type
1274 * @param iter the message iter
1275 * @returns the string
1278 dbus_message_iter_get_string (DBusMessageIter *iter)
1280 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_STRING);
1282 return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
1283 iter->pos + 1, NULL);
1287 * Returns the 32 bit signed integer value that an iterator may point to.
1288 * Note that you need to check that the iterator points to
1289 * a string value before using this function.
1291 * @see dbus_message_iter_get_field_type
1292 * @param iter the message iter
1293 * @returns the integer
1296 dbus_message_iter_get_int32 (DBusMessageIter *iter)
1298 return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
1299 iter->pos + 1, NULL);
1303 * Returns the 32 bit unsigned integer value that an iterator may point to.
1304 * Note that you need to check that the iterator points to
1305 * a string value before using this function.
1307 * @see dbus_message_iter_get_field_type
1308 * @param iter the message iter
1309 * @returns the integer
1312 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
1314 return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
1315 iter->pos + 1, NULL);
1319 * Returns the double value that an iterator may point to.
1320 * Note that you need to check that the iterator points to
1321 * a string value before using this function.
1323 * @see dbus_message_iter_get_field_type
1324 * @param iter the message iter
1325 * @returns the double
1328 dbus_message_iter_get_double (DBusMessageIter *iter)
1330 return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
1331 iter->pos + 1, NULL);
1335 * Returns the byte array that the iterator may point to.
1336 * Note that you need to check that the iterator points
1337 * to a byte array prior to using this function.
1339 * @todo this function should probably take "unsigned char **" as
1340 * an out param argument, and return boolean or result code.
1342 * @param iter the iterator
1343 * @param len return location for length of byte array
1344 * @returns the byte array
1347 dbus_message_iter_get_byte_array (DBusMessageIter *iter,
1350 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_BYTE_ARRAY);
1352 return _dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
1353 iter->pos + 1, NULL, len);
1357 * Returns the string array that the iterator may point to.
1358 * Note that you need to check that the iterator points
1359 * to a byte array prior to using this function.
1361 * @todo this function should probably take "char **" as
1362 * an out param argument, and return boolean or result code.
1364 * @param iter the iterator
1365 * @param len return location for length of byte array
1366 * @returns the byte array
1369 dbus_message_iter_get_string_array (DBusMessageIter *iter,
1372 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_STRING_ARRAY);
1374 return _dbus_demarshal_string_array (&iter->message->body, iter->message->byte_order,
1375 iter->pos + 1, NULL, len);
1379 * Sets the message sender.
1381 * @todo implement #NULL sender to unset
1383 * @param message the message
1384 * @param sender the sender
1385 * @returns #FALSE if not enough memory
1388 dbus_message_set_sender (DBusMessage *message,
1391 _dbus_assert (!message->locked);
1395 _dbus_warn ("need to implement unsetting sender field\n");
1400 return set_string_field (message,
1407 dbus_message_get_sender (DBusMessage *message)
1409 return get_string_field (message, FIELD_SENDER, NULL);
1415 * @addtogroup DBusMessageInternals
1420 * @typedef DBusMessageLoader
1422 * The DBusMessageLoader object encapsulates the process of converting
1423 * a byte stream into a series of DBusMessage. It buffers the incoming
1424 * bytes as efficiently as possible, and generates a queue of
1425 * messages. DBusMessageLoader is typically used as part of a
1426 * DBusTransport implementation. The DBusTransport then hands off
1427 * the loaded messages to a DBusConnection, making the messages
1428 * visible to the application.
1433 * Implementation details of DBusMessageLoader.
1434 * All members are private.
1436 struct DBusMessageLoader
1438 int refcount; /**< Reference count. */
1440 DBusString data; /**< Buffered data */
1442 DBusList *messages; /**< Complete messages. */
1444 long max_message_size; /**< Maximum size of a message */
1446 unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
1448 unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
1452 * The initial buffer size of the message loader.
1454 * @todo this should be based on min header size plus some average
1455 * body size, or something. Or rather, the min header size only, if we
1456 * want to try to read only the header, store that in a DBusMessage,
1457 * then read only the body and store that, etc., depends on
1458 * how we optimize _dbus_message_loader_get_buffer() and what
1459 * the exact message format is.
1461 #define INITIAL_LOADER_DATA_LEN 32
1464 * Creates a new message loader. Returns #NULL if memory can't
1467 * @returns new loader, or #NULL.
1470 _dbus_message_loader_new (void)
1472 DBusMessageLoader *loader;
1474 loader = dbus_new0 (DBusMessageLoader, 1);
1478 loader->refcount = 1;
1480 /* Try to cap message size at something that won't *totally* hose
1481 * the system if we have a couple of them.
1483 loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
1485 if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
1491 /* preallocate the buffer for speed, ignore failure */
1492 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
1493 _dbus_string_set_length (&loader->data, 0);
1499 * Increments the reference count of the loader.
1501 * @param loader the loader.
1504 _dbus_message_loader_ref (DBusMessageLoader *loader)
1506 loader->refcount += 1;
1510 * Decrements the reference count of the loader and finalizes the
1511 * loader when the count reaches zero.
1513 * @param loader the loader.
1516 _dbus_message_loader_unref (DBusMessageLoader *loader)
1518 loader->refcount -= 1;
1519 if (loader->refcount == 0)
1521 _dbus_list_foreach (&loader->messages,
1522 (DBusForeachFunction) dbus_message_unref,
1524 _dbus_list_clear (&loader->messages);
1525 _dbus_string_free (&loader->data);
1531 * Gets the buffer to use for reading data from the network. Network
1532 * data is read directly into an allocated buffer, which is then used
1533 * in the DBusMessage, to avoid as many extra memcpy's as possible.
1534 * The buffer must always be returned immediately using
1535 * _dbus_message_loader_return_buffer(), even if no bytes are
1536 * successfully read.
1538 * @todo this function can be a lot more clever. For example
1539 * it can probably always return a buffer size to read exactly
1540 * the body of the next message, thus avoiding any memory wastage
1543 * @param loader the message loader.
1544 * @param buffer the buffer
1547 _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
1548 DBusString **buffer)
1550 _dbus_assert (!loader->buffer_outstanding);
1552 *buffer = &loader->data;
1554 loader->buffer_outstanding = TRUE;
1558 * The smallest header size that can occur.
1559 * (It won't be valid)
1561 #define DBUS_MINIMUM_HEADER_SIZE 16
1563 /** Pack four characters as in "abcd" into a uint32 */
1564 #define FOUR_CHARS_TO_UINT32(a, b, c, d) \
1565 ((((dbus_uint32_t)a) << 24) | \
1566 (((dbus_uint32_t)b) << 16) | \
1567 (((dbus_uint32_t)c) << 8) | \
1570 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
1571 #define DBUS_HEADER_FIELD_NAME_AS_UINT32 \
1572 FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
1574 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
1575 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
1576 FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
1578 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
1579 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32 \
1580 FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
1582 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
1583 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32 \
1584 FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
1587 /* FIXME should be using DBusString for the stuff we demarshal. char*
1588 * evil. Also, out of memory handling here seems suboptimal.
1589 * Should probably report it as a distinct error from "corrupt message,"
1590 * so we can postpone parsing this message. Also, we aren't
1591 * checking for demarshal failure everywhere.
1594 decode_header_data (DBusString *data,
1597 HeaderField fields[FIELD_LAST])
1603 if (header_len < 16)
1607 while (i < FIELD_LAST)
1609 fields[i].offset = -1;
1613 fields[FIELD_HEADER_LENGTH].offset = 4;
1614 fields[FIELD_BODY_LENGTH].offset = 8;
1615 fields[FIELD_CLIENT_SERIAL].offset = 12;
1617 /* Now handle the fields */
1619 while (pos < header_len)
1621 pos = _DBUS_ALIGN_VALUE (pos, 4);
1623 if ((pos + 4) > header_len)
1626 _dbus_string_get_const_data_len (data, &field, pos, 4);
1629 _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
1631 /* I believe FROM_BE is right, but if not we'll find out
1634 switch (DBUS_UINT32_FROM_BE (*(int*)field))
1636 case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
1637 if (fields[FIELD_SERVICE].offset >= 0)
1639 _dbus_verbose ("%s field provided twice\n",
1640 DBUS_HEADER_FIELD_SERVICE);
1644 fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
1645 _dbus_verbose ("Found service name at offset %d\n",
1646 fields[FIELD_SERVICE].offset);
1649 case DBUS_HEADER_FIELD_NAME_AS_UINT32:
1650 if (fields[FIELD_NAME].offset >= 0)
1652 _dbus_verbose ("%s field provided twice\n",
1653 DBUS_HEADER_FIELD_NAME);
1657 fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
1659 _dbus_verbose ("Found message name at offset %d\n",
1660 fields[FIELD_NAME].offset);
1662 case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
1663 if (fields[FIELD_SENDER].offset >= 0)
1665 _dbus_verbose ("%s field provided twice\n",
1666 DBUS_HEADER_FIELD_SENDER);
1670 fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
1672 _dbus_verbose ("Found sender name at offset %d\n",
1673 fields[FIELD_NAME].offset);
1676 case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
1677 if (fields[FIELD_REPLY_SERIAL].offset >= 0)
1679 _dbus_verbose ("%s field provided twice\n",
1680 DBUS_HEADER_FIELD_REPLY);
1684 fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
1686 _dbus_verbose ("Found reply serial at offset %d\n",
1687 fields[FIELD_REPLY_SERIAL].offset);
1691 _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c\n",
1692 field[0], field[1], field[2], field[3]);
1695 /* This function has to validate the fields */
1696 if (!_dbus_marshal_get_field_end_pos (data, byte_order, pos, &new_pos))
1699 if (new_pos > header_len)
1709 * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
1710 * indicating to the loader how many bytes of the buffer were filled
1711 * in. This function must always be called, even if no bytes were
1712 * successfully read.
1714 * @param loader the loader.
1715 * @param buffer the buffer.
1716 * @param bytes_read number of bytes that were read into the buffer.
1719 _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
1723 _dbus_assert (loader->buffer_outstanding);
1724 _dbus_assert (buffer == &loader->data);
1726 loader->buffer_outstanding = FALSE;
1728 if (loader->corrupted)
1731 while (_dbus_string_get_length (&loader->data) >= 16)
1733 DBusMessage *message;
1734 const char *header_data;
1735 int byte_order, header_len, body_len;
1737 _dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
1739 _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
1741 byte_order = header_data[0];
1743 if (byte_order != DBUS_LITTLE_ENDIAN &&
1744 byte_order != DBUS_BIG_ENDIAN)
1746 _dbus_verbose ("Message with bad byte order '%c' received\n",
1748 loader->corrupted = TRUE;
1752 header_len = _dbus_unpack_int32 (byte_order, header_data + 4);
1753 body_len = _dbus_unpack_int32 (byte_order, header_data + 8);
1755 if (header_len + body_len > loader->max_message_size)
1757 _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %d\n",
1758 header_len, body_len, loader->max_message_size);
1759 loader->corrupted = TRUE;
1763 if (_dbus_string_get_length (&loader->data) >= header_len + body_len)
1765 HeaderField fields[FIELD_LAST];
1768 /* FIXME right now if this doesn't have enough memory, the
1769 * loader becomes corrupted. Instead we should just not
1770 * parse this message for now.
1772 if (!decode_header_data (&loader->data, header_len, byte_order,
1775 loader->corrupted = TRUE;
1779 message = dbus_message_new_empty_header ();
1780 if (message == NULL)
1781 break; /* ugh, postpone this I guess. */
1783 /* Copy in the offsets we found */
1785 while (i < FIELD_LAST)
1787 message->header_fields[i] = fields[i];
1791 if (!_dbus_list_append (&loader->messages, message))
1793 dbus_message_unref (message);
1797 _dbus_assert (_dbus_string_get_length (&message->header) == 0);
1798 _dbus_assert (_dbus_string_get_length (&message->body) == 0);
1800 _dbus_assert (_dbus_string_get_length (&loader->data) >=
1801 (header_len + body_len));
1803 if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
1805 _dbus_list_remove_last (&loader->messages, message);
1806 dbus_message_unref (message);
1810 if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
1814 /* put the header back, we'll try again later */
1815 result = _dbus_string_copy_len (&message->header, 0, header_len,
1817 _dbus_assert (result); /* because DBusString never reallocs smaller */
1819 _dbus_list_remove_last (&loader->messages, message);
1820 dbus_message_unref (message);
1824 _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
1825 _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
1827 _dbus_verbose ("Loaded message %p\n", message);
1835 * Pops a loaded message (passing ownership of the message
1836 * to the caller). Returns #NULL if no messages have been
1839 * @param loader the loader.
1840 * @returns the next message, or #NULL if none.
1843 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
1845 return _dbus_list_pop_first (&loader->messages);
1850 * Checks whether the loader is confused due to bad data.
1851 * If messages are received that are invalid, the
1852 * loader gets confused and gives up permanently.
1853 * This state is called "corrupted."
1855 * @param loader the loader
1856 * @returns #TRUE if the loader is hosed.
1859 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
1861 return loader->corrupted;
1865 * Sets the maximum size message we allow.
1867 * @param loader the loader
1868 * @param size the max message size in bytes
1871 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader,
1874 loader->max_message_size = size;
1878 * Gets the maximum allowed message size in bytes.
1880 * @param loader the loader
1881 * @returns max size in bytes
1884 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader)
1886 return loader->max_message_size;
1890 #ifdef DBUS_BUILD_TESTS
1891 #include "dbus-test.h"
1895 message_iter_test (DBusMessage *message)
1897 DBusMessageIter *iter;
1900 iter = dbus_message_get_fields_iter (message);
1903 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_STRING)
1904 _dbus_assert_not_reached ("Field type isn't string");
1906 str = dbus_message_iter_get_string (iter);
1907 if (strcmp (str, "Test string") != 0)
1908 _dbus_assert_not_reached ("Strings differ");
1911 if (!dbus_message_iter_next (iter))
1912 _dbus_assert_not_reached ("Reached end of fields");
1914 /* Signed integer tests */
1915 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_INT32)
1916 _dbus_assert_not_reached ("Field type isn't int32");
1918 if (dbus_message_iter_get_int32 (iter) != -0x12345678)
1919 _dbus_assert_not_reached ("Signed integers differ");
1921 if (!dbus_message_iter_next (iter))
1922 _dbus_assert_not_reached ("Reached end of fields");
1924 /* Unsigned integer tests */
1925 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_UINT32)
1926 _dbus_assert_not_reached ("Field type isn't int32");
1928 if (dbus_message_iter_get_int32 (iter) != 0xedd1e)
1929 _dbus_assert_not_reached ("Unsigned integers differ");
1931 if (!dbus_message_iter_next (iter))
1932 _dbus_assert_not_reached ("Reached end of fields");
1935 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_DOUBLE)
1936 _dbus_assert_not_reached ("Field type isn't double");
1938 if (dbus_message_iter_get_double (iter) != 3.14159)
1939 _dbus_assert_not_reached ("Doubles differ");
1941 if (dbus_message_iter_next (iter))
1942 _dbus_assert_not_reached ("Didn't reach end of fields");
1944 dbus_message_iter_unref (iter);
1948 * @ingroup DBusMessageInternals
1949 * Unit test for DBusMessage.
1951 * @returns #TRUE on success.
1954 _dbus_message_test (void)
1956 DBusMessage *message;
1957 DBusMessageLoader *loader;
1960 dbus_int32_t our_int;
1964 /* Test the vararg functions */
1965 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
1966 _dbus_message_set_client_serial (message, 1);
1967 dbus_message_append_fields (message,
1968 DBUS_TYPE_INT32, -0x12345678,
1969 DBUS_TYPE_STRING, "Test string",
1970 DBUS_TYPE_DOUBLE, 3.14159,
1972 _dbus_verbose_bytes_of_string (&message->header, 0,
1973 _dbus_string_get_length (&message->header));
1974 _dbus_verbose_bytes_of_string (&message->body, 0,
1975 _dbus_string_get_length (&message->body));
1977 if (dbus_message_get_fields (message,
1978 DBUS_TYPE_INT32, &our_int,
1979 DBUS_TYPE_STRING, &our_str,
1980 DBUS_TYPE_DOUBLE, &our_double,
1981 0) != DBUS_RESULT_SUCCESS)
1982 _dbus_assert_not_reached ("Could not get fields");
1984 if (our_int != -0x12345678)
1985 _dbus_assert_not_reached ("integers differ!");
1987 if (our_double != 3.14159)
1988 _dbus_assert_not_reached ("doubles differ!");
1990 if (strcmp (our_str, "Test string") != 0)
1991 _dbus_assert_not_reached ("strings differ!");
1993 dbus_free (our_str);
1994 dbus_message_unref (message);
1996 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
1997 _dbus_message_set_client_serial (message, 1);
1998 _dbus_message_set_reply_serial (message, 0x12345678);
2000 dbus_message_append_string (message, "Test string");
2001 dbus_message_append_int32 (message, -0x12345678);
2002 dbus_message_append_uint32 (message, 0xedd1e);
2003 dbus_message_append_double (message, 3.14159);
2005 message_iter_test (message);
2007 /* Message loader test */
2008 _dbus_message_lock (message);
2009 loader = _dbus_message_loader_new ();
2011 /* Write the header data one byte at a time */
2012 _dbus_string_get_const_data (&message->header, &data);
2013 for (i = 0; i < _dbus_string_get_length (&message->header); i++)
2017 _dbus_message_loader_get_buffer (loader, &buffer);
2018 _dbus_string_append_byte (buffer, data[i]);
2019 _dbus_message_loader_return_buffer (loader, buffer, 1);
2022 /* Write the body data one byte at a time */
2023 _dbus_string_get_const_data (&message->body, &data);
2024 for (i = 0; i < _dbus_string_get_length (&message->body); i++)
2028 _dbus_message_loader_get_buffer (loader, &buffer);
2029 _dbus_string_append_byte (buffer, data[i]);
2030 _dbus_message_loader_return_buffer (loader, buffer, 1);
2033 dbus_message_unref (message);
2035 /* Now pop back the message */
2036 if (_dbus_message_loader_get_is_corrupted (loader))
2037 _dbus_assert_not_reached ("message loader corrupted");
2039 message = _dbus_message_loader_pop_message (loader);
2041 _dbus_assert_not_reached ("received a NULL message");
2043 if (_dbus_message_get_reply_serial (message) != 0x12345678)
2044 _dbus_assert_not_reached ("reply serial fields differ");
2046 message_iter_test (message);
2048 dbus_message_unref (message);
2049 _dbus_message_loader_unref (loader);
2054 #endif /* DBUS_BUILD_TESTS */