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