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