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