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