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