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