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