2005-01-16 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-message.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-message.c  DBusMessage object
3  *
4  * Copyright (C) 2002, 2003, 2004, 2005  Red Hat Inc.
5  * Copyright (C) 2002, 2003  CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
8  *
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.
13  *
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.
18  *
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
22  *
23  */
24
25 #include "dbus-internals.h"
26 #include "dbus-marshal-recursive.h"
27 #include "dbus-marshal-validate.h"
28 #include "dbus-marshal-header.h"
29 #include "dbus-message.h"
30 #include "dbus-message-internal.h"
31 #include "dbus-object-tree.h"
32 #include "dbus-memory.h"
33 #include "dbus-list.h"
34 #include "dbus-dataslot.h"
35 #include <string.h>
36
37 /**
38  * @defgroup DBusMessageInternals DBusMessage implementation details
39  * @ingroup DBusInternals
40  * @brief DBusMessage private implementation details.
41  *
42  * The guts of DBusMessage and its methods.
43  *
44  * @{
45  */
46
47 static dbus_bool_t dbus_message_iter_get_args        (DBusMessageIter *iter,
48                                                       DBusError       *error,
49                                                       int              first_arg_type,
50                                                       ...);
51 static dbus_bool_t dbus_message_iter_get_args_valist (DBusMessageIter *iter,
52                                                       DBusError       *error,
53                                                       int              first_arg_type,
54                                                       va_list          var_args);
55
56 /* Not thread locked, but strictly const/read-only so should be OK
57  */
58 /** An static string representing an empty signature */
59 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,  "");
60
61 /** How many bits are in the changed_stamp used to validate iterators */
62 #define CHANGED_STAMP_BITS 21
63
64 /**
65  * @brief Internals of DBusMessage
66  *
67  * Object representing a message received from or to be sent to
68  * another application. This is an opaque object, all members
69  * are private.
70  */
71 struct DBusMessage
72 {
73   DBusAtomic refcount; /**< Reference count */
74
75   DBusHeader header; /**< Header network data and associated cache */
76
77   DBusString body;   /**< Body network data. */
78
79   char byte_order; /**< Message byte order. */
80
81   unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
82
83   DBusList *size_counters;   /**< 0-N DBusCounter used to track message size. */
84   long size_counter_delta;   /**< Size we incremented the size counters by.   */
85
86   dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; /**< Incremented when iterators are invalidated. */
87
88   DBusDataSlotList slot_list;   /**< Data stored by allocated integer ID */
89
90 #ifndef DBUS_DISABLE_CHECKS
91   int generation; /**< _dbus_current_generation when message was created */
92 #endif
93 };
94
95 /* these have wacky values to help trap uninitialized iterators;
96  * but has to fit in 3 bits
97  */
98 enum {
99   DBUS_MESSAGE_ITER_TYPE_READER = 3,
100   DBUS_MESSAGE_ITER_TYPE_WRITER = 7
101 };
102
103 /** typedef for internals of message iterator */
104 typedef struct DBusMessageRealIter DBusMessageRealIter;
105
106 /**
107  * @brief Internals of DBusMessageIter
108  *
109  * Object representing a position in a message. All fields are internal.
110  */
111 struct DBusMessageRealIter
112 {
113   DBusMessage *message; /**< Message used */
114   dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS; /**< stamp to detect invalid iters */
115   dbus_uint32_t iter_type : 3;      /**< whether this is a reader or writer iter */
116   dbus_uint32_t sig_refcount : 8;   /**< depth of open_signature() */
117   union
118   {
119     DBusTypeWriter writer; /**< writer */
120     DBusTypeReader reader; /**< reader */
121   } u; /**< the type writer or reader that does all the work */
122 };
123
124 /**
125  * Gets the data to be sent over the network for this message.
126  * The header and then the body should be written out.
127  * This function is guaranteed to always return the same
128  * data once a message is locked (with _dbus_message_lock()).
129  *
130  * @param message the message.
131  * @param header return location for message header data.
132  * @param body return location for message body data.
133  */
134 void
135 _dbus_message_get_network_data (DBusMessage          *message,
136                                 const DBusString    **header,
137                                 const DBusString    **body)
138 {
139   _dbus_assert (message->locked);
140
141   *header = &message->header.data;
142   *body = &message->body;
143 }
144
145 /**
146  * Sets the serial number of a message.
147  * This can only be done once on a message.
148  *
149  * @param message the message
150  * @param serial the serial
151  */
152 void
153 _dbus_message_set_serial (DBusMessage   *message,
154                           dbus_uint32_t  serial)
155 {
156   _dbus_return_if_fail (message != NULL);
157   _dbus_return_if_fail (!message->locked);
158   _dbus_return_if_fail (dbus_message_get_serial (message) == 0);
159
160   _dbus_header_set_serial (&message->header, serial);
161 }
162
163 /**
164  * Adds a counter to be incremented immediately with the
165  * size of this message, and decremented by the size
166  * of this message when this message if finalized.
167  * The link contains a counter with its refcount already
168  * incremented, but the counter itself not incremented.
169  * Ownership of link and counter refcount is passed to
170  * the message.
171  *
172  * @param message the message
173  * @param link link with counter as data
174  */
175 void
176 _dbus_message_add_size_counter_link (DBusMessage  *message,
177                                      DBusList     *link)
178 {
179   /* right now we don't recompute the delta when message
180    * size changes, and that's OK for current purposes
181    * I think, but could be important to change later.
182    * Do recompute it whenever there are no outstanding counters,
183    * since it's basically free.
184    */
185   if (message->size_counters == NULL)
186     {
187       message->size_counter_delta =
188         _dbus_string_get_length (&message->header.data) +
189         _dbus_string_get_length (&message->body);
190
191 #if 0
192       _dbus_verbose ("message has size %ld\n",
193                      message->size_counter_delta);
194 #endif
195     }
196
197   _dbus_list_append_link (&message->size_counters, link);
198
199   _dbus_counter_adjust (link->data, message->size_counter_delta);
200 }
201
202 /**
203  * Adds a counter to be incremented immediately with the
204  * size of this message, and decremented by the size
205  * of this message when this message if finalized.
206  *
207  * @param message the message
208  * @param counter the counter
209  * @returns #FALSE if no memory
210  */
211 dbus_bool_t
212 _dbus_message_add_size_counter (DBusMessage *message,
213                                 DBusCounter *counter)
214 {
215   DBusList *link;
216
217   link = _dbus_list_alloc_link (counter);
218   if (link == NULL)
219     return FALSE;
220
221   _dbus_counter_ref (counter);
222   _dbus_message_add_size_counter_link (message, link);
223
224   return TRUE;
225 }
226
227 /**
228  * Removes a counter tracking the size of this message, and decrements
229  * the counter by the size of this message.
230  *
231  * @param message the message
232  * @param link_return return the link used
233  * @param counter the counter
234  */
235 void
236 _dbus_message_remove_size_counter (DBusMessage  *message,
237                                    DBusCounter  *counter,
238                                    DBusList    **link_return)
239 {
240   DBusList *link;
241
242   link = _dbus_list_find_last (&message->size_counters,
243                                counter);
244   _dbus_assert (link != NULL);
245
246   _dbus_list_unlink (&message->size_counters,
247                      link);
248   if (link_return)
249     *link_return = link;
250   else
251     _dbus_list_free_link (link);
252
253   _dbus_counter_adjust (counter, - message->size_counter_delta);
254
255   _dbus_counter_unref (counter);
256 }
257
258 /**
259  * Locks a message. Allows checking that applications don't keep a
260  * reference to a message in the outgoing queue and change it
261  * underneath us. Messages are locked when they enter the outgoing
262  * queue (dbus_connection_send_message()), and the library complains
263  * if the message is modified while locked.
264  *
265  * @param message the message to lock.
266  */
267 void
268 _dbus_message_lock (DBusMessage  *message)
269 {
270   if (!message->locked)
271     {
272       _dbus_header_update_lengths (&message->header,
273                                    _dbus_string_get_length (&message->body));
274
275       /* must have a signature if you have a body */
276       _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
277                     dbus_message_get_signature (message) != NULL);
278
279       message->locked = TRUE;
280     }
281 }
282
283 static dbus_bool_t
284 set_or_delete_string_field (DBusMessage *message,
285                             int          field,
286                             int          typecode,
287                             const char  *value)
288 {
289   if (value == NULL)
290     return _dbus_header_delete_field (&message->header, field);
291   else
292     return _dbus_header_set_field_basic (&message->header,
293                                          field,
294                                          typecode,
295                                          &value);
296 }
297
298 static void
299 get_const_signature (DBusHeader        *header,
300                      const DBusString **type_str_p,
301                      int               *type_pos_p)
302 {
303   if (_dbus_header_get_field_raw (header,
304                                   DBUS_HEADER_FIELD_SIGNATURE,
305                                   type_str_p,
306                                   type_pos_p))
307     {
308       *type_pos_p += 1; /* skip the signature length which is 1 byte */
309     }
310   else
311     {
312       *type_str_p = &_dbus_empty_signature_str;
313       *type_pos_p = 0;
314     }
315 }
316
317 #if 0
318 /* Probably we don't need to use this */
319 /**
320  * Sets the signature of the message, i.e. the arguments in the
321  * message payload. The signature includes only "in" arguments for
322  * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
323  * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
324  * what you might expect (it does not include the signature of the
325  * entire C++-style method).
326  *
327  * The signature is a string made up of type codes such as
328  * #DBUS_TYPE_INT32. The string is terminated with nul (nul is also
329  * the value of #DBUS_TYPE_INVALID). The macros such as
330  * #DBUS_TYPE_INT32 evaluate to integers; to assemble a signature you
331  * may find it useful to use the string forms, such as
332  * #DBUS_TYPE_INT32_AS_STRING.
333  *
334  * An "unset" or #NULL signature is considered the same as an empty
335  * signature. In fact dbus_message_get_signature() will never return
336  * #NULL.
337  *
338  * @param message the message
339  * @param signature the type signature or #NULL to unset
340  * @returns #FALSE if no memory
341  */
342 static dbus_bool_t
343 _dbus_message_set_signature (DBusMessage *message,
344                              const char  *signature)
345 {
346   _dbus_return_val_if_fail (message != NULL, FALSE);
347   _dbus_return_val_if_fail (!message->locked, FALSE);
348   _dbus_return_val_if_fail (signature == NULL ||
349                             _dbus_check_is_valid_signature (signature));
350   /* can't delete the signature if you have a message body */
351   _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
352                             signature != NULL);
353
354   return set_or_delete_string_field (message,
355                                      DBUS_HEADER_FIELD_SIGNATURE,
356                                      DBUS_TYPE_SIGNATURE,
357                                      signature);
358 }
359 #endif
360
361 /** @} */
362
363 /**
364  * @defgroup DBusMessage DBusMessage
365  * @ingroup  DBus
366  * @brief Message to be sent or received over a DBusConnection.
367  *
368  * A DBusMessage is the most basic unit of communication over a
369  * DBusConnection. A DBusConnection represents a stream of messages
370  * received from a remote application, and a stream of messages
371  * sent to a remote application.
372  *
373  * @{
374  */
375
376 /**
377  * @typedef DBusMessage
378  *
379  * Opaque data type representing a message received from or to be
380  * sent to another application.
381  */
382
383 /**
384  * Returns the serial of a message or 0 if none has been specified.
385  * The message's serial number is provided by the application sending
386  * the message and is used to identify replies to this message.  All
387  * messages received on a connection will have a serial, but messages
388  * you haven't sent yet may return 0.
389  *
390  * @param message the message
391  * @returns the client serial
392  */
393 dbus_uint32_t
394 dbus_message_get_serial (DBusMessage *message)
395 {
396   _dbus_return_val_if_fail (message != NULL, 0);
397
398   return _dbus_header_get_serial (&message->header);
399 }
400
401 /**
402  * Sets the reply serial of a message (the client serial
403  * of the message this is a reply to).
404  *
405  * @param message the message
406  * @param reply_serial the client serial
407  * @returns #FALSE if not enough memory
408  */
409 dbus_bool_t
410 dbus_message_set_reply_serial (DBusMessage   *message,
411                                dbus_uint32_t  reply_serial)
412 {
413   _dbus_return_val_if_fail (message != NULL, FALSE);
414   _dbus_return_val_if_fail (!message->locked, FALSE);
415
416   return _dbus_header_set_field_basic (&message->header,
417                                        DBUS_HEADER_FIELD_REPLY_SERIAL,
418                                        DBUS_TYPE_UINT32,
419                                        &reply_serial);
420 }
421
422 /**
423  * Returns the serial that the message is a reply to or 0 if none.
424  *
425  * @param message the message
426  * @returns the reply serial
427  */
428 dbus_uint32_t
429 dbus_message_get_reply_serial  (DBusMessage *message)
430 {
431   dbus_uint32_t v_UINT32;
432
433   _dbus_return_val_if_fail (message != NULL, 0);
434
435   if (_dbus_header_get_field_basic (&message->header,
436                                     DBUS_HEADER_FIELD_REPLY_SERIAL,
437                                     DBUS_TYPE_UINT32,
438                                     &v_UINT32))
439     return v_UINT32;
440   else
441     return 0;
442 }
443
444 static void
445 free_size_counter (void *element,
446                    void *data)
447 {
448   DBusCounter *counter = element;
449   DBusMessage *message = data;
450
451   _dbus_counter_adjust (counter, - message->size_counter_delta);
452
453   _dbus_counter_unref (counter);
454 }
455
456 static void
457 dbus_message_finalize (DBusMessage *message)
458 {
459   _dbus_assert (message->refcount.value == 0);
460
461   /* This calls application callbacks! */
462   _dbus_data_slot_list_free (&message->slot_list);
463
464   _dbus_list_foreach (&message->size_counters,
465                       free_size_counter, message);
466   _dbus_list_clear (&message->size_counters);
467
468   _dbus_header_free (&message->header);
469   _dbus_string_free (&message->body);
470
471   dbus_free (message);
472 }
473
474 /* Message Cache
475  *
476  * We cache some DBusMessage to reduce the overhead of allocating
477  * them.  In my profiling this consistently made about an 8%
478  * difference.  It avoids the malloc for the message, the malloc for
479  * the slot list, the malloc for the header string and body string,
480  * and the associated free() calls. It does introduce another global
481  * lock which could be a performance issue in certain cases.
482  *
483  * For the echo client/server the round trip time goes from around
484  * .000077 to .000069 with the message cache on my laptop. The sysprof
485  * change is as follows (numbers are cumulative percentage):
486  *
487  *  with message cache implemented as array as it is now (0.000069 per):
488  *    new_empty_header           1.46
489  *      mutex_lock               0.56    # i.e. _DBUS_LOCK(message_cache)
490  *      mutex_unlock             0.25
491  *      self                     0.41
492  *    unref                      2.24
493  *      self                     0.68
494  *      list_clear               0.43
495  *      mutex_lock               0.33    # i.e. _DBUS_LOCK(message_cache)
496  *      mutex_unlock             0.25
497  *
498  *  with message cache implemented as list (0.000070 per roundtrip):
499  *    new_empty_header           2.72
500  *      list_pop_first           1.88
501  *    unref                      3.3
502  *      list_prepend             1.63
503  *
504  * without cache (0.000077 per roundtrip):
505  *    new_empty_header           6.7
506  *      string_init_preallocated 3.43
507  *        dbus_malloc            2.43
508  *      dbus_malloc0             2.59
509  *
510  *    unref                      4.02
511  *      string_free              1.82
512  *        dbus_free              1.63
513  *      dbus_free                0.71
514  *
515  * If you implement the message_cache with a list, the primary reason
516  * it's slower is that you add another thread lock (on the DBusList
517  * mempool).
518  */
519
520 /** Avoid caching huge messages */
521 #define MAX_MESSAGE_SIZE_TO_CACHE _DBUS_ONE_MEGABYTE
522
523 /** Avoid caching too many messages */
524 #define MAX_MESSAGE_CACHE_SIZE    5
525
526 _DBUS_DEFINE_GLOBAL_LOCK (message_cache);
527 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
528 static int message_cache_count = 0;
529 static dbus_bool_t message_cache_shutdown_registered = FALSE;
530
531 static void
532 dbus_message_cache_shutdown (void *data)
533 {
534   int i;
535
536   _DBUS_LOCK (message_cache);
537
538   i = 0;
539   while (i < MAX_MESSAGE_CACHE_SIZE)
540     {
541       if (message_cache[i])
542         dbus_message_finalize (message_cache[i]);
543
544       ++i;
545     }
546
547   message_cache_count = 0;
548   message_cache_shutdown_registered = FALSE;
549
550   _DBUS_UNLOCK (message_cache);
551 }
552
553 /**
554  * Tries to get a message from the message cache.  The retrieved
555  * message will have junk in it, so it still needs to be cleared out
556  * in dbus_message_new_empty_header()
557  *
558  * @returns the message, or #NULL if none cached
559  */
560 static DBusMessage*
561 dbus_message_get_cached (void)
562 {
563   DBusMessage *message;
564   int i;
565
566   message = NULL;
567
568   _DBUS_LOCK (message_cache);
569
570   _dbus_assert (message_cache_count >= 0);
571
572   if (message_cache_count == 0)
573     {
574       _DBUS_UNLOCK (message_cache);
575       return NULL;
576     }
577
578   /* This is not necessarily true unless count > 0, and
579    * message_cache is uninitialized until the shutdown is
580    * registered
581    */
582   _dbus_assert (message_cache_shutdown_registered);
583
584   i = 0;
585   while (i < MAX_MESSAGE_CACHE_SIZE)
586     {
587       if (message_cache[i])
588         {
589           message = message_cache[i];
590           message_cache[i] = NULL;
591           message_cache_count -= 1;
592           break;
593         }
594       ++i;
595     }
596   _dbus_assert (message_cache_count >= 0);
597   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
598   _dbus_assert (message != NULL);
599
600   _DBUS_UNLOCK (message_cache);
601
602   _dbus_assert (message->refcount.value == 0);
603   _dbus_assert (message->size_counters == NULL);
604
605   return message;
606 }
607
608 /**
609  * Tries to cache a message, otherwise finalize it.
610  *
611  * @param message the message
612  */
613 static void
614 dbus_message_cache_or_finalize (DBusMessage *message)
615 {
616   dbus_bool_t was_cached;
617   int i;
618
619   _dbus_assert (message->refcount.value == 0);
620
621   /* This calls application code and has to be done first thing
622    * without holding the lock
623    */
624   _dbus_data_slot_list_clear (&message->slot_list);
625
626   _dbus_list_foreach (&message->size_counters,
627                       free_size_counter, message);
628   _dbus_list_clear (&message->size_counters);
629
630   was_cached = FALSE;
631
632   _DBUS_LOCK (message_cache);
633
634   if (!message_cache_shutdown_registered)
635     {
636       _dbus_assert (message_cache_count == 0);
637
638       if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
639         goto out;
640
641       i = 0;
642       while (i < MAX_MESSAGE_CACHE_SIZE)
643         {
644           message_cache[i] = NULL;
645           ++i;
646         }
647
648       message_cache_shutdown_registered = TRUE;
649     }
650
651   _dbus_assert (message_cache_count >= 0);
652
653   if ((_dbus_string_get_length (&message->header.data) +
654        _dbus_string_get_length (&message->body)) >
655       MAX_MESSAGE_SIZE_TO_CACHE)
656     goto out;
657
658   if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
659     goto out;
660
661   /* Find empty slot */
662   i = 0;
663   while (message_cache[i] != NULL)
664     ++i;
665
666   _dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
667
668   _dbus_assert (message_cache[i] == NULL);
669   message_cache[i] = message;
670   message_cache_count += 1;
671   was_cached = TRUE;
672
673  out:
674   _DBUS_UNLOCK (message_cache);
675
676   if (!was_cached)
677     dbus_message_finalize (message);
678 }
679
680 static DBusMessage*
681 dbus_message_new_empty_header (void)
682 {
683   DBusMessage *message;
684   dbus_bool_t from_cache;
685
686   message = dbus_message_get_cached ();
687
688   if (message != NULL)
689     {
690       from_cache = TRUE;
691     }
692   else
693     {
694       from_cache = FALSE;
695       message = dbus_new (DBusMessage, 1);
696       if (message == NULL)
697         return NULL;
698 #ifndef DBUS_DISABLE_CHECKS
699       message->generation = _dbus_current_generation;
700 #endif
701     }
702
703   message->refcount.value = 1;
704   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
705   message->locked = FALSE;
706   message->size_counters = NULL;
707   message->size_counter_delta = 0;
708   message->changed_stamp = 0;
709
710   if (!from_cache)
711     _dbus_data_slot_list_init (&message->slot_list);
712
713   if (from_cache)
714     {
715       _dbus_header_reinit (&message->header, message->byte_order);
716       _dbus_string_set_length (&message->body, 0);
717     }
718   else
719     {
720       if (!_dbus_header_init (&message->header, message->byte_order))
721         {
722           dbus_free (message);
723           return NULL;
724         }
725
726       if (!_dbus_string_init_preallocated (&message->body, 32))
727         {
728           _dbus_header_free (&message->header);
729           dbus_free (message);
730           return NULL;
731         }
732     }
733
734   return message;
735 }
736
737 /**
738  * Constructs a new message of the given message type.
739  * Types include #DBUS_MESSAGE_TYPE_METHOD_CALL,
740  * #DBUS_MESSAGE_TYPE_SIGNAL, and so forth.
741  *
742  * @param message_type type of message
743  * @returns new message or #NULL If no memory
744  */
745 DBusMessage*
746 dbus_message_new (int message_type)
747 {
748   DBusMessage *message;
749
750   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
751
752   message = dbus_message_new_empty_header ();
753   if (message == NULL)
754     return NULL;
755
756   if (!_dbus_header_create (&message->header,
757                             message_type,
758                             NULL, NULL, NULL, NULL, NULL))
759     {
760       dbus_message_unref (message);
761       return NULL;
762     }
763
764   return message;
765 }
766
767 /**
768  * Constructs a new message to invoke a method on a remote
769  * object. Returns #NULL if memory can't be allocated for the
770  * message. The destination may be #NULL in which case no destination
771  * is set; this is appropriate when using D-BUS in a peer-to-peer
772  * context (no message bus). The interface may be #NULL, which means
773  * that if multiple methods with the given name exist it is undefined
774  * which one will be invoked.
775   *
776  * @param destination service that the message should be sent to or #NULL
777  * @param path object path the message should be sent to
778  * @param interface interface to invoke method on
779  * @param method method to invoke
780  *
781  * @returns a new DBusMessage, free with dbus_message_unref()
782  * @see dbus_message_unref()
783  */
784 DBusMessage*
785 dbus_message_new_method_call (const char *destination,
786                               const char *path,
787                               const char *interface,
788                               const char *method)
789 {
790   DBusMessage *message;
791
792   _dbus_return_val_if_fail (path != NULL, NULL);
793   _dbus_return_val_if_fail (method != NULL, NULL);
794   _dbus_return_val_if_fail (destination == NULL ||
795                             _dbus_check_is_valid_service (destination), NULL);
796   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
797   _dbus_return_val_if_fail (interface == NULL ||
798                             _dbus_check_is_valid_interface (interface), NULL);
799   _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
800
801   message = dbus_message_new_empty_header ();
802   if (message == NULL)
803     return NULL;
804
805   if (!_dbus_header_create (&message->header,
806                             DBUS_MESSAGE_TYPE_METHOD_CALL,
807                             destination, path, interface, method, NULL))
808     {
809       dbus_message_unref (message);
810       return NULL;
811     }
812
813   return message;
814 }
815
816 /**
817  * Constructs a message that is a reply to a method call. Returns
818  * #NULL if memory can't be allocated for the message.
819  *
820  * @param method_call the message which the created
821  * message is a reply to.
822  * @returns a new DBusMessage, free with dbus_message_unref()
823  * @see dbus_message_new_method_call(), dbus_message_unref()
824  */
825 DBusMessage*
826 dbus_message_new_method_return (DBusMessage *method_call)
827 {
828   DBusMessage *message;
829   const char *sender;
830
831   _dbus_return_val_if_fail (method_call != NULL, NULL);
832
833   sender = dbus_message_get_sender (method_call);
834
835   /* sender is allowed to be null here in peer-to-peer case */
836
837   message = dbus_message_new_empty_header ();
838   if (message == NULL)
839     return NULL;
840
841   if (!_dbus_header_create (&message->header,
842                             DBUS_MESSAGE_TYPE_METHOD_RETURN,
843                             sender, NULL, NULL, NULL, NULL))
844     {
845       dbus_message_unref (message);
846       return NULL;
847     }
848
849   dbus_message_set_no_reply (message, TRUE);
850
851   if (!dbus_message_set_reply_serial (message,
852                                       dbus_message_get_serial (method_call)))
853     {
854       dbus_message_unref (message);
855       return NULL;
856     }
857
858   return message;
859 }
860
861 /**
862  * Constructs a new message representing a signal emission. Returns
863  * #NULL if memory can't be allocated for the message.  A signal is
864  * identified by its originating interface, and the name of the
865  * signal.
866  *
867  * @param path the path to the object emitting the signal
868  * @param interface the interface the signal is emitted from
869  * @param name name of the signal
870  * @returns a new DBusMessage, free with dbus_message_unref()
871  * @see dbus_message_unref()
872  */
873 DBusMessage*
874 dbus_message_new_signal (const char *path,
875                          const char *interface,
876                          const char *name)
877 {
878   DBusMessage *message;
879
880   _dbus_return_val_if_fail (path != NULL, NULL);
881   _dbus_return_val_if_fail (interface != NULL, NULL);
882   _dbus_return_val_if_fail (name != NULL, NULL);
883   _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
884   _dbus_return_val_if_fail (_dbus_check_is_valid_interface (interface), NULL);
885   _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
886
887   message = dbus_message_new_empty_header ();
888   if (message == NULL)
889     return NULL;
890
891   if (!_dbus_header_create (&message->header,
892                             DBUS_MESSAGE_TYPE_SIGNAL,
893                             NULL, path, interface, name, NULL))
894     {
895       dbus_message_unref (message);
896       return NULL;
897     }
898
899   dbus_message_set_no_reply (message, TRUE);
900
901   return message;
902 }
903
904 /**
905  * Creates a new message that is an error reply to a certain message.
906  * Error replies are possible in response to method calls primarily.
907  *
908  * @param reply_to the original message
909  * @param error_name the error name
910  * @param error_message the error message string or #NULL for none
911  * @returns a new error message
912  */
913 DBusMessage*
914 dbus_message_new_error (DBusMessage *reply_to,
915                         const char  *error_name,
916                         const char  *error_message)
917 {
918   DBusMessage *message;
919   const char *sender;
920   DBusMessageIter iter;
921
922   _dbus_return_val_if_fail (reply_to != NULL, NULL);
923   _dbus_return_val_if_fail (error_name != NULL, NULL);
924   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
925
926   sender = dbus_message_get_sender (reply_to);
927
928   /* sender may be NULL for non-message-bus case or
929    * when the message bus is dealing with an unregistered
930    * connection.
931    */
932   message = dbus_message_new_empty_header ();
933   if (message == NULL)
934     return NULL;
935
936   if (!_dbus_header_create (&message->header,
937                             DBUS_MESSAGE_TYPE_ERROR,
938                             sender, NULL, NULL, NULL, error_name))
939     {
940       dbus_message_unref (message);
941       return NULL;
942     }
943
944   dbus_message_set_no_reply (message, TRUE);
945
946   if (!dbus_message_set_reply_serial (message,
947                                       dbus_message_get_serial (reply_to)))
948     {
949       dbus_message_unref (message);
950       return NULL;
951     }
952
953   if (error_message != NULL)
954     {
955       dbus_message_iter_init_append (message, &iter);
956       if (!dbus_message_iter_append_basic (&iter,
957                                            DBUS_TYPE_STRING,
958                                            &error_message))
959         {
960           dbus_message_unref (message);
961           return NULL;
962         }
963     }
964
965   return message;
966 }
967
968 /**
969  * Creates a new message that is an error reply to a certain message.
970  * Error replies are possible in response to method calls primarily.
971  *
972  * @param reply_to the original message
973  * @param error_name the error name
974  * @param error_format the error message format as with printf
975  * @param ... format string arguments
976  * @returns a new error message
977  */
978 DBusMessage*
979 dbus_message_new_error_printf (DBusMessage *reply_to,
980                                const char  *error_name,
981                                const char  *error_format,
982                                ...)
983 {
984   va_list args;
985   DBusString str;
986   DBusMessage *message;
987
988   _dbus_return_val_if_fail (reply_to != NULL, NULL);
989   _dbus_return_val_if_fail (error_name != NULL, NULL);
990   _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
991
992   if (!_dbus_string_init (&str))
993     return NULL;
994
995   va_start (args, error_format);
996
997   if (_dbus_string_append_printf_valist (&str, error_format, args))
998     message = dbus_message_new_error (reply_to, error_name,
999                                       _dbus_string_get_const_data (&str));
1000   else
1001     message = NULL;
1002
1003   _dbus_string_free (&str);
1004
1005   va_end (args);
1006
1007   return message;
1008 }
1009
1010
1011 /**
1012  * Creates a new message that is an exact replica of the message
1013  * specified, except that its refcount is set to 1, its message serial
1014  * is reset to 0, and if the original message was "locked" (in the
1015  * outgoing message queue and thus not modifiable) the new message
1016  * will not be locked.
1017  *
1018  * @param message the message.
1019  * @returns the new message.
1020  */
1021 DBusMessage *
1022 dbus_message_copy (const DBusMessage *message)
1023 {
1024   DBusMessage *retval;
1025
1026   _dbus_return_val_if_fail (message != NULL, NULL);
1027
1028   retval = dbus_new0 (DBusMessage, 1);
1029   if (retval == NULL)
1030     return NULL;
1031
1032   retval->refcount.value = 1;
1033   retval->byte_order = message->byte_order;
1034   retval->locked = FALSE;
1035 #ifndef DBUS_DISABLE_CHECKS
1036   retval->generation = message->generation;
1037 #endif
1038
1039   if (!_dbus_header_copy (&message->header, &retval->header))
1040     {
1041       dbus_free (retval);
1042       return NULL;
1043     }
1044
1045   if (!_dbus_string_init_preallocated (&retval->body,
1046                                        _dbus_string_get_length (&message->body)))
1047     {
1048       _dbus_header_free (&retval->header);
1049       dbus_free (retval);
1050       return NULL;
1051     }
1052
1053   if (!_dbus_string_copy (&message->body, 0,
1054                           &retval->body, 0))
1055     goto failed_copy;
1056
1057   return retval;
1058
1059  failed_copy:
1060   _dbus_header_free (&retval->header);
1061   _dbus_string_free (&retval->body);
1062   dbus_free (retval);
1063
1064   return NULL;
1065 }
1066
1067
1068 /**
1069  * Increments the reference count of a DBusMessage.
1070  *
1071  * @param message The message
1072  * @returns the message
1073  * @see dbus_message_unref
1074  */
1075 DBusMessage *
1076 dbus_message_ref (DBusMessage *message)
1077 {
1078   dbus_int32_t old_refcount;
1079
1080   _dbus_return_val_if_fail (message != NULL, NULL);
1081   _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
1082
1083   old_refcount = _dbus_atomic_inc (&message->refcount);
1084   _dbus_assert (old_refcount >= 1);
1085
1086   return message;
1087 }
1088
1089 /**
1090  * Decrements the reference count of a DBusMessage.
1091  *
1092  * @param message The message
1093  * @see dbus_message_ref
1094  */
1095 void
1096 dbus_message_unref (DBusMessage *message)
1097 {
1098  dbus_int32_t old_refcount;
1099
1100   _dbus_return_if_fail (message != NULL);
1101   _dbus_return_if_fail (message->generation == _dbus_current_generation);
1102
1103   old_refcount = _dbus_atomic_dec (&message->refcount);
1104
1105   _dbus_assert (old_refcount >= 0);
1106
1107   if (old_refcount == 1)
1108     {
1109       /* Calls application callbacks! */
1110       dbus_message_cache_or_finalize (message);
1111     }
1112 }
1113
1114 /**
1115  * Gets the type of a message. Types include
1116  * #DBUS_MESSAGE_TYPE_METHOD_CALL, #DBUS_MESSAGE_TYPE_METHOD_RETURN,
1117  * #DBUS_MESSAGE_TYPE_ERROR, #DBUS_MESSAGE_TYPE_SIGNAL, but other
1118  * types are allowed and all code must silently ignore messages of
1119  * unknown type. DBUS_MESSAGE_TYPE_INVALID will never be returned,
1120  * however.
1121  *
1122  *
1123  * @param message the message
1124  * @returns the type of the message
1125  */
1126 int
1127 dbus_message_get_type (DBusMessage *message)
1128 {
1129   _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
1130
1131   return _dbus_header_get_message_type (&message->header);
1132 }
1133
1134 /**
1135  * Appends fields to a message given a variable argument list. The
1136  * variable argument list should contain the type of each argument
1137  * followed by the value to append. Appendable types are basic types,
1138  * and arrays of fixed-length basic types. To append variable-length
1139  * basic types, or any more complex value, you have to use an iterator
1140  * rather than this function.
1141  *
1142  * To append a basic type, specify its type code followed by the
1143  * value. For example:
1144  *
1145  * @code
1146  * DBUS_TYPE_INT32, 42,
1147  * DBUS_TYPE_STRING, "Hello World"
1148  * @endcode
1149  * or
1150  * @code
1151  * dbus_int32_t val = 42;
1152  * DBUS_TYPE_INT32, val
1153  * @endcode
1154  *
1155  * Be sure that your provided value is the right size. For example, this
1156  * won't work:
1157  * @code
1158  * DBUS_TYPE_INT64, 42
1159  * @endcode
1160  * Because the "42" will be a 32-bit integer. You need to cast to
1161  * 64-bit.
1162  *
1163  * To append an array of fixed-length basic types, pass in the
1164  * DBUS_TYPE_ARRAY typecode, the element typecode, the address of
1165  * the array pointer, and a 32-bit integer giving the number of
1166  * elements in the array. So for example:
1167  * @code
1168  * const dbus_int32_t array[] = { 1, 2, 3 };
1169  * const dbus_int32_t *v_ARRAY = array;
1170  * DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY, 3
1171  * @endcode
1172  *
1173  * @warning in C, given "int array[]", "&array == array" (the
1174  * comp.lang.c FAQ says otherwise, but gcc and the FAQ don't agree).
1175  * So if you're using an array instead of a pointer you have to create
1176  * a pointer variable, assign the array to it, then take the address
1177  * of the pointer variable. For strings it works to write
1178  * const char *array = "Hello" and then use &array though.
1179  *
1180  * The last argument to this function must be #DBUS_TYPE_INVALID,
1181  * marking the end of the argument list.
1182  *
1183  * @todo support DBUS_TYPE_STRUCT and DBUS_TYPE_VARIANT and complex arrays
1184  *
1185  * @todo If this fails due to lack of memory, the message is hosed and
1186  * you have to start over building the whole message.
1187  *
1188  * @param message the message
1189  * @param first_arg_type type of the first argument
1190  * @param ... value of first argument, list of additional type-value pairs
1191  * @returns #TRUE on success
1192  */
1193 dbus_bool_t
1194 dbus_message_append_args (DBusMessage *message,
1195                           int          first_arg_type,
1196                           ...)
1197 {
1198   dbus_bool_t retval;
1199   va_list var_args;
1200
1201   _dbus_return_val_if_fail (message != NULL, FALSE);
1202
1203   va_start (var_args, first_arg_type);
1204   retval = dbus_message_append_args_valist (message,
1205                                             first_arg_type,
1206                                             var_args);
1207   va_end (var_args);
1208
1209   return retval;
1210 }
1211
1212 /**
1213  * This function takes a va_list for use by language bindings.
1214  * It's otherwise the same as dbus_message_append_args().
1215  *
1216  * @todo for now, if this function fails due to OOM it will leave
1217  * the message half-written and you have to discard the message
1218  * and start over.
1219  *
1220  * @see dbus_message_append_args.
1221  * @param message the message
1222  * @param first_arg_type type of first argument
1223  * @param var_args value of first argument, then list of type/value pairs
1224  * @returns #TRUE on success
1225  */
1226 dbus_bool_t
1227 dbus_message_append_args_valist (DBusMessage *message,
1228                                  int          first_arg_type,
1229                                  va_list      var_args)
1230 {
1231   int type;
1232   DBusMessageIter iter;
1233
1234   _dbus_return_val_if_fail (message != NULL, FALSE);
1235
1236   type = first_arg_type;
1237
1238   dbus_message_iter_init_append (message, &iter);
1239
1240   while (type != DBUS_TYPE_INVALID)
1241     {
1242       if (_dbus_type_is_basic (type))
1243         {
1244           const DBusBasicValue *value;
1245           value = va_arg (var_args, const DBusBasicValue*);
1246
1247           if (!dbus_message_iter_append_basic (&iter,
1248                                                type,
1249                                                value))
1250             goto failed;
1251         }
1252       else if (type == DBUS_TYPE_ARRAY)
1253         {
1254           int element_type;
1255           const DBusBasicValue **value;
1256           int n_elements;
1257           DBusMessageIter array;
1258           char buf[2];
1259
1260           element_type = va_arg (var_args, int);
1261
1262 #ifndef DBUS_DISABLE_CHECKS
1263           if (!_dbus_type_is_fixed (element_type))
1264             {
1265               _dbus_warn ("arrays of %s can't be appended with %s for now\n",
1266                           _dbus_type_to_string (element_type),
1267                           _DBUS_FUNCTION_NAME);
1268               goto failed;
1269             }
1270 #endif
1271
1272           value = va_arg (var_args, const DBusBasicValue**);
1273           n_elements = va_arg (var_args, int);
1274
1275           buf[0] = element_type;
1276           buf[1] = '\0';
1277           if (!dbus_message_iter_open_container (&iter,
1278                                                  DBUS_TYPE_ARRAY,
1279                                                  buf,
1280                                                  &array))
1281             goto failed;
1282
1283           if (!dbus_message_iter_append_fixed_array (&array,
1284                                                      element_type,
1285                                                      value,
1286                                                      n_elements))
1287             goto failed;
1288
1289           if (!dbus_message_iter_close_container (&iter, &array))
1290             goto failed;
1291         }
1292 #ifndef DBUS_DISABLE_CHECKS
1293       else
1294         {
1295           _dbus_warn ("type %s isn't supported yet in %s\n",
1296                       _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
1297           goto failed;
1298         }
1299 #endif
1300
1301       type = va_arg (var_args, int);
1302     }
1303
1304   return TRUE;
1305
1306  failed:
1307   return FALSE;
1308 }
1309
1310 /**
1311  * Gets arguments from a message given a variable argument list.  The
1312  * supported types include those supported by
1313  * dbus_message_append_args(); that is, basic types and arrays of
1314  * fixed-length basic types.  The arguments are the same as they would
1315  * be for dbus_message_iter_get_basic() or
1316  * dbus_message_iter_get_fixed_array().
1317  *
1318  * In addition to those types, arrays of string, object path, and
1319  * signature are supported; but these are returned as allocated memory
1320  * and must be freed with dbus_free_string_array(), while the other
1321  * types are returned as const references.
1322  *
1323  * The variable argument list should contain the type of the argument
1324  * followed by a pointer to where the value should be stored. The list
1325  * is terminated with #DBUS_TYPE_INVALID.
1326  *
1327  * The returned values are constant; do not free them. They point
1328  * into the #DBusMessage.
1329  *
1330  * If the requested arguments are not present, or do not have the
1331  * requested types, then an error will be set.
1332  *
1333  * @todo support DBUS_TYPE_STRUCT and DBUS_TYPE_VARIANT and complex arrays
1334  *
1335  * @param message the message
1336  * @param error error to be filled in on failure
1337  * @param first_arg_type the first argument type
1338  * @param ... location for first argument value, then list of type-location pairs
1339  * @returns #FALSE if the error was set
1340  */
1341 dbus_bool_t
1342 dbus_message_get_args (DBusMessage     *message,
1343                        DBusError       *error,
1344                        int              first_arg_type,
1345                        ...)
1346 {
1347   dbus_bool_t retval;
1348   va_list var_args;
1349
1350   _dbus_return_val_if_fail (message != NULL, FALSE);
1351   _dbus_return_val_if_error_is_set (error, FALSE);
1352
1353   va_start (var_args, first_arg_type);
1354   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
1355   va_end (var_args);
1356
1357   return retval;
1358 }
1359
1360 /**
1361  * This function takes a va_list for use by language bindings. It is
1362  * otherwise the same as dbus_message_get_args().
1363  *
1364  * @see dbus_message_get_args
1365  * @param message the message
1366  * @param error error to be filled in
1367  * @param first_arg_type type of the first argument
1368  * @param var_args return location for first argument, followed by list of type/location pairs
1369  * @returns #FALSE if error was set
1370  */
1371 dbus_bool_t
1372 dbus_message_get_args_valist (DBusMessage     *message,
1373                               DBusError       *error,
1374                               int              first_arg_type,
1375                               va_list          var_args)
1376 {
1377   DBusMessageIter iter;
1378
1379   _dbus_return_val_if_fail (message != NULL, FALSE);
1380   _dbus_return_val_if_error_is_set (error, FALSE);
1381
1382   dbus_message_iter_init (message, &iter);
1383   return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
1384 }
1385
1386 /**
1387  * Reads arguments from a message iterator given a variable argument
1388  * list. Only arguments of basic type and arrays of fixed-length
1389  * basic type may be read with this function. See
1390  * dbus_message_get_args() for more details.
1391  *
1392  * @todo this is static for now because there's no corresponding
1393  * iter_append_args() and I'm not sure we need this function to be
1394  * public since dbus_message_get_args() is what you usually want
1395  *
1396  * @param iter the message iterator
1397  * @param error error to be filled in on failure
1398  * @param first_arg_type the first argument type
1399  * @param ... location for first argument value, then list of type-location pairs
1400  * @returns #FALSE if the error was set
1401  */
1402 static dbus_bool_t
1403 dbus_message_iter_get_args (DBusMessageIter *iter,
1404                             DBusError       *error,
1405                             int              first_arg_type,
1406                             ...)
1407 {
1408   dbus_bool_t retval;
1409   va_list var_args;
1410
1411   _dbus_return_val_if_fail (iter != NULL, FALSE);
1412   _dbus_return_val_if_error_is_set (error, FALSE);
1413
1414   va_start (var_args, first_arg_type);
1415   retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
1416   va_end (var_args);
1417
1418   return retval;
1419 }
1420
1421 static void
1422 _dbus_message_iter_init_common (DBusMessage         *message,
1423                                 DBusMessageRealIter *real,
1424                                 int                  iter_type)
1425 {
1426   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
1427
1428   real->message = message;
1429   real->changed_stamp = message->changed_stamp;
1430   real->iter_type = iter_type;
1431   real->sig_refcount = 0;
1432 }
1433
1434 /**
1435  * Initializes a #DBusMessageIter for reading the arguments of the
1436  * message passed in.
1437  *
1438  * @param message the message
1439  * @param iter pointer to an iterator to initialize
1440  * @returns #FALSE if the message has no arguments
1441  */
1442 dbus_bool_t
1443 dbus_message_iter_init (DBusMessage     *message,
1444                         DBusMessageIter *iter)
1445 {
1446   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1447   const DBusString *type_str;
1448   int type_pos;
1449
1450   _dbus_return_val_if_fail (message != NULL, FALSE);
1451   _dbus_return_val_if_fail (iter != NULL, FALSE);
1452
1453   get_const_signature (&message->header, &type_str, &type_pos);
1454
1455   _dbus_message_iter_init_common (message, real,
1456                                   DBUS_MESSAGE_ITER_TYPE_READER);
1457
1458   _dbus_type_reader_init (&real->u.reader,
1459                           message->byte_order,
1460                           type_str, type_pos,
1461                           &message->body,
1462                           0);
1463
1464   return _dbus_type_reader_has_next (&real->u.reader);
1465 }
1466
1467 #ifndef DBUS_DISABLE_CHECKS
1468 static dbus_bool_t
1469 _dbus_message_iter_check (DBusMessageRealIter *iter)
1470 {
1471   if (iter == NULL)
1472     {
1473       _dbus_warn ("dbus message iterator is NULL\n");
1474       return FALSE;
1475     }
1476
1477   if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
1478     {
1479       if (iter->u.reader.byte_order != iter->message->byte_order)
1480         {
1481           _dbus_warn ("dbus message changed byte order since iterator was created\n");
1482           return FALSE;
1483         }
1484     }
1485   else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
1486     {
1487       if (iter->u.writer.byte_order != iter->message->byte_order)
1488         {
1489           _dbus_warn ("dbus message changed byte order since append iterator was created\n");
1490           return FALSE;
1491         }
1492     }
1493   else
1494     {
1495       _dbus_warn ("dbus message iterator looks uninitialized or corrupted\n");
1496       return FALSE;
1497     }
1498
1499   if (iter->changed_stamp != iter->message->changed_stamp)
1500     {
1501       _dbus_warn ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
1502       return FALSE;
1503     }
1504
1505   return TRUE;
1506 }
1507 #endif /* DBUS_DISABLE_CHECKS */
1508
1509 /**
1510  * Checks if an iterator has any more fields.
1511  *
1512  * @param iter the message iter
1513  * @returns #TRUE if there are more fields
1514  * following
1515  */
1516 dbus_bool_t
1517 dbus_message_iter_has_next (DBusMessageIter *iter)
1518 {
1519   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1520
1521   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
1522   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
1523
1524   return _dbus_type_reader_has_next (&real->u.reader);
1525 }
1526
1527 /**
1528  * Moves the iterator to the next field, if any. If there's no next
1529  * field, returns #FALSE. If the iterator moves forward, returns
1530  * #TRUE.
1531  *
1532  * @param iter the message iter
1533  * @returns #TRUE if the iterator was moved to the next field
1534  */
1535 dbus_bool_t
1536 dbus_message_iter_next (DBusMessageIter *iter)
1537 {
1538   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1539
1540   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
1541   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
1542
1543   return _dbus_type_reader_next (&real->u.reader);
1544 }
1545
1546 /**
1547  * Returns the argument type of the argument that the message iterator
1548  * points to. If the iterator is at the end of the message, returns
1549  * #DBUS_TYPE_INVALID. You can thus write a loop as follows:
1550  *
1551  * @code
1552  * dbus_message_iter_init (&iter);
1553  * while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
1554  *   dbus_message_iter_next (&iter);
1555  * @endcode
1556  *
1557  * @param iter the message iter
1558  * @returns the argument type
1559  */
1560 int
1561 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
1562 {
1563   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1564
1565   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
1566   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
1567
1568   return _dbus_type_reader_get_current_type (&real->u.reader);
1569 }
1570
1571 /**
1572  * Returns the element type of the array that the message iterator
1573  * points to. Note that you need to check that the iterator points to
1574  * an array prior to using this function.
1575  *
1576  * @param iter the message iter
1577  * @returns the array element type
1578  */
1579 int
1580 dbus_message_iter_get_element_type (DBusMessageIter *iter)
1581 {
1582   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1583
1584   _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
1585   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
1586   _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
1587
1588   return _dbus_type_reader_get_element_type (&real->u.reader);
1589 }
1590
1591 /**
1592  * Recurses into a container value when reading values from a message,
1593  * initializing a sub-iterator to use for traversing the child values
1594  * of the container.
1595  *
1596  * Note that this recurses into a value, not a type, so you can only
1597  * recurse if the value exists. The main implication of this is that
1598  * if you have for example an empty array of array of int32, you can
1599  * recurse into the outermost array, but it will have no values, so
1600  * you won't be able to recurse further. There's no array of int32 to
1601  * recurse into.
1602  *
1603  * @param iter the message iterator
1604  * @param sub the sub-iterator to initialize
1605  */
1606 void
1607 dbus_message_iter_recurse (DBusMessageIter  *iter,
1608                            DBusMessageIter  *sub)
1609 {
1610   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1611   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
1612
1613   _dbus_return_if_fail (_dbus_message_iter_check (real));
1614   _dbus_return_if_fail (sub != NULL);
1615
1616   *real_sub = *real;
1617   _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
1618 }
1619
1620 /**
1621  * Reads a basic-typed value from the message iterator.
1622  * Basic types are the non-containers such as integer and string.
1623  *
1624  * The value argument should be the address of a location to store
1625  * the returned value. So for int32 it should be a "dbus_int32_t*"
1626  * and for string a "const char**". The returned value is
1627  * by reference and should not be freed.
1628  *
1629  * All returned values are guaranteed to fit in 8 bytes. So you can
1630  * write code like this:
1631  *
1632  * @code
1633  * #ifdef DBUS_HAVE_INT64
1634  * dbus_uint64_t value;
1635  * int type;
1636  * dbus_message_iter_get_basic (&read_iter, &value);
1637  * type = dbus_message_iter_get_arg_type (&read_iter);
1638  * dbus_message_iter_append_basic (&write_iter, type, &value);
1639  * #endif
1640  * @endcode
1641  *
1642  * To avoid the #DBUS_HAVE_INT64 conditional, create a struct or
1643  * something that occupies at least 8 bytes, e.g. you could use a
1644  * struct with two int32 values in it. dbus_uint64_t is just one
1645  * example of a type that's large enough to hold any possible value.
1646  *
1647  * Be sure you have somehow checked that
1648  * dbus_message_iter_get_arg_type() matches the type you are
1649  * expecting, or you'll crash when you try to use an integer as a
1650  * string or something.
1651  *
1652  * @param iter the iterator
1653  * @param value location to store the value
1654  */
1655 void
1656 dbus_message_iter_get_basic (DBusMessageIter  *iter,
1657                              void             *value)
1658 {
1659   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1660
1661   _dbus_return_if_fail (_dbus_message_iter_check (real));
1662   _dbus_return_if_fail (value != NULL);
1663
1664   _dbus_type_reader_read_basic (&real->u.reader,
1665                                 value);
1666 }
1667
1668 /**
1669  * Reads a block of fixed-length values from the message iterator.
1670  * Fixed-length values are those basic types that are not string-like,
1671  * such as integers, bool, double. The block read will be from the
1672  * current position in the array until the end of the array.
1673  *
1674  * The value argument should be the address of a location to store the
1675  * returned array. So for int32 it should be a "const dbus_int32_t**"
1676  * The returned value is by reference and should not be freed.
1677  *
1678  * @param iter the iterator
1679  * @param value location to store the block
1680  * @param n_elements number of elements in the block
1681  */
1682 void
1683 dbus_message_iter_get_fixed_array (DBusMessageIter  *iter,
1684                                    void             *value,
1685                                    int              *n_elements)
1686 {
1687   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1688
1689   _dbus_return_if_fail (_dbus_message_iter_check (real));
1690   _dbus_return_if_fail (value != NULL);
1691   _dbus_return_if_fail (_dbus_type_is_fixed (_dbus_type_reader_get_element_type (&real->u.reader)));
1692
1693   _dbus_type_reader_read_fixed_multi (&real->u.reader,
1694                                       value, n_elements);
1695 }
1696
1697 /**
1698  * This function takes a va_list for use by language bindings and is
1699  * otherwise the same as dbus_message_iter_get_args().
1700  * dbus_message_get_args() is the place to go for complete
1701  * documentation.
1702  *
1703  * @todo this is static for now, should be public if
1704  * dbus_message_iter_get_args_valist() is made public.
1705  *
1706  * @see dbus_message_get_args
1707  * @param iter the message iter
1708  * @param error error to be filled in
1709  * @param first_arg_type type of the first argument
1710  * @param var_args return location for first argument, followed by list of type/location pairs
1711  * @returns #FALSE if error was set
1712  */
1713 static dbus_bool_t
1714 dbus_message_iter_get_args_valist (DBusMessageIter *iter,
1715                                    DBusError       *error,
1716                                    int              first_arg_type,
1717                                    va_list          var_args)
1718 {
1719   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1720   int spec_type, msg_type, i;
1721   dbus_bool_t retval;
1722
1723   _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
1724   _dbus_return_val_if_error_is_set (error, FALSE);
1725
1726   retval = FALSE;
1727
1728   spec_type = first_arg_type;
1729   i = 0;
1730
1731   while (spec_type != DBUS_TYPE_INVALID)
1732     {
1733       msg_type = dbus_message_iter_get_arg_type (iter);
1734
1735       if (msg_type != spec_type)
1736         {
1737           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1738                           "Argument %d is specified to be of type \"%s\", but "
1739                           "is actually of type \"%s\"\n", i,
1740                           _dbus_type_to_string (spec_type),
1741                           _dbus_type_to_string (msg_type));
1742
1743           goto out;
1744         }
1745
1746       if (_dbus_type_is_basic (spec_type))
1747         {
1748           DBusBasicValue *ptr;
1749
1750           ptr = va_arg (var_args, DBusBasicValue*);
1751
1752           _dbus_return_val_if_fail (ptr != NULL, FALSE);
1753
1754           _dbus_type_reader_read_basic (&real->u.reader,
1755                                         ptr);
1756         }
1757       else if (spec_type == DBUS_TYPE_ARRAY)
1758         {
1759           int element_type;
1760           int spec_element_type;
1761           const DBusBasicValue **ptr;
1762           int *n_elements_p;
1763           DBusTypeReader array;
1764
1765           spec_element_type = va_arg (var_args, int);
1766           element_type = _dbus_type_reader_get_element_type (&real->u.reader);
1767
1768           if (spec_element_type != element_type)
1769             {
1770               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1771                               "Argument %d is specified to be an array of \"%s\", but "
1772                               "is actually an array of \"%s\"\n",
1773                               i,
1774                               _dbus_type_to_string (spec_element_type),
1775                               _dbus_type_to_string (element_type));
1776
1777               goto out;
1778             }
1779
1780           if (_dbus_type_is_fixed (spec_element_type))
1781             {
1782               ptr = va_arg (var_args, const DBusBasicValue**);
1783               n_elements_p = va_arg (var_args, int*);
1784
1785               _dbus_return_val_if_fail (ptr != NULL, FALSE);
1786               _dbus_return_val_if_fail (n_elements_p != NULL, FALSE);
1787
1788               _dbus_type_reader_recurse (&real->u.reader, &array);
1789
1790               _dbus_type_reader_read_fixed_multi (&array,
1791                                                   ptr, n_elements_p);
1792             }
1793           else if (spec_element_type == DBUS_TYPE_STRING ||
1794                    spec_element_type == DBUS_TYPE_SIGNATURE ||
1795                    spec_element_type == DBUS_TYPE_OBJECT_PATH)
1796             {
1797               char ***str_array_p;
1798               int i;
1799               char **str_array;
1800
1801               str_array_p = va_arg (var_args, char***);
1802               n_elements_p = va_arg (var_args, int*);
1803
1804               _dbus_return_val_if_fail (str_array_p != NULL, FALSE);
1805               _dbus_return_val_if_fail (n_elements_p != NULL, FALSE);
1806
1807               /* Count elements in the array */
1808               _dbus_type_reader_recurse (&real->u.reader, &array);
1809
1810               i = 0;
1811               if (_dbus_type_reader_has_next (&array))
1812                 {
1813                   while (_dbus_type_reader_next (&array))
1814                     ++i;
1815                 }
1816
1817               str_array = dbus_new0 (char*, i + 1);
1818               if (str_array == NULL)
1819                 {
1820                   _DBUS_SET_OOM (error);
1821                   goto out;
1822                 }
1823
1824               /* Now go through and dup each string */
1825               _dbus_type_reader_recurse (&real->u.reader, &array);
1826
1827               i = 0;
1828               if (_dbus_type_reader_has_next (&array))
1829                 {
1830                   do
1831                     {
1832                       const char *s;
1833                       _dbus_type_reader_read_basic (&array,
1834                                                     &s);
1835
1836                       str_array[i] = _dbus_strdup (s);
1837                       if (str_array[i] == NULL)
1838                         {
1839                           dbus_free_string_array (str_array);
1840                           _DBUS_SET_OOM (error);
1841                           goto out;
1842                         }
1843
1844                       ++i;
1845                     }
1846                   while (_dbus_type_reader_next (&array));
1847                 }
1848
1849               *str_array_p = str_array;
1850               *n_elements_p = i;
1851             }
1852 #ifndef DBUS_DISABLE_CHECKS
1853           else
1854             {
1855               _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
1856                           _DBUS_FUNCTION_NAME);
1857               goto out;
1858             }
1859 #endif
1860         }
1861 #ifndef DBUS_DISABLE_CHECKS
1862       else
1863         {
1864           _dbus_warn ("you can only read arrays and basic types with %s for now\n",
1865                       _DBUS_FUNCTION_NAME);
1866           goto out;
1867         }
1868 #endif
1869
1870       spec_type = va_arg (var_args, int);
1871       if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
1872         {
1873           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1874                           "Message has only %d arguments, but more were expected", i);
1875           goto out;
1876         }
1877
1878       i++;
1879     }
1880
1881   retval = TRUE;
1882
1883  out:
1884
1885   return retval;
1886 }
1887
1888 /**
1889  * Initializes a #DBusMessageIter for appending arguments to the end
1890  * of a message.
1891  *
1892  * @todo If appending any of the arguments fails due to lack of
1893  * memory, generally the message is hosed and you have to start over
1894  * building the whole message.
1895  *
1896  * @param message the message
1897  * @param iter pointer to an iterator to initialize
1898  */
1899 void
1900 dbus_message_iter_init_append (DBusMessage     *message,
1901                                DBusMessageIter *iter)
1902 {
1903   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1904
1905   _dbus_return_if_fail (message != NULL);
1906   _dbus_return_if_fail (iter != NULL);
1907
1908   _dbus_message_iter_init_common (message, real,
1909                                   DBUS_MESSAGE_ITER_TYPE_WRITER);
1910
1911   /* We create the signature string and point iterators at it "on demand"
1912    * when a value is actually appended. That means that init() never fails
1913    * due to OOM.
1914    */
1915   _dbus_type_writer_init_types_delayed (&real->u.writer,
1916                                         message->byte_order,
1917                                         &message->body,
1918                                         _dbus_string_get_length (&message->body));
1919 }
1920
1921 /**
1922  * Creates a temporary signature string containing the current
1923  * signature, stores it in the iterator, and points the iterator to
1924  * the end of it. Used any time we write to the message.
1925  *
1926  * @param real an iterator without a type_str
1927  * @returns #FALSE if no memory
1928  */
1929 static dbus_bool_t
1930 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
1931 {
1932   DBusString *str;
1933   const DBusString *current_sig;
1934   int current_sig_pos;
1935
1936   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
1937
1938   if (real->u.writer.type_str != NULL)
1939     {
1940       _dbus_assert (real->sig_refcount > 0);
1941       real->sig_refcount += 1;
1942       return TRUE;
1943     }
1944
1945   str = dbus_new (DBusString, 1);
1946   if (str == NULL)
1947     return FALSE;
1948
1949   if (!_dbus_header_get_field_raw (&real->message->header,
1950                                    DBUS_HEADER_FIELD_SIGNATURE,
1951                                    &current_sig, &current_sig_pos))
1952     current_sig = NULL;
1953
1954   if (current_sig)
1955     {
1956       int current_len;
1957
1958       current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
1959       current_sig_pos += 1; /* move on to sig data */
1960
1961       if (!_dbus_string_init_preallocated (str, current_len + 4))
1962         {
1963           dbus_free (str);
1964           return FALSE;
1965         }
1966
1967       if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
1968                                   str, 0))
1969         {
1970           _dbus_string_free (str);
1971           dbus_free (str);
1972           return FALSE;
1973         }
1974     }
1975   else
1976     {
1977       if (!_dbus_string_init_preallocated (str, 4))
1978         {
1979           dbus_free (str);
1980           return FALSE;
1981         }
1982     }
1983
1984   real->sig_refcount = 1;
1985
1986   _dbus_type_writer_add_types (&real->u.writer,
1987                                str, _dbus_string_get_length (str));
1988   return TRUE;
1989 }
1990
1991 /**
1992  * Sets the new signature as the message signature, frees the
1993  * signature string, and marks the iterator as not having a type_str
1994  * anymore. Frees the signature even if it fails, so you can't
1995  * really recover from failure. Kinda busted.
1996  *
1997  * @param real an iterator without a type_str
1998  * @returns #FALSE if no memory
1999  */
2000 static dbus_bool_t
2001 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
2002 {
2003   DBusString *str;
2004   const char *v_STRING;
2005   dbus_bool_t retval;
2006
2007   _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2008   _dbus_assert (real->u.writer.type_str != NULL);
2009   _dbus_assert (real->sig_refcount > 0);
2010
2011   real->sig_refcount -= 1;
2012
2013   if (real->sig_refcount > 0)
2014     return TRUE;
2015   _dbus_assert (real->sig_refcount == 0);
2016
2017   retval = TRUE;
2018
2019   str = real->u.writer.type_str;
2020
2021   v_STRING = _dbus_string_get_const_data (str);
2022   if (!_dbus_header_set_field_basic (&real->message->header,
2023                                      DBUS_HEADER_FIELD_SIGNATURE,
2024                                      DBUS_TYPE_SIGNATURE,
2025                                      &v_STRING))
2026     retval = FALSE;
2027
2028   _dbus_type_writer_remove_types (&real->u.writer);
2029   _dbus_string_free (str);
2030   dbus_free (str);
2031
2032   return retval;
2033 }
2034
2035 #ifndef DBUS_DISABLE_CHECKS
2036 static dbus_bool_t
2037 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
2038 {
2039   if (!_dbus_message_iter_check (iter))
2040     return FALSE;
2041
2042   if (iter->message->locked)
2043     {
2044       _dbus_warn ("dbus append iterator can't be used: message is locked (has already been sent)\n");
2045       return FALSE;
2046     }
2047
2048   return TRUE;
2049 }
2050 #endif /* DBUS_DISABLE_CHECKS */
2051
2052 /**
2053  * Appends a basic-typed value to the message. The basic types are the
2054  * non-container types such as integer and string.
2055  *
2056  * The "value" argument should be the address of a basic-typed value.
2057  * So for string, const char**. For integer, dbus_int32_t*.
2058  *
2059  * @todo If this fails due to lack of memory, the message is hosed and
2060  * you have to start over building the whole message.
2061  *
2062  * @param iter the append iterator
2063  * @param type the type of the value
2064  * @param value the address of the value
2065  * @returns #FALSE if not enough memory
2066  */
2067 dbus_bool_t
2068 dbus_message_iter_append_basic (DBusMessageIter *iter,
2069                                 int              type,
2070                                 const void      *value)
2071 {
2072   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2073   dbus_bool_t ret;
2074
2075   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2076   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2077   _dbus_return_val_if_fail (_dbus_type_is_basic (type), FALSE);
2078   _dbus_return_val_if_fail (value != NULL, FALSE);
2079
2080   if (!_dbus_message_iter_open_signature (real))
2081     return FALSE;
2082
2083   ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
2084
2085   if (!_dbus_message_iter_close_signature (real))
2086     ret = FALSE;
2087
2088   return ret;
2089 }
2090
2091 /**
2092  * Appends a block of fixed-length values to an array. The
2093  * fixed-length types are all basic types that are not string-like. So
2094  * int32, double, bool, etc. You must call
2095  * dbus_message_iter_open_container() to open an array of values
2096  * before calling this function. You may call this function multiple
2097  * times (and intermixed with calls to
2098  * dbus_message_iter_append_basic()) for the same array.
2099  *
2100  * The "value" argument should be the address of the array.  So for
2101  * integer, "dbus_int32_t**" is expected for example.
2102  *
2103  * @warning in C, given "int array[]", "&array == array" (the
2104  * comp.lang.c FAQ says otherwise, but gcc and the FAQ don't agree).
2105  * So if you're using an array instead of a pointer you have to create
2106  * a pointer variable, assign the array to it, then take the address
2107  * of the pointer variable.
2108  * @code
2109  * const dbus_int32_t array[] = { 1, 2, 3 };
2110  * const dbus_int32_t *v_ARRAY = array;
2111  * if (!dbus_message_iter_append_fixed_array (&iter, DBUS_TYPE_INT32, &v_ARRAY, 3))
2112  *   fprintf (stderr, "No memory!\n");
2113  * @endcode
2114  * For strings it works to write const char *array = "Hello" and then
2115  * use &array though.
2116  *
2117  * @todo If this fails due to lack of memory, the message is hosed and
2118  * you have to start over building the whole message.
2119  *
2120  * @param iter the append iterator
2121  * @param element_type the type of the array elements
2122  * @param value the address of the array
2123  * @param n_elements the number of elements to append
2124  * @returns #FALSE if not enough memory
2125  */
2126 dbus_bool_t
2127 dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
2128                                       int              element_type,
2129                                       const void      *value,
2130                                       int              n_elements)
2131 {
2132   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2133   dbus_bool_t ret;
2134
2135   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2136   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2137   _dbus_return_val_if_fail (_dbus_type_is_fixed (element_type), FALSE);
2138   _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
2139   _dbus_return_val_if_fail (value != NULL, FALSE);
2140   _dbus_return_val_if_fail (n_elements >= 0, FALSE);
2141   _dbus_return_val_if_fail (n_elements <=
2142                             DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
2143                             FALSE);
2144
2145   ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
2146
2147   return ret;
2148 }
2149
2150 /**
2151  * Appends a container-typed value to the message; you are required to
2152  * append the contents of the container using the returned
2153  * sub-iterator, and then call
2154  * dbus_message_iter_close_container(). Container types are for
2155  * example struct, variant, and array. For variants, the
2156  * contained_signature should be the type of the single value inside
2157  * the variant. For structs, contained_signature should be #NULL; it
2158  * will be set to whatever types you write into the struct.  For
2159  * arrays, contained_signature should be the type of the array
2160  * elements.
2161  *
2162  * @todo If this fails due to lack of memory, the message is hosed and
2163  * you have to start over building the whole message.
2164  *
2165  * @param iter the append iterator
2166  * @param type the type of the value
2167  * @param contained_signature the type of container contents
2168  * @param sub sub-iterator to initialize
2169  * @returns #FALSE if not enough memory
2170  */
2171 dbus_bool_t
2172 dbus_message_iter_open_container (DBusMessageIter *iter,
2173                                   int              type,
2174                                   const char      *contained_signature,
2175                                   DBusMessageIter *sub)
2176 {
2177   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2178   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2179   DBusString contained_str;
2180
2181   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2182   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2183   _dbus_return_val_if_fail (_dbus_type_is_container (type), FALSE);
2184   _dbus_return_val_if_fail (sub != NULL, FALSE);
2185   _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
2186                              contained_signature == NULL) ||
2187                             contained_signature != NULL, FALSE);
2188
2189   if (!_dbus_message_iter_open_signature (real))
2190     return FALSE;
2191
2192   _dbus_string_init_const (&contained_str, contained_signature);
2193
2194   *real_sub = *real;
2195   return _dbus_type_writer_recurse (&real->u.writer,
2196                                     type,
2197                                     &contained_str, 0,
2198                                     &real_sub->u.writer);
2199 }
2200
2201
2202 /**
2203  * Closes a container-typed value appended to the message; may write
2204  * out more information to the message known only after the entire
2205  * container is written, and may free resources created by
2206  * dbus_message_iter_open_container().
2207  *
2208  * @todo If this fails due to lack of memory, the message is hosed and
2209  * you have to start over building the whole message.
2210  *
2211  * @param iter the append iterator
2212  * @param sub sub-iterator to close
2213  * @returns #FALSE if not enough memory
2214  */
2215 dbus_bool_t
2216 dbus_message_iter_close_container (DBusMessageIter *iter,
2217                                    DBusMessageIter *sub)
2218 {
2219   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2220   DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2221   dbus_bool_t ret;
2222
2223   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2224   _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2225   _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
2226   _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2227
2228   ret = _dbus_type_writer_unrecurse (&real->u.writer,
2229                                      &real_sub->u.writer);
2230
2231   if (!_dbus_message_iter_close_signature (real))
2232     ret = FALSE;
2233
2234   return ret;
2235 }
2236
2237 /**
2238  * Sets a flag indicating that the message does not want a reply; if
2239  * this flag is set, the other end of the connection may (but is not
2240  * required to) optimize by not sending method return or error
2241  * replies. If this flag is set, there is no way to know whether the
2242  * message successfully arrived at the remote end. Normally you know a
2243  * message was received when you receive the reply to it.
2244  *
2245  * @param message the message
2246  * @param no_reply #TRUE if no reply is desired
2247  */
2248 void
2249 dbus_message_set_no_reply (DBusMessage *message,
2250                            dbus_bool_t  no_reply)
2251 {
2252   _dbus_return_if_fail (message != NULL);
2253   _dbus_return_if_fail (!message->locked);
2254
2255   _dbus_header_toggle_flag (&message->header,
2256                             DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
2257                             no_reply);
2258 }
2259
2260 /**
2261  * Returns #TRUE if the message does not expect
2262  * a reply.
2263  *
2264  * @param message the message
2265  * @returns #TRUE if the message sender isn't waiting for a reply
2266  */
2267 dbus_bool_t
2268 dbus_message_get_no_reply (DBusMessage *message)
2269 {
2270   _dbus_return_val_if_fail (message != NULL, FALSE);
2271
2272   return _dbus_header_get_flag (&message->header,
2273                                 DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
2274 }
2275
2276 /**
2277  * Sets a flag indicating that the addressed service will be
2278  * auto-activated before the message is delivered. When this flag is
2279  * set, the message is held until the service is succesfully activated
2280  * or fails to activate. In case of failure, the reply will be an
2281  * activation error. If this flag is not set (the default
2282  *
2283  * @param message the message
2284  * @param auto_activation #TRUE if auto-activation is desired
2285  */
2286 void
2287 dbus_message_set_auto_activation (DBusMessage *message,
2288                                   dbus_bool_t  auto_activation)
2289 {
2290   _dbus_return_if_fail (message != NULL);
2291   _dbus_return_if_fail (!message->locked);
2292
2293   _dbus_header_toggle_flag (&message->header,
2294                             DBUS_HEADER_FLAG_AUTO_ACTIVATION,
2295                             auto_activation);
2296 }
2297
2298 /**
2299  * Returns #TRUE if the message will cause the addressed service to be
2300  * auto-activated.
2301  *
2302  * @param message the message
2303  * @returns #TRUE if the message will use auto-activation
2304  */
2305 dbus_bool_t
2306 dbus_message_get_auto_activation (DBusMessage *message)
2307 {
2308   _dbus_return_val_if_fail (message != NULL, FALSE);
2309
2310   return _dbus_header_get_flag (&message->header,
2311                                 DBUS_HEADER_FLAG_AUTO_ACTIVATION);
2312 }
2313
2314
2315 /**
2316  * Sets the object path this message is being sent to (for
2317  * DBUS_MESSAGE_TYPE_METHOD_CALL) or the one a signal is being
2318  * emitted from (for DBUS_MESSAGE_TYPE_SIGNAL).
2319  *
2320  * @param message the message
2321  * @param object_path the path or #NULL to unset
2322  * @returns #FALSE if not enough memory
2323  */
2324 dbus_bool_t
2325 dbus_message_set_path (DBusMessage   *message,
2326                        const char    *object_path)
2327 {
2328   _dbus_return_val_if_fail (message != NULL, FALSE);
2329   _dbus_return_val_if_fail (!message->locked, FALSE);
2330   _dbus_return_val_if_fail (object_path == NULL ||
2331                             _dbus_check_is_valid_path (object_path),
2332                             FALSE);
2333
2334   return set_or_delete_string_field (message,
2335                                      DBUS_HEADER_FIELD_PATH,
2336                                      DBUS_TYPE_OBJECT_PATH,
2337                                      object_path);
2338 }
2339
2340 /**
2341  * Gets the object path this message is being sent to (for
2342  * DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted from (for
2343  * DBUS_MESSAGE_TYPE_SIGNAL). Returns #NULL if none.
2344  *
2345  * @param message the message
2346  * @returns the path (should not be freed) or #NULL
2347  */
2348 const char*
2349 dbus_message_get_path (DBusMessage   *message)
2350 {
2351   const char *v;
2352
2353   _dbus_return_val_if_fail (message != NULL, NULL);
2354
2355   v = NULL; /* in case field doesn't exist */
2356   _dbus_header_get_field_basic (&message->header,
2357                                 DBUS_HEADER_FIELD_PATH,
2358                                 DBUS_TYPE_OBJECT_PATH,
2359                                 &v);
2360   return v;
2361 }
2362
2363 /**
2364  * Gets the object path this message is being sent to
2365  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted
2366  * from (for DBUS_MESSAGE_TYPE_SIGNAL) in a decomposed
2367  * format (one array element per path component).
2368  * Free the returned array with dbus_free_string_array().
2369  *
2370  * An empty but non-NULL path array means the path "/".
2371  * So the path "/foo/bar" becomes { "foo", "bar", NULL }
2372  * and the path "/" becomes { NULL }.
2373  *
2374  * @todo this could be optimized by using the len from the message
2375  * instead of calling strlen() again
2376  *
2377  * @param message the message
2378  * @param path place to store allocated array of path components; #NULL set here if no path field exists
2379  * @returns #FALSE if no memory to allocate the array
2380  */
2381 dbus_bool_t
2382 dbus_message_get_path_decomposed (DBusMessage   *message,
2383                                   char        ***path)
2384 {
2385   const char *v;
2386
2387   _dbus_return_val_if_fail (message != NULL, FALSE);
2388   _dbus_return_val_if_fail (path != NULL, FALSE);
2389
2390   *path = NULL;
2391
2392   v = dbus_message_get_path (message);
2393   if (v != NULL)
2394     {
2395       if (!_dbus_decompose_path (v, strlen (v),
2396                                  path, NULL))
2397         return FALSE;
2398     }
2399   return TRUE;
2400 }
2401
2402 /**
2403  * Sets the interface this message is being sent to
2404  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or
2405  * the interface a signal is being emitted from
2406  * (for DBUS_MESSAGE_TYPE_SIGNAL).
2407  *
2408  * @param message the message
2409  * @param interface the interface or #NULL to unset
2410  * @returns #FALSE if not enough memory
2411  */
2412 dbus_bool_t
2413 dbus_message_set_interface (DBusMessage  *message,
2414                             const char   *interface)
2415 {
2416   _dbus_return_val_if_fail (message != NULL, FALSE);
2417   _dbus_return_val_if_fail (!message->locked, FALSE);
2418   _dbus_return_val_if_fail (interface == NULL ||
2419                             _dbus_check_is_valid_interface (interface),
2420                             FALSE);
2421
2422   return set_or_delete_string_field (message,
2423                                      DBUS_HEADER_FIELD_INTERFACE,
2424                                      DBUS_TYPE_STRING,
2425                                      interface);
2426 }
2427
2428 /**
2429  * Gets the interface this message is being sent to
2430  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted
2431  * from (for DBUS_MESSAGE_TYPE_SIGNAL).
2432  * The interface name is fully-qualified (namespaced).
2433  * Returns #NULL if none.
2434  *
2435  * @param message the message
2436  * @returns the message interface (should not be freed) or #NULL
2437  */
2438 const char*
2439 dbus_message_get_interface (DBusMessage *message)
2440 {
2441   const char *v;
2442
2443   _dbus_return_val_if_fail (message != NULL, NULL);
2444
2445   v = NULL; /* in case field doesn't exist */
2446   _dbus_header_get_field_basic (&message->header,
2447                                 DBUS_HEADER_FIELD_INTERFACE,
2448                                 DBUS_TYPE_STRING,
2449                                 &v);
2450   return v;
2451 }
2452
2453 /**
2454  * Sets the interface member being invoked
2455  * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
2456  * (DBUS_MESSAGE_TYPE_SIGNAL).
2457  * The interface name is fully-qualified (namespaced).
2458  *
2459  * @param message the message
2460  * @param member the member or #NULL to unset
2461  * @returns #FALSE if not enough memory
2462  */
2463 dbus_bool_t
2464 dbus_message_set_member (DBusMessage  *message,
2465                          const char   *member)
2466 {
2467   _dbus_return_val_if_fail (message != NULL, FALSE);
2468   _dbus_return_val_if_fail (!message->locked, FALSE);
2469   _dbus_return_val_if_fail (member == NULL ||
2470                             _dbus_check_is_valid_member (member),
2471                             FALSE);
2472
2473   return set_or_delete_string_field (message,
2474                                      DBUS_HEADER_FIELD_MEMBER,
2475                                      DBUS_TYPE_STRING,
2476                                      member);
2477 }
2478
2479 /**
2480  * Gets the interface member being invoked
2481  * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
2482  * (DBUS_MESSAGE_TYPE_SIGNAL). Returns #NULL if none.
2483  *
2484  * @param message the message
2485  * @returns the member name (should not be freed) or #NULL
2486  */
2487 const char*
2488 dbus_message_get_member (DBusMessage *message)
2489 {
2490   const char *v;
2491
2492   _dbus_return_val_if_fail (message != NULL, NULL);
2493
2494   v = NULL; /* in case field doesn't exist */
2495   _dbus_header_get_field_basic (&message->header,
2496                                 DBUS_HEADER_FIELD_MEMBER,
2497                                 DBUS_TYPE_STRING,
2498                                 &v);
2499   return v;
2500 }
2501
2502 /**
2503  * Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
2504  * The name is fully-qualified (namespaced).
2505  *
2506  * @param message the message
2507  * @param error_name the name or #NULL to unset
2508  * @returns #FALSE if not enough memory
2509  */
2510 dbus_bool_t
2511 dbus_message_set_error_name (DBusMessage  *message,
2512                              const char   *error_name)
2513 {
2514   _dbus_return_val_if_fail (message != NULL, FALSE);
2515   _dbus_return_val_if_fail (!message->locked, FALSE);
2516   _dbus_return_val_if_fail (error_name == NULL ||
2517                             _dbus_check_is_valid_error_name (error_name),
2518                             FALSE);
2519
2520   return set_or_delete_string_field (message,
2521                                      DBUS_HEADER_FIELD_ERROR_NAME,
2522                                      DBUS_TYPE_STRING,
2523                                      error_name);
2524 }
2525
2526 /**
2527  * Gets the error name (DBUS_MESSAGE_TYPE_ERROR only)
2528  * or #NULL if none.
2529  *
2530  * @param message the message
2531  * @returns the error name (should not be freed) or #NULL
2532  */
2533 const char*
2534 dbus_message_get_error_name (DBusMessage *message)
2535 {
2536   const char *v;
2537
2538   _dbus_return_val_if_fail (message != NULL, NULL);
2539
2540   v = NULL; /* in case field doesn't exist */
2541   _dbus_header_get_field_basic (&message->header,
2542                                 DBUS_HEADER_FIELD_ERROR_NAME,
2543                                 DBUS_TYPE_STRING,
2544                                 &v);
2545   return v;
2546 }
2547
2548 /**
2549  * Sets the message's destination service.
2550  *
2551  * @param message the message
2552  * @param destination the destination service name or #NULL to unset
2553  * @returns #FALSE if not enough memory
2554  */
2555 dbus_bool_t
2556 dbus_message_set_destination (DBusMessage  *message,
2557                               const char   *destination)
2558 {
2559   _dbus_return_val_if_fail (message != NULL, FALSE);
2560   _dbus_return_val_if_fail (!message->locked, FALSE);
2561   _dbus_return_val_if_fail (destination == NULL ||
2562                             _dbus_check_is_valid_service (destination),
2563                             FALSE);
2564
2565   return set_or_delete_string_field (message,
2566                                      DBUS_HEADER_FIELD_DESTINATION,
2567                                      DBUS_TYPE_STRING,
2568                                      destination);
2569 }
2570
2571 /**
2572  * Gets the destination service of a message or #NULL if there is
2573  * none set.
2574  *
2575  * @param message the message
2576  * @returns the message destination service (should not be freed) or #NULL
2577  */
2578 const char*
2579 dbus_message_get_destination (DBusMessage *message)
2580 {
2581   const char *v;
2582
2583   _dbus_return_val_if_fail (message != NULL, NULL);
2584
2585   v = NULL; /* in case field doesn't exist */
2586   _dbus_header_get_field_basic (&message->header,
2587                                 DBUS_HEADER_FIELD_DESTINATION,
2588                                 DBUS_TYPE_STRING,
2589                                 &v);
2590   return v;
2591 }
2592
2593 /**
2594  * Sets the message sender.
2595  *
2596  * @param message the message
2597  * @param sender the sender or #NULL to unset
2598  * @returns #FALSE if not enough memory
2599  */
2600 dbus_bool_t
2601 dbus_message_set_sender (DBusMessage  *message,
2602                          const char   *sender)
2603 {
2604   _dbus_return_val_if_fail (message != NULL, FALSE);
2605   _dbus_return_val_if_fail (!message->locked, FALSE);
2606   _dbus_return_val_if_fail (sender == NULL ||
2607                             _dbus_check_is_valid_service (sender),
2608                             FALSE);
2609
2610   return set_or_delete_string_field (message,
2611                                      DBUS_HEADER_FIELD_SENDER,
2612                                      DBUS_TYPE_STRING,
2613                                      sender);
2614 }
2615
2616 /**
2617  * Gets the service which originated this message,
2618  * or #NULL if unknown or inapplicable.
2619  *
2620  * @param message the message
2621  * @returns the service name or #NULL
2622  */
2623 const char*
2624 dbus_message_get_sender (DBusMessage *message)
2625 {
2626   const char *v;
2627
2628   _dbus_return_val_if_fail (message != NULL, NULL);
2629
2630   v = NULL; /* in case field doesn't exist */
2631   _dbus_header_get_field_basic (&message->header,
2632                                 DBUS_HEADER_FIELD_SENDER,
2633                                 DBUS_TYPE_STRING,
2634                                 &v);
2635   return v;
2636 }
2637
2638 /**
2639  * Gets the type signature of the message, i.e. the arguments in the
2640  * message payload. The signature includes only "in" arguments for
2641  * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
2642  * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
2643  * what you might expect (it does not include the signature of the
2644  * entire C++-style method).
2645  *
2646  * The signature is a string made up of type codes such as
2647  * #DBUS_TYPE_INT32. The string is terminated with nul (nul is also
2648  * the value of #DBUS_TYPE_INVALID).
2649  *
2650  * @param message the message
2651  * @returns the type signature
2652  */
2653 const char*
2654 dbus_message_get_signature (DBusMessage *message)
2655 {
2656   const DBusString *type_str;
2657   int type_pos;
2658
2659   _dbus_return_val_if_fail (message != NULL, NULL);
2660
2661   get_const_signature (&message->header, &type_str, &type_pos);
2662
2663   return _dbus_string_get_const_data_len (type_str, type_pos, 0);
2664 }
2665
2666 static dbus_bool_t
2667 _dbus_message_has_type_interface_member (DBusMessage *message,
2668                                          int          type,
2669                                          const char  *interface,
2670                                          const char  *member)
2671 {
2672   const char *n;
2673
2674   _dbus_assert (message != NULL);
2675   _dbus_assert (interface != NULL);
2676   _dbus_assert (member != NULL);
2677
2678   if (dbus_message_get_type (message) != type)
2679     return FALSE;
2680
2681   /* Optimize by checking the short member name first
2682    * instead of the longer interface name
2683    */
2684
2685   n = dbus_message_get_member (message);
2686
2687   if (n && strcmp (n, member) == 0)
2688     {
2689       n = dbus_message_get_interface (message);
2690
2691       if (n == NULL || strcmp (n, interface) == 0)
2692         return TRUE;
2693     }
2694
2695   return FALSE;
2696 }
2697
2698 /**
2699  * Checks whether the message is a method call with the given
2700  * interface and member fields.  If the message is not
2701  * #DBUS_MESSAGE_TYPE_METHOD_CALL, or has a different interface or
2702  * member field, returns #FALSE. If the interface field is missing,
2703  * then it will be assumed equal to the provided interface.  The D-BUS
2704  * protocol allows method callers to leave out the interface name.
2705  *
2706  * @param message the message
2707  * @param interface the name to check (must not be #NULL)
2708  * @param method the name to check (must not be #NULL)
2709  *
2710  * @returns #TRUE if the message is the specified method call
2711  */
2712 dbus_bool_t
2713 dbus_message_is_method_call (DBusMessage *message,
2714                              const char  *interface,
2715                              const char  *method)
2716 {
2717   _dbus_return_val_if_fail (message != NULL, FALSE);
2718   _dbus_return_val_if_fail (interface != NULL, FALSE);
2719   _dbus_return_val_if_fail (method != NULL, FALSE);
2720   /* don't check that interface/method are valid since it would be
2721    * expensive, and not catch many common errors
2722    */
2723
2724   return _dbus_message_has_type_interface_member (message,
2725                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
2726                                                   interface, method);
2727 }
2728
2729 /**
2730  * Checks whether the message is a signal with the given interface and
2731  * member fields.  If the message is not #DBUS_MESSAGE_TYPE_SIGNAL, or
2732  * has a different interface or member field, returns #FALSE.  If the
2733  * interface field in the message is missing, it is assumed to match
2734  * any interface you pass in to this function.
2735  *
2736  * @param message the message
2737  * @param interface the name to check (must not be #NULL)
2738  * @param signal_name the name to check (must not be #NULL)
2739  *
2740  * @returns #TRUE if the message is the specified signal
2741  */
2742 dbus_bool_t
2743 dbus_message_is_signal (DBusMessage *message,
2744                         const char  *interface,
2745                         const char  *signal_name)
2746 {
2747   _dbus_return_val_if_fail (message != NULL, FALSE);
2748   _dbus_return_val_if_fail (interface != NULL, FALSE);
2749   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
2750   /* don't check that interface/name are valid since it would be
2751    * expensive, and not catch many common errors
2752    */
2753
2754   return _dbus_message_has_type_interface_member (message,
2755                                                   DBUS_MESSAGE_TYPE_SIGNAL,
2756                                                   interface, signal_name);
2757 }
2758
2759 /**
2760  * Checks whether the message is an error reply with the given error
2761  * name.  If the message is not #DBUS_MESSAGE_TYPE_ERROR, or has a
2762  * different name, returns #FALSE.
2763  *
2764  * @param message the message
2765  * @param error_name the name to check (must not be #NULL)
2766  *
2767  * @returns #TRUE if the message is the specified error
2768  */
2769 dbus_bool_t
2770 dbus_message_is_error (DBusMessage *message,
2771                        const char  *error_name)
2772 {
2773   const char *n;
2774
2775   _dbus_return_val_if_fail (message != NULL, FALSE);
2776   _dbus_return_val_if_fail (error_name != NULL, FALSE);
2777   /* don't check that error_name is valid since it would be expensive,
2778    * and not catch many common errors
2779    */
2780
2781   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
2782     return FALSE;
2783
2784   n = dbus_message_get_error_name (message);
2785
2786   if (n && strcmp (n, error_name) == 0)
2787     return TRUE;
2788   else
2789     return FALSE;
2790 }
2791
2792 /**
2793  * Checks whether the message was sent to the given service.  If the
2794  * message has no service specified or has a different name, returns
2795  * #FALSE.
2796  *
2797  * @param message the message
2798  * @param service the service to check (must not be #NULL)
2799  *
2800  * @returns #TRUE if the message has the given destination service
2801  */
2802 dbus_bool_t
2803 dbus_message_has_destination (DBusMessage  *message,
2804                               const char   *service)
2805 {
2806   const char *s;
2807
2808   _dbus_return_val_if_fail (message != NULL, FALSE);
2809   _dbus_return_val_if_fail (service != NULL, FALSE);
2810   /* don't check that service name is valid since it would be expensive,
2811    * and not catch many common errors
2812    */
2813
2814   s = dbus_message_get_destination (message);
2815
2816   if (s && strcmp (s, service) == 0)
2817     return TRUE;
2818   else
2819     return FALSE;
2820 }
2821
2822 /**
2823  * Checks whether the message has the given service as its sender.  If
2824  * the message has no sender specified or has a different sender,
2825  * returns #FALSE. Note that if a peer application owns multiple
2826  * services, its messages will have only one of those services as the
2827  * sender (usually the base service). So you can't use this
2828  * function to prove the sender didn't own service Foo, you can
2829  * only use it to prove that it did.
2830  *
2831  * @todo this function is probably useless unless we make a hard guarantee
2832  * that the sender field in messages will always be the base service name
2833  *
2834  * @param message the message
2835  * @param service the service to check (must not be #NULL)
2836  *
2837  * @returns #TRUE if the message has the given origin service
2838  */
2839 dbus_bool_t
2840 dbus_message_has_sender (DBusMessage  *message,
2841                          const char   *service)
2842 {
2843   const char *s;
2844
2845   _dbus_return_val_if_fail (message != NULL, FALSE);
2846   _dbus_return_val_if_fail (service != NULL, FALSE);
2847   /* don't check that service name is valid since it would be expensive,
2848    * and not catch many common errors
2849    */
2850
2851   s = dbus_message_get_sender (message);
2852
2853   if (s && strcmp (s, service) == 0)
2854     return TRUE;
2855   else
2856     return FALSE;
2857 }
2858
2859 /**
2860  * Checks whether the message has the given signature; see
2861  * dbus_message_get_signature() for more details on what the signature
2862  * looks like.
2863  *
2864  * @param message the message
2865  * @param signature typecode array
2866  * @returns #TRUE if message has the given signature
2867 */
2868 dbus_bool_t
2869 dbus_message_has_signature (DBusMessage   *message,
2870                             const char    *signature)
2871 {
2872   const char *s;
2873
2874   _dbus_return_val_if_fail (message != NULL, FALSE);
2875   _dbus_return_val_if_fail (signature != NULL, FALSE);
2876   /* don't check that signature is valid since it would be expensive,
2877    * and not catch many common errors
2878    */
2879
2880   s = dbus_message_get_signature (message);
2881
2882   if (s && strcmp (s, signature) == 0)
2883     return TRUE;
2884   else
2885     return FALSE;
2886 }
2887
2888 /**
2889  * Sets a #DBusError based on the contents of the given
2890  * message. The error is only set if the message
2891  * is an error message, as in DBUS_MESSAGE_TYPE_ERROR.
2892  * The name of the error is set to the name of the message,
2893  * and the error message is set to the first argument
2894  * if the argument exists and is a string.
2895  *
2896  * The return value indicates whether the error was set (the error is
2897  * set if and only if the message is an error message).  So you can
2898  * check for an error reply and convert it to DBusError in one go:
2899  * @code
2900  *  if (dbus_set_error_from_message (error, reply))
2901  *    return error;
2902  *  else
2903  *    process reply;
2904  * @endcode
2905  *
2906  * @param error the error to set
2907  * @param message the message to set it from
2908  * @returns #TRUE if dbus_message_get_is_error() returns #TRUE for the message
2909  */
2910 dbus_bool_t
2911 dbus_set_error_from_message (DBusError   *error,
2912                              DBusMessage *message)
2913 {
2914   const char *str;
2915
2916   _dbus_return_val_if_fail (message != NULL, FALSE);
2917   _dbus_return_val_if_error_is_set (error, FALSE);
2918
2919   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
2920     return FALSE;
2921
2922   str = NULL;
2923   dbus_message_get_args (message, NULL,
2924                          DBUS_TYPE_STRING, &str,
2925                          DBUS_TYPE_INVALID);
2926
2927   dbus_set_error (error, dbus_message_get_error_name (message),
2928                   str ? "%s" : NULL, str);
2929
2930   return TRUE;
2931 }
2932
2933 /** @} */
2934
2935 /**
2936  * @addtogroup DBusMessageInternals
2937  *
2938  * @{
2939  */
2940 /**
2941  * @typedef DBusMessageLoader
2942  *
2943  * The DBusMessageLoader object encapsulates the process of converting
2944  * a byte stream into a series of DBusMessage. It buffers the incoming
2945  * bytes as efficiently as possible, and generates a queue of
2946  * messages. DBusMessageLoader is typically used as part of a
2947  * DBusTransport implementation. The DBusTransport then hands off
2948  * the loaded messages to a DBusConnection, making the messages
2949  * visible to the application.
2950  *
2951  * @todo write tests for break-loader that a) randomly delete header
2952  * fields and b) set string fields to zero-length and other funky
2953  * values.
2954  *
2955  */
2956
2957 /**
2958  * Implementation details of DBusMessageLoader.
2959  * All members are private.
2960  */
2961 struct DBusMessageLoader
2962 {
2963   int refcount;        /**< Reference count. */
2964
2965   DBusString data;     /**< Buffered data */
2966
2967   DBusList *messages;  /**< Complete messages. */
2968
2969   long max_message_size; /**< Maximum size of a message */
2970
2971   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
2972
2973   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
2974 };
2975
2976 /**
2977  * The initial buffer size of the message loader.
2978  *
2979  * @todo this should be based on min header size plus some average
2980  * body size, or something. Or rather, the min header size only, if we
2981  * want to try to read only the header, store that in a DBusMessage,
2982  * then read only the body and store that, etc., depends on
2983  * how we optimize _dbus_message_loader_get_buffer() and what
2984  * the exact message format is.
2985  */
2986 #define INITIAL_LOADER_DATA_LEN 32
2987
2988 /**
2989  * Creates a new message loader. Returns #NULL if memory can't
2990  * be allocated.
2991  *
2992  * @returns new loader, or #NULL.
2993  */
2994 DBusMessageLoader*
2995 _dbus_message_loader_new (void)
2996 {
2997   DBusMessageLoader *loader;
2998
2999   loader = dbus_new0 (DBusMessageLoader, 1);
3000   if (loader == NULL)
3001     return NULL;
3002
3003   loader->refcount = 1;
3004
3005   /* Try to cap message size at something that won't *totally* hose
3006    * the system if we have a couple of them.
3007    */
3008   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
3009
3010   if (!_dbus_string_init (&loader->data))
3011     {
3012       dbus_free (loader);
3013       return NULL;
3014     }
3015
3016   /* preallocate the buffer for speed, ignore failure */
3017   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
3018   _dbus_string_set_length (&loader->data, 0);
3019
3020   return loader;
3021 }
3022
3023 /**
3024  * Increments the reference count of the loader.
3025  *
3026  * @param loader the loader.
3027  * @returns the loader
3028  */
3029 DBusMessageLoader *
3030 _dbus_message_loader_ref (DBusMessageLoader *loader)
3031 {
3032   loader->refcount += 1;
3033
3034   return loader;
3035 }
3036
3037 /**
3038  * Decrements the reference count of the loader and finalizes the
3039  * loader when the count reaches zero.
3040  *
3041  * @param loader the loader.
3042  */
3043 void
3044 _dbus_message_loader_unref (DBusMessageLoader *loader)
3045 {
3046   loader->refcount -= 1;
3047   if (loader->refcount == 0)
3048     {
3049       _dbus_list_foreach (&loader->messages,
3050                           (DBusForeachFunction) dbus_message_unref,
3051                           NULL);
3052       _dbus_list_clear (&loader->messages);
3053       _dbus_string_free (&loader->data);
3054       dbus_free (loader);
3055     }
3056 }
3057
3058 /**
3059  * Gets the buffer to use for reading data from the network.  Network
3060  * data is read directly into an allocated buffer, which is then used
3061  * in the DBusMessage, to avoid as many extra memcpy's as possible.
3062  * The buffer must always be returned immediately using
3063  * _dbus_message_loader_return_buffer(), even if no bytes are
3064  * successfully read.
3065  *
3066  * @todo this function can be a lot more clever. For example
3067  * it can probably always return a buffer size to read exactly
3068  * the body of the next message, thus avoiding any memory wastage
3069  * or reallocs.
3070  *
3071  * @todo we need to enforce a max length on strings in header fields.
3072  *
3073  * @param loader the message loader.
3074  * @param buffer the buffer
3075  */
3076 void
3077 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
3078                                  DBusString        **buffer)
3079 {
3080   _dbus_assert (!loader->buffer_outstanding);
3081
3082   *buffer = &loader->data;
3083
3084   loader->buffer_outstanding = TRUE;
3085 }
3086
3087 /**
3088  * The smallest header size that can occur.  (It won't be valid due to
3089  * missing required header fields.) This is 4 bytes, two uint32, an
3090  * array length.
3091  */
3092 #define DBUS_MINIMUM_HEADER_SIZE 16
3093
3094 /**
3095  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
3096  * indicating to the loader how many bytes of the buffer were filled
3097  * in. This function must always be called, even if no bytes were
3098  * successfully read.
3099  *
3100  * @param loader the loader.
3101  * @param buffer the buffer.
3102  * @param bytes_read number of bytes that were read into the buffer.
3103  */
3104 void
3105 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
3106                                     DBusString         *buffer,
3107                                     int                 bytes_read)
3108 {
3109   _dbus_assert (loader->buffer_outstanding);
3110   _dbus_assert (buffer == &loader->data);
3111
3112   loader->buffer_outstanding = FALSE;
3113 }
3114
3115 /*
3116  * FIXME when we move the header out of the buffer, that memmoves all
3117  * buffered messages. Kind of crappy.
3118  *
3119  * Also we copy the header and body, which is kind of crappy.  To
3120  * avoid this, we have to allow header and body to be in a single
3121  * memory block, which is good for messages we read and bad for
3122  * messages we are creating. But we could move_len() the buffer into
3123  * this single memory block, and move_len() will just swap the buffers
3124  * if you're moving the entire buffer replacing the dest string.
3125  *
3126  * We could also have the message loader tell the transport how many
3127  * bytes to read; so it would first ask for some arbitrary number like
3128  * 256, then if the message was incomplete it would use the
3129  * header/body len to ask for exactly the size of the message (or
3130  * blocks the size of a typical kernel buffer for the socket). That
3131  * way we don't get trailing bytes in the buffer that have to be
3132  * memmoved. Though I suppose we also don't have a chance of reading a
3133  * bunch of small messages at once, so the optimization may be stupid.
3134  *
3135  * Another approach would be to keep a "start" index into
3136  * loader->data and only delete it occasionally, instead of after
3137  * each message is loaded.
3138  *
3139  * load_message() returns FALSE if not enough memory
3140  */
3141 static dbus_bool_t
3142 load_message (DBusMessageLoader *loader,
3143               DBusMessage       *message,
3144               int                byte_order,
3145               int                fields_array_len,
3146               int                header_len,
3147               int                body_len)
3148 {
3149   dbus_bool_t oom;
3150   DBusValidity validity;
3151   const DBusString *type_str;
3152   int type_pos;
3153
3154   oom = FALSE;
3155
3156 #if 0
3157   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
3158 #endif
3159
3160   /* 1. VALIDATE AND COPY OVER HEADER */
3161   _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
3162   _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
3163
3164   if (!_dbus_header_load_untrusted (&message->header,
3165                                     &validity,
3166                                     byte_order,
3167                                     fields_array_len,
3168                                     header_len,
3169                                     body_len,
3170                                     &loader->data, 0,
3171                                     _dbus_string_get_length (&loader->data)))
3172     {
3173       _dbus_verbose ("Failed to load header for new message code %d\n", validity);
3174       if (validity == DBUS_VALID)
3175         oom = TRUE;
3176       goto failed;
3177     }
3178
3179   _dbus_assert (validity == DBUS_VALID);
3180
3181   message->byte_order = byte_order;
3182
3183   /* 2. VALIDATE BODY */
3184
3185   get_const_signature (&message->header, &type_str, &type_pos);
3186
3187   /* Because the bytes_remaining arg is NULL, this validates that the
3188    * body is the right length
3189    */
3190   validity = _dbus_validate_body_with_reason (type_str,
3191                                               type_pos,
3192                                               byte_order,
3193                                               NULL,
3194                                               &loader->data,
3195                                               header_len,
3196                                               body_len);
3197   if (validity != DBUS_VALID)
3198     {
3199       _dbus_verbose ("Failed to validate message body code %d\n", validity);
3200       goto failed;
3201     }
3202
3203   /* 3. COPY OVER BODY AND QUEUE MESSAGE */
3204
3205   if (!_dbus_list_append (&loader->messages, message))
3206     {
3207       _dbus_verbose ("Failed to append new message to loader queue\n");
3208       oom = TRUE;
3209       goto failed;
3210     }
3211
3212   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
3213   _dbus_assert (_dbus_string_get_length (&loader->data) >=
3214                 (header_len + body_len));
3215
3216   if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
3217     {
3218       _dbus_verbose ("Failed to move body into new message\n");
3219       oom = TRUE;
3220       goto failed;
3221     }
3222
3223   _dbus_string_delete (&loader->data, 0, header_len + body_len);
3224
3225   _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
3226   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
3227
3228   _dbus_verbose ("Loaded message %p\n", message);
3229
3230   _dbus_assert (!oom);
3231   _dbus_assert (!loader->corrupted);
3232
3233   return TRUE;
3234
3235  failed:
3236
3237   /* Clean up */
3238
3239   /* does nothing if the message isn't in the list */
3240   _dbus_list_remove_last (&loader->messages, message);
3241
3242   if (!oom)
3243     loader->corrupted = TRUE;
3244
3245   _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
3246
3247   return !oom;
3248 }
3249
3250 /**
3251  * Converts buffered data into messages, if we have enough data.  If
3252  * we don't have enough data, does nothing.
3253  *
3254  * @todo we need to check that the proper named header fields exist
3255  * for each message type.
3256  *
3257  * @todo If a message has unknown type, we should probably eat it
3258  * right here rather than passing it out to applications.  However
3259  * it's not an error to see messages of unknown type.
3260  *
3261  * @param loader the loader.
3262  * @returns #TRUE if we had enough memory to finish.
3263  */
3264 dbus_bool_t
3265 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
3266 {
3267   while (!loader->corrupted &&
3268          _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
3269     {
3270       DBusValidity validity;
3271       int byte_order, fields_array_len, header_len, body_len;
3272
3273       if (_dbus_header_have_message_untrusted (loader->max_message_size,
3274                                                &validity,
3275                                                &byte_order,
3276                                                &fields_array_len,
3277                                                &header_len,
3278                                                &body_len,
3279                                                &loader->data, 0,
3280                                                _dbus_string_get_length (&loader->data)))
3281         {
3282           DBusMessage *message;
3283
3284           _dbus_assert (validity == DBUS_VALID);
3285
3286           message = dbus_message_new_empty_header ();
3287           if (message == NULL)
3288             return FALSE;
3289
3290           if (!load_message (loader, message,
3291                              byte_order, fields_array_len,
3292                              header_len, body_len))
3293             {
3294               dbus_message_unref (message);
3295               return FALSE;
3296             }
3297         }
3298       else
3299         {
3300           _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
3301                          validity);
3302           if (validity != DBUS_VALID)
3303             loader->corrupted = TRUE;
3304           return TRUE;
3305         }
3306     }
3307
3308   return TRUE;
3309 }
3310
3311 /**
3312  * Peeks at first loaded message, returns #NULL if no messages have
3313  * been queued.
3314  *
3315  * @param loader the loader.
3316  * @returns the next message, or #NULL if none.
3317  */
3318 DBusMessage*
3319 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
3320 {
3321   if (loader->messages)
3322     return loader->messages->data;
3323   else
3324     return NULL;
3325 }
3326
3327 /**
3328  * Pops a loaded message (passing ownership of the message
3329  * to the caller). Returns #NULL if no messages have been
3330  * queued.
3331  *
3332  * @param loader the loader.
3333  * @returns the next message, or #NULL if none.
3334  */
3335 DBusMessage*
3336 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
3337 {
3338   return _dbus_list_pop_first (&loader->messages);
3339 }
3340
3341 /**
3342  * Pops a loaded message inside a list link (passing ownership of the
3343  * message and link to the caller). Returns #NULL if no messages have
3344  * been loaded.
3345  *
3346  * @param loader the loader.
3347  * @returns the next message link, or #NULL if none.
3348  */
3349 DBusList*
3350 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
3351 {
3352   return _dbus_list_pop_first_link (&loader->messages);
3353 }
3354
3355 /**
3356  * Returns a popped message link, used to undo a pop.
3357  *
3358  * @param loader the loader
3359  * @param link the link with a message in it
3360  */
3361 void
3362 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
3363                                            DBusList           *link)
3364 {
3365   _dbus_list_prepend_link (&loader->messages, link);
3366 }
3367
3368 /**
3369  * Checks whether the loader is confused due to bad data.
3370  * If messages are received that are invalid, the
3371  * loader gets confused and gives up permanently.
3372  * This state is called "corrupted."
3373  *
3374  * @param loader the loader
3375  * @returns #TRUE if the loader is hosed.
3376  */
3377 dbus_bool_t
3378 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
3379 {
3380   return loader->corrupted;
3381 }
3382
3383 /**
3384  * Sets the maximum size message we allow.
3385  *
3386  * @param loader the loader
3387  * @param size the max message size in bytes
3388  */
3389 void
3390 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
3391                                            long                size)
3392 {
3393   if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
3394     {
3395       _dbus_verbose ("clamping requested max message size %ld to %d\n",
3396                      size, DBUS_MAXIMUM_MESSAGE_LENGTH);
3397       size = DBUS_MAXIMUM_MESSAGE_LENGTH;
3398     }
3399   loader->max_message_size = size;
3400 }
3401
3402 /**
3403  * Gets the maximum allowed message size in bytes.
3404  *
3405  * @param loader the loader
3406  * @returns max size in bytes
3407  */
3408 long
3409 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
3410 {
3411   return loader->max_message_size;
3412 }
3413
3414 static DBusDataSlotAllocator slot_allocator;
3415 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
3416
3417 /**
3418  * Allocates an integer ID to be used for storing application-specific
3419  * data on any DBusMessage. The allocated ID may then be used
3420  * with dbus_message_set_data() and dbus_message_get_data().
3421  * The passed-in slot must be initialized to -1, and is filled in
3422  * with the slot ID. If the passed-in slot is not -1, it's assumed
3423  * to be already allocated, and its refcount is incremented.
3424  *
3425  * The allocated slot is global, i.e. all DBusMessage objects will
3426  * have a slot with the given integer ID reserved.
3427  *
3428  * @param slot_p address of a global variable storing the slot
3429  * @returns #FALSE on failure (no memory)
3430  */
3431 dbus_bool_t
3432 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
3433 {
3434   return _dbus_data_slot_allocator_alloc (&slot_allocator,
3435                                           _DBUS_LOCK_NAME (message_slots),
3436                                           slot_p);
3437 }
3438
3439 /**
3440  * Deallocates a global ID for message data slots.
3441  * dbus_message_get_data() and dbus_message_set_data() may no
3442  * longer be used with this slot.  Existing data stored on existing
3443  * DBusMessage objects will be freed when the message is
3444  * finalized, but may not be retrieved (and may only be replaced if
3445  * someone else reallocates the slot).  When the refcount on the
3446  * passed-in slot reaches 0, it is set to -1.
3447  *
3448  * @param slot_p address storing the slot to deallocate
3449  */
3450 void
3451 dbus_message_free_data_slot (dbus_int32_t *slot_p)
3452 {
3453   _dbus_return_if_fail (*slot_p >= 0);
3454
3455   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
3456 }
3457
3458 /**
3459  * Stores a pointer on a DBusMessage, along
3460  * with an optional function to be used for freeing
3461  * the data when the data is set again, or when
3462  * the message is finalized. The slot number
3463  * must have been allocated with dbus_message_allocate_data_slot().
3464  *
3465  * @param message the message
3466  * @param slot the slot number
3467  * @param data the data to store
3468  * @param free_data_func finalizer function for the data
3469  * @returns #TRUE if there was enough memory to store the data
3470  */
3471 dbus_bool_t
3472 dbus_message_set_data (DBusMessage     *message,
3473                        dbus_int32_t     slot,
3474                        void            *data,
3475                        DBusFreeFunction free_data_func)
3476 {
3477   DBusFreeFunction old_free_func;
3478   void *old_data;
3479   dbus_bool_t retval;
3480
3481   _dbus_return_val_if_fail (message != NULL, FALSE);
3482   _dbus_return_val_if_fail (slot >= 0, FALSE);
3483
3484   retval = _dbus_data_slot_list_set (&slot_allocator,
3485                                      &message->slot_list,
3486                                      slot, data, free_data_func,
3487                                      &old_free_func, &old_data);
3488
3489   if (retval)
3490     {
3491       /* Do the actual free outside the message lock */
3492       if (old_free_func)
3493         (* old_free_func) (old_data);
3494     }
3495
3496   return retval;
3497 }
3498
3499 /**
3500  * Retrieves data previously set with dbus_message_set_data().
3501  * The slot must still be allocated (must not have been freed).
3502  *
3503  * @param message the message
3504  * @param slot the slot to get data from
3505  * @returns the data, or #NULL if not found
3506  */
3507 void*
3508 dbus_message_get_data (DBusMessage   *message,
3509                        dbus_int32_t   slot)
3510 {
3511   void *res;
3512
3513   _dbus_return_val_if_fail (message != NULL, NULL);
3514
3515   res = _dbus_data_slot_list_get (&slot_allocator,
3516                                   &message->slot_list,
3517                                   slot);
3518
3519   return res;
3520 }
3521
3522 /**
3523  * Utility function to convert a machine-readable (not translated)
3524  * string into a D-BUS message type.
3525  *
3526  * @code
3527  *   "method_call"    -> DBUS_MESSAGE_TYPE_METHOD_CALL
3528  *   "method_return"  -> DBUS_MESSAGE_TYPE_METHOD_RETURN
3529  *   "signal"         -> DBUS_MESSAGE_TYPE_SIGNAL
3530  *   "error"          -> DBUS_MESSAGE_TYPE_ERROR
3531  *   anything else    -> DBUS_MESSAGE_TYPE_INVALID
3532  * @endcode
3533  *
3534  */
3535 int
3536 dbus_message_type_from_string (const char *type_str)
3537 {
3538   if (strcmp (type_str, "method_call") == 0)
3539     return DBUS_MESSAGE_TYPE_METHOD_CALL;
3540   if (strcmp (type_str, "method_return") == 0)
3541     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
3542   else if (strcmp (type_str, "signal") == 0)
3543     return DBUS_MESSAGE_TYPE_SIGNAL;
3544   else if (strcmp (type_str, "error") == 0)
3545     return DBUS_MESSAGE_TYPE_ERROR;
3546   else
3547     return DBUS_MESSAGE_TYPE_INVALID;
3548 }
3549
3550 /**
3551  * Utility function to convert a D-BUS message type into a
3552  * machine-readable string (not translated).
3553  *
3554  * @code
3555  *   DBUS_MESSAGE_TYPE_METHOD_CALL    -> "method_call"
3556  *   DBUS_MESSAGE_TYPE_METHOD_RETURN  -> "method_return"
3557  *   DBUS_MESSAGE_TYPE_SIGNAL         -> "signal"
3558  *   DBUS_MESSAGE_TYPE_ERROR          -> "error"
3559  *   DBUS_MESSAGE_TYPE_INVALID        -> "invalid"
3560  * @endcode
3561  *
3562  */
3563 const char *
3564 dbus_message_type_to_string (int type)
3565 {
3566   switch (type)
3567     {
3568     case DBUS_MESSAGE_TYPE_METHOD_CALL:
3569       return "method_call";
3570     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
3571       return "method_return";
3572     case DBUS_MESSAGE_TYPE_SIGNAL:
3573       return "signal";
3574     case DBUS_MESSAGE_TYPE_ERROR:
3575       return "error";
3576     default:
3577       return "invalid";
3578     }
3579 }
3580
3581 /** @} */
3582 #ifdef DBUS_BUILD_TESTS
3583 #include "dbus-test.h"
3584 #include <stdio.h>
3585 #include <stdlib.h>
3586
3587 static dbus_bool_t
3588 check_have_valid_message (DBusMessageLoader *loader)
3589 {
3590   DBusMessage *message;
3591   dbus_bool_t retval;
3592
3593   message = NULL;
3594   retval = FALSE;
3595
3596   if (!_dbus_message_loader_queue_messages (loader))
3597     _dbus_assert_not_reached ("no memory to queue messages");
3598
3599   if (_dbus_message_loader_get_is_corrupted (loader))
3600     {
3601       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
3602       goto failed;
3603     }
3604
3605   message = _dbus_message_loader_pop_message (loader);
3606   if (message == NULL)
3607     {
3608       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
3609       goto failed;
3610     }
3611
3612   if (_dbus_string_get_length (&loader->data) > 0)
3613     {
3614       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
3615       goto failed;
3616     }
3617
3618 #if 0
3619   /* FIXME */
3620   /* Verify that we're able to properly deal with the message.
3621    * For example, this would detect improper handling of messages
3622    * in nonstandard byte order.
3623    */
3624   if (!check_message_handling (message))
3625     goto failed;
3626 #endif
3627
3628   retval = TRUE;
3629
3630  failed:
3631   if (message)
3632     dbus_message_unref (message);
3633
3634   return retval;
3635 }
3636
3637 static dbus_bool_t
3638 check_invalid_message (DBusMessageLoader *loader)
3639 {
3640   dbus_bool_t retval;
3641
3642   retval = FALSE;
3643
3644   if (!_dbus_message_loader_queue_messages (loader))
3645     _dbus_assert_not_reached ("no memory to queue messages");
3646
3647   if (!_dbus_message_loader_get_is_corrupted (loader))
3648     {
3649       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
3650       goto failed;
3651     }
3652
3653   retval = TRUE;
3654
3655  failed:
3656   return retval;
3657 }
3658
3659 static dbus_bool_t
3660 check_incomplete_message (DBusMessageLoader *loader)
3661 {
3662   DBusMessage *message;
3663   dbus_bool_t retval;
3664
3665   message = NULL;
3666   retval = FALSE;
3667
3668   if (!_dbus_message_loader_queue_messages (loader))
3669     _dbus_assert_not_reached ("no memory to queue messages");
3670
3671   if (_dbus_message_loader_get_is_corrupted (loader))
3672     {
3673       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
3674       goto failed;
3675     }
3676
3677   message = _dbus_message_loader_pop_message (loader);
3678   if (message != NULL)
3679     {
3680       _dbus_warn ("loaded message that was expected to be incomplete\n");
3681       goto failed;
3682     }
3683
3684   retval = TRUE;
3685
3686  failed:
3687   if (message)
3688     dbus_message_unref (message);
3689   return retval;
3690 }
3691
3692 static dbus_bool_t
3693 check_loader_results (DBusMessageLoader      *loader,
3694                       DBusMessageValidity     validity)
3695 {
3696   if (!_dbus_message_loader_queue_messages (loader))
3697     _dbus_assert_not_reached ("no memory to queue messages");
3698
3699   switch (validity)
3700     {
3701     case _DBUS_MESSAGE_VALID:
3702       return check_have_valid_message (loader);
3703     case _DBUS_MESSAGE_INVALID:
3704       return check_invalid_message (loader);
3705     case _DBUS_MESSAGE_INCOMPLETE:
3706       return check_incomplete_message (loader);
3707     case _DBUS_MESSAGE_UNKNOWN:
3708       return TRUE;
3709     }
3710
3711   _dbus_assert_not_reached ("bad DBusMessageValidity");
3712   return FALSE;
3713 }
3714
3715
3716 /**
3717  * Loads the message in the given message file.
3718  *
3719  * @param filename filename to load
3720  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
3721  * @param data string to load message into
3722  * @returns #TRUE if the message was loaded
3723  */
3724 dbus_bool_t
3725 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
3726                                             dbus_bool_t          is_raw,
3727                                             DBusString          *data)
3728 {
3729   dbus_bool_t retval;
3730
3731   retval = FALSE;
3732
3733   if (is_raw)
3734     {
3735       DBusError error;
3736
3737       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
3738       dbus_error_init (&error);
3739       if (!_dbus_file_get_contents (data, filename, &error))
3740         {
3741           _dbus_warn ("Could not load message file %s: %s\n",
3742                       _dbus_string_get_const_data (filename),
3743                       error.message);
3744           dbus_error_free (&error);
3745           goto failed;
3746         }
3747     }
3748   else
3749     {
3750       if (FALSE) /* Message builder disabled, probably permanently,
3751                   * I want to do it another way
3752                   */
3753         {
3754           _dbus_warn ("Could not load message file %s\n",
3755                       _dbus_string_get_const_data (filename));
3756           goto failed;
3757         }
3758     }
3759
3760   retval = TRUE;
3761
3762  failed:
3763
3764   return retval;
3765 }
3766
3767 /**
3768  * Tries loading the message in the given message file
3769  * and verifies that DBusMessageLoader can handle it.
3770  *
3771  * @param filename filename to load
3772  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
3773  * @param expected_validity what the message has to be like to return #TRUE
3774  * @returns #TRUE if the message has the expected validity
3775  */
3776 dbus_bool_t
3777 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
3778                                            dbus_bool_t          is_raw,
3779                                            DBusMessageValidity  expected_validity)
3780 {
3781   DBusString data;
3782   dbus_bool_t retval;
3783
3784   retval = FALSE;
3785
3786   if (!_dbus_string_init (&data))
3787     _dbus_assert_not_reached ("could not allocate string\n");
3788
3789   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
3790                                                    &data))
3791     goto failed;
3792
3793   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
3794
3795  failed:
3796
3797   if (!retval)
3798     {
3799       if (_dbus_string_get_length (&data) > 0)
3800         _dbus_verbose_bytes_of_string (&data, 0,
3801                                        _dbus_string_get_length (&data));
3802
3803       _dbus_warn ("Failed message loader test on %s\n",
3804                   _dbus_string_get_const_data (filename));
3805     }
3806
3807   _dbus_string_free (&data);
3808
3809   return retval;
3810 }
3811
3812 /**
3813  * Tries loading the given message data.
3814  *
3815  *
3816  * @param data the message data
3817  * @param expected_validity what the message has to be like to return #TRUE
3818  * @returns #TRUE if the message has the expected validity
3819  */
3820 dbus_bool_t
3821 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
3822                                            DBusMessageValidity  expected_validity)
3823 {
3824   DBusMessageLoader *loader;
3825   dbus_bool_t retval;
3826   int len;
3827   int i;
3828
3829   loader = NULL;
3830   retval = FALSE;
3831
3832   /* Write the data one byte at a time */
3833
3834   loader = _dbus_message_loader_new ();
3835
3836   /* check some trivial loader functions */
3837   _dbus_message_loader_ref (loader);
3838   _dbus_message_loader_unref (loader);
3839   _dbus_message_loader_get_max_message_size (loader);
3840
3841   len = _dbus_string_get_length (data);
3842   for (i = 0; i < len; i++)
3843     {
3844       DBusString *buffer;
3845
3846       _dbus_message_loader_get_buffer (loader, &buffer);
3847       _dbus_string_append_byte (buffer,
3848                                 _dbus_string_get_byte (data, i));
3849       _dbus_message_loader_return_buffer (loader, buffer, 1);
3850     }
3851
3852   if (!check_loader_results (loader, expected_validity))
3853     goto failed;
3854
3855   _dbus_message_loader_unref (loader);
3856   loader = NULL;
3857
3858   /* Write the data all at once */
3859
3860   loader = _dbus_message_loader_new ();
3861
3862   {
3863     DBusString *buffer;
3864
3865     _dbus_message_loader_get_buffer (loader, &buffer);
3866     _dbus_string_copy (data, 0, buffer,
3867                        _dbus_string_get_length (buffer));
3868     _dbus_message_loader_return_buffer (loader, buffer, 1);
3869   }
3870
3871   if (!check_loader_results (loader, expected_validity))
3872     goto failed;
3873
3874   _dbus_message_loader_unref (loader);
3875   loader = NULL;
3876
3877   /* Write the data 2 bytes at a time */
3878
3879   loader = _dbus_message_loader_new ();
3880
3881   len = _dbus_string_get_length (data);
3882   for (i = 0; i < len; i += 2)
3883     {
3884       DBusString *buffer;
3885
3886       _dbus_message_loader_get_buffer (loader, &buffer);
3887       _dbus_string_append_byte (buffer,
3888                                 _dbus_string_get_byte (data, i));
3889       if ((i+1) < len)
3890         _dbus_string_append_byte (buffer,
3891                                   _dbus_string_get_byte (data, i+1));
3892       _dbus_message_loader_return_buffer (loader, buffer, 1);
3893     }
3894
3895   if (!check_loader_results (loader, expected_validity))
3896     goto failed;
3897
3898   _dbus_message_loader_unref (loader);
3899   loader = NULL;
3900
3901   retval = TRUE;
3902
3903  failed:
3904
3905   if (loader)
3906     _dbus_message_loader_unref (loader);
3907
3908   return retval;
3909 }
3910
3911 static dbus_bool_t
3912 process_test_subdir (const DBusString          *test_base_dir,
3913                      const char                *subdir,
3914                      DBusMessageValidity        validity,
3915                      DBusForeachMessageFileFunc function,
3916                      void                      *user_data)
3917 {
3918   DBusString test_directory;
3919   DBusString filename;
3920   DBusDirIter *dir;
3921   dbus_bool_t retval;
3922   DBusError error;
3923
3924   retval = FALSE;
3925   dir = NULL;
3926
3927   if (!_dbus_string_init (&test_directory))
3928     _dbus_assert_not_reached ("didn't allocate test_directory\n");
3929
3930   _dbus_string_init_const (&filename, subdir);
3931
3932   if (!_dbus_string_copy (test_base_dir, 0,
3933                           &test_directory, 0))
3934     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
3935
3936   if (!_dbus_concat_dir_and_file (&test_directory, &filename))
3937     _dbus_assert_not_reached ("couldn't allocate full path");
3938
3939   _dbus_string_free (&filename);
3940   if (!_dbus_string_init (&filename))
3941     _dbus_assert_not_reached ("didn't allocate filename string\n");
3942
3943   dbus_error_init (&error);
3944   dir = _dbus_directory_open (&test_directory, &error);
3945   if (dir == NULL)
3946     {
3947       _dbus_warn ("Could not open %s: %s\n",
3948                   _dbus_string_get_const_data (&test_directory),
3949                   error.message);
3950       dbus_error_free (&error);
3951       goto failed;
3952     }
3953
3954   printf ("Testing %s:\n", subdir);
3955
3956  next:
3957   while (_dbus_directory_get_next_file (dir, &filename, &error))
3958     {
3959       DBusString full_path;
3960       dbus_bool_t is_raw;
3961
3962       if (!_dbus_string_init (&full_path))
3963         _dbus_assert_not_reached ("couldn't init string");
3964
3965       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
3966         _dbus_assert_not_reached ("couldn't copy dir to full_path");
3967
3968       if (!_dbus_concat_dir_and_file (&full_path, &filename))
3969         _dbus_assert_not_reached ("couldn't concat file to dir");
3970
3971       if (_dbus_string_ends_with_c_str (&filename, ".message"))
3972         is_raw = FALSE;
3973       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
3974         is_raw = TRUE;
3975       else
3976         {
3977           _dbus_verbose ("Skipping non-.message file %s\n",
3978                          _dbus_string_get_const_data (&filename));
3979           _dbus_string_free (&full_path);
3980           goto next;
3981         }
3982
3983       printf ("    %s\n",
3984               _dbus_string_get_const_data (&filename));
3985
3986       _dbus_verbose (" expecting %s for %s\n",
3987                      validity == _DBUS_MESSAGE_VALID ? "valid" :
3988                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
3989                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
3990                      _dbus_string_get_const_data (&filename));
3991
3992       if (! (*function) (&full_path, is_raw, validity, user_data))
3993         {
3994           _dbus_string_free (&full_path);
3995           goto failed;
3996         }
3997       else
3998         _dbus_string_free (&full_path);
3999     }
4000
4001   if (dbus_error_is_set (&error))
4002     {
4003       _dbus_warn ("Could not get next file in %s: %s\n",
4004                   _dbus_string_get_const_data (&test_directory),
4005                   error.message);
4006       dbus_error_free (&error);
4007       goto failed;
4008     }
4009
4010   retval = TRUE;
4011
4012  failed:
4013
4014   if (dir)
4015     _dbus_directory_close (dir);
4016   _dbus_string_free (&test_directory);
4017   _dbus_string_free (&filename);
4018
4019   return retval;
4020 }
4021
4022 /**
4023  * Runs the given function on every message file in the test suite.
4024  * The function should return #FALSE on test failure or fatal error.
4025  *
4026  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
4027  * @param func the function to run
4028  * @param user_data data for function
4029  * @returns #FALSE if there's a failure
4030  */
4031 dbus_bool_t
4032 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
4033                                                DBusForeachMessageFileFunc func,
4034                                                void                      *user_data)
4035 {
4036   DBusString test_directory;
4037   dbus_bool_t retval;
4038
4039   retval = FALSE;
4040
4041   _dbus_string_init_const (&test_directory, test_data_dir);
4042
4043   if (!process_test_subdir (&test_directory, "valid-messages",
4044                             _DBUS_MESSAGE_VALID, func, user_data))
4045     goto failed;
4046
4047   if (!process_test_subdir (&test_directory, "invalid-messages",
4048                             _DBUS_MESSAGE_INVALID, func, user_data))
4049     goto failed;
4050
4051   if (!process_test_subdir (&test_directory, "incomplete-messages",
4052                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
4053     goto failed;
4054
4055   retval = TRUE;
4056
4057  failed:
4058
4059   _dbus_string_free (&test_directory);
4060
4061   return retval;
4062 }
4063
4064 #define GET_AND_CHECK(iter, typename, literal)                                  \
4065   do {                                                                          \
4066     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename)         \
4067       _dbus_assert_not_reached ("got wrong argument type from message iter");   \
4068     dbus_message_iter_get_basic (&iter, &v_##typename);                         \
4069     if (v_##typename != literal)                                                \
4070       _dbus_assert_not_reached ("got wrong value from message iter");           \
4071   } while (0)
4072
4073 #define GET_AND_CHECK_STRCMP(iter, typename, literal)                           \
4074   do {                                                                          \
4075     if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_##typename)         \
4076       _dbus_assert_not_reached ("got wrong argument type from message iter");   \
4077     dbus_message_iter_get_basic (&iter, &v_##typename);                         \
4078     if (strcmp (v_##typename, literal) != 0)                                    \
4079       _dbus_assert_not_reached ("got wrong value from message iter");           \
4080   } while (0)
4081
4082 #define GET_AND_CHECK_AND_NEXT(iter, typename, literal)         \
4083   do {                                                          \
4084     GET_AND_CHECK(iter, typename, literal);                     \
4085     if (!dbus_message_iter_next (&iter))                        \
4086       _dbus_assert_not_reached ("failed to move iter to next"); \
4087   } while (0)
4088
4089 #define GET_AND_CHECK_STRCMP_AND_NEXT(iter, typename, literal)  \
4090   do {                                                          \
4091     GET_AND_CHECK_STRCMP(iter, typename, literal);              \
4092     if (!dbus_message_iter_next (&iter))                        \
4093       _dbus_assert_not_reached ("failed to move iter to next"); \
4094   } while (0)
4095
4096 static void
4097 message_iter_test (DBusMessage *message)
4098 {
4099   DBusMessageIter iter, array, array2;
4100   const char *v_STRING;
4101   double v_DOUBLE;
4102   dbus_int32_t v_INT32;
4103   dbus_uint32_t v_UINT32;
4104 #ifdef DBUS_HAVE_INT64
4105   dbus_int64_t v_INT64;
4106   dbus_uint64_t v_UINT64;
4107 #endif
4108   unsigned char v_BYTE;
4109   unsigned char v_BOOLEAN;
4110
4111   const dbus_int32_t *our_int_array;
4112   int len;
4113
4114   dbus_message_iter_init (message, &iter);
4115
4116   GET_AND_CHECK_STRCMP_AND_NEXT (iter, STRING, "Test string");
4117   GET_AND_CHECK_AND_NEXT (iter, INT32, -0x12345678);
4118   GET_AND_CHECK_AND_NEXT (iter, UINT32, 0xedd1e);
4119   GET_AND_CHECK_AND_NEXT (iter, DOUBLE, 3.14159);
4120
4121   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
4122     _dbus_assert_not_reached ("Argument type not an array");
4123
4124   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
4125     _dbus_assert_not_reached ("Array type not double");
4126
4127   dbus_message_iter_recurse (&iter, &array);
4128
4129   GET_AND_CHECK_AND_NEXT (array, DOUBLE, 1.5);
4130   GET_AND_CHECK (array, DOUBLE, 2.5);
4131
4132   if (dbus_message_iter_next (&array))
4133     _dbus_assert_not_reached ("Didn't reach end of array");
4134
4135   if (!dbus_message_iter_next (&iter))
4136     _dbus_assert_not_reached ("Reached end of arguments");
4137
4138   GET_AND_CHECK_AND_NEXT (iter, BYTE, 0xF0);
4139
4140   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
4141     _dbus_assert_not_reached ("no array");
4142
4143   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_INT32)
4144     _dbus_assert_not_reached ("Array type not int32");
4145
4146   /* Empty array */
4147   dbus_message_iter_recurse (&iter, &array);
4148
4149   if (dbus_message_iter_next (&array))
4150     _dbus_assert_not_reached ("Didn't reach end of array");
4151
4152   if (!dbus_message_iter_next (&iter))
4153     _dbus_assert_not_reached ("Reached end of arguments");
4154
4155   GET_AND_CHECK (iter, BYTE, 0xF0);
4156
4157   if (dbus_message_iter_next (&iter))
4158     _dbus_assert_not_reached ("Didn't reach end of arguments");
4159 }
4160
4161 static void
4162 verify_test_message (DBusMessage *message)
4163 {
4164   DBusMessageIter iter;
4165   DBusError error;
4166   dbus_int32_t our_int;
4167   const char *our_str;
4168   double our_double;
4169   unsigned char our_bool;
4170   unsigned char our_byte_1, our_byte_2;
4171   dbus_uint32_t our_uint32;
4172   const dbus_int32_t *our_uint32_array = (void*)0xdeadbeef;
4173   int our_uint32_array_len;
4174   dbus_int32_t *our_int32_array = (void*)0xdeadbeef;
4175   int our_int32_array_len;
4176 #ifdef DBUS_HAVE_INT64
4177   dbus_int64_t our_int64;
4178   dbus_uint64_t our_uint64;
4179   dbus_int64_t *our_uint64_array = (void*)0xdeadbeef;
4180   int our_uint64_array_len;
4181   const dbus_int64_t *our_int64_array = (void*)0xdeadbeef;
4182   int our_int64_array_len;
4183 #endif
4184   const double *our_double_array = (void*)0xdeadbeef;
4185   int our_double_array_len;
4186   const unsigned char *our_byte_array = (void*)0xdeadbeef;
4187   int our_byte_array_len;
4188   const unsigned char *our_boolean_array = (void*)0xdeadbeef;
4189   int our_boolean_array_len;
4190
4191   dbus_message_iter_init (message, &iter);
4192
4193   dbus_error_init (&error);
4194   if (!dbus_message_iter_get_args (&iter, &error,
4195                                    DBUS_TYPE_INT32, &our_int,
4196 #ifdef DBUS_HAVE_INT64
4197                                    DBUS_TYPE_INT64, &our_int64,
4198                                    DBUS_TYPE_UINT64, &our_uint64,
4199 #endif
4200                                    DBUS_TYPE_STRING, &our_str,
4201                                    DBUS_TYPE_DOUBLE, &our_double,
4202                                    DBUS_TYPE_BOOLEAN, &our_bool,
4203                                    DBUS_TYPE_BYTE, &our_byte_1,
4204                                    DBUS_TYPE_BYTE, &our_byte_2,
4205                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
4206                                    &our_uint32_array, &our_uint32_array_len,
4207                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
4208                                    &our_int32_array, &our_int32_array_len,
4209 #ifdef DBUS_HAVE_INT64
4210                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
4211                                    &our_uint64_array, &our_uint64_array_len,
4212                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
4213                                    &our_int64_array, &our_int64_array_len,
4214 #endif
4215                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
4216                                    &our_double_array, &our_double_array_len,
4217                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
4218                                    &our_byte_array, &our_byte_array_len,
4219                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
4220                                    &our_boolean_array, &our_boolean_array_len,
4221                                    0))
4222     {
4223       _dbus_warn ("error: %s - %s\n", error.name,
4224                   (error.message != NULL) ? error.message : "no message");
4225       _dbus_assert_not_reached ("Could not get arguments");
4226     }
4227
4228   if (our_int != -0x12345678)
4229     _dbus_assert_not_reached ("integers differ!");
4230
4231 #ifdef DBUS_HAVE_INT64
4232   if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
4233     _dbus_assert_not_reached ("64-bit integers differ!");
4234   if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
4235     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
4236 #endif
4237
4238   if (our_double != 3.14159)
4239     _dbus_assert_not_reached ("doubles differ!");
4240
4241   if (strcmp (our_str, "Test string") != 0)
4242     _dbus_assert_not_reached ("strings differ!");
4243
4244   if (!our_bool)
4245     _dbus_assert_not_reached ("booleans differ");
4246
4247   if (our_byte_1 != 42)
4248     _dbus_assert_not_reached ("bytes differ!");
4249
4250   if (our_byte_2 != 24)
4251     _dbus_assert_not_reached ("bytes differ!");
4252
4253   if (our_uint32_array_len != 4 ||
4254       our_uint32_array[0] != 0x12345678 ||
4255       our_uint32_array[1] != 0x23456781 ||
4256       our_uint32_array[2] != 0x34567812 ||
4257       our_uint32_array[3] != 0x45678123)
4258     _dbus_assert_not_reached ("uint array differs");
4259
4260   if (our_int32_array_len != 4 ||
4261       our_int32_array[0] != 0x12345678 ||
4262       our_int32_array[1] != -0x23456781 ||
4263       our_int32_array[2] != 0x34567812 ||
4264       our_int32_array[3] != -0x45678123)
4265     _dbus_assert_not_reached ("int array differs");
4266
4267 #ifdef DBUS_HAVE_INT64
4268   if (our_uint64_array_len != 4 ||
4269       our_uint64_array[0] != 0x12345678 ||
4270       our_uint64_array[1] != 0x23456781 ||
4271       our_uint64_array[2] != 0x34567812 ||
4272       our_uint64_array[3] != 0x45678123)
4273     _dbus_assert_not_reached ("uint64 array differs");
4274
4275   if (our_int64_array_len != 4 ||
4276       our_int64_array[0] != 0x12345678 ||
4277       our_int64_array[1] != -0x23456781 ||
4278       our_int64_array[2] != 0x34567812 ||
4279       our_int64_array[3] != -0x45678123)
4280     _dbus_assert_not_reached ("int64 array differs");
4281 #endif /* DBUS_HAVE_INT64 */
4282
4283   if (our_double_array_len != 3)
4284     _dbus_assert_not_reached ("double array had wrong length");
4285
4286   /* On all IEEE machines (i.e. everything sane) exact equality
4287    * should be preserved over the wire
4288    */
4289   if (our_double_array[0] != 0.1234 ||
4290       our_double_array[1] != 9876.54321 ||
4291       our_double_array[2] != -300.0)
4292     _dbus_assert_not_reached ("double array had wrong values");
4293
4294   if (our_byte_array_len != 4)
4295     _dbus_assert_not_reached ("byte array had wrong length");
4296
4297   if (our_byte_array[0] != 'a' ||
4298       our_byte_array[1] != 'b' ||
4299       our_byte_array[2] != 'c' ||
4300       our_byte_array[3] != 234)
4301     _dbus_assert_not_reached ("byte array had wrong values");
4302
4303   if (our_boolean_array_len != 5)
4304     _dbus_assert_not_reached ("bool array had wrong length");
4305
4306   if (our_boolean_array[0] != TRUE ||
4307       our_boolean_array[1] != FALSE ||
4308       our_boolean_array[2] != TRUE ||
4309       our_boolean_array[3] != TRUE ||
4310       our_boolean_array[4] != FALSE)
4311     _dbus_assert_not_reached ("bool array had wrong values");
4312
4313   if (dbus_message_iter_next (&iter))
4314     _dbus_assert_not_reached ("Didn't reach end of arguments");
4315 }
4316
4317 /**
4318  * @ingroup DBusMessageInternals
4319  * Unit test for DBusMessage.
4320  *
4321  * @returns #TRUE on success.
4322  */
4323 dbus_bool_t
4324 _dbus_message_test (const char *test_data_dir)
4325 {
4326   DBusMessage *message;
4327   DBusMessageLoader *loader;
4328   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
4329   int i;
4330   const char *data;
4331   DBusMessage *copy;
4332   const char *name1;
4333   const char *name2;
4334   const dbus_uint32_t our_uint32_array[] =
4335     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
4336   const dbus_uint32_t our_int32_array[] =
4337     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
4338   const dbus_uint32_t *v_ARRAY_UINT32 = our_uint32_array;
4339   const dbus_int32_t *v_ARRAY_INT32 = our_int32_array;
4340 #ifdef DBUS_HAVE_INT64
4341   const dbus_uint64_t our_uint64_array[] =
4342     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
4343   const dbus_uint64_t our_int64_array[] =
4344     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
4345   const dbus_uint64_t *v_ARRAY_UINT64 = our_uint64_array;
4346   const dbus_int64_t *v_ARRAY_INT64 = our_int64_array;
4347 #endif
4348   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
4349   const char **v_ARRAY_STRING = our_string_array;
4350   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
4351   const double *v_ARRAY_DOUBLE = our_double_array;
4352   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
4353   const unsigned char *v_ARRAY_BYTE = our_byte_array;
4354   const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
4355   const unsigned char *v_ARRAY_BOOLEAN = our_boolean_array;
4356   char sig[64];
4357   const char *s;
4358   char *t;
4359   DBusError error;
4360   const char *v_STRING;
4361   double v_DOUBLE;
4362   dbus_int32_t v_INT32;
4363   dbus_uint32_t v_UINT32;
4364 #ifdef DBUS_HAVE_INT64
4365   dbus_int64_t v_INT64;
4366   dbus_uint64_t v_UINT64;
4367 #endif
4368   unsigned char v_BYTE;
4369   unsigned char v2_BYTE;
4370   unsigned char v_BOOLEAN;
4371
4372   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
4373
4374   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
4375                                           "/org/freedesktop/TestPath",
4376                                           "Foo.TestInterface",
4377                                           "TestMethod");
4378   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
4379   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
4380                                              "TestMethod"));
4381   _dbus_assert (strcmp (dbus_message_get_path (message),
4382                         "/org/freedesktop/TestPath") == 0);
4383   _dbus_message_set_serial (message, 1234);
4384
4385   /* string length including nul byte not a multiple of 4 */
4386   if (!dbus_message_set_sender (message, "org.foo.bar1"))
4387     _dbus_assert_not_reached ("out of memory");
4388
4389   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
4390   dbus_message_set_reply_serial (message, 5678);
4391
4392   _dbus_verbose_bytes_of_string (&message->header.data, 0,
4393                                  _dbus_string_get_length (&message->header.data));
4394   _dbus_verbose_bytes_of_string (&message->body, 0,
4395                                  _dbus_string_get_length (&message->body));
4396
4397   if (!dbus_message_set_sender (message, NULL))
4398     _dbus_assert_not_reached ("out of memory");
4399
4400
4401   _dbus_verbose_bytes_of_string (&message->header.data, 0,
4402                                  _dbus_string_get_length (&message->header.data));
4403   _dbus_verbose_bytes_of_string (&message->body, 0,
4404                                  _dbus_string_get_length (&message->body));
4405
4406
4407   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
4408   _dbus_assert (dbus_message_get_serial (message) == 1234);
4409   _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
4410   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
4411
4412   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
4413   dbus_message_set_no_reply (message, TRUE);
4414   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
4415   dbus_message_set_no_reply (message, FALSE);
4416   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
4417
4418   /* Set/get some header fields */
4419
4420   if (!dbus_message_set_path (message, "/foo"))
4421     _dbus_assert_not_reached ("out of memory");
4422   _dbus_assert (strcmp (dbus_message_get_path (message),
4423                         "/foo") == 0);
4424
4425   if (!dbus_message_set_interface (message, "org.Foo"))
4426     _dbus_assert_not_reached ("out of memory");
4427   _dbus_assert (strcmp (dbus_message_get_interface (message),
4428                         "org.Foo") == 0);
4429
4430   if (!dbus_message_set_member (message, "Bar"))
4431     _dbus_assert_not_reached ("out of memory");
4432   _dbus_assert (strcmp (dbus_message_get_member (message),
4433                         "Bar") == 0);
4434
4435   /* Set/get them with longer values */
4436   if (!dbus_message_set_path (message, "/foo/bar"))
4437     _dbus_assert_not_reached ("out of memory");
4438   _dbus_assert (strcmp (dbus_message_get_path (message),
4439                         "/foo/bar") == 0);
4440
4441   if (!dbus_message_set_interface (message, "org.Foo.Bar"))
4442     _dbus_assert_not_reached ("out of memory");
4443   _dbus_assert (strcmp (dbus_message_get_interface (message),
4444                         "org.Foo.Bar") == 0);
4445
4446   if (!dbus_message_set_member (message, "BarFoo"))
4447     _dbus_assert_not_reached ("out of memory");
4448   _dbus_assert (strcmp (dbus_message_get_member (message),
4449                         "BarFoo") == 0);
4450
4451   /* Realloc shorter again */
4452
4453   if (!dbus_message_set_path (message, "/foo"))
4454     _dbus_assert_not_reached ("out of memory");
4455   _dbus_assert (strcmp (dbus_message_get_path (message),
4456                         "/foo") == 0);
4457
4458   if (!dbus_message_set_interface (message, "org.Foo"))
4459     _dbus_assert_not_reached ("out of memory");
4460   _dbus_assert (strcmp (dbus_message_get_interface (message),
4461                         "org.Foo") == 0);
4462
4463   if (!dbus_message_set_member (message, "Bar"))
4464     _dbus_assert_not_reached ("out of memory");
4465   _dbus_assert (strcmp (dbus_message_get_member (message),
4466                         "Bar") == 0);
4467
4468   dbus_message_unref (message);
4469
4470   /* Test the vararg functions */
4471   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
4472                                           "/org/freedesktop/TestPath",
4473                                           "Foo.TestInterface",
4474                                           "TestMethod");
4475   _dbus_message_set_serial (message, 1);
4476
4477   v_INT32 = -0x12345678;
4478 #ifdef DBUS_HAVE_INT64
4479   v_INT64 = DBUS_INT64_CONSTANT (-0x123456789abcd);
4480   v_UINT64 = DBUS_UINT64_CONSTANT (0x123456789abcd);
4481 #endif
4482   v_STRING = "Test string";
4483   v_DOUBLE = 3.14159;
4484   v_BOOLEAN = TRUE;
4485   v_BYTE = 42;
4486   v2_BYTE = 24;
4487
4488   dbus_message_append_args (message,
4489                             DBUS_TYPE_INT32, &v_INT32,
4490 #ifdef DBUS_HAVE_INT64
4491                             DBUS_TYPE_INT64, &v_INT64,
4492                             DBUS_TYPE_UINT64, &v_UINT64,
4493 #endif
4494                             DBUS_TYPE_STRING, &v_STRING,
4495                             DBUS_TYPE_DOUBLE, &v_DOUBLE,
4496                             DBUS_TYPE_BOOLEAN, &v_BOOLEAN,
4497                             DBUS_TYPE_BYTE, &v_BYTE,
4498                             DBUS_TYPE_BYTE, &v2_BYTE,
4499                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &v_ARRAY_UINT32,
4500                             _DBUS_N_ELEMENTS (our_uint32_array),
4501                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &v_ARRAY_INT32,
4502                             _DBUS_N_ELEMENTS (our_int32_array),
4503 #ifdef DBUS_HAVE_INT64
4504                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, &v_ARRAY_UINT64,
4505                             _DBUS_N_ELEMENTS (our_uint64_array),
4506                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, &v_ARRAY_INT64,
4507                             _DBUS_N_ELEMENTS (our_int64_array),
4508 #endif
4509                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, &v_ARRAY_DOUBLE,
4510                             _DBUS_N_ELEMENTS (our_double_array),
4511                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &v_ARRAY_BYTE,
4512                             _DBUS_N_ELEMENTS (our_byte_array),
4513                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, &v_ARRAY_BOOLEAN,
4514                             _DBUS_N_ELEMENTS (our_boolean_array),
4515                             DBUS_TYPE_INVALID);
4516
4517   i = 0;
4518   sig[i++] = DBUS_TYPE_INT32;
4519 #ifdef DBUS_HAVE_INT64
4520   sig[i++] = DBUS_TYPE_INT64;
4521   sig[i++] = DBUS_TYPE_UINT64;
4522 #endif
4523   sig[i++] = DBUS_TYPE_STRING;
4524   sig[i++] = DBUS_TYPE_DOUBLE;
4525   sig[i++] = DBUS_TYPE_BOOLEAN;
4526   sig[i++] = DBUS_TYPE_BYTE;
4527   sig[i++] = DBUS_TYPE_BYTE;
4528   sig[i++] = DBUS_TYPE_ARRAY;
4529   sig[i++] = DBUS_TYPE_UINT32;
4530   sig[i++] = DBUS_TYPE_ARRAY;
4531   sig[i++] = DBUS_TYPE_INT32;
4532 #ifdef DBUS_HAVE_INT64
4533   sig[i++] = DBUS_TYPE_ARRAY;
4534   sig[i++] = DBUS_TYPE_UINT64;
4535   sig[i++] = DBUS_TYPE_ARRAY;
4536   sig[i++] = DBUS_TYPE_INT64;
4537 #endif
4538   sig[i++] = DBUS_TYPE_ARRAY;
4539   sig[i++] = DBUS_TYPE_DOUBLE;
4540   sig[i++] = DBUS_TYPE_ARRAY;
4541   sig[i++] = DBUS_TYPE_BYTE;
4542   sig[i++] = DBUS_TYPE_ARRAY;
4543   sig[i++] = DBUS_TYPE_BOOLEAN;
4544   sig[i++] = DBUS_TYPE_INVALID;
4545
4546   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
4547
4548   _dbus_verbose ("HEADER\n");
4549   _dbus_verbose_bytes_of_string (&message->header.data, 0,
4550                                  _dbus_string_get_length (&message->header.data));
4551   _dbus_verbose ("BODY\n");
4552   _dbus_verbose_bytes_of_string (&message->body, 0,
4553                                  _dbus_string_get_length (&message->body));
4554
4555   _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
4556                  sig, dbus_message_get_signature (message));
4557
4558   s = dbus_message_get_signature (message);
4559
4560   _dbus_assert (dbus_message_has_signature (message, sig));
4561   _dbus_assert (strcmp (s, sig) == 0);
4562
4563   verify_test_message (message);
4564
4565   copy = dbus_message_copy (message);
4566
4567   _dbus_assert (dbus_message_get_reply_serial (message) ==
4568                 dbus_message_get_reply_serial (copy));
4569   _dbus_assert (message->header.padding == copy->header.padding);
4570
4571   _dbus_assert (_dbus_string_get_length (&message->header.data) ==
4572                 _dbus_string_get_length (&copy->header.data));
4573
4574   _dbus_assert (_dbus_string_get_length (&message->body) ==
4575                 _dbus_string_get_length (&copy->body));
4576
4577   verify_test_message (copy);
4578
4579   name1 = dbus_message_get_interface (message);
4580   name2 = dbus_message_get_interface (copy);
4581
4582   _dbus_assert (strcmp (name1, name2) == 0);
4583
4584   name1 = dbus_message_get_member (message);
4585   name2 = dbus_message_get_member (copy);
4586
4587   _dbus_assert (strcmp (name1, name2) == 0);
4588
4589   dbus_message_unref (message);
4590   dbus_message_unref (copy);
4591
4592 #if 0
4593   /* FIXME */
4594   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
4595                                           "/org/freedesktop/TestPath",
4596                                           "Foo.TestInterface",
4597                                           "TestMethod");
4598
4599   _dbus_message_set_serial (message, 1);
4600   dbus_message_set_reply_serial (message, 0x12345678);
4601
4602   dbus_message_iter_init_append (message, &iter);
4603   dbus_message_iter_append_string (&iter, "Test string");
4604   dbus_message_iter_append_int32 (&iter, -0x12345678);
4605   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
4606   dbus_message_iter_append_double (&iter, 3.14159);
4607
4608   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
4609   dbus_message_iter_append_double (&child_iter, 1.5);
4610   dbus_message_iter_append_double (&child_iter, 2.5);
4611
4612   /* dict */
4613   dbus_message_iter_append_dict (&iter, &child_iter);
4614   dbus_message_iter_append_dict_key (&child_iter, "test");
4615   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
4616
4617   /* dict (in dict) */
4618   dbus_message_iter_append_dict_key (&child_iter, "testdict");
4619   dbus_message_iter_append_dict (&child_iter, &child_iter2);
4620
4621   dbus_message_iter_append_dict_key (&child_iter2, "dictkey");
4622   dbus_message_iter_append_string (&child_iter2, "dictvalue");
4623
4624   /* array of array of int32  (in dict) */
4625   dbus_message_iter_append_dict_key (&child_iter, "array");
4626   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
4627   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
4628   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
4629   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
4630   _dbus_warn ("next call expected to fail with wrong array type\n");
4631   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
4632   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
4633   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
4634   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
4635   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
4636
4637   dbus_message_iter_append_byte (&iter, 0xF0);
4638
4639   dbus_message_iter_append_nil (&iter);
4640
4641   dbus_message_iter_append_custom (&iter, "MyTypeName",
4642                                    "data", 5);
4643
4644   dbus_message_iter_append_byte (&iter, 0xF0);
4645
4646   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_INT32);
4647
4648   dbus_message_iter_append_byte (&iter, 0xF0);
4649
4650   dbus_message_iter_append_dict (&iter, &child_iter);
4651
4652   dbus_message_iter_append_byte (&iter, 0xF0);
4653
4654   message_iter_test (message);
4655
4656   /* Message loader test */
4657   _dbus_message_lock (message);
4658   loader = _dbus_message_loader_new ();
4659
4660   /* check ref/unref */
4661   _dbus_message_loader_ref (loader);
4662   _dbus_message_loader_unref (loader);
4663
4664   /* Write the header data one byte at a time */
4665   data = _dbus_string_get_const_data (&message->header);
4666   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
4667     {
4668       DBusString *buffer;
4669
4670       _dbus_message_loader_get_buffer (loader, &buffer);
4671       _dbus_string_append_byte (buffer, data[i]);
4672       _dbus_message_loader_return_buffer (loader, buffer, 1);
4673     }
4674
4675   /* Write the body data one byte at a time */
4676   data = _dbus_string_get_const_data (&message->body);
4677   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
4678     {
4679       DBusString *buffer;
4680
4681       _dbus_message_loader_get_buffer (loader, &buffer);
4682       _dbus_string_append_byte (buffer, data[i]);
4683       _dbus_message_loader_return_buffer (loader, buffer, 1);
4684     }
4685
4686   copy = dbus_message_copy (message); /* save for tests below */
4687   dbus_message_unref (message);
4688
4689   /* Now pop back the message */
4690   if (!_dbus_message_loader_queue_messages (loader))
4691     _dbus_assert_not_reached ("no memory to queue messages");
4692
4693   if (_dbus_message_loader_get_is_corrupted (loader))
4694     _dbus_assert_not_reached ("message loader corrupted");
4695
4696   message = _dbus_message_loader_pop_message (loader);
4697   if (!message)
4698     _dbus_assert_not_reached ("received a NULL message");
4699
4700   if (dbus_message_get_reply_serial (message) != 0x12345678)
4701     _dbus_assert_not_reached ("reply serial fields differ");
4702
4703   message_iter_test (message);
4704
4705   dbus_message_unref (message);
4706   _dbus_message_loader_unref (loader);
4707
4708   message = dbus_message_new_method_return (copy);
4709   if (message == NULL)
4710     _dbus_assert_not_reached ("out of memory\n");
4711   dbus_message_unref (copy);
4712
4713   if (!dbus_message_append_args (message,
4714                                  DBUS_TYPE_STRING, "hello",
4715                                  DBUS_TYPE_INVALID))
4716     _dbus_assert_not_reached ("no memory");
4717
4718   if (!dbus_message_has_signature (message, "s"))
4719     _dbus_assert_not_reached ("method return has wrong signature");
4720
4721   dbus_error_init (&error);
4722   if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
4723                               &t, DBUS_TYPE_INVALID))
4724
4725     {
4726       _dbus_warn ("Failed to get expected string arg: %s\n", error.message);
4727       exit (1);
4728     }
4729   dbus_free (t);
4730
4731   dbus_message_unref (message);
4732
4733   /* This ServiceAcquired message used to trigger a bug in
4734    * setting header fields, adding to regression test.
4735    */
4736   message = dbus_message_new_signal (DBUS_PATH_ORG_FREEDESKTOP_DBUS,
4737                                      DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
4738                                      "ServiceAcquired");
4739
4740   if (message == NULL)
4741     _dbus_assert_not_reached ("out of memory");
4742
4743   _dbus_verbose ("Bytes after creation\n");
4744   _dbus_verbose_bytes_of_string (&message->header, 0,
4745                                  _dbus_string_get_length (&message->header));
4746
4747   if (!dbus_message_set_destination (message, ":1.0") ||
4748       !dbus_message_append_args (message,
4749                                  DBUS_TYPE_STRING, ":1.0",
4750                                  DBUS_TYPE_INVALID))
4751     _dbus_assert_not_reached ("out of memory");
4752
4753   _dbus_verbose ("Bytes after set_destination() and append_args()\n");
4754   _dbus_verbose_bytes_of_string (&message->header, 0,
4755                                  _dbus_string_get_length (&message->header));
4756
4757   if (!dbus_message_set_sender (message, "org.freedesktop.DBus"))
4758     _dbus_assert_not_reached ("out of memory");
4759
4760   _dbus_verbose ("Bytes after set_sender()\n");
4761   _dbus_verbose_bytes_of_string (&message->header, 0,
4762                                  _dbus_string_get_length (&message->header));
4763
4764   /* When the bug happened the above set_destination() would
4765    * corrupt the signature
4766    */
4767   if (!dbus_message_has_signature (message, "s"))
4768     {
4769       _dbus_warn ("Signature should be 's' but is '%s'\n",
4770                   dbus_message_get_signature (message));
4771       _dbus_assert_not_reached ("signal has wrong signature");
4772     }
4773
4774   /* have to set destination again to reproduce the bug */
4775   if (!dbus_message_set_destination (message, ":1.0"))
4776     _dbus_assert_not_reached ("out of memory");
4777
4778   _dbus_verbose ("Bytes after set_destination()\n");
4779   _dbus_verbose_bytes_of_string (&message->header, 0,
4780                                  _dbus_string_get_length (&message->header));
4781
4782   /* When the bug happened the above set_destination() would
4783    * corrupt the signature
4784    */
4785   if (!dbus_message_has_signature (message, "s"))
4786     {
4787       _dbus_warn ("Signature should be 's' but is '%s'\n",
4788                   dbus_message_get_signature (message));
4789       _dbus_assert_not_reached ("signal has wrong signature");
4790     }
4791
4792   dbus_error_init (&error);
4793   if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
4794                               &t, DBUS_TYPE_INVALID))
4795
4796     {
4797       _dbus_warn ("Failed to get expected string arg for signal: %s\n", error.message);
4798       exit (1);
4799     }
4800   dbus_free (t);
4801
4802   dbus_message_unref (message);
4803
4804   /* Now load every message in test_data_dir if we have one */
4805   if (test_data_dir == NULL)
4806     return TRUE;
4807
4808   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
4809                                                         (DBusForeachMessageFileFunc)
4810                                                         dbus_internal_do_not_use_try_message_file,
4811                                                         NULL);
4812
4813 #endif /* Commented out most tests for now */
4814
4815   return TRUE;
4816 }
4817
4818 #endif /* DBUS_BUILD_TESTS */