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