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