2003-08-18 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  Red Hat Inc.
5  * Copyright (C) 2002, 2003  CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 1.2
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.h"
27 #include "dbus-message.h"
28 #include "dbus-message-internal.h"
29 #include "dbus-memory.h"
30 #include "dbus-list.h"
31 #include "dbus-message-builder.h"
32 #include "dbus-dataslot.h"
33 #include <string.h>
34
35 /**
36  * @defgroup DBusMessageInternals DBusMessage implementation details
37  * @ingroup DBusInternals
38  * @brief DBusMessage private implementation details.
39  *
40  * The guts of DBusMessage and its methods.
41  *
42  * @{
43  */
44
45 enum
46 {
47   FIELD_HEADER_LENGTH,
48   FIELD_BODY_LENGTH,
49   FIELD_CLIENT_SERIAL,
50   FIELD_INTERFACE,
51   FIELD_MEMBER,
52   FIELD_ERROR_NAME,
53   FIELD_SERVICE,
54   FIELD_SENDER,
55   FIELD_REPLY_SERIAL,
56
57   FIELD_LAST
58 };
59
60 static dbus_bool_t field_is_named[FIELD_LAST] =
61 {
62   FALSE, /* FIELD_HEADER_LENGTH */
63   FALSE, /* FIELD_BODY_LENGTH */
64   FALSE, /* FIELD_CLIENT_SERIAL */
65   TRUE,  /* FIELD_INTERFACE */
66   TRUE,  /* FIELD_MEMBER */
67   TRUE,  /* FIELD_ERROR_NAME */
68   TRUE,  /* FIELD_SERVICE */
69   TRUE,  /* FIELD_SENDER */
70   TRUE   /* FIELD_REPLY_SERIAL */
71 };
72
73 typedef struct
74 {
75   int offset; /**< Offset to start of field (location of name of field
76                * for named fields)
77                */
78 } HeaderField;
79
80 #define BYTE_ORDER_OFFSET   0
81 #define TYPE_OFFSET         1
82 #define FLAGS_OFFSET        2
83 #define VERSION_OFFSET      3
84
85 /**
86  * @brief Internals of DBusMessage
87  * 
88  * Object representing a message received from or to be sent to
89  * another application. This is an opaque object, all members
90  * are private.
91  */
92 struct DBusMessage
93 {
94   DBusAtomic refcount; /**< Reference count */
95
96   DBusString header; /**< Header network data, stored
97                       * separately from body so we can
98                       * independently realloc it.
99                       */
100
101   HeaderField header_fields[FIELD_LAST]; /**< Track the location
102                                            * of each field in "header"
103                                            */
104
105   dbus_uint32_t client_serial; /**< Cached client serial value for speed */
106   dbus_uint32_t reply_serial;  /**< Cached reply serial value for speed */
107   
108   int header_padding; /**< bytes of alignment in header */
109   
110   DBusString body;   /**< Body network data. */
111
112   char byte_order; /**< Message byte order. */
113
114   DBusList *size_counters;   /**< 0-N DBusCounter used to track message size. */
115   long size_counter_delta;   /**< Size we incremented the size counters by.   */
116
117   dbus_uint32_t changed_stamp; /**< Incremented when iterators are invalidated. */
118   
119   unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
120
121   DBusDataSlotList slot_list;   /**< Data stored by allocated integer ID */  
122 };
123
124 enum {
125   DBUS_MESSAGE_ITER_TYPE_MESSAGE,
126   DBUS_MESSAGE_ITER_TYPE_ARRAY,
127   DBUS_MESSAGE_ITER_TYPE_DICT
128 };
129
130 /** typedef for internals of message iterator */
131 typedef struct DBusMessageRealIter DBusMessageRealIter;
132
133 /**
134  * @brief Internals of DBusMessageIter
135  * 
136  * Object representing a position in a message. All fields are internal.
137  */
138 struct DBusMessageRealIter
139 {
140   DBusMessageRealIter *parent_iter; /**< parent iter, or NULL */
141   DBusMessage *message; /**< Message used */
142   dbus_uint32_t changed_stamp; /**< stamp to detect invalid iters */
143   
144   /* This is an int instead of an enum to get a guaranteed size for the dummy: */
145   int type; /**< type of iter */
146   
147   int pos; /**< Current position in the string */
148   int end; /**< position right after the container */
149   int container_start; /**< offset of the start of the container */
150   int container_length_pos; /**< offset of the length of the container */
151   
152   int wrote_dict_key; /**< whether we wrote the dict key for the current dict element */
153
154   int array_type_pos; /**< pointer to the position of the array element type */
155   int array_type_done; /**< TRUE if the array type is fully finished */
156 };
157
158 /**
159  * Gets the data to be sent over the network for this message.
160  * The header and then the body should be written out.
161  * This function is guaranteed to always return the same
162  * data once a message is locked (with _dbus_message_lock()).
163  *
164  * @param message the message.
165  * @param header return location for message header data.
166  * @param body return location for message body data.
167  */
168 void
169 _dbus_message_get_network_data (DBusMessage          *message,
170                                 const DBusString    **header,
171                                 const DBusString    **body)
172 {
173   _dbus_assert (message->locked);
174   
175   *header = &message->header;
176   *body = &message->body;
177 }
178
179 static void
180 clear_header_padding (DBusMessage *message)
181 {
182   _dbus_string_shorten (&message->header,
183                         message->header_padding);
184   message->header_padding = 0;
185 }              
186
187 static dbus_bool_t
188 append_header_padding (DBusMessage *message)
189 {
190   int old_len;
191   old_len = _dbus_string_get_length (&message->header);
192   if (!_dbus_string_align_length (&message->header, 8))
193     return FALSE;
194
195   message->header_padding = _dbus_string_get_length (&message->header) - old_len;
196
197   return TRUE;
198 }
199
200 static void
201 adjust_field_offsets (DBusMessage *message,
202                       int          offsets_after,
203                       int          delta)
204 {
205   int i;
206
207   if (delta == 0)
208     return;
209   
210   i = 0;
211   while (i < FIELD_LAST)
212     {
213       if (message->header_fields[i].offset > offsets_after)
214         message->header_fields[i].offset += delta;
215
216       ++i;
217     }
218 }
219
220 #ifdef DBUS_BUILD_TESTS
221 /* tests-only until it's actually used */
222 static dbus_int32_t
223 get_int_field (DBusMessage *message,
224                int          field)
225 {
226   int offset;
227
228   _dbus_assert (field < FIELD_LAST);
229   
230   offset = message->header_fields[field].offset;
231   
232   if (offset < 0)
233     return -1; /* useless if -1 is a valid value of course */
234   
235   return _dbus_demarshal_int32 (&message->header,
236                                 message->byte_order,
237                                 offset,
238                                 NULL);
239 }
240 #endif
241
242 static dbus_uint32_t
243 get_uint_field (DBusMessage *message,
244                 int          field)
245 {
246   int offset;
247   
248   _dbus_assert (field < FIELD_LAST);
249   
250   offset = message->header_fields[field].offset;
251   
252   if (offset < 0)
253     return -1; /* useless if -1 is a valid value of course */
254   
255   return _dbus_demarshal_uint32 (&message->header,
256                                  message->byte_order,
257                                  offset,
258                                  NULL);
259 }
260
261 static const char*
262 get_string_field (DBusMessage *message,
263                   int          field,
264                   int         *len)
265 {
266   int offset;
267   const char *data;
268
269   offset = message->header_fields[field].offset;
270
271   _dbus_assert (field < FIELD_LAST);
272   
273   if (offset < 0)
274     return NULL;
275
276   /* offset points to string length, string data follows it */
277   /* FIXME _dbus_demarshal_const_string() that returned
278    * a reference to the string plus its len might be nice.
279    */
280   
281   if (len)
282     *len = _dbus_demarshal_uint32 (&message->header,
283                                    message->byte_order,
284                                    offset,
285                                    NULL);
286
287   data = _dbus_string_get_const_data (&message->header);
288   
289   return data + (offset + 4); 
290 }
291
292 #ifdef DBUS_BUILD_TESTS
293 static dbus_bool_t
294 append_int_field (DBusMessage *message,
295                   int          field,
296                   const char  *name,
297                   int          value)
298 {
299   int orig_len;
300
301   _dbus_assert (!message->locked);
302
303   clear_header_padding (message);
304   
305   orig_len = _dbus_string_get_length (&message->header);
306   
307   if (!_dbus_string_align_length (&message->header, 4))
308     goto failed;  
309   
310   if (!_dbus_string_append_len (&message->header, name, 4))
311     goto failed;
312
313   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
314     goto failed;
315
316   if (!_dbus_string_align_length (&message->header, 4))
317     goto failed;
318   
319   message->header_fields[field].offset =
320     _dbus_string_get_length (&message->header);
321   
322   if (!_dbus_marshal_int32 (&message->header, message->byte_order,
323                             value))
324     goto failed;
325
326   if (!append_header_padding (message))
327     goto failed;
328   
329   return TRUE;
330   
331  failed:
332   message->header_fields[field].offset = -1;
333   _dbus_string_set_length (&message->header, orig_len);
334
335   /* this must succeed because it was allocated on function entry and
336    * DBusString doesn't ever realloc smaller
337    */
338   if (!append_header_padding (message))
339     _dbus_assert_not_reached ("failed to reappend header padding");
340   return FALSE;
341 }
342 #endif
343
344 static dbus_bool_t
345 append_uint_field (DBusMessage *message,
346                    int          field,
347                    const char  *name,
348                    int          value)
349 {
350   int orig_len;
351
352   _dbus_assert (!message->locked);
353
354   clear_header_padding (message);
355   
356   orig_len = _dbus_string_get_length (&message->header);
357   
358   if (!_dbus_string_align_length (&message->header, 4))
359     goto failed;  
360   
361   if (!_dbus_string_append_len (&message->header, name, 4))
362     goto failed;
363
364   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_UINT32))
365     goto failed;
366
367   if (!_dbus_string_align_length (&message->header, 4))
368     goto failed;
369   
370   message->header_fields[field].offset =
371     _dbus_string_get_length (&message->header);
372   
373   if (!_dbus_marshal_uint32 (&message->header, message->byte_order,
374                              value))
375     goto failed;
376
377   if (!append_header_padding (message))
378     goto failed;
379   
380   return TRUE;
381   
382  failed:
383   message->header_fields[field].offset = -1;
384   _dbus_string_set_length (&message->header, orig_len);
385
386   /* this must succeed because it was allocated on function entry and
387    * DBusString doesn't ever realloc smaller
388    */
389   if (!append_header_padding (message))
390     _dbus_assert_not_reached ("failed to reappend header padding");
391   return FALSE;
392 }
393
394 static dbus_bool_t
395 append_string_field (DBusMessage *message,
396                      int          field,
397                      const char  *name,
398                      const char  *value)
399 {
400   int orig_len;
401
402   _dbus_assert (!message->locked);
403
404   clear_header_padding (message);
405   
406   orig_len = _dbus_string_get_length (&message->header);
407
408   if (!_dbus_string_align_length (&message->header, 4))
409     goto failed;
410   
411   if (!_dbus_string_append_len (&message->header, name, 4))
412     goto failed;
413   
414   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_STRING))
415     goto failed;
416
417   if (!_dbus_string_align_length (&message->header, 4))
418     goto failed;
419   
420   message->header_fields[field].offset =
421     _dbus_string_get_length (&message->header);
422   
423   if (!_dbus_marshal_string (&message->header, message->byte_order,
424                              value))
425     goto failed;
426
427   if (!append_header_padding (message))
428     goto failed;
429   
430   return TRUE;
431   
432  failed:
433   message->header_fields[field].offset = -1;
434   _dbus_string_set_length (&message->header, orig_len);
435
436   /* this must succeed because it was allocated on function entry and
437    * DBusString doesn't ever realloc smaller
438    */
439   if (!append_header_padding (message))
440     _dbus_assert_not_reached ("failed to reappend header padding");
441   
442   return FALSE;
443 }
444
445 #ifdef DBUS_BUILD_TESTS
446 /* This isn't used, but building it when tests are enabled just to
447  * keep it compiling if we need it in future
448  */
449 static void
450 delete_int_or_uint_field (DBusMessage *message,
451                           int          field)
452 {
453   int offset = message->header_fields[field].offset;
454
455   _dbus_assert (!message->locked);
456   _dbus_assert (field_is_named[field]);
457   
458   if (offset < 0)
459     return;  
460
461   clear_header_padding (message);
462   
463   /* The field typecode and name take up 8 bytes */
464   _dbus_string_delete (&message->header,
465                        offset - 8,
466                        12);
467
468   message->header_fields[field].offset = -1;
469   
470   adjust_field_offsets (message,
471                         offset - 8,
472                         - 12);
473
474   append_header_padding (message);
475 }
476 #endif
477
478 static void
479 delete_string_field (DBusMessage *message,
480                      int          field)
481 {
482   int offset = message->header_fields[field].offset;
483   int len;
484   int delete_len;
485   
486   _dbus_assert (!message->locked);
487   _dbus_assert (field_is_named[field]);
488   
489   if (offset < 0)
490     return;
491
492   clear_header_padding (message);
493   
494   get_string_field (message, field, &len);
495   
496   /* The field typecode and name take up 8 bytes, and the nul
497    * termination is 1 bytes, string length integer is 4 bytes
498    */
499   delete_len = 8 + 4 + 1 + len;
500   
501   _dbus_string_delete (&message->header,
502                        offset - 8,
503                        delete_len);
504
505   message->header_fields[field].offset = -1;
506   
507   adjust_field_offsets (message,
508                         offset - 8,
509                         - delete_len);
510
511   append_header_padding (message);
512 }
513
514 #ifdef DBUS_BUILD_TESTS
515 static dbus_bool_t
516 set_int_field (DBusMessage *message,
517                int          field,
518                int          value)
519 {
520   int offset = message->header_fields[field].offset;
521
522   _dbus_assert (!message->locked);
523   
524   if (offset < 0)
525     {
526       /* need to append the field */
527
528       switch (field)
529         {
530         default:
531           _dbus_assert_not_reached ("appending an int field we don't support appending");
532           return FALSE;
533         }
534     }
535   else
536     {
537       _dbus_marshal_set_int32 (&message->header,
538                                message->byte_order,
539                                offset, value);
540
541       return TRUE;
542     }
543 }
544 #endif
545
546 static dbus_bool_t
547 set_uint_field (DBusMessage  *message,
548                 int           field,
549                 dbus_uint32_t value)
550 {
551   int offset = message->header_fields[field].offset;
552
553   _dbus_assert (!message->locked);
554   
555   if (offset < 0)
556     {
557       /* need to append the field */
558
559       switch (field)
560         {
561         case FIELD_REPLY_SERIAL:
562           return append_uint_field (message, field,
563                                     DBUS_HEADER_FIELD_REPLY,
564                                     value);
565         default:
566           _dbus_assert_not_reached ("appending a uint field we don't support appending");
567           return FALSE;
568         }
569     }
570   else
571     {
572       _dbus_marshal_set_uint32 (&message->header,
573                                 message->byte_order,
574                                 offset, value);
575
576       return TRUE;
577     }
578 }
579
580 static dbus_bool_t
581 set_string_field (DBusMessage *message,
582                   int          field,
583                   const char  *value)
584 {
585   int offset = message->header_fields[field].offset;
586
587   _dbus_assert (!message->locked);
588   _dbus_assert (value != NULL);
589   
590   if (offset < 0)
591     {      
592       /* need to append the field */
593
594       switch (field)
595         {
596         case FIELD_SENDER:
597           return append_string_field (message, field,
598                                       DBUS_HEADER_FIELD_SENDER,
599                                       value);
600         case FIELD_INTERFACE:
601           return append_string_field (message, field,
602                                       DBUS_HEADER_FIELD_INTERFACE,
603                                       value);
604         case FIELD_MEMBER:
605           return append_string_field (message, field,
606                                       DBUS_HEADER_FIELD_MEMBER,
607                                       value);
608         case FIELD_ERROR_NAME:
609           return append_string_field (message, field,
610                                       DBUS_HEADER_FIELD_ERROR_NAME,
611                                       value);
612         case FIELD_SERVICE:
613           return append_string_field (message, field,
614                                       DBUS_HEADER_FIELD_SERVICE,
615                                       value);
616         default:
617           _dbus_assert_not_reached ("appending a string field we don't support appending");
618           return FALSE;
619         }
620     }
621   else
622     {
623       DBusString v;
624       int old_len;
625       int new_len;
626       int len;
627       
628       clear_header_padding (message);
629       
630       old_len = _dbus_string_get_length (&message->header);
631
632       len = strlen (value);
633       
634       _dbus_string_init_const_len (&v, value,
635                                    len + 1); /* include nul */
636       if (!_dbus_marshal_set_string (&message->header,
637                                      message->byte_order,
638                                      offset, &v,
639                                      len))
640         goto failed;
641       
642       new_len = _dbus_string_get_length (&message->header);
643
644       adjust_field_offsets (message,
645                             offset,
646                             new_len - old_len);
647
648       if (!append_header_padding (message))
649         goto failed;
650       
651       return TRUE;
652
653     failed:
654       /* this must succeed because it was allocated on function entry and
655        * DBusString doesn't ever realloc smaller
656        */
657       if (!append_header_padding (message))
658         _dbus_assert_not_reached ("failed to reappend header padding");
659
660       return FALSE;
661     }
662 }
663
664 /**
665  * Sets the serial number of a message. 
666  * This can only be done once on a message.
667  * 
668  * @param message the message
669  * @param serial the serial
670  */
671 void
672 _dbus_message_set_serial (DBusMessage  *message,
673                           dbus_int32_t  serial)
674 {
675   _dbus_assert (!message->locked);
676   _dbus_assert (dbus_message_get_serial (message) == 0);
677   
678   set_uint_field (message, FIELD_CLIENT_SERIAL,
679                   serial);
680   message->client_serial = serial;
681 }
682
683 /**
684  * Sets the reply serial of a message (the client serial
685  * of the message this is a reply to).
686  *
687  * @param message the message
688  * @param reply_serial the client serial
689  * @returns #FALSE if not enough memory
690  */
691 dbus_bool_t
692 dbus_message_set_reply_serial (DBusMessage   *message,
693                                dbus_uint32_t  reply_serial)
694 {
695   _dbus_assert (!message->locked);
696
697   if (set_uint_field (message, FIELD_REPLY_SERIAL,
698                       reply_serial))
699     {
700       message->reply_serial = reply_serial;
701       return TRUE;
702     }
703   else
704     return FALSE;
705 }
706
707 /**
708  * Returns the serial of a message or -1 if none has been specified.
709  * The message's serial number is provided by the application sending
710  * the message and is used to identify replies to this message.
711  *
712  * @param message the message
713  * @returns the client serial
714  */
715 dbus_uint32_t
716 dbus_message_get_serial (DBusMessage *message)
717 {
718   return message->client_serial;
719 }
720
721 /**
722  * Returns the serial that the message is
723  * a reply to or 0 if none.
724  *
725  * @param message the message
726  * @returns the reply serial
727  */
728 dbus_uint32_t
729 dbus_message_get_reply_serial  (DBusMessage *message)
730 {
731   return message->reply_serial;
732 }
733
734 /**
735  * Adds a counter to be incremented immediately with the
736  * size of this message, and decremented by the size
737  * of this message when this message if finalized.
738  * The link contains a counter with its refcount already
739  * incremented, but the counter itself not incremented.
740  * Ownership of link and counter refcount is passed to
741  * the message.
742  *
743  * @param message the message
744  * @param link link with counter as data
745  */
746 void
747 _dbus_message_add_size_counter_link (DBusMessage  *message,
748                                      DBusList     *link)
749 {
750   /* right now we don't recompute the delta when message
751    * size changes, and that's OK for current purposes
752    * I think, but could be important to change later.
753    * Do recompute it whenever there are no outstanding counters,
754    * since it's basically free.
755    */
756   if (message->size_counters == NULL)
757     {
758       message->size_counter_delta =
759         _dbus_string_get_length (&message->header) +
760         _dbus_string_get_length (&message->body);
761       
762 #if 0
763       _dbus_verbose ("message has size %ld\n",
764                      message->size_counter_delta);
765 #endif
766     }
767   
768   _dbus_list_append_link (&message->size_counters, link);
769   
770   _dbus_counter_adjust (link->data, message->size_counter_delta);
771 }
772
773 /**
774  * Adds a counter to be incremented immediately with the
775  * size of this message, and decremented by the size
776  * of this message when this message if finalized.
777  *
778  * @param message the message
779  * @param counter the counter
780  * @returns #FALSE if no memory
781  */
782 dbus_bool_t
783 _dbus_message_add_size_counter (DBusMessage *message,
784                                 DBusCounter *counter)
785 {
786   DBusList *link;
787
788   link = _dbus_list_alloc_link (counter);
789   if (link == NULL)
790     return FALSE;
791
792   _dbus_counter_ref (counter);
793   _dbus_message_add_size_counter_link (message, link);
794
795   return TRUE;
796 }
797
798 /**
799  * Removes a counter tracking the size of this message, and decrements
800  * the counter by the size of this message.
801  *
802  * @param message the message
803  * @param link_return return the link used
804  * @param counter the counter
805  */
806 void
807 _dbus_message_remove_size_counter (DBusMessage  *message,
808                                    DBusCounter  *counter,
809                                    DBusList    **link_return)
810 {
811   DBusList *link;
812
813   link = _dbus_list_find_last (&message->size_counters,
814                                counter);
815   _dbus_assert (link != NULL);
816
817   _dbus_list_unlink (&message->size_counters,
818                      link);
819   if (link_return)
820     *link_return = link;
821   else
822     _dbus_list_free_link (link);
823
824   _dbus_counter_adjust (counter, message->size_counter_delta);
825
826   _dbus_counter_unref (counter);
827 }
828
829 static dbus_bool_t
830 dbus_message_create_header (DBusMessage *message,
831                             int          type,
832                             const char  *interface,
833                             const char  *member,
834                             const char  *error_name,
835                             const char  *service)
836 {
837   unsigned int flags;
838
839   _dbus_assert ((interface && member) ||
840                 (error_name) ||
841                 !(interface || member || error_name));
842   
843   if (!_dbus_string_append_byte (&message->header, message->byte_order))
844     return FALSE;
845
846   if (!_dbus_string_append_byte (&message->header, type))
847     return FALSE;
848   
849   flags = 0;
850   if (!_dbus_string_append_byte (&message->header, flags))
851     return FALSE;
852
853   if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
854     return FALSE;
855
856   message->header_fields[FIELD_HEADER_LENGTH].offset = 4;
857   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
858     return FALSE;
859
860   message->header_fields[FIELD_BODY_LENGTH].offset = 8;
861   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
862     return FALSE;
863
864   message->header_fields[FIELD_CLIENT_SERIAL].offset = 12;
865   if (!_dbus_marshal_int32 (&message->header, message->byte_order, -1))
866     return FALSE;
867   
868   /* Marshal message service */
869   if (service != NULL)
870     {
871       if (!append_string_field (message,
872                                 FIELD_SERVICE,
873                                 DBUS_HEADER_FIELD_SERVICE,
874                                 service))
875         return FALSE;
876     }
877
878   if (interface != NULL)
879     {
880       if (!append_string_field (message,
881                                 FIELD_INTERFACE,
882                                 DBUS_HEADER_FIELD_INTERFACE,
883                                 interface))
884         return FALSE;
885     }
886
887   if (member != NULL)
888     {
889       if (!append_string_field (message,
890                                 FIELD_MEMBER,
891                                 DBUS_HEADER_FIELD_MEMBER,
892                                 member))
893         return FALSE;
894     }
895
896   if (error_name != NULL)
897     {
898       if (!append_string_field (message,
899                                 FIELD_ERROR_NAME,
900                                 DBUS_HEADER_FIELD_ERROR_NAME,
901                                 error_name))
902         return FALSE;
903     }
904   
905   return TRUE;
906 }
907
908 /**
909  * Locks a message. Allows checking that applications don't keep a
910  * reference to a message in the outgoing queue and change it
911  * underneath us. Messages are locked when they enter the outgoing
912  * queue (dbus_connection_send_message()), and the library complains
913  * if the message is modified while locked.
914  *
915  * @param message the message to lock.
916  */
917 void
918 _dbus_message_lock (DBusMessage  *message)
919 {
920   if (!message->locked)
921     {
922       /* Fill in our lengths */
923       set_uint_field (message,
924                       FIELD_HEADER_LENGTH,
925                       _dbus_string_get_length (&message->header));
926
927       set_uint_field (message,
928                       FIELD_BODY_LENGTH,
929                       _dbus_string_get_length (&message->body));
930
931       message->locked = TRUE;
932     }
933 }
934
935 /** @} */
936
937 /**
938  * @defgroup DBusMessage DBusMessage
939  * @ingroup  DBus
940  * @brief Message to be sent or received over a DBusConnection.
941  *
942  * A DBusMessage is the most basic unit of communication over a
943  * DBusConnection. A DBusConnection represents a stream of messages
944  * received from a remote application, and a stream of messages
945  * sent to a remote application.
946  *
947  * @{
948  */
949
950 /**
951  * @typedef DBusMessage
952  *
953  * Opaque data type representing a message received from or to be
954  * sent to another application.
955  */
956
957 static DBusMessage*
958 dbus_message_new_empty_header (void)
959 {
960   DBusMessage *message;
961   int i;
962   
963   message = dbus_new0 (DBusMessage, 1);
964   if (message == NULL)
965     return NULL;
966   
967   message->refcount.value = 1;
968   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
969   message->client_serial = 0;
970   message->reply_serial = 0;
971
972   _dbus_data_slot_list_init (&message->slot_list);
973   
974   i = 0;
975   while (i < FIELD_LAST)
976     {
977       message->header_fields[i].offset = -1;
978       ++i;
979     }
980   
981   if (!_dbus_string_init_preallocated (&message->header, 64))
982     {
983       dbus_free (message);
984       return NULL;
985     }
986   
987   if (!_dbus_string_init_preallocated (&message->body, 64))
988     {
989       _dbus_string_free (&message->header);
990       dbus_free (message);
991       return NULL;
992     }
993   
994   return message;
995 }
996
997 /**
998  * Constructs a new message of the given message type.
999  * Types include #DBUS_MESSAGE_TYPE_METHOD_CALL,
1000  * #DBUS_MESSAGE_TYPE_SIGNAL, and so forth.
1001  *
1002  * @param message_type type of message
1003  * @returns new message or #NULL If no memory
1004  */
1005 DBusMessage*
1006 dbus_message_new (int message_type)
1007 {
1008   DBusMessage *message;
1009
1010   _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
1011   
1012   message = dbus_message_new_empty_header ();
1013   if (message == NULL)
1014     return NULL;
1015   
1016   if (!dbus_message_create_header (message,
1017                                    message_type,
1018                                    NULL, NULL, NULL, NULL))
1019     {
1020       dbus_message_unref (message);
1021       return NULL;
1022     }
1023   
1024   return message;
1025 }
1026
1027 /**
1028  * Constructs a new message to invoke a method on a remote
1029  * object. Returns #NULL if memory can't be allocated for the
1030  * message. The service may be #NULL in which case no service is set;
1031  * this is appropriate when using D-BUS in a peer-to-peer context (no
1032  * message bus).
1033  *
1034  * @param interface interface to invoke method on
1035  * @param method method to invoke
1036  * @param destination_service service that the message should be sent to or #NULL
1037  * @returns a new DBusMessage, free with dbus_message_unref()
1038  * @see dbus_message_unref()
1039  */
1040 DBusMessage*
1041 dbus_message_new_method_call (const char *interface,
1042                               const char *method,
1043                               const char *destination_service)            
1044 {
1045   DBusMessage *message;
1046
1047   _dbus_return_val_if_fail (interface != NULL, NULL);
1048   _dbus_return_val_if_fail (method != NULL, NULL);
1049   
1050   message = dbus_message_new_empty_header ();
1051   if (message == NULL)
1052     return NULL;
1053   
1054   if (!dbus_message_create_header (message,
1055                                    DBUS_MESSAGE_TYPE_METHOD_CALL,
1056                                    interface, method, NULL, destination_service))
1057     {
1058       dbus_message_unref (message);
1059       return NULL;
1060     }
1061   
1062   return message;
1063 }
1064
1065 /**
1066  * Constructs a message that is a reply to a method call. Returns
1067  * #NULL if memory can't be allocated for the message.
1068  *
1069  * @param method_call the message which the created
1070  * message is a reply to.
1071  * @returns a new DBusMessage, free with dbus_message_unref()
1072  * @see dbus_message_new_method_call(), dbus_message_unref()
1073  */ 
1074 DBusMessage*
1075 dbus_message_new_method_return (DBusMessage *method_call)
1076 {
1077   DBusMessage *message;
1078   const char *sender;
1079
1080   _dbus_return_val_if_fail (method_call != NULL, NULL);
1081   
1082   sender = get_string_field (method_call,
1083                              FIELD_SENDER, NULL);
1084
1085   /* sender is allowed to be null here in peer-to-peer case */
1086
1087   message = dbus_message_new_empty_header ();
1088   if (message == NULL)
1089     return NULL;
1090   
1091   if (!dbus_message_create_header (message,
1092                                    DBUS_MESSAGE_TYPE_METHOD_RETURN,
1093                                    NULL, NULL, NULL, sender))
1094     {
1095       dbus_message_unref (message);
1096       return NULL;
1097     }
1098
1099   if (!dbus_message_set_reply_serial (message,
1100                                       dbus_message_get_serial (method_call)))
1101     {
1102       dbus_message_unref (message);
1103       return NULL;
1104     }
1105
1106   return message;
1107 }
1108
1109 /**
1110  * Constructs a new message representing a signal emission. Returns
1111  * #NULL if memory can't be allocated for the message.
1112  * A signal is identified by its originating interface, and
1113  * the name of the signal.
1114  *
1115  * @param interface the interface the signal is emitted from
1116  * @param name name of the signal
1117  * @returns a new DBusMessage, free with dbus_message_unref()
1118  * @see dbus_message_unref()
1119  */
1120 DBusMessage*
1121 dbus_message_new_signal (const char *interface,
1122                          const char *name)
1123 {
1124   DBusMessage *message;
1125
1126   _dbus_return_val_if_fail (name != NULL, NULL);
1127   
1128   message = dbus_message_new_empty_header ();
1129   if (message == NULL)
1130     return NULL;
1131   
1132   if (!dbus_message_create_header (message,
1133                                    DBUS_MESSAGE_TYPE_SIGNAL,
1134                                    interface, name, NULL, NULL))
1135     {
1136       dbus_message_unref (message);
1137       return NULL;
1138     }
1139   
1140   return message;
1141 }
1142
1143 /**
1144  * Creates a new message that is an error reply to a certain message.
1145  * Error replies are possible in response to method calls primarily.
1146  *
1147  * @param reply_to the original message
1148  * @param error_name the error name
1149  * @param error_message the error message string or #NULL for none
1150  * @returns a new error message
1151  */
1152 DBusMessage*
1153 dbus_message_new_error (DBusMessage *reply_to,
1154                         const char  *error_name,
1155                         const char  *error_message)
1156 {
1157   DBusMessage *message;
1158   const char *sender;
1159   DBusMessageIter iter;
1160
1161   _dbus_return_val_if_fail (reply_to != NULL, NULL);
1162   _dbus_return_val_if_fail (error_name != NULL, NULL);
1163   
1164   sender = get_string_field (reply_to,
1165                              FIELD_SENDER, NULL);
1166
1167   /* sender may be NULL for non-message-bus case or
1168    * when the message bus is dealing with an unregistered
1169    * connection.
1170    */
1171   message = dbus_message_new_empty_header ();
1172   if (message == NULL)
1173     return NULL;
1174   
1175   if (!dbus_message_create_header (message,
1176                                    DBUS_MESSAGE_TYPE_ERROR,
1177                                    NULL, NULL, error_name, sender))
1178     {
1179       dbus_message_unref (message);
1180       return NULL;
1181     }
1182
1183   if (!dbus_message_set_reply_serial (message,
1184                                       dbus_message_get_serial (reply_to)))
1185     {
1186       dbus_message_unref (message);
1187       return NULL;
1188     }
1189
1190   if (error_message != NULL)
1191     {
1192       dbus_message_append_iter_init (message, &iter);
1193       if (!dbus_message_iter_append_string (&iter, error_message))
1194         {
1195           dbus_message_unref (message);
1196           return NULL;
1197         }
1198     }
1199   
1200   return message;
1201 }
1202
1203 /**
1204  * Creates a new message that is an exact replica of the message
1205  * specified, except that its refcount is set to 1.
1206  *
1207  * @param message the message.
1208  * @returns the new message.
1209  */
1210 DBusMessage *
1211 dbus_message_copy (const DBusMessage *message)
1212 {
1213   DBusMessage *retval;
1214   int i;
1215
1216   _dbus_return_val_if_fail (message != NULL, NULL);
1217   
1218   retval = dbus_new0 (DBusMessage, 1);
1219   if (retval == NULL)
1220     return NULL;
1221   
1222   retval->refcount.value = 1;
1223   retval->byte_order = message->byte_order;
1224   retval->client_serial = message->client_serial;
1225   retval->reply_serial = message->reply_serial;
1226   retval->header_padding = message->header_padding;
1227   retval->locked = FALSE;
1228   
1229   if (!_dbus_string_init (&retval->header))
1230     {
1231       dbus_free (retval);
1232       return NULL;
1233     }
1234   
1235   if (!_dbus_string_init (&retval->body))
1236     {
1237       _dbus_string_free (&retval->header);
1238       dbus_free (retval);
1239       return NULL;
1240     }
1241
1242   if (!_dbus_string_copy (&message->header, 0,
1243                           &retval->header, 0))
1244     {
1245       _dbus_string_free (&retval->header);
1246       _dbus_string_free (&retval->body);
1247       dbus_free (retval);
1248
1249       return NULL;
1250     }
1251
1252   if (!_dbus_string_copy (&message->body, 0,
1253                           &retval->body, 0))
1254     {
1255       _dbus_string_free (&retval->header);
1256       _dbus_string_free (&retval->body);
1257       dbus_free (retval);
1258
1259       return NULL;
1260     }
1261
1262   for (i = 0; i < FIELD_LAST; i++)
1263     {
1264       retval->header_fields[i].offset = message->header_fields[i].offset;
1265     }
1266   
1267   return retval;
1268 }
1269
1270
1271 /**
1272  * Increments the reference count of a DBusMessage.
1273  *
1274  * @param message The message
1275  * @see dbus_message_unref
1276  */
1277 void
1278 dbus_message_ref (DBusMessage *message)
1279 {
1280   dbus_int32_t old_refcount;
1281
1282   _dbus_return_if_fail (message != NULL);
1283   
1284   old_refcount = _dbus_atomic_inc (&message->refcount);
1285   _dbus_assert (old_refcount >= 1);
1286 }
1287
1288 static void
1289 free_size_counter (void *element,
1290                    void *data)
1291 {
1292   DBusCounter *counter = element;
1293   DBusMessage *message = data;
1294   
1295   _dbus_counter_adjust (counter, - message->size_counter_delta);
1296
1297   _dbus_counter_unref (counter);
1298 }
1299
1300 /**
1301  * Decrements the reference count of a DBusMessage.
1302  *
1303  * @param message The message
1304  * @see dbus_message_ref
1305  */
1306 void
1307 dbus_message_unref (DBusMessage *message)
1308 {
1309  dbus_int32_t old_refcount;
1310
1311   _dbus_return_if_fail (message != NULL);
1312   
1313   old_refcount = _dbus_atomic_dec (&message->refcount);
1314   
1315   _dbus_assert (old_refcount >= 0);
1316
1317   if (old_refcount == 1)
1318     {
1319       /* This calls application callbacks! */
1320       _dbus_data_slot_list_free (&message->slot_list);
1321       
1322       _dbus_list_foreach (&message->size_counters,
1323                           free_size_counter, message);
1324       _dbus_list_clear (&message->size_counters);
1325       
1326       _dbus_string_free (&message->header);
1327       _dbus_string_free (&message->body);
1328       
1329       dbus_free (message);
1330     }
1331 }
1332
1333 /**
1334  * Gets the type of a message. Types include
1335  * DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_METHOD_RETURN,
1336  * DBUS_MESSAGE_TYPE_ERROR, DBUS_MESSAGE_TYPE_SIGNAL, but other types
1337  * are allowed and all code must silently ignore messages of unknown
1338  * type. DBUS_MESSAGE_TYPE_INVALID will never be returned, however.
1339  *
1340  *
1341  * @param message the message
1342  * @returns the type of the message
1343  */
1344 int
1345 dbus_message_get_type (DBusMessage *message)
1346 {
1347   int type;
1348
1349   type = _dbus_string_get_byte (&message->header, 1);
1350   _dbus_assert (type != DBUS_MESSAGE_TYPE_INVALID);
1351
1352   return type;
1353 }
1354
1355 /**
1356  * Sets the interface this message is being sent to
1357  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or
1358  * the interface a signal is being emitted from
1359  * (for DBUS_MESSAGE_TYPE_SIGNAL).
1360  *
1361  * @param message the message
1362  * @param interface the interface
1363  * @returns #FALSE if not enough memory
1364  */
1365 dbus_bool_t
1366 dbus_message_set_interface (DBusMessage  *message,
1367                             const char   *interface)
1368 {
1369   _dbus_return_val_if_fail (message != NULL, FALSE);
1370   _dbus_return_val_if_fail (!message->locked, FALSE);
1371   
1372   if (interface == NULL)
1373     {
1374       delete_string_field (message, FIELD_INTERFACE);
1375       return TRUE;
1376     }
1377   else
1378     {
1379       return set_string_field (message,
1380                                FIELD_INTERFACE,
1381                                interface);
1382     }
1383 }
1384
1385 /**
1386  * Gets the interface this message is being sent to
1387  * (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted
1388  * from (for DBUS_MESSAGE_TYPE_SIGNAL).
1389  * The interface name is fully-qualified (namespaced).
1390  *
1391  * @param message the message
1392  * @returns the message interface (should not be freed)
1393  */
1394 const char*
1395 dbus_message_get_interface (DBusMessage *message)
1396 {
1397   _dbus_return_val_if_fail (message != NULL, NULL);
1398   
1399   return get_string_field (message, FIELD_INTERFACE, NULL);
1400 }
1401
1402 /**
1403  * Sets the interface member being invoked
1404  * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
1405  * (DBUS_MESSAGE_TYPE_SIGNAL).
1406  * The interface name is fully-qualified (namespaced).
1407  *
1408  * @param message the message
1409  * @param member the member
1410  * @returns #FALSE if not enough memory
1411  */
1412 dbus_bool_t
1413 dbus_message_set_member (DBusMessage  *message,
1414                        const char   *member)
1415 {
1416   _dbus_return_val_if_fail (message != NULL, FALSE);
1417   _dbus_return_val_if_fail (!message->locked, FALSE);
1418   
1419   if (member == NULL)
1420     {
1421       delete_string_field (message, FIELD_MEMBER);
1422       return TRUE;
1423     }
1424   else
1425     {
1426       return set_string_field (message,
1427                                FIELD_MEMBER,
1428                                member);
1429     }
1430 }
1431
1432 /**
1433  * Gets the interface member being invoked
1434  * (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted
1435  * (DBUS_MESSAGE_TYPE_SIGNAL).
1436  * 
1437  * @param message the message
1438  * @returns the member name (should not be freed)
1439  */
1440 const char*
1441 dbus_message_get_member (DBusMessage *message)
1442 {
1443   _dbus_return_val_if_fail (message != NULL, NULL);
1444   
1445   return get_string_field (message, FIELD_MEMBER, NULL);
1446 }
1447
1448 /**
1449  * Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
1450  * The name is fully-qualified (namespaced).
1451  *
1452  * @param message the message
1453  * @param name the name
1454  * @returns #FALSE if not enough memory
1455  */
1456 dbus_bool_t
1457 dbus_message_set_error_name (DBusMessage  *message,
1458                              const char   *error_name)
1459 {
1460   _dbus_return_val_if_fail (message != NULL, FALSE);
1461   _dbus_return_val_if_fail (!message->locked, FALSE);
1462   
1463   if (error_name == NULL)
1464     {
1465       delete_string_field (message, FIELD_ERROR_NAME);
1466       return TRUE;
1467     }
1468   else
1469     {
1470       return set_string_field (message,
1471                                FIELD_ERROR_NAME,
1472                                error_name);
1473     }
1474 }
1475
1476 /**
1477  * Gets the error name (DBUS_MESSAGE_TYPE_ERROR only).
1478  * 
1479  * @param message the message
1480  * @returns the error name (should not be freed)
1481  */
1482 const char*
1483 dbus_message_get_error_name (DBusMessage *message)
1484 {
1485   _dbus_return_val_if_fail (message != NULL, NULL);
1486   
1487   return get_string_field (message, FIELD_ERROR_NAME, NULL);
1488 }
1489
1490 /**
1491  * Sets the message's destination service.
1492  *
1493  * @param message the message
1494  * @param destination the destination service name
1495  * @returns #FALSE if not enough memory
1496  */
1497 dbus_bool_t
1498 dbus_message_set_destination (DBusMessage  *message,
1499                               const char   *destination)
1500 {
1501   _dbus_return_val_if_fail (message != NULL, FALSE);
1502   _dbus_return_val_if_fail (!message->locked, FALSE);
1503   
1504   if (destination == NULL)
1505     {
1506       delete_string_field (message, FIELD_SERVICE);
1507       return TRUE;
1508     }
1509   else
1510     {
1511       return set_string_field (message,
1512                                FIELD_SERVICE,
1513                                destination);
1514     }
1515 }
1516
1517 /**
1518  * Gets the destination service of a message.
1519  * 
1520  * @param message the message
1521  * @returns the message destination service (should not be freed)
1522  */
1523 const char*
1524 dbus_message_get_destination (DBusMessage *message)
1525 {
1526   _dbus_return_val_if_fail (message != NULL, NULL);
1527   
1528   return get_string_field (message, FIELD_SERVICE, NULL);
1529 }
1530
1531 /**
1532  * Appends fields to a message given a variable argument list. The
1533  * variable argument list should contain the type of the argument
1534  * followed by the value to add.  Array values are specified by an int
1535  * typecode followed by a pointer to the array followed by an int
1536  * giving the length of the array.  The argument list must be
1537  * terminated with #DBUS_TYPE_INVALID.
1538  *
1539  * This function doesn't support dicts or non-fundamental arrays.
1540  *
1541  * This function supports #DBUS_TYPE_INT64 and #DBUS_TYPE_UINT64
1542  * only if #DBUS_HAVE_INT64 is defined.
1543  *
1544  * @param message the message
1545  * @param first_arg_type type of the first argument
1546  * @param ... value of first argument, list of additional type-value pairs
1547  * @returns #TRUE on success
1548  */
1549 dbus_bool_t
1550 dbus_message_append_args (DBusMessage *message,
1551                           int first_arg_type,
1552                           ...)
1553 {
1554   dbus_bool_t retval;
1555   va_list var_args;
1556
1557   _dbus_return_val_if_fail (message != NULL, FALSE);
1558   
1559   va_start (var_args, first_arg_type);
1560   retval = dbus_message_append_args_valist (message,
1561                                             first_arg_type,
1562                                             var_args);
1563   va_end (var_args);
1564
1565   return retval;
1566 }
1567
1568 /**
1569  * This function takes a va_list for use by language bindings.
1570  * It's otherwise the same as dbus_message_append_args().
1571  *
1572  * @todo: Shouldn't this function clean up the changes to the message
1573  *        on failures? (Yes)
1574   
1575  * @see dbus_message_append_args.  
1576  * @param message the message
1577  * @param first_arg_type type of first argument
1578  * @param var_args value of first argument, then list of type/value pairs
1579  * @returns #TRUE on success
1580  */
1581 dbus_bool_t
1582 dbus_message_append_args_valist (DBusMessage *message,
1583                                  int          first_arg_type,
1584                                  va_list      var_args)
1585 {
1586   int type, old_len;
1587   DBusMessageIter iter;
1588
1589   _dbus_return_val_if_fail (message != NULL, FALSE);
1590   
1591   old_len = _dbus_string_get_length (&message->body);
1592   
1593   type = first_arg_type;
1594
1595   dbus_message_append_iter_init (message, &iter);
1596   
1597   while (type != 0)
1598     {
1599       switch (type)
1600         {
1601         case DBUS_TYPE_NIL:
1602           if (!dbus_message_iter_append_nil (&iter))
1603             goto errorout;
1604           break;
1605         case DBUS_TYPE_BOOLEAN:
1606           if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
1607             goto errorout;
1608           break;
1609         case DBUS_TYPE_INT32:
1610           if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
1611             goto errorout;
1612           break;
1613         case DBUS_TYPE_UINT32:
1614           if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
1615             goto errorout;          
1616           break;
1617 #ifdef DBUS_HAVE_INT64
1618         case DBUS_TYPE_INT64:
1619           if (!dbus_message_iter_append_int64 (&iter, va_arg (var_args, dbus_int64_t)))
1620             goto errorout;
1621           break;
1622         case DBUS_TYPE_UINT64:
1623           if (!dbus_message_iter_append_uint64 (&iter, va_arg (var_args, dbus_uint64_t)))
1624             goto errorout;          
1625           break;
1626 #endif /* DBUS_HAVE_INT64 */
1627         case DBUS_TYPE_DOUBLE:
1628           if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
1629             goto errorout;
1630           break;
1631         case DBUS_TYPE_STRING:
1632           if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
1633             goto errorout;
1634           break;
1635         case DBUS_TYPE_NAMED:
1636           {
1637             const char *name;
1638             unsigned char *data;
1639             int len;
1640  
1641             name = va_arg (var_args, const char *);
1642             data = va_arg (var_args, unsigned char *);
1643             len = va_arg (var_args, int);
1644
1645             if (!dbus_message_iter_append_named (&iter, name, data, len))
1646               goto errorout;
1647             break;
1648           }
1649         case DBUS_TYPE_ARRAY:
1650           {
1651             void *data;
1652             int len, type;
1653  
1654             type = va_arg (var_args, int);
1655             data = va_arg (var_args, void *);
1656             len = va_arg (var_args, int);
1657
1658             switch (type)
1659               {
1660               case DBUS_TYPE_BYTE:
1661                 if (!dbus_message_iter_append_byte_array (&iter, (unsigned char *)data, len))
1662                   goto errorout;
1663                 break;
1664               case DBUS_TYPE_BOOLEAN:
1665                 if (!dbus_message_iter_append_boolean_array (&iter, (unsigned char *)data, len))
1666                   goto errorout;
1667                 break;
1668               case DBUS_TYPE_INT32:
1669                 if (!dbus_message_iter_append_int32_array (&iter, (dbus_int32_t *)data, len))
1670                   goto errorout;
1671                 break;
1672               case DBUS_TYPE_UINT32:
1673                 if (!dbus_message_iter_append_uint32_array (&iter, (dbus_uint32_t *)data, len))
1674                   goto errorout;
1675                 break;
1676 #ifdef DBUS_HAVE_INT64
1677               case DBUS_TYPE_INT64:
1678                 if (!dbus_message_iter_append_int64_array (&iter, (dbus_int64_t *)data, len))
1679                   goto errorout;
1680                 break;
1681               case DBUS_TYPE_UINT64:
1682                 if (!dbus_message_iter_append_uint64_array (&iter, (dbus_uint64_t *)data, len))
1683                   goto errorout;
1684                 break;
1685 #endif /* DBUS_HAVE_INT64 */
1686               case DBUS_TYPE_DOUBLE:
1687                 if (!dbus_message_iter_append_double_array (&iter, (double *)data, len))
1688                   goto errorout;
1689                 break;
1690               case DBUS_TYPE_STRING:
1691                 if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
1692                   goto errorout;
1693                 break;
1694               case DBUS_TYPE_NIL:
1695               case DBUS_TYPE_ARRAY:
1696               case DBUS_TYPE_NAMED:
1697               case DBUS_TYPE_DICT:
1698                 _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
1699                 goto errorout;
1700               default:
1701                 _dbus_warn ("Unknown field type %d\n", type);
1702                 goto errorout;
1703               }
1704           }
1705           break;
1706           
1707         case DBUS_TYPE_DICT:
1708           _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
1709           goto errorout;
1710         default:
1711           _dbus_warn ("Unknown field type %d\n", type);
1712           goto errorout;
1713         }
1714
1715       type = va_arg (var_args, int);
1716     }
1717
1718   return TRUE;
1719
1720  errorout:
1721   return FALSE;
1722 }
1723
1724
1725 /**
1726  * Gets arguments from a message given a variable argument list.
1727  * The variable argument list should contain the type of the
1728  * argumen followed by a pointer to where the value should be
1729  * stored. The list is terminated with #DBUS_TYPE_INVALID.
1730  *
1731  * @param message the message
1732  * @param error error to be filled in on failure
1733  * @param first_arg_type the first argument type
1734  * @param ... location for first argument value, then list of type-location pairs
1735  * @returns #FALSE if the error was set
1736  */
1737 dbus_bool_t
1738 dbus_message_get_args (DBusMessage     *message,
1739                        DBusError       *error,
1740                        int              first_arg_type,
1741                        ...)
1742 {
1743   dbus_bool_t retval;
1744   va_list var_args;
1745
1746   _dbus_return_val_if_fail (message != NULL, FALSE);
1747   _dbus_return_val_if_error_is_set (error, FALSE);
1748   
1749   va_start (var_args, first_arg_type);
1750   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
1751   va_end (var_args);
1752
1753   return retval;
1754 }
1755
1756 /**
1757  * This function takes a va_list for use by language bindings
1758  *
1759  * @todo We need to free the argument data when an error occurs.
1760  *
1761  * @see dbus_message_get_args
1762  * @param message the message
1763  * @param error error to be filled in
1764  * @param first_arg_type type of the first argument
1765  * @param var_args return location for first argument, followed by list of type/location pairs
1766  * @returns #FALSE if error was set
1767  */
1768 dbus_bool_t
1769 dbus_message_get_args_valist (DBusMessage     *message,
1770                               DBusError       *error,
1771                               int              first_arg_type,
1772                               va_list          var_args)
1773 {
1774   DBusMessageIter iter;
1775
1776   _dbus_return_val_if_fail (message != NULL, FALSE);
1777   _dbus_return_val_if_error_is_set (error, FALSE);
1778   
1779   dbus_message_iter_init (message, &iter);
1780   return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
1781 }
1782
1783 /**
1784  * Gets arguments from a message iterator given a variable argument list.
1785  * The variable argument list should contain the type of the
1786  * argumen followed by a pointer to where the value should be
1787  * stored. The list is terminated with 0.
1788  *
1789  * @param iter the message iterator 
1790  * @param error error to be filled in on failure
1791  * @param first_arg_type the first argument type
1792  * @param ... location for first argument value, then list of type-location pairs
1793  * @returns #FALSE if the error was set
1794  */
1795 dbus_bool_t
1796 dbus_message_iter_get_args (DBusMessageIter *iter,
1797                             DBusError       *error,
1798                             int              first_arg_type,
1799                             ...)
1800 {
1801   dbus_bool_t retval;
1802   va_list var_args;
1803
1804   _dbus_return_val_if_fail (iter != NULL, FALSE);
1805   _dbus_return_val_if_error_is_set (error, FALSE);
1806   
1807   va_start (var_args, first_arg_type);
1808   retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
1809   va_end (var_args);
1810
1811   return retval;
1812 }
1813
1814 /**
1815  * This function takes a va_list for use by language bindings
1816  *
1817  * This function supports #DBUS_TYPE_INT64 and #DBUS_TYPE_UINT64
1818  * only if #DBUS_HAVE_INT64 is defined.
1819  *
1820  * @todo this function (or some lower-level non-convenience function)
1821  * needs better error handling; should allow the application to
1822  * distinguish between out of memory, and bad data from the remote
1823  * app. It also needs to not leak a bunch of args when it gets
1824  * to the arg that's bad, as that would be a security hole
1825  * (allow one app to force another to leak memory)
1826  *
1827  * @todo We need to free the argument data when an error occurs.
1828  *
1829  * @see dbus_message_get_args
1830  * @param iter the message iter
1831  * @param error error to be filled in
1832  * @param first_arg_type type of the first argument
1833  * @param var_args return location for first argument, followed by list of type/location pairs
1834  * @returns #FALSE if error was set
1835  */
1836 dbus_bool_t
1837 dbus_message_iter_get_args_valist (DBusMessageIter *iter,
1838                                    DBusError       *error,
1839                                    int              first_arg_type,
1840                                    va_list          var_args)
1841 {
1842   int spec_type, msg_type, i;
1843   dbus_bool_t retval;
1844
1845   _dbus_return_val_if_fail (iter != NULL, FALSE);
1846   _dbus_return_val_if_error_is_set (error, FALSE);
1847
1848   retval = FALSE;
1849   
1850   spec_type = first_arg_type;
1851   i = 0;
1852   
1853   while (spec_type != 0)
1854     {
1855       msg_type = dbus_message_iter_get_arg_type (iter);      
1856       
1857       if (msg_type != spec_type)
1858         {
1859           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1860                           "Argument %d is specified to be of type \"%s\", but "
1861                           "is actually of type \"%s\"\n", i,
1862                           _dbus_type_to_string (spec_type),
1863                           _dbus_type_to_string (msg_type));
1864
1865           goto out;
1866         }
1867
1868       switch (spec_type)
1869         {
1870         case DBUS_TYPE_NIL:
1871           break;
1872         case DBUS_TYPE_BYTE:
1873           {
1874             unsigned char *ptr;
1875
1876             ptr = va_arg (var_args, unsigned char *);
1877
1878             *ptr = dbus_message_iter_get_byte (iter);
1879             break;
1880           }
1881         case DBUS_TYPE_BOOLEAN:
1882           {
1883             dbus_bool_t *ptr;
1884
1885             ptr = va_arg (var_args, dbus_bool_t *);
1886
1887             *ptr = dbus_message_iter_get_boolean (iter);
1888             break;
1889           }
1890         case DBUS_TYPE_INT32:
1891           {
1892             dbus_int32_t *ptr;
1893
1894             ptr = va_arg (var_args, dbus_int32_t *);
1895
1896             *ptr = dbus_message_iter_get_int32 (iter);
1897             break;
1898           }
1899         case DBUS_TYPE_UINT32:
1900           {
1901             dbus_uint32_t *ptr;
1902
1903             ptr = va_arg (var_args, dbus_uint32_t *);
1904
1905             *ptr = dbus_message_iter_get_uint32 (iter);
1906             break;
1907           }
1908 #ifdef DBUS_HAVE_INT64
1909         case DBUS_TYPE_INT64:
1910           {
1911             dbus_int64_t *ptr;
1912
1913             ptr = va_arg (var_args, dbus_int64_t *);
1914
1915             *ptr = dbus_message_iter_get_int64 (iter);
1916             break;
1917           }
1918         case DBUS_TYPE_UINT64:
1919           {
1920             dbus_uint64_t *ptr;
1921
1922             ptr = va_arg (var_args, dbus_uint64_t *);
1923
1924             *ptr = dbus_message_iter_get_uint64 (iter);
1925             break;
1926           }
1927 #endif /* DBUS_HAVE_INT64 */
1928           
1929         case DBUS_TYPE_DOUBLE:
1930           {
1931             double *ptr;
1932
1933             ptr = va_arg (var_args, double *);
1934
1935             *ptr = dbus_message_iter_get_double (iter);
1936             break;
1937           }
1938
1939         case DBUS_TYPE_STRING:
1940           {
1941             char **ptr;
1942
1943             ptr = va_arg (var_args, char **);
1944
1945             *ptr = dbus_message_iter_get_string (iter);
1946
1947             if (!*ptr)
1948               {
1949                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1950                 goto out;
1951               }
1952             
1953             break;
1954           }
1955
1956         case DBUS_TYPE_NAMED:
1957           {
1958             char **name;
1959             unsigned char **data;
1960             int *len;
1961  
1962             name = va_arg (var_args, char **);
1963             data = va_arg (var_args, unsigned char **);
1964             len = va_arg (var_args, int *);
1965
1966             if (!dbus_message_iter_get_named (iter, name, data, len))
1967               {
1968                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1969                 goto out;
1970               }
1971           }
1972           break;
1973         case DBUS_TYPE_ARRAY:
1974           {
1975             void **data;
1976             int *len, type;
1977  
1978             type = va_arg (var_args, int);
1979             data = va_arg (var_args, void *);
1980             len = va_arg (var_args, int *);
1981
1982             if (dbus_message_iter_get_array_type (iter) != type)
1983               {
1984                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1985                                 "Argument %d is specified to be of type \"array of %s\", but "
1986                                 "is actually of type \"array of %s\"\n", i,
1987                                 _dbus_type_to_string (type),
1988                                 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
1989                 goto out;
1990               }
1991             
1992             switch (type)
1993               {
1994               case DBUS_TYPE_BYTE:
1995                 if (!dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len))
1996                   {
1997                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1998                     goto out;
1999                   }
2000                 break;
2001               case DBUS_TYPE_BOOLEAN:
2002                 if (!dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len))
2003                   {
2004                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2005                     goto out;
2006                   }
2007                 break;
2008               case DBUS_TYPE_INT32:
2009                 if (!dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len))
2010                   {
2011                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2012                     goto out;
2013                   }
2014                 break;
2015               case DBUS_TYPE_UINT32:
2016                 if (!dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len))
2017                   {
2018                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2019                     goto out;
2020                   }
2021                 break;
2022 #ifdef DBUS_HAVE_INT64
2023               case DBUS_TYPE_INT64:
2024                 if (!dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len))
2025                   {
2026                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2027                     goto out;
2028                   }
2029                 break;
2030               case DBUS_TYPE_UINT64:
2031                 if (!dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len))
2032                   {
2033                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2034                     goto out;
2035                   }
2036                 break;
2037 #endif /* DBUS_HAVE_INT64 */
2038               case DBUS_TYPE_DOUBLE:
2039                 if (!dbus_message_iter_get_double_array (iter, (double **)data, len))
2040                   {
2041                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2042                     goto out;
2043                   }
2044                 break;
2045               case DBUS_TYPE_STRING:
2046                 if (!dbus_message_iter_get_string_array (iter, (char ***)data, len))
2047                   {
2048                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2049                     goto out;
2050                   }
2051                 break;
2052               case DBUS_TYPE_NIL:
2053               case DBUS_TYPE_ARRAY:
2054               case DBUS_TYPE_NAMED:
2055               case DBUS_TYPE_DICT:
2056                 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
2057                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2058                 goto out;
2059               default:
2060                 _dbus_warn ("Unknown field type %d\n", type);
2061                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2062                 goto out;
2063               }
2064           }
2065           break;
2066         case DBUS_TYPE_DICT:
2067           _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
2068           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2069           goto out;
2070         default:          
2071           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2072           _dbus_warn ("Unknown field type %d\n", spec_type);
2073           goto out;
2074         }
2075       
2076       spec_type = va_arg (var_args, int);
2077       if (spec_type != 0 && !dbus_message_iter_next (iter))
2078         {
2079           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
2080                           "Message has only %d arguments, but more were expected", i);
2081           goto out;
2082         }
2083
2084       i++;
2085     }
2086   
2087   retval = TRUE;
2088   
2089  out:
2090   
2091   return retval;
2092 }
2093
2094
2095 /**
2096  * Initializes a DBusMessageIter representing the arguments of the
2097  * message passed in.
2098  *
2099  * @param message the message
2100  * @param iter pointer to an iterator to initialize
2101  */
2102 void
2103 dbus_message_iter_init (DBusMessage     *message,
2104                         DBusMessageIter *iter)
2105 {
2106   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2107
2108   _dbus_return_if_fail (message != NULL);
2109   _dbus_return_if_fail (iter != NULL);
2110   
2111   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
2112   
2113   real->message = message;
2114   real->parent_iter = NULL;
2115   real->changed_stamp = message->changed_stamp;
2116   
2117   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
2118   real->pos = 0;
2119   real->end = _dbus_string_get_length (&message->body);
2120   
2121   real->container_start = 0;
2122   real->container_length_pos = 0;
2123   real->wrote_dict_key = 0;
2124   real->array_type_pos = 0;
2125 }
2126
2127 #ifndef DBUS_DISABLE_CHECKS
2128 static dbus_bool_t
2129 dbus_message_iter_check (DBusMessageRealIter *iter)
2130 {
2131   if (iter == NULL)
2132     {
2133       _dbus_warn ("dbus iterator check failed: iterator is NULL\n");
2134       return FALSE;
2135     }
2136   
2137   if (iter->changed_stamp != iter->message->changed_stamp)
2138     {
2139       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message\n");
2140       return FALSE;
2141     }
2142   
2143   if (iter->pos < 0 || iter->pos > iter->end)
2144     {
2145       _dbus_warn ("dbus iterator check failed: invalid position\n");
2146       return FALSE;
2147     }
2148
2149   return TRUE;
2150 }
2151 #endif /* DBUS_DISABLE_CHECKS */
2152
2153 static int
2154 skip_array_type (DBusMessageRealIter *iter, int pos)
2155 {
2156   const char *data;
2157
2158   do
2159     {
2160       data = _dbus_string_get_const_data_len (&iter->message->body,
2161                                               pos++, 1);
2162     }
2163   while (*data == DBUS_TYPE_ARRAY);
2164   
2165   return pos;
2166 }
2167
2168 static int
2169 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
2170 {
2171   const char *data;
2172   int pos, len;
2173   
2174   switch (iter->type)
2175     {
2176     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
2177       data = _dbus_string_get_const_data_len (&iter->message->body,
2178                                               iter->pos, 1);
2179       if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
2180         *type = *data;
2181       else
2182         *type = DBUS_TYPE_INVALID;
2183       
2184       return skip_array_type (iter, iter->pos);
2185       
2186     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
2187       data = _dbus_string_get_const_data_len (&iter->message->body,
2188                                               iter->array_type_pos, 1);
2189       if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
2190         *type = *data;
2191       else
2192         *type = DBUS_TYPE_INVALID;
2193       
2194       return iter->pos;
2195       
2196     case DBUS_MESSAGE_ITER_TYPE_DICT:
2197       /* Get the length of the string */
2198       len = _dbus_demarshal_uint32 (&iter->message->body,
2199                                     iter->message->byte_order,
2200                                     iter->pos, &pos);
2201       pos = pos + len + 1;
2202
2203       data = _dbus_string_get_const_data_len (&iter->message->body,
2204                                               pos, 1);
2205       if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
2206         *type = *data;
2207       else
2208         *type = DBUS_TYPE_INVALID;
2209
2210       return skip_array_type (iter, pos);
2211       
2212     default:
2213       _dbus_assert_not_reached ("Invalid iter type");
2214       break;
2215     }
2216   *type = DBUS_TYPE_INVALID;
2217   return iter->pos;
2218 }
2219
2220
2221 /**
2222  * Checks if an iterator has any more fields.
2223  *
2224  * @param iter the message iter
2225  * @returns #TRUE if there are more fields
2226  * following
2227  */
2228 dbus_bool_t
2229 dbus_message_iter_has_next (DBusMessageIter *iter)
2230 {
2231   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2232   int end_pos;
2233   int type, pos;
2234
2235   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2236
2237   if (real->pos >= real->end)
2238     return FALSE;
2239   
2240   pos = dbus_message_iter_get_data_start (real, &type);
2241   
2242   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
2243                                       real->message->byte_order,
2244                                       type, pos, &end_pos))
2245     return FALSE;
2246   
2247   if (end_pos >= real->end)
2248     return FALSE;
2249
2250   return TRUE;  
2251 }
2252
2253 /**
2254  * Moves the iterator to the next field.
2255  *
2256  * @param iter The message iter
2257  * @returns #TRUE if the iterator was moved to the next field
2258  */
2259 dbus_bool_t
2260 dbus_message_iter_next (DBusMessageIter *iter)
2261 {
2262   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2263   int end_pos;
2264   int type, pos;
2265
2266   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2267
2268   pos = dbus_message_iter_get_data_start (real, &type);
2269   
2270   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
2271                                       real->message->byte_order,
2272                                       type, pos, &end_pos))
2273     return FALSE;
2274
2275   if (end_pos >= real->end)
2276     return FALSE;
2277
2278   real->pos = end_pos;
2279
2280   return TRUE;
2281 }
2282
2283 /**
2284  * Returns the argument type of the argument that the
2285  * message iterator points at.
2286  *
2287  * @param iter the message iter
2288  * @returns the field type
2289  */
2290 int
2291 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
2292 {
2293   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2294   int type, pos;
2295
2296   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2297
2298   if (real->pos >= real->end)
2299     return DBUS_TYPE_INVALID;
2300
2301   pos = dbus_message_iter_get_data_start (real, &type);
2302   
2303   return type;
2304 }
2305
2306 static int
2307 iter_get_array_type (DBusMessageRealIter *iter, int *array_type_pos)
2308 {
2309   const char *data;
2310   int _array_type_pos;
2311   int len, pos;
2312   
2313   switch (iter->type)
2314     {
2315     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
2316       _array_type_pos = iter->pos + 1;
2317       break;
2318     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
2319       _array_type_pos = iter->array_type_pos + 1;
2320       break;
2321     case DBUS_MESSAGE_ITER_TYPE_DICT:
2322       /* Get the length of the string */
2323       len = _dbus_demarshal_uint32 (&iter->message->body,
2324                                     iter->message->byte_order,
2325                                     iter->pos, &pos);
2326       pos = pos + len + 1;
2327       data = _dbus_string_get_const_data_len (&iter->message->body,
2328                                               pos + 1, 1);
2329       _array_type_pos = pos + 1;
2330       break;
2331     default:
2332       _dbus_assert_not_reached ("wrong iter type");
2333       return DBUS_TYPE_INVALID;
2334     }
2335
2336   if (array_type_pos != NULL)
2337     *array_type_pos = _array_type_pos;
2338   
2339   data = _dbus_string_get_const_data_len (&iter->message->body,
2340                                           _array_type_pos, 1);
2341   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
2342     return  *data;
2343   
2344   return DBUS_TYPE_INVALID;
2345 }
2346
2347
2348 /**
2349  * Returns the element type of the array that the
2350  * message iterator points at. Note that you need
2351  * to check that the iterator points to an array
2352  * prior to using this function.
2353  *
2354  * @param iter the message iter
2355  * @returns the field type
2356  */
2357 int
2358 dbus_message_iter_get_array_type (DBusMessageIter *iter)
2359 {
2360   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2361   int type, pos;
2362
2363   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2364
2365   if (real->pos >= real->end)
2366     return DBUS_TYPE_INVALID;
2367
2368   pos = dbus_message_iter_get_data_start (real, &type);
2369
2370   _dbus_assert (type == DBUS_TYPE_ARRAY);
2371
2372   return iter_get_array_type (real, NULL);
2373 }
2374
2375
2376 /**
2377  * Returns the string value that an iterator may point to.
2378  * Note that you need to check that the iterator points to
2379  * a string value before using this function.
2380  *
2381  * @see dbus_message_iter_get_arg_type
2382  * @param iter the message iter
2383  * @returns the string
2384  */
2385 char *
2386 dbus_message_iter_get_string (DBusMessageIter *iter)
2387 {
2388   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2389   int type, pos;
2390
2391   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
2392
2393   pos = dbus_message_iter_get_data_start (real, &type);
2394   
2395   _dbus_assert (type == DBUS_TYPE_STRING);
2396
2397   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
2398                                  pos, NULL);
2399 }
2400
2401 /**
2402  * Returns the name and data from a named type that an
2403  * iterator may point to. Note that you need to check that
2404  * the iterator points to a named type before using this
2405  * function.
2406  *
2407  * @see dbus_message_iter_get_arg_type
2408  * @param iter the message iter
2409  * @param name return location for the name
2410  * @param value return location for data
2411  * @param len return location for length of data
2412  * @returns TRUE if get succeed
2413  * 
2414  */
2415 dbus_bool_t
2416 dbus_message_iter_get_named (DBusMessageIter   *iter,
2417                              char             **name,
2418                              unsigned char    **value,
2419                              int               *len)
2420 {
2421   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2422   int type, pos;
2423   char *_name;
2424
2425   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2426
2427   pos = dbus_message_iter_get_data_start (real, &type);
2428   
2429   _dbus_assert (type == DBUS_TYPE_NAMED);
2430   
2431   _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
2432                                   pos, &pos);
2433
2434   if (_name == NULL)
2435     return FALSE;
2436   
2437   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
2438                                    pos + 1, NULL, value, len))
2439     {
2440       dbus_free (_name);
2441       return FALSE;
2442     }
2443
2444   *name = _name;
2445   
2446   return TRUE;
2447 }
2448
2449 /**
2450  * Returns the byte value that an iterator may point to.
2451  * Note that you need to check that the iterator points to
2452  * a byte value before using this function.
2453  *
2454  * @see dbus_message_iter_get_arg_type
2455  * @param iter the message iter
2456  * @returns the byte value
2457  */
2458 unsigned char
2459 dbus_message_iter_get_byte (DBusMessageIter *iter)
2460 {
2461   unsigned char value;
2462   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2463   int type, pos;
2464
2465   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
2466
2467   pos = dbus_message_iter_get_data_start (real, &type);
2468   
2469   _dbus_assert (type == DBUS_TYPE_BYTE);
2470
2471   value = _dbus_string_get_byte (&real->message->body, pos);
2472   
2473   return value;
2474 }
2475
2476
2477 /**
2478  * Returns the boolean value that an iterator may point to.
2479  * Note that you need to check that the iterator points to
2480  * a boolean value before using this function.
2481  *
2482  * @see dbus_message_iter_get_arg_type
2483  * @param iter the message iter
2484  * @returns the boolean value
2485  */
2486 dbus_bool_t
2487 dbus_message_iter_get_boolean (DBusMessageIter *iter)
2488 {
2489   unsigned char value;
2490   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2491   int type, pos;
2492
2493   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2494
2495   pos = dbus_message_iter_get_data_start (real, &type);
2496   
2497   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
2498
2499   value = _dbus_string_get_byte (&real->message->body, pos);
2500   
2501   return value;
2502 }
2503
2504 /**
2505  * Returns the 32 bit signed integer value that an iterator may point to.
2506  * Note that you need to check that the iterator points to
2507  * a 32-bit integer value before using this function.
2508  *
2509  * @see dbus_message_iter_get_arg_type
2510  * @param iter the message iter
2511  * @returns the integer
2512  */
2513 dbus_int32_t
2514 dbus_message_iter_get_int32 (DBusMessageIter *iter)
2515 {
2516   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2517   int type, pos;
2518
2519   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
2520
2521   pos = dbus_message_iter_get_data_start (real, &type);
2522   
2523   _dbus_assert (type == DBUS_TYPE_INT32);
2524   
2525   return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
2526                                 pos, NULL);
2527 }
2528
2529 /**
2530  * Returns the 32 bit unsigned integer value that an iterator may point to.
2531  * Note that you need to check that the iterator points to
2532  * a 32-bit unsigned integer value before using this function.
2533  *
2534  * @see dbus_message_iter_get_arg_type
2535  * @param iter the message iter
2536  * @returns the integer
2537  */
2538 dbus_uint32_t
2539 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
2540 {
2541   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2542   int type, pos;
2543
2544   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
2545
2546   pos = dbus_message_iter_get_data_start (real, &type);
2547   
2548   _dbus_assert (type == DBUS_TYPE_UINT32);
2549   
2550   return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
2551                                  pos, NULL);
2552 }
2553
2554 #ifdef DBUS_HAVE_INT64
2555
2556 /**
2557  * Returns the 64 bit signed integer value that an iterator may point
2558  * to.  Note that you need to check that the iterator points to a
2559  * 64-bit integer value before using this function.
2560  *
2561  * This function only exists if #DBUS_HAVE_INT64 is defined.
2562  *
2563  * @see dbus_message_iter_get_arg_type
2564  * @param iter the message iter
2565  * @returns the integer
2566  */
2567 dbus_int64_t
2568 dbus_message_iter_get_int64 (DBusMessageIter *iter)
2569 {
2570   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2571   int type, pos;
2572
2573   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
2574
2575   pos = dbus_message_iter_get_data_start (real, &type);
2576   
2577   _dbus_assert (type == DBUS_TYPE_INT64);
2578   
2579   return _dbus_demarshal_int64 (&real->message->body, real->message->byte_order,
2580                                 pos, NULL);
2581 }
2582
2583 /**
2584  * Returns the 64 bit unsigned integer value that an iterator may point to.
2585  * Note that you need to check that the iterator points to
2586  * a 64-bit unsigned integer value before using this function.
2587  * 
2588  * This function only exists if #DBUS_HAVE_INT64 is defined.
2589  * 
2590  * @see dbus_message_iter_get_arg_type
2591  * @param iter the message iter
2592  * @returns the integer
2593  */
2594 dbus_uint64_t
2595 dbus_message_iter_get_uint64 (DBusMessageIter *iter)
2596 {
2597   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2598   int type, pos;
2599
2600   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
2601
2602   pos = dbus_message_iter_get_data_start (real, &type);
2603   
2604   _dbus_assert (type == DBUS_TYPE_UINT64);
2605   
2606   return _dbus_demarshal_uint64 (&real->message->body, real->message->byte_order,
2607                                  pos, NULL);
2608 }
2609
2610 #endif /* DBUS_HAVE_INT64 */
2611
2612 /**
2613  * Returns the double value that an iterator may point to.
2614  * Note that you need to check that the iterator points to
2615  * a string value before using this function.
2616  *
2617  * @see dbus_message_iter_get_arg_type
2618  * @param iter the message iter
2619  * @returns the double
2620  */
2621 double
2622 dbus_message_iter_get_double (DBusMessageIter *iter)
2623 {
2624   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2625   int type, pos;
2626
2627   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0.0);
2628
2629   pos = dbus_message_iter_get_data_start (real, &type);
2630   
2631   _dbus_assert (type == DBUS_TYPE_DOUBLE);
2632   
2633   return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
2634                                  pos, NULL);
2635 }
2636
2637 /**
2638  * Initializes an iterator for the array that the iterator
2639  * may point to. Note that you need to check that the iterator
2640  * points to an array prior to using this function.
2641  *
2642  * The array element type is returned in array_type, and the array
2643  * iterator can only be used to get that type of data.
2644  *
2645  * @param iter the iterator
2646  * @param array_iter pointer to an iterator to initialize
2647  * @param array_type gets set to the type of the array elements
2648  * @returns #TRUE on success
2649  */
2650 dbus_bool_t
2651 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
2652                                        DBusMessageIter *array_iter,
2653                                        int             *array_type)
2654 {
2655   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2656   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
2657   int type, pos, len_pos, len, array_type_pos;
2658   int _array_type;
2659
2660   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2661
2662   pos = dbus_message_iter_get_data_start (real, &type);
2663   
2664   _dbus_assert (type == DBUS_TYPE_ARRAY);
2665
2666   _array_type = iter_get_array_type (real, &array_type_pos);
2667   
2668   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
2669   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
2670                                 pos, &pos);
2671   
2672   array_real->parent_iter = real;
2673   array_real->message = real->message;
2674   array_real->changed_stamp = real->message->changed_stamp;
2675   
2676   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
2677   array_real->pos = pos;
2678   array_real->end = pos + len;
2679   
2680   array_real->container_start = pos;
2681   array_real->container_length_pos = len_pos;
2682   array_real->wrote_dict_key = 0;
2683   array_real->array_type_pos = array_type_pos;
2684   array_real->array_type_done = TRUE;
2685   
2686   if (array_type != NULL)
2687     *array_type = _array_type;
2688   
2689   return TRUE;
2690 }
2691
2692
2693 /**
2694  * Initializes an iterator for the dict that the iterator
2695  * may point to. Note that you need to check that the iterator
2696  * points to a dict prior to using this function.
2697  *
2698  * @param iter the iterator
2699  * @param dict_iter pointer to an iterator to initialize
2700  * @returns #TRUE on success
2701  */
2702 dbus_bool_t
2703 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
2704                                       DBusMessageIter *dict_iter)
2705 {
2706   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2707   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
2708   int type, pos, len_pos, len;
2709
2710   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2711
2712   pos = dbus_message_iter_get_data_start (real, &type);
2713   
2714   _dbus_assert (type == DBUS_TYPE_DICT);
2715
2716   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
2717   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
2718                                 pos, &pos);
2719   
2720   dict_real->parent_iter = real;
2721   dict_real->message = real->message;
2722   dict_real->changed_stamp = real->message->changed_stamp;
2723   
2724   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
2725   dict_real->pos = pos;
2726   dict_real->end = pos + len;
2727   
2728   dict_real->container_start = pos;
2729   dict_real->container_length_pos = len_pos;
2730   dict_real->wrote_dict_key = 0;
2731
2732   return TRUE;
2733 }
2734
2735 /**
2736  * Returns the byte array that the iterator may point to.
2737  * Note that you need to check that the iterator points
2738  * to a byte array prior to using this function.
2739  *
2740  * @param iter the iterator
2741  * @param value return location for array values
2742  * @param len return location for length of byte array
2743  * @returns #TRUE on success
2744  */
2745 dbus_bool_t
2746 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
2747                                   unsigned char   **value,
2748                                   int              *len)
2749 {
2750   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2751   int type, pos;
2752
2753   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2754
2755   pos = dbus_message_iter_get_data_start (real, &type);
2756   
2757   _dbus_assert (type == DBUS_TYPE_ARRAY);
2758
2759   type = iter_get_array_type (real, NULL);
2760
2761   _dbus_assert (type == DBUS_TYPE_BYTE);
2762
2763   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
2764                                    pos, NULL, value, len))
2765     return FALSE;
2766   else
2767     return TRUE;
2768 }
2769
2770 /**
2771  * Returns the boolean array that the iterator may point to. Note that
2772  * you need to check that the iterator points to an array of the
2773  * correct type prior to using this function.
2774  *
2775  * @param iter the iterator
2776  * @param value return location for the array
2777  * @param len return location for the array length
2778  * @returns #TRUE on success
2779  */
2780 dbus_bool_t
2781 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
2782                                      unsigned char    **value,
2783                                      int               *len)
2784 {
2785   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2786   int type, pos;
2787
2788   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2789
2790   pos = dbus_message_iter_get_data_start (real, &type);
2791   
2792   _dbus_assert (type == DBUS_TYPE_ARRAY);
2793
2794   type = iter_get_array_type (real, NULL);
2795
2796   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
2797
2798   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
2799                                    pos, NULL, value, len))
2800     return FALSE;
2801   else
2802     return TRUE;
2803 }
2804
2805 /**
2806  * Returns the 32 bit signed integer array that the iterator may point
2807  * to. Note that you need to check that the iterator points to an
2808  * array of the correct type prior to using this function.
2809  *
2810  * @param iter the iterator
2811  * @param value return location for the array
2812  * @param len return location for the array length
2813  * @returns #TRUE on success
2814  */
2815 dbus_bool_t
2816 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
2817                                     dbus_int32_t   **value,
2818                                     int             *len)
2819 {
2820   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2821   int type, pos;
2822
2823   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2824
2825   pos = dbus_message_iter_get_data_start (real, &type);
2826   
2827   _dbus_assert (type == DBUS_TYPE_ARRAY);
2828
2829   type = iter_get_array_type (real, NULL);
2830   
2831   _dbus_assert (type == DBUS_TYPE_INT32);
2832
2833   if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
2834                                     pos, NULL, value, len))
2835     return FALSE;
2836   else
2837     return TRUE;
2838 }
2839
2840 /**
2841  * Returns the 32 bit unsigned integer array that the iterator may point
2842  * to. Note that you need to check that the iterator points to an
2843  * array of the correct type prior to using this function.
2844  *
2845  * @param iter the iterator
2846  * @param value return location for the array
2847  * @param len return location for the array length
2848  * @returns #TRUE on success
2849  */
2850 dbus_bool_t
2851 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
2852                                      dbus_uint32_t  **value,
2853                                      int             *len)
2854 {
2855   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2856   int type, pos;
2857
2858   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2859
2860   pos = dbus_message_iter_get_data_start (real, &type);
2861   
2862   _dbus_assert (type == DBUS_TYPE_ARRAY);
2863
2864   type = iter_get_array_type (real, NULL);
2865   _dbus_assert (type == DBUS_TYPE_UINT32);
2866
2867   if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
2868                                     pos, NULL, value, len))
2869     return FALSE;
2870   else
2871     return TRUE;
2872 }
2873
2874 #ifdef DBUS_HAVE_INT64
2875
2876 /**
2877  * Returns the 64 bit signed integer array that the iterator may point
2878  * to. Note that you need to check that the iterator points to an
2879  * array of the correct type prior to using this function.
2880  * 
2881  * This function only exists if #DBUS_HAVE_INT64 is defined.
2882  *
2883  * @param iter the iterator
2884  * @param value return location for the array
2885  * @param len return location for the array length
2886  * @returns #TRUE on success
2887  */
2888 dbus_bool_t
2889 dbus_message_iter_get_int64_array  (DBusMessageIter *iter,
2890                                     dbus_int64_t   **value,
2891                                     int             *len)
2892 {
2893   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2894   int type, pos;
2895
2896   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2897
2898   pos = dbus_message_iter_get_data_start (real, &type);
2899   
2900   _dbus_assert (type == DBUS_TYPE_ARRAY);
2901
2902   type = iter_get_array_type (real, NULL);
2903   
2904   _dbus_assert (type == DBUS_TYPE_INT64);
2905
2906   if (!_dbus_demarshal_int64_array (&real->message->body, real->message->byte_order,
2907                                     pos, NULL, value, len))
2908     return FALSE;
2909   else
2910     return TRUE;
2911 }
2912
2913 /**
2914  * Returns the 64 bit unsigned integer array that the iterator may point
2915  * to. Note that you need to check that the iterator points to an
2916  * array of the correct type prior to using this function.
2917  *
2918  * This function only exists if #DBUS_HAVE_INT64 is defined.
2919  *
2920  * @param iter the iterator
2921  * @param value return location for the array
2922  * @param len return location for the array length
2923  * @returns #TRUE on success
2924  */
2925 dbus_bool_t
2926 dbus_message_iter_get_uint64_array  (DBusMessageIter *iter,
2927                                      dbus_uint64_t  **value,
2928                                      int             *len)
2929 {
2930   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2931   int type, pos;
2932
2933   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2934
2935   pos = dbus_message_iter_get_data_start (real, &type);
2936   
2937   _dbus_assert (type == DBUS_TYPE_ARRAY);
2938
2939   type = iter_get_array_type (real, NULL);
2940   _dbus_assert (type == DBUS_TYPE_UINT64);
2941
2942   if (!_dbus_demarshal_uint64_array (&real->message->body, real->message->byte_order,
2943                                     pos, NULL, value, len))
2944     return FALSE;
2945   else
2946     return TRUE;
2947 }
2948
2949 #endif /* DBUS_HAVE_INT64 */
2950
2951 /**
2952  * Returns the double array that the iterator may point to. Note that
2953  * you need to check that the iterator points to an array of the
2954  * correct type prior to using this function.
2955  *
2956  * @param iter the iterator
2957  * @param value return location for the array
2958  * @param len return location for the array length
2959  * @returns #TRUE on success
2960  */
2961 dbus_bool_t
2962 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
2963                                      double         **value,
2964                                      int             *len)
2965 {
2966   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2967   int type, pos;
2968
2969   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2970
2971   pos = dbus_message_iter_get_data_start (real, &type);
2972   
2973   _dbus_assert (type == DBUS_TYPE_ARRAY);
2974
2975   type = iter_get_array_type (real, NULL);
2976   _dbus_assert (type == DBUS_TYPE_DOUBLE);
2977
2978   if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
2979                                      pos, NULL, value, len))
2980     return FALSE;
2981   else
2982     return TRUE;
2983 }
2984
2985 /**
2986  * Returns the string array that the iterator may point to.
2987  * Note that you need to check that the iterator points
2988  * to a byte array prior to using this function.
2989  *
2990  * The returned value is a #NULL-terminated array of strings.
2991  * Each string is a separate malloc block, and the array
2992  * itself is a malloc block. You can free this type of
2993  * string array with dbus_free_string_array().
2994  *
2995  * @param iter the iterator
2996  * @param value return location for string values
2997  * @param len return location for length of byte array
2998  * @returns #TRUE on success
2999  */
3000 dbus_bool_t
3001 dbus_message_iter_get_string_array (DBusMessageIter *iter,
3002                                     char          ***value,
3003                                     int             *len)
3004 {
3005   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3006   int type, pos;
3007
3008   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3009
3010   pos = dbus_message_iter_get_data_start (real, &type);
3011   
3012   _dbus_assert (type == DBUS_TYPE_ARRAY);
3013
3014   type = iter_get_array_type (real, NULL);
3015   _dbus_assert (type == DBUS_TYPE_STRING);
3016
3017   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
3018                                      pos, NULL, value, len))
3019     return FALSE;
3020   else
3021     return TRUE;
3022 }
3023
3024 /**
3025  * Returns the key name fot the dict entry that an iterator
3026  * may point to. Note that you need to check that the iterator
3027  * points to a dict entry before using this function.
3028  *
3029  * @see dbus_message_iter_init_dict_iterator
3030  * @param iter the message iter
3031  * @returns the key name
3032  */
3033 char *
3034 dbus_message_iter_get_dict_key (DBusMessageIter   *iter)
3035 {
3036   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3037
3038   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
3039
3040   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
3041
3042   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
3043                                  real->pos, NULL);
3044 }
3045
3046 /**
3047  * Initializes a DBusMessageIter pointing to the end of the
3048  * message. This iterator can be used to append data to the
3049  * message.
3050  *
3051  * @param message the message
3052  * @param iter pointer to an iterator to initialize
3053  */
3054 void
3055 dbus_message_append_iter_init (DBusMessage     *message,
3056                                DBusMessageIter *iter)
3057 {
3058   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3059
3060   _dbus_return_if_fail (message != NULL);
3061   _dbus_return_if_fail (iter != NULL);
3062   
3063   real->message = message;
3064   real->parent_iter = NULL;
3065   real->changed_stamp = message->changed_stamp;
3066   
3067   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
3068   real->end = _dbus_string_get_length (&real->message->body);
3069   real->pos = real->end;
3070   
3071   real->container_length_pos = 0;
3072   real->wrote_dict_key = 0;
3073 }
3074
3075 #ifndef DBUS_DISABLE_CHECKS
3076 static dbus_bool_t
3077 dbus_message_iter_append_check (DBusMessageRealIter *iter)
3078 {
3079   if (iter == NULL)
3080     {
3081       _dbus_warn ("dbus iterator check failed: NULL iterator\n");
3082       return FALSE;
3083     }
3084   
3085   if (iter->message->locked)
3086     {
3087       _dbus_warn ("dbus iterator check failed: message is locked (has already been sent)\n");
3088       return FALSE;
3089     }
3090       
3091   if (iter->changed_stamp != iter->message->changed_stamp)
3092     {
3093       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message");
3094       return FALSE;
3095     }
3096   
3097   if (iter->pos != iter->end)
3098     {
3099       _dbus_warn ("dbus iterator check failed: can only append at end of message");
3100       return FALSE;
3101     }
3102   
3103   if (iter->pos != _dbus_string_get_length (&iter->message->body))
3104     {
3105       _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
3106       return FALSE;
3107     }
3108
3109   return TRUE;
3110 }
3111 #endif /* DBUS_DISABLE_CHECKS */
3112
3113 static dbus_bool_t
3114 dbus_message_iter_append_type (DBusMessageRealIter *iter,
3115                                int                  type)
3116 {
3117   const char *data;
3118   switch (iter->type)
3119     {
3120     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
3121       if (!_dbus_string_append_byte (&iter->message->body, type))
3122         return FALSE;
3123       break;
3124       
3125     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
3126       data = _dbus_string_get_const_data_len (&iter->message->body,
3127                                               iter->array_type_pos, 1);
3128       if (type != *data)
3129         {
3130           _dbus_warn ("Appended element of wrong type for array\n");
3131           return FALSE;
3132         }
3133       break;
3134       
3135     case DBUS_MESSAGE_ITER_TYPE_DICT:
3136       if (!iter->wrote_dict_key)
3137         {
3138           _dbus_warn ("Appending dict data before key name\n");
3139           return FALSE;
3140         }
3141       
3142       if (!_dbus_string_append_byte (&iter->message->body, type))
3143         return FALSE;
3144       
3145       break;
3146       
3147     default:
3148       _dbus_assert_not_reached ("Invalid iter type");
3149       break;
3150     }
3151   
3152   return TRUE;
3153 }
3154
3155 static void
3156 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
3157 {
3158   iter->changed_stamp = iter->message->changed_stamp;
3159   
3160   /* Set new end of iter */
3161   iter->end = _dbus_string_get_length (&iter->message->body);
3162   iter->pos = iter->end;
3163
3164   /* Set container length */
3165   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
3166       (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
3167     _dbus_marshal_set_uint32 (&iter->message->body,
3168                               iter->message->byte_order,
3169                               iter->container_length_pos,
3170                               iter->end - iter->container_start);
3171   
3172   if (iter->parent_iter)
3173     dbus_message_iter_update_after_change (iter->parent_iter);
3174 }
3175
3176 static void
3177 dbus_message_iter_append_done (DBusMessageRealIter *iter)
3178 {
3179   iter->message->changed_stamp++;
3180   dbus_message_iter_update_after_change (iter);
3181   iter->wrote_dict_key = FALSE;
3182 }
3183
3184 /**
3185  * Appends a nil value to the message
3186  *
3187  * @param iter an iterator pointing to the end of the message
3188  * @returns #TRUE on success
3189  */
3190 dbus_bool_t
3191 dbus_message_iter_append_nil (DBusMessageIter *iter)
3192 {
3193   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3194
3195   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3196
3197   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
3198     return FALSE;
3199   
3200   dbus_message_iter_append_done (real);
3201   
3202   return TRUE;
3203 }
3204
3205 /**
3206  * Appends a boolean value to the message
3207  *
3208  * @param iter an iterator pointing to the end of the message
3209  * @param value the boolean value
3210  * @returns #TRUE on success
3211  */
3212 dbus_bool_t
3213 dbus_message_iter_append_boolean (DBusMessageIter *iter,
3214                                   dbus_bool_t     value)
3215 {
3216   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3217
3218   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3219
3220   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
3221     return FALSE;
3222   
3223   if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
3224     {
3225       _dbus_string_set_length (&real->message->body, real->pos);
3226       return FALSE;
3227     }
3228
3229   dbus_message_iter_append_done (real);
3230   
3231   return TRUE;
3232 }
3233
3234 /**
3235  * Appends a byte to the message
3236  *
3237  * @param iter an iterator pointing to the end of the message
3238  * @param value the byte value
3239  * @returns #TRUE on success
3240  */
3241 dbus_bool_t
3242 dbus_message_iter_append_byte (DBusMessageIter *iter,
3243                                unsigned char    value)
3244 {
3245   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3246
3247   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3248
3249   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BYTE))
3250     return FALSE;
3251   
3252   if (!_dbus_string_append_byte (&real->message->body, value))
3253     {
3254       _dbus_string_set_length (&real->message->body, real->pos);
3255       return FALSE;
3256     }
3257
3258   dbus_message_iter_append_done (real);
3259   
3260   return TRUE;
3261 }
3262
3263
3264 /**
3265  * Appends a 32 bit signed integer to the message.
3266  *
3267  * @param iter an iterator pointing to the end of the message
3268  * @param value the integer value
3269  * @returns #TRUE on success
3270  */
3271 dbus_bool_t
3272 dbus_message_iter_append_int32   (DBusMessageIter *iter,
3273                                   dbus_int32_t  value)
3274 {
3275   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3276
3277   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3278
3279   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT32))
3280     return FALSE;
3281   
3282   if (!_dbus_marshal_int32 (&real->message->body, real->message->byte_order, value))
3283     {
3284       _dbus_string_set_length (&real->message->body, real->pos);
3285       return FALSE;
3286     }
3287
3288   dbus_message_iter_append_done (real);
3289   
3290   return TRUE;
3291 }
3292
3293 /**
3294  * Appends a 32 bit unsigned integer to the message.
3295  *
3296  * @param iter an iterator pointing to the end of the message
3297  * @param value the integer value
3298  * @returns #TRUE on success
3299  */
3300 dbus_bool_t
3301 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
3302                                  dbus_uint32_t    value)
3303 {
3304   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3305
3306   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3307
3308   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
3309     return FALSE;
3310   
3311   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
3312     {
3313       _dbus_string_set_length (&real->message->body, real->pos);
3314       return FALSE;
3315     }
3316
3317   dbus_message_iter_append_done (real);
3318   
3319   return TRUE;
3320 }
3321
3322 #ifdef DBUS_HAVE_INT64
3323
3324 /**
3325  * Appends a 64 bit signed integer to the message.
3326  *
3327  * This function only exists if #DBUS_HAVE_INT64 is defined.
3328  *
3329  * @param iter an iterator pointing to the end of the message
3330  * @param value the integer value
3331  * @returns #TRUE on success
3332  */
3333 dbus_bool_t
3334 dbus_message_iter_append_int64   (DBusMessageIter *iter,
3335                                   dbus_int64_t  value)
3336 {
3337   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3338
3339   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3340
3341   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT64))
3342     return FALSE;
3343   
3344   if (!_dbus_marshal_int64 (&real->message->body, real->message->byte_order, value))
3345     {
3346       _dbus_string_set_length (&real->message->body, real->pos);
3347       return FALSE;
3348     }
3349
3350   dbus_message_iter_append_done (real);
3351   
3352   return TRUE;
3353 }
3354
3355 /**
3356  * Appends a 64 bit unsigned integer to the message.
3357  *
3358  * This function only exists if #DBUS_HAVE_INT64 is defined.
3359  *
3360  * @param iter an iterator pointing to the end of the message
3361  * @param value the integer value
3362  * @returns #TRUE on success
3363  */
3364 dbus_bool_t
3365 dbus_message_iter_append_uint64 (DBusMessageIter *iter,
3366                                  dbus_uint64_t    value)
3367 {
3368   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3369
3370   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3371
3372   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT64))
3373     return FALSE;
3374   
3375   if (!_dbus_marshal_uint64 (&real->message->body, real->message->byte_order, value))
3376     {
3377       _dbus_string_set_length (&real->message->body, real->pos);
3378       return FALSE;
3379     }
3380
3381   dbus_message_iter_append_done (real);
3382   
3383   return TRUE;
3384 }
3385
3386 #endif /* DBUS_HAVE_INT64 */
3387
3388 /**
3389  * Appends a double value to the message.
3390  *
3391  * @param iter an iterator pointing to the end of the message
3392  * @param value the double value
3393  * @returns #TRUE on success
3394  */
3395 dbus_bool_t
3396 dbus_message_iter_append_double (DBusMessageIter *iter,
3397                                  double           value)
3398 {
3399   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3400
3401   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3402
3403   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
3404     return FALSE;
3405   
3406   if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
3407     {
3408       _dbus_string_set_length (&real->message->body, real->pos);
3409       return FALSE;
3410     }
3411
3412   dbus_message_iter_append_done (real);
3413   
3414   return TRUE;
3415 }
3416
3417 /**
3418  * Appends a UTF-8 string to the message.
3419  *
3420  * @param iter an iterator pointing to the end of the message
3421  * @param value the string
3422  * @returns #TRUE on success
3423  */
3424 dbus_bool_t
3425 dbus_message_iter_append_string (DBusMessageIter *iter,
3426                                  const char      *value)
3427 {
3428   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3429
3430   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3431
3432   if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
3433     return FALSE;
3434   
3435   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
3436     {
3437       _dbus_string_set_length (&real->message->body, real->pos);
3438       return FALSE;
3439     }
3440
3441   dbus_message_iter_append_done (real);
3442   
3443   return TRUE;
3444 }
3445
3446 /**
3447  * Appends a named type data chunk to the message. A named
3448  * type is simply an arbitrary UTF-8 string used as a type
3449  * tag, plus an array of arbitrary bytes to be interpreted
3450  * according to the type tag.
3451  *
3452  * @param iter an iterator pointing to the end of the message
3453  * @param name the name of the type
3454  * @param data the binary data used to store the value
3455  * @param len the length of the binary data in bytes
3456  * @returns #TRUE on success
3457  */
3458 dbus_bool_t
3459 dbus_message_iter_append_named (DBusMessageIter      *iter,
3460                                 const char           *name,
3461                                 const unsigned char  *data,
3462                                 int                   len)
3463 {
3464   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3465
3466   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3467
3468   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NAMED))
3469     return FALSE;
3470   
3471    if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
3472     {
3473       _dbus_string_set_length (&real->message->body, real->pos);
3474       return FALSE;
3475     }
3476    
3477   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
3478     {
3479       _dbus_string_set_length (&real->message->body, real->pos);
3480       return FALSE;
3481     }
3482
3483   dbus_message_iter_append_done (real);
3484   
3485   return TRUE;
3486 }
3487
3488
3489 /**
3490  * Appends a dict key name to the message. The iterator used
3491  * must point to a dict.
3492  *
3493  * @param iter an iterator pointing to the end of the message
3494  * @param value the string
3495  * @returns #TRUE on success
3496  */
3497 dbus_bool_t
3498 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
3499                                    const char      *value)
3500 {
3501   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3502
3503   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3504   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
3505   
3506   if (real->wrote_dict_key)
3507     {
3508       _dbus_warn ("Appendinging multiple dict key names\n");
3509       return FALSE;
3510     }
3511   
3512   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
3513     {
3514       return FALSE;
3515     }
3516
3517   dbus_message_iter_append_done (real);
3518   real->wrote_dict_key = TRUE;
3519   
3520   return TRUE;
3521 }
3522
3523 static dbus_bool_t
3524 array_iter_type_mark_done (DBusMessageRealIter *iter)
3525 {
3526   int len_pos;
3527   
3528   if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
3529     array_iter_type_mark_done (iter->parent_iter);
3530   else
3531     return TRUE;
3532
3533   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
3534                                sizeof (dbus_uint32_t));
3535
3536   /* Empty length for now, backfill later */
3537   if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
3538     {
3539       _dbus_string_set_length (&iter->message->body, iter->pos);
3540       return FALSE;
3541     }
3542
3543   iter->container_start = _dbus_string_get_length (&iter->message->body);
3544   iter->container_length_pos = len_pos;
3545   iter->array_type_done = TRUE;
3546
3547   return TRUE;
3548 }
3549
3550 static dbus_bool_t
3551 append_array_type (DBusMessageRealIter *real,
3552                    int                  element_type,
3553                    dbus_bool_t         *array_type_done,
3554                    int                 *array_type_pos)
3555 {
3556   int existing_element_type;
3557   
3558   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
3559     return FALSE;
3560   
3561   if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
3562       real->array_type_done)
3563     {
3564       existing_element_type = iter_get_array_type (real, array_type_pos);
3565       if (existing_element_type != element_type)
3566         {
3567           _dbus_warn ("Appending array of %s, when expecting array of %s\n",
3568                       _dbus_type_to_string (element_type),
3569                       _dbus_type_to_string (existing_element_type));
3570           _dbus_string_set_length (&real->message->body, real->pos);
3571           return FALSE;
3572         }
3573       if (array_type_done != NULL)
3574           *array_type_done = TRUE;
3575     }
3576   else
3577     {
3578       if (array_type_pos != NULL)
3579         *array_type_pos = _dbus_string_get_length (&real->message->body);
3580       
3581       /* Append element type */
3582       if (!_dbus_string_append_byte (&real->message->body, element_type))
3583         {
3584           _dbus_string_set_length (&real->message->body, real->pos);
3585           return FALSE;
3586         }
3587
3588       if (array_type_done != NULL)
3589         *array_type_done = element_type != DBUS_TYPE_ARRAY;
3590       
3591       if (element_type != DBUS_TYPE_ARRAY &&
3592           !array_iter_type_mark_done (real))
3593         return FALSE;
3594     }
3595
3596   return TRUE;
3597 }
3598
3599 /**
3600  * Appends an array to the message and initializes an iterator that
3601  * can be used to append to the array.
3602  *
3603  * @param iter an iterator pointing to the end of the message
3604  * @param array_iter pointer to an iter that will be initialized
3605  * @param element_type the type of the array elements
3606  * @returns #TRUE on success
3607  */
3608 dbus_bool_t
3609 dbus_message_iter_append_array (DBusMessageIter      *iter,
3610                                 DBusMessageIter      *array_iter,
3611                                 int                   element_type)
3612 {
3613   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3614   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
3615   int len_pos;
3616   int array_type_pos;
3617   dbus_bool_t array_type_done;
3618
3619   if (element_type == DBUS_TYPE_NIL)
3620     {
3621       _dbus_warn ("Can't create NIL arrays\n");
3622       return FALSE;
3623     }
3624   
3625   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3626
3627   if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
3628     return FALSE;
3629
3630   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
3631
3632   if (array_type_done)
3633     {
3634       /* Empty length for now, backfill later */
3635       if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
3636         {
3637           _dbus_string_set_length (&real->message->body, real->pos);
3638           return FALSE;
3639         }
3640     }
3641   
3642   array_real->parent_iter = real;
3643   array_real->message = real->message;
3644   array_real->changed_stamp = real->message->changed_stamp;
3645   
3646   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
3647   array_real->pos = _dbus_string_get_length (&real->message->body);
3648   array_real->end = array_real->end;
3649   
3650   array_real->container_start = array_real->pos;
3651   array_real->container_length_pos = len_pos;
3652   array_real->wrote_dict_key = 0;
3653   array_real->array_type_done = array_type_done;
3654   array_real->array_type_pos = array_type_pos;
3655
3656   dbus_message_iter_append_done (array_real);
3657   
3658   return TRUE;
3659 }
3660
3661 /**
3662  * Appends a dict to the message and initializes an iterator that
3663  * can be used to append to the dict.
3664  *
3665  * @param iter an iterator pointing to the end of the message
3666  * @param dict_iter pointer to an iter that will be initialized
3667  * @returns #TRUE on success
3668  */
3669 dbus_bool_t
3670 dbus_message_iter_append_dict (DBusMessageIter      *iter,
3671                                DBusMessageIter      *dict_iter)
3672 {
3673   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3674   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
3675   int len_pos;
3676
3677   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3678
3679   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
3680     return FALSE;
3681
3682   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
3683
3684   /* Empty length for now, backfill later */
3685   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
3686     {
3687       _dbus_string_set_length (&real->message->body, real->pos);
3688       return FALSE;
3689     }
3690   
3691   dict_real->parent_iter = real;
3692   dict_real->message = real->message;
3693   dict_real->changed_stamp = real->message->changed_stamp;
3694   
3695   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
3696   dict_real->pos = _dbus_string_get_length (&real->message->body);
3697   dict_real->end = dict_real->end;
3698   
3699   dict_real->container_start = dict_real->pos;
3700   dict_real->container_length_pos = len_pos;
3701   dict_real->wrote_dict_key = 0;
3702
3703   dbus_message_iter_append_done (dict_real);
3704   
3705   return TRUE;
3706 }
3707
3708
3709 /**
3710  * Appends a boolean array to the message.
3711  *
3712  * @param iter an iterator pointing to the end of the message
3713  * @param value the array
3714  * @param len the length of the array
3715  * @returns #TRUE on success
3716  */
3717 dbus_bool_t
3718 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
3719                                         unsigned const char *value,
3720                                         int                  len)
3721 {
3722   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3723
3724   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3725
3726   if (!append_array_type (real, DBUS_TYPE_BOOLEAN, NULL, NULL))
3727     return FALSE;
3728   
3729   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
3730     {
3731       _dbus_string_set_length (&real->message->body, real->pos);
3732       return FALSE;
3733     }
3734
3735   dbus_message_iter_append_done (real);
3736   
3737   return TRUE;
3738 }
3739
3740 /**
3741  * Appends a 32 bit signed integer array to the message.
3742  *
3743  * @param iter an iterator pointing to the end of the message
3744  * @param value the array
3745  * @param len the length of the array
3746  * @returns #TRUE on success
3747  */
3748 dbus_bool_t
3749 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
3750                                       const dbus_int32_t *value,
3751                                       int                 len)
3752 {
3753   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3754
3755   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3756
3757   if (!append_array_type (real, DBUS_TYPE_INT32, NULL, NULL))
3758     return FALSE;
3759   
3760   if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
3761     {
3762       _dbus_string_set_length (&real->message->body, real->pos);
3763       return FALSE;
3764     }
3765
3766   dbus_message_iter_append_done (real);
3767   
3768   return TRUE;
3769 }
3770
3771 /**
3772  * Appends a 32 bit unsigned integer array to the message.
3773  *
3774  * @param iter an iterator pointing to the end of the message
3775  * @param value the array
3776  * @param len the length of the array
3777  * @returns #TRUE on success
3778  */
3779 dbus_bool_t
3780 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
3781                                        const dbus_uint32_t *value,
3782                                        int                  len)
3783 {
3784   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3785
3786   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3787
3788   if (!append_array_type (real, DBUS_TYPE_UINT32, NULL, NULL))
3789     return FALSE;
3790   
3791   if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
3792     {
3793       _dbus_string_set_length (&real->message->body, real->pos);
3794       return FALSE;
3795     }
3796
3797   dbus_message_iter_append_done (real);
3798   
3799   return TRUE;
3800 }
3801
3802 #ifdef DBUS_HAVE_INT64
3803
3804 /**
3805  * Appends a 64 bit signed integer array to the message.
3806  *
3807  * This function only exists if #DBUS_HAVE_INT64 is defined.
3808  *
3809  * @param iter an iterator pointing to the end of the message
3810  * @param value the array
3811  * @param len the length of the array
3812  * @returns #TRUE on success
3813  */
3814 dbus_bool_t
3815 dbus_message_iter_append_int64_array (DBusMessageIter    *iter,
3816                                       const dbus_int64_t *value,
3817                                       int                 len)
3818 {
3819   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3820
3821   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3822
3823   if (!append_array_type (real, DBUS_TYPE_INT64, NULL, NULL))
3824     return FALSE;
3825   
3826   if (!_dbus_marshal_int64_array (&real->message->body, real->message->byte_order, value, len))
3827     {
3828       _dbus_string_set_length (&real->message->body, real->pos);
3829       return FALSE;
3830     }
3831
3832   dbus_message_iter_append_done (real);
3833   
3834   return TRUE;
3835 }
3836
3837 /**
3838  * Appends a 64 bit unsigned integer array to the message.
3839  *
3840  * This function only exists if #DBUS_HAVE_INT64 is defined.
3841  *
3842  * @param iter an iterator pointing to the end of the message
3843  * @param value the array
3844  * @param len the length of the array
3845  * @returns #TRUE on success
3846  */
3847 dbus_bool_t
3848 dbus_message_iter_append_uint64_array (DBusMessageIter     *iter,
3849                                        const dbus_uint64_t *value,
3850                                        int                  len)
3851 {
3852   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3853
3854   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3855
3856   if (!append_array_type (real, DBUS_TYPE_UINT64, NULL, NULL))
3857     return FALSE;
3858   
3859   if (!_dbus_marshal_uint64_array (&real->message->body, real->message->byte_order, value, len))
3860     {
3861       _dbus_string_set_length (&real->message->body, real->pos);
3862       return FALSE;
3863     }
3864
3865   dbus_message_iter_append_done (real);
3866   
3867   return TRUE;
3868 }
3869 #endif /* DBUS_HAVE_INT64 */
3870
3871 /**
3872  * Appends a double array to the message.
3873  *
3874  * @param iter an iterator pointing to the end of the message
3875  * @param value the array
3876  * @param len the length of the array
3877  * @returns #TRUE on success
3878  */
3879 dbus_bool_t
3880 dbus_message_iter_append_double_array (DBusMessageIter *iter,
3881                                        const double    *value,
3882                                        int              len)
3883 {
3884   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3885
3886   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3887
3888   if (!append_array_type (real, DBUS_TYPE_DOUBLE, NULL, NULL))
3889     return FALSE;
3890   
3891   if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
3892     {
3893       _dbus_string_set_length (&real->message->body, real->pos);
3894       return FALSE;
3895     }
3896
3897   dbus_message_iter_append_done (real);
3898   
3899   return TRUE;
3900 }
3901
3902 /**
3903  * Appends a byte array to the message.
3904  *
3905  * @param iter an iterator pointing to the end of the message
3906  * @param value the array
3907  * @param len the length of the array
3908  * @returns #TRUE on success
3909  */
3910 dbus_bool_t
3911 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
3912                                      unsigned const char *value,
3913                                      int                  len)
3914 {
3915   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3916
3917   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3918
3919   if (!append_array_type (real, DBUS_TYPE_BYTE, NULL, NULL))
3920     return FALSE;
3921   
3922   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
3923     {
3924       _dbus_string_set_length (&real->message->body, real->pos);
3925       return FALSE;
3926     }
3927
3928   dbus_message_iter_append_done (real);
3929   
3930   return TRUE;
3931 }
3932
3933 /**
3934  * Appends a string array to the message.
3935  *
3936  * @param iter an iterator pointing to the end of the message
3937  * @param value the array
3938  * @param len the length of the array
3939  * @returns #TRUE on success
3940  */
3941 dbus_bool_t
3942 dbus_message_iter_append_string_array (DBusMessageIter *iter,
3943                                        const char     **value,
3944                                        int              len)
3945 {
3946   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3947
3948   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3949
3950   if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
3951     return FALSE;
3952   
3953   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
3954     {
3955       _dbus_string_set_length (&real->message->body, real->pos);
3956       return FALSE;
3957     }
3958
3959   dbus_message_iter_append_done (real);
3960   
3961   return TRUE;
3962 }
3963
3964 /**
3965  * Sets the message sender.
3966  *
3967  * @param message the message
3968  * @param sender the sender
3969  * @returns #FALSE if not enough memory
3970  */
3971 dbus_bool_t
3972 dbus_message_set_sender (DBusMessage  *message,
3973                          const char   *sender)
3974 {
3975   _dbus_return_val_if_fail (message != NULL, FALSE);
3976   _dbus_return_val_if_fail (!message->locked, FALSE);
3977
3978   if (sender == NULL)
3979     {
3980       delete_string_field (message, FIELD_SENDER);
3981       return TRUE;
3982     }
3983   else
3984     {
3985       return set_string_field (message,
3986                                FIELD_SENDER,
3987                                sender);
3988     }
3989 }
3990
3991 /**
3992  * Sets a flag indicating that the message does not want a reply; if
3993  * this flag is set, the other end of the connection may (but is not
3994  * required to) optimize by not sending method return or error
3995  * replies. If this flag is set, there is no way to know whether the
3996  * message successfully arrived at the remote end.
3997  *
3998  * @param message the message
3999  * @param no_reply #TRUE if no reply is desired
4000  */
4001 void
4002 dbus_message_set_no_reply (DBusMessage *message,
4003                            dbus_bool_t  no_reply)
4004 {
4005   char *header;
4006
4007   _dbus_return_if_fail (message != NULL);
4008   _dbus_return_if_fail (!message->locked);
4009   
4010   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
4011   
4012   if (no_reply)
4013     *header |= DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
4014   else
4015     *header &= ~DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;    
4016 }
4017
4018 /**
4019  * Returns #TRUE if the message does not expect
4020  * a reply.
4021  *
4022  * @param message the message
4023  * @returns #TRUE if the message sender isn't waiting for a reply
4024  */
4025 dbus_bool_t
4026 dbus_message_get_no_reply (DBusMessage *message)
4027 {
4028   const char *header;
4029
4030   _dbus_return_val_if_fail (message != NULL, FALSE);
4031   
4032   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
4033
4034   return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
4035 }
4036
4037 /**
4038  * Gets the service which originated this message,
4039  * or #NULL if unknown or inapplicable.
4040  *
4041  * @param message the message
4042  * @returns the service name or #NULL
4043  */
4044 const char*
4045 dbus_message_get_sender (DBusMessage *message)
4046 {
4047   _dbus_return_val_if_fail (message != NULL, NULL);
4048   
4049   return get_string_field (message, FIELD_SENDER, NULL);
4050 }
4051
4052 static dbus_bool_t
4053 _dbus_message_has_type_interface_member (DBusMessage *message,
4054                                          int          type,
4055                                          const char  *interface,
4056                                          const char  *method)
4057 {
4058   const char *n;
4059
4060   _dbus_assert (message != NULL);
4061   _dbus_assert (interface != NULL);
4062   _dbus_assert (method != NULL);
4063
4064   if (dbus_message_get_type (message) != type)
4065     return FALSE;
4066
4067   /* Optimize by checking the short method name first
4068    * instead of the longer interface name
4069    */  
4070
4071   n = dbus_message_get_member (message);
4072
4073   if (n && strcmp (n, method) == 0)
4074     {
4075       n = dbus_message_get_interface (message);
4076       
4077       if (n && strcmp (n, interface) == 0)
4078         return TRUE;
4079     }
4080
4081   return FALSE;
4082 }
4083
4084 /**
4085  * Checks whether the message is a method call with the given
4086  * interface and member fields.  If the message is not
4087  * #DBUS_MESSAGE_TYPE_METHOD_CALL, or has a different interface or member field,
4088  * returns #FALSE.
4089  *
4090  * @param message the message
4091  * @param interface the name to check (must not be #NULL)
4092  * @param method the name to check (must not be #NULL)
4093  * 
4094  * @returns #TRUE if the message is the specified method call
4095  */
4096 dbus_bool_t
4097 dbus_message_is_method_call (DBusMessage *message,
4098                              const char  *interface,
4099                              const char  *method)
4100 {
4101   _dbus_return_val_if_fail (message != NULL, FALSE);
4102   _dbus_return_val_if_fail (interface != NULL, FALSE);
4103   _dbus_return_val_if_fail (method != NULL, FALSE);
4104
4105   return _dbus_message_has_type_interface_member (message,
4106                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
4107                                                   interface, method);
4108 }
4109
4110 /**
4111  * Checks whether the message is a signal with the given
4112  * interface and member fields.  If the message is not
4113  * #DBUS_MESSAGE_TYPE_SIGNAL, or has a different interface or member field,
4114  * returns #FALSE.
4115  *
4116  * @param message the message
4117  * @param interface the name to check (must not be #NULL)
4118  * @param signal_name the name to check (must not be #NULL)
4119  * 
4120  * @returns #TRUE if the message is the specified signal
4121  */
4122 dbus_bool_t
4123 dbus_message_is_signal (DBusMessage *message,
4124                         const char  *interface,
4125                         const char  *signal_name)
4126 {
4127   _dbus_return_val_if_fail (message != NULL, FALSE);
4128   _dbus_return_val_if_fail (interface != NULL, FALSE);
4129   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
4130
4131   return _dbus_message_has_type_interface_member (message,
4132                                                   DBUS_MESSAGE_TYPE_SIGNAL,
4133                                                   interface, signal_name);
4134 }
4135
4136 /**
4137  * Checks whether the message is an error reply with the given error
4138  * name.  If the message is not #DBUS_MESSAGE_TYPE_ERROR, or has a
4139  * different name, returns #FALSE.
4140  *
4141  * @param message the message
4142  * @param error_name the name to check (must not be #NULL)
4143  * 
4144  * @returns #TRUE if the message is the specified error
4145  */
4146 dbus_bool_t
4147 dbus_message_is_error (DBusMessage *message,
4148                         const char  *error_name)
4149 {
4150   const char *n;
4151   
4152   _dbus_return_val_if_fail (message != NULL, FALSE);
4153   _dbus_return_val_if_fail (error_name != NULL, FALSE);
4154
4155   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
4156     return FALSE;
4157
4158   n = dbus_message_get_member (message);
4159
4160   if (n && strcmp (n, error_name) == 0)
4161     return TRUE;
4162   else
4163     return FALSE;
4164 }
4165
4166 /**
4167  * Checks whether the message was sent to the given service.  If the
4168  * message has no service specified or has a different name, returns
4169  * #FALSE.
4170  *
4171  * @param message the message
4172  * @param service the service to check (must not be #NULL)
4173  * 
4174  * @returns #TRUE if the message has the given destination service
4175  */
4176 dbus_bool_t
4177 dbus_message_has_destination (DBusMessage  *message,
4178                               const char   *service)
4179 {
4180   const char *s;
4181
4182   _dbus_return_val_if_fail (message != NULL, FALSE);
4183   _dbus_return_val_if_fail (service != NULL, FALSE);
4184   
4185   s = dbus_message_get_destination (message);
4186
4187   if (s && strcmp (s, service) == 0)
4188     return TRUE;
4189   else
4190     return FALSE;
4191 }
4192
4193 /**
4194  * Checks whether the message has the given service as its sender.  If
4195  * the message has no sender specified or has a different sender,
4196  * returns #FALSE. Note that if a peer application owns multiple
4197  * services, its messages will have only one of those services as the
4198  * sender (usually the base service). So you can't use this
4199  * function to prove the sender didn't own service Foo, you can
4200  * only use it to prove that it did.
4201  *
4202  * @param message the message
4203  * @param service the service to check (must not be #NULL)
4204  * 
4205  * @returns #TRUE if the message has the given origin service
4206  */
4207 dbus_bool_t
4208 dbus_message_has_sender (DBusMessage  *message,
4209                          const char   *service)
4210 {
4211   const char *s;
4212
4213   _dbus_assert (service != NULL);
4214   
4215   s = dbus_message_get_sender (message);
4216
4217   if (s && strcmp (s, service) == 0)
4218     return TRUE;
4219   else
4220     return FALSE;
4221 }
4222
4223 /**
4224  * Sets a #DBusError based on the contents of the given
4225  * message. The error is only set if the message
4226  * is an error message, as in DBUS_MESSAGE_TYPE_ERROR.
4227  * The name of the error is set to the name of the message,
4228  * and the error message is set to the first argument
4229  * if the argument exists and is a string.
4230  *
4231  * The return value indicates whether the error was set (the error is
4232  * set if and only if the message is an error message).
4233  * So you can check for an error reply and convert it to DBusError
4234  * in one go.
4235  *
4236  * @param error the error to set
4237  * @param message the message to set it from
4238  * @returns #TRUE if dbus_message_get_is_error() returns #TRUE for the message
4239  */
4240 dbus_bool_t
4241 dbus_set_error_from_message (DBusError   *error,
4242                              DBusMessage *message)
4243 {
4244   char *str;
4245
4246   _dbus_return_val_if_fail (message != NULL, FALSE);
4247   _dbus_return_val_if_error_is_set (error, FALSE);
4248   
4249   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
4250     return FALSE;
4251
4252   str = NULL;
4253   dbus_message_get_args (message, NULL,
4254                          DBUS_TYPE_STRING, &str,
4255                          DBUS_TYPE_INVALID);
4256
4257   dbus_set_error (error, dbus_message_get_error_name (message),
4258                   str ? "%s" : NULL, str);
4259
4260   dbus_free (str);
4261   
4262   return TRUE;
4263 }
4264
4265 /** @} */
4266
4267 /**
4268  * @addtogroup DBusMessageInternals
4269  *
4270  * @{
4271  */
4272 /**
4273  * @typedef DBusMessageLoader
4274  *
4275  * The DBusMessageLoader object encapsulates the process of converting
4276  * a byte stream into a series of DBusMessage. It buffers the incoming
4277  * bytes as efficiently as possible, and generates a queue of
4278  * messages. DBusMessageLoader is typically used as part of a
4279  * DBusTransport implementation. The DBusTransport then hands off
4280  * the loaded messages to a DBusConnection, making the messages
4281  * visible to the application.
4282  *
4283  * @todo write tests for break-loader that a) randomly delete header
4284  * fields and b) set string fields to zero-length and other funky
4285  * values.
4286  * 
4287  */
4288
4289 /* we definitely use signed ints for sizes, so don't exceed
4290  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
4291  * over 128M is pretty nuts anyhow.
4292  */
4293
4294 /**
4295  * The maximum sane message size.
4296  */
4297 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
4298
4299 /**
4300  * Implementation details of DBusMessageLoader.
4301  * All members are private.
4302  */
4303 struct DBusMessageLoader
4304 {
4305   int refcount;        /**< Reference count. */
4306
4307   DBusString data;     /**< Buffered data */
4308   
4309   DBusList *messages;  /**< Complete messages. */
4310
4311   long max_message_size; /**< Maximum size of a message */
4312   
4313   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
4314
4315   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
4316 };
4317
4318 /**
4319  * The initial buffer size of the message loader.
4320  * 
4321  * @todo this should be based on min header size plus some average
4322  * body size, or something. Or rather, the min header size only, if we
4323  * want to try to read only the header, store that in a DBusMessage,
4324  * then read only the body and store that, etc., depends on
4325  * how we optimize _dbus_message_loader_get_buffer() and what
4326  * the exact message format is.
4327  */
4328 #define INITIAL_LOADER_DATA_LEN 32
4329
4330 /**
4331  * Creates a new message loader. Returns #NULL if memory can't
4332  * be allocated.
4333  *
4334  * @returns new loader, or #NULL.
4335  */
4336 DBusMessageLoader*
4337 _dbus_message_loader_new (void)
4338 {
4339   DBusMessageLoader *loader;
4340
4341   loader = dbus_new0 (DBusMessageLoader, 1);
4342   if (loader == NULL)
4343     return NULL;
4344   
4345   loader->refcount = 1;
4346
4347   /* Try to cap message size at something that won't *totally* hose
4348    * the system if we have a couple of them.
4349    */
4350   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
4351   
4352   if (!_dbus_string_init (&loader->data))
4353     {
4354       dbus_free (loader);
4355       return NULL;
4356     }
4357
4358   /* preallocate the buffer for speed, ignore failure */
4359   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
4360   _dbus_string_set_length (&loader->data, 0);
4361   
4362   return loader;
4363 }
4364
4365 /**
4366  * Increments the reference count of the loader.
4367  *
4368  * @param loader the loader.
4369  */
4370 void
4371 _dbus_message_loader_ref (DBusMessageLoader *loader)
4372 {
4373   loader->refcount += 1;
4374 }
4375
4376 /**
4377  * Decrements the reference count of the loader and finalizes the
4378  * loader when the count reaches zero.
4379  *
4380  * @param loader the loader.
4381  */
4382 void
4383 _dbus_message_loader_unref (DBusMessageLoader *loader)
4384 {
4385   loader->refcount -= 1;
4386   if (loader->refcount == 0)
4387     {
4388       _dbus_list_foreach (&loader->messages,
4389                           (DBusForeachFunction) dbus_message_unref,
4390                           NULL);
4391       _dbus_list_clear (&loader->messages);
4392       _dbus_string_free (&loader->data);
4393       dbus_free (loader);
4394     }
4395 }
4396
4397 /**
4398  * Gets the buffer to use for reading data from the network.  Network
4399  * data is read directly into an allocated buffer, which is then used
4400  * in the DBusMessage, to avoid as many extra memcpy's as possible.
4401  * The buffer must always be returned immediately using
4402  * _dbus_message_loader_return_buffer(), even if no bytes are
4403  * successfully read.
4404  *
4405  * @todo this function can be a lot more clever. For example
4406  * it can probably always return a buffer size to read exactly
4407  * the body of the next message, thus avoiding any memory wastage
4408  * or reallocs.
4409  *
4410  * @todo we need to enforce a max length on strings in header fields.
4411  * 
4412  * @param loader the message loader.
4413  * @param buffer the buffer
4414  */
4415 void
4416 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
4417                                  DBusString        **buffer)
4418 {
4419   _dbus_assert (!loader->buffer_outstanding);
4420
4421   *buffer = &loader->data;
4422   
4423   loader->buffer_outstanding = TRUE;
4424 }
4425
4426 /**
4427  * The smallest header size that can occur. 
4428  * (It won't be valid)
4429  */
4430 #define DBUS_MINIMUM_HEADER_SIZE 16
4431
4432 /** Pack four characters as in "abcd" into a uint32 */
4433 #define FOUR_CHARS_TO_UINT32(a, b, c, d)                \
4434                       ((((dbus_uint32_t)a) << 24) |     \
4435                        (((dbus_uint32_t)b) << 16) |     \
4436                        (((dbus_uint32_t)c) << 8)  |     \
4437                        ((dbus_uint32_t)d))
4438
4439 /** DBUS_HEADER_FIELD_INTERFACE packed into a dbus_uint32_t */
4440 #define DBUS_HEADER_FIELD_INTERFACE_AS_UINT32    \
4441   FOUR_CHARS_TO_UINT32 ('i', 'f', 'c', 'e')
4442
4443 /** DBUS_HEADER_FIELD_MEMBER packed into a dbus_uint32_t */
4444 #define DBUS_HEADER_FIELD_MEMBER_AS_UINT32    \
4445   FOUR_CHARS_TO_UINT32 ('m', 'e', 'b', 'r')
4446
4447 /** DBUS_HEADER_FIELD_ERROR_NAME packed into a dbus_uint32_t */
4448 #define DBUS_HEADER_FIELD_ERROR_NAME_AS_UINT32    \
4449   FOUR_CHARS_TO_UINT32 ('e', 'r', 'n', 'm')
4450
4451 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
4452 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
4453   FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
4454
4455 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
4456 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32   \
4457   FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
4458
4459 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
4460 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32  \
4461   FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
4462
4463 static dbus_bool_t
4464 decode_string_field (const DBusString   *data,
4465                      HeaderField         fields[FIELD_LAST],
4466                      int                 pos,
4467                      int                 type,
4468                      int                 field,
4469                      const char         *field_name)
4470 {
4471   DBusString tmp;
4472   int string_data_pos;
4473   
4474   if (fields[field].offset >= 0)
4475     {
4476       _dbus_verbose ("%s field provided twice\n",
4477                      field_name);
4478       return FALSE;
4479     }
4480
4481   if (type != DBUS_TYPE_STRING)
4482     {
4483       _dbus_verbose ("%s field has wrong type %s\n",
4484                      field_name, _dbus_type_to_string (type));
4485       return FALSE;
4486     }
4487
4488   /* skip padding after typecode, skip string length;
4489    * we assume that the string arg has already been validated
4490    * for sanity and UTF-8
4491    */
4492   string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
4493   _dbus_assert (string_data_pos < _dbus_string_get_length (data));
4494   
4495   _dbus_string_init_const (&tmp,
4496                            _dbus_string_get_const_data (data) + string_data_pos);
4497
4498   if (field == FIELD_INTERFACE)
4499     {
4500       if (!_dbus_string_validate_interface (&tmp, 0, _dbus_string_get_length (&tmp)))
4501         {
4502           _dbus_verbose ("%s field has invalid content \"%s\"\n",
4503                          field_name, _dbus_string_get_const_data (&tmp));
4504           return FALSE;
4505         }
4506       
4507       if (_dbus_string_equal_c_str (&tmp,
4508                                     DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
4509         {
4510           _dbus_verbose ("Message is on the local interface\n");
4511           return FALSE;
4512         }
4513     }
4514   else if (field == FIELD_MEMBER)
4515     {
4516       if (!_dbus_string_validate_member (&tmp, 0, _dbus_string_get_length (&tmp)))
4517         {
4518           _dbus_verbose ("%s field has invalid content \"%s\"\n",
4519                          field_name, _dbus_string_get_const_data (&tmp));
4520           return FALSE;
4521         }
4522     }
4523   else if (field == FIELD_ERROR_NAME)
4524     {
4525       if (!_dbus_string_validate_error_name (&tmp, 0, _dbus_string_get_length (&tmp)))
4526         {
4527           _dbus_verbose ("%s field has invalid content \"%s\"\n",
4528                          field_name, _dbus_string_get_const_data (&tmp));
4529           return FALSE;
4530         }
4531     }
4532   else if (field == FIELD_SERVICE)
4533     {
4534       if (!_dbus_string_validate_service (&tmp, 0, _dbus_string_get_length (&tmp)))
4535         {
4536           _dbus_verbose ("%s field has invalid content \"%s\"\n",
4537                          field_name, _dbus_string_get_const_data (&tmp));
4538           return FALSE;
4539         }
4540     }
4541   else
4542     {
4543       _dbus_assert_not_reached ("Unknown field\n");
4544     }
4545   
4546   fields[field].offset = _DBUS_ALIGN_VALUE (pos, 4);
4547   
4548 #if 0
4549   _dbus_verbose ("Found field %s name at offset %d\n",
4550                  field_name, fields[field].offset);
4551 #endif
4552
4553   return TRUE;
4554 }
4555
4556 static dbus_bool_t
4557 decode_header_data (const DBusString   *data,
4558                     int                 header_len,
4559                     int                 byte_order,
4560                     int                 message_type,
4561                     HeaderField         fields[FIELD_LAST],
4562                     int                *message_padding)
4563 {
4564   const char *field;
4565   int pos, new_pos;
4566   int i;
4567   int type;
4568   
4569   if (header_len < 16)
4570     {
4571       _dbus_verbose ("Header length %d is too short\n", header_len);
4572       return FALSE;
4573     }
4574   
4575   i = 0;
4576   while (i < FIELD_LAST)
4577     {
4578       fields[i].offset = -1;
4579       ++i;
4580     }
4581   
4582   fields[FIELD_HEADER_LENGTH].offset = 4;
4583   fields[FIELD_BODY_LENGTH].offset = 8;   
4584   fields[FIELD_CLIENT_SERIAL].offset = 12;
4585   
4586   /* Now handle the named fields. A real named field is at least 4
4587    * bytes for the name, plus a type code (1 byte) plus padding.  So
4588    * if we have less than 8 bytes left, it must be alignment padding,
4589    * not a field. While >= 8 bytes can't be entirely alignment
4590    * padding.
4591    */  
4592   pos = 16;
4593   while ((pos + 7) < header_len)
4594     {
4595       pos = _DBUS_ALIGN_VALUE (pos, 4);
4596       
4597       if ((pos + 4) > header_len)
4598         {
4599           _dbus_verbose ("not enough space remains in header for header field value\n");
4600           return FALSE;
4601         }
4602       
4603       field =_dbus_string_get_const_data_len (data, pos, 4);
4604       pos += 4;
4605
4606       _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
4607       
4608       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
4609         {
4610           _dbus_verbose ("Failed to validate type of named header field\n");
4611           return FALSE;
4612         }
4613       
4614       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
4615         {
4616           _dbus_verbose ("Failed to validate argument to named header field\n");
4617           return FALSE;
4618         }
4619
4620       if (new_pos > header_len)
4621         {
4622           _dbus_verbose ("Named header field tries to extend beyond header length\n");
4623           return FALSE;
4624         }
4625       
4626       switch (DBUS_UINT32_FROM_BE (*(int*)field))
4627         {
4628         case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
4629           if (!decode_string_field (data, fields, pos, type,
4630                                     FIELD_SERVICE,
4631                                     DBUS_HEADER_FIELD_SERVICE))
4632             return FALSE;
4633           break;
4634
4635         case DBUS_HEADER_FIELD_INTERFACE_AS_UINT32:
4636           if (!decode_string_field (data, fields, pos, type,
4637                                     FIELD_INTERFACE,
4638                                     DBUS_HEADER_FIELD_INTERFACE))
4639             return FALSE;
4640           break;
4641
4642         case DBUS_HEADER_FIELD_MEMBER_AS_UINT32:
4643           if (!decode_string_field (data, fields, pos, type,
4644                                     FIELD_MEMBER,
4645                                     DBUS_HEADER_FIELD_MEMBER))
4646             return FALSE;
4647           break;
4648
4649         case DBUS_HEADER_FIELD_ERROR_NAME_AS_UINT32:
4650           if (!decode_string_field (data, fields, pos, type,
4651                                     FIELD_ERROR_NAME,
4652                                     DBUS_HEADER_FIELD_ERROR_NAME))
4653             return FALSE;
4654           break;
4655           
4656         case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
4657           if (!decode_string_field (data, fields, pos, type,
4658                                     FIELD_SENDER,
4659                                     DBUS_HEADER_FIELD_SENDER))
4660             return FALSE;
4661           break;
4662           
4663         case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
4664           if (fields[FIELD_REPLY_SERIAL].offset >= 0)
4665             {
4666               _dbus_verbose ("%s field provided twice\n",
4667                              DBUS_HEADER_FIELD_REPLY);
4668               return FALSE;
4669             }
4670
4671           if (type != DBUS_TYPE_UINT32)
4672             {
4673               _dbus_verbose ("%s field has wrong type\n", DBUS_HEADER_FIELD_REPLY);
4674               return FALSE;
4675             }
4676           
4677           fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos, 4);
4678
4679           _dbus_verbose ("Found reply serial at offset %d\n",
4680                          fields[FIELD_REPLY_SERIAL].offset);
4681           break;
4682
4683         default:
4684           _dbus_verbose ("Ignoring an unknown header field: %.4s at offset %d\n",
4685                          field, pos);
4686         }
4687       
4688       pos = new_pos;
4689     }
4690
4691   if (pos < header_len)
4692     {
4693       /* Alignment padding, verify that it's nul */
4694       _dbus_assert ((header_len - pos) < 8);
4695
4696       if (!_dbus_string_validate_nul (data,
4697                                       pos, (header_len - pos)))
4698         {
4699           _dbus_verbose ("header alignment padding is not nul\n");
4700           return FALSE;
4701         }
4702     }
4703
4704   /* Depending on message type, enforce presence of certain fields. */
4705   switch (message_type)
4706     {
4707     case DBUS_MESSAGE_TYPE_SIGNAL:
4708     case DBUS_MESSAGE_TYPE_METHOD_CALL:
4709       if (fields[FIELD_INTERFACE].offset < 0)
4710         {
4711           _dbus_verbose ("No %s field provided\n",
4712                          DBUS_HEADER_FIELD_INTERFACE);
4713           return FALSE;
4714         }
4715       if (fields[FIELD_MEMBER].offset < 0)
4716         {
4717           _dbus_verbose ("No %s field provided\n",
4718                          DBUS_HEADER_FIELD_MEMBER);
4719           return FALSE;
4720         }
4721       break;
4722     case DBUS_MESSAGE_TYPE_ERROR:
4723       if (fields[FIELD_ERROR_NAME].offset < 0)
4724         {
4725           _dbus_verbose ("No %s field provided\n",
4726                          DBUS_HEADER_FIELD_ERROR_NAME);
4727           return FALSE;
4728         }
4729       break;
4730     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
4731       break;
4732     default:
4733       /* An unknown type, spec requires us to ignore it */
4734       break;
4735     }
4736   
4737   if (message_padding)
4738     *message_padding = header_len - pos;  
4739   
4740   return TRUE;
4741 }
4742
4743 /**
4744  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
4745  * indicating to the loader how many bytes of the buffer were filled
4746  * in. This function must always be called, even if no bytes were
4747  * successfully read.
4748  *
4749  * @param loader the loader.
4750  * @param buffer the buffer.
4751  * @param bytes_read number of bytes that were read into the buffer.
4752  */
4753 void
4754 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
4755                                     DBusString         *buffer,
4756                                     int                 bytes_read)
4757 {
4758   _dbus_assert (loader->buffer_outstanding);
4759   _dbus_assert (buffer == &loader->data);
4760
4761   loader->buffer_outstanding = FALSE;
4762 }
4763
4764 /**
4765  * Converts buffered data into messages.
4766  *
4767  * @todo we need to check that the proper named header fields exist
4768  * for each message type.
4769  * 
4770  * @todo If a message has unknown type, we should probably eat it
4771  * right here rather than passing it out to applications.  However
4772  * it's not an error to see messages of unknown type.
4773  * 
4774  * @param loader the loader.
4775  * @returns #TRUE if we had enough memory to finish.
4776  */
4777 dbus_bool_t
4778 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
4779 {
4780   if (loader->corrupted)
4781     return TRUE;
4782
4783   while (_dbus_string_get_length (&loader->data) >= 16)
4784     {
4785       DBusMessage *message;      
4786       const char *header_data;
4787       int byte_order, message_type, header_len, body_len, header_padding;
4788       dbus_uint32_t header_len_unsigned, body_len_unsigned;
4789       
4790       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
4791
4792       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
4793
4794       if (header_data[VERSION_OFFSET] != DBUS_MAJOR_PROTOCOL_VERSION)
4795         {
4796           _dbus_verbose ("Message has protocol version %d ours is %d\n",
4797                          (int) header_data[VERSION_OFFSET], DBUS_MAJOR_PROTOCOL_VERSION);
4798           loader->corrupted = TRUE;
4799           return TRUE;
4800         }
4801       
4802       byte_order = header_data[BYTE_ORDER_OFFSET];
4803
4804       if (byte_order != DBUS_LITTLE_ENDIAN &&
4805           byte_order != DBUS_BIG_ENDIAN)
4806         {
4807           _dbus_verbose ("Message with bad byte order '%c' received\n",
4808                          byte_order);
4809           loader->corrupted = TRUE;
4810           return TRUE;
4811         }
4812
4813       /* Unknown types are ignored, but INVALID is
4814        * disallowed
4815        */
4816       message_type = header_data[TYPE_OFFSET];
4817       if (message_type == DBUS_MESSAGE_TYPE_INVALID)
4818         {
4819           _dbus_verbose ("Message with bad type '%d' received\n",
4820                          message_type);
4821           loader->corrupted = TRUE;
4822           return TRUE;
4823         }      
4824       
4825       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
4826       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
4827
4828       if (header_len_unsigned < 16)
4829         {
4830           _dbus_verbose ("Message had broken too-small header length %u\n",
4831                          header_len_unsigned);
4832           loader->corrupted = TRUE;
4833           return TRUE;
4834         }
4835
4836       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
4837           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
4838         {
4839           _dbus_verbose ("Header or body length too large (%u %u)\n",
4840                          header_len_unsigned,
4841                          body_len_unsigned);
4842           loader->corrupted = TRUE;
4843           return TRUE;
4844         }
4845
4846       /* Now that we know the values are in signed range, get
4847        * rid of stupid unsigned, just causes bugs
4848        */
4849       header_len = header_len_unsigned;
4850       body_len = body_len_unsigned;
4851
4852       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
4853         {
4854           
4855           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
4856                          header_len);
4857           loader->corrupted = TRUE;
4858           return TRUE;
4859         }
4860       
4861       if (header_len + body_len > loader->max_message_size)
4862         {
4863           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
4864                          header_len, body_len, loader->max_message_size);
4865           loader->corrupted = TRUE;
4866           return TRUE;
4867         }
4868
4869       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
4870         {
4871           HeaderField fields[FIELD_LAST];
4872           int i;
4873           int next_arg;          
4874
4875 #if 0
4876           _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);
4877 #endif    
4878           if (!decode_header_data (&loader->data,
4879                                    header_len, byte_order,
4880                                    message_type,
4881                                    fields, &header_padding))
4882             {
4883               _dbus_verbose ("Header was invalid\n");
4884               loader->corrupted = TRUE;
4885               return TRUE;
4886             }
4887           
4888           next_arg = header_len;
4889           while (next_arg < (header_len + body_len))
4890             {
4891               int type;
4892               int prev = next_arg;
4893
4894               if (!_dbus_marshal_validate_type (&loader->data, next_arg,
4895                                                 &type, &next_arg))
4896                 {
4897                   _dbus_verbose ("invalid typecode at offset %d\n", prev);
4898                   loader->corrupted = TRUE;
4899                   return TRUE;
4900                 }
4901       
4902               if (!_dbus_marshal_validate_arg (&loader->data,
4903                                                byte_order,
4904                                                0,
4905                                                type, -1,
4906                                                next_arg,
4907                                                &next_arg))
4908                 {
4909                   _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
4910                   loader->corrupted = TRUE;
4911                   return TRUE;
4912                 }
4913
4914               _dbus_assert (next_arg > prev);
4915             }
4916           
4917           if (next_arg > (header_len + body_len))
4918             {
4919               _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
4920                              next_arg, header_len, body_len,
4921                              header_len + body_len);
4922               loader->corrupted = TRUE;
4923               return TRUE;
4924             }
4925
4926           message = dbus_message_new_empty_header ();
4927           if (message == NULL)
4928             {
4929               _dbus_verbose ("Failed to allocate empty message\n");
4930               return FALSE;
4931             }
4932
4933           message->byte_order = byte_order;
4934           message->header_padding = header_padding;
4935           
4936           /* Copy in the offsets we found */
4937           i = 0;
4938           while (i < FIELD_LAST)
4939             {
4940               message->header_fields[i] = fields[i];
4941               ++i;
4942             }
4943           
4944           if (!_dbus_list_append (&loader->messages, message))
4945             {
4946               _dbus_verbose ("Failed to append new message to loader queue\n");
4947               dbus_message_unref (message);
4948               return FALSE;
4949             }
4950
4951           _dbus_assert (_dbus_string_get_length (&message->header) == 0);
4952           _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4953
4954           _dbus_assert (_dbus_string_get_length (&loader->data) >=
4955                         (header_len + body_len));
4956           
4957           if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
4958             {
4959               _dbus_verbose ("Failed to move header into new message\n");
4960               _dbus_list_remove_last (&loader->messages, message);
4961               dbus_message_unref (message);
4962               return FALSE;
4963             }
4964           
4965           if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
4966             {
4967               dbus_bool_t result;
4968
4969               _dbus_verbose ("Failed to move body into new message\n");
4970               
4971               /* put the header back, we'll try again later */
4972               result = _dbus_string_copy_len (&message->header, 0, header_len,
4973                                               &loader->data, 0);
4974               _dbus_assert (result); /* because DBusString never reallocs smaller */
4975
4976               _dbus_list_remove_last (&loader->messages, message);
4977               dbus_message_unref (message);
4978               return FALSE;
4979             }
4980
4981           _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
4982           _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4983
4984           /* Fill in caches (we checked the types of these fields
4985            * earlier)
4986            */
4987           message->reply_serial = get_uint_field (message,
4988                                                   FIELD_REPLY_SERIAL);
4989           message->client_serial = get_uint_field (message,
4990                                                    FIELD_CLIENT_SERIAL);
4991           
4992           _dbus_verbose ("Loaded message %p\n", message);
4993         }
4994       else
4995         return TRUE;
4996     }
4997
4998   return TRUE;
4999 }
5000
5001 /**
5002  * Peeks at first loaded message, returns #NULL if no messages have
5003  * been queued.
5004  *
5005  * @param loader the loader.
5006  * @returns the next message, or #NULL if none.
5007  */
5008 DBusMessage*
5009 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
5010 {
5011   if (loader->messages)
5012     return loader->messages->data;
5013   else
5014     return NULL;
5015 }
5016
5017 /**
5018  * Pops a loaded message (passing ownership of the message
5019  * to the caller). Returns #NULL if no messages have been
5020  * queued.
5021  *
5022  * @param loader the loader.
5023  * @returns the next message, or #NULL if none.
5024  */
5025 DBusMessage*
5026 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
5027 {
5028   return _dbus_list_pop_first (&loader->messages);
5029 }
5030
5031 /**
5032  * Pops a loaded message inside a list link (passing ownership of the
5033  * message and link to the caller). Returns #NULL if no messages have
5034  * been loaded.
5035  *
5036  * @param loader the loader.
5037  * @returns the next message link, or #NULL if none.
5038  */
5039 DBusList*
5040 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
5041 {
5042   return _dbus_list_pop_first_link (&loader->messages);
5043 }
5044
5045 /**
5046  * Returns a popped message link, used to undo a pop.
5047  *
5048  * @param loader the loader
5049  * @param link the link with a message in it
5050  */
5051 void
5052 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
5053                                            DBusList           *link)
5054 {
5055   _dbus_list_prepend_link (&loader->messages, link);
5056 }
5057
5058 /**
5059  * Checks whether the loader is confused due to bad data.
5060  * If messages are received that are invalid, the
5061  * loader gets confused and gives up permanently.
5062  * This state is called "corrupted."
5063  *
5064  * @param loader the loader
5065  * @returns #TRUE if the loader is hosed.
5066  */
5067 dbus_bool_t
5068 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
5069 {
5070   return loader->corrupted;
5071 }
5072
5073 /**
5074  * Sets the maximum size message we allow.
5075  *
5076  * @param loader the loader
5077  * @param size the max message size in bytes
5078  */
5079 void
5080 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
5081                                            long                size)
5082 {
5083   if (size > MAX_SANE_MESSAGE_SIZE)
5084     {
5085       _dbus_verbose ("clamping requested max message size %ld to %d\n",
5086                      size, MAX_SANE_MESSAGE_SIZE);
5087       size = MAX_SANE_MESSAGE_SIZE;
5088     }
5089   loader->max_message_size = size;
5090 }
5091
5092 /**
5093  * Gets the maximum allowed message size in bytes.
5094  *
5095  * @param loader the loader
5096  * @returns max size in bytes
5097  */
5098 long
5099 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
5100 {
5101   return loader->max_message_size;
5102 }
5103
5104 static DBusDataSlotAllocator slot_allocator;
5105 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
5106
5107 /**
5108  * Allocates an integer ID to be used for storing application-specific
5109  * data on any DBusMessage. The allocated ID may then be used
5110  * with dbus_message_set_data() and dbus_message_get_data().
5111  * The passed-in slot must be initialized to -1, and is filled in
5112  * with the slot ID. If the passed-in slot is not -1, it's assumed
5113  * to be already allocated, and its refcount is incremented.
5114  * 
5115  * The allocated slot is global, i.e. all DBusMessage objects will
5116  * have a slot with the given integer ID reserved.
5117  *
5118  * @param slot_p address of a global variable storing the slot
5119  * @returns #FALSE on failure (no memory)
5120  */
5121 dbus_bool_t
5122 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
5123 {
5124   return _dbus_data_slot_allocator_alloc (&slot_allocator,
5125                                           _DBUS_LOCK_NAME (message_slots),
5126                                           slot_p);
5127 }
5128
5129 /**
5130  * Deallocates a global ID for message data slots.
5131  * dbus_message_get_data() and dbus_message_set_data() may no
5132  * longer be used with this slot.  Existing data stored on existing
5133  * DBusMessage objects will be freed when the message is
5134  * finalized, but may not be retrieved (and may only be replaced if
5135  * someone else reallocates the slot).  When the refcount on the
5136  * passed-in slot reaches 0, it is set to -1.
5137  *
5138  * @param slot_p address storing the slot to deallocate
5139  */
5140 void
5141 dbus_message_free_data_slot (dbus_int32_t *slot_p)
5142 {
5143   _dbus_return_if_fail (*slot_p >= 0);
5144   
5145   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
5146 }
5147
5148 /**
5149  * Stores a pointer on a DBusMessage, along
5150  * with an optional function to be used for freeing
5151  * the data when the data is set again, or when
5152  * the message is finalized. The slot number
5153  * must have been allocated with dbus_message_allocate_data_slot().
5154  *
5155  * @param message the message
5156  * @param slot the slot number
5157  * @param data the data to store
5158  * @param free_data_func finalizer function for the data
5159  * @returns #TRUE if there was enough memory to store the data
5160  */
5161 dbus_bool_t
5162 dbus_message_set_data (DBusMessage     *message,
5163                        dbus_int32_t     slot,
5164                        void            *data,
5165                        DBusFreeFunction free_data_func)
5166 {
5167   DBusFreeFunction old_free_func;
5168   void *old_data;
5169   dbus_bool_t retval;
5170
5171   _dbus_return_val_if_fail (message != NULL, FALSE);
5172   _dbus_return_val_if_fail (slot >= 0, FALSE);
5173
5174   retval = _dbus_data_slot_list_set (&slot_allocator,
5175                                      &message->slot_list,
5176                                      slot, data, free_data_func,
5177                                      &old_free_func, &old_data);
5178
5179   if (retval)
5180     {
5181       /* Do the actual free outside the message lock */
5182       if (old_free_func)
5183         (* old_free_func) (old_data);
5184     }
5185
5186   return retval;
5187 }
5188
5189 /**
5190  * Retrieves data previously set with dbus_message_set_data().
5191  * The slot must still be allocated (must not have been freed).
5192  *
5193  * @param message the message
5194  * @param slot the slot to get data from
5195  * @returns the data, or #NULL if not found
5196  */
5197 void*
5198 dbus_message_get_data (DBusMessage   *message,
5199                        dbus_int32_t   slot)
5200 {
5201   void *res;
5202
5203   _dbus_return_val_if_fail (message != NULL, NULL);
5204   
5205   res = _dbus_data_slot_list_get (&slot_allocator,
5206                                   &message->slot_list,
5207                                   slot);
5208
5209   return res;
5210 }
5211
5212 /** @} */
5213 #ifdef DBUS_BUILD_TESTS
5214 #include "dbus-test.h"
5215 #include <stdio.h>
5216
5217 static void
5218 message_iter_test (DBusMessage *message)
5219 {
5220   DBusMessageIter iter, dict, array, array2;
5221   char *str;
5222   unsigned char *data;
5223   dbus_int32_t *our_int_array;
5224   int len;
5225   
5226   dbus_message_iter_init (message, &iter);
5227
5228   /* String tests */
5229   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
5230     _dbus_assert_not_reached ("Argument type isn't string");
5231
5232   str = dbus_message_iter_get_string (&iter);
5233   if (strcmp (str, "Test string") != 0)
5234     _dbus_assert_not_reached ("Strings differ");
5235   dbus_free (str);
5236
5237   if (!dbus_message_iter_next (&iter))
5238     _dbus_assert_not_reached ("Reached end of arguments");
5239
5240   /* Signed integer tests */
5241   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
5242     _dbus_assert_not_reached ("Argument type isn't int32");
5243
5244   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
5245     _dbus_assert_not_reached ("Signed integers differ");
5246
5247   if (!dbus_message_iter_next (&iter))
5248     _dbus_assert_not_reached ("Reached end of fields");
5249   
5250   /* Unsigned integer tests */
5251   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
5252     _dbus_assert_not_reached ("Argument type isn't int32");
5253
5254   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
5255     _dbus_assert_not_reached ("Unsigned integers differ");
5256
5257   if (!dbus_message_iter_next (&iter))
5258     _dbus_assert_not_reached ("Reached end of arguments");
5259
5260   /* Double tests */
5261   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
5262     _dbus_assert_not_reached ("Argument type isn't double");
5263
5264   if (dbus_message_iter_get_double (&iter) != 3.14159)
5265     _dbus_assert_not_reached ("Doubles differ");
5266
5267   if (!dbus_message_iter_next (&iter))
5268     _dbus_assert_not_reached ("Reached end of arguments");
5269
5270   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
5271     _dbus_assert_not_reached ("Argument type not an array");
5272
5273   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
5274     _dbus_assert_not_reached ("Array type not double");
5275
5276   
5277   if (!dbus_message_iter_init_array_iterator (&iter, &array, NULL))
5278     _dbus_assert_not_reached ("Array init failed");
5279
5280   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
5281     _dbus_assert_not_reached ("Argument type isn't double");
5282
5283   if (dbus_message_iter_get_double (&array) != 1.5)
5284     _dbus_assert_not_reached ("Unsigned integers differ");
5285
5286   if (!dbus_message_iter_next (&array))
5287     _dbus_assert_not_reached ("Reached end of arguments");
5288
5289   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
5290     _dbus_assert_not_reached ("Argument type isn't double");
5291
5292   if (dbus_message_iter_get_double (&array) != 2.5)
5293     _dbus_assert_not_reached ("Unsigned integers differ");
5294
5295   if (dbus_message_iter_next (&array))
5296     _dbus_assert_not_reached ("Didn't reach end of arguments");
5297   
5298   if (!dbus_message_iter_next (&iter))
5299     _dbus_assert_not_reached ("Reached end of arguments");
5300   
5301
5302   /* dict */
5303
5304   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
5305     _dbus_assert_not_reached ("not dict type");
5306      
5307   if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
5308     _dbus_assert_not_reached ("dict iter failed");
5309
5310   str = dbus_message_iter_get_dict_key (&dict);
5311   if (str == NULL || strcmp (str, "test") != 0)
5312     _dbus_assert_not_reached ("wrong dict key");
5313   dbus_free (str);
5314
5315   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
5316     _dbus_assert_not_reached ("wrong dict entry type");
5317
5318   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
5319     _dbus_assert_not_reached ("wrong dict entry value");
5320
5321   if (!dbus_message_iter_next (&dict))
5322     _dbus_assert_not_reached ("reached end of dict");
5323   
5324   /* array of array of int32 (in dict) */
5325
5326   str = dbus_message_iter_get_dict_key (&dict);
5327   if (str == NULL || strcmp (str, "array") != 0)
5328     _dbus_assert_not_reached ("wrong dict key");
5329   dbus_free (str);
5330   
5331   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
5332     _dbus_assert_not_reached ("Argument type not an array");
5333
5334   if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
5335     _dbus_assert_not_reached ("Array type not array");
5336
5337   if (!dbus_message_iter_init_array_iterator (&dict, &array, NULL))
5338     _dbus_assert_not_reached ("Array init failed");
5339
5340   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
5341     _dbus_assert_not_reached ("Argument type isn't array");
5342   
5343   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
5344     _dbus_assert_not_reached ("Array type not int32");
5345   
5346   if (!dbus_message_iter_init_array_iterator (&array, &array2, NULL))
5347     _dbus_assert_not_reached ("Array init failed");
5348
5349   if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
5350     _dbus_assert_not_reached ("Argument type isn't int32");
5351
5352   if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
5353     _dbus_assert_not_reached ("Signed integers differ");
5354
5355   if (!dbus_message_iter_next (&array2))
5356     _dbus_assert_not_reached ("Reached end of arguments");
5357
5358   if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
5359     _dbus_assert_not_reached ("Signed integers differ");
5360
5361   if (dbus_message_iter_next (&array2))
5362     _dbus_assert_not_reached ("Didn't reached end of arguments");
5363
5364   if (!dbus_message_iter_next (&array))
5365     _dbus_assert_not_reached ("Reached end of arguments");
5366
5367   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
5368     _dbus_assert_not_reached ("Array type not int32");
5369
5370   if (!dbus_message_iter_get_int32_array (&array,
5371                                           &our_int_array,
5372                                           &len))
5373     _dbus_assert_not_reached ("couldn't get int32 array");
5374
5375   _dbus_assert (len == 3);
5376   _dbus_assert (our_int_array[0] == 0x34567812 &&
5377                 our_int_array[1] == 0x45678123 &&
5378                 our_int_array[2] == 0x56781234);
5379   dbus_free (our_int_array);
5380   
5381   if (dbus_message_iter_next (&array))
5382     _dbus_assert_not_reached ("Didn't reach end of array");
5383
5384   if (dbus_message_iter_next (&dict))
5385     _dbus_assert_not_reached ("Didn't reach end of dict");
5386   
5387   if (!dbus_message_iter_next (&iter))
5388     _dbus_assert_not_reached ("Reached end of arguments");
5389   
5390   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BYTE)
5391     {
5392       _dbus_warn ("type was: %d\n", dbus_message_iter_get_arg_type (&iter));
5393       _dbus_assert_not_reached ("wrong type after dict (should be byte)");
5394     }
5395   
5396   if (dbus_message_iter_get_byte (&iter) != 0xF0)
5397     _dbus_assert_not_reached ("wrong value after dict");
5398
5399
5400   if (!dbus_message_iter_next (&iter))
5401     _dbus_assert_not_reached ("Reached end of arguments");
5402   
5403   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NIL)
5404     _dbus_assert_not_reached ("not a nil type");
5405   
5406   if (!dbus_message_iter_next (&iter))
5407     _dbus_assert_not_reached ("Reached end of arguments");
5408   
5409   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NAMED)
5410     _dbus_assert_not_reached ("wrong type after dict");
5411
5412   if (!dbus_message_iter_get_named (&iter, &str, &data, &len))
5413     _dbus_assert_not_reached ("failed to get named");
5414
5415   _dbus_assert (strcmp (str, "named")==0);
5416   _dbus_assert (len == 5);
5417   _dbus_assert (strcmp (data, "data")==0);
5418   dbus_free (str);
5419   dbus_free (data);
5420   
5421   if (dbus_message_iter_next (&iter))
5422     _dbus_assert_not_reached ("Didn't reach end of arguments");
5423 }
5424
5425
5426 static dbus_bool_t
5427 check_message_handling_type (DBusMessageIter *iter,
5428                              int type)
5429 {
5430   DBusMessageIter child_iter;
5431   
5432   switch (type)
5433     {
5434     case DBUS_TYPE_NIL:
5435       break;
5436     case DBUS_TYPE_BYTE:
5437       dbus_message_iter_get_byte (iter);
5438       break;
5439     case DBUS_TYPE_BOOLEAN:
5440       dbus_message_iter_get_boolean (iter);
5441       break;
5442     case DBUS_TYPE_INT32:
5443       dbus_message_iter_get_int32 (iter);
5444       break;
5445     case DBUS_TYPE_UINT32:
5446       dbus_message_iter_get_uint32 (iter);
5447       break;
5448     case DBUS_TYPE_INT64:
5449 #ifdef DBUS_HAVE_INT64
5450       dbus_message_iter_get_int64 (iter);
5451 #endif
5452       break;
5453     case DBUS_TYPE_UINT64:
5454 #ifdef DBUS_HAVE_INT64
5455       dbus_message_iter_get_uint64 (iter);
5456 #endif
5457       break;
5458     case DBUS_TYPE_DOUBLE:
5459       dbus_message_iter_get_double (iter);
5460       break;
5461     case DBUS_TYPE_STRING:
5462       {
5463         char *str;
5464         str = dbus_message_iter_get_string (iter);
5465         if (str == NULL)
5466           {
5467             _dbus_warn ("NULL string in message\n");
5468             return FALSE;
5469           }
5470         dbus_free (str);
5471       }
5472       break;
5473     case DBUS_TYPE_NAMED:
5474       {
5475         char *name;
5476         unsigned char *data;
5477         int len;
5478         
5479         if (!dbus_message_iter_get_named (iter, &name, &data, &len))
5480           {
5481             _dbus_warn ("error reading name from named type\n");
5482             return FALSE;
5483           }
5484         dbus_free (data);
5485         dbus_free (name);
5486       }
5487       break;
5488     case DBUS_TYPE_ARRAY:
5489       {
5490         int array_type;
5491
5492         if (!dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type))
5493           {
5494             _dbus_warn ("Failed to init array iterator\n");
5495             return FALSE;
5496           }
5497
5498         while (dbus_message_iter_has_next (&child_iter))
5499           {
5500             if (!check_message_handling_type (&child_iter, array_type))
5501               {
5502                 _dbus_warn ("error in array element\n");
5503                 return FALSE;
5504               }
5505             
5506             if (!dbus_message_iter_next (&child_iter))
5507               break;
5508           }
5509       }
5510       break;
5511     case DBUS_TYPE_DICT:
5512       {
5513         int entry_type;
5514         char *key;
5515         
5516         if (!dbus_message_iter_init_dict_iterator (iter, &child_iter))
5517           {
5518             _dbus_warn ("Failed to init dict iterator\n");
5519             return FALSE;
5520           }
5521
5522         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
5523           {
5524             key = dbus_message_iter_get_dict_key (&child_iter);
5525             if (key == NULL)
5526               {
5527                 _dbus_warn ("error reading dict key\n");
5528                 return FALSE;
5529               }
5530             dbus_free (key);
5531             
5532             if (!check_message_handling_type (&child_iter, entry_type))
5533               {
5534                 _dbus_warn ("error in dict value\n");
5535                 return FALSE;
5536               }
5537             
5538             if (!dbus_message_iter_next (&child_iter))
5539               break;
5540           }
5541       }
5542       break;
5543       
5544     default:
5545       _dbus_warn ("unknown type %d\n", type);
5546       return FALSE;
5547       break;
5548     }
5549   return TRUE;
5550 }
5551   
5552   
5553 static dbus_bool_t
5554 check_message_handling (DBusMessage *message)
5555 {
5556   DBusMessageIter iter;
5557   int type;
5558   dbus_bool_t retval;
5559   dbus_uint32_t client_serial;
5560   
5561   retval = FALSE;
5562   
5563   client_serial = dbus_message_get_serial (message);
5564
5565   /* can't use set_serial due to the assertions at the start of it */
5566   set_uint_field (message, FIELD_CLIENT_SERIAL,
5567                   client_serial);
5568   
5569   if (client_serial != dbus_message_get_serial (message))
5570     {
5571       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
5572       goto failed;
5573     }
5574   
5575   /* If we implement message_set_arg (message, n, value)
5576    * then we would want to test it here
5577    */
5578
5579   dbus_message_iter_init (message, &iter);
5580   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
5581     {
5582       if (!check_message_handling_type (&iter, type))
5583         goto failed;
5584
5585       if (!dbus_message_iter_next (&iter))
5586         break;
5587     }
5588   
5589   retval = TRUE;
5590   
5591  failed:
5592   return retval;
5593 }
5594
5595 static dbus_bool_t
5596 check_have_valid_message (DBusMessageLoader *loader)
5597 {
5598   DBusMessage *message;
5599   dbus_bool_t retval;
5600
5601   message = NULL;
5602   retval = FALSE;
5603
5604   if (!_dbus_message_loader_queue_messages (loader))
5605     _dbus_assert_not_reached ("no memory to queue messages");
5606   
5607   if (_dbus_message_loader_get_is_corrupted (loader))
5608     {
5609       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
5610       goto failed;
5611     }
5612   
5613   message = _dbus_message_loader_pop_message (loader);
5614   if (message == NULL)
5615     {
5616       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
5617       goto failed;
5618     }
5619   
5620   if (_dbus_string_get_length (&loader->data) > 0)
5621     {
5622       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
5623       goto failed;
5624     }
5625
5626   /* Verify that we're able to properly deal with the message.
5627    * For example, this would detect improper handling of messages
5628    * in nonstandard byte order.
5629    */
5630   if (!check_message_handling (message))
5631     goto failed;  
5632   
5633   retval = TRUE;
5634
5635  failed:
5636   if (message)
5637     dbus_message_unref (message);
5638
5639   return retval;
5640 }
5641
5642 static dbus_bool_t
5643 check_invalid_message (DBusMessageLoader *loader)
5644 {
5645   dbus_bool_t retval;
5646
5647   retval = FALSE;
5648
5649   if (!_dbus_message_loader_queue_messages (loader))
5650     _dbus_assert_not_reached ("no memory to queue messages");
5651   
5652   if (!_dbus_message_loader_get_is_corrupted (loader))
5653     {
5654       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
5655       goto failed;
5656     }
5657
5658   retval = TRUE;
5659
5660  failed:
5661   return retval;
5662 }
5663
5664 static dbus_bool_t
5665 check_incomplete_message (DBusMessageLoader *loader)
5666 {
5667   DBusMessage *message;
5668   dbus_bool_t retval;
5669
5670   message = NULL;
5671   retval = FALSE;
5672
5673   if (!_dbus_message_loader_queue_messages (loader))
5674     _dbus_assert_not_reached ("no memory to queue messages");
5675   
5676   if (_dbus_message_loader_get_is_corrupted (loader))
5677     {
5678       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
5679       goto failed;
5680     }
5681   
5682   message = _dbus_message_loader_pop_message (loader);
5683   if (message != NULL)
5684     {
5685       _dbus_warn ("loaded message that was expected to be incomplete\n");
5686       goto failed;
5687     }
5688
5689   retval = TRUE;
5690
5691  failed:
5692   if (message)
5693     dbus_message_unref (message);
5694   return retval;
5695 }
5696
5697 static dbus_bool_t
5698 check_loader_results (DBusMessageLoader      *loader,
5699                       DBusMessageValidity     validity)
5700 {
5701   if (!_dbus_message_loader_queue_messages (loader))
5702     _dbus_assert_not_reached ("no memory to queue messages");
5703   
5704   switch (validity)
5705     {
5706     case _DBUS_MESSAGE_VALID:
5707       return check_have_valid_message (loader);
5708     case _DBUS_MESSAGE_INVALID:
5709       return check_invalid_message (loader);
5710     case _DBUS_MESSAGE_INCOMPLETE:
5711       return check_incomplete_message (loader);
5712     case _DBUS_MESSAGE_UNKNOWN:
5713       return TRUE;
5714     }
5715
5716   _dbus_assert_not_reached ("bad DBusMessageValidity");
5717   return FALSE;
5718 }
5719
5720
5721 /**
5722  * Loads the message in the given message file.
5723  *
5724  * @param filename filename to load
5725  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
5726  * @param data string to load message into
5727  * @returns #TRUE if the message was loaded
5728  */
5729 dbus_bool_t
5730 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
5731                                             dbus_bool_t          is_raw,
5732                                             DBusString          *data)
5733 {
5734   dbus_bool_t retval;
5735
5736   retval = FALSE;  
5737
5738   if (is_raw)
5739     {
5740       DBusError error;
5741
5742       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
5743       dbus_error_init (&error);
5744       if (!_dbus_file_get_contents (data, filename, &error))
5745         {
5746           _dbus_warn ("Could not load message file %s: %s\n",
5747                       _dbus_string_get_const_data (filename),
5748                       error.message);
5749           dbus_error_free (&error);
5750           goto failed;
5751         }
5752     }
5753   else
5754     {
5755       if (!_dbus_message_data_load (data, filename))
5756         {
5757           _dbus_warn ("Could not load message file %s\n",
5758                       _dbus_string_get_const_data (filename));
5759           goto failed;
5760         }
5761     }
5762
5763   retval = TRUE;
5764   
5765  failed:
5766
5767   return retval;
5768 }
5769
5770 /**
5771  * Tries loading the message in the given message file
5772  * and verifies that DBusMessageLoader can handle it.
5773  *
5774  * @param filename filename to load
5775  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
5776  * @param expected_validity what the message has to be like to return #TRUE
5777  * @returns #TRUE if the message has the expected validity
5778  */
5779 dbus_bool_t
5780 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
5781                                            dbus_bool_t          is_raw,
5782                                            DBusMessageValidity  expected_validity)
5783 {
5784   DBusString data;
5785   dbus_bool_t retval;
5786
5787   retval = FALSE;
5788   
5789   if (!_dbus_string_init (&data))
5790     _dbus_assert_not_reached ("could not allocate string\n");
5791
5792   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
5793                                                    &data))
5794     goto failed;
5795
5796   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
5797
5798  failed:
5799
5800   if (!retval)
5801     {
5802       if (_dbus_string_get_length (&data) > 0)
5803         _dbus_verbose_bytes_of_string (&data, 0,
5804                                        _dbus_string_get_length (&data));
5805       
5806       _dbus_warn ("Failed message loader test on %s\n",
5807                   _dbus_string_get_const_data (filename));
5808     }
5809   
5810   _dbus_string_free (&data);
5811
5812   return retval;
5813 }
5814
5815 /**
5816  * Tries loading the given message data.
5817  *
5818  *
5819  * @param data the message data
5820  * @param expected_validity what the message has to be like to return #TRUE
5821  * @returns #TRUE if the message has the expected validity
5822  */
5823 dbus_bool_t
5824 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
5825                                            DBusMessageValidity  expected_validity)
5826 {
5827   DBusMessageLoader *loader;
5828   dbus_bool_t retval;
5829   int len;
5830   int i;
5831
5832   loader = NULL;
5833   retval = FALSE;
5834
5835   /* Write the data one byte at a time */
5836   
5837   loader = _dbus_message_loader_new ();
5838
5839   /* check some trivial loader functions */
5840   _dbus_message_loader_ref (loader);
5841   _dbus_message_loader_unref (loader);
5842   _dbus_message_loader_get_max_message_size (loader);
5843   
5844   len = _dbus_string_get_length (data);
5845   for (i = 0; i < len; i++)
5846     {
5847       DBusString *buffer;
5848
5849       _dbus_message_loader_get_buffer (loader, &buffer);
5850       _dbus_string_append_byte (buffer,
5851                                 _dbus_string_get_byte (data, i));
5852       _dbus_message_loader_return_buffer (loader, buffer, 1);
5853     }
5854   
5855   if (!check_loader_results (loader, expected_validity))
5856     goto failed;
5857
5858   _dbus_message_loader_unref (loader);
5859   loader = NULL;
5860
5861   /* Write the data all at once */
5862   
5863   loader = _dbus_message_loader_new ();
5864
5865   {
5866     DBusString *buffer;
5867     
5868     _dbus_message_loader_get_buffer (loader, &buffer);
5869     _dbus_string_copy (data, 0, buffer,
5870                        _dbus_string_get_length (buffer));
5871     _dbus_message_loader_return_buffer (loader, buffer, 1);
5872   }
5873   
5874   if (!check_loader_results (loader, expected_validity))
5875     goto failed;
5876
5877   _dbus_message_loader_unref (loader);
5878   loader = NULL;  
5879
5880   /* Write the data 2 bytes at a time */
5881   
5882   loader = _dbus_message_loader_new ();
5883
5884   len = _dbus_string_get_length (data);
5885   for (i = 0; i < len; i += 2)
5886     {
5887       DBusString *buffer;
5888
5889       _dbus_message_loader_get_buffer (loader, &buffer);
5890       _dbus_string_append_byte (buffer,
5891                                 _dbus_string_get_byte (data, i));
5892       if ((i+1) < len)
5893         _dbus_string_append_byte (buffer,
5894                                   _dbus_string_get_byte (data, i+1));
5895       _dbus_message_loader_return_buffer (loader, buffer, 1);
5896     }
5897   
5898   if (!check_loader_results (loader, expected_validity))
5899     goto failed;
5900
5901   _dbus_message_loader_unref (loader);
5902   loader = NULL;
5903   
5904   retval = TRUE;
5905   
5906  failed:
5907   
5908   if (loader)
5909     _dbus_message_loader_unref (loader);
5910   
5911   return retval;
5912 }
5913
5914 static dbus_bool_t
5915 process_test_subdir (const DBusString          *test_base_dir,
5916                      const char                *subdir,
5917                      DBusMessageValidity        validity,
5918                      DBusForeachMessageFileFunc function,
5919                      void                      *user_data)
5920 {
5921   DBusString test_directory;
5922   DBusString filename;
5923   DBusDirIter *dir;
5924   dbus_bool_t retval;
5925   DBusError error;
5926
5927   retval = FALSE;
5928   dir = NULL;
5929   
5930   if (!_dbus_string_init (&test_directory))
5931     _dbus_assert_not_reached ("didn't allocate test_directory\n");
5932
5933   _dbus_string_init_const (&filename, subdir);
5934   
5935   if (!_dbus_string_copy (test_base_dir, 0,
5936                           &test_directory, 0))
5937     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
5938   
5939   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
5940     _dbus_assert_not_reached ("couldn't allocate full path");
5941
5942   _dbus_string_free (&filename);
5943   if (!_dbus_string_init (&filename))
5944     _dbus_assert_not_reached ("didn't allocate filename string\n");
5945
5946   dbus_error_init (&error);
5947   dir = _dbus_directory_open (&test_directory, &error);
5948   if (dir == NULL)
5949     {
5950       _dbus_warn ("Could not open %s: %s\n",
5951                   _dbus_string_get_const_data (&test_directory),
5952                   error.message);
5953       dbus_error_free (&error);
5954       goto failed;
5955     }
5956
5957   printf ("Testing:\n");
5958   
5959  next:
5960   while (_dbus_directory_get_next_file (dir, &filename, &error))
5961     {
5962       DBusString full_path;
5963       dbus_bool_t is_raw;
5964       
5965       if (!_dbus_string_init (&full_path))
5966         _dbus_assert_not_reached ("couldn't init string");
5967
5968       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
5969         _dbus_assert_not_reached ("couldn't copy dir to full_path");
5970
5971       if (!_dbus_concat_dir_and_file (&full_path, &filename))
5972         _dbus_assert_not_reached ("couldn't concat file to dir");
5973
5974       if (_dbus_string_ends_with_c_str (&filename, ".message"))
5975         is_raw = FALSE;
5976       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
5977         is_raw = TRUE;
5978       else
5979         {
5980           _dbus_verbose ("Skipping non-.message file %s\n",
5981                          _dbus_string_get_const_data (&filename));
5982           _dbus_string_free (&full_path);
5983           goto next;
5984         }
5985
5986       printf ("    %s\n",
5987               _dbus_string_get_const_data (&filename));
5988       
5989       _dbus_verbose (" expecting %s for %s\n",
5990                      validity == _DBUS_MESSAGE_VALID ? "valid" :
5991                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
5992                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
5993                      _dbus_string_get_const_data (&filename));
5994       
5995       if (! (*function) (&full_path, is_raw, validity, user_data))
5996         {
5997           _dbus_string_free (&full_path);
5998           goto failed;
5999         }
6000       else
6001         _dbus_string_free (&full_path);
6002     }
6003
6004   if (dbus_error_is_set (&error))
6005     {
6006       _dbus_warn ("Could not get next file in %s: %s\n",
6007                   _dbus_string_get_const_data (&test_directory),
6008                   error.message);
6009       dbus_error_free (&error);
6010       goto failed;
6011     }
6012     
6013   retval = TRUE;
6014   
6015  failed:
6016
6017   if (dir)
6018     _dbus_directory_close (dir);
6019   _dbus_string_free (&test_directory);
6020   _dbus_string_free (&filename);
6021
6022   return retval;
6023 }
6024                      
6025 /**
6026  * Runs the given function on every message file in the test suite.
6027  * The function should return #FALSE on test failure or fatal error.
6028  *
6029  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
6030  * @param func the function to run
6031  * @param user_data data for function
6032  * @returns #FALSE if there's a failure
6033  */
6034 dbus_bool_t
6035 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
6036                                                DBusForeachMessageFileFunc func,
6037                                                void                      *user_data)
6038 {
6039   DBusString test_directory;
6040   dbus_bool_t retval;
6041
6042   retval = FALSE;
6043   
6044   _dbus_string_init_const (&test_directory, test_data_dir);
6045
6046   if (!process_test_subdir (&test_directory, "valid-messages",
6047                             _DBUS_MESSAGE_VALID, func, user_data))
6048     goto failed;
6049
6050   if (!process_test_subdir (&test_directory, "invalid-messages",
6051                             _DBUS_MESSAGE_INVALID, func, user_data))
6052     goto failed;
6053   
6054   if (!process_test_subdir (&test_directory, "incomplete-messages",
6055                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
6056     goto failed;
6057
6058   retval = TRUE;
6059   
6060  failed:
6061
6062   _dbus_string_free (&test_directory);
6063   
6064   return retval;
6065 }
6066
6067 static void
6068 verify_test_message (DBusMessage *message)
6069 {
6070   DBusMessageIter iter, dict;
6071   DBusError error;
6072   dbus_int32_t our_int;
6073   char *our_str;
6074   double our_double;
6075   dbus_bool_t our_bool;
6076   dbus_uint32_t our_uint32;
6077   dbus_int32_t *our_uint32_array;
6078   int our_uint32_array_len;
6079   dbus_int32_t *our_int32_array;
6080   int our_int32_array_len;
6081   char **our_string_array;
6082   int our_string_array_len;
6083 #ifdef DBUS_HAVE_INT64
6084   dbus_int64_t our_int64;
6085   dbus_uint64_t our_uint64;
6086   dbus_int64_t *our_uint64_array;
6087   int our_uint64_array_len;
6088   dbus_int64_t *our_int64_array;
6089   int our_int64_array_len;
6090 #endif
6091   double *our_double_array;
6092   int our_double_array_len;
6093   unsigned char *our_byte_array;
6094   int our_byte_array_len;
6095   unsigned char *our_boolean_array;
6096   int our_boolean_array_len;
6097   
6098   dbus_message_iter_init (message, &iter);
6099
6100   dbus_error_init (&error);
6101   if (!dbus_message_iter_get_args (&iter, &error,
6102                                    DBUS_TYPE_INT32, &our_int,
6103 #ifdef DBUS_HAVE_INT64
6104                                    DBUS_TYPE_INT64, &our_int64,
6105                                    DBUS_TYPE_UINT64, &our_uint64,
6106 #endif
6107                                    DBUS_TYPE_STRING, &our_str,
6108                                    DBUS_TYPE_DOUBLE, &our_double,
6109                                    DBUS_TYPE_BOOLEAN, &our_bool,
6110                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
6111                                    &our_uint32_array, &our_uint32_array_len,
6112                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
6113                                    &our_int32_array, &our_int32_array_len,
6114 #ifdef DBUS_HAVE_INT64
6115                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
6116                                    &our_uint64_array, &our_uint64_array_len,
6117                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
6118                                    &our_int64_array, &our_int64_array_len,
6119 #endif
6120                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
6121                                    &our_string_array, &our_string_array_len,
6122                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
6123                                    &our_double_array, &our_double_array_len,
6124                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
6125                                    &our_byte_array, &our_byte_array_len,
6126                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
6127                                    &our_boolean_array, &our_boolean_array_len,
6128                                    0))
6129     {
6130       _dbus_warn ("error: %s - %s\n", error.name,
6131                   (error.message != NULL) ? error.message : "no message");
6132       _dbus_assert_not_reached ("Could not get arguments");
6133     }
6134
6135   if (our_int != -0x12345678)
6136     _dbus_assert_not_reached ("integers differ!");
6137
6138 #ifdef DBUS_HAVE_INT64
6139   if (our_int64 != -0x123456789abcd)
6140     _dbus_assert_not_reached ("64-bit integers differ!");
6141   if (our_uint64 != 0x123456789abcd)
6142     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
6143 #endif
6144   
6145   if (our_double != 3.14159)
6146     _dbus_assert_not_reached ("doubles differ!");
6147
6148   if (strcmp (our_str, "Test string") != 0)
6149     _dbus_assert_not_reached ("strings differ!");
6150   dbus_free (our_str);
6151
6152   if (!our_bool)
6153     _dbus_assert_not_reached ("booleans differ");
6154
6155   if (our_uint32_array_len != 4 ||
6156       our_uint32_array[0] != 0x12345678 ||
6157       our_uint32_array[1] != 0x23456781 ||
6158       our_uint32_array[2] != 0x34567812 ||
6159       our_uint32_array[3] != 0x45678123)
6160     _dbus_assert_not_reached ("uint array differs");
6161   dbus_free (our_uint32_array);
6162
6163   if (our_int32_array_len != 4 ||
6164       our_int32_array[0] != 0x12345678 ||
6165       our_int32_array[1] != -0x23456781 ||
6166       our_int32_array[2] != 0x34567812 ||
6167       our_int32_array[3] != -0x45678123)
6168     _dbus_assert_not_reached ("int array differs");
6169   dbus_free (our_int32_array);
6170
6171 #ifdef DBUS_HAVE_INT64
6172   if (our_uint64_array_len != 4 ||
6173       our_uint64_array[0] != 0x12345678 ||
6174       our_uint64_array[1] != 0x23456781 ||
6175       our_uint64_array[2] != 0x34567812 ||
6176       our_uint64_array[3] != 0x45678123)
6177     _dbus_assert_not_reached ("uint64 array differs");
6178   dbus_free (our_uint64_array);
6179   
6180   if (our_int64_array_len != 4 ||
6181       our_int64_array[0] != 0x12345678 ||
6182       our_int64_array[1] != -0x23456781 ||
6183       our_int64_array[2] != 0x34567812 ||
6184       our_int64_array[3] != -0x45678123)
6185     _dbus_assert_not_reached ("int64 array differs");
6186   dbus_free (our_int64_array);
6187 #endif /* DBUS_HAVE_INT64 */
6188   
6189   if (our_string_array_len != 4)
6190     _dbus_assert_not_reached ("string array has wrong length");
6191
6192   if (strcmp (our_string_array[0], "Foo") != 0 ||
6193       strcmp (our_string_array[1], "bar") != 0 ||
6194       strcmp (our_string_array[2], "") != 0 ||
6195       strcmp (our_string_array[3], "woo woo woo woo") != 0)
6196     _dbus_assert_not_reached ("string array differs");
6197
6198   dbus_free_string_array (our_string_array);
6199
6200   if (our_double_array_len != 3)
6201     _dbus_assert_not_reached ("double array had wrong length");
6202
6203   /* On all IEEE machines (i.e. everything sane) exact equality
6204    * should be preserved over the wire
6205    */
6206   if (our_double_array[0] != 0.1234 ||
6207       our_double_array[1] != 9876.54321 ||
6208       our_double_array[2] != -300.0)
6209     _dbus_assert_not_reached ("double array had wrong values");
6210
6211   dbus_free (our_double_array);
6212
6213   if (our_byte_array_len != 4)
6214     _dbus_assert_not_reached ("byte array had wrong length");
6215
6216   if (our_byte_array[0] != 'a' ||
6217       our_byte_array[1] != 'b' ||
6218       our_byte_array[2] != 'c' ||
6219       our_byte_array[3] != 234)
6220     _dbus_assert_not_reached ("byte array had wrong values");
6221
6222   dbus_free (our_byte_array);
6223
6224   if (our_boolean_array_len != 5)
6225     _dbus_assert_not_reached ("bool array had wrong length");
6226
6227   if (our_boolean_array[0] != TRUE ||
6228       our_boolean_array[1] != FALSE ||
6229       our_boolean_array[2] != TRUE ||
6230       our_boolean_array[3] != TRUE ||
6231       our_boolean_array[4] != FALSE)
6232     _dbus_assert_not_reached ("bool array had wrong values");
6233
6234   dbus_free (our_boolean_array);
6235   
6236   if (!dbus_message_iter_next (&iter))
6237     _dbus_assert_not_reached ("Reached end of arguments");
6238
6239   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
6240     _dbus_assert_not_reached ("not dict type");
6241      
6242   if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
6243     _dbus_assert_not_reached ("dict iter failed");
6244
6245   our_str = dbus_message_iter_get_dict_key (&dict);
6246   if (our_str == NULL || strcmp (our_str, "test") != 0)
6247     _dbus_assert_not_reached ("wrong dict key");
6248   dbus_free (our_str);
6249
6250   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
6251     {
6252       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
6253       _dbus_assert_not_reached ("wrong dict entry type");
6254     }
6255
6256   if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
6257     {
6258       _dbus_verbose ("dict entry val: %x\n", our_uint32);
6259       _dbus_assert_not_reached ("wrong dict entry value");
6260     }
6261
6262   if (dbus_message_iter_next (&dict))
6263     _dbus_assert_not_reached ("Didn't reach end of dict");
6264   
6265   if (!dbus_message_iter_next (&iter))
6266     _dbus_assert_not_reached ("Reached end of arguments");
6267   
6268   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
6269     _dbus_assert_not_reached ("wrong type after dict");
6270   
6271   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
6272     _dbus_assert_not_reached ("wrong value after dict");
6273
6274   if (dbus_message_iter_next (&iter))
6275     _dbus_assert_not_reached ("Didn't reach end of arguments");
6276 }
6277
6278 /**
6279  * @ingroup DBusMessageInternals
6280  * Unit test for DBusMessage.
6281  *
6282  * @returns #TRUE on success.
6283  */
6284 dbus_bool_t
6285 _dbus_message_test (const char *test_data_dir)
6286 {
6287   DBusMessage *message;
6288   DBusMessageLoader *loader;
6289   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
6290   int i;
6291   const char *data;
6292   DBusMessage *copy;
6293   const char *name1;
6294   const char *name2;
6295   const dbus_uint32_t our_uint32_array[] =
6296     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
6297   const dbus_uint32_t our_int32_array[] =
6298     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
6299 #ifdef DBUS_HAVE_INT64
6300   const dbus_uint64_t our_uint64_array[] =
6301     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
6302   const dbus_uint64_t our_int64_array[] =
6303     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
6304 #endif
6305   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
6306   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
6307   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
6308   const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
6309   
6310   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
6311
6312   message = dbus_message_new_method_call ("Foo.TestInterface",
6313                                           "TestMethod",
6314                                           "org.freedesktop.DBus.TestService");
6315   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
6316   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
6317                                              "TestMethod"));
6318   _dbus_message_set_serial (message, 1234);
6319   dbus_message_set_sender (message, "org.foo.bar");
6320   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar"));
6321   dbus_message_set_sender (message, NULL);
6322   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar"));
6323   _dbus_assert (dbus_message_get_serial (message) == 1234);
6324   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
6325
6326   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
6327   dbus_message_set_no_reply (message, TRUE);
6328   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
6329   dbus_message_set_no_reply (message, FALSE);
6330   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
6331   
6332   dbus_message_unref (message);
6333   
6334   /* Test the vararg functions */
6335   message = dbus_message_new_method_call ("Foo.TestInterface",
6336                                           "TestMethod",
6337                                           "org.freedesktop.DBus.TestService");
6338   _dbus_message_set_serial (message, 1);
6339   dbus_message_append_args (message,
6340                             DBUS_TYPE_INT32, -0x12345678,
6341 #ifdef DBUS_HAVE_INT64
6342                             DBUS_TYPE_INT64, -0x123456789abcd,
6343                             DBUS_TYPE_UINT64, 0x123456789abcd,
6344 #endif
6345                             DBUS_TYPE_STRING, "Test string",
6346                             DBUS_TYPE_DOUBLE, 3.14159,
6347                             DBUS_TYPE_BOOLEAN, TRUE,
6348                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_uint32_array,
6349                             _DBUS_N_ELEMENTS (our_uint32_array),
6350                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, our_int32_array,
6351                             _DBUS_N_ELEMENTS (our_int32_array),
6352 #ifdef DBUS_HAVE_INT64
6353                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, our_uint64_array,
6354                             _DBUS_N_ELEMENTS (our_uint64_array),
6355                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, our_int64_array,
6356                             _DBUS_N_ELEMENTS (our_int64_array),
6357 #endif
6358                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, our_string_array,
6359                             _DBUS_N_ELEMENTS (our_string_array),
6360                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, our_double_array,
6361                             _DBUS_N_ELEMENTS (our_double_array),
6362                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, our_byte_array,
6363                             _DBUS_N_ELEMENTS (our_byte_array),
6364                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, our_boolean_array,
6365                             _DBUS_N_ELEMENTS (our_boolean_array),
6366                             0);
6367   
6368   dbus_message_append_iter_init (message, &iter);
6369   dbus_message_iter_append_dict (&iter, &child_iter);
6370   dbus_message_iter_append_dict_key (&child_iter, "test");
6371   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
6372   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
6373   
6374   _dbus_verbose_bytes_of_string (&message->header, 0,
6375                                  _dbus_string_get_length (&message->header));
6376   _dbus_verbose_bytes_of_string (&message->body, 0,
6377                                  _dbus_string_get_length (&message->body));
6378
6379   verify_test_message (message);
6380
6381   copy = dbus_message_copy (message);
6382   
6383   _dbus_assert (message->client_serial == copy->client_serial);
6384   _dbus_assert (message->reply_serial == copy->reply_serial);
6385   _dbus_assert (message->header_padding == copy->header_padding);
6386   
6387   _dbus_assert (_dbus_string_get_length (&message->header) ==
6388                 _dbus_string_get_length (&copy->header));
6389
6390   _dbus_assert (_dbus_string_get_length (&message->body) ==
6391                 _dbus_string_get_length (&copy->body));
6392
6393   verify_test_message (copy);
6394
6395   name1 = dbus_message_get_interface (message);
6396   name2 = dbus_message_get_interface (copy);
6397
6398   _dbus_assert (strcmp (name1, name2) == 0);
6399
6400   name1 = dbus_message_get_member (message);
6401   name2 = dbus_message_get_member (copy);
6402
6403   _dbus_assert (strcmp (name1, name2) == 0);
6404   
6405   dbus_message_unref (message);
6406   dbus_message_unref (copy);
6407
6408   message = dbus_message_new_method_call ("Foo.TestInterface",
6409                                           "TestMethod",
6410                                           "org.freedesktop.DBus.TestService");
6411   _dbus_message_set_serial (message, 1);
6412   dbus_message_set_reply_serial (message, 0x12345678);
6413
6414   dbus_message_append_iter_init (message, &iter);
6415   dbus_message_iter_append_string (&iter, "Test string");
6416   dbus_message_iter_append_int32 (&iter, -0x12345678);
6417   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
6418   dbus_message_iter_append_double (&iter, 3.14159);
6419
6420   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
6421   dbus_message_iter_append_double (&child_iter, 1.5);
6422   dbus_message_iter_append_double (&child_iter, 2.5);
6423
6424   /* dict */
6425   dbus_message_iter_append_dict (&iter, &child_iter);
6426   dbus_message_iter_append_dict_key (&child_iter, "test");
6427   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
6428
6429   /* array of array of int32  (in dict) */
6430   dbus_message_iter_append_dict_key (&child_iter, "array");
6431   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
6432   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
6433   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
6434   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
6435   _dbus_warn ("next call expected to fail with wrong array type\n");
6436   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
6437   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
6438   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
6439   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
6440   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
6441   
6442   dbus_message_iter_append_byte (&iter, 0xF0);
6443
6444   dbus_message_iter_append_nil (&iter);
6445
6446   dbus_message_iter_append_named (&iter, "named",
6447                                   "data", 5);
6448   
6449   message_iter_test (message);
6450
6451   /* Message loader test */
6452   _dbus_message_lock (message);
6453   loader = _dbus_message_loader_new ();
6454
6455   /* check ref/unref */
6456   _dbus_message_loader_ref (loader);
6457   _dbus_message_loader_unref (loader);
6458   
6459   /* Write the header data one byte at a time */
6460   data = _dbus_string_get_const_data (&message->header);
6461   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
6462     {
6463       DBusString *buffer;
6464
6465       _dbus_message_loader_get_buffer (loader, &buffer);
6466       _dbus_string_append_byte (buffer, data[i]);
6467       _dbus_message_loader_return_buffer (loader, buffer, 1);
6468     }
6469
6470   /* Write the body data one byte at a time */
6471   data = _dbus_string_get_const_data (&message->body);
6472   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
6473     {
6474       DBusString *buffer;
6475
6476       _dbus_message_loader_get_buffer (loader, &buffer);
6477       _dbus_string_append_byte (buffer, data[i]);
6478       _dbus_message_loader_return_buffer (loader, buffer, 1);
6479     }
6480
6481   dbus_message_unref (message);
6482
6483   /* Now pop back the message */
6484   if (!_dbus_message_loader_queue_messages (loader))
6485     _dbus_assert_not_reached ("no memory to queue messages");
6486   
6487   if (_dbus_message_loader_get_is_corrupted (loader))
6488     _dbus_assert_not_reached ("message loader corrupted");
6489   
6490   message = _dbus_message_loader_pop_message (loader);
6491   if (!message)
6492     _dbus_assert_not_reached ("received a NULL message");
6493
6494   if (dbus_message_get_reply_serial (message) != 0x12345678)
6495     _dbus_assert_not_reached ("reply serial fields differ");
6496   
6497   message_iter_test (message);
6498   
6499   dbus_message_unref (message);
6500   _dbus_message_loader_unref (loader);
6501
6502   /* Now load every message in test_data_dir if we have one */
6503   if (test_data_dir == NULL)
6504     return TRUE;
6505
6506   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
6507                                                         (DBusForeachMessageFileFunc)
6508                                                         dbus_internal_do_not_use_try_message_file,
6509                                                         NULL);
6510 }
6511
6512 #endif /* DBUS_BUILD_TESTS */