2004-03-16 Richard Hult <richard@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             dbus_bool_t err = FALSE;
2264  
2265             type = va_arg (var_args, int);
2266             data = va_arg (var_args, void *);
2267             len = va_arg (var_args, int *);
2268
2269             _dbus_return_val_if_fail (data != NULL, FALSE);
2270             _dbus_return_val_if_fail (len != NULL, FALSE);
2271             
2272             if (dbus_message_iter_get_array_type (iter) != type)
2273               {
2274                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
2275                                 "Argument %d is specified to be of type \"array of %s\", but "
2276                                 "is actually of type \"array of %s\"\n", i,
2277                                 _dbus_type_to_string (type),
2278                                 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
2279                 goto out;
2280               }
2281             
2282             switch (type)
2283               {
2284               case DBUS_TYPE_BYTE:
2285                 err = !dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len);
2286                 break;
2287               case DBUS_TYPE_BOOLEAN:
2288                 err = !dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len);
2289                 break;
2290               case DBUS_TYPE_INT32:
2291                 err = !dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len);
2292                 break;
2293               case DBUS_TYPE_UINT32:
2294                 err = !dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len);
2295                 break;
2296 #ifdef DBUS_HAVE_INT64
2297               case DBUS_TYPE_INT64:
2298                 err = !dbus_message_iter_get_int64_array (iter, (dbus_int64_t **)data, len);
2299                 break;
2300               case DBUS_TYPE_UINT64:
2301                 err = !dbus_message_iter_get_uint64_array (iter, (dbus_uint64_t **)data, len);
2302                 break;
2303 #endif /* DBUS_HAVE_INT64 */
2304               case DBUS_TYPE_DOUBLE:
2305                 err = !dbus_message_iter_get_double_array (iter, (double **)data, len);
2306                 break;
2307               case DBUS_TYPE_STRING:
2308                 err = !dbus_message_iter_get_string_array (iter, (char ***)data, len);
2309                 break;
2310               case DBUS_TYPE_NIL:
2311               case DBUS_TYPE_ARRAY:
2312               case DBUS_TYPE_CUSTOM:
2313               case DBUS_TYPE_DICT:
2314                 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
2315                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2316                 goto out;
2317               default:
2318                 _dbus_warn ("Unknown field type %d\n", type);
2319                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2320                 goto out;
2321               }
2322             if (err)
2323               {
2324                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
2325                 goto out;
2326               }
2327           }
2328           break;
2329         case DBUS_TYPE_DICT:
2330           _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
2331           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2332           goto out;
2333         default:          
2334           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
2335           _dbus_warn ("Unknown field type %d\n", spec_type);
2336           goto out;
2337         }
2338       
2339       spec_type = va_arg (var_args, int);
2340       if (spec_type != 0 && !dbus_message_iter_next (iter))
2341         {
2342           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
2343                           "Message has only %d arguments, but more were expected", i);
2344           goto out;
2345         }
2346
2347       i++;
2348     }
2349   
2350   retval = TRUE;
2351   
2352  out:
2353   
2354   return retval;
2355 }
2356
2357
2358 /**
2359  * Initializes a DBusMessageIter representing the arguments of the
2360  * message passed in.
2361  *
2362  * @param message the message
2363  * @param iter pointer to an iterator to initialize
2364  */
2365 void
2366 dbus_message_iter_init (DBusMessage     *message,
2367                         DBusMessageIter *iter)
2368 {
2369   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2370
2371   _dbus_return_if_fail (message != NULL);
2372   _dbus_return_if_fail (iter != NULL);
2373   
2374   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
2375   
2376   real->message = message;
2377   real->parent_iter = NULL;
2378   real->changed_stamp = message->changed_stamp;
2379   
2380   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
2381   real->pos = 0;
2382   real->end = _dbus_string_get_length (&message->body);
2383   
2384   real->container_start = 0;
2385   real->container_length_pos = 0;
2386   real->wrote_dict_key = 0;
2387   real->array_type_pos = 0;
2388 }
2389
2390 #ifndef DBUS_DISABLE_CHECKS
2391 static dbus_bool_t
2392 dbus_message_iter_check (DBusMessageRealIter *iter)
2393 {
2394   if (iter == NULL)
2395     {
2396       _dbus_warn ("dbus iterator check failed: iterator is NULL\n");
2397       return FALSE;
2398     }
2399   
2400   if (iter->changed_stamp != iter->message->changed_stamp)
2401     {
2402       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message\n");
2403       return FALSE;
2404     }
2405   
2406   if (iter->pos < 0 || iter->pos > iter->end)
2407     {
2408       _dbus_warn ("dbus iterator check failed: invalid position\n");
2409       return FALSE;
2410     }
2411
2412   return TRUE;
2413 }
2414 #endif /* DBUS_DISABLE_CHECKS */
2415
2416 static int
2417 skip_array_type (DBusMessageRealIter *iter, int pos)
2418 {
2419   const char *data;
2420
2421   do
2422     {
2423       data = _dbus_string_get_const_data_len (&iter->message->body,
2424                                               pos++, 1);
2425     }
2426   while (*data == DBUS_TYPE_ARRAY);
2427   
2428   return pos;
2429 }
2430
2431 /* FIXME what are these _dbus_type_is_valid() checks for?
2432  * haven't we validated the message?
2433  */
2434 static int
2435 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
2436 {
2437   const char *data;
2438   int pos, len;
2439   
2440   switch (iter->type)
2441     {
2442     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
2443       data = _dbus_string_get_const_data_len (&iter->message->body,
2444                                               iter->pos, 1);
2445       if (_dbus_type_is_valid (*data))
2446         *type = *data;
2447       else
2448         *type = DBUS_TYPE_INVALID;
2449       
2450       return skip_array_type (iter, iter->pos);
2451       
2452     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
2453       data = _dbus_string_get_const_data_len (&iter->message->body,
2454                                               iter->array_type_pos, 1);
2455       if (_dbus_type_is_valid (*data))
2456         *type = *data;
2457       else
2458         *type = DBUS_TYPE_INVALID;
2459       
2460       return iter->pos;
2461       
2462     case DBUS_MESSAGE_ITER_TYPE_DICT:
2463       /* Get the length of the string */
2464       len = _dbus_demarshal_uint32 (&iter->message->body,
2465                                     iter->message->byte_order,
2466                                     iter->pos, &pos);
2467       pos = pos + len + 1;
2468
2469       data = _dbus_string_get_const_data_len (&iter->message->body,
2470                                               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, pos);
2477       
2478     default:
2479       _dbus_assert_not_reached ("Invalid iter type");
2480       break;
2481     }
2482   *type = DBUS_TYPE_INVALID;
2483   return iter->pos;
2484 }
2485
2486
2487 /**
2488  * Checks if an iterator has any more fields.
2489  *
2490  * @param iter the message iter
2491  * @returns #TRUE if there are more fields
2492  * following
2493  */
2494 dbus_bool_t
2495 dbus_message_iter_has_next (DBusMessageIter *iter)
2496 {
2497   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2498   int end_pos;
2499   int type, pos;
2500
2501   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2502
2503   if (real->pos >= real->end)
2504     return FALSE;
2505   
2506   pos = dbus_message_iter_get_data_start (real, &type);
2507   
2508   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
2509                                       real->message->byte_order,
2510                                       type, pos, &end_pos))
2511     return FALSE;
2512   
2513   if (end_pos >= real->end)
2514     return FALSE;
2515
2516   return TRUE;  
2517 }
2518
2519 /**
2520  * Moves the iterator to the next field.
2521  *
2522  * @param iter The message iter
2523  * @returns #TRUE if the iterator was moved to the next field
2524  */
2525 dbus_bool_t
2526 dbus_message_iter_next (DBusMessageIter *iter)
2527 {
2528   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2529   int end_pos;
2530   int type, pos;
2531
2532   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2533
2534   pos = dbus_message_iter_get_data_start (real, &type);
2535   
2536   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
2537                                       real->message->byte_order,
2538                                       type, pos, &end_pos))
2539     return FALSE;
2540
2541   if (end_pos >= real->end)
2542     return FALSE;
2543
2544   real->pos = end_pos;
2545
2546   return TRUE;
2547 }
2548
2549 /**
2550  * Returns the argument type of the argument that the
2551  * message iterator points at.
2552  *
2553  * @param iter the message iter
2554  * @returns the field type
2555  */
2556 int
2557 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
2558 {
2559   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2560   int type, pos;
2561
2562   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2563
2564   if (real->pos >= real->end)
2565     {
2566       _dbus_verbose ("  iterator at or beyond end of message\n");
2567       return DBUS_TYPE_INVALID;
2568     }
2569
2570   pos = dbus_message_iter_get_data_start (real, &type);
2571   
2572   return type;
2573 }
2574
2575 /* FIXME why do we validate the typecode in here, hasn't the message
2576  * already been verified?
2577  */
2578 static int
2579 iter_get_array_type (DBusMessageRealIter *iter, int *array_type_pos)
2580 {
2581   const char *data;
2582   int _array_type_pos;
2583   int len, pos;
2584   
2585   switch (iter->type)
2586     {
2587     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
2588       _array_type_pos = iter->pos + 1;
2589       break;
2590     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
2591       _array_type_pos = iter->array_type_pos + 1;
2592       break;
2593     case DBUS_MESSAGE_ITER_TYPE_DICT:
2594       /* Get the length of the string */
2595       len = _dbus_demarshal_uint32 (&iter->message->body,
2596                                     iter->message->byte_order,
2597                                     iter->pos, &pos);
2598       pos = pos + len + 1;
2599       data = _dbus_string_get_const_data_len (&iter->message->body,
2600                                               pos + 1, 1);
2601       _array_type_pos = pos + 1;
2602       break;
2603     default:
2604       _dbus_assert_not_reached ("wrong iter type");
2605       return DBUS_TYPE_INVALID;
2606     }
2607
2608   if (array_type_pos != NULL)
2609     *array_type_pos = _array_type_pos;
2610   
2611   data = _dbus_string_get_const_data_len (&iter->message->body,
2612                                           _array_type_pos, 1);
2613   if (_dbus_type_is_valid (*data))
2614     return  *data;
2615   
2616   return DBUS_TYPE_INVALID;
2617 }
2618
2619
2620 /**
2621  * Returns the element type of the array that the
2622  * message iterator points at. Note that you need
2623  * to check that the iterator points to an array
2624  * prior to using this function.
2625  *
2626  * @param iter the message iter
2627  * @returns the field type
2628  */
2629 int
2630 dbus_message_iter_get_array_type (DBusMessageIter *iter)
2631 {
2632   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2633   int type, pos;
2634
2635   _dbus_return_val_if_fail (dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2636
2637   if (real->pos >= real->end)
2638     return DBUS_TYPE_INVALID;
2639
2640   pos = dbus_message_iter_get_data_start (real, &type);
2641
2642   _dbus_assert (type == DBUS_TYPE_ARRAY);
2643
2644   return iter_get_array_type (real, NULL);
2645 }
2646
2647
2648 /**
2649  * Returns the string value that an iterator may point to.
2650  * Note that you need to check that the iterator points to
2651  * a string value before using this function.
2652  *
2653  * @see dbus_message_iter_get_arg_type
2654  * @param iter the message iter
2655  * @returns the string
2656  */
2657 char *
2658 dbus_message_iter_get_string (DBusMessageIter *iter)
2659 {
2660   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2661   int type, pos;
2662
2663   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
2664
2665   pos = dbus_message_iter_get_data_start (real, &type);
2666   
2667   _dbus_assert (type == DBUS_TYPE_STRING);
2668
2669   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
2670                                  pos, NULL);
2671 }
2672
2673 #if 0
2674 /**
2675  * @todo FIXME to finish this _dbus_demarshal_object_path() needs
2676  * to not explode the path.
2677  * 
2678  * Returns the object path value that an iterator may point to.
2679  * Note that you need to check that the iterator points to
2680  * an object path value before using this function.
2681  *
2682  * @see dbus_message_iter_get_arg_type
2683  * @param iter the message iter
2684  * @returns the path
2685  */
2686 char *
2687 dbus_message_iter_get_object_path (DBusMessageIter  *iter)
2688 {
2689   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2690   int type, pos;
2691
2692   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
2693
2694   pos = dbus_message_iter_get_data_start (real, &type);
2695   
2696   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
2697
2698   return _dbus_demarshal_object_path (&real->message->body, real->message->byte_order,
2699                                       pos, NULL);
2700 }
2701 #endif
2702
2703 /**
2704  * Returns the name and data from a custom type that an iterator may
2705  * point to. Note that you need to check that the iterator points to a
2706  * custom type before using this function.
2707  *
2708  * @see dbus_message_iter_get_arg_type
2709  * @param iter the message iter
2710  * @param name return location for the name of the custom type
2711  * @param value return location for data
2712  * @param len return location for length of data
2713  * @returns TRUE if get succeed
2714  * 
2715  */
2716 dbus_bool_t
2717 dbus_message_iter_get_custom (DBusMessageIter   *iter,
2718                               char             **name,
2719                               unsigned char    **value,
2720                               int               *len)
2721 {
2722   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2723   int type, pos;
2724   char *_name;
2725
2726   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2727
2728   pos = dbus_message_iter_get_data_start (real, &type);
2729   
2730   _dbus_assert (type == DBUS_TYPE_CUSTOM);
2731   
2732   _name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
2733                                   pos, &pos);
2734
2735   if (_name == NULL)
2736     return FALSE;
2737   
2738   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
2739                                    pos, NULL, value, len))
2740     {
2741       dbus_free (_name);
2742       return FALSE;
2743     }
2744
2745   *name = _name;
2746   
2747   return TRUE;
2748 }
2749
2750 /**
2751  * Returns the byte value that an iterator may point to.
2752  * Note that you need to check that the iterator points to
2753  * a byte value before using this function.
2754  *
2755  * @see dbus_message_iter_get_arg_type
2756  * @param iter the message iter
2757  * @returns the byte value
2758  */
2759 unsigned char
2760 dbus_message_iter_get_byte (DBusMessageIter *iter)
2761 {
2762   unsigned char value;
2763   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2764   int type, pos;
2765
2766   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
2767
2768   pos = dbus_message_iter_get_data_start (real, &type);
2769   
2770   _dbus_assert (type == DBUS_TYPE_BYTE);
2771
2772   value = _dbus_string_get_byte (&real->message->body, pos);
2773   
2774   return value;
2775 }
2776
2777
2778 /**
2779  * Returns the boolean value that an iterator may point to.
2780  * Note that you need to check that the iterator points to
2781  * a boolean value before using this function.
2782  *
2783  * @see dbus_message_iter_get_arg_type
2784  * @param iter the message iter
2785  * @returns the boolean value
2786  */
2787 dbus_bool_t
2788 dbus_message_iter_get_boolean (DBusMessageIter *iter)
2789 {
2790   unsigned char value;
2791   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2792   int type, pos;
2793
2794   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
2795
2796   pos = dbus_message_iter_get_data_start (real, &type);
2797   
2798   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
2799
2800   value = _dbus_string_get_byte (&real->message->body, pos);
2801   
2802   return value;
2803 }
2804
2805 /**
2806  * Returns the 32 bit signed integer value that an iterator may point to.
2807  * Note that you need to check that the iterator points to
2808  * a 32-bit integer value before using this function.
2809  *
2810  * @see dbus_message_iter_get_arg_type
2811  * @param iter the message iter
2812  * @returns the integer
2813  */
2814 dbus_int32_t
2815 dbus_message_iter_get_int32 (DBusMessageIter *iter)
2816 {
2817   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2818   int type, pos;
2819
2820   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
2821
2822   pos = dbus_message_iter_get_data_start (real, &type);
2823   
2824   _dbus_assert (type == DBUS_TYPE_INT32);
2825   
2826   return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
2827                                 pos, NULL);
2828 }
2829
2830 /**
2831  * Returns the 32 bit unsigned integer value that an iterator may point to.
2832  * Note that you need to check that the iterator points to
2833  * a 32-bit unsigned integer value before using this function.
2834  *
2835  * @see dbus_message_iter_get_arg_type
2836  * @param iter the message iter
2837  * @returns the integer
2838  */
2839 dbus_uint32_t
2840 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
2841 {
2842   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2843   int type, pos;
2844
2845   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
2846
2847   pos = dbus_message_iter_get_data_start (real, &type);
2848   
2849   _dbus_assert (type == DBUS_TYPE_UINT32);
2850   
2851   return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
2852                                  pos, NULL);
2853 }
2854
2855 #ifdef DBUS_HAVE_INT64
2856
2857 /**
2858  * Returns the 64 bit signed integer value that an iterator may point
2859  * to.  Note that you need to check that the iterator points to a
2860  * 64-bit integer value before using this function.
2861  *
2862  * This function only exists if #DBUS_HAVE_INT64 is defined.
2863  *
2864  * @see dbus_message_iter_get_arg_type
2865  * @param iter the message iter
2866  * @returns the integer
2867  */
2868 dbus_int64_t
2869 dbus_message_iter_get_int64 (DBusMessageIter *iter)
2870 {
2871   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2872   int type, pos;
2873
2874   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
2875
2876   pos = dbus_message_iter_get_data_start (real, &type);
2877   
2878   _dbus_assert (type == DBUS_TYPE_INT64);
2879   
2880   return _dbus_demarshal_int64 (&real->message->body, real->message->byte_order,
2881                                 pos, NULL);
2882 }
2883
2884 /**
2885  * Returns the 64 bit unsigned integer value that an iterator may point to.
2886  * Note that you need to check that the iterator points to
2887  * a 64-bit unsigned integer value before using this function.
2888  * 
2889  * This function only exists if #DBUS_HAVE_INT64 is defined.
2890  * 
2891  * @see dbus_message_iter_get_arg_type
2892  * @param iter the message iter
2893  * @returns the integer
2894  */
2895 dbus_uint64_t
2896 dbus_message_iter_get_uint64 (DBusMessageIter *iter)
2897 {
2898   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2899   int type, pos;
2900
2901   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0);
2902
2903   pos = dbus_message_iter_get_data_start (real, &type);
2904   
2905   _dbus_assert (type == DBUS_TYPE_UINT64);
2906   
2907   return _dbus_demarshal_uint64 (&real->message->body, real->message->byte_order,
2908                                  pos, NULL);
2909 }
2910
2911 #endif /* DBUS_HAVE_INT64 */
2912
2913 /**
2914  * Returns the double value that an iterator may point to.
2915  * Note that you need to check that the iterator points to
2916  * a string value before using this function.
2917  *
2918  * @see dbus_message_iter_get_arg_type
2919  * @param iter the message iter
2920  * @returns the double
2921  */
2922 double
2923 dbus_message_iter_get_double (DBusMessageIter *iter)
2924 {
2925   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2926   int type, pos;
2927
2928   _dbus_return_val_if_fail (dbus_message_iter_check (real), 0.0);
2929
2930   pos = dbus_message_iter_get_data_start (real, &type);
2931   
2932   _dbus_assert (type == DBUS_TYPE_DOUBLE);
2933   
2934   return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
2935                                  pos, NULL);
2936 }
2937
2938 /**
2939  * Initializes an iterator for the array that the iterator
2940  * may point to. Note that you need to check that the iterator
2941  * points to an array prior to using this function.
2942  *
2943  * The array element type is returned in array_type, and the array
2944  * iterator can only be used to get that type of data.
2945  *
2946  * @param iter the iterator
2947  * @param array_iter pointer to an iterator to initialize
2948  * @param array_type gets set to the type of the array elements
2949  */
2950 void
2951 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
2952                                        DBusMessageIter *array_iter,
2953                                        int             *array_type)
2954 {
2955   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2956   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
2957   int type, pos, len_pos, len, array_type_pos;
2958   int _array_type;
2959
2960   _dbus_return_if_fail (dbus_message_iter_check (real));
2961
2962   pos = dbus_message_iter_get_data_start (real, &type);
2963   
2964   _dbus_assert (type == DBUS_TYPE_ARRAY);
2965
2966   _array_type = iter_get_array_type (real, &array_type_pos);
2967   
2968   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
2969   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
2970                                 pos, &pos);
2971   
2972   array_real->parent_iter = real;
2973   array_real->message = real->message;
2974   array_real->changed_stamp = real->message->changed_stamp;
2975   
2976   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
2977   array_real->pos = pos;
2978   array_real->end = pos + len;
2979   
2980   array_real->container_start = pos;
2981   array_real->container_length_pos = len_pos;
2982   array_real->wrote_dict_key = 0;
2983   array_real->array_type_pos = array_type_pos;
2984   array_real->array_type_done = TRUE;
2985   
2986   if (array_type != NULL)
2987     *array_type = _array_type;
2988 }
2989
2990
2991 /**
2992  * Initializes an iterator for the dict that the iterator
2993  * may point to. Note that you need to check that the iterator
2994  * points to a dict prior to using this function.
2995  *
2996  * @param iter the iterator
2997  * @param dict_iter pointer to an iterator to initialize
2998  */
2999 void
3000 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
3001                                       DBusMessageIter *dict_iter)
3002 {
3003   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3004   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
3005   int type, pos, len_pos, len;
3006
3007   _dbus_return_if_fail (dbus_message_iter_check (real));
3008
3009   pos = dbus_message_iter_get_data_start (real, &type);
3010   
3011   _dbus_assert (type == DBUS_TYPE_DICT);
3012
3013   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
3014   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
3015                                 pos, &pos);
3016   
3017   dict_real->parent_iter = real;
3018   dict_real->message = real->message;
3019   dict_real->changed_stamp = real->message->changed_stamp;
3020   
3021   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
3022   dict_real->pos = pos;
3023   dict_real->end = pos + len;
3024   
3025   dict_real->container_start = pos;
3026   dict_real->container_length_pos = len_pos;
3027   dict_real->wrote_dict_key = 0;
3028 }
3029
3030 /**
3031  * Returns the byte array that the iterator may point to.
3032  * Note that you need to check that the iterator points
3033  * to a byte array prior to using this function.
3034  *
3035  * @param iter the iterator
3036  * @param value return location for array values
3037  * @param len return location for length of byte array
3038  * @returns #TRUE on success
3039  */
3040 dbus_bool_t
3041 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
3042                                   unsigned char   **value,
3043                                   int              *len)
3044 {
3045   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3046   int type, pos;
3047
3048   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3049
3050   pos = dbus_message_iter_get_data_start (real, &type);
3051   
3052   _dbus_assert (type == DBUS_TYPE_ARRAY);
3053
3054   type = iter_get_array_type (real, NULL);
3055
3056   _dbus_assert (type == DBUS_TYPE_BYTE);
3057
3058   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
3059                                    pos, NULL, value, len))
3060     return FALSE;
3061   else
3062     return TRUE;
3063 }
3064
3065 /**
3066  * Returns the boolean array that the iterator may point to. Note that
3067  * you need to check that the iterator points to an array of the
3068  * correct type prior to using this function.
3069  *
3070  * @param iter the iterator
3071  * @param value return location for the array
3072  * @param len return location for the array length
3073  * @returns #TRUE on success
3074  */
3075 dbus_bool_t
3076 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
3077                                      unsigned char    **value,
3078                                      int               *len)
3079 {
3080   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3081   int type, pos;
3082
3083   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3084
3085   pos = dbus_message_iter_get_data_start (real, &type);
3086   
3087   _dbus_assert (type == DBUS_TYPE_ARRAY);
3088
3089   type = iter_get_array_type (real, NULL);
3090
3091   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
3092
3093   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
3094                                    pos, NULL, value, len))
3095     return FALSE;
3096   else
3097     return TRUE;
3098 }
3099
3100 /**
3101  * Returns the 32 bit signed integer array that the iterator may point
3102  * to. Note that you need to check that the iterator points to an
3103  * array of the correct type prior to using this function.
3104  *
3105  * @param iter the iterator
3106  * @param value return location for the array
3107  * @param len return location for the array length
3108  * @returns #TRUE on success
3109  */
3110 dbus_bool_t
3111 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
3112                                     dbus_int32_t   **value,
3113                                     int             *len)
3114 {
3115   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3116   int type, pos;
3117
3118   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3119
3120   pos = dbus_message_iter_get_data_start (real, &type);
3121   
3122   _dbus_assert (type == DBUS_TYPE_ARRAY);
3123
3124   type = iter_get_array_type (real, NULL);
3125   
3126   _dbus_assert (type == DBUS_TYPE_INT32);
3127
3128   if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
3129                                     pos, NULL, value, len))
3130     return FALSE;
3131   else
3132     return TRUE;
3133 }
3134
3135 /**
3136  * Returns the 32 bit unsigned integer array that the iterator may point
3137  * to. Note that you need to check that the iterator points to an
3138  * array of the correct type prior to using this function.
3139  *
3140  * @param iter the iterator
3141  * @param value return location for the array
3142  * @param len return location for the array length
3143  * @returns #TRUE on success
3144  */
3145 dbus_bool_t
3146 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
3147                                      dbus_uint32_t  **value,
3148                                      int             *len)
3149 {
3150   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3151   int type, pos;
3152
3153   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3154
3155   pos = dbus_message_iter_get_data_start (real, &type);
3156   
3157   _dbus_assert (type == DBUS_TYPE_ARRAY);
3158
3159   type = iter_get_array_type (real, NULL);
3160   _dbus_assert (type == DBUS_TYPE_UINT32);
3161
3162   if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
3163                                     pos, NULL, value, len))
3164     return FALSE;
3165   else
3166     return TRUE;
3167 }
3168
3169 #ifdef DBUS_HAVE_INT64
3170
3171 /**
3172  * Returns the 64 bit signed integer array that the iterator may point
3173  * to. Note that you need to check that the iterator points to an
3174  * array of the correct type prior to using this function.
3175  * 
3176  * This function only exists if #DBUS_HAVE_INT64 is defined.
3177  *
3178  * @param iter the iterator
3179  * @param value return location for the array
3180  * @param len return location for the array length
3181  * @returns #TRUE on success
3182  */
3183 dbus_bool_t
3184 dbus_message_iter_get_int64_array  (DBusMessageIter *iter,
3185                                     dbus_int64_t   **value,
3186                                     int             *len)
3187 {
3188   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3189   int type, pos;
3190
3191   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3192
3193   pos = dbus_message_iter_get_data_start (real, &type);
3194   
3195   _dbus_assert (type == DBUS_TYPE_ARRAY);
3196
3197   type = iter_get_array_type (real, NULL);
3198   
3199   _dbus_assert (type == DBUS_TYPE_INT64);
3200
3201   if (!_dbus_demarshal_int64_array (&real->message->body, real->message->byte_order,
3202                                     pos, NULL, value, len))
3203     return FALSE;
3204   else
3205     return TRUE;
3206 }
3207
3208 /**
3209  * Returns the 64 bit unsigned integer array that the iterator may point
3210  * to. Note that you need to check that the iterator points to an
3211  * array of the correct type prior to using this function.
3212  *
3213  * This function only exists if #DBUS_HAVE_INT64 is defined.
3214  *
3215  * @param iter the iterator
3216  * @param value return location for the array
3217  * @param len return location for the array length
3218  * @returns #TRUE on success
3219  */
3220 dbus_bool_t
3221 dbus_message_iter_get_uint64_array  (DBusMessageIter *iter,
3222                                      dbus_uint64_t  **value,
3223                                      int             *len)
3224 {
3225   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3226   int type, pos;
3227
3228   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3229
3230   pos = dbus_message_iter_get_data_start (real, &type);
3231   
3232   _dbus_assert (type == DBUS_TYPE_ARRAY);
3233
3234   type = iter_get_array_type (real, NULL);
3235   _dbus_assert (type == DBUS_TYPE_UINT64);
3236
3237   if (!_dbus_demarshal_uint64_array (&real->message->body, real->message->byte_order,
3238                                     pos, NULL, value, len))
3239     return FALSE;
3240   else
3241     return TRUE;
3242 }
3243
3244 #endif /* DBUS_HAVE_INT64 */
3245
3246 /**
3247  * Returns the double array that the iterator may point to. Note that
3248  * you need to check that the iterator points to an array of the
3249  * correct type prior to using this function.
3250  *
3251  * @param iter the iterator
3252  * @param value return location for the array
3253  * @param len return location for the array length
3254  * @returns #TRUE on success
3255  */
3256 dbus_bool_t
3257 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
3258                                      double         **value,
3259                                      int             *len)
3260 {
3261   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3262   int type, pos;
3263
3264   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3265
3266   pos = dbus_message_iter_get_data_start (real, &type);
3267   
3268   _dbus_assert (type == DBUS_TYPE_ARRAY);
3269
3270   type = iter_get_array_type (real, NULL);
3271   _dbus_assert (type == DBUS_TYPE_DOUBLE);
3272
3273   if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
3274                                      pos, NULL, value, len))
3275     return FALSE;
3276   else
3277     return TRUE;
3278 }
3279
3280 /**
3281  * Returns the string array that the iterator may point to.
3282  * Note that you need to check that the iterator points
3283  * to a string array prior to using this function.
3284  *
3285  * The returned value is a #NULL-terminated array of strings.
3286  * Each string is a separate malloc block, and the array
3287  * itself is a malloc block. You can free this type of
3288  * string array with dbus_free_string_array().
3289  *
3290  * @param iter the iterator
3291  * @param value return location for string values
3292  * @param len return location for length of byte array
3293  * @returns #TRUE on success
3294  */
3295 dbus_bool_t
3296 dbus_message_iter_get_string_array (DBusMessageIter *iter,
3297                                     char          ***value,
3298                                     int             *len)
3299 {
3300   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3301   int type, pos;
3302
3303   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3304
3305   pos = dbus_message_iter_get_data_start (real, &type);
3306   
3307   _dbus_assert (type == DBUS_TYPE_ARRAY);
3308
3309   type = iter_get_array_type (real, NULL);
3310   _dbus_assert (type == DBUS_TYPE_STRING);
3311
3312   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
3313                                      pos, NULL, value, len))
3314     return FALSE;
3315   else
3316     return TRUE;
3317 }
3318
3319 #if 0
3320 /**
3321  * @todo FIXME to implement this _dbus_demarshal_object_path_array()
3322  * needs implementing
3323  * 
3324  * Returns the object path array that the iterator may point to.
3325  * Note that you need to check that the iterator points
3326  * to an object path array prior to using this function.
3327  *
3328  * The returned value is a #NULL-terminated array of strings.
3329  * Each string is a separate malloc block, and the array
3330  * itself is a malloc block. You can free this type of
3331  * array with dbus_free_string_array().
3332  *
3333  * @param iter the iterator
3334  * @param value return location for string values
3335  * @param len return location for length of byte array
3336  * @returns #TRUE on success
3337  */
3338 dbus_bool_t
3339 dbus_message_iter_get_object_path_array (DBusMessageIter *iter,
3340                                          char          ***value,
3341                                          int             *len)
3342 {
3343   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3344   int type, pos;
3345
3346   _dbus_return_val_if_fail (dbus_message_iter_check (real), FALSE);
3347
3348   pos = dbus_message_iter_get_data_start (real, &type);
3349   
3350   _dbus_assert (type == DBUS_TYPE_ARRAY);
3351
3352   type = iter_get_array_type (real, NULL);
3353   _dbus_assert (type == DBUS_TYPE_OBJECT_PATH);
3354
3355   if (!_dbus_demarshal_object_path_array (&real->message->body, real->message->byte_order,
3356                                           pos, NULL, value, len))
3357     return FALSE;
3358   else
3359     return TRUE;
3360 }
3361 #endif
3362
3363 /**
3364  * Returns the key name fot the dict entry that an iterator
3365  * may point to. Note that you need to check that the iterator
3366  * points to a dict entry before using this function.
3367  *
3368  * @see dbus_message_iter_init_dict_iterator
3369  * @param iter the message iter
3370  * @returns the key name
3371  */
3372 char *
3373 dbus_message_iter_get_dict_key (DBusMessageIter   *iter)
3374 {
3375   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3376
3377   _dbus_return_val_if_fail (dbus_message_iter_check (real), NULL);
3378
3379   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
3380
3381   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
3382                                  real->pos, NULL);
3383 }
3384
3385 /**
3386  * Initializes a DBusMessageIter pointing to the end of the
3387  * message. This iterator can be used to append data to the
3388  * message.
3389  *
3390  * @param message the message
3391  * @param iter pointer to an iterator to initialize
3392  */
3393 void
3394 dbus_message_append_iter_init (DBusMessage     *message,
3395                                DBusMessageIter *iter)
3396 {
3397   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3398
3399   _dbus_return_if_fail (message != NULL);
3400   _dbus_return_if_fail (iter != NULL);
3401   
3402   real->message = message;
3403   real->parent_iter = NULL;
3404   real->changed_stamp = message->changed_stamp;
3405   
3406   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
3407   real->end = _dbus_string_get_length (&real->message->body);
3408   real->pos = real->end;
3409   
3410   real->container_length_pos = 0;
3411   real->wrote_dict_key = 0;
3412 }
3413
3414 #ifndef DBUS_DISABLE_CHECKS
3415 static dbus_bool_t
3416 dbus_message_iter_append_check (DBusMessageRealIter *iter)
3417 {
3418   if (iter == NULL)
3419     {
3420       _dbus_warn ("dbus iterator check failed: NULL iterator\n");
3421       return FALSE;
3422     }
3423   
3424   if (iter->message->locked)
3425     {
3426       _dbus_warn ("dbus iterator check failed: message is locked (has already been sent)\n");
3427       return FALSE;
3428     }
3429       
3430   if (iter->changed_stamp != iter->message->changed_stamp)
3431     {
3432       _dbus_warn ("dbus iterator check failed: invalid iterator, must re-initialize it after modifying the message");
3433       return FALSE;
3434     }
3435   
3436   if (iter->pos != iter->end)
3437     {
3438       _dbus_warn ("dbus iterator check failed: can only append at end of message");
3439       return FALSE;
3440     }
3441   
3442   if (iter->pos != _dbus_string_get_length (&iter->message->body))
3443     {
3444       _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
3445       return FALSE;
3446     }
3447
3448   return TRUE;
3449 }
3450 #endif /* DBUS_DISABLE_CHECKS */
3451
3452 static dbus_bool_t
3453 dbus_message_iter_append_type (DBusMessageRealIter *iter,
3454                                int                  type)
3455 {
3456   const char *data;
3457   switch (iter->type)
3458     {
3459     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
3460       if (!_dbus_string_append_byte (&iter->message->signature, type))
3461         return FALSE;
3462       
3463       if (!_dbus_string_append_byte (&iter->message->body, type))
3464         {
3465           _dbus_string_shorten (&iter->message->signature, 1);
3466           return FALSE;
3467         }
3468       break;
3469       
3470     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
3471       data = _dbus_string_get_const_data_len (&iter->message->body,
3472                                               iter->array_type_pos, 1);
3473       if (type != *data)
3474         {
3475           _dbus_warn ("Appended element of wrong type for array\n");
3476           return FALSE;
3477         }
3478       break;
3479       
3480     case DBUS_MESSAGE_ITER_TYPE_DICT:
3481       if (!iter->wrote_dict_key)
3482         {
3483           _dbus_warn ("Appending dict data before key name\n");
3484           return FALSE;
3485         }
3486       
3487       if (!_dbus_string_append_byte (&iter->message->body, type))
3488         return FALSE;
3489       
3490       break;
3491       
3492     default:
3493       _dbus_assert_not_reached ("Invalid iter type");
3494       break;
3495     }
3496   
3497   return TRUE;
3498 }
3499
3500 static void
3501 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
3502 {
3503   iter->changed_stamp = iter->message->changed_stamp;
3504   
3505   /* Set new end of iter */
3506   iter->end = _dbus_string_get_length (&iter->message->body);
3507   iter->pos = iter->end;
3508
3509   /* Set container length */
3510   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
3511       (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY && iter->array_type_done))
3512     _dbus_marshal_set_uint32 (&iter->message->body,
3513                               iter->message->byte_order,
3514                               iter->container_length_pos,
3515                               iter->end - iter->container_start);
3516   
3517   if (iter->parent_iter)
3518     dbus_message_iter_update_after_change (iter->parent_iter);
3519 }
3520
3521 static void
3522 dbus_message_iter_append_done (DBusMessageRealIter *iter)
3523 {
3524   iter->message->changed_stamp++;
3525   dbus_message_iter_update_after_change (iter);
3526   iter->wrote_dict_key = FALSE;
3527 }
3528
3529 /**
3530  * Appends a nil value to the message
3531  *
3532  * @param iter an iterator pointing to the end of the message
3533  * @returns #TRUE on success
3534  */
3535 dbus_bool_t
3536 dbus_message_iter_append_nil (DBusMessageIter *iter)
3537 {
3538   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3539
3540   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3541
3542   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
3543     return FALSE;
3544   
3545   dbus_message_iter_append_done (real);
3546   
3547   return TRUE;
3548 }
3549
3550 /**
3551  * Appends a boolean value to the message
3552  *
3553  * @param iter an iterator pointing to the end of the message
3554  * @param value the boolean value
3555  * @returns #TRUE on success
3556  */
3557 dbus_bool_t
3558 dbus_message_iter_append_boolean (DBusMessageIter *iter,
3559                                   dbus_bool_t     value)
3560 {
3561   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3562
3563   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3564
3565   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
3566     return FALSE;
3567   
3568   if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
3569     {
3570       _dbus_string_set_length (&real->message->body, real->pos);
3571       return FALSE;
3572     }
3573
3574   dbus_message_iter_append_done (real);
3575   
3576   return TRUE;
3577 }
3578
3579 /**
3580  * Appends a byte to the message
3581  *
3582  * @param iter an iterator pointing to the end of the message
3583  * @param value the byte value
3584  * @returns #TRUE on success
3585  */
3586 dbus_bool_t
3587 dbus_message_iter_append_byte (DBusMessageIter *iter,
3588                                unsigned char    value)
3589 {
3590   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3591
3592   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3593
3594   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BYTE))
3595     return FALSE;
3596   
3597   if (!_dbus_string_append_byte (&real->message->body, value))
3598     {
3599       _dbus_string_set_length (&real->message->body, real->pos);
3600       return FALSE;
3601     }
3602
3603   dbus_message_iter_append_done (real);
3604   
3605   return TRUE;
3606 }
3607
3608
3609 /**
3610  * Appends a 32 bit signed integer to the message.
3611  *
3612  * @param iter an iterator pointing to the end of the message
3613  * @param value the integer value
3614  * @returns #TRUE on success
3615  */
3616 dbus_bool_t
3617 dbus_message_iter_append_int32   (DBusMessageIter *iter,
3618                                   dbus_int32_t  value)
3619 {
3620   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3621
3622   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3623
3624   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT32))
3625     return FALSE;
3626   
3627   if (!_dbus_marshal_int32 (&real->message->body, real->message->byte_order, value))
3628     {
3629       _dbus_string_set_length (&real->message->body, real->pos);
3630       return FALSE;
3631     }
3632
3633   dbus_message_iter_append_done (real);
3634   
3635   return TRUE;
3636 }
3637
3638 /**
3639  * Appends a 32 bit unsigned integer to the message.
3640  *
3641  * @param iter an iterator pointing to the end of the message
3642  * @param value the integer value
3643  * @returns #TRUE on success
3644  */
3645 dbus_bool_t
3646 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
3647                                  dbus_uint32_t    value)
3648 {
3649   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3650
3651   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3652
3653   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
3654     return FALSE;
3655   
3656   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
3657     {
3658       _dbus_string_set_length (&real->message->body, real->pos);
3659       return FALSE;
3660     }
3661
3662   dbus_message_iter_append_done (real);
3663   
3664   return TRUE;
3665 }
3666
3667 #ifdef DBUS_HAVE_INT64
3668
3669 /**
3670  * Appends a 64 bit signed integer to the message.
3671  *
3672  * This function only exists if #DBUS_HAVE_INT64 is defined.
3673  *
3674  * @param iter an iterator pointing to the end of the message
3675  * @param value the integer value
3676  * @returns #TRUE on success
3677  */
3678 dbus_bool_t
3679 dbus_message_iter_append_int64   (DBusMessageIter *iter,
3680                                   dbus_int64_t  value)
3681 {
3682   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3683
3684   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3685
3686   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT64))
3687     return FALSE;
3688   
3689   if (!_dbus_marshal_int64 (&real->message->body, real->message->byte_order, value))
3690     {
3691       _dbus_string_set_length (&real->message->body, real->pos);
3692       return FALSE;
3693     }
3694
3695   dbus_message_iter_append_done (real);
3696   
3697   return TRUE;
3698 }
3699
3700 /**
3701  * Appends a 64 bit unsigned integer to the message.
3702  *
3703  * This function only exists if #DBUS_HAVE_INT64 is defined.
3704  *
3705  * @param iter an iterator pointing to the end of the message
3706  * @param value the integer value
3707  * @returns #TRUE on success
3708  */
3709 dbus_bool_t
3710 dbus_message_iter_append_uint64 (DBusMessageIter *iter,
3711                                  dbus_uint64_t    value)
3712 {
3713   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3714
3715   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3716
3717   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT64))
3718     return FALSE;
3719   
3720   if (!_dbus_marshal_uint64 (&real->message->body, real->message->byte_order, value))
3721     {
3722       _dbus_string_set_length (&real->message->body, real->pos);
3723       return FALSE;
3724     }
3725
3726   dbus_message_iter_append_done (real);
3727   
3728   return TRUE;
3729 }
3730
3731 #endif /* DBUS_HAVE_INT64 */
3732
3733 /**
3734  * Appends a double value to the message.
3735  *
3736  * @param iter an iterator pointing to the end of the message
3737  * @param value the double value
3738  * @returns #TRUE on success
3739  */
3740 dbus_bool_t
3741 dbus_message_iter_append_double (DBusMessageIter *iter,
3742                                  double           value)
3743 {
3744   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3745
3746   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3747
3748   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
3749     return FALSE;
3750   
3751   if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
3752     {
3753       _dbus_string_set_length (&real->message->body, real->pos);
3754       return FALSE;
3755     }
3756
3757   dbus_message_iter_append_done (real);
3758   
3759   return TRUE;
3760 }
3761
3762 /**
3763  * Appends a UTF-8 string to the message.
3764  *
3765  * @todo add return_val_if_fail(UTF-8 is valid)
3766  *
3767  * @param iter an iterator pointing to the end of the message
3768  * @param value the string
3769  * @returns #TRUE on success
3770  */
3771 dbus_bool_t
3772 dbus_message_iter_append_string (DBusMessageIter *iter,
3773                                  const char      *value)
3774 {
3775   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3776
3777   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3778   
3779   if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
3780     return FALSE;
3781   
3782   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
3783     {
3784       _dbus_string_set_length (&real->message->body, real->pos);
3785       return FALSE;
3786     }
3787
3788   dbus_message_iter_append_done (real);
3789   
3790   return TRUE;
3791 }
3792
3793 /**
3794  * Appends a custom type data chunk to the message. A custom
3795  * type is simply an arbitrary UTF-8 string used as a type
3796  * tag, plus an array of arbitrary bytes to be interpreted
3797  * according to the type tag.
3798  *
3799  * @param iter an iterator pointing to the end of the message
3800  * @param name the name of the type
3801  * @param data the binary data used to store the value
3802  * @param len the length of the binary data in bytes
3803  * @returns #TRUE on success
3804  */
3805 dbus_bool_t
3806 dbus_message_iter_append_custom (DBusMessageIter      *iter,
3807                                  const char           *name,
3808                                  const unsigned char  *data,
3809                                  int                   len)
3810 {
3811   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3812
3813   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3814
3815   if (!dbus_message_iter_append_type (real, DBUS_TYPE_CUSTOM))
3816     return FALSE;
3817   
3818    if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, name))
3819     {
3820       _dbus_string_set_length (&real->message->body, real->pos);
3821       return FALSE;
3822     }
3823    
3824   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
3825     {
3826       _dbus_string_set_length (&real->message->body, real->pos);
3827       return FALSE;
3828     }
3829
3830   dbus_message_iter_append_done (real);
3831   
3832   return TRUE;
3833 }
3834
3835
3836 /**
3837  * Appends a dict key name to the message. The iterator used
3838  * must point to a dict.
3839  *
3840  * @param iter an iterator pointing to the end of the message
3841  * @param value the string
3842  * @returns #TRUE on success
3843  */
3844 dbus_bool_t
3845 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
3846                                    const char      *value)
3847 {
3848   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3849
3850   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3851   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
3852   
3853   if (real->wrote_dict_key)
3854     {
3855       _dbus_warn ("Appending multiple dict key names\n");
3856       return FALSE;
3857     }
3858   
3859   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
3860     {
3861       return FALSE;
3862     }
3863
3864   dbus_message_iter_append_done (real);
3865   real->wrote_dict_key = TRUE;
3866   
3867   return TRUE;
3868 }
3869
3870 static dbus_bool_t
3871 array_iter_type_mark_done (DBusMessageRealIter *iter)
3872 {
3873   int len_pos;
3874   
3875   if (iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
3876     array_iter_type_mark_done (iter->parent_iter);
3877   else
3878     return TRUE;
3879
3880   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&iter->message->body),
3881                                sizeof (dbus_uint32_t));
3882
3883   /* Empty length for now, backfill later */
3884   if (!_dbus_marshal_uint32 (&iter->message->body, iter->message->byte_order, 0))
3885     {
3886       _dbus_string_set_length (&iter->message->body, iter->pos);
3887       return FALSE;
3888     }
3889
3890   iter->container_start = _dbus_string_get_length (&iter->message->body);
3891   iter->container_length_pos = len_pos;
3892   iter->array_type_done = TRUE;
3893
3894   return TRUE;
3895 }
3896
3897 static dbus_bool_t
3898 append_array_type (DBusMessageRealIter *real,
3899                    int                  element_type,
3900                    dbus_bool_t         *array_type_done,
3901                    int                 *array_type_pos)
3902 {
3903   int existing_element_type;
3904   
3905   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
3906     return FALSE;
3907   
3908   if (real->type == DBUS_MESSAGE_ITER_TYPE_ARRAY &&
3909       real->array_type_done)
3910     {
3911       existing_element_type = iter_get_array_type (real, array_type_pos);
3912       if (existing_element_type != element_type)
3913         {
3914           _dbus_warn ("Appending array of %s, when expecting array of %s\n",
3915                       _dbus_type_to_string (element_type),
3916                       _dbus_type_to_string (existing_element_type));
3917           _dbus_string_set_length (&real->message->body, real->pos);
3918           return FALSE;
3919         }
3920       if (array_type_done != NULL)
3921           *array_type_done = TRUE;
3922     }
3923   else
3924     {
3925       if (array_type_pos != NULL)
3926         *array_type_pos = _dbus_string_get_length (&real->message->body);
3927
3928
3929       if (!_dbus_string_append_byte (&real->message->signature, element_type))
3930         {
3931           _dbus_string_set_length (&real->message->body, real->pos);
3932           return FALSE;
3933         }
3934       
3935       /* Append element type */
3936       if (!_dbus_string_append_byte (&real->message->body, element_type))
3937         {
3938           _dbus_string_shorten (&real->message->signature, 1);
3939           _dbus_string_set_length (&real->message->body, real->pos);
3940           return FALSE;
3941         }
3942
3943       if (array_type_done != NULL)
3944         *array_type_done = element_type != DBUS_TYPE_ARRAY;
3945       
3946       if (element_type != DBUS_TYPE_ARRAY &&
3947           !array_iter_type_mark_done (real))
3948         {
3949           _dbus_string_shorten (&real->message->signature, 1);
3950           return FALSE;
3951         }        
3952     }
3953
3954   return TRUE;
3955 }
3956
3957 /**
3958  * Appends an array to the message and initializes an iterator that
3959  * can be used to append to the array.
3960  *
3961  * @param iter an iterator pointing to the end of the message
3962  * @param array_iter pointer to an iter that will be initialized
3963  * @param element_type the type of the array elements
3964  * @returns #TRUE on success
3965  */
3966 dbus_bool_t
3967 dbus_message_iter_append_array (DBusMessageIter      *iter,
3968                                 DBusMessageIter      *array_iter,
3969                                 int                   element_type)
3970 {
3971   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3972   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
3973   int len_pos;
3974   int array_type_pos;
3975   dbus_bool_t array_type_done;
3976
3977   if (element_type == DBUS_TYPE_NIL)
3978     {
3979       _dbus_warn ("Can't create NIL arrays\n");
3980       return FALSE;
3981     }
3982   
3983   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
3984
3985   if (!append_array_type (real, element_type, &array_type_done, &array_type_pos))
3986     return FALSE;
3987
3988   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
3989
3990   if (array_type_done)
3991     {
3992       /* Empty length for now, backfill later */
3993       if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
3994         {
3995           _dbus_string_set_length (&real->message->body, real->pos);
3996           return FALSE;
3997         }
3998     }
3999   
4000   array_real->parent_iter = real;
4001   array_real->message = real->message;
4002   array_real->changed_stamp = real->message->changed_stamp;
4003   
4004   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
4005   array_real->pos = _dbus_string_get_length (&real->message->body);
4006   array_real->end = array_real->end;
4007   
4008   array_real->container_start = array_real->pos;
4009   array_real->container_length_pos = len_pos;
4010   array_real->wrote_dict_key = 0;
4011   array_real->array_type_done = array_type_done;
4012   array_real->array_type_pos = array_type_pos;
4013
4014   dbus_message_iter_append_done (array_real);
4015   
4016   return TRUE;
4017 }
4018
4019 /**
4020  * Appends a dict to the message and initializes an iterator that
4021  * can be used to append to the dict.
4022  *
4023  * @param iter an iterator pointing to the end of the message
4024  * @param dict_iter pointer to an iter that will be initialized
4025  * @returns #TRUE on success
4026  */
4027 dbus_bool_t
4028 dbus_message_iter_append_dict (DBusMessageIter      *iter,
4029                                DBusMessageIter      *dict_iter)
4030 {
4031   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
4032   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
4033   int len_pos;
4034
4035   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
4036   
4037   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
4038     return FALSE;  
4039   
4040   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
4041
4042   /* Empty length for now, backfill later */
4043   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
4044     {
4045       _dbus_string_set_length (&real->message->body, real->pos);
4046       return FALSE;
4047     }
4048   
4049   dict_real->parent_iter = real;
4050   dict_real->message = real->message;
4051   dict_real->changed_stamp = real->message->changed_stamp;
4052   
4053   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
4054   dict_real->pos = _dbus_string_get_length (&real->message->body);
4055   dict_real->end = dict_real->end;
4056   
4057   dict_real->container_start = dict_real->pos;
4058   dict_real->container_length_pos = len_pos;
4059   dict_real->wrote_dict_key = 0;
4060
4061   dbus_message_iter_append_done (dict_real);
4062   
4063   real->wrote_dict_key = FALSE;
4064   
4065   return TRUE;
4066 }
4067
4068
4069 /**
4070  * Appends a boolean array to the message.
4071  *
4072  * @param iter an iterator pointing to the end of the message
4073  * @param value the array
4074  * @param len the length of the array
4075  * @returns #TRUE on success
4076  */
4077 dbus_bool_t
4078 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
4079                                         unsigned const char *value,
4080                                         int                  len)
4081 {
4082   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
4083
4084   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
4085
4086   if (!append_array_type (real, DBUS_TYPE_BOOLEAN, NULL, NULL))
4087     return FALSE;
4088   
4089   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
4090     {
4091       _dbus_string_set_length (&real->message->body, real->pos);
4092       return FALSE;
4093     }
4094
4095   dbus_message_iter_append_done (real);
4096   
4097   return TRUE;
4098 }
4099
4100 /**
4101  * Appends a 32 bit signed integer array to the message.
4102  *
4103  * @param iter an iterator pointing to the end of the message
4104  * @param value the array
4105  * @param len the length of the array
4106  * @returns #TRUE on success
4107  */
4108 dbus_bool_t
4109 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
4110                                       const dbus_int32_t *value,
4111                                       int                 len)
4112 {
4113   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
4114
4115   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
4116
4117   if (!append_array_type (real, DBUS_TYPE_INT32, NULL, NULL))
4118     return FALSE;
4119   
4120   if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
4121     {
4122       _dbus_string_set_length (&real->message->body, real->pos);
4123       return FALSE;
4124     }
4125
4126   dbus_message_iter_append_done (real);
4127   
4128   return TRUE;
4129 }
4130
4131 /**
4132  * Appends a 32 bit unsigned integer array to the message.
4133  *
4134  * @param iter an iterator pointing to the end of the message
4135  * @param value the array
4136  * @param len the length of the array
4137  * @returns #TRUE on success
4138  */
4139 dbus_bool_t
4140 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
4141                                        const dbus_uint32_t *value,
4142                                        int                  len)
4143 {
4144   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
4145
4146   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
4147
4148   if (!append_array_type (real, DBUS_TYPE_UINT32, NULL, NULL))
4149     return FALSE;
4150   
4151   if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
4152     {
4153       _dbus_string_set_length (&real->message->body, real->pos);
4154       return FALSE;
4155     }
4156
4157   dbus_message_iter_append_done (real);
4158   
4159   return TRUE;
4160 }
4161
4162 #ifdef DBUS_HAVE_INT64
4163
4164 /**
4165  * Appends a 64 bit signed integer array to the message.
4166  *
4167  * This function only exists if #DBUS_HAVE_INT64 is defined.
4168  *
4169  * @param iter an iterator pointing to the end of the message
4170  * @param value the array
4171  * @param len the length of the array
4172  * @returns #TRUE on success
4173  */
4174 dbus_bool_t
4175 dbus_message_iter_append_int64_array (DBusMessageIter    *iter,
4176                                       const dbus_int64_t *value,
4177                                       int                 len)
4178 {
4179   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
4180
4181   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
4182
4183   if (!append_array_type (real, DBUS_TYPE_INT64, NULL, NULL))
4184     return FALSE;
4185   
4186   if (!_dbus_marshal_int64_array (&real->message->body, real->message->byte_order, value, len))
4187     {
4188       _dbus_string_set_length (&real->message->body, real->pos);
4189       return FALSE;
4190     }
4191
4192   dbus_message_iter_append_done (real);
4193   
4194   return TRUE;
4195 }
4196
4197 /**
4198  * Appends a 64 bit unsigned integer array to the message.
4199  *
4200  * This function only exists if #DBUS_HAVE_INT64 is defined.
4201  *
4202  * @param iter an iterator pointing to the end of the message
4203  * @param value the array
4204  * @param len the length of the array
4205  * @returns #TRUE on success
4206  */
4207 dbus_bool_t
4208 dbus_message_iter_append_uint64_array (DBusMessageIter     *iter,
4209                                        const dbus_uint64_t *value,
4210                                        int                  len)
4211 {
4212   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
4213
4214   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
4215
4216   if (!append_array_type (real, DBUS_TYPE_UINT64, NULL, NULL))
4217     return FALSE;
4218   
4219   if (!_dbus_marshal_uint64_array (&real->message->body, real->message->byte_order, value, len))
4220     {
4221       _dbus_string_set_length (&real->message->body, real->pos);
4222       return FALSE;
4223     }
4224
4225   dbus_message_iter_append_done (real);
4226   
4227   return TRUE;
4228 }
4229 #endif /* DBUS_HAVE_INT64 */
4230
4231 /**
4232  * Appends a double array to the message.
4233  *
4234  * @param iter an iterator pointing to the end of the message
4235  * @param value the array
4236  * @param len the length of the array
4237  * @returns #TRUE on success
4238  */
4239 dbus_bool_t
4240 dbus_message_iter_append_double_array (DBusMessageIter *iter,
4241                                        const double    *value,
4242                                        int              len)
4243 {
4244   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
4245
4246   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
4247
4248   if (!append_array_type (real, DBUS_TYPE_DOUBLE, NULL, NULL))
4249     return FALSE;
4250   
4251   if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
4252     {
4253       _dbus_string_set_length (&real->message->body, real->pos);
4254       return FALSE;
4255     }
4256
4257   dbus_message_iter_append_done (real);
4258   
4259   return TRUE;
4260 }
4261
4262 /**
4263  * Appends a byte array to the message.
4264  *
4265  * @param iter an iterator pointing to the end of the message
4266  * @param value the array
4267  * @param len the length of the array
4268  * @returns #TRUE on success
4269  */
4270 dbus_bool_t
4271 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
4272                                      unsigned const char *value,
4273                                      int                  len)
4274 {
4275   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
4276
4277   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
4278
4279   if (!append_array_type (real, DBUS_TYPE_BYTE, NULL, NULL))
4280     return FALSE;
4281   
4282   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
4283     {
4284       _dbus_string_set_length (&real->message->body, real->pos);
4285       return FALSE;
4286     }
4287
4288   dbus_message_iter_append_done (real);
4289   
4290   return TRUE;
4291 }
4292
4293 /**
4294  * Appends a string array to the message.
4295  *
4296  * @param iter an iterator pointing to the end of the message
4297  * @param value the array
4298  * @param len the length of the array
4299  * @returns #TRUE on success
4300  */
4301 dbus_bool_t
4302 dbus_message_iter_append_string_array (DBusMessageIter *iter,
4303                                        const char     **value,
4304                                        int              len)
4305 {
4306   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
4307
4308   _dbus_return_val_if_fail (dbus_message_iter_append_check (real), FALSE);
4309
4310   if (!append_array_type (real, DBUS_TYPE_STRING, NULL, NULL))
4311     return FALSE;
4312   
4313   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
4314     {
4315       _dbus_string_set_length (&real->message->body, real->pos);
4316       return FALSE;
4317     }
4318
4319   dbus_message_iter_append_done (real);
4320   
4321   return TRUE;
4322 }
4323
4324 /**
4325  * Sets the message sender.
4326  *
4327  * @param message the message
4328  * @param sender the sender
4329  * @returns #FALSE if not enough memory
4330  */
4331 dbus_bool_t
4332 dbus_message_set_sender (DBusMessage  *message,
4333                          const char   *sender)
4334 {
4335   _dbus_return_val_if_fail (message != NULL, FALSE);
4336   _dbus_return_val_if_fail (!message->locked, FALSE);
4337
4338   return set_string_field (message,
4339                            DBUS_HEADER_FIELD_SENDER_SERVICE,
4340                            DBUS_TYPE_STRING,
4341                            sender);
4342 }
4343
4344 /**
4345  * Sets a flag indicating that the message does not want a reply; if
4346  * this flag is set, the other end of the connection may (but is not
4347  * required to) optimize by not sending method return or error
4348  * replies. If this flag is set, there is no way to know whether the
4349  * message successfully arrived at the remote end.
4350  *
4351  * @param message the message
4352  * @param no_reply #TRUE if no reply is desired
4353  */
4354 void
4355 dbus_message_set_no_reply (DBusMessage *message,
4356                            dbus_bool_t  no_reply)
4357 {
4358   char *header;
4359
4360   _dbus_return_if_fail (message != NULL);
4361   _dbus_return_if_fail (!message->locked);
4362   
4363   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
4364   
4365   if (no_reply)
4366     *header |= DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;
4367   else
4368     *header &= ~DBUS_HEADER_FLAG_NO_REPLY_EXPECTED;    
4369 }
4370
4371 /**
4372  * Returns #TRUE if the message does not expect
4373  * a reply.
4374  *
4375  * @param message the message
4376  * @returns #TRUE if the message sender isn't waiting for a reply
4377  */
4378 dbus_bool_t
4379 dbus_message_get_no_reply (DBusMessage *message)
4380 {
4381   const char *header;
4382
4383   _dbus_return_val_if_fail (message != NULL, FALSE);
4384   
4385   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
4386
4387   return (*header & DBUS_HEADER_FLAG_NO_REPLY_EXPECTED) != 0;
4388 }
4389
4390 void
4391 dbus_message_set_auto_activation (DBusMessage *message,
4392                                   dbus_bool_t  auto_activation)
4393 {
4394   char *header;
4395
4396   _dbus_return_if_fail (message != NULL);
4397   _dbus_return_if_fail (!message->locked);
4398   
4399   header = _dbus_string_get_data_len (&message->header, FLAGS_OFFSET, 1);
4400   
4401   if (auto_activation)
4402     *header |= DBUS_HEADER_FLAG_AUTO_ACTIVATION;
4403   else
4404     *header &= ~DBUS_HEADER_FLAG_AUTO_ACTIVATION;
4405 }
4406
4407 dbus_bool_t
4408 dbus_message_get_auto_activation (DBusMessage *message)
4409 {
4410   const char *header;
4411
4412   _dbus_return_val_if_fail (message != NULL, FALSE);
4413   
4414   header = _dbus_string_get_const_data_len (&message->header, FLAGS_OFFSET, 1);
4415
4416   return (*header & DBUS_HEADER_FLAG_AUTO_ACTIVATION) != 0;
4417 }
4418
4419 /**
4420  * Gets the service which originated this message,
4421  * or #NULL if unknown or inapplicable.
4422  *
4423  * @param message the message
4424  * @returns the service name or #NULL
4425  */
4426 const char*
4427 dbus_message_get_sender (DBusMessage *message)
4428 {
4429   _dbus_return_val_if_fail (message != NULL, NULL);
4430   
4431   return get_string_field (message, 
4432                            DBUS_HEADER_FIELD_SENDER_SERVICE,
4433                            NULL);
4434 }
4435
4436 /**
4437  * Gets the type signature of the message, i.e. the arguments in the
4438  * message payload. The signature includes only "in" arguments for
4439  * #DBUS_MESSAGE_TYPE_METHOD_CALL and only "out" arguments for
4440  * #DBUS_MESSAGE_TYPE_METHOD_RETURN, so is slightly different from
4441  * what you might expect (it does not include the signature of the
4442  * entire C++-style method).
4443  *
4444  * The signature is a string made up of type codes such
4445  * as #DBUS_TYPE_STRING. The string is terminated with nul
4446  * (nul is also the value of #DBUS_TYPE_INVALID).
4447  * 
4448  * @param message the message
4449  * @returns the type signature
4450  */
4451 const char*
4452 dbus_message_get_signature (DBusMessage *message)
4453 {
4454   _dbus_return_val_if_fail (message != NULL, NULL);
4455   
4456   return _dbus_string_get_const_data (&message->signature);
4457 }
4458
4459 static dbus_bool_t
4460 _dbus_message_has_type_interface_member (DBusMessage *message,
4461                                          int          type,
4462                                          const char  *interface,
4463                                          const char  *method)
4464 {
4465   const char *n;
4466
4467   _dbus_assert (message != NULL);
4468   _dbus_assert (interface != NULL);
4469   _dbus_assert (method != NULL);
4470
4471   if (dbus_message_get_type (message) != type)
4472     return FALSE;
4473
4474   /* Optimize by checking the short method name first
4475    * instead of the longer interface name
4476    */  
4477
4478   n = dbus_message_get_member (message);
4479
4480   if (n && strcmp (n, method) == 0)
4481     {
4482       n = dbus_message_get_interface (message);
4483       
4484       if (n && strcmp (n, interface) == 0)
4485         return TRUE;
4486     }
4487
4488   return FALSE;
4489 }
4490
4491 /**
4492  * Checks whether the message is a method call with the given
4493  * interface and member fields.  If the message is not
4494  * #DBUS_MESSAGE_TYPE_METHOD_CALL, or has a different interface or member field,
4495  * returns #FALSE.
4496  *
4497  * @param message the message
4498  * @param interface the name to check (must not be #NULL)
4499  * @param method the name to check (must not be #NULL)
4500  * 
4501  * @returns #TRUE if the message is the specified method call
4502  */
4503 dbus_bool_t
4504 dbus_message_is_method_call (DBusMessage *message,
4505                              const char  *interface,
4506                              const char  *method)
4507 {
4508   _dbus_return_val_if_fail (message != NULL, FALSE);
4509   _dbus_return_val_if_fail (interface != NULL, FALSE);
4510   _dbus_return_val_if_fail (method != NULL, FALSE);
4511
4512   return _dbus_message_has_type_interface_member (message,
4513                                                   DBUS_MESSAGE_TYPE_METHOD_CALL,
4514                                                   interface, method);
4515 }
4516
4517 /**
4518  * Checks whether the message is a signal with the given
4519  * interface and member fields.  If the message is not
4520  * #DBUS_MESSAGE_TYPE_SIGNAL, or has a different interface or member field,
4521  * returns #FALSE.
4522  *
4523  * @param message the message
4524  * @param interface the name to check (must not be #NULL)
4525  * @param signal_name the name to check (must not be #NULL)
4526  * 
4527  * @returns #TRUE if the message is the specified signal
4528  */
4529 dbus_bool_t
4530 dbus_message_is_signal (DBusMessage *message,
4531                         const char  *interface,
4532                         const char  *signal_name)
4533 {
4534   _dbus_return_val_if_fail (message != NULL, FALSE);
4535   _dbus_return_val_if_fail (interface != NULL, FALSE);
4536   _dbus_return_val_if_fail (signal_name != NULL, FALSE);
4537
4538   return _dbus_message_has_type_interface_member (message,
4539                                                   DBUS_MESSAGE_TYPE_SIGNAL,
4540                                                   interface, signal_name);
4541 }
4542
4543 /**
4544  * Checks whether the message is an error reply with the given error
4545  * name.  If the message is not #DBUS_MESSAGE_TYPE_ERROR, or has a
4546  * different name, returns #FALSE.
4547  *
4548  * @param message the message
4549  * @param error_name the name to check (must not be #NULL)
4550  * 
4551  * @returns #TRUE if the message is the specified error
4552  */
4553 dbus_bool_t
4554 dbus_message_is_error (DBusMessage *message,
4555                         const char  *error_name)
4556 {
4557   const char *n;
4558   
4559   _dbus_return_val_if_fail (message != NULL, FALSE);
4560   _dbus_return_val_if_fail (error_name != NULL, FALSE);
4561
4562   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
4563     return FALSE;
4564
4565   n = dbus_message_get_error_name (message);
4566
4567   if (n && strcmp (n, error_name) == 0)
4568     return TRUE;
4569   else
4570     return FALSE;
4571 }
4572
4573 /**
4574  * Checks whether the message was sent to the given service.  If the
4575  * message has no service specified or has a different name, returns
4576  * #FALSE.
4577  *
4578  * @param message the message
4579  * @param service the service to check (must not be #NULL)
4580  * 
4581  * @returns #TRUE if the message has the given destination service
4582  */
4583 dbus_bool_t
4584 dbus_message_has_destination (DBusMessage  *message,
4585                               const char   *service)
4586 {
4587   const char *s;
4588
4589   _dbus_return_val_if_fail (message != NULL, FALSE);
4590   _dbus_return_val_if_fail (service != NULL, FALSE);
4591   
4592   s = dbus_message_get_destination (message);
4593
4594   if (s && strcmp (s, service) == 0)
4595     return TRUE;
4596   else
4597     return FALSE;
4598 }
4599
4600 /**
4601  * Checks whether the message has the given service as its sender.  If
4602  * the message has no sender specified or has a different sender,
4603  * returns #FALSE. Note that if a peer application owns multiple
4604  * services, its messages will have only one of those services as the
4605  * sender (usually the base service). So you can't use this
4606  * function to prove the sender didn't own service Foo, you can
4607  * only use it to prove that it did.
4608  *
4609  * @param message the message
4610  * @param service the service to check (must not be #NULL)
4611  * 
4612  * @returns #TRUE if the message has the given origin service
4613  */
4614 dbus_bool_t
4615 dbus_message_has_sender (DBusMessage  *message,
4616                          const char   *service)
4617 {
4618   const char *s;
4619
4620   _dbus_return_val_if_fail (message != NULL, FALSE);
4621   _dbus_return_val_if_fail (service != NULL, FALSE);
4622   
4623   s = dbus_message_get_sender (message);
4624
4625   if (s && strcmp (s, service) == 0)
4626     return TRUE;
4627   else
4628     return FALSE;
4629 }
4630
4631 /**
4632  * Checks whether the message has the given signature;
4633  * see dbus_message_get_signature() for more details on
4634  * what the signature looks like.
4635  *
4636  * @param message the message
4637  * @param signature typecode array
4638  * @returns #TRUE if message has the given signature
4639 */
4640 dbus_bool_t
4641 dbus_message_has_signature (DBusMessage   *message,
4642                             const char    *signature)
4643 {
4644   _dbus_return_val_if_fail (message != NULL, FALSE);
4645   _dbus_return_val_if_fail (signature != NULL, FALSE);
4646
4647   return _dbus_string_equal_c_str (&message->signature, signature);
4648 }
4649
4650 /**
4651  * Sets a #DBusError based on the contents of the given
4652  * message. The error is only set if the message
4653  * is an error message, as in DBUS_MESSAGE_TYPE_ERROR.
4654  * The name of the error is set to the name of the message,
4655  * and the error message is set to the first argument
4656  * if the argument exists and is a string.
4657  *
4658  * The return value indicates whether the error was set (the error is
4659  * set if and only if the message is an error message).
4660  * So you can check for an error reply and convert it to DBusError
4661  * in one go.
4662  *
4663  * @param error the error to set
4664  * @param message the message to set it from
4665  * @returns #TRUE if dbus_message_get_is_error() returns #TRUE for the message
4666  */
4667 dbus_bool_t
4668 dbus_set_error_from_message (DBusError   *error,
4669                              DBusMessage *message)
4670 {
4671   char *str;
4672
4673   _dbus_return_val_if_fail (message != NULL, FALSE);
4674   _dbus_return_val_if_error_is_set (error, FALSE);
4675   
4676   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
4677     return FALSE;
4678
4679   str = NULL;
4680   dbus_message_get_args (message, NULL,
4681                          DBUS_TYPE_STRING, &str,
4682                          DBUS_TYPE_INVALID);
4683
4684   dbus_set_error (error, dbus_message_get_error_name (message),
4685                   str ? "%s" : NULL, str);
4686
4687   dbus_free (str);
4688   
4689   return TRUE;
4690 }
4691
4692 /** @} */
4693
4694 /**
4695  * @addtogroup DBusMessageInternals
4696  *
4697  * @{
4698  */
4699 /**
4700  * @typedef DBusMessageLoader
4701  *
4702  * The DBusMessageLoader object encapsulates the process of converting
4703  * a byte stream into a series of DBusMessage. It buffers the incoming
4704  * bytes as efficiently as possible, and generates a queue of
4705  * messages. DBusMessageLoader is typically used as part of a
4706  * DBusTransport implementation. The DBusTransport then hands off
4707  * the loaded messages to a DBusConnection, making the messages
4708  * visible to the application.
4709  *
4710  * @todo write tests for break-loader that a) randomly delete header
4711  * fields and b) set string fields to zero-length and other funky
4712  * values.
4713  * 
4714  */
4715
4716 /* we definitely use signed ints for sizes, so don't exceed
4717  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
4718  * over 128M is pretty nuts anyhow.
4719  */
4720
4721 /**
4722  * The maximum sane message size.
4723  */
4724 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
4725
4726 /**
4727  * Implementation details of DBusMessageLoader.
4728  * All members are private.
4729  */
4730 struct DBusMessageLoader
4731 {
4732   int refcount;        /**< Reference count. */
4733
4734   DBusString data;     /**< Buffered data */
4735   
4736   DBusList *messages;  /**< Complete messages. */
4737
4738   long max_message_size; /**< Maximum size of a message */
4739   
4740   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
4741
4742   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
4743 };
4744
4745 /**
4746  * The initial buffer size of the message loader.
4747  * 
4748  * @todo this should be based on min header size plus some average
4749  * body size, or something. Or rather, the min header size only, if we
4750  * want to try to read only the header, store that in a DBusMessage,
4751  * then read only the body and store that, etc., depends on
4752  * how we optimize _dbus_message_loader_get_buffer() and what
4753  * the exact message format is.
4754  */
4755 #define INITIAL_LOADER_DATA_LEN 32
4756
4757 /**
4758  * Creates a new message loader. Returns #NULL if memory can't
4759  * be allocated.
4760  *
4761  * @returns new loader, or #NULL.
4762  */
4763 DBusMessageLoader*
4764 _dbus_message_loader_new (void)
4765 {
4766   DBusMessageLoader *loader;
4767
4768   loader = dbus_new0 (DBusMessageLoader, 1);
4769   if (loader == NULL)
4770     return NULL;
4771   
4772   loader->refcount = 1;
4773
4774   /* Try to cap message size at something that won't *totally* hose
4775    * the system if we have a couple of them.
4776    */
4777   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
4778   
4779   if (!_dbus_string_init (&loader->data))
4780     {
4781       dbus_free (loader);
4782       return NULL;
4783     }
4784
4785   /* preallocate the buffer for speed, ignore failure */
4786   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
4787   _dbus_string_set_length (&loader->data, 0);
4788   
4789   return loader;
4790 }
4791
4792 /**
4793  * Increments the reference count of the loader.
4794  *
4795  * @param loader the loader.
4796  * @returns the loader
4797  */
4798 DBusMessageLoader *
4799 _dbus_message_loader_ref (DBusMessageLoader *loader)
4800 {
4801   loader->refcount += 1;
4802
4803   return loader;
4804 }
4805
4806 /**
4807  * Decrements the reference count of the loader and finalizes the
4808  * loader when the count reaches zero.
4809  *
4810  * @param loader the loader.
4811  */
4812 void
4813 _dbus_message_loader_unref (DBusMessageLoader *loader)
4814 {
4815   loader->refcount -= 1;
4816   if (loader->refcount == 0)
4817     {
4818       _dbus_list_foreach (&loader->messages,
4819                           (DBusForeachFunction) dbus_message_unref,
4820                           NULL);
4821       _dbus_list_clear (&loader->messages);
4822       _dbus_string_free (&loader->data);
4823       dbus_free (loader);
4824     }
4825 }
4826
4827 /**
4828  * Gets the buffer to use for reading data from the network.  Network
4829  * data is read directly into an allocated buffer, which is then used
4830  * in the DBusMessage, to avoid as many extra memcpy's as possible.
4831  * The buffer must always be returned immediately using
4832  * _dbus_message_loader_return_buffer(), even if no bytes are
4833  * successfully read.
4834  *
4835  * @todo this function can be a lot more clever. For example
4836  * it can probably always return a buffer size to read exactly
4837  * the body of the next message, thus avoiding any memory wastage
4838  * or reallocs.
4839  *
4840  * @todo we need to enforce a max length on strings in header fields.
4841  * 
4842  * @param loader the message loader.
4843  * @param buffer the buffer
4844  */
4845 void
4846 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
4847                                  DBusString        **buffer)
4848 {
4849   _dbus_assert (!loader->buffer_outstanding);
4850
4851   *buffer = &loader->data;
4852   
4853   loader->buffer_outstanding = TRUE;
4854 }
4855
4856 /**
4857  * The smallest header size that can occur. 
4858  * (It won't be valid)
4859  */
4860 #define DBUS_MINIMUM_HEADER_SIZE 16
4861
4862 static dbus_bool_t
4863 decode_string_field (const DBusString   *data,
4864                      int                 field,
4865                      HeaderField        *header_field,
4866                      DBusString         *field_data,
4867                      int                 pos,
4868                      int                 type)
4869 {
4870   int string_data_pos;
4871
4872   _dbus_assert (header_field != NULL);
4873   _dbus_assert (field_data != NULL);
4874   
4875   if (header_field->name_offset >= 0)
4876     {
4877       _dbus_verbose ("%s field provided twice\n",
4878                      _dbus_header_field_to_string (field));
4879       return FALSE;
4880     }
4881
4882   if (type != DBUS_TYPE_STRING)
4883     {
4884       _dbus_verbose ("%s field has wrong type %s\n",
4885                      _dbus_header_field_to_string (field),
4886                      _dbus_type_to_string (type));
4887       return FALSE;
4888     }
4889
4890   /* skip padding after typecode, skip string length;
4891    * we assume that the string arg has already been validated
4892    * for sanity and UTF-8
4893    */
4894   string_data_pos = _DBUS_ALIGN_VALUE (pos, 4) + 4;
4895   _dbus_assert (string_data_pos < _dbus_string_get_length (data));
4896   
4897   _dbus_string_init_const (field_data,
4898                            _dbus_string_get_const_data (data) + string_data_pos);
4899
4900   header_field->name_offset  = pos;
4901   header_field->value_offset = _DBUS_ALIGN_VALUE (pos, 4);
4902   
4903 #if 0
4904   _dbus_verbose ("Found field %s at offset %d\n",
4905                  _dbus_header_field_to_string (field),
4906                  header_field->value_offset);
4907 #endif
4908
4909   return TRUE;
4910 }
4911
4912 /* FIXME because the service/interface/member/error names are already
4913  * validated to be in the particular ASCII subset, UTF-8 validating
4914  * them could be skipped as a probably-interesting optimization.
4915  * The UTF-8 validation definitely shows up in profiles.
4916  */
4917 static dbus_bool_t
4918 decode_header_data (const DBusString   *data,
4919                     int                 header_len,
4920                     int                 byte_order,
4921                     int                 message_type,
4922                     HeaderField         fields[DBUS_HEADER_FIELD_LAST + 1],
4923                     int                *message_padding)
4924 {
4925   DBusString field_data;
4926   int pos, new_pos;
4927   int i;
4928   int field;
4929   int type;
4930   
4931   if (header_len < 16)
4932     {
4933       _dbus_verbose ("Header length %d is too short\n", header_len);
4934       return FALSE;
4935     }
4936   
4937   i = 0;
4938   while (i <= DBUS_HEADER_FIELD_LAST)
4939     {
4940       fields[i].name_offset  = -1;
4941       fields[i].value_offset = -1;
4942       ++i;
4943     }
4944   
4945   pos = 16;
4946   while (pos < header_len)
4947     {
4948       field = _dbus_string_get_byte (data, pos);
4949       if (field == DBUS_HEADER_FIELD_INVALID)
4950         break; /* Must be padding */
4951       pos++;
4952
4953       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
4954         {
4955           _dbus_verbose ("Failed to validate type of named header field pos = %d\n",
4956                          pos);
4957           return FALSE;
4958         }
4959       
4960       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, -1, pos, &new_pos))
4961         {
4962           _dbus_verbose ("Failed to validate argument to named header field pos = %d\n",
4963                          pos);
4964           return FALSE;
4965         }
4966
4967       if (new_pos > header_len)
4968         {
4969           _dbus_verbose ("Named header field tries to extend beyond header length\n");
4970           return FALSE;
4971         }
4972       
4973       switch (field)
4974         {
4975         case DBUS_HEADER_FIELD_SERVICE:
4976           if (!decode_string_field (data, field, &fields[field],
4977                                     &field_data, pos, type))
4978             return FALSE;
4979
4980           if (!_dbus_string_validate_service (&field_data, 0,
4981                                               _dbus_string_get_length (&field_data)))
4982             {
4983               _dbus_verbose ("service field has invalid content \"%s\"\n",
4984                              _dbus_string_get_const_data (&field_data));
4985               return FALSE;
4986             }
4987           break;
4988
4989         case DBUS_HEADER_FIELD_INTERFACE:
4990           if (!decode_string_field (data, field, &fields[field],
4991                                     &field_data, pos, type))
4992             return FALSE;
4993
4994           if (!_dbus_string_validate_interface (&field_data, 0,
4995                                                 _dbus_string_get_length (&field_data)))
4996             {
4997               _dbus_verbose ("interface field has invalid content \"%s\"\n",
4998                              _dbus_string_get_const_data (&field_data));
4999               return FALSE;
5000             }
5001       
5002           if (_dbus_string_equal_c_str (&field_data,
5003                                         DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL))
5004             {
5005               _dbus_verbose ("Message is on the local interface\n");
5006               return FALSE;
5007             }
5008           break;
5009
5010         case DBUS_HEADER_FIELD_MEMBER:
5011           if (!decode_string_field (data, field, &fields[field],
5012                                     &field_data, pos, type))
5013             return FALSE;
5014           
5015           if (!_dbus_string_validate_member (&field_data, 0,
5016                                              _dbus_string_get_length (&field_data)))
5017             {
5018               _dbus_verbose ("member field has invalid content \"%s\"\n",
5019                              _dbus_string_get_const_data (&field_data));
5020               return FALSE;
5021             }
5022           break;
5023
5024         case DBUS_HEADER_FIELD_ERROR_NAME:
5025           if (!decode_string_field (data, field, &fields[field],
5026                                     &field_data, pos, type))
5027             return FALSE;
5028           
5029           if (!_dbus_string_validate_error_name (&field_data, 0,
5030                                                  _dbus_string_get_length (&field_data)))
5031             {
5032               _dbus_verbose ("error-name field has invalid content \"%s\"\n",
5033                              _dbus_string_get_const_data (&field_data));
5034               return FALSE;
5035             }
5036           break;
5037           
5038         case DBUS_HEADER_FIELD_SENDER_SERVICE:
5039           if (!decode_string_field (data, field, &fields[field],
5040                                     &field_data, pos, type))
5041             return FALSE;
5042           
5043           if (!_dbus_string_validate_service (&field_data, 0,
5044                                               _dbus_string_get_length (&field_data)))
5045             {
5046               _dbus_verbose ("sender-service field has invalid content \"%s\"\n",
5047                              _dbus_string_get_const_data (&field_data));
5048               return FALSE;
5049             }
5050           break;
5051
5052         case DBUS_HEADER_FIELD_PATH:
5053
5054           /* Path was already validated as part of standard
5055            * type validation, since there's an OBJECT_PATH
5056            * type.
5057            */
5058           
5059           if (fields[field].name_offset >= 0)
5060             {
5061               _dbus_verbose ("path field provided twice\n");
5062               return FALSE;
5063             }
5064           if (type != DBUS_TYPE_OBJECT_PATH)
5065             {
5066               _dbus_verbose ("path field has wrong type\n");
5067               return FALSE;
5068             }
5069
5070           fields[field].name_offset  = pos;
5071           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
5072
5073           /* No forging signals from the local path */
5074           {
5075             const char *s;
5076             s = _dbus_string_get_const_data_len (data,
5077                                                  fields[field].value_offset,
5078                                                  _dbus_string_get_length (data) -
5079                                                  fields[field].value_offset);
5080             if (strcmp (s, DBUS_PATH_ORG_FREEDESKTOP_LOCAL) == 0)
5081               {
5082                 _dbus_verbose ("Message is on the local path\n");
5083                 return FALSE;
5084               }
5085           }
5086           
5087           _dbus_verbose ("Found path at offset %d\n",
5088                          fields[field].value_offset);
5089           break;
5090           
5091         case DBUS_HEADER_FIELD_REPLY_SERIAL:
5092           if (fields[field].name_offset >= 0)
5093             {
5094               _dbus_verbose ("reply field provided twice\n");
5095               return FALSE;
5096             }
5097
5098           if (type != DBUS_TYPE_UINT32)
5099             {
5100               _dbus_verbose ("reply field has wrong type\n");
5101               return FALSE;
5102             }
5103           
5104           fields[field].name_offset  = pos;
5105           fields[field].value_offset = _DBUS_ALIGN_VALUE (pos, 4);
5106
5107           _dbus_verbose ("Found reply serial %u at offset %d\n",
5108                          _dbus_demarshal_uint32 (data,
5109                                                  byte_order,
5110                                                  fields[field].value_offset,
5111                                                  NULL),
5112                          fields[field].value_offset);
5113           break;
5114
5115         default:
5116           _dbus_verbose ("Ignoring an unknown header field: %d at offset %d\n",
5117                          field, pos);
5118         }
5119       
5120       pos = new_pos;
5121     }
5122
5123   if (pos < header_len)
5124     {
5125       /* Alignment padding, verify that it's nul */
5126       if ((header_len - pos) >= 8)
5127         {
5128           _dbus_verbose ("too much header alignment padding\n");
5129           return FALSE;
5130         }
5131
5132       if (!_dbus_string_validate_nul (data,
5133                                       pos, (header_len - pos)))
5134         {
5135           _dbus_verbose ("header alignment padding is not nul\n");
5136           return FALSE;
5137         }
5138     }
5139
5140   /* Depending on message type, enforce presence of certain fields. */
5141   switch (message_type)
5142     {
5143     case DBUS_MESSAGE_TYPE_SIGNAL:
5144     case DBUS_MESSAGE_TYPE_METHOD_CALL:
5145       if (fields[DBUS_HEADER_FIELD_PATH].value_offset < 0)
5146         {
5147           _dbus_verbose ("No path field provided\n");
5148           return FALSE;
5149         }
5150       /* FIXME make this optional, only for method calls */
5151       if (fields[DBUS_HEADER_FIELD_INTERFACE].value_offset < 0)
5152         {
5153           _dbus_verbose ("No interface field provided\n");
5154           return FALSE;
5155         }
5156       if (fields[DBUS_HEADER_FIELD_MEMBER].value_offset < 0)
5157         {
5158           _dbus_verbose ("No member field provided\n");
5159           return FALSE;
5160         }
5161       break;
5162     case DBUS_MESSAGE_TYPE_ERROR:
5163       if (fields[DBUS_HEADER_FIELD_ERROR_NAME].value_offset < 0)
5164         {
5165           _dbus_verbose ("No error-name field provided\n");
5166           return FALSE;
5167         }
5168       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
5169         {
5170           _dbus_verbose ("No reply serial field provided in error\n");
5171           return FALSE;
5172         }
5173       break;
5174     case DBUS_MESSAGE_TYPE_METHOD_RETURN:
5175       if (fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset < 0)
5176         {
5177           _dbus_verbose ("No reply serial field provided in method return\n");
5178           return FALSE;
5179         }
5180       break;
5181     default:
5182       /* An unknown type, spec requires us to ignore it */
5183       break;
5184     }
5185   
5186   if (message_padding)
5187     *message_padding = header_len - pos;  
5188   
5189   return TRUE;
5190 }
5191
5192 /**
5193  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
5194  * indicating to the loader how many bytes of the buffer were filled
5195  * in. This function must always be called, even if no bytes were
5196  * successfully read.
5197  *
5198  * @param loader the loader.
5199  * @param buffer the buffer.
5200  * @param bytes_read number of bytes that were read into the buffer.
5201  */
5202 void
5203 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
5204                                     DBusString         *buffer,
5205                                     int                 bytes_read)
5206 {
5207   _dbus_assert (loader->buffer_outstanding);
5208   _dbus_assert (buffer == &loader->data);
5209
5210   loader->buffer_outstanding = FALSE;
5211 }
5212
5213 static dbus_bool_t
5214 load_one_message (DBusMessageLoader *loader,
5215                   int                byte_order,
5216                   int                message_type,
5217                   int                header_len,
5218                   int                body_len)
5219 {
5220   DBusMessage *message;
5221   HeaderField fields[DBUS_HEADER_FIELD_LAST + 1];
5222   int i;
5223   int next_arg;
5224   dbus_bool_t oom;
5225   int header_padding;
5226   
5227   message = NULL;
5228   oom = FALSE;
5229   
5230 #if 0
5231   _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
5232 #endif    
5233
5234   if (!decode_header_data (&loader->data,
5235                            header_len, byte_order,
5236                            message_type,
5237                            fields, &header_padding))
5238     {
5239       _dbus_verbose ("Header was invalid\n");
5240       loader->corrupted = TRUE;
5241       goto failed;
5242     }
5243           
5244   next_arg = header_len;
5245   while (next_arg < (header_len + body_len))
5246     {
5247       int type;
5248       int prev = next_arg;
5249
5250       if (!_dbus_marshal_validate_type (&loader->data, next_arg,
5251                                         &type, &next_arg))
5252         {
5253           _dbus_verbose ("invalid typecode at offset %d\n", prev);
5254           loader->corrupted = TRUE;
5255           goto failed;
5256         }
5257       
5258       if (!_dbus_marshal_validate_arg (&loader->data,
5259                                        byte_order,
5260                                        0,
5261                                        type, -1,
5262                                        next_arg,
5263                                        &next_arg))
5264         {
5265           _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
5266           loader->corrupted = TRUE;
5267           goto failed;
5268         }
5269
5270       _dbus_assert (next_arg > prev);
5271     }
5272           
5273   if (next_arg > (header_len + body_len))
5274     {
5275       _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
5276                      next_arg, header_len, body_len,
5277                      header_len + body_len);
5278       loader->corrupted = TRUE;
5279       goto failed;
5280     }
5281
5282   message = dbus_message_new_empty_header ();
5283   if (message == NULL)
5284     {
5285       _dbus_verbose ("Failed to allocate empty message\n");
5286       oom = TRUE;
5287       goto failed;
5288     }
5289
5290   message->byte_order = byte_order;
5291   message->header_padding = header_padding;
5292           
5293   /* Copy in the offsets we found */
5294   i = 0;
5295   while (i <= DBUS_HEADER_FIELD_LAST)
5296     {
5297       message->header_fields[i] = fields[i];
5298       ++i;
5299     }
5300           
5301   if (!_dbus_list_append (&loader->messages, message))
5302     {
5303       _dbus_verbose ("Failed to append new message to loader queue\n");
5304       oom = TRUE;
5305       goto failed;
5306     }
5307
5308   _dbus_assert (_dbus_string_get_length (&message->header) == 0);
5309   _dbus_assert (_dbus_string_get_length (&message->body) == 0);
5310
5311   _dbus_assert (_dbus_string_get_length (&loader->data) >=
5312                 (header_len + body_len));
5313           
5314   if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
5315     {
5316       _dbus_verbose ("Failed to move header into new message\n");
5317       oom = TRUE;
5318       goto failed;
5319     }
5320           
5321   if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
5322     {
5323       _dbus_verbose ("Failed to move body into new message\n");
5324       
5325       oom = TRUE;
5326       goto failed;
5327     }
5328
5329   _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
5330   _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
5331
5332   /* Fill in caches (we checked the types of these fields
5333    * earlier)
5334    */
5335   message->reply_serial = get_uint_field (message,
5336                                           DBUS_HEADER_FIELD_REPLY_SERIAL);
5337   
5338   message->client_serial = _dbus_demarshal_uint32 (&message->header,
5339                                                    message->byte_order,
5340                                                    CLIENT_SERIAL_OFFSET,
5341                                                    NULL);
5342   if (message->client_serial == 0 ||
5343       (message->header_fields[DBUS_HEADER_FIELD_REPLY_SERIAL].value_offset >= 0 && message->reply_serial == 0))
5344     {
5345       _dbus_verbose ("client_serial = %d reply_serial = %d, one of these no good\n",
5346                      message->client_serial,
5347                      message->reply_serial);
5348       
5349       loader->corrupted = TRUE;
5350       goto failed;
5351     }
5352           
5353   /* Fill in signature (FIXME should do this during validation,
5354    * but I didn't want to spend time on it since we want to change
5355    * the wire format to contain the signature anyway)
5356    */
5357   {
5358     DBusMessageIter iter;
5359
5360     dbus_message_iter_init (message, &iter);
5361
5362     do
5363       {
5364         int t;
5365
5366         t = dbus_message_iter_get_arg_type (&iter);
5367         if (t == DBUS_TYPE_INVALID)
5368           break;
5369
5370         if (!_dbus_string_append_byte (&message->signature,
5371                                        t))
5372           {
5373             _dbus_verbose ("failed to append type byte to signature\n");
5374             oom = TRUE;
5375             goto failed;
5376           }
5377
5378         if (t == DBUS_TYPE_ARRAY)
5379           {
5380             DBusMessageIter child_iter;
5381             int array_type = t;
5382
5383             child_iter = iter;
5384                     
5385             while (array_type == DBUS_TYPE_ARRAY)
5386               {
5387                 DBusMessageIter parent_iter = child_iter;
5388                 dbus_message_iter_init_array_iterator (&parent_iter,
5389                                                        &child_iter,
5390                                                        &array_type);
5391                                             
5392                 if (!_dbus_string_append_byte (&message->signature,
5393                                                array_type))
5394                   {
5395                     _dbus_verbose ("failed to append array type byte to signature\n");
5396
5397                     oom = TRUE;
5398                     goto failed;
5399                   }
5400               }
5401           }
5402       }
5403     while (dbus_message_iter_next (&iter));
5404   }
5405           
5406   _dbus_verbose ("Loaded message %p\n", message);
5407
5408   _dbus_assert (!oom);
5409   _dbus_assert (!loader->corrupted);
5410
5411   return TRUE;
5412
5413  failed:
5414   
5415   /* Clean up */
5416   
5417   if (message != NULL)
5418     {
5419       /* Put the data back so we can try again later if it was an OOM issue */
5420       if (_dbus_string_get_length (&message->body) > 0)
5421         {
5422           dbus_bool_t result;
5423           
5424           result = _dbus_string_copy_len (&message->body, 0, body_len,
5425                                           &loader->data, 0);
5426           
5427           _dbus_assert (result); /* because DBusString never reallocs smaller */
5428         }
5429       
5430       if (_dbus_string_get_length (&message->header) > 0)
5431         {
5432           dbus_bool_t result;
5433           
5434           result = _dbus_string_copy_len (&message->header, 0, header_len,
5435                                           &loader->data, 0);
5436           
5437           _dbus_assert (result); /* because DBusString never reallocs smaller */
5438         }
5439
5440       /* does nothing if the message isn't in the list */
5441       _dbus_list_remove_last (&loader->messages, message);
5442
5443       dbus_message_unref (message);
5444     }
5445
5446   
5447   return !oom;
5448 }
5449
5450 /**
5451  * Converts buffered data into messages.
5452  *
5453  * @todo we need to check that the proper named header fields exist
5454  * for each message type.
5455  * 
5456  * @todo If a message has unknown type, we should probably eat it
5457  * right here rather than passing it out to applications.  However
5458  * it's not an error to see messages of unknown type.
5459  * 
5460  * @param loader the loader.
5461  * @returns #TRUE if we had enough memory to finish.
5462  */
5463 dbus_bool_t
5464 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
5465 {
5466   while (!loader->corrupted && _dbus_string_get_length (&loader->data) >= 16)
5467     {
5468       const char *header_data;
5469       int byte_order, message_type, header_len, body_len;
5470       dbus_uint32_t header_len_unsigned, body_len_unsigned;
5471       
5472       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
5473
5474       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
5475
5476       if (header_data[VERSION_OFFSET] != DBUS_MAJOR_PROTOCOL_VERSION)
5477         {
5478           _dbus_verbose ("Message has protocol version %d ours is %d\n",
5479                          (int) header_data[VERSION_OFFSET], DBUS_MAJOR_PROTOCOL_VERSION);
5480           loader->corrupted = TRUE;
5481           return TRUE;
5482         }
5483       
5484       byte_order = header_data[BYTE_ORDER_OFFSET];
5485
5486       if (byte_order != DBUS_LITTLE_ENDIAN &&
5487           byte_order != DBUS_BIG_ENDIAN)
5488         {
5489           _dbus_verbose ("Message with bad byte order '%c' received\n",
5490                          byte_order);
5491           loader->corrupted = TRUE;
5492           return TRUE;
5493         }
5494
5495       /* Unknown types are ignored, but INVALID is
5496        * disallowed
5497        */
5498       message_type = header_data[TYPE_OFFSET];
5499       if (message_type == DBUS_MESSAGE_TYPE_INVALID)
5500         {
5501           _dbus_verbose ("Message with bad type '%d' received\n",
5502                          message_type);
5503           loader->corrupted = TRUE;
5504           return TRUE;
5505         }      
5506       
5507       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
5508       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
5509
5510       if (header_len_unsigned < 16)
5511         {
5512           _dbus_verbose ("Message had broken too-small header length %u\n",
5513                          header_len_unsigned);
5514           loader->corrupted = TRUE;
5515           return TRUE;
5516         }
5517
5518       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
5519           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
5520         {
5521           _dbus_verbose ("Header or body length too large (%u %u)\n",
5522                          header_len_unsigned,
5523                          body_len_unsigned);
5524           loader->corrupted = TRUE;
5525           return TRUE;
5526         }
5527
5528       /* Now that we know the values are in signed range, get
5529        * rid of stupid unsigned, just causes bugs
5530        */
5531       header_len = header_len_unsigned;
5532       body_len = body_len_unsigned;
5533
5534       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
5535         {
5536           
5537           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
5538                          header_len);
5539           loader->corrupted = TRUE;
5540           return TRUE;
5541         }
5542       
5543       if (header_len + body_len > loader->max_message_size)
5544         {
5545           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
5546                          header_len, body_len, loader->max_message_size);
5547           loader->corrupted = TRUE;
5548           return TRUE;
5549         }
5550
5551       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
5552         {
5553           if (!load_one_message (loader, byte_order, message_type,
5554                                  header_len, body_len))
5555             return FALSE;
5556         }
5557       else
5558         return TRUE;
5559     }
5560
5561   return TRUE;
5562 }
5563
5564 /**
5565  * Peeks at first loaded message, returns #NULL if no messages have
5566  * been queued.
5567  *
5568  * @param loader the loader.
5569  * @returns the next message, or #NULL if none.
5570  */
5571 DBusMessage*
5572 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
5573 {
5574   if (loader->messages)
5575     return loader->messages->data;
5576   else
5577     return NULL;
5578 }
5579
5580 /**
5581  * Pops a loaded message (passing ownership of the message
5582  * to the caller). Returns #NULL if no messages have been
5583  * queued.
5584  *
5585  * @param loader the loader.
5586  * @returns the next message, or #NULL if none.
5587  */
5588 DBusMessage*
5589 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
5590 {
5591   return _dbus_list_pop_first (&loader->messages);
5592 }
5593
5594 /**
5595  * Pops a loaded message inside a list link (passing ownership of the
5596  * message and link to the caller). Returns #NULL if no messages have
5597  * been loaded.
5598  *
5599  * @param loader the loader.
5600  * @returns the next message link, or #NULL if none.
5601  */
5602 DBusList*
5603 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
5604 {
5605   return _dbus_list_pop_first_link (&loader->messages);
5606 }
5607
5608 /**
5609  * Returns a popped message link, used to undo a pop.
5610  *
5611  * @param loader the loader
5612  * @param link the link with a message in it
5613  */
5614 void
5615 _dbus_message_loader_putback_message_link (DBusMessageLoader  *loader,
5616                                            DBusList           *link)
5617 {
5618   _dbus_list_prepend_link (&loader->messages, link);
5619 }
5620
5621 /**
5622  * Checks whether the loader is confused due to bad data.
5623  * If messages are received that are invalid, the
5624  * loader gets confused and gives up permanently.
5625  * This state is called "corrupted."
5626  *
5627  * @param loader the loader
5628  * @returns #TRUE if the loader is hosed.
5629  */
5630 dbus_bool_t
5631 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
5632 {
5633   return loader->corrupted;
5634 }
5635
5636 /**
5637  * Sets the maximum size message we allow.
5638  *
5639  * @param loader the loader
5640  * @param size the max message size in bytes
5641  */
5642 void
5643 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
5644                                            long                size)
5645 {
5646   if (size > MAX_SANE_MESSAGE_SIZE)
5647     {
5648       _dbus_verbose ("clamping requested max message size %ld to %d\n",
5649                      size, MAX_SANE_MESSAGE_SIZE);
5650       size = MAX_SANE_MESSAGE_SIZE;
5651     }
5652   loader->max_message_size = size;
5653 }
5654
5655 /**
5656  * Gets the maximum allowed message size in bytes.
5657  *
5658  * @param loader the loader
5659  * @returns max size in bytes
5660  */
5661 long
5662 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
5663 {
5664   return loader->max_message_size;
5665 }
5666
5667 static DBusDataSlotAllocator slot_allocator;
5668 _DBUS_DEFINE_GLOBAL_LOCK (message_slots);
5669
5670 /**
5671  * Allocates an integer ID to be used for storing application-specific
5672  * data on any DBusMessage. The allocated ID may then be used
5673  * with dbus_message_set_data() and dbus_message_get_data().
5674  * The passed-in slot must be initialized to -1, and is filled in
5675  * with the slot ID. If the passed-in slot is not -1, it's assumed
5676  * to be already allocated, and its refcount is incremented.
5677  * 
5678  * The allocated slot is global, i.e. all DBusMessage objects will
5679  * have a slot with the given integer ID reserved.
5680  *
5681  * @param slot_p address of a global variable storing the slot
5682  * @returns #FALSE on failure (no memory)
5683  */
5684 dbus_bool_t
5685 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
5686 {
5687   return _dbus_data_slot_allocator_alloc (&slot_allocator,
5688                                           _DBUS_LOCK_NAME (message_slots),
5689                                           slot_p);
5690 }
5691
5692 /**
5693  * Deallocates a global ID for message data slots.
5694  * dbus_message_get_data() and dbus_message_set_data() may no
5695  * longer be used with this slot.  Existing data stored on existing
5696  * DBusMessage objects will be freed when the message is
5697  * finalized, but may not be retrieved (and may only be replaced if
5698  * someone else reallocates the slot).  When the refcount on the
5699  * passed-in slot reaches 0, it is set to -1.
5700  *
5701  * @param slot_p address storing the slot to deallocate
5702  */
5703 void
5704 dbus_message_free_data_slot (dbus_int32_t *slot_p)
5705 {
5706   _dbus_return_if_fail (*slot_p >= 0);
5707   
5708   _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
5709 }
5710
5711 /**
5712  * Stores a pointer on a DBusMessage, along
5713  * with an optional function to be used for freeing
5714  * the data when the data is set again, or when
5715  * the message is finalized. The slot number
5716  * must have been allocated with dbus_message_allocate_data_slot().
5717  *
5718  * @param message the message
5719  * @param slot the slot number
5720  * @param data the data to store
5721  * @param free_data_func finalizer function for the data
5722  * @returns #TRUE if there was enough memory to store the data
5723  */
5724 dbus_bool_t
5725 dbus_message_set_data (DBusMessage     *message,
5726                        dbus_int32_t     slot,
5727                        void            *data,
5728                        DBusFreeFunction free_data_func)
5729 {
5730   DBusFreeFunction old_free_func;
5731   void *old_data;
5732   dbus_bool_t retval;
5733
5734   _dbus_return_val_if_fail (message != NULL, FALSE);
5735   _dbus_return_val_if_fail (slot >= 0, FALSE);
5736
5737   retval = _dbus_data_slot_list_set (&slot_allocator,
5738                                      &message->slot_list,
5739                                      slot, data, free_data_func,
5740                                      &old_free_func, &old_data);
5741
5742   if (retval)
5743     {
5744       /* Do the actual free outside the message lock */
5745       if (old_free_func)
5746         (* old_free_func) (old_data);
5747     }
5748
5749   return retval;
5750 }
5751
5752 /**
5753  * Retrieves data previously set with dbus_message_set_data().
5754  * The slot must still be allocated (must not have been freed).
5755  *
5756  * @param message the message
5757  * @param slot the slot to get data from
5758  * @returns the data, or #NULL if not found
5759  */
5760 void*
5761 dbus_message_get_data (DBusMessage   *message,
5762                        dbus_int32_t   slot)
5763 {
5764   void *res;
5765
5766   _dbus_return_val_if_fail (message != NULL, NULL);
5767   
5768   res = _dbus_data_slot_list_get (&slot_allocator,
5769                                   &message->slot_list,
5770                                   slot);
5771
5772   return res;
5773 }
5774
5775 /**
5776  * Utility function to convert a machine-readable (not translated)
5777  * string into a D-BUS message type.
5778  *
5779  * @code
5780  *   "method_call"    -> DBUS_MESSAGE_TYPE_METHOD_CALL
5781  *   "method_return"  -> DBUS_MESSAGE_TYPE_METHOD_RETURN
5782  *   "signal"         -> DBUS_MESSAGE_TYPE_SIGNAL
5783  *   "error"          -> DBUS_MESSAGE_TYPE_ERROR
5784  *   anything else    -> DBUS_MESSAGE_TYPE_INVALID
5785  * @endcode
5786  * 
5787  */
5788 int
5789 dbus_message_type_from_string (const char *type_str)
5790 {
5791   if (strcmp (type_str, "method_call") == 0)
5792     return DBUS_MESSAGE_TYPE_METHOD_CALL;
5793   if (strcmp (type_str, "method_return") == 0)
5794     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
5795   else if (strcmp (type_str, "signal") == 0)
5796     return DBUS_MESSAGE_TYPE_SIGNAL;
5797   else if (strcmp (type_str, "error") == 0)
5798     return DBUS_MESSAGE_TYPE_ERROR;
5799   else
5800     return DBUS_MESSAGE_TYPE_INVALID;
5801 }
5802
5803 /** @} */
5804 #ifdef DBUS_BUILD_TESTS
5805 #include "dbus-test.h"
5806 #include <stdio.h>
5807 #include <stdlib.h>
5808
5809 static void
5810 message_iter_test (DBusMessage *message)
5811 {
5812   DBusMessageIter iter, dict, dict2, array, array2;
5813   char *str;
5814   unsigned char *data;
5815   dbus_int32_t *our_int_array;
5816   int len;
5817   
5818   dbus_message_iter_init (message, &iter);
5819
5820   /* String tests */
5821   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
5822     _dbus_assert_not_reached ("Argument type isn't string");
5823
5824   str = dbus_message_iter_get_string (&iter);
5825   if (strcmp (str, "Test string") != 0)
5826     _dbus_assert_not_reached ("Strings differ");
5827   dbus_free (str);
5828
5829   if (!dbus_message_iter_next (&iter))
5830     _dbus_assert_not_reached ("Reached end of arguments");
5831
5832   /* Signed integer tests */
5833   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
5834     _dbus_assert_not_reached ("Argument type isn't int32");
5835
5836   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
5837     _dbus_assert_not_reached ("Signed integers differ");
5838
5839   if (!dbus_message_iter_next (&iter))
5840     _dbus_assert_not_reached ("Reached end of fields");
5841   
5842   /* Unsigned integer tests */
5843   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
5844     _dbus_assert_not_reached ("Argument type isn't int32");
5845
5846   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
5847     _dbus_assert_not_reached ("Unsigned integers differ");
5848
5849   if (!dbus_message_iter_next (&iter))
5850     _dbus_assert_not_reached ("Reached end of arguments");
5851
5852   /* Double tests */
5853   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
5854     _dbus_assert_not_reached ("Argument type isn't double");
5855
5856   if (dbus_message_iter_get_double (&iter) != 3.14159)
5857     _dbus_assert_not_reached ("Doubles differ");
5858
5859   if (!dbus_message_iter_next (&iter))
5860     _dbus_assert_not_reached ("Reached end of arguments");
5861
5862   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
5863     _dbus_assert_not_reached ("Argument type not an array");
5864
5865   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_DOUBLE)
5866     _dbus_assert_not_reached ("Array type not double");
5867
5868   
5869   dbus_message_iter_init_array_iterator (&iter, &array, NULL);
5870
5871   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
5872     _dbus_assert_not_reached ("Argument type isn't double");
5873
5874   if (dbus_message_iter_get_double (&array) != 1.5)
5875     _dbus_assert_not_reached ("Unsigned integers differ");
5876
5877   if (!dbus_message_iter_next (&array))
5878     _dbus_assert_not_reached ("Reached end of arguments");
5879
5880   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_DOUBLE)
5881     _dbus_assert_not_reached ("Argument type isn't double");
5882
5883   if (dbus_message_iter_get_double (&array) != 2.5)
5884     _dbus_assert_not_reached ("Unsigned integers differ");
5885
5886   if (dbus_message_iter_next (&array))
5887     _dbus_assert_not_reached ("Didn't reach end of arguments");
5888   
5889   if (!dbus_message_iter_next (&iter))
5890     _dbus_assert_not_reached ("Reached end of arguments");
5891   
5892
5893   /* dict */
5894
5895   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
5896     _dbus_assert_not_reached ("not dict type");
5897      
5898   dbus_message_iter_init_dict_iterator (&iter, &dict);
5899
5900   str = dbus_message_iter_get_dict_key (&dict);
5901   if (str == NULL || strcmp (str, "test") != 0)
5902     _dbus_assert_not_reached ("wrong dict key");
5903   dbus_free (str);
5904
5905   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
5906     _dbus_assert_not_reached ("wrong dict entry type");
5907
5908   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
5909     _dbus_assert_not_reached ("wrong dict entry value");
5910
5911   /* dict (in dict) */
5912
5913   if (!dbus_message_iter_next (&dict))
5914     _dbus_assert_not_reached ("reached end of dict");
5915   
5916   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_DICT)
5917     _dbus_assert_not_reached ("not dict type");
5918     
5919   dbus_message_iter_init_dict_iterator (&dict, &dict2);
5920   
5921   str = dbus_message_iter_get_dict_key (&dict2);
5922   if (str == NULL || strcmp (str, "dictkey") != 0)
5923     _dbus_assert_not_reached ("wrong dict key");
5924   dbus_free (str);
5925   
5926   if (dbus_message_iter_get_arg_type (&dict2) != DBUS_TYPE_STRING)
5927     _dbus_assert_not_reached ("wrong dict entry type");
5928   
5929   str = dbus_message_iter_get_string (&dict2);
5930   if (str == NULL || strcmp (str, "dictvalue") != 0)
5931     _dbus_assert_not_reached ("wrong dict entry value");
5932   dbus_free (str);
5933   
5934   if (dbus_message_iter_next (&dict2))
5935     _dbus_assert_not_reached ("didn't reach end of dict");
5936
5937   if (!dbus_message_iter_next (&dict))
5938     _dbus_assert_not_reached ("reached end of dict");
5939   
5940   /* array of array of int32 (in dict) */
5941
5942   str = dbus_message_iter_get_dict_key (&dict);
5943   if (str == NULL || strcmp (str, "array") != 0)
5944     _dbus_assert_not_reached ("wrong dict key");
5945   dbus_free (str);
5946   
5947   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_ARRAY)
5948     _dbus_assert_not_reached ("Argument type not an array");
5949
5950   if (dbus_message_iter_get_array_type (&dict) != DBUS_TYPE_ARRAY)
5951     _dbus_assert_not_reached ("Array type not array");
5952
5953   dbus_message_iter_init_array_iterator (&dict, &array, NULL);
5954
5955   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_ARRAY)
5956     _dbus_assert_not_reached ("Argument type isn't array");
5957   
5958   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
5959     _dbus_assert_not_reached ("Array type not int32");
5960   
5961   dbus_message_iter_init_array_iterator (&array, &array2, NULL);
5962
5963   if (dbus_message_iter_get_arg_type (&array2) != DBUS_TYPE_INT32)
5964     _dbus_assert_not_reached ("Argument type isn't int32");
5965
5966   if (dbus_message_iter_get_int32 (&array2) != 0x12345678)
5967     _dbus_assert_not_reached ("Signed integers differ");
5968
5969   if (!dbus_message_iter_next (&array2))
5970     _dbus_assert_not_reached ("Reached end of arguments");
5971
5972   if (dbus_message_iter_get_int32 (&array2) != 0x23456781)
5973     _dbus_assert_not_reached ("Signed integers differ");
5974
5975   if (dbus_message_iter_next (&array2))
5976     _dbus_assert_not_reached ("Didn't reached end of arguments");
5977
5978   if (!dbus_message_iter_next (&array))
5979     _dbus_assert_not_reached ("Reached end of arguments");
5980
5981   if (dbus_message_iter_get_array_type (&array) != DBUS_TYPE_INT32)
5982     _dbus_assert_not_reached ("Array type not int32");
5983
5984   if (!dbus_message_iter_get_int32_array (&array,
5985                                           &our_int_array,
5986                                           &len))
5987     _dbus_assert_not_reached ("couldn't get int32 array");
5988
5989   _dbus_assert (len == 3);
5990   _dbus_assert (our_int_array[0] == 0x34567812 &&
5991                 our_int_array[1] == 0x45678123 &&
5992                 our_int_array[2] == 0x56781234);
5993   dbus_free (our_int_array);
5994   
5995   if (dbus_message_iter_next (&array))
5996     _dbus_assert_not_reached ("Didn't reach end of array");
5997
5998   if (dbus_message_iter_next (&dict))
5999     _dbus_assert_not_reached ("Didn't reach end of dict");
6000   
6001   if (!dbus_message_iter_next (&iter))
6002     _dbus_assert_not_reached ("Reached end of arguments");
6003   
6004   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_BYTE)
6005     {
6006       _dbus_warn ("type was: %d\n", dbus_message_iter_get_arg_type (&iter));
6007       _dbus_assert_not_reached ("wrong type after dict (should be byte)");
6008     }
6009   
6010   if (dbus_message_iter_get_byte (&iter) != 0xF0)
6011     _dbus_assert_not_reached ("wrong value after dict");
6012
6013
6014   if (!dbus_message_iter_next (&iter))
6015     _dbus_assert_not_reached ("Reached end of arguments");
6016   
6017   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_NIL)
6018     _dbus_assert_not_reached ("not a nil type");
6019   
6020   if (!dbus_message_iter_next (&iter))
6021     _dbus_assert_not_reached ("Reached end of arguments");
6022   
6023   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_CUSTOM)
6024     _dbus_assert_not_reached ("wrong type after dict");
6025
6026   if (!dbus_message_iter_get_custom (&iter, &str, &data, &len))
6027     _dbus_assert_not_reached ("failed to get custom type");
6028
6029   _dbus_assert (strcmp (str, "MyTypeName")==0);
6030   _dbus_assert (len == 5);
6031   _dbus_assert (strcmp (data, "data")==0);
6032   dbus_free (str);
6033   dbus_free (data);
6034   
6035   if (!dbus_message_iter_next (&iter))
6036     _dbus_assert_not_reached ("Reached end of arguments");
6037
6038   if (dbus_message_iter_get_byte (&iter) != 0xF0)
6039     _dbus_assert_not_reached ("wrong value after custom");
6040
6041   if (dbus_message_iter_next (&iter))
6042     _dbus_assert_not_reached ("Didn't reach end of arguments");
6043 }
6044
6045
6046 static dbus_bool_t
6047 check_message_handling_type (DBusMessageIter *iter,
6048                              int type)
6049 {
6050   DBusMessageIter child_iter;
6051   
6052   switch (type)
6053     {
6054     case DBUS_TYPE_NIL:
6055       break;
6056     case DBUS_TYPE_BYTE:
6057       dbus_message_iter_get_byte (iter);
6058       break;
6059     case DBUS_TYPE_BOOLEAN:
6060       dbus_message_iter_get_boolean (iter);
6061       break;
6062     case DBUS_TYPE_INT32:
6063       dbus_message_iter_get_int32 (iter);
6064       break;
6065     case DBUS_TYPE_UINT32:
6066       dbus_message_iter_get_uint32 (iter);
6067       break;
6068     case DBUS_TYPE_INT64:
6069 #ifdef DBUS_HAVE_INT64
6070       dbus_message_iter_get_int64 (iter);
6071 #endif
6072       break;
6073     case DBUS_TYPE_UINT64:
6074 #ifdef DBUS_HAVE_INT64
6075       dbus_message_iter_get_uint64 (iter);
6076 #endif
6077       break;
6078     case DBUS_TYPE_DOUBLE:
6079       dbus_message_iter_get_double (iter);
6080       break;
6081     case DBUS_TYPE_STRING:
6082       {
6083         char *str;
6084         str = dbus_message_iter_get_string (iter);
6085         if (str == NULL)
6086           {
6087             _dbus_warn ("NULL string in message\n");
6088             return FALSE;
6089           }
6090         dbus_free (str);
6091       }
6092       break;
6093     case DBUS_TYPE_CUSTOM:
6094       {
6095         char *name;
6096         unsigned char *data;
6097         int len;
6098         
6099         if (!dbus_message_iter_get_custom (iter, &name, &data, &len))
6100           {
6101             _dbus_warn ("error reading name from custom type\n");
6102             return FALSE;
6103           }
6104         dbus_free (data);
6105         dbus_free (name);
6106       }
6107       break;
6108     case DBUS_TYPE_ARRAY:
6109       {
6110         int array_type;
6111
6112         dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type);
6113
6114         while (dbus_message_iter_has_next (&child_iter))
6115           {
6116             if (!check_message_handling_type (&child_iter, array_type))
6117               {
6118                 _dbus_warn ("error in array element\n");
6119                 return FALSE;
6120               }
6121             
6122             if (!dbus_message_iter_next (&child_iter))
6123               break;
6124           }
6125       }
6126       break;
6127     case DBUS_TYPE_DICT:
6128       {
6129         int entry_type;
6130         char *key;
6131         
6132         dbus_message_iter_init_dict_iterator (iter, &child_iter);
6133
6134         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
6135           {
6136             key = dbus_message_iter_get_dict_key (&child_iter);
6137             if (key == NULL)
6138               {
6139                 _dbus_warn ("error reading dict key\n");
6140                 return FALSE;
6141               }
6142             dbus_free (key);
6143             
6144             if (!check_message_handling_type (&child_iter, entry_type))
6145               {
6146                 _dbus_warn ("error in dict value\n");
6147                 return FALSE;
6148               }
6149             
6150             if (!dbus_message_iter_next (&child_iter))
6151               break;
6152           }
6153       }
6154       break;
6155       
6156     default:
6157       _dbus_warn ("unknown type %d\n", type);
6158       return FALSE;
6159       break;
6160     }
6161   return TRUE;
6162 }
6163   
6164   
6165 static dbus_bool_t
6166 check_message_handling (DBusMessage *message)
6167 {
6168   DBusMessageIter iter;
6169   int type;
6170   dbus_bool_t retval;
6171   dbus_uint32_t client_serial;
6172   
6173   retval = FALSE;
6174   
6175   client_serial = dbus_message_get_serial (message);
6176
6177   /* can't use set_serial due to the assertions at the start of it */
6178   _dbus_marshal_set_uint32 (&message->header,
6179                             message->byte_order,
6180                             CLIENT_SERIAL_OFFSET,
6181                             client_serial);
6182   
6183   if (client_serial != dbus_message_get_serial (message))
6184     {
6185       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
6186       goto failed;
6187     }
6188   
6189   /* If we implement message_set_arg (message, n, value)
6190    * then we would want to test it here
6191    */
6192
6193   dbus_message_iter_init (message, &iter);
6194   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
6195     {
6196       if (!check_message_handling_type (&iter, type))
6197         goto failed;
6198
6199       if (!dbus_message_iter_next (&iter))
6200         break;
6201     }
6202   
6203   retval = TRUE;
6204   
6205  failed:
6206   return retval;
6207 }
6208
6209 static dbus_bool_t
6210 check_have_valid_message (DBusMessageLoader *loader)
6211 {
6212   DBusMessage *message;
6213   dbus_bool_t retval;
6214
6215   message = NULL;
6216   retval = FALSE;
6217
6218   if (!_dbus_message_loader_queue_messages (loader))
6219     _dbus_assert_not_reached ("no memory to queue messages");
6220   
6221   if (_dbus_message_loader_get_is_corrupted (loader))
6222     {
6223       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
6224       goto failed;
6225     }
6226   
6227   message = _dbus_message_loader_pop_message (loader);
6228   if (message == NULL)
6229     {
6230       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
6231       goto failed;
6232     }
6233   
6234   if (_dbus_string_get_length (&loader->data) > 0)
6235     {
6236       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
6237       goto failed;
6238     }
6239
6240   /* Verify that we're able to properly deal with the message.
6241    * For example, this would detect improper handling of messages
6242    * in nonstandard byte order.
6243    */
6244   if (!check_message_handling (message))
6245     goto failed;  
6246   
6247   retval = TRUE;
6248
6249  failed:
6250   if (message)
6251     dbus_message_unref (message);
6252
6253   return retval;
6254 }
6255
6256 static dbus_bool_t
6257 check_invalid_message (DBusMessageLoader *loader)
6258 {
6259   dbus_bool_t retval;
6260
6261   retval = FALSE;
6262
6263   if (!_dbus_message_loader_queue_messages (loader))
6264     _dbus_assert_not_reached ("no memory to queue messages");
6265   
6266   if (!_dbus_message_loader_get_is_corrupted (loader))
6267     {
6268       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
6269       goto failed;
6270     }
6271
6272   retval = TRUE;
6273
6274  failed:
6275   return retval;
6276 }
6277
6278 static dbus_bool_t
6279 check_incomplete_message (DBusMessageLoader *loader)
6280 {
6281   DBusMessage *message;
6282   dbus_bool_t retval;
6283
6284   message = NULL;
6285   retval = FALSE;
6286
6287   if (!_dbus_message_loader_queue_messages (loader))
6288     _dbus_assert_not_reached ("no memory to queue messages");
6289   
6290   if (_dbus_message_loader_get_is_corrupted (loader))
6291     {
6292       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
6293       goto failed;
6294     }
6295   
6296   message = _dbus_message_loader_pop_message (loader);
6297   if (message != NULL)
6298     {
6299       _dbus_warn ("loaded message that was expected to be incomplete\n");
6300       goto failed;
6301     }
6302
6303   retval = TRUE;
6304
6305  failed:
6306   if (message)
6307     dbus_message_unref (message);
6308   return retval;
6309 }
6310
6311 static dbus_bool_t
6312 check_loader_results (DBusMessageLoader      *loader,
6313                       DBusMessageValidity     validity)
6314 {
6315   if (!_dbus_message_loader_queue_messages (loader))
6316     _dbus_assert_not_reached ("no memory to queue messages");
6317   
6318   switch (validity)
6319     {
6320     case _DBUS_MESSAGE_VALID:
6321       return check_have_valid_message (loader);
6322     case _DBUS_MESSAGE_INVALID:
6323       return check_invalid_message (loader);
6324     case _DBUS_MESSAGE_INCOMPLETE:
6325       return check_incomplete_message (loader);
6326     case _DBUS_MESSAGE_UNKNOWN:
6327       return TRUE;
6328     }
6329
6330   _dbus_assert_not_reached ("bad DBusMessageValidity");
6331   return FALSE;
6332 }
6333
6334
6335 /**
6336  * Loads the message in the given message file.
6337  *
6338  * @param filename filename to load
6339  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
6340  * @param data string to load message into
6341  * @returns #TRUE if the message was loaded
6342  */
6343 dbus_bool_t
6344 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
6345                                             dbus_bool_t          is_raw,
6346                                             DBusString          *data)
6347 {
6348   dbus_bool_t retval;
6349
6350   retval = FALSE;  
6351
6352   if (is_raw)
6353     {
6354       DBusError error;
6355
6356       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
6357       dbus_error_init (&error);
6358       if (!_dbus_file_get_contents (data, filename, &error))
6359         {
6360           _dbus_warn ("Could not load message file %s: %s\n",
6361                       _dbus_string_get_const_data (filename),
6362                       error.message);
6363           dbus_error_free (&error);
6364           goto failed;
6365         }
6366     }
6367   else
6368     {
6369       if (!_dbus_message_data_load (data, filename))
6370         {
6371           _dbus_warn ("Could not load message file %s\n",
6372                       _dbus_string_get_const_data (filename));
6373           goto failed;
6374         }
6375     }
6376
6377   retval = TRUE;
6378   
6379  failed:
6380
6381   return retval;
6382 }
6383
6384 /**
6385  * Tries loading the message in the given message file
6386  * and verifies that DBusMessageLoader can handle it.
6387  *
6388  * @param filename filename to load
6389  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
6390  * @param expected_validity what the message has to be like to return #TRUE
6391  * @returns #TRUE if the message has the expected validity
6392  */
6393 dbus_bool_t
6394 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
6395                                            dbus_bool_t          is_raw,
6396                                            DBusMessageValidity  expected_validity)
6397 {
6398   DBusString data;
6399   dbus_bool_t retval;
6400
6401   retval = FALSE;
6402   
6403   if (!_dbus_string_init (&data))
6404     _dbus_assert_not_reached ("could not allocate string\n");
6405
6406   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
6407                                                    &data))
6408     goto failed;
6409
6410   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
6411
6412  failed:
6413
6414   if (!retval)
6415     {
6416       if (_dbus_string_get_length (&data) > 0)
6417         _dbus_verbose_bytes_of_string (&data, 0,
6418                                        _dbus_string_get_length (&data));
6419       
6420       _dbus_warn ("Failed message loader test on %s\n",
6421                   _dbus_string_get_const_data (filename));
6422     }
6423   
6424   _dbus_string_free (&data);
6425
6426   return retval;
6427 }
6428
6429 /**
6430  * Tries loading the given message data.
6431  *
6432  *
6433  * @param data the message data
6434  * @param expected_validity what the message has to be like to return #TRUE
6435  * @returns #TRUE if the message has the expected validity
6436  */
6437 dbus_bool_t
6438 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
6439                                            DBusMessageValidity  expected_validity)
6440 {
6441   DBusMessageLoader *loader;
6442   dbus_bool_t retval;
6443   int len;
6444   int i;
6445
6446   loader = NULL;
6447   retval = FALSE;
6448
6449   /* Write the data one byte at a time */
6450   
6451   loader = _dbus_message_loader_new ();
6452
6453   /* check some trivial loader functions */
6454   _dbus_message_loader_ref (loader);
6455   _dbus_message_loader_unref (loader);
6456   _dbus_message_loader_get_max_message_size (loader);
6457   
6458   len = _dbus_string_get_length (data);
6459   for (i = 0; i < len; i++)
6460     {
6461       DBusString *buffer;
6462
6463       _dbus_message_loader_get_buffer (loader, &buffer);
6464       _dbus_string_append_byte (buffer,
6465                                 _dbus_string_get_byte (data, i));
6466       _dbus_message_loader_return_buffer (loader, buffer, 1);
6467     }
6468   
6469   if (!check_loader_results (loader, expected_validity))
6470     goto failed;
6471
6472   _dbus_message_loader_unref (loader);
6473   loader = NULL;
6474
6475   /* Write the data all at once */
6476   
6477   loader = _dbus_message_loader_new ();
6478
6479   {
6480     DBusString *buffer;
6481     
6482     _dbus_message_loader_get_buffer (loader, &buffer);
6483     _dbus_string_copy (data, 0, buffer,
6484                        _dbus_string_get_length (buffer));
6485     _dbus_message_loader_return_buffer (loader, buffer, 1);
6486   }
6487   
6488   if (!check_loader_results (loader, expected_validity))
6489     goto failed;
6490
6491   _dbus_message_loader_unref (loader);
6492   loader = NULL;  
6493
6494   /* Write the data 2 bytes at a time */
6495   
6496   loader = _dbus_message_loader_new ();
6497
6498   len = _dbus_string_get_length (data);
6499   for (i = 0; i < len; i += 2)
6500     {
6501       DBusString *buffer;
6502
6503       _dbus_message_loader_get_buffer (loader, &buffer);
6504       _dbus_string_append_byte (buffer,
6505                                 _dbus_string_get_byte (data, i));
6506       if ((i+1) < len)
6507         _dbus_string_append_byte (buffer,
6508                                   _dbus_string_get_byte (data, i+1));
6509       _dbus_message_loader_return_buffer (loader, buffer, 1);
6510     }
6511   
6512   if (!check_loader_results (loader, expected_validity))
6513     goto failed;
6514
6515   _dbus_message_loader_unref (loader);
6516   loader = NULL;
6517   
6518   retval = TRUE;
6519   
6520  failed:
6521   
6522   if (loader)
6523     _dbus_message_loader_unref (loader);
6524   
6525   return retval;
6526 }
6527
6528 static dbus_bool_t
6529 process_test_subdir (const DBusString          *test_base_dir,
6530                      const char                *subdir,
6531                      DBusMessageValidity        validity,
6532                      DBusForeachMessageFileFunc function,
6533                      void                      *user_data)
6534 {
6535   DBusString test_directory;
6536   DBusString filename;
6537   DBusDirIter *dir;
6538   dbus_bool_t retval;
6539   DBusError error;
6540
6541   retval = FALSE;
6542   dir = NULL;
6543   
6544   if (!_dbus_string_init (&test_directory))
6545     _dbus_assert_not_reached ("didn't allocate test_directory\n");
6546
6547   _dbus_string_init_const (&filename, subdir);
6548   
6549   if (!_dbus_string_copy (test_base_dir, 0,
6550                           &test_directory, 0))
6551     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
6552   
6553   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
6554     _dbus_assert_not_reached ("couldn't allocate full path");
6555
6556   _dbus_string_free (&filename);
6557   if (!_dbus_string_init (&filename))
6558     _dbus_assert_not_reached ("didn't allocate filename string\n");
6559
6560   dbus_error_init (&error);
6561   dir = _dbus_directory_open (&test_directory, &error);
6562   if (dir == NULL)
6563     {
6564       _dbus_warn ("Could not open %s: %s\n",
6565                   _dbus_string_get_const_data (&test_directory),
6566                   error.message);
6567       dbus_error_free (&error);
6568       goto failed;
6569     }
6570
6571   printf ("Testing %s:\n", subdir);
6572   
6573  next:
6574   while (_dbus_directory_get_next_file (dir, &filename, &error))
6575     {
6576       DBusString full_path;
6577       dbus_bool_t is_raw;
6578       
6579       if (!_dbus_string_init (&full_path))
6580         _dbus_assert_not_reached ("couldn't init string");
6581
6582       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
6583         _dbus_assert_not_reached ("couldn't copy dir to full_path");
6584
6585       if (!_dbus_concat_dir_and_file (&full_path, &filename))
6586         _dbus_assert_not_reached ("couldn't concat file to dir");
6587
6588       if (_dbus_string_ends_with_c_str (&filename, ".message"))
6589         is_raw = FALSE;
6590       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
6591         is_raw = TRUE;
6592       else
6593         {
6594           _dbus_verbose ("Skipping non-.message file %s\n",
6595                          _dbus_string_get_const_data (&filename));
6596           _dbus_string_free (&full_path);
6597           goto next;
6598         }
6599
6600       printf ("    %s\n",
6601               _dbus_string_get_const_data (&filename));
6602       
6603       _dbus_verbose (" expecting %s for %s\n",
6604                      validity == _DBUS_MESSAGE_VALID ? "valid" :
6605                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
6606                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")),
6607                      _dbus_string_get_const_data (&filename));
6608       
6609       if (! (*function) (&full_path, is_raw, validity, user_data))
6610         {
6611           _dbus_string_free (&full_path);
6612           goto failed;
6613         }
6614       else
6615         _dbus_string_free (&full_path);
6616     }
6617
6618   if (dbus_error_is_set (&error))
6619     {
6620       _dbus_warn ("Could not get next file in %s: %s\n",
6621                   _dbus_string_get_const_data (&test_directory),
6622                   error.message);
6623       dbus_error_free (&error);
6624       goto failed;
6625     }
6626     
6627   retval = TRUE;
6628   
6629  failed:
6630
6631   if (dir)
6632     _dbus_directory_close (dir);
6633   _dbus_string_free (&test_directory);
6634   _dbus_string_free (&filename);
6635
6636   return retval;
6637 }
6638                      
6639 /**
6640  * Runs the given function on every message file in the test suite.
6641  * The function should return #FALSE on test failure or fatal error.
6642  *
6643  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
6644  * @param func the function to run
6645  * @param user_data data for function
6646  * @returns #FALSE if there's a failure
6647  */
6648 dbus_bool_t
6649 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
6650                                                DBusForeachMessageFileFunc func,
6651                                                void                      *user_data)
6652 {
6653   DBusString test_directory;
6654   dbus_bool_t retval;
6655
6656   retval = FALSE;
6657   
6658   _dbus_string_init_const (&test_directory, test_data_dir);
6659
6660   if (!process_test_subdir (&test_directory, "valid-messages",
6661                             _DBUS_MESSAGE_VALID, func, user_data))
6662     goto failed;
6663
6664   if (!process_test_subdir (&test_directory, "invalid-messages",
6665                             _DBUS_MESSAGE_INVALID, func, user_data))
6666     goto failed;
6667   
6668   if (!process_test_subdir (&test_directory, "incomplete-messages",
6669                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
6670     goto failed;
6671
6672   retval = TRUE;
6673   
6674  failed:
6675
6676   _dbus_string_free (&test_directory);
6677   
6678   return retval;
6679 }
6680
6681 static void
6682 verify_test_message (DBusMessage *message)
6683 {
6684   DBusMessageIter iter, dict;
6685   DBusError error;
6686   dbus_int32_t our_int;
6687   char *our_str;
6688   double our_double;
6689   dbus_bool_t our_bool;
6690   dbus_uint32_t our_uint32;
6691   dbus_int32_t *our_uint32_array;
6692   int our_uint32_array_len;
6693   dbus_int32_t *our_int32_array;
6694   int our_int32_array_len;
6695   char **our_string_array;
6696   int our_string_array_len;
6697 #ifdef DBUS_HAVE_INT64
6698   dbus_int64_t our_int64;
6699   dbus_uint64_t our_uint64;
6700   dbus_int64_t *our_uint64_array;
6701   int our_uint64_array_len;
6702   dbus_int64_t *our_int64_array;
6703   int our_int64_array_len;
6704 #endif
6705   double *our_double_array;
6706   int our_double_array_len;
6707   unsigned char *our_byte_array;
6708   int our_byte_array_len;
6709   unsigned char *our_boolean_array;
6710   int our_boolean_array_len;
6711   
6712   dbus_message_iter_init (message, &iter);
6713
6714   dbus_error_init (&error);
6715   if (!dbus_message_iter_get_args (&iter, &error,
6716                                    DBUS_TYPE_INT32, &our_int,
6717 #ifdef DBUS_HAVE_INT64
6718                                    DBUS_TYPE_INT64, &our_int64,
6719                                    DBUS_TYPE_UINT64, &our_uint64,
6720 #endif
6721                                    DBUS_TYPE_STRING, &our_str,
6722                                    DBUS_TYPE_DOUBLE, &our_double,
6723                                    DBUS_TYPE_BOOLEAN, &our_bool,
6724                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32,
6725                                    &our_uint32_array, &our_uint32_array_len,
6726                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
6727                                    &our_int32_array, &our_int32_array_len,
6728 #ifdef DBUS_HAVE_INT64
6729                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64,
6730                                    &our_uint64_array, &our_uint64_array_len,
6731                                    DBUS_TYPE_ARRAY, DBUS_TYPE_INT64,
6732                                    &our_int64_array, &our_int64_array_len,
6733 #endif
6734                                    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
6735                                    &our_string_array, &our_string_array_len,
6736                                    DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE,
6737                                    &our_double_array, &our_double_array_len,
6738                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
6739                                    &our_byte_array, &our_byte_array_len,
6740                                    DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN,
6741                                    &our_boolean_array, &our_boolean_array_len,
6742                                    0))
6743     {
6744       _dbus_warn ("error: %s - %s\n", error.name,
6745                   (error.message != NULL) ? error.message : "no message");
6746       _dbus_assert_not_reached ("Could not get arguments");
6747     }
6748
6749   if (our_int != -0x12345678)
6750     _dbus_assert_not_reached ("integers differ!");
6751
6752 #ifdef DBUS_HAVE_INT64
6753   if (our_int64 != DBUS_INT64_CONSTANT (-0x123456789abcd))
6754     _dbus_assert_not_reached ("64-bit integers differ!");
6755   if (our_uint64 != DBUS_UINT64_CONSTANT (0x123456789abcd))
6756     _dbus_assert_not_reached ("64-bit unsigned integers differ!");
6757 #endif
6758   
6759   if (our_double != 3.14159)
6760     _dbus_assert_not_reached ("doubles differ!");
6761
6762   if (strcmp (our_str, "Test string") != 0)
6763     _dbus_assert_not_reached ("strings differ!");
6764   dbus_free (our_str);
6765
6766   if (!our_bool)
6767     _dbus_assert_not_reached ("booleans differ");
6768
6769   if (our_uint32_array_len != 4 ||
6770       our_uint32_array[0] != 0x12345678 ||
6771       our_uint32_array[1] != 0x23456781 ||
6772       our_uint32_array[2] != 0x34567812 ||
6773       our_uint32_array[3] != 0x45678123)
6774     _dbus_assert_not_reached ("uint array differs");
6775   dbus_free (our_uint32_array);
6776
6777   if (our_int32_array_len != 4 ||
6778       our_int32_array[0] != 0x12345678 ||
6779       our_int32_array[1] != -0x23456781 ||
6780       our_int32_array[2] != 0x34567812 ||
6781       our_int32_array[3] != -0x45678123)
6782     _dbus_assert_not_reached ("int array differs");
6783   dbus_free (our_int32_array);
6784
6785 #ifdef DBUS_HAVE_INT64
6786   if (our_uint64_array_len != 4 ||
6787       our_uint64_array[0] != 0x12345678 ||
6788       our_uint64_array[1] != 0x23456781 ||
6789       our_uint64_array[2] != 0x34567812 ||
6790       our_uint64_array[3] != 0x45678123)
6791     _dbus_assert_not_reached ("uint64 array differs");
6792   dbus_free (our_uint64_array);
6793   
6794   if (our_int64_array_len != 4 ||
6795       our_int64_array[0] != 0x12345678 ||
6796       our_int64_array[1] != -0x23456781 ||
6797       our_int64_array[2] != 0x34567812 ||
6798       our_int64_array[3] != -0x45678123)
6799     _dbus_assert_not_reached ("int64 array differs");
6800   dbus_free (our_int64_array);
6801 #endif /* DBUS_HAVE_INT64 */
6802   
6803   if (our_string_array_len != 4)
6804     _dbus_assert_not_reached ("string array has wrong length");
6805
6806   if (strcmp (our_string_array[0], "Foo") != 0 ||
6807       strcmp (our_string_array[1], "bar") != 0 ||
6808       strcmp (our_string_array[2], "") != 0 ||
6809       strcmp (our_string_array[3], "woo woo woo woo") != 0)
6810     _dbus_assert_not_reached ("string array differs");
6811
6812   dbus_free_string_array (our_string_array);
6813
6814   if (our_double_array_len != 3)
6815     _dbus_assert_not_reached ("double array had wrong length");
6816
6817   /* On all IEEE machines (i.e. everything sane) exact equality
6818    * should be preserved over the wire
6819    */
6820   if (our_double_array[0] != 0.1234 ||
6821       our_double_array[1] != 9876.54321 ||
6822       our_double_array[2] != -300.0)
6823     _dbus_assert_not_reached ("double array had wrong values");
6824
6825   dbus_free (our_double_array);
6826
6827   if (our_byte_array_len != 4)
6828     _dbus_assert_not_reached ("byte array had wrong length");
6829
6830   if (our_byte_array[0] != 'a' ||
6831       our_byte_array[1] != 'b' ||
6832       our_byte_array[2] != 'c' ||
6833       our_byte_array[3] != 234)
6834     _dbus_assert_not_reached ("byte array had wrong values");
6835
6836   dbus_free (our_byte_array);
6837
6838   if (our_boolean_array_len != 5)
6839     _dbus_assert_not_reached ("bool array had wrong length");
6840
6841   if (our_boolean_array[0] != TRUE ||
6842       our_boolean_array[1] != FALSE ||
6843       our_boolean_array[2] != TRUE ||
6844       our_boolean_array[3] != TRUE ||
6845       our_boolean_array[4] != FALSE)
6846     _dbus_assert_not_reached ("bool array had wrong values");
6847
6848   dbus_free (our_boolean_array);
6849   
6850   if (!dbus_message_iter_next (&iter))
6851     _dbus_assert_not_reached ("Reached end of arguments");
6852
6853   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
6854     _dbus_assert_not_reached ("not dict type");
6855      
6856   dbus_message_iter_init_dict_iterator (&iter, &dict);
6857
6858   our_str = dbus_message_iter_get_dict_key (&dict);
6859   if (our_str == NULL || strcmp (our_str, "test") != 0)
6860     _dbus_assert_not_reached ("wrong dict key");
6861   dbus_free (our_str);
6862
6863   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
6864     {
6865       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
6866       _dbus_assert_not_reached ("wrong dict entry type");
6867     }
6868
6869   if ((our_uint32 = dbus_message_iter_get_uint32 (&dict)) != 0xDEADBEEF)
6870     {
6871       _dbus_verbose ("dict entry val: %x\n", our_uint32);
6872       _dbus_assert_not_reached ("wrong dict entry value");
6873     }
6874
6875   if (dbus_message_iter_next (&dict))
6876     _dbus_assert_not_reached ("Didn't reach end of dict");
6877   
6878   if (!dbus_message_iter_next (&iter))
6879     _dbus_assert_not_reached ("Reached end of arguments");
6880   
6881   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
6882     _dbus_assert_not_reached ("wrong type after dict");
6883   
6884   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
6885     _dbus_assert_not_reached ("wrong value after dict");
6886
6887   if (dbus_message_iter_next (&iter))
6888     _dbus_assert_not_reached ("Didn't reach end of arguments");
6889 }
6890
6891 /**
6892  * @ingroup DBusMessageInternals
6893  * Unit test for DBusMessage.
6894  *
6895  * @returns #TRUE on success.
6896  */
6897 dbus_bool_t
6898 _dbus_message_test (const char *test_data_dir)
6899 {
6900   DBusMessage *message;
6901   DBusMessageLoader *loader;
6902   DBusMessageIter iter, child_iter, child_iter2, child_iter3;
6903   int i;
6904   const char *data;
6905   DBusMessage *copy;
6906   const char *name1;
6907   const char *name2;
6908   const dbus_uint32_t our_uint32_array[] =
6909     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
6910   const dbus_uint32_t our_int32_array[] =
6911     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
6912 #ifdef DBUS_HAVE_INT64
6913   const dbus_uint64_t our_uint64_array[] =
6914     { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
6915   const dbus_uint64_t our_int64_array[] =
6916     { 0x12345678, -0x23456781, 0x34567812, -0x45678123 };
6917 #endif
6918   const char *our_string_array[] = { "Foo", "bar", "", "woo woo woo woo" };
6919   const double our_double_array[] = { 0.1234, 9876.54321, -300.0 };
6920   const unsigned char our_byte_array[] = { 'a', 'b', 'c', 234 };
6921   const unsigned char our_boolean_array[] = { TRUE, FALSE, TRUE, TRUE, FALSE };
6922   char sig[64];
6923   const char *s;
6924   char *t;
6925   DBusError error;
6926   
6927   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
6928
6929   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
6930                                           "/org/freedesktop/TestPath",
6931                                           "Foo.TestInterface",
6932                                           "TestMethod");
6933   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
6934   _dbus_assert (dbus_message_is_method_call (message, "Foo.TestInterface",
6935                                              "TestMethod"));
6936   _dbus_assert (strcmp (dbus_message_get_path (message),
6937                         "/org/freedesktop/TestPath") == 0);
6938   _dbus_message_set_serial (message, 1234);
6939   /* string length including nul byte not a multiple of 4 */
6940   if (!dbus_message_set_sender (message, "org.foo.bar1"))
6941     _dbus_assert_not_reached ("out of memory");
6942   _dbus_assert (dbus_message_has_sender (message, "org.foo.bar1"));
6943   dbus_message_set_reply_serial (message, 5678);
6944   if (!dbus_message_set_sender (message, NULL))
6945     _dbus_assert_not_reached ("out of memory");
6946   _dbus_assert (!dbus_message_has_sender (message, "org.foo.bar1"));
6947   _dbus_assert (dbus_message_get_serial (message) == 1234);
6948   _dbus_assert (dbus_message_get_reply_serial (message) == 5678);
6949   _dbus_assert (dbus_message_has_destination (message, "org.freedesktop.DBus.TestService"));
6950
6951   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
6952   dbus_message_set_no_reply (message, TRUE);
6953   _dbus_assert (dbus_message_get_no_reply (message) == TRUE);
6954   dbus_message_set_no_reply (message, FALSE);
6955   _dbus_assert (dbus_message_get_no_reply (message) == FALSE);
6956
6957   /* Set/get some header fields */
6958   
6959   if (!dbus_message_set_path (message, "/foo"))
6960     _dbus_assert_not_reached ("out of memory");
6961   _dbus_assert (strcmp (dbus_message_get_path (message),
6962                         "/foo") == 0);
6963
6964   if (!dbus_message_set_interface (message, "org.Foo"))
6965     _dbus_assert_not_reached ("out of memory");
6966   _dbus_assert (strcmp (dbus_message_get_interface (message),
6967                         "org.Foo") == 0);
6968   
6969   if (!dbus_message_set_member (message, "Bar"))
6970     _dbus_assert_not_reached ("out of memory");
6971   _dbus_assert (strcmp (dbus_message_get_member (message),
6972                         "Bar") == 0);
6973
6974   /* Set/get them with longer values */
6975   if (!dbus_message_set_path (message, "/foo/bar"))
6976     _dbus_assert_not_reached ("out of memory");
6977   _dbus_assert (strcmp (dbus_message_get_path (message),
6978                         "/foo/bar") == 0);
6979
6980   if (!dbus_message_set_interface (message, "org.Foo.Bar"))
6981     _dbus_assert_not_reached ("out of memory");
6982   _dbus_assert (strcmp (dbus_message_get_interface (message),
6983                         "org.Foo.Bar") == 0);
6984   
6985   if (!dbus_message_set_member (message, "BarFoo"))
6986     _dbus_assert_not_reached ("out of memory");
6987   _dbus_assert (strcmp (dbus_message_get_member (message),
6988                         "BarFoo") == 0);
6989
6990   /* Realloc shorter again */
6991   
6992   if (!dbus_message_set_path (message, "/foo"))
6993     _dbus_assert_not_reached ("out of memory");
6994   _dbus_assert (strcmp (dbus_message_get_path (message),
6995                         "/foo") == 0);
6996
6997   if (!dbus_message_set_interface (message, "org.Foo"))
6998     _dbus_assert_not_reached ("out of memory");
6999   _dbus_assert (strcmp (dbus_message_get_interface (message),
7000                         "org.Foo") == 0);
7001   
7002   if (!dbus_message_set_member (message, "Bar"))
7003     _dbus_assert_not_reached ("out of memory");
7004   _dbus_assert (strcmp (dbus_message_get_member (message),
7005                         "Bar") == 0);
7006   
7007   dbus_message_unref (message);
7008   
7009   /* Test the vararg functions */
7010   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
7011                                           "/org/freedesktop/TestPath",
7012                                           "Foo.TestInterface",
7013                                           "TestMethod");
7014   _dbus_message_set_serial (message, 1);
7015   dbus_message_append_args (message,
7016                             DBUS_TYPE_INT32, -0x12345678,
7017 #ifdef DBUS_HAVE_INT64
7018                             DBUS_TYPE_INT64, DBUS_INT64_CONSTANT (-0x123456789abcd),
7019                             DBUS_TYPE_UINT64, DBUS_UINT64_CONSTANT (0x123456789abcd),
7020 #endif
7021                             DBUS_TYPE_STRING, "Test string",
7022                             DBUS_TYPE_DOUBLE, 3.14159,
7023                             DBUS_TYPE_BOOLEAN, TRUE,
7024                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_uint32_array,
7025                             _DBUS_N_ELEMENTS (our_uint32_array),
7026                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, our_int32_array,
7027                             _DBUS_N_ELEMENTS (our_int32_array),
7028 #ifdef DBUS_HAVE_INT64
7029                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT64, our_uint64_array,
7030                             _DBUS_N_ELEMENTS (our_uint64_array),
7031                             DBUS_TYPE_ARRAY, DBUS_TYPE_INT64, our_int64_array,
7032                             _DBUS_N_ELEMENTS (our_int64_array),
7033 #endif
7034                             DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, our_string_array,
7035                             _DBUS_N_ELEMENTS (our_string_array),
7036                             DBUS_TYPE_ARRAY, DBUS_TYPE_DOUBLE, our_double_array,
7037                             _DBUS_N_ELEMENTS (our_double_array),
7038                             DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, our_byte_array,
7039                             _DBUS_N_ELEMENTS (our_byte_array),
7040                             DBUS_TYPE_ARRAY, DBUS_TYPE_BOOLEAN, our_boolean_array,
7041                             _DBUS_N_ELEMENTS (our_boolean_array),
7042                             0);
7043   
7044   dbus_message_append_iter_init (message, &iter);
7045   dbus_message_iter_append_dict (&iter, &child_iter);
7046   dbus_message_iter_append_dict_key (&child_iter, "test");
7047   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
7048   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
7049
7050   i = 0;
7051   sig[i++] = DBUS_TYPE_INT32;
7052 #ifdef DBUS_HAVE_INT64
7053   sig[i++] = DBUS_TYPE_INT64;
7054   sig[i++] = DBUS_TYPE_UINT64;
7055 #endif
7056   sig[i++] = DBUS_TYPE_STRING;
7057   sig[i++] = DBUS_TYPE_DOUBLE;
7058   sig[i++] = DBUS_TYPE_BOOLEAN;
7059   sig[i++] = DBUS_TYPE_ARRAY;
7060   sig[i++] = DBUS_TYPE_UINT32;
7061   sig[i++] = DBUS_TYPE_ARRAY;
7062   sig[i++] = DBUS_TYPE_INT32;
7063 #ifdef DBUS_HAVE_INT64
7064   sig[i++] = DBUS_TYPE_ARRAY;
7065   sig[i++] = DBUS_TYPE_UINT64;
7066   sig[i++] = DBUS_TYPE_ARRAY;
7067   sig[i++] = DBUS_TYPE_INT64;
7068 #endif
7069   sig[i++] = DBUS_TYPE_ARRAY;
7070   sig[i++] = DBUS_TYPE_STRING;
7071   sig[i++] = DBUS_TYPE_ARRAY;
7072   sig[i++] = DBUS_TYPE_DOUBLE;
7073   sig[i++] = DBUS_TYPE_ARRAY;
7074   sig[i++] = DBUS_TYPE_BYTE;
7075   sig[i++] = DBUS_TYPE_ARRAY;
7076   sig[i++] = DBUS_TYPE_BOOLEAN;
7077   sig[i++] = DBUS_TYPE_DICT;
7078   sig[i++] = DBUS_TYPE_UINT32;
7079   sig[i++] = DBUS_TYPE_INVALID;
7080
7081   _dbus_assert (i < (int) _DBUS_N_ELEMENTS (sig));
7082   
7083   _dbus_verbose_bytes_of_string (&message->header, 0,
7084                                  _dbus_string_get_length (&message->header));
7085   _dbus_verbose_bytes_of_string (&message->body, 0,
7086                                  _dbus_string_get_length (&message->body));
7087   
7088   _dbus_verbose ("Signature expected \"%s\" actual \"%s\"\n",
7089                  sig, dbus_message_get_signature (message));
7090   
7091   s = dbus_message_get_signature (message);
7092   
7093   _dbus_assert (dbus_message_has_signature (message, sig));
7094   _dbus_assert (strcmp (s, sig) == 0);
7095   
7096   verify_test_message (message);
7097
7098   copy = dbus_message_copy (message);
7099   
7100   _dbus_assert (message->client_serial == copy->client_serial);
7101   _dbus_assert (message->reply_serial == copy->reply_serial);
7102   _dbus_assert (message->header_padding == copy->header_padding);
7103   
7104   _dbus_assert (_dbus_string_get_length (&message->header) ==
7105                 _dbus_string_get_length (&copy->header));
7106
7107   _dbus_assert (_dbus_string_get_length (&message->body) ==
7108                 _dbus_string_get_length (&copy->body));
7109
7110   _dbus_assert (_dbus_string_get_length (&message->signature) ==
7111                 _dbus_string_get_length (&copy->signature));
7112   
7113   verify_test_message (copy);
7114
7115   name1 = dbus_message_get_interface (message);
7116   name2 = dbus_message_get_interface (copy);
7117
7118   _dbus_assert (strcmp (name1, name2) == 0);
7119
7120   name1 = dbus_message_get_member (message);
7121   name2 = dbus_message_get_member (copy);
7122
7123   _dbus_assert (strcmp (name1, name2) == 0);
7124   
7125   dbus_message_unref (message);  
7126   dbus_message_unref (copy);
7127
7128   message = dbus_message_new_method_call ("org.freedesktop.DBus.TestService",
7129                                           "/org/freedesktop/TestPath",
7130                                           "Foo.TestInterface",
7131                                           "TestMethod");
7132
7133   _dbus_message_set_serial (message, 1);
7134   dbus_message_set_reply_serial (message, 0x12345678);
7135
7136   dbus_message_append_iter_init (message, &iter);
7137   dbus_message_iter_append_string (&iter, "Test string");
7138   dbus_message_iter_append_int32 (&iter, -0x12345678);
7139   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
7140   dbus_message_iter_append_double (&iter, 3.14159);
7141
7142   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_DOUBLE);
7143   dbus_message_iter_append_double (&child_iter, 1.5);
7144   dbus_message_iter_append_double (&child_iter, 2.5);
7145
7146   /* dict */
7147   dbus_message_iter_append_dict (&iter, &child_iter);
7148   dbus_message_iter_append_dict_key (&child_iter, "test");
7149   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
7150
7151   /* dict (in dict) */
7152   dbus_message_iter_append_dict_key (&child_iter, "testdict");
7153   dbus_message_iter_append_dict (&child_iter, &child_iter2);
7154
7155   dbus_message_iter_append_dict_key (&child_iter2, "dictkey");
7156   dbus_message_iter_append_string (&child_iter2, "dictvalue");
7157
7158   /* array of array of int32  (in dict) */
7159   dbus_message_iter_append_dict_key (&child_iter, "array");
7160   dbus_message_iter_append_array (&child_iter, &child_iter2, DBUS_TYPE_ARRAY);
7161   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
7162   dbus_message_iter_append_int32 (&child_iter3, 0x12345678);
7163   dbus_message_iter_append_int32 (&child_iter3, 0x23456781);
7164   _dbus_warn ("next call expected to fail with wrong array type\n");
7165   _dbus_assert (!dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_UINT32));
7166   dbus_message_iter_append_array (&child_iter2, &child_iter3, DBUS_TYPE_INT32);
7167   dbus_message_iter_append_int32 (&child_iter3, 0x34567812);
7168   dbus_message_iter_append_int32 (&child_iter3, 0x45678123);
7169   dbus_message_iter_append_int32 (&child_iter3, 0x56781234);
7170   
7171   dbus_message_iter_append_byte (&iter, 0xF0);
7172
7173   dbus_message_iter_append_nil (&iter);
7174
7175   dbus_message_iter_append_custom (&iter, "MyTypeName",
7176                                    "data", 5);
7177   
7178   dbus_message_iter_append_byte (&iter, 0xF0);
7179
7180   message_iter_test (message);
7181   
7182   /* Message loader test */
7183   _dbus_message_lock (message);
7184   loader = _dbus_message_loader_new ();
7185
7186   /* check ref/unref */
7187   _dbus_message_loader_ref (loader);
7188   _dbus_message_loader_unref (loader);
7189   
7190   /* Write the header data one byte at a time */
7191   data = _dbus_string_get_const_data (&message->header);
7192   for (i = 0; i < _dbus_string_get_length (&message->header); 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   /* Write the body data one byte at a time */
7202   data = _dbus_string_get_const_data (&message->body);
7203   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
7204     {
7205       DBusString *buffer;
7206
7207       _dbus_message_loader_get_buffer (loader, &buffer);
7208       _dbus_string_append_byte (buffer, data[i]);
7209       _dbus_message_loader_return_buffer (loader, buffer, 1);
7210     }
7211
7212   copy = dbus_message_copy (message); /* save for tests below */
7213   dbus_message_unref (message);
7214
7215   /* Now pop back the message */
7216   if (!_dbus_message_loader_queue_messages (loader))
7217     _dbus_assert_not_reached ("no memory to queue messages");
7218   
7219   if (_dbus_message_loader_get_is_corrupted (loader))
7220     _dbus_assert_not_reached ("message loader corrupted");
7221   
7222   message = _dbus_message_loader_pop_message (loader);
7223   if (!message)
7224     _dbus_assert_not_reached ("received a NULL message");
7225
7226   if (dbus_message_get_reply_serial (message) != 0x12345678)
7227     _dbus_assert_not_reached ("reply serial fields differ");
7228   
7229   message_iter_test (message);
7230   
7231   dbus_message_unref (message);
7232   _dbus_message_loader_unref (loader);
7233
7234   message = dbus_message_new_method_return (copy);
7235   if (message == NULL)
7236     _dbus_assert_not_reached ("out of memory\n");
7237   dbus_message_unref (copy);
7238
7239   if (!dbus_message_append_args (message,
7240                                  DBUS_TYPE_STRING, "hello",
7241                                  DBUS_TYPE_INVALID))
7242     _dbus_assert_not_reached ("no memory");
7243
7244   if (!dbus_message_has_signature (message, "s"))
7245     _dbus_assert_not_reached ("method return has wrong signature");
7246
7247   dbus_error_init (&error);
7248   if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING,
7249                               &t, DBUS_TYPE_INVALID))
7250     
7251     {
7252       _dbus_warn ("Failed to get expected string arg: %s\n", error.message);
7253       exit (1);
7254     }
7255   dbus_free (t);
7256   
7257   dbus_message_unref (message);
7258   
7259   /* Now load every message in test_data_dir if we have one */
7260   if (test_data_dir == NULL)
7261     return TRUE;
7262
7263   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
7264                                                         (DBusForeachMessageFileFunc)
7265                                                         dbus_internal_do_not_use_try_message_file,
7266                                                         NULL);
7267 }
7268
7269 #endif /* DBUS_BUILD_TESTS */