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