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