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