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