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.
44 * @brief Internals of DBusMessage
46 * Object representing a message received from or to be sent to
47 * another application. This is an opaque object, all members
52 int refcount; /**< Reference count */
54 DBusString header; /**< Header network data, stored
55 * separately from body so we can
56 * independently realloc it.
59 DBusString body; /**< Body network data. */
61 char byte_order; /**< Message byte order. */
63 char *name; /**< Message name. */
64 char *service; /**< Message destination service. */
65 char *sender; /**< Message sender service. */
67 dbus_int32_t client_serial; /**< Client serial or -1 if not set */
68 dbus_int32_t reply_serial; /**< Reply serial or -1 if not set */
70 DBusCounter *size_counter; /**< Counter for the size of the message, or #NULL */
71 long size_counter_delta; /**< Size we incremented the size counter by. */
73 unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
77 * @brief Internals of DBusMessageIter
79 * Object representing a position in a message. All fields are internal.
81 struct DBusMessageIter
83 int refcount; /**< Reference count */
85 int pos; /**< Current position in the string */
87 DBusMessage *message; /**< Message used */
91 * Gets the data to be sent over the network for this message.
92 * The header and then the body should be written out.
93 * This function is guaranteed to always return the same
94 * data once a message is locked (with _dbus_message_lock()).
96 * @param message the message.
97 * @param header return location for message header data.
98 * @param body return location for message body data.
101 _dbus_message_get_network_data (DBusMessage *message,
102 const DBusString **header,
103 const DBusString **body)
105 _dbus_assert (message->locked);
107 *header = &message->header;
108 *body = &message->body;
112 * Sets the client serial of a message.
113 * This can only be done once on a message.
115 * @param message the message
116 * @param client_serial the client serial
119 _dbus_message_set_client_serial (DBusMessage *message,
120 dbus_int32_t client_serial)
122 _dbus_assert (message->client_serial == -1);
124 message->client_serial = client_serial;
128 * Returns the serial that the message is
131 * @param message the message
132 * @returns the reply serial
135 _dbus_message_get_reply_serial (DBusMessage *message)
137 return message->client_serial;
141 * Sets the message sender. This can only
142 * be done once on a message.
144 * @param message the message
145 * @param sender the sender
148 _dbus_message_set_sender (DBusMessage *message,
151 _dbus_assert (message->sender == NULL);
153 message->sender = _dbus_strdup (sender);
157 * Adds a counter to be incremented immediately with the
158 * size of this message, and decremented by the size
159 * of this message when this message if finalized.
161 * @param message the message
162 * @param counter the counter
165 _dbus_message_add_size_counter (DBusMessage *message,
166 DBusCounter *counter)
168 _dbus_assert (message->size_counter == NULL); /* If this fails we may need to keep a list of
169 * counters instead of just one
172 message->size_counter = counter;
173 _dbus_counter_ref (message->size_counter);
175 /* When we can change message size, we may want to
176 * update this each time we do so, or we may want to
177 * just KISS like this.
179 message->size_counter_delta =
180 _dbus_string_get_length (&message->header) +
181 _dbus_string_get_length (&message->body);
183 _dbus_verbose ("message has size %ld\n",
184 message->size_counter_delta);
186 _dbus_counter_adjust (message->size_counter, message->size_counter_delta);
190 dbus_message_write_header (DBusMessage *message)
194 _dbus_assert (message->client_serial != -1);
196 _dbus_string_append_byte (&message->header, DBUS_COMPILER_BYTE_ORDER);
197 _dbus_string_append_len (&message->header, "\0\0\0", 3);
199 /* We just lengthen the string here and pack in the real length later */
200 _dbus_string_lengthen (&message->header, 4);
202 _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER,
203 _dbus_string_get_length (&message->body));
205 /* Marshal client serial */
206 _dbus_assert (message->client_serial >= 0);
207 _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER,
208 message->client_serial);
210 /* Marshal message service */
211 if (message->service)
213 _dbus_string_align_length (&message->header, 4);
214 _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_SERVICE, 4);
215 _dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
217 _dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER,
221 /* Marshal message name */
222 _dbus_assert (message->name != NULL);
223 _dbus_string_align_length (&message->header, 4);
224 _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_NAME, 4);
225 _dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
227 _dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER, message->name);
229 /* Marshal reply serial */
230 if (message->reply_serial != -1)
232 _dbus_string_align_length (&message->header, 4);
233 _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_REPLY, 4);
235 _dbus_string_append_byte (&message->header, DBUS_TYPE_INT32);
236 _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER,
237 message->reply_serial);
243 _dbus_string_align_length (&message->header, 4);
244 _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_SENDER, 4);
245 _dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
247 _dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER,
251 /* Fill in the length */
252 _dbus_string_get_data_len (&message->header, &len_data, 4, 4);
253 _dbus_pack_int32 (_dbus_string_get_length (&message->header),
254 DBUS_COMPILER_BYTE_ORDER, len_data);
258 * Locks a message. Allows checking that applications don't keep a
259 * reference to a message in the outgoing queue and change it
260 * underneath us. Messages are locked when they enter the outgoing
261 * queue (dbus_connection_send_message()), and the library complains
262 * if the message is modified while locked.
264 * @param message the message to lock.
267 _dbus_message_lock (DBusMessage *message)
269 if (!message->locked)
270 dbus_message_write_header (message);
272 message->locked = TRUE;
278 * @defgroup DBusMessage DBusMessage
280 * @brief Message to be sent or received over a DBusConnection.
282 * A DBusMessage is the most basic unit of communication over a
283 * DBusConnection. A DBusConnection represents a stream of messages
284 * received from a remote application, and a stream of messages
285 * sent to a remote application.
291 * @typedef DBusMessage
293 * Opaque data type representing a message received from or to be
294 * sent to another application.
298 * Constructs a new message. Returns #NULL if memory
299 * can't be allocated for the message.
301 * @todo use DBusString internally to store service and name.
303 * @param service service that the message should be sent to
304 * @param name name of the message
305 * @returns a new DBusMessage, free with dbus_message_unref()
306 * @see dbus_message_unref()
309 dbus_message_new (const char *service,
312 DBusMessage *message;
314 message = dbus_new0 (DBusMessage, 1);
318 message->refcount = 1;
319 message->byte_order = DBUS_COMPILER_BYTE_ORDER;
321 message->service = _dbus_strdup (service);
322 message->name = _dbus_strdup (name);
324 message->client_serial = -1;
325 message->reply_serial = -1;
327 if (!_dbus_string_init (&message->header, _DBUS_INT_MAX))
329 dbus_free (message->service);
330 dbus_free (message->name);
335 if (!_dbus_string_init (&message->body, _DBUS_INT_MAX))
337 dbus_free (message->service);
338 dbus_free (message->name);
339 _dbus_string_free (&message->header);
348 * Constructs a message that is a reply to some other
349 * message. Returns #NULL if memory can't be allocated
352 * @param name the name of the message
353 * @param original_message the message which the created
354 * message is a reply to.
355 * @returns a new DBusMessage, free with dbus_message_unref()
356 * @see dbus_message_new(), dbus_message_unref()
359 dbus_message_new_reply (const char *name,
360 DBusMessage *original_message)
362 DBusMessage *message;
364 _dbus_assert (original_message->sender != NULL);
366 message = dbus_message_new (original_message->sender, name);
371 message->reply_serial = original_message->client_serial;
378 * Increments the reference count of a DBusMessage.
380 * @param message The message
381 * @see dbus_message_unref
384 dbus_message_ref (DBusMessage *message)
386 _dbus_assert (message->refcount > 0);
388 message->refcount += 1;
392 * Decrements the reference count of a DBusMessage.
394 * @param message The message
395 * @see dbus_message_ref
398 dbus_message_unref (DBusMessage *message)
400 _dbus_assert (message->refcount > 0);
402 message->refcount -= 1;
403 if (message->refcount == 0)
405 if (message->size_counter != NULL)
407 _dbus_counter_adjust (message->size_counter,
408 - message->size_counter_delta);
409 _dbus_counter_unref (message->size_counter);
412 _dbus_string_free (&message->header);
413 _dbus_string_free (&message->body);
415 dbus_free (message->service);
416 dbus_free (message->name);
422 * Gets the name of a message.
424 * @param message the message
425 * @returns the message name (should not be freed)
428 dbus_message_get_name (DBusMessage *message)
430 return message->name;
434 * Gets the destination service of a message.
436 * @param message the message
437 * @returns the message destination service (should not be freed)
440 dbus_message_get_service (DBusMessage *message)
442 return message->service;
446 * Appends fields to a message given a variable argument
447 * list. The variable argument list should contain the type
448 * of the field followed by the value to add.
449 * The list is terminated with 0.
451 * @param message the message
452 * @param first_field_type type of the first field
453 * @param ... value of first field, list of additional type-value pairs
454 * @returns #TRUE on success
457 dbus_message_append_fields (DBusMessage *message,
458 int first_field_type,
464 va_start (var_args, first_field_type);
465 retval = dbus_message_append_fields_valist (message,
474 * This function takes a va_list for use by language bindings
476 * @see dbus_message_append_fields.
477 * @param message the message
478 * @param first_field_type type of first field
479 * @param var_args value of first field, then list of type/value pairs
480 * @returns #TRUE on success
483 dbus_message_append_fields_valist (DBusMessage *message,
484 int first_field_type,
489 old_len = _dbus_string_get_length (&message->body);
491 type = first_field_type;
497 case DBUS_TYPE_INT32:
498 if (!dbus_message_append_int32 (message, va_arg (var_args, dbus_int32_t)))
501 case DBUS_TYPE_UINT32:
502 if (!dbus_message_append_uint32 (message, va_arg (var_args, dbus_uint32_t)))
505 case DBUS_TYPE_DOUBLE:
506 if (!dbus_message_append_double (message, va_arg (var_args, double)))
509 case DBUS_TYPE_STRING:
510 if (!dbus_message_append_string (message, va_arg (var_args, const char *)))
513 case DBUS_TYPE_BYTE_ARRAY:
518 data = va_arg (var_args, unsigned char *);
519 len = va_arg (var_args, int);
521 if (!dbus_message_append_byte_array (message, data, len))
526 _dbus_warn ("Unknown field type %d\n", type);
529 type = va_arg (var_args, int);
535 _dbus_string_set_length (&message->body, old_len);
540 * Appends a 32 bit signed integer to the message.
542 * @param message the message
543 * @param value the integer value
544 * @returns #TRUE on success
547 dbus_message_append_int32 (DBusMessage *message,
550 _dbus_assert (!message->locked);
552 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
554 _dbus_string_shorten (&message->body, 1);
558 return _dbus_marshal_int32 (&message->body,
559 DBUS_COMPILER_BYTE_ORDER, value);
563 * Appends a 32 bit unsigned integer to the message.
565 * @param message the message
566 * @param value the integer value
567 * @returns #TRUE on success
570 dbus_message_append_uint32 (DBusMessage *message,
573 _dbus_assert (!message->locked);
575 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
577 _dbus_string_shorten (&message->body, 1);
581 return _dbus_marshal_uint32 (&message->body,
582 DBUS_COMPILER_BYTE_ORDER, value);
586 * Appends a double value to the message.
588 * @param message the message
589 * @param value the double value
590 * @returns #TRUE on success
593 dbus_message_append_double (DBusMessage *message,
596 _dbus_assert (!message->locked);
598 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
600 _dbus_string_shorten (&message->body, 1);
604 return _dbus_marshal_double (&message->body,
605 DBUS_COMPILER_BYTE_ORDER, value);
609 * Appends a UTF-8 string to the message.
611 * @param message the message
612 * @param value the string
613 * @returns #TRUE on success
616 dbus_message_append_string (DBusMessage *message,
619 _dbus_assert (!message->locked);
621 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
623 _dbus_string_shorten (&message->body, 1);
627 return _dbus_marshal_string (&message->body,
628 DBUS_COMPILER_BYTE_ORDER, value);
632 * Appends a byte array to the message.
634 * @param message the message
635 * @param value the array
636 * @param len the length of the array
637 * @returns #TRUE on success
640 dbus_message_append_byte_array (DBusMessage *message,
641 unsigned const char *value,
644 _dbus_assert (!message->locked);
646 if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
648 _dbus_string_shorten (&message->body, 1);
652 return _dbus_marshal_byte_array (&message->body,
653 DBUS_COMPILER_BYTE_ORDER, value, len);
657 * Gets fields from a message given a variable argument list.
658 * The variable argument list should contain the type of the
659 * field followed by a pointer to where the value should be
660 * stored. The list is terminated with 0.
662 * @param message the message
663 * @param first_field_type the first field type
664 * @param ... location for first field value, then list of type-location pairs
665 * @returns result code
668 dbus_message_get_fields (DBusMessage *message,
669 int first_field_type,
672 DBusResultCode retval;
675 va_start (var_args, first_field_type);
676 retval = dbus_message_get_fields_valist (message, first_field_type, var_args);
683 * This function takes a va_list for use by language bindings
685 * @todo this function (or some lower-level non-convenience function)
686 * needs better error handling; should allow the application to
687 * distinguish between out of memory, and bad data from the remote
688 * app. It also needs to not leak a bunch of args when it gets
689 * to the arg that's bad, as that would be a security hole
690 * (allow one app to force another to leak memory)
692 * @todo We need to free the field data when an error occurs.
694 * @see dbus_message_get_fields
695 * @param message the message
696 * @param first_field_type type of the first field
697 * @param var_args return location for first field, followed by list of type/location pairs
698 * @returns result code
701 dbus_message_get_fields_valist (DBusMessage *message,
702 int first_field_type,
705 int spec_type, msg_type, i;
706 DBusMessageIter *iter;
708 iter = dbus_message_get_fields_iter (message);
713 spec_type = first_field_type;
716 while (spec_type != 0)
718 msg_type = dbus_message_iter_get_field_type (iter);
720 if (msg_type != spec_type)
722 _dbus_verbose ("Field %d is specified to be of type \"%s\", but "
723 "is actually of type \"%s\"\n", i,
724 _dbus_type_to_string (spec_type),
725 _dbus_type_to_string (msg_type));
726 dbus_message_iter_unref (iter);
728 return DBUS_RESULT_INVALID_FIELDS;
733 case DBUS_TYPE_INT32:
737 ptr = va_arg (var_args, dbus_int32_t *);
739 *ptr = dbus_message_iter_get_int32 (iter);
742 case DBUS_TYPE_UINT32:
746 ptr = va_arg (var_args, dbus_uint32_t *);
748 *ptr = dbus_message_iter_get_uint32 (iter);
752 case DBUS_TYPE_DOUBLE:
756 ptr = va_arg (var_args, double *);
758 *ptr = dbus_message_iter_get_double (iter);
762 case DBUS_TYPE_STRING:
766 ptr = va_arg (var_args, char **);
768 *ptr = dbus_message_iter_get_string (iter);
771 return DBUS_RESULT_NO_MEMORY;
776 case DBUS_TYPE_BYTE_ARRAY:
781 ptr = va_arg (var_args, char **);
782 len = va_arg (var_args, int *);
784 *ptr = dbus_message_iter_get_byte_array (iter, len);
787 return DBUS_RESULT_NO_MEMORY;
792 _dbus_warn ("Unknown field type %d\n", spec_type);
795 spec_type = va_arg (var_args, int);
796 if (spec_type != 0 && !dbus_message_iter_next (iter))
798 _dbus_verbose ("More fields than exist in the message were specified\n");
800 dbus_message_iter_unref (iter);
801 return DBUS_RESULT_INVALID_FIELDS;
806 dbus_message_iter_unref (iter);
807 return DBUS_RESULT_SUCCESS;
811 * Returns a DBusMessageIter representing the fields of the
814 * @todo IMO the message iter should follow the GtkTextIter pattern,
815 * a static object with a "stamp" value used to detect invalid
816 * iter uses (uninitialized or after changing the message).
817 * ref/unref is kind of annoying to deal with, and slower too.
818 * This implies not ref'ing the message from the iter.
820 * @param message the message
821 * @returns a new iter.
824 dbus_message_get_fields_iter (DBusMessage *message)
826 DBusMessageIter *iter;
828 iter = dbus_new (DBusMessageIter, 1);
830 dbus_message_ref (message);
833 iter->message = message;
840 * Increments the reference count of a DBusMessageIter.
842 * @param iter the message iter
843 * @see dbus_message_iter_unref
846 dbus_message_iter_ref (DBusMessageIter *iter)
848 _dbus_assert (iter->refcount > 0);
854 * Decrements the reference count of a DBusMessageIter.
856 * @param iter The message iter
857 * @see dbus_message_iter_ref
860 dbus_message_iter_unref (DBusMessageIter *iter)
862 _dbus_assert (iter->refcount > 0);
866 if (iter->refcount == 0)
868 dbus_message_unref (iter->message);
875 * Checks if an iterator has any more fields.
877 * @param iter the message iter
878 * @returns #TRUE if there are more fields
882 dbus_message_iter_has_next (DBusMessageIter *iter)
886 if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
887 iter->pos, &end_pos))
890 if (end_pos >= _dbus_string_get_length (&iter->message->body))
897 * Moves the iterator to the next field.
899 * @param iter The message iter
900 * @returns #TRUE if the iterator was moved to the next field
903 dbus_message_iter_next (DBusMessageIter *iter)
907 if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
908 iter->pos, &end_pos))
911 if (end_pos >= _dbus_string_get_length (&iter->message->body))
920 * Returns the field type of the field that the
921 * message iterator points at.
923 * @param iter the message iter
924 * @returns the field type
927 dbus_message_iter_get_field_type (DBusMessageIter *iter)
931 if (iter->pos >= _dbus_string_get_length (&iter->message->body))
932 return DBUS_TYPE_INVALID;
934 _dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
936 if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING)
939 return DBUS_TYPE_INVALID;
943 * Returns the string value that an iterator may point to.
944 * Note that you need to check that the iterator points to
945 * a string value before using this function.
947 * @see dbus_message_iter_get_field_type
948 * @param iter the message iter
949 * @returns the string
952 dbus_message_iter_get_string (DBusMessageIter *iter)
954 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_STRING);
956 return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
957 iter->pos + 1, NULL);
961 * Returns the 32 bit signed integer value that an iterator may point to.
962 * Note that you need to check that the iterator points to
963 * a string value before using this function.
965 * @see dbus_message_iter_get_field_type
966 * @param iter the message iter
967 * @returns the integer
970 dbus_message_iter_get_int32 (DBusMessageIter *iter)
972 return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
973 iter->pos + 1, NULL);
977 * Returns the 32 bit unsigned integer value that an iterator may point to.
978 * Note that you need to check that the iterator points to
979 * a string value before using this function.
981 * @see dbus_message_iter_get_field_type
982 * @param iter the message iter
983 * @returns the integer
986 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
988 return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
989 iter->pos + 1, NULL);
993 * Returns the double value that an iterator may point to.
994 * Note that you need to check that the iterator points to
995 * a string value before using this function.
997 * @see dbus_message_iter_get_field_type
998 * @param iter the message iter
999 * @returns the double
1002 dbus_message_iter_get_double (DBusMessageIter *iter)
1004 return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
1005 iter->pos + 1, NULL);
1009 * Returns the byte array that the iterator may point to.
1010 * Note that you need to check that the iterator points
1011 * to a byte array prior to using this function.
1013 * @todo this function should probably take "unsigned char **" as
1014 * an out param argument, and return boolean or result code.
1016 * @param iter the iterator
1017 * @param len return location for length of byte array
1018 * @returns the byte array
1021 dbus_message_iter_get_byte_array (DBusMessageIter *iter,
1024 _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_BYTE_ARRAY);
1026 return _dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
1027 iter->pos + 1, NULL, len);
1033 * @addtogroup DBusMessageInternals
1038 * @typedef DBusMessageLoader
1040 * The DBusMessageLoader object encapsulates the process of converting
1041 * a byte stream into a series of DBusMessage. It buffers the incoming
1042 * bytes as efficiently as possible, and generates a queue of
1043 * messages. DBusMessageLoader is typically used as part of a
1044 * DBusTransport implementation. The DBusTransport then hands off
1045 * the loaded messages to a DBusConnection, making the messages
1046 * visible to the application.
1051 * Implementation details of DBusMessageLoader.
1052 * All members are private.
1054 struct DBusMessageLoader
1056 int refcount; /**< Reference count. */
1058 DBusString data; /**< Buffered data */
1060 DBusList *messages; /**< Complete messages. */
1062 long max_message_size; /**< Maximum size of a message */
1064 unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
1066 unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
1070 * The initial buffer size of the message loader.
1072 * @todo this should be based on min header size plus some average
1073 * body size, or something. Or rather, the min header size only, if we
1074 * want to try to read only the header, store that in a DBusMessage,
1075 * then read only the body and store that, etc., depends on
1076 * how we optimize _dbus_message_loader_get_buffer() and what
1077 * the exact message format is.
1079 #define INITIAL_LOADER_DATA_LEN 32
1082 * Creates a new message loader. Returns #NULL if memory can't
1085 * @returns new loader, or #NULL.
1088 _dbus_message_loader_new (void)
1090 DBusMessageLoader *loader;
1092 loader = dbus_new0 (DBusMessageLoader, 1);
1096 loader->refcount = 1;
1098 /* Try to cap message size at something that won't *totally* hose
1099 * the system if we have a couple of them.
1101 loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
1103 if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
1109 /* preallocate the buffer for speed, ignore failure */
1110 _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
1111 _dbus_string_set_length (&loader->data, 0);
1117 * Increments the reference count of the loader.
1119 * @param loader the loader.
1122 _dbus_message_loader_ref (DBusMessageLoader *loader)
1124 loader->refcount += 1;
1128 * Decrements the reference count of the loader and finalizes the
1129 * loader when the count reaches zero.
1131 * @param loader the loader.
1134 _dbus_message_loader_unref (DBusMessageLoader *loader)
1136 loader->refcount -= 1;
1137 if (loader->refcount == 0)
1139 _dbus_list_foreach (&loader->messages,
1140 (DBusForeachFunction) dbus_message_unref,
1142 _dbus_list_clear (&loader->messages);
1143 _dbus_string_free (&loader->data);
1149 * Gets the buffer to use for reading data from the network. Network
1150 * data is read directly into an allocated buffer, which is then used
1151 * in the DBusMessage, to avoid as many extra memcpy's as possible.
1152 * The buffer must always be returned immediately using
1153 * _dbus_message_loader_return_buffer(), even if no bytes are
1154 * successfully read.
1156 * @todo this function can be a lot more clever. For example
1157 * it can probably always return a buffer size to read exactly
1158 * the body of the next message, thus avoiding any memory wastage
1161 * @param loader the message loader.
1162 * @param buffer the buffer
1165 _dbus_message_loader_get_buffer (DBusMessageLoader *loader,
1166 DBusString **buffer)
1168 _dbus_assert (!loader->buffer_outstanding);
1170 *buffer = &loader->data;
1172 loader->buffer_outstanding = TRUE;
1176 * The smallest header size that can occur.
1177 * (It won't be valid)
1179 #define DBUS_MINIMUM_HEADER_SIZE 16
1181 /** Pack four characters as in "abcd" into a uint32 */
1182 #define FOUR_CHARS_TO_UINT32(a, b, c, d) \
1183 ((((dbus_uint32_t)a) << 24) | \
1184 (((dbus_uint32_t)b) << 16) | \
1185 (((dbus_uint32_t)c) << 8) | \
1188 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
1189 #define DBUS_HEADER_FIELD_NAME_AS_UINT32 \
1190 FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
1192 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
1193 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
1194 FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
1196 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
1197 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32 \
1198 FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
1200 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
1201 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32 \
1202 FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
1205 /* FIXME should be using DBusString for the stuff we demarshal. char*
1206 * evil. Also, out of memory handling here seems suboptimal.
1207 * Should probably report it as a distinct error from "corrupt message,"
1208 * so we can postpone parsing this message. Also, we aren't
1209 * checking for demarshal failure everywhere.
1212 decode_header_data (DBusString *data,
1215 dbus_int32_t *client_serial,
1216 dbus_int32_t *reply_serial,
1224 /* First demarshal the client serial */
1225 *client_serial = _dbus_demarshal_int32 (data, byte_order, 12, &pos);
1231 /* Now handle the fields */
1232 while (pos < header_len)
1234 pos = _DBUS_ALIGN_VALUE (pos, 4);
1236 if ((pos + 4) > header_len)
1239 _dbus_string_get_const_data_len (data, &field, pos, 4);
1242 _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
1244 /* I believe FROM_BE is right, but if not we'll find out
1247 switch (DBUS_UINT32_FROM_BE (*(int*)field))
1249 case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
1250 if (*service != NULL)
1252 _dbus_verbose ("%s field provided twice\n",
1253 DBUS_HEADER_FIELD_SERVICE);
1257 *service = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
1258 /* FIXME check for demarshal failure SECURITY */
1260 case DBUS_HEADER_FIELD_NAME_AS_UINT32:
1263 _dbus_verbose ("%s field provided twice\n",
1264 DBUS_HEADER_FIELD_NAME);
1268 *name = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
1269 /* FIXME check for demarshal failure SECURITY */
1271 case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
1272 if (*sender != NULL)
1274 _dbus_verbose ("%s field provided twice\n",
1275 DBUS_HEADER_FIELD_NAME);
1279 *sender = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
1280 /* FIXME check for demarshal failure SECURITY */
1282 case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
1283 *reply_serial = _dbus_demarshal_int32 (data, byte_order, pos + 1, &new_pos);
1287 _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c\n",
1288 field[0], field[1], field[2], field[3]);
1290 if (!_dbus_marshal_get_field_end_pos (data, byte_order, pos, &new_pos))
1294 if (new_pos > header_len)
1303 dbus_free (*service);
1309 * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
1310 * indicating to the loader how many bytes of the buffer were filled
1311 * in. This function must always be called, even if no bytes were
1312 * successfully read.
1314 * @param loader the loader.
1315 * @param buffer the buffer.
1316 * @param bytes_read number of bytes that were read into the buffer.
1319 _dbus_message_loader_return_buffer (DBusMessageLoader *loader,
1323 _dbus_assert (loader->buffer_outstanding);
1324 _dbus_assert (buffer == &loader->data);
1326 loader->buffer_outstanding = FALSE;
1328 if (loader->corrupted)
1331 while (_dbus_string_get_length (&loader->data) >= 16)
1333 DBusMessage *message;
1334 const char *header_data;
1335 int byte_order, header_len, body_len;
1337 _dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
1339 _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
1341 byte_order = header_data[0];
1343 if (byte_order != DBUS_LITTLE_ENDIAN &&
1344 byte_order != DBUS_BIG_ENDIAN)
1346 _dbus_verbose ("Message with bad byte order '%c' received\n",
1348 loader->corrupted = TRUE;
1352 header_len = _dbus_unpack_int32 (byte_order, header_data + 4);
1353 body_len = _dbus_unpack_int32 (byte_order, header_data + 8);
1355 if (header_len + body_len > loader->max_message_size)
1357 _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %d\n",
1358 header_len, body_len, loader->max_message_size);
1359 loader->corrupted = TRUE;
1363 if (_dbus_string_get_length (&loader->data) >= header_len + body_len)
1365 dbus_int32_t client_serial, reply_serial;
1366 char *service, *name, *sender;
1368 /* FIXME right now if this doesn't have enough memory, the
1369 * loader becomes corrupted. Instead we should just not
1370 * parse this message for now.
1372 if (!decode_header_data (&loader->data, header_len, byte_order,
1373 &client_serial, &reply_serial, &service, &name, &sender))
1375 loader->corrupted = TRUE;
1380 message = dbus_message_new (service, name);
1381 message->reply_serial = reply_serial;
1382 message->client_serial = client_serial;
1383 _dbus_message_set_sender (message, sender);
1385 dbus_free (service);
1389 if (message == NULL)
1390 break; /* ugh, postpone this I guess. */
1392 if (!_dbus_list_append (&loader->messages, message))
1394 dbus_message_unref (message);
1398 _dbus_assert (_dbus_string_get_length (&message->header) == 0);
1399 _dbus_assert (_dbus_string_get_length (&message->body) == 0);
1401 if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
1403 _dbus_list_remove_last (&loader->messages, message);
1404 dbus_message_unref (message);
1408 if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
1412 /* put the header back, we'll try again later */
1413 result = _dbus_string_copy_len (&message->header, 0, header_len,
1415 _dbus_assert (result); /* because DBusString never reallocs smaller */
1417 _dbus_list_remove_last (&loader->messages, message);
1418 dbus_message_unref (message);
1422 _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
1423 _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
1425 _dbus_verbose ("Loaded message %p\n", message);
1433 * Pops a loaded message (passing ownership of the message
1434 * to the caller). Returns #NULL if no messages have been
1437 * @param loader the loader.
1438 * @returns the next message, or #NULL if none.
1441 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
1443 return _dbus_list_pop_first (&loader->messages);
1448 * Checks whether the loader is confused due to bad data.
1449 * If messages are received that are invalid, the
1450 * loader gets confused and gives up permanently.
1451 * This state is called "corrupted."
1453 * @param loader the loader
1454 * @returns #TRUE if the loader is hosed.
1457 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
1459 return loader->corrupted;
1463 * Sets the maximum size message we allow.
1465 * @param loader the loader
1466 * @param size the max message size in bytes
1469 _dbus_message_loader_set_max_message_size (DBusMessageLoader *loader,
1472 loader->max_message_size = size;
1476 * Gets the maximum allowed message size in bytes.
1478 * @param loader the loader
1479 * @returns max size in bytes
1482 _dbus_message_loader_get_max_message_size (DBusMessageLoader *loader)
1484 return loader->max_message_size;
1488 #ifdef DBUS_BUILD_TESTS
1489 #include "dbus-test.h"
1493 message_iter_test (DBusMessage *message)
1495 DBusMessageIter *iter;
1498 iter = dbus_message_get_fields_iter (message);
1501 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_STRING)
1502 _dbus_assert_not_reached ("Field type isn't string");
1504 str = dbus_message_iter_get_string (iter);
1505 if (strcmp (str, "Test string") != 0)
1506 _dbus_assert_not_reached ("Strings differ");
1509 if (!dbus_message_iter_next (iter))
1510 _dbus_assert_not_reached ("Reached end of fields");
1512 /* Signed integer tests */
1513 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_INT32)
1514 _dbus_assert_not_reached ("Field type isn't int32");
1516 if (dbus_message_iter_get_int32 (iter) != -0x12345678)
1517 _dbus_assert_not_reached ("Signed integers differ");
1519 if (!dbus_message_iter_next (iter))
1520 _dbus_assert_not_reached ("Reached end of fields");
1522 /* Unsigned integer tests */
1523 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_UINT32)
1524 _dbus_assert_not_reached ("Field type isn't int32");
1526 if (dbus_message_iter_get_int32 (iter) != 0xedd1e)
1527 _dbus_assert_not_reached ("Unsigned integers differ");
1529 if (!dbus_message_iter_next (iter))
1530 _dbus_assert_not_reached ("Reached end of fields");
1533 if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_DOUBLE)
1534 _dbus_assert_not_reached ("Field type isn't double");
1536 if (dbus_message_iter_get_double (iter) != 3.14159)
1537 _dbus_assert_not_reached ("Doubles differ");
1539 if (dbus_message_iter_next (iter))
1540 _dbus_assert_not_reached ("Didn't reach end of fields");
1542 dbus_message_iter_unref (iter);
1546 * @ingroup DBusMessageInternals
1547 * Unit test for DBusMessage.
1549 * @returns #TRUE on success.
1552 _dbus_message_test (void)
1554 DBusMessage *message;
1555 DBusMessageLoader *loader;
1558 dbus_int32_t our_int;
1562 /* Test the vararg functions */
1563 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
1564 message->client_serial = 1;
1565 dbus_message_append_fields (message,
1566 DBUS_TYPE_INT32, -0x12345678,
1567 DBUS_TYPE_STRING, "Test string",
1568 DBUS_TYPE_DOUBLE, 3.14159,
1571 if (dbus_message_get_fields (message,
1572 DBUS_TYPE_INT32, &our_int,
1573 DBUS_TYPE_STRING, &our_str,
1574 DBUS_TYPE_DOUBLE, &our_double,
1575 0) != DBUS_RESULT_SUCCESS)
1576 _dbus_assert_not_reached ("Could not get fields");
1578 if (our_int != -0x12345678)
1579 _dbus_assert_not_reached ("integers differ!");
1581 if (our_double != 3.14159)
1582 _dbus_assert_not_reached ("doubles differ!");
1584 if (strcmp (our_str, "Test string") != 0)
1585 _dbus_assert_not_reached ("strings differ!");
1587 message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
1588 message->client_serial = 1;
1589 message->reply_serial = 0x12345678;
1591 dbus_message_append_string (message, "Test string");
1592 dbus_message_append_int32 (message, -0x12345678);
1593 dbus_message_append_uint32 (message, 0xedd1e);
1594 dbus_message_append_double (message, 3.14159);
1596 message_iter_test (message);
1598 /* Message loader test */
1599 _dbus_message_lock (message);
1600 loader = _dbus_message_loader_new ();
1602 /* Write the header data one byte at a time */
1603 _dbus_string_get_const_data (&message->header, &data);
1604 for (i = 0; i < _dbus_string_get_length (&message->header); i++)
1608 _dbus_message_loader_get_buffer (loader, &buffer);
1609 _dbus_string_append_byte (buffer, data[i]);
1610 _dbus_message_loader_return_buffer (loader, buffer, 1);
1613 /* Write the body data one byte at a time */
1614 _dbus_string_get_const_data (&message->body, &data);
1615 for (i = 0; i < _dbus_string_get_length (&message->body); i++)
1619 _dbus_message_loader_get_buffer (loader, &buffer);
1620 _dbus_string_append_byte (buffer, data[i]);
1621 _dbus_message_loader_return_buffer (loader, buffer, 1);
1624 dbus_message_unref (message);
1626 /* Now pop back the message */
1627 if (_dbus_message_loader_get_is_corrupted (loader))
1628 _dbus_assert_not_reached ("message loader corrupted");
1630 message = _dbus_message_loader_pop_message (loader);
1632 _dbus_assert_not_reached ("received a NULL message");
1634 if (message->reply_serial != 0x12345678)
1635 _dbus_assert_not_reached ("reply serial fields differ");
1637 message_iter_test (message);
1639 dbus_message_unref (message);
1640 _dbus_message_loader_unref (loader);
1645 #endif /* DBUS_BUILD_TESTS */