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