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