2003-04-10 Havoc Pennington <hp@pobox.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 <string.h>
33
34 /**
35  * @defgroup DBusMessageInternals DBusMessage implementation details
36  * @ingroup DBusInternals
37  * @brief DBusMessage private implementation details.
38  *
39  * The guts of DBusMessage and its methods.
40  *
41  * @{
42  */
43
44 enum
45 {
46   FIELD_HEADER_LENGTH,
47   FIELD_BODY_LENGTH,
48   FIELD_CLIENT_SERIAL,
49   FIELD_NAME,
50   FIELD_SERVICE,
51   FIELD_SENDER,
52   FIELD_REPLY_SERIAL,
53
54   FIELD_LAST
55 };
56
57 static dbus_bool_t field_is_named[FIELD_LAST] =
58 {
59   FALSE, /* FIELD_HEADER_LENGTH */
60   FALSE, /* FIELD_BODY_LENGTH */
61   FALSE, /* FIELD_CLIENT_SERIAL */
62   TRUE,  /* FIELD_NAME */
63   TRUE,  /* FIELD_SERVICE */
64   TRUE,  /* FIELD_SENDER */
65   TRUE   /* FIELD_REPLY_SERIAL */
66 };
67
68 typedef struct
69 {
70   int offset; /**< Offset to start of field (location of name of field
71                * for named fields)
72                */
73 } HeaderField;
74
75 /**
76  * @brief Internals of DBusMessage
77  * 
78  * Object representing a message received from or to be sent to
79  * another application. This is an opaque object, all members
80  * are private.
81  */
82 struct DBusMessage
83 {
84   dbus_atomic_t refcount; /**< Reference count */
85
86   DBusString header; /**< Header network data, stored
87                       * separately from body so we can
88                       * independently realloc it.
89                       */
90
91   HeaderField header_fields[FIELD_LAST]; /**< Track the location
92                                            * of each field in "header"
93                                            */
94
95   dbus_int32_t client_serial; /**< Cached client serial value for speed */
96   dbus_int32_t reply_serial;  /**< Cached reply serial value for speed */
97   
98   int header_padding; /**< bytes of alignment in header */
99   
100   DBusString body;   /**< Body network data. */
101
102   char byte_order; /**< Message byte order. */
103
104   DBusCounter *size_counter; /**< Counter for the size of the message, or #NULL */
105   long size_counter_delta;   /**< Size we incremented the size counter by. */
106
107   dbus_uint32_t changed_stamp;
108   
109   unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
110 };
111
112 enum {
113   DBUS_MESSAGE_ITER_TYPE_MESSAGE,
114   DBUS_MESSAGE_ITER_TYPE_ARRAY,
115   DBUS_MESSAGE_ITER_TYPE_DICT
116 };
117
118 typedef struct DBusMessageRealIter DBusMessageRealIter;
119
120 /**
121  * @brief Internals of DBusMessageIter
122  * 
123  * Object representing a position in a message. All fields are internal.
124  */
125 struct DBusMessageRealIter
126 {
127   DBusMessageRealIter *parent_iter; /**< parent iter, or NULL */
128   DBusMessage *message; /**< Message used */
129   dbus_uint32_t changed_stamp; /**< stamp to detect invalid iters */
130   
131   /* This is an int instead of an enum to get a guaranteed size for the dummy: */
132   int type; /**< type of iter */
133   
134   int pos; /**< Current position in the string */
135   int end; /**< position right after the container */
136   int container_type; /**< type of the items in the container (used for arrays) */
137   int container_start; /**< offset of the start of the container */
138   int container_length_pos; /**< offset of the length of the container */
139   int wrote_dict_key; /**< whether we wrote the dict key for the current dict element */
140 };
141
142 /**
143  * Gets the data to be sent over the network for this message.
144  * The header and then the body should be written out.
145  * This function is guaranteed to always return the same
146  * data once a message is locked (with _dbus_message_lock()).
147  *
148  * @param message the message.
149  * @param header return location for message header data.
150  * @param body return location for message body data.
151  */
152 void
153 _dbus_message_get_network_data (DBusMessage          *message,
154                                 const DBusString    **header,
155                                 const DBusString    **body)
156 {
157   _dbus_assert (message->locked);
158   
159   *header = &message->header;
160   *body = &message->body;
161 }
162
163 static void
164 clear_header_padding (DBusMessage *message)
165 {
166   _dbus_string_shorten (&message->header,
167                         message->header_padding);
168   message->header_padding = 0;
169 }              
170
171 static dbus_bool_t
172 append_header_padding (DBusMessage *message)
173 {
174   int old_len;
175   old_len = _dbus_string_get_length (&message->header);
176   if (!_dbus_string_align_length (&message->header, 8))
177     return FALSE;
178
179   message->header_padding = _dbus_string_get_length (&message->header) - old_len;
180
181   return TRUE;
182 }
183
184 static void
185 adjust_field_offsets (DBusMessage *message,
186                       int          offsets_after,
187                       int          delta)
188 {
189   int i;
190
191   if (delta == 0)
192     return;
193   
194   i = 0;
195   while (i < FIELD_LAST)
196     {
197       if (message->header_fields[i].offset > offsets_after)
198         message->header_fields[i].offset += delta;
199
200       ++i;
201     }
202 }
203
204 static const char*
205 get_string_field (DBusMessage *message,
206                   int          field,
207                   int         *len)
208 {
209   int offset;
210   const char *data;
211
212   offset = message->header_fields[field].offset;
213
214   _dbus_assert (field < FIELD_LAST);
215   
216   if (offset < 0)
217     return NULL;
218
219   /* offset points to string length, string data follows it */
220   /* FIXME _dbus_demarshal_const_string() that returned
221    * a reference to the string plus its len might be nice.
222    */
223   
224   if (len)
225     *len = _dbus_demarshal_uint32 (&message->header,
226                                    message->byte_order,
227                                    offset,
228                                    NULL);
229
230   data = _dbus_string_get_const_data (&message->header);
231   
232   return data + (offset + 4); 
233 }
234
235 static dbus_int32_t
236 get_int_field (DBusMessage *message,
237                int          field)
238 {
239   int offset;
240
241   _dbus_assert (field < FIELD_LAST);
242   
243   offset = message->header_fields[field].offset;
244   
245   if (offset < 0)
246     return -1; /* useless if -1 is a valid value of course */
247   
248   return _dbus_demarshal_int32 (&message->header,
249                                 message->byte_order,
250                                 offset,
251                                 NULL);
252 }
253
254 static dbus_bool_t
255 append_int_field (DBusMessage *message,
256                   int          field,
257                   const char  *name,
258                   int          value)
259 {
260   int orig_len;
261
262   _dbus_assert (!message->locked);
263
264   clear_header_padding (message);
265   
266   orig_len = _dbus_string_get_length (&message->header);
267   
268   if (!_dbus_string_align_length (&message->header, 4))
269     goto failed;  
270   
271   if (!_dbus_string_append_len (&message->header, name, 4))
272     goto failed;
273
274   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
275     goto failed;
276
277   if (!_dbus_string_align_length (&message->header, 4))
278     goto failed;
279   
280   message->header_fields[FIELD_REPLY_SERIAL].offset =
281     _dbus_string_get_length (&message->header);
282   
283   if (!_dbus_marshal_int32 (&message->header, message->byte_order,
284                             value))
285     goto failed;
286
287   if (!append_header_padding (message))
288     goto failed;
289   
290   return TRUE;
291   
292  failed:
293   message->header_fields[field].offset = -1;
294   _dbus_string_set_length (&message->header, orig_len);
295
296   /* this must succeed because it was allocated on function entry and
297    * DBusString doesn't ever realloc smaller
298    */
299   if (!append_header_padding (message))
300     _dbus_assert_not_reached ("failed to reappend header padding");
301   return FALSE;
302 }
303
304 static dbus_bool_t
305 append_string_field (DBusMessage *message,
306                      int          field,
307                      const char  *name,
308                      const char  *value)
309 {
310   int orig_len;
311
312   _dbus_assert (!message->locked);
313
314   clear_header_padding (message);
315   
316   orig_len = _dbus_string_get_length (&message->header);
317
318   if (!_dbus_string_align_length (&message->header, 4))
319     goto failed;
320   
321   if (!_dbus_string_append_len (&message->header, name, 4))
322     goto failed;
323   
324   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_STRING))
325     goto failed;
326
327   if (!_dbus_string_align_length (&message->header, 4))
328     goto failed;
329   
330   message->header_fields[field].offset =
331     _dbus_string_get_length (&message->header);
332   
333   if (!_dbus_marshal_string (&message->header, message->byte_order,
334                              value))
335     goto failed;
336
337   if (!append_header_padding (message))
338     goto failed;
339   
340   return TRUE;
341   
342  failed:
343   message->header_fields[field].offset = -1;
344   _dbus_string_set_length (&message->header, orig_len);
345
346   /* this must succeed because it was allocated on function entry and
347    * DBusString doesn't ever realloc smaller
348    */
349   if (!append_header_padding (message))
350     _dbus_assert_not_reached ("failed to reappend header padding");
351   
352   return FALSE;
353 }
354
355 #ifdef DBUS_BUILD_TESTS
356 /* This isn't used, but building it when tests are enabled just to
357  * keep it compiling if we need it in future
358  */
359 static void
360 delete_int_field (DBusMessage *message,
361                   int          field)
362 {
363   int offset = message->header_fields[field].offset;
364
365   _dbus_assert (!message->locked);
366   _dbus_assert (field_is_named[field]);
367   
368   if (offset < 0)
369     return;  
370
371   clear_header_padding (message);
372   
373   /* The field typecode and name take up 8 bytes */
374   _dbus_string_delete (&message->header,
375                        offset - 8,
376                        12);
377
378   message->header_fields[field].offset = -1;
379   
380   adjust_field_offsets (message,
381                         offset - 8,
382                         - 12);
383
384   append_header_padding (message);
385 }
386 #endif
387
388 static void
389 delete_string_field (DBusMessage *message,
390                      int          field)
391 {
392   int offset = message->header_fields[field].offset;
393   int len;
394   int delete_len;
395   
396   _dbus_assert (!message->locked);
397   _dbus_assert (field_is_named[field]);
398   
399   if (offset < 0)
400     return;
401
402   clear_header_padding (message);
403   
404   get_string_field (message, field, &len);
405   
406   /* The field typecode and name take up 8 bytes, and the nul
407    * termination is 1 bytes, string length integer is 4 bytes
408    */
409   delete_len = 8 + 4 + 1 + len;
410   
411   _dbus_string_delete (&message->header,
412                        offset - 8,
413                        delete_len);
414
415   message->header_fields[field].offset = -1;
416   
417   adjust_field_offsets (message,
418                         offset - 8,
419                         - delete_len);
420
421   append_header_padding (message);
422 }
423
424 static dbus_bool_t
425 set_int_field (DBusMessage *message,
426                int          field,
427                int          value)
428 {
429   int offset = message->header_fields[field].offset;
430
431   _dbus_assert (!message->locked);
432   
433   if (offset < 0)
434     {
435       /* need to append the field */
436
437       switch (field)
438         {
439         case FIELD_REPLY_SERIAL:
440           return append_int_field (message, field,
441                                    DBUS_HEADER_FIELD_REPLY,
442                                    value);
443         default:
444           _dbus_assert_not_reached ("appending an int field we don't support appending");
445           return FALSE;
446         }
447     }
448   else
449     {
450       _dbus_marshal_set_int32 (&message->header,
451                                message->byte_order,
452                                offset, value);
453
454       return TRUE;
455     }
456 }
457
458 static dbus_bool_t
459 set_uint_field (DBusMessage  *message,
460                 int           field,
461                 dbus_uint32_t value)
462 {
463   int offset = message->header_fields[field].offset;
464
465   _dbus_assert (!message->locked);
466   
467   if (offset < 0)
468     {
469       /* need to append the field */
470
471       switch (field)
472         {
473         default:
474           _dbus_assert_not_reached ("appending a uint field we don't support appending");
475           return FALSE;
476         }
477     }
478   else
479     {
480       _dbus_marshal_set_uint32 (&message->header,
481                                 message->byte_order,
482                                 offset, value);
483
484       return TRUE;
485     }
486 }
487
488 static dbus_bool_t
489 set_string_field (DBusMessage *message,
490                   int          field,
491                   const char  *value)
492 {
493   int offset = message->header_fields[field].offset;
494
495   _dbus_assert (!message->locked);
496   _dbus_assert (value != NULL);
497   
498   if (offset < 0)
499     {      
500       /* need to append the field */
501
502       switch (field)
503         {
504         case FIELD_SENDER:
505           return append_string_field (message, field,
506                                       DBUS_HEADER_FIELD_SENDER,
507                                       value);
508         default:
509           _dbus_assert_not_reached ("appending a string field we don't support appending");
510           return FALSE;
511         }
512     }
513   else
514     {
515       DBusString v;
516       int old_len;
517       int new_len;
518       int len;
519       
520       clear_header_padding (message);
521       
522       old_len = _dbus_string_get_length (&message->header);
523
524       len = strlen (value);
525       
526       _dbus_string_init_const_len (&v, value,
527                                    len + 1); /* include nul */
528       if (!_dbus_marshal_set_string (&message->header,
529                                      message->byte_order,
530                                      offset, &v,
531                                      len))
532         goto failed;
533       
534       new_len = _dbus_string_get_length (&message->header);
535
536       adjust_field_offsets (message,
537                             offset,
538                             new_len - old_len);
539
540       if (!append_header_padding (message))
541         goto failed;
542       
543       return TRUE;
544
545     failed:
546       /* this must succeed because it was allocated on function entry and
547        * DBusString doesn't ever realloc smaller
548        */
549       if (!append_header_padding (message))
550         _dbus_assert_not_reached ("failed to reappend header padding");
551
552       return FALSE;
553     }
554 }
555
556 /**
557  * Sets the serial number of a message. 
558  * This can only be done once on a message.
559  * 
560  * @param message the message
561  * @param serial the serial
562  */
563 void
564 _dbus_message_set_serial (DBusMessage  *message,
565                           dbus_int32_t  serial)
566 {
567   _dbus_assert (!message->locked);
568   _dbus_assert (dbus_message_get_serial (message) < 0);
569   
570   set_int_field (message, FIELD_CLIENT_SERIAL,
571                  serial);
572   message->client_serial = serial;
573 }
574
575 /**
576  * Sets the reply serial of a message (the client serial
577  * of the message this is a reply to).
578  *
579  * @param message the message
580  * @param reply_serial the client serial
581  * @returns #FALSE if not enough memory
582  */
583 dbus_bool_t
584 dbus_message_set_reply_serial (DBusMessage  *message,
585                                 dbus_int32_t  reply_serial)
586 {
587   _dbus_assert (!message->locked);
588
589   if (set_int_field (message, FIELD_REPLY_SERIAL,
590                      reply_serial))
591     {
592       message->reply_serial = reply_serial;
593       return TRUE;
594     }
595   else
596     return FALSE;
597 }
598
599 /**
600  * Returns the serial of a message or -1 if none has been specified.
601  * The message's serial number is provided by the application sending
602  * the message and is used to identify replies to this message.
603  *
604  * @param message the message
605  * @returns the client serial
606  */
607 dbus_int32_t
608 dbus_message_get_serial (DBusMessage *message)
609 {
610   return message->client_serial;
611 }
612
613 /**
614  * Returns the serial that the message is
615  * a reply to or -1 if none.
616  *
617  * @param message the message
618  * @returns the reply serial
619  */
620 dbus_int32_t
621 dbus_message_get_reply_serial  (DBusMessage *message)
622 {
623   return message->reply_serial;
624 }
625
626 /**
627  * Adds a counter to be incremented immediately with the
628  * size of this message, and decremented by the size
629  * of this message when this message if finalized.
630  *
631  * @param message the message
632  * @param counter the counter
633  */
634 void
635 _dbus_message_add_size_counter (DBusMessage *message,
636                                 DBusCounter *counter)
637 {
638   _dbus_assert (message->size_counter == NULL); /* If this fails we may need to keep a list of
639                                                  * counters instead of just one
640                                                  */
641
642   message->size_counter = counter;
643   _dbus_counter_ref (message->size_counter);
644
645   /* When we can change message size, we may want to
646    * update this each time we do so, or we may want to
647    * just KISS like this.
648    */
649   message->size_counter_delta =
650     _dbus_string_get_length (&message->header) +
651     _dbus_string_get_length (&message->body);
652
653 #if 0
654   _dbus_verbose ("message has size %ld\n",
655                  message->size_counter_delta);
656 #endif
657   
658   _dbus_counter_adjust (message->size_counter, message->size_counter_delta);
659 }
660
661 static dbus_bool_t
662 dbus_message_create_header (DBusMessage *message,
663                             const char  *service,
664                             const char  *name)
665 {
666   unsigned int flags;
667   
668   if (!_dbus_string_append_byte (&message->header, message->byte_order))
669     return FALSE;
670
671   flags = 0;
672   if (!_dbus_string_append_byte (&message->header, flags))
673     return FALSE;
674
675   if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
676     return FALSE;
677
678   if (!_dbus_string_append_byte (&message->header, 0))
679     return FALSE;
680
681   message->header_fields[FIELD_HEADER_LENGTH].offset = 4;
682   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
683     return FALSE;
684
685   message->header_fields[FIELD_BODY_LENGTH].offset = 8;
686   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
687     return FALSE;
688
689   message->header_fields[FIELD_CLIENT_SERIAL].offset = 12;
690   if (!_dbus_marshal_int32 (&message->header, message->byte_order, -1))
691     return FALSE;
692   
693   /* Marshal message service */
694   if (service != NULL)
695     {
696       if (!append_string_field (message,
697                                 FIELD_SERVICE,
698                                 DBUS_HEADER_FIELD_SERVICE,
699                                 service))
700         return FALSE;
701     }
702
703   _dbus_assert (name != NULL);
704   if (!append_string_field (message,
705                             FIELD_NAME,
706                             DBUS_HEADER_FIELD_NAME,
707                             name))
708     return FALSE;
709   
710   return TRUE;
711 }
712
713 /**
714  * Locks a message. Allows checking that applications don't keep a
715  * reference to a message in the outgoing queue and change it
716  * underneath us. Messages are locked when they enter the outgoing
717  * queue (dbus_connection_send_message()), and the library complains
718  * if the message is modified while locked.
719  *
720  * @param message the message to lock.
721  */
722 void
723 _dbus_message_lock (DBusMessage  *message)
724 {
725   if (!message->locked)
726     {
727       /* Fill in our lengths */
728       set_uint_field (message,
729                       FIELD_HEADER_LENGTH,
730                       _dbus_string_get_length (&message->header));
731
732       set_uint_field (message,
733                       FIELD_BODY_LENGTH,
734                       _dbus_string_get_length (&message->body));
735
736       message->locked = TRUE;
737     }
738 }
739
740 /** @} */
741
742 /**
743  * @defgroup DBusMessage DBusMessage
744  * @ingroup  DBus
745  * @brief Message to be sent or received over a DBusConnection.
746  *
747  * A DBusMessage is the most basic unit of communication over a
748  * DBusConnection. A DBusConnection represents a stream of messages
749  * received from a remote application, and a stream of messages
750  * sent to a remote application.
751  *
752  * @{
753  */
754
755 /**
756  * @typedef DBusMessage
757  *
758  * Opaque data type representing a message received from or to be
759  * sent to another application.
760  */
761
762 static DBusMessage*
763 dbus_message_new_empty_header (void)
764 {
765   DBusMessage *message;
766   int i;
767   
768   message = dbus_new0 (DBusMessage, 1);
769   if (message == NULL)
770     return NULL;
771   
772   message->refcount = 1;
773   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
774   message->client_serial = -1;
775   message->reply_serial = -1;
776   
777   i = 0;
778   while (i < FIELD_LAST)
779     {
780       message->header_fields[i].offset = -1;
781       ++i;
782     }
783   
784   if (!_dbus_string_init (&message->header))
785     {
786       dbus_free (message);
787       return NULL;
788     }
789   
790   if (!_dbus_string_init (&message->body))
791     {
792       _dbus_string_free (&message->header);
793       dbus_free (message);
794       return NULL;
795     }
796   
797   return message;
798 }
799
800
801 /**
802  * Constructs a new message. Returns #NULL if memory can't be
803  * allocated for the message. The service may be #NULL in which case
804  * no service is set; this is appropriate when using D-BUS in a
805  * peer-to-peer context (no message bus).
806  *
807  * @todo reverse the arguments, first 'name' then 'service'
808  * as 'name' is more fundamental
809  *
810  * @param service service that the message should be sent to or #NULL
811  * @param name name of the message
812  * @returns a new DBusMessage, free with dbus_message_unref()
813  * @see dbus_message_unref()
814  */
815 DBusMessage*
816 dbus_message_new (const char *service,
817                   const char *name)
818 {
819   DBusMessage *message;
820
821   message = dbus_message_new_empty_header ();
822   if (message == NULL)
823     return NULL;
824   
825   if (!dbus_message_create_header (message, service, name))
826     {
827       dbus_message_unref (message);
828       return NULL;
829     }
830   
831   return message;
832 }
833
834 /**
835  * Constructs a message that is a reply to some other
836  * message. Returns #NULL if memory can't be allocated
837  * for the message.
838  *
839  * @param original_message the message which the created
840  * message is a reply to.
841  * @returns a new DBusMessage, free with dbus_message_unref()
842  * @see dbus_message_new(), dbus_message_unref()
843  */ 
844 DBusMessage*
845 dbus_message_new_reply (DBusMessage *original_message)
846 {
847   DBusMessage *message;
848   const char *sender, *name;
849
850   sender = get_string_field (original_message,
851                              FIELD_SENDER, NULL);
852   name = get_string_field (original_message,
853                            FIELD_NAME, NULL);
854
855   /* sender is allowed to be null here in peer-to-peer case */
856   
857   message = dbus_message_new (sender, name);
858   
859   if (message == NULL)
860     return NULL;
861
862   if (!dbus_message_set_reply_serial (message,
863                                       dbus_message_get_serial (original_message)))
864     {
865       dbus_message_unref (message);
866       return NULL;
867     }
868
869   return message;
870 }
871
872 /**
873  * Creates a new message that is an error reply to a certain message.
874  *
875  * @param original_message the original message
876  * @param error_name the error name
877  * @param error_message the error message string
878  * @returns a new error message
879  */
880 DBusMessage*
881 dbus_message_new_error_reply (DBusMessage *original_message,
882                               const char  *error_name,
883                               const char  *error_message)
884 {
885   DBusMessage *message;
886   const char *sender;
887   DBusMessageIter iter;
888
889   sender = get_string_field (original_message,
890                              FIELD_SENDER, NULL);
891   
892   _dbus_assert (sender != NULL);
893   
894   message = dbus_message_new (sender, error_name);
895   
896   if (message == NULL)
897     return NULL;
898
899   if (!dbus_message_set_reply_serial (message,
900                                       dbus_message_get_serial (original_message)))
901     {
902       dbus_message_unref (message);
903       return NULL;
904     }
905
906   dbus_message_append_iter_init (message, &iter);
907   if (!dbus_message_iter_append_string (&iter, error_message))
908     {
909       dbus_message_unref (message);
910       return NULL;
911     }
912
913   dbus_message_set_is_error (message, TRUE);
914   
915   return message;
916 }
917
918 /**
919  * Creates a new message that is an exact replica of the message
920  * specified, except that its refcount is set to 1.
921  *
922  * @param message the message.
923  * @returns the new message.
924  */
925 DBusMessage *
926 dbus_message_copy (const DBusMessage *message)
927 {
928   DBusMessage *retval;
929   int i;
930   
931   retval = dbus_new0 (DBusMessage, 1);
932   if (retval == NULL)
933     return NULL;
934   
935   retval->refcount = 1;
936   retval->byte_order = message->byte_order;
937   retval->client_serial = message->client_serial;
938   retval->reply_serial = message->reply_serial;
939   retval->header_padding = message->header_padding;
940   retval->locked = FALSE;
941   
942   if (!_dbus_string_init (&retval->header))
943     {
944       dbus_free (retval);
945       return NULL;
946     }
947   
948   if (!_dbus_string_init (&retval->body))
949     {
950       _dbus_string_free (&retval->header);
951       dbus_free (retval);
952       return NULL;
953     }
954
955   if (!_dbus_string_copy (&message->header, 0,
956                           &retval->header, 0))
957     {
958       _dbus_string_free (&retval->header);
959       _dbus_string_free (&retval->body);
960       dbus_free (retval);
961
962       return NULL;
963     }
964
965   if (!_dbus_string_copy (&message->body, 0,
966                           &retval->body, 0))
967     {
968       _dbus_string_free (&retval->header);
969       _dbus_string_free (&retval->body);
970       dbus_free (retval);
971
972       return NULL;
973     }
974
975   for (i = 0; i < FIELD_LAST; i++)
976     {
977       retval->header_fields[i].offset = message->header_fields[i].offset;
978     }
979   
980   return retval;
981 }
982
983
984 /**
985  * Increments the reference count of a DBusMessage.
986  *
987  * @param message The message
988  * @see dbus_message_unref
989  */
990 void
991 dbus_message_ref (DBusMessage *message)
992 {
993   dbus_atomic_t refcount;
994
995   refcount = _dbus_atomic_inc (&message->refcount);
996   _dbus_assert (refcount > 1);
997 }
998
999 /**
1000  * Decrements the reference count of a DBusMessage.
1001  *
1002  * @param message The message
1003  * @see dbus_message_ref
1004  */
1005 void
1006 dbus_message_unref (DBusMessage *message)
1007 {
1008   dbus_atomic_t refcount;
1009
1010   refcount = _dbus_atomic_dec (&message->refcount);
1011   
1012   _dbus_assert (refcount >= 0);
1013
1014   if (refcount == 0)
1015     {
1016       if (message->size_counter != NULL)
1017         {
1018           _dbus_counter_adjust (message->size_counter,
1019                                 - message->size_counter_delta);
1020           _dbus_counter_unref (message->size_counter);
1021         }
1022       
1023       _dbus_string_free (&message->header);
1024       _dbus_string_free (&message->body);
1025       
1026       dbus_free (message);
1027     }
1028 }
1029
1030 /**
1031  * Gets the name of a message.
1032  *
1033  * @param message the message
1034  * @returns the message name (should not be freed)
1035  */
1036 const char*
1037 dbus_message_get_name (DBusMessage *message)
1038 {
1039   return get_string_field (message, FIELD_NAME, NULL);
1040 }
1041
1042 /**
1043  * Gets the destination service of a message.
1044  *
1045  * @todo I think if we have set_sender/get_sender,
1046  * this function might be better named set_destination/
1047  * get_destination for clarity, as the sender
1048  * is also a service name.
1049  * 
1050  * @param message the message
1051  * @returns the message destination service (should not be freed)
1052  */
1053 const char*
1054 dbus_message_get_service (DBusMessage *message)
1055 {
1056   return get_string_field (message, FIELD_SERVICE, NULL);
1057 }
1058
1059 /**
1060  * Appends fields to a message given a variable argument
1061  * list. The variable argument list should contain the type
1062  * of the argument followed by the value to add.
1063  * Array values are specified by a int typecode followed by a pointer
1064  * to the array followed by an int giving the length of the array.
1065  * The argument list must be terminated with 0.
1066  *
1067  * This function doesn't support dicts or non-fundamental arrays.
1068  *
1069  * @param message the message
1070  * @param first_arg_type type of the first argument
1071  * @param ... value of first argument, list of additional type-value pairs
1072  * @returns #TRUE on success
1073  */
1074 dbus_bool_t
1075 dbus_message_append_args (DBusMessage *message,
1076                           int first_arg_type,
1077                           ...)
1078 {
1079   dbus_bool_t retval;
1080   va_list var_args;
1081
1082   va_start (var_args, first_arg_type);
1083   retval = dbus_message_append_args_valist (message,
1084                                             first_arg_type,
1085                                             var_args);
1086   va_end (var_args);
1087
1088   return retval;
1089 }
1090
1091 /**
1092  * This function takes a va_list for use by language bindings
1093  *
1094  * @todo: Shouldn't this function clean up the changes to the message
1095  *        on failures?
1096   
1097  * @see dbus_message_append_args.  
1098  * @param message the message
1099  * @param first_arg_type type of first argument
1100  * @param var_args value of first argument, then list of type/value pairs
1101  * @returns #TRUE on success
1102  */
1103 dbus_bool_t
1104 dbus_message_append_args_valist (DBusMessage *message,
1105                                  int          first_arg_type,
1106                                  va_list      var_args)
1107 {
1108   int type, old_len;
1109   DBusMessageIter iter;
1110
1111   old_len = _dbus_string_get_length (&message->body);
1112   
1113   type = first_arg_type;
1114
1115   dbus_message_append_iter_init (message, &iter);
1116   
1117   while (type != 0)
1118     {
1119       switch (type)
1120         {
1121         case DBUS_TYPE_NIL:
1122           if (!dbus_message_iter_append_nil (&iter))
1123             goto errorout;
1124           break;
1125         case DBUS_TYPE_BOOLEAN:
1126           if (!dbus_message_iter_append_boolean (&iter, va_arg (var_args, dbus_bool_t)))
1127             goto errorout;
1128           break;
1129         case DBUS_TYPE_INT32:
1130           if (!dbus_message_iter_append_int32 (&iter, va_arg (var_args, dbus_int32_t)))
1131             goto errorout;
1132           break;
1133         case DBUS_TYPE_UINT32:
1134           if (!dbus_message_iter_append_uint32 (&iter, va_arg (var_args, dbus_uint32_t)))
1135             goto errorout;          
1136           break;
1137         case DBUS_TYPE_DOUBLE:
1138           if (!dbus_message_iter_append_double (&iter, va_arg (var_args, double)))
1139             goto errorout;
1140           break;
1141         case DBUS_TYPE_STRING:
1142           if (!dbus_message_iter_append_string (&iter, va_arg (var_args, const char *)))
1143             goto errorout;
1144           break;
1145         case DBUS_TYPE_NAMED:
1146           {
1147             const char *name;
1148             unsigned char *data;
1149             int len;
1150  
1151             name = va_arg (var_args, const char *);
1152             data = va_arg (var_args, unsigned char *);
1153             len = va_arg (var_args, int);
1154
1155             if (!dbus_message_iter_append_named (&iter, name, data, len))
1156               goto errorout;
1157             break;
1158           }
1159         case DBUS_TYPE_ARRAY:
1160           {
1161             void *data;
1162             int len, type;
1163  
1164             type = va_arg (var_args, int);
1165             data = va_arg (var_args, void *);
1166             len = va_arg (var_args, int);
1167
1168             switch (type)
1169               {
1170               case DBUS_TYPE_BYTE:
1171                 if (!dbus_message_iter_append_byte_array (&iter, (unsigned char *)data, len))
1172                   goto errorout;
1173                 break;
1174               case DBUS_TYPE_BOOLEAN:
1175                 if (!dbus_message_iter_append_boolean_array (&iter, (unsigned char *)data, len))
1176                   goto errorout;
1177                 break;
1178               case DBUS_TYPE_INT32:
1179                 if (!dbus_message_iter_append_int32_array (&iter, (dbus_int32_t *)data, len))
1180                   goto errorout;
1181                 break;
1182               case DBUS_TYPE_UINT32:
1183                 if (!dbus_message_iter_append_uint32_array (&iter, (dbus_uint32_t *)data, len))
1184                   goto errorout;
1185                 break;
1186               case DBUS_TYPE_DOUBLE:
1187                 if (!dbus_message_iter_append_double_array (&iter, (double *)data, len))
1188                   goto errorout;
1189                 break;
1190               case DBUS_TYPE_STRING:
1191                 if (!dbus_message_iter_append_string_array (&iter, (const char **)data, len))
1192                   goto errorout;
1193                 break;
1194               case DBUS_TYPE_NIL:
1195               case DBUS_TYPE_ARRAY:
1196               case DBUS_TYPE_NAMED:
1197               case DBUS_TYPE_DICT:
1198                 _dbus_warn ("dbus_message_append_args_valist doesn't support recursive arrays\n");
1199                 goto errorout;
1200               default:
1201                 _dbus_warn ("Unknown field type %d\n", type);
1202                 goto errorout;
1203               }
1204           }
1205           break;
1206           
1207         case DBUS_TYPE_DICT:
1208           _dbus_warn ("dbus_message_append_args_valist doesn't support dicts\n");
1209           goto errorout;
1210         default:
1211           _dbus_warn ("Unknown field type %d\n", type);
1212           goto errorout;
1213         }
1214
1215       type = va_arg (var_args, int);
1216     }
1217
1218   return TRUE;
1219
1220  errorout:
1221   return FALSE;
1222 }
1223
1224
1225 /**
1226  * Gets arguments from a message given a variable argument list.
1227  * The variable argument list should contain the type of the
1228  * argumen followed by a pointer to where the value should be
1229  * stored. The list is terminated with 0.
1230  *
1231  * @param message the message
1232  * @param error error to be filled in on failure
1233  * @param first_arg_type the first argument type
1234  * @param ... location for first argument value, then list of type-location pairs
1235  * @returns #FALSE if the error was set
1236  */
1237 dbus_bool_t
1238 dbus_message_get_args (DBusMessage     *message,
1239                        DBusError       *error,
1240                        int              first_arg_type,
1241                        ...)
1242 {
1243   dbus_bool_t retval;
1244   va_list var_args;
1245
1246   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1247   
1248   va_start (var_args, first_arg_type);
1249   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
1250   va_end (var_args);
1251
1252   return retval;
1253 }
1254
1255 /**
1256  * This function takes a va_list for use by language bindings
1257  *
1258  * @todo We need to free the argument data when an error occurs.
1259  *
1260  * @see dbus_message_get_args
1261  * @param message the message
1262  * @param error error to be filled in
1263  * @param first_arg_type type of the first argument
1264  * @param var_args return location for first argument, followed by list of type/location pairs
1265  * @returns #FALSE if error was set
1266  */
1267 dbus_bool_t
1268 dbus_message_get_args_valist (DBusMessage     *message,
1269                               DBusError       *error,
1270                               int              first_arg_type,
1271                               va_list          var_args)
1272 {
1273   DBusMessageIter iter;
1274
1275   dbus_message_iter_init (message, &iter);
1276   return dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
1277 }
1278
1279 /**
1280  * Gets arguments from a message iterator given a variable argument list.
1281  * The variable argument list should contain the type of the
1282  * argumen followed by a pointer to where the value should be
1283  * stored. The list is terminated with 0.
1284  *
1285  * @param iter the message iterator 
1286  * @param error error to be filled in on failure
1287  * @param first_arg_type the first argument type
1288  * @param ... location for first argument value, then list of type-location pairs
1289  * @returns #FALSE if the error was set
1290  */
1291 dbus_bool_t
1292 dbus_message_iter_get_args (DBusMessageIter *iter,
1293                             DBusError       *error,
1294                             int              first_arg_type,
1295                             ...)
1296 {
1297   dbus_bool_t retval;
1298   va_list var_args;
1299
1300   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1301   
1302   va_start (var_args, first_arg_type);
1303   retval = dbus_message_iter_get_args_valist (iter, error, first_arg_type, var_args);
1304   va_end (var_args);
1305
1306   return retval;
1307 }
1308
1309 /**
1310  * This function takes a va_list for use by language bindings
1311  *
1312  * @todo this function (or some lower-level non-convenience function)
1313  * needs better error handling; should allow the application to
1314  * distinguish between out of memory, and bad data from the remote
1315  * app. It also needs to not leak a bunch of args when it gets
1316  * to the arg that's bad, as that would be a security hole
1317  * (allow one app to force another to leak memory)
1318  *
1319  * @todo We need to free the argument data when an error occurs.
1320  *
1321  * @see dbus_message_get_args
1322  * @param iter the message iter
1323  * @param error error to be filled in
1324  * @param first_arg_type type of the first argument
1325  * @param var_args return location for first argument, followed by list of type/location pairs
1326  * @returns #FALSE if error was set
1327  */
1328 dbus_bool_t
1329 dbus_message_iter_get_args_valist (DBusMessageIter *iter,
1330                                    DBusError       *error,
1331                                    int              first_arg_type,
1332                                    va_list          var_args)
1333 {
1334   int spec_type, msg_type, i;
1335   dbus_bool_t retval;
1336
1337   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1338
1339   retval = FALSE;
1340   
1341   spec_type = first_arg_type;
1342   i = 0;
1343   
1344   while (spec_type != 0)
1345     {
1346       msg_type = dbus_message_iter_get_arg_type (iter);      
1347       
1348       if (msg_type != spec_type)
1349         {
1350           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1351                           "Argument %d is specified to be of type \"%s\", but "
1352                           "is actually of type \"%s\"\n", i,
1353                           _dbus_type_to_string (spec_type),
1354                           _dbus_type_to_string (msg_type));
1355
1356           goto out;
1357         }
1358
1359       switch (spec_type)
1360         {
1361         case DBUS_TYPE_NIL:
1362           break;
1363         case DBUS_TYPE_BYTE:
1364           {
1365             unsigned char *ptr;
1366
1367             ptr = va_arg (var_args, unsigned char *);
1368
1369             *ptr = dbus_message_iter_get_byte (iter);
1370             break;
1371           }
1372         case DBUS_TYPE_BOOLEAN:
1373           {
1374             dbus_bool_t *ptr;
1375
1376             ptr = va_arg (var_args, dbus_bool_t *);
1377
1378             *ptr = dbus_message_iter_get_boolean (iter);
1379             break;
1380           }
1381         case DBUS_TYPE_INT32:
1382           {
1383             dbus_int32_t *ptr;
1384
1385             ptr = va_arg (var_args, dbus_int32_t *);
1386
1387             *ptr = dbus_message_iter_get_int32 (iter);
1388             break;
1389           }
1390         case DBUS_TYPE_UINT32:
1391           {
1392             dbus_uint32_t *ptr;
1393
1394             ptr = va_arg (var_args, dbus_uint32_t *);
1395
1396             *ptr = dbus_message_iter_get_uint32 (iter);
1397             break;
1398           }
1399
1400         case DBUS_TYPE_DOUBLE:
1401           {
1402             double *ptr;
1403
1404             ptr = va_arg (var_args, double *);
1405
1406             *ptr = dbus_message_iter_get_double (iter);
1407             break;
1408           }
1409
1410         case DBUS_TYPE_STRING:
1411           {
1412             char **ptr;
1413
1414             ptr = va_arg (var_args, char **);
1415
1416             *ptr = dbus_message_iter_get_string (iter);
1417
1418             if (!*ptr)
1419               {
1420                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1421                 goto out;
1422               }
1423             
1424             break;
1425           }
1426
1427         case DBUS_TYPE_NAMED:
1428           {
1429             char **name;
1430             unsigned char **data;
1431             int *len;
1432  
1433             name = va_arg (var_args, char **);
1434             data = va_arg (var_args, unsigned char **);
1435             len = va_arg (var_args, int *);
1436
1437             *name = dbus_message_iter_get_named (iter, data, len);
1438             if (*name == NULL)
1439               {
1440                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1441                 goto out;
1442               }
1443           }
1444           break;
1445         case DBUS_TYPE_ARRAY:
1446           {
1447             void **data;
1448             int *len, type;
1449  
1450             type = va_arg (var_args, int);
1451             data = va_arg (var_args, void *);
1452             len = va_arg (var_args, int *);
1453
1454             if (dbus_message_iter_get_array_type (iter) != type)
1455               {
1456                 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1457                                 "Argument %d is specified to be of type \"array of %s\", but "
1458                                 "is actually of type \"array of %s\"\n", i,
1459                                 _dbus_type_to_string (type),
1460                                 _dbus_type_to_string (dbus_message_iter_get_array_type (iter)));
1461                 goto out;
1462               }
1463             
1464             switch (type)
1465               {
1466               case DBUS_TYPE_BYTE:
1467                 if (!dbus_message_iter_get_byte_array (iter, (unsigned char **)data, len))
1468                   {
1469                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1470                     goto out;
1471                   }
1472                 break;
1473               case DBUS_TYPE_BOOLEAN:
1474                 if (!dbus_message_iter_get_boolean_array (iter, (unsigned char **)data, len))
1475                   {
1476                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1477                     goto out;
1478                   }
1479                 break;
1480               case DBUS_TYPE_INT32:
1481                 if (!dbus_message_iter_get_int32_array (iter, (dbus_int32_t **)data, len))
1482                   {
1483                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1484                     goto out;
1485                   }
1486                 break;
1487               case DBUS_TYPE_UINT32:
1488                 if (!dbus_message_iter_get_uint32_array (iter, (dbus_uint32_t **)data, len))
1489                   {
1490                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1491                     goto out;
1492                   }
1493                 break;
1494               case DBUS_TYPE_DOUBLE:
1495                 if (!dbus_message_iter_get_double_array (iter, (double **)data, len))
1496                   {
1497                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1498                     goto out;
1499                   }
1500                 break;
1501               case DBUS_TYPE_STRING:
1502                 if (!dbus_message_iter_get_string_array (iter, (char ***)data, len))
1503                   {
1504                     dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1505                     goto out;
1506                   }
1507                 break;
1508               case DBUS_TYPE_NIL:
1509               case DBUS_TYPE_ARRAY:
1510               case DBUS_TYPE_NAMED:
1511               case DBUS_TYPE_DICT:
1512                 _dbus_warn ("dbus_message_get_args_valist doesn't support recursive arrays\n");
1513                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1514                 goto out;
1515               default:
1516                 _dbus_warn ("Unknown field type %d\n", type);
1517                 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1518                 goto out;
1519               }
1520           }
1521           break;
1522         case DBUS_TYPE_DICT:
1523           _dbus_warn ("dbus_message_get_args_valist doesn't support dicts\n");
1524           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1525           goto out;
1526         default:          
1527           dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, NULL);
1528           _dbus_warn ("Unknown field type %d\n", spec_type);
1529           goto out;
1530         }
1531       
1532       spec_type = va_arg (var_args, int);
1533       if (spec_type != 0 && !dbus_message_iter_next (iter))
1534         {
1535           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1536                           "Message has only %d arguments, but more were expected", i);
1537           goto out;
1538         }
1539
1540       i++;
1541     }
1542   
1543   retval = TRUE;
1544   
1545  out:
1546   
1547   return retval;
1548 }
1549
1550
1551 /**
1552  * Initializes a DBusMessageIter representing the arguments of the
1553  * message passed in.
1554  *
1555  * @param message the message
1556  * @param _iter pointer to an iterator to initialize
1557  */
1558 void
1559 dbus_message_iter_init (DBusMessage *message,
1560                         DBusMessageIter *iter)
1561 {
1562   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1563
1564   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
1565   
1566   real->message = message;
1567   real->parent_iter = NULL;
1568   real->changed_stamp = message->changed_stamp;
1569   
1570   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
1571   real->pos = 0;
1572   real->end = _dbus_string_get_length (&message->body);
1573   
1574   real->container_type = 0;
1575   real->container_start = 0;
1576   real->container_length_pos = 0;
1577   real->wrote_dict_key = 0;
1578 }
1579
1580 static void
1581 dbus_message_iter_check (DBusMessageRealIter *iter)
1582 {
1583   if (iter->changed_stamp != iter->message->changed_stamp) 
1584     _dbus_warn ("dbus iterator check failed: invalid iterator\n");
1585   if (iter->pos < 0 || iter->pos > iter->end)
1586     _dbus_warn ("dbus iterator check failed: invalid position\n");
1587 }
1588
1589 static int
1590 dbus_message_iter_get_data_start (DBusMessageRealIter *iter, int *type)
1591 {
1592   const char *data;
1593   int pos, len;
1594   
1595   switch (iter->type)
1596     {
1597     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
1598       data = _dbus_string_get_const_data_len (&iter->message->body,
1599                                               iter->pos, 1);
1600       if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1601         *type = *data;
1602       else
1603         *type = DBUS_TYPE_INVALID;
1604       
1605       return iter->pos + 1;
1606       
1607     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
1608       *type = iter->container_type;
1609       return iter->pos;
1610       
1611       
1612     case DBUS_MESSAGE_ITER_TYPE_DICT:
1613       /* Get the length of the string */
1614       len = _dbus_demarshal_uint32 (&iter->message->body,
1615                                     iter->message->byte_order,
1616                                     iter->pos, &pos);
1617       pos = pos + len + 1;
1618       data = _dbus_string_get_const_data_len (&iter->message->body,
1619                                               pos, 1);
1620       if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1621         *type = *data;
1622       else
1623         *type = DBUS_TYPE_INVALID;
1624       return pos + 1;
1625     default:
1626       _dbus_assert_not_reached ("Invalid iter type");
1627       break;
1628     }
1629   *type = DBUS_TYPE_INVALID;
1630   return iter->pos;
1631 }
1632
1633
1634 /**
1635  * Checks if an iterator has any more fields.
1636  *
1637  * @param iter the message iter
1638  * @returns #TRUE if there are more fields
1639  * following
1640  */
1641 dbus_bool_t
1642 dbus_message_iter_has_next (DBusMessageIter *iter)
1643 {
1644   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1645   int end_pos;
1646   int type, pos;
1647
1648   dbus_message_iter_check (real);
1649
1650   if (real->pos >= real->end)
1651     return FALSE;
1652   
1653   pos = dbus_message_iter_get_data_start (real, &type);
1654   
1655   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
1656                                       real->message->byte_order,
1657                                       type, pos, &end_pos))
1658     return FALSE;
1659   
1660   if (end_pos >= real->end)
1661     return FALSE;
1662
1663   return TRUE;  
1664 }
1665
1666 /**
1667  * Moves the iterator to the next field.
1668  *
1669  * @param _iter The message iter
1670  * @returns #TRUE if the iterator was moved to the next field
1671  */
1672 dbus_bool_t
1673 dbus_message_iter_next (DBusMessageIter *iter)
1674 {
1675   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1676   int end_pos;
1677   int type, pos;
1678
1679   dbus_message_iter_check (real);
1680
1681   pos = dbus_message_iter_get_data_start (real, &type);
1682   
1683   if (!_dbus_marshal_get_arg_end_pos (&real->message->body,
1684                                       real->message->byte_order,
1685                                       type, pos, &end_pos))
1686     return FALSE;
1687
1688   if (end_pos >= real->end)
1689     return FALSE;
1690
1691   real->pos = end_pos;
1692
1693   return TRUE;
1694 }
1695
1696 /**
1697  * Returns the argument type of the argument that the
1698  * message iterator points at.
1699  *
1700  * @param iter the message iter
1701  * @returns the field type
1702  */
1703 int
1704 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
1705 {
1706   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1707   int type, pos;
1708
1709   dbus_message_iter_check (real);
1710
1711   if (real->pos >= real->end)
1712     return DBUS_TYPE_INVALID;
1713
1714   pos = dbus_message_iter_get_data_start (real, &type);
1715   
1716   return type;
1717 }
1718
1719 /**
1720  * Returns the element type of the array that the
1721  * message iterator points at. Note that you need
1722  * to check that the iterator points to an array
1723  * prior to using this function.
1724  *
1725  * @param iter the message iter
1726  * @returns the field type
1727  */
1728 int
1729 dbus_message_iter_get_array_type (DBusMessageIter *iter)
1730 {
1731   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1732   int type, pos;
1733   const char *data;
1734
1735   dbus_message_iter_check (real);
1736
1737   if (real->pos >= real->end)
1738     return DBUS_TYPE_INVALID;
1739
1740   pos = dbus_message_iter_get_data_start (real, &type);
1741
1742   _dbus_assert (type == DBUS_TYPE_ARRAY);
1743
1744   data = _dbus_string_get_const_data_len (&real->message->body,
1745                                           pos,
1746                                           1);
1747   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1748     return *data;
1749   
1750   return DBUS_TYPE_INVALID;
1751 }
1752
1753
1754 /**
1755  * Returns the string value that an iterator may point to.
1756  * Note that you need to check that the iterator points to
1757  * a string value before using this function.
1758  *
1759  * @see dbus_message_iter_get_arg_type
1760  * @param iter the message iter
1761  * @returns the string
1762  */
1763 char *
1764 dbus_message_iter_get_string (DBusMessageIter *iter)
1765 {
1766   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1767   int type, pos;
1768
1769   dbus_message_iter_check (real);
1770
1771   pos = dbus_message_iter_get_data_start (real, &type);
1772   
1773   _dbus_assert (type == DBUS_TYPE_STRING);
1774
1775   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
1776                                  pos, NULL);
1777 }
1778
1779 /**
1780  * Returns the name and data from a named type that an
1781  * iterator may point to. Note that you need to check that
1782  * the iterator points to a named type before using this
1783  * function.
1784  *
1785  * @see dbus_message_iter_get_arg_type
1786  * @param iter the message iter
1787  * @param value return location for data
1788  * @param len return location for length of data
1789  * @returns the named type name as a string
1790  * 
1791  */
1792 char *
1793 dbus_message_iter_get_named (DBusMessageIter   *iter,
1794                              unsigned char    **value,
1795                              int               *len)
1796 {
1797   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1798   int type, pos;
1799   char *name;
1800
1801   dbus_message_iter_check (real);
1802
1803   pos = dbus_message_iter_get_data_start (real, &type);
1804   
1805   _dbus_assert (type == DBUS_TYPE_NAMED);
1806   
1807   name = _dbus_demarshal_string (&real->message->body, real->message->byte_order,
1808                                  pos, &pos);
1809
1810   if (name == NULL)
1811     return NULL;
1812   
1813   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
1814                                    pos + 1, NULL, value, len))
1815     {
1816       dbus_free (name);
1817       return NULL;
1818     }
1819   else
1820     return name;
1821 }
1822
1823 /**
1824  * Returns the byte value that an iterator may point to.
1825  * Note that you need to check that the iterator points to
1826  * a byte value before using this function.
1827  *
1828  * @see dbus_message_iter_get_arg_type
1829  * @param iter the message iter
1830  * @returns the byte value
1831  */
1832 unsigned char
1833 dbus_message_iter_get_byte (DBusMessageIter *iter)
1834 {
1835   unsigned char value;
1836   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1837   int type, pos;
1838
1839   dbus_message_iter_check (real);
1840
1841   pos = dbus_message_iter_get_data_start (real, &type);
1842   
1843   _dbus_assert (type == DBUS_TYPE_BYTE);
1844
1845   value = _dbus_string_get_byte (&real->message->body, pos);
1846   
1847   return value;
1848 }
1849
1850
1851 /**
1852  * Returns the boolean value that an iterator may point to.
1853  * Note that you need to check that the iterator points to
1854  * a boolean value before using this function.
1855  *
1856  * @see dbus_message_iter_get_arg_type
1857  * @param iter the message iter
1858  * @returns the boolean value
1859  */
1860 dbus_bool_t
1861 dbus_message_iter_get_boolean (DBusMessageIter *iter)
1862 {
1863   unsigned char value;
1864   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1865   int type, pos;
1866
1867   dbus_message_iter_check (real);
1868
1869   pos = dbus_message_iter_get_data_start (real, &type);
1870   
1871   _dbus_assert (type == DBUS_TYPE_BOOLEAN);
1872
1873   value = _dbus_string_get_byte (&real->message->body, pos);
1874   
1875   return value;
1876 }
1877
1878 /**
1879  * Returns the 32 bit signed integer value that an iterator may point to.
1880  * Note that you need to check that the iterator points to
1881  * an integer value before using this function.
1882  *
1883  * @see dbus_message_iter_get_arg_type
1884  * @param iter the message iter
1885  * @returns the integer
1886  */
1887 dbus_int32_t
1888 dbus_message_iter_get_int32 (DBusMessageIter *iter)
1889 {
1890   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1891   int type, pos;
1892
1893   dbus_message_iter_check (real);
1894
1895   pos = dbus_message_iter_get_data_start (real, &type);
1896   
1897   _dbus_assert (type == DBUS_TYPE_INT32);
1898   
1899   return _dbus_demarshal_int32 (&real->message->body, real->message->byte_order,
1900                                 pos, NULL);
1901 }
1902
1903 /**
1904  * Returns the 32 bit unsigned integer value that an iterator may point to.
1905  * Note that you need to check that the iterator points to
1906  * an unsigned integer value before using this function.
1907  *
1908  * @see dbus_message_iter_get_arg_type
1909  * @param iter the message iter
1910  * @returns the integer
1911  */
1912 dbus_uint32_t
1913 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
1914 {
1915   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1916   int type, pos;
1917
1918   dbus_message_iter_check (real);
1919
1920   pos = dbus_message_iter_get_data_start (real, &type);
1921   
1922   _dbus_assert (type == DBUS_TYPE_UINT32);
1923   
1924   return _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
1925                                  pos, NULL);
1926 }
1927
1928 /**
1929  * Returns the double value that an iterator may point to.
1930  * Note that you need to check that the iterator points to
1931  * a string value before using this function.
1932  *
1933  * @see dbus_message_iter_get_arg_type
1934  * @param iter the message iter
1935  * @returns the double
1936  */
1937 double
1938 dbus_message_iter_get_double (DBusMessageIter *iter)
1939 {
1940   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1941   int type, pos;
1942
1943   dbus_message_iter_check (real);
1944
1945   pos = dbus_message_iter_get_data_start (real, &type);
1946   
1947   _dbus_assert (type == DBUS_TYPE_DOUBLE);
1948   
1949   return _dbus_demarshal_double (&real->message->body, real->message->byte_order,
1950                                  pos, NULL);
1951 }
1952
1953 /**
1954  * Initializes an iterator for the array that the iterator
1955  * may point to. Note that you need to check that the iterator
1956  * points to an array prior to using this function.
1957  *
1958  * The array element type is returned in array_type, and the array
1959  * iterator can only be used to get that type of data.
1960  *
1961  * @param iter the iterator
1962  * @param array_iter pointer to an iterator to initialize
1963  * @param array_type gets set to the type of the array elements
1964  * @returns #TRUE on success
1965  */
1966 dbus_bool_t
1967 dbus_message_iter_init_array_iterator (DBusMessageIter *iter,
1968                                        DBusMessageIter *array_iter,
1969                                        int             *array_type)
1970 {
1971   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
1972   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
1973   int type, pos, len_pos, len;
1974   int _array_type;
1975   const char *data;
1976
1977   dbus_message_iter_check (real);
1978
1979   pos = dbus_message_iter_get_data_start (real, &type);
1980   
1981   _dbus_assert (type == DBUS_TYPE_ARRAY);
1982
1983   data = _dbus_string_get_const_data_len (&real->message->body,
1984                                           pos,
1985                                           1);
1986   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_LAST)
1987     _array_type = *data;
1988   else
1989     return FALSE;
1990
1991   len_pos = _DBUS_ALIGN_VALUE (pos + 1, sizeof (dbus_uint32_t));
1992   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
1993                                 pos + 1, &pos);
1994   
1995   array_real->parent_iter = real;
1996   array_real->message = real->message;
1997   array_real->changed_stamp = real->message->changed_stamp;
1998   
1999   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
2000   array_real->pos = pos;
2001   array_real->end = pos + len;
2002   
2003   array_real->container_type = _array_type;
2004   array_real->container_start = pos;
2005   array_real->container_length_pos = len_pos;
2006   array_real->wrote_dict_key = 0;
2007
2008   if (array_type != NULL)
2009     *array_type = _array_type;
2010   
2011   return TRUE;
2012 }
2013
2014
2015 /**
2016  * Initializes an iterator for the dict that the iterator
2017  * may point to. Note that you need to check that the iterator
2018  * points to a dict prior to using this function.
2019  *
2020  * @param iter the iterator
2021  * @param dict_iter pointer to an iterator to initialize
2022  * @returns #TRUE on success
2023  */
2024 dbus_bool_t
2025 dbus_message_iter_init_dict_iterator (DBusMessageIter *iter,
2026                                       DBusMessageIter *dict_iter)
2027 {
2028   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2029   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
2030   int type, pos, len_pos, len;
2031
2032   dbus_message_iter_check (real);
2033
2034   pos = dbus_message_iter_get_data_start (real, &type);
2035   
2036   _dbus_assert (type == DBUS_TYPE_DICT);
2037
2038   len_pos = _DBUS_ALIGN_VALUE (pos, sizeof (dbus_uint32_t));
2039   len = _dbus_demarshal_uint32 (&real->message->body, real->message->byte_order,
2040                                 pos, &pos);
2041   
2042   dict_real->parent_iter = real;
2043   dict_real->message = real->message;
2044   dict_real->changed_stamp = real->message->changed_stamp;
2045   
2046   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
2047   dict_real->pos = pos;
2048   dict_real->end = pos + len;
2049   
2050   dict_real->container_type = 0;
2051   dict_real->container_start = pos;
2052   dict_real->container_length_pos = len_pos;
2053   dict_real->wrote_dict_key = 0;
2054
2055   return TRUE;
2056 }
2057
2058 /**
2059  * Returns the byte array that the iterator may point to.
2060  * Note that you need to check that the iterator points
2061  * to a byte array prior to using this function.
2062  *
2063  * @param iter the iterator
2064  * @param value return location for array values
2065  * @param len return location for length of byte array
2066  * @returns #TRUE on success
2067  */
2068 dbus_bool_t
2069 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
2070                                   unsigned char   **value,
2071                                   int              *len)
2072 {
2073   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2074   int type, pos;
2075   const char *data;
2076
2077   dbus_message_iter_check (real);
2078
2079   pos = dbus_message_iter_get_data_start (real, &type);
2080   
2081   _dbus_assert (type == DBUS_TYPE_ARRAY);
2082
2083   data = _dbus_string_get_const_data_len (&real->message->body,
2084                                           pos,
2085                                           1);
2086
2087   _dbus_assert (*data == DBUS_TYPE_BYTE);
2088
2089   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
2090                                    pos + 1, NULL, value, len))
2091     return FALSE;
2092   else
2093     return TRUE;
2094 }
2095
2096 /**
2097  * Returns the boolean array that the iterator may point to. Note that
2098  * you need to check that the iterator points to an array of the
2099  * correct type prior to using this function.
2100  *
2101  * @param iter the iterator
2102  * @param value return location for the array
2103  * @param len return location for the array length
2104  * @returns #TRUE on success
2105  */
2106 dbus_bool_t
2107 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
2108                                      unsigned char    **value,
2109                                      int               *len)
2110 {
2111   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2112   int type, pos;
2113   const char *data;
2114
2115   dbus_message_iter_check (real);
2116
2117   pos = dbus_message_iter_get_data_start (real, &type);
2118   
2119   _dbus_assert (type == DBUS_TYPE_ARRAY);
2120
2121   data = _dbus_string_get_const_data_len (&real->message->body,
2122                                           pos,
2123                                           1);
2124
2125   _dbus_assert (*data == DBUS_TYPE_BOOLEAN);
2126
2127   if (!_dbus_demarshal_byte_array (&real->message->body, real->message->byte_order,
2128                                    pos + 1, NULL, value, len))
2129     return FALSE;
2130   else
2131     return TRUE;
2132 }
2133
2134 /**
2135  * Returns the 32 bit signed integer array that the iterator may point
2136  * to. Note that you need to check that the iterator points to an
2137  * array of the correct type prior to using this function.
2138  *
2139  * @param iter the iterator
2140  * @param value return location for the array
2141  * @param len return location for the array length
2142  * @returns #TRUE on success
2143  */
2144 dbus_bool_t
2145 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
2146                                     dbus_int32_t   **value,
2147                                     int             *len)
2148 {
2149   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2150   int type, pos;
2151   const char *data;
2152
2153   dbus_message_iter_check (real);
2154
2155   pos = dbus_message_iter_get_data_start (real, &type);
2156   
2157   _dbus_assert (type == DBUS_TYPE_ARRAY);
2158
2159   data = _dbus_string_get_const_data_len (&real->message->body,
2160                                           pos,
2161                                           1);
2162
2163   _dbus_assert (*data == DBUS_TYPE_INT32);
2164
2165   if (!_dbus_demarshal_int32_array (&real->message->body, real->message->byte_order,
2166                                     pos + 1, NULL, value, len))
2167     return FALSE;
2168   else
2169     return TRUE;
2170 }
2171
2172 /**
2173  * Returns the 32 bit unsigned integer array that the iterator may point
2174  * to. Note that you need to check that the iterator points to an
2175  * array of the correct type prior to using this function.
2176  *
2177  * @param iter the iterator
2178  * @param value return location for the array
2179  * @param len return location for the array length
2180  * @returns #TRUE on success
2181  */
2182 dbus_bool_t
2183 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
2184                                      dbus_uint32_t  **value,
2185                                      int             *len)
2186 {
2187   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2188   int type, pos;
2189   const char *data;
2190
2191   dbus_message_iter_check (real);
2192
2193   pos = dbus_message_iter_get_data_start (real, &type);
2194   
2195   _dbus_assert (type == DBUS_TYPE_ARRAY);
2196
2197   data = _dbus_string_get_const_data_len (&real->message->body,
2198                                           pos,
2199                                           1);
2200
2201   _dbus_assert (*data == DBUS_TYPE_UINT32);
2202
2203   if (!_dbus_demarshal_uint32_array (&real->message->body, real->message->byte_order,
2204                                     pos + 1, NULL, value, len))
2205     return FALSE;
2206   else
2207     return TRUE;
2208 }
2209
2210 /**
2211  * Returns the double array that the iterator may point to. Note that
2212  * you need to check that the iterator points to an array of the
2213  * correct type prior to using this function.
2214  *
2215  * @param iter the iterator
2216  * @param value return location for the array
2217  * @param len return location for the array length
2218  * @returns #TRUE on success
2219  */
2220 dbus_bool_t
2221 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
2222                                      double         **value,
2223                                      int             *len)
2224 {
2225   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2226   int type, pos;
2227   const char *data;
2228
2229   dbus_message_iter_check (real);
2230
2231   pos = dbus_message_iter_get_data_start (real, &type);
2232   
2233   _dbus_assert (type == DBUS_TYPE_ARRAY);
2234
2235   data = _dbus_string_get_const_data_len (&real->message->body,
2236                                           pos,
2237                                           1);
2238
2239   _dbus_assert (*data == DBUS_TYPE_DOUBLE);
2240
2241   if (!_dbus_demarshal_double_array (&real->message->body, real->message->byte_order,
2242                                      pos + 1, NULL, value, len))
2243     return FALSE;
2244   else
2245     return TRUE;
2246 }
2247
2248 /**
2249  * Returns the string array that the iterator may point to.
2250  * Note that you need to check that the iterator points
2251  * to a byte array prior to using this function.
2252  *
2253  * The returned value is a #NULL-terminated array of strings.
2254  * Each string is a separate malloc block, and the array
2255  * itself is a malloc block. You can free this type of
2256  * string array with dbus_free_string_array().
2257  *
2258  * @param iter the iterator
2259  * @param value return location for string values
2260  * @param len return location for length of byte array
2261  * @returns #TRUE on success
2262  */
2263 dbus_bool_t
2264 dbus_message_iter_get_string_array (DBusMessageIter *iter,
2265                                     char          ***value,
2266                                     int             *len)
2267 {
2268   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2269   int type, pos;
2270   const char *data;
2271
2272   dbus_message_iter_check (real);
2273
2274   pos = dbus_message_iter_get_data_start (real, &type);
2275   
2276   _dbus_assert (type == DBUS_TYPE_ARRAY);
2277
2278   data = _dbus_string_get_const_data_len (&real->message->body,
2279                                           pos,
2280                                           1);
2281
2282   _dbus_assert (*data == DBUS_TYPE_STRING);
2283
2284   if (!_dbus_demarshal_string_array (&real->message->body, real->message->byte_order,
2285                                      pos + 1, NULL, value, len))
2286     return FALSE;
2287   else
2288     return TRUE;
2289 }
2290
2291 /**
2292  * Returns the key name fot the dict entry that an iterator
2293  * may point to. Note that you need to check that the iterator
2294  * points to a dict entry before using this function.
2295  *
2296  * @see dbus_message_iter_init_dict_iterator
2297  * @param iter the message iter
2298  * @returns the key name
2299  */
2300 char *
2301 dbus_message_iter_get_dict_key (DBusMessageIter   *iter)
2302 {
2303   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2304
2305   dbus_message_iter_check (real);
2306
2307   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
2308
2309   return _dbus_demarshal_string (&real->message->body, real->message->byte_order,
2310                                  real->pos, NULL);
2311 }
2312
2313 /**
2314  * Initializes a DBusMessageIter pointing to the end of the
2315  * message. This iterator can be used to append data to the
2316  * message.
2317  *
2318  * @param message the message
2319  * @param _iter pointer to an iterator to initialize
2320  */
2321 void
2322 dbus_message_append_iter_init (DBusMessage *message,
2323                                DBusMessageIter *iter)
2324 {
2325   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2326   
2327   real->message = message;
2328   real->parent_iter = NULL;
2329   real->changed_stamp = message->changed_stamp;
2330   
2331   real->type = DBUS_MESSAGE_ITER_TYPE_MESSAGE;
2332   real->end = _dbus_string_get_length (&real->message->body);
2333   real->pos = real->end;
2334   
2335   real->container_type = 0;
2336   real->container_length_pos = 0;
2337   real->wrote_dict_key = 0;
2338 }
2339
2340 static void
2341 dbus_message_iter_append_check (DBusMessageRealIter *iter)
2342 {
2343   _dbus_assert (!iter->message->locked);
2344   
2345   if (iter->changed_stamp != iter->message->changed_stamp)
2346     _dbus_warn ("dbus iterator check failed: invalid iterator");
2347   
2348   if (iter->pos != iter->end)
2349     _dbus_warn ("dbus iterator check failed: can only append at end of message");
2350   
2351   if (iter->pos != _dbus_string_get_length (&iter->message->body))
2352     _dbus_warn ("dbus iterator check failed: append pos not at end of message string");
2353 }
2354
2355 static dbus_bool_t
2356 dbus_message_iter_append_type (DBusMessageRealIter *iter,
2357                                int type)
2358 {
2359   switch (iter->type)
2360     {
2361     case DBUS_MESSAGE_ITER_TYPE_MESSAGE:
2362       if (!_dbus_string_append_byte (&iter->message->body, type))
2363         return FALSE;
2364       break;
2365       
2366     case DBUS_MESSAGE_ITER_TYPE_ARRAY:
2367       if (type != iter->container_type)
2368         {
2369           _dbus_warn ("Appended element of wrong type for array\n");
2370           return FALSE;
2371         }
2372       break;
2373       
2374     case DBUS_MESSAGE_ITER_TYPE_DICT:
2375       if (!iter->wrote_dict_key)
2376         {
2377           _dbus_warn ("Appending dict data before key name\n");
2378           return FALSE;
2379         }
2380       
2381       if (!_dbus_string_append_byte (&iter->message->body, type))
2382         return FALSE;
2383       
2384       break;
2385       
2386     default:
2387       _dbus_assert_not_reached ("Invalid iter type");
2388       break;
2389     }
2390   
2391   return TRUE;
2392 }
2393
2394 static void
2395 dbus_message_iter_update_after_change (DBusMessageRealIter *iter)
2396 {
2397   iter->changed_stamp = iter->message->changed_stamp;
2398   
2399   /* Set new end of iter */
2400   iter->end = _dbus_string_get_length (&iter->message->body);
2401   iter->pos = iter->end;
2402
2403   /* Set container length */
2404   if (iter->type == DBUS_MESSAGE_ITER_TYPE_DICT ||
2405       iter->type == DBUS_MESSAGE_ITER_TYPE_ARRAY)
2406     _dbus_marshal_set_uint32 (&iter->message->body,
2407                               iter->message->byte_order,
2408                               iter->container_length_pos,
2409                               iter->end - iter->container_start);
2410   
2411   if (iter->parent_iter)
2412     dbus_message_iter_update_after_change (iter->parent_iter);
2413 }
2414
2415 static void
2416 dbus_message_iter_append_done (DBusMessageRealIter *iter)
2417 {
2418   iter->message->changed_stamp++;
2419   dbus_message_iter_update_after_change (iter);
2420   iter->wrote_dict_key = FALSE;
2421 }
2422
2423 /**
2424  * Appends a nil value to the message
2425  *
2426  * @param iter an iterator pointing to the end of the message
2427  * @returns #TRUE on success
2428  */
2429 dbus_bool_t
2430 dbus_message_iter_append_nil (DBusMessageIter *iter)
2431 {
2432   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2433
2434   dbus_message_iter_append_check (real);
2435
2436   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NIL))
2437     return FALSE;
2438   
2439   dbus_message_iter_append_done (real);
2440   
2441   return TRUE;
2442 }
2443
2444 /**
2445  * Appends a boolean value to the message
2446  *
2447  * @param iter an iterator pointing to the end of the message
2448  * @param value the boolean value
2449  * @returns #TRUE on success
2450  */
2451 dbus_bool_t
2452 dbus_message_iter_append_boolean (DBusMessageIter *iter,
2453                                   dbus_bool_t     value)
2454 {
2455   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2456
2457   dbus_message_iter_append_check (real);
2458
2459   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
2460     return FALSE;
2461   
2462   if (!_dbus_string_append_byte (&real->message->body, (value != FALSE)))
2463     {
2464       _dbus_string_set_length (&real->message->body, real->pos);
2465       return FALSE;
2466     }
2467
2468   dbus_message_iter_append_done (real);
2469   
2470   return TRUE;
2471 }
2472
2473 /**
2474  * Appends a byte to the message
2475  *
2476  * @param iter an iterator pointing to the end of the message
2477  * @param value the byte value
2478  * @returns #TRUE on success
2479  */
2480 dbus_bool_t
2481 dbus_message_iter_append_byte (DBusMessageIter *iter,
2482                                unsigned char    value)
2483 {
2484   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2485
2486   dbus_message_iter_append_check (real);
2487
2488   if (!dbus_message_iter_append_type (real, DBUS_TYPE_BOOLEAN))
2489     return FALSE;
2490   
2491   if (!_dbus_string_append_byte (&real->message->body, value))
2492     {
2493       _dbus_string_set_length (&real->message->body, real->pos);
2494       return FALSE;
2495     }
2496
2497   dbus_message_iter_append_done (real);
2498   
2499   return TRUE;
2500 }
2501
2502
2503 /**
2504  * Appends a 32 bit signed integer to the message.
2505  *
2506  * @param iter an iterator pointing to the end of the message
2507  * @param value the integer value
2508  * @returns #TRUE on success
2509  */
2510 dbus_bool_t
2511 dbus_message_iter_append_int32   (DBusMessageIter *iter,
2512                                   dbus_int32_t  value)
2513 {
2514   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2515
2516   dbus_message_iter_append_check (real);
2517
2518   if (!dbus_message_iter_append_type (real, DBUS_TYPE_INT32))
2519     return FALSE;
2520   
2521   if (!_dbus_marshal_int32 (&real->message->body, real->message->byte_order, value))
2522     {
2523       _dbus_string_set_length (&real->message->body, real->pos);
2524       return FALSE;
2525     }
2526
2527   dbus_message_iter_append_done (real);
2528   
2529   return TRUE;
2530 }
2531
2532 /**
2533  * Appends a 32 bit unsigned integer to the message.
2534  *
2535  * @param iter an iterator pointing to the end of the message
2536  * @param value the integer value
2537  * @returns #TRUE on success
2538  */
2539 dbus_bool_t
2540 dbus_message_iter_append_uint32 (DBusMessageIter *iter,
2541                                  dbus_uint32_t    value)
2542 {
2543   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2544
2545   dbus_message_iter_append_check (real);
2546
2547   if (!dbus_message_iter_append_type (real, DBUS_TYPE_UINT32))
2548     return FALSE;
2549   
2550   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, value))
2551     {
2552       _dbus_string_set_length (&real->message->body, real->pos);
2553       return FALSE;
2554     }
2555
2556   dbus_message_iter_append_done (real);
2557   
2558   return TRUE;
2559 }
2560
2561 /**
2562  * Appends a double value to the message.
2563  *
2564  * @param iter an iterator pointing to the end of the message
2565  * @param value the double value
2566  * @returns #TRUE on success
2567  */
2568 dbus_bool_t
2569 dbus_message_iter_append_double (DBusMessageIter *iter,
2570                                  double           value)
2571 {
2572   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2573
2574   dbus_message_iter_append_check (real);
2575
2576   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DOUBLE))
2577     return FALSE;
2578   
2579   if (!_dbus_marshal_double (&real->message->body, real->message->byte_order, value))
2580     {
2581       _dbus_string_set_length (&real->message->body, real->pos);
2582       return FALSE;
2583     }
2584
2585   dbus_message_iter_append_done (real);
2586   
2587   return TRUE;
2588 }
2589
2590 /**
2591  * Appends a UTF-8 string to the message.
2592  *
2593  * @param iter an iterator pointing to the end of the message
2594  * @param value the string
2595  * @returns #TRUE on success
2596  */
2597 dbus_bool_t
2598 dbus_message_iter_append_string (DBusMessageIter *iter,
2599                                  const char      *value)
2600 {
2601   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2602
2603   dbus_message_iter_append_check (real);
2604
2605   if (!dbus_message_iter_append_type (real, DBUS_TYPE_STRING))
2606     return FALSE;
2607   
2608   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
2609     {
2610       _dbus_string_set_length (&real->message->body, real->pos);
2611       return FALSE;
2612     }
2613
2614   dbus_message_iter_append_done (real);
2615   
2616   return TRUE;
2617 }
2618
2619 /**
2620  * Appends a named type data chunk to the message.
2621  *
2622  * @param iter an iterator pointing to the end of the message
2623  * @param name the name of the type
2624  * @parame
2625  * @returns #TRUE on success
2626  */
2627 dbus_bool_t
2628 dbus_message_iter_append_named (DBusMessageIter      *iter,
2629                                 const char           *name,
2630                                 const unsigned char  *data,
2631                                 int                   len)
2632 {
2633   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2634
2635   dbus_message_iter_append_check (real);
2636
2637   if (!dbus_message_iter_append_type (real, DBUS_TYPE_NAMED))
2638     return FALSE;
2639   
2640    if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, data))
2641     {
2642       _dbus_string_set_length (&real->message->body, real->pos);
2643       return FALSE;
2644     }
2645    
2646   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, data, len))
2647     {
2648       _dbus_string_set_length (&real->message->body, real->pos);
2649       return FALSE;
2650     }
2651
2652   dbus_message_iter_append_done (real);
2653   
2654   return TRUE;
2655 }
2656
2657
2658 /**
2659  * Appends a dict key name to the message. The iterator used
2660  * must point to a dict.
2661  *
2662  * @param iter an iterator pointing to the end of the message
2663  * @param value the string
2664  * @returns #TRUE on success
2665  */
2666 dbus_bool_t
2667 dbus_message_iter_append_dict_key (DBusMessageIter *iter,
2668                                    const char      *value)
2669 {
2670   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2671
2672   dbus_message_iter_append_check (real);
2673   _dbus_assert (real->type == DBUS_MESSAGE_ITER_TYPE_DICT);
2674   
2675   if (real->wrote_dict_key)
2676     {
2677       _dbus_warn ("Appendinging multiple dict key names\n");
2678       return FALSE;
2679     }
2680   
2681   if (!_dbus_marshal_string (&real->message->body, real->message->byte_order, value))
2682     {
2683       return FALSE;
2684     }
2685
2686   dbus_message_iter_append_done (real);
2687   real->wrote_dict_key = TRUE;
2688   
2689   return TRUE;
2690 }
2691
2692 /**
2693  * Appends an array to the message and initializes an iterator that
2694  * can be used to append to the array.
2695  *
2696  * @param iter an iterator pointing to the end of the message
2697  * @param array_iter pointer to an iter that will be initialized
2698  * @param element_type the type of the array elements
2699  * @returns #TRUE on success
2700  */
2701 dbus_bool_t
2702 dbus_message_iter_append_array (DBusMessageIter      *iter,
2703                                 DBusMessageIter      *array_iter,
2704                                 int                   element_type)
2705 {
2706   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2707   DBusMessageRealIter *array_real = (DBusMessageRealIter *)array_iter;
2708   int len_pos;
2709
2710   dbus_message_iter_append_check (real);
2711
2712   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2713     return FALSE;
2714
2715   if (!_dbus_string_append_byte (&real->message->body, element_type))
2716     {
2717       _dbus_string_set_length (&real->message->body, real->pos);
2718       return FALSE;
2719     }
2720
2721   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
2722
2723   /* Empty length for now, backfill later */
2724   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
2725     {
2726       _dbus_string_set_length (&real->message->body, real->pos);
2727       return FALSE;
2728     }
2729   
2730   array_real->parent_iter = real;
2731   array_real->message = real->message;
2732   array_real->changed_stamp = real->message->changed_stamp;
2733   
2734   array_real->type = DBUS_MESSAGE_ITER_TYPE_ARRAY;
2735   array_real->pos = _dbus_string_get_length (&real->message->body);
2736   array_real->end = array_real->end;
2737   
2738   array_real->container_type = element_type;
2739   array_real->container_start = array_real->pos;
2740   array_real->container_length_pos = len_pos;
2741   array_real->wrote_dict_key = 0;
2742
2743   dbus_message_iter_append_done (array_real);
2744   
2745   return TRUE;
2746 }
2747
2748 /**
2749  * Appends a dict to the message and initializes an iterator that
2750  * can be used to append to the dict.
2751  *
2752  * @param iter an iterator pointing to the end of the message
2753  * @param array_iter pointer to an iter that will be initialized
2754  * @param element_type the type of the array elements
2755  * @returns #TRUE on success
2756  */
2757 dbus_bool_t
2758 dbus_message_iter_append_dict (DBusMessageIter      *iter,
2759                                DBusMessageIter      *dict_iter)
2760 {
2761   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2762   DBusMessageRealIter *dict_real = (DBusMessageRealIter *)dict_iter;
2763   int len_pos;
2764
2765   dbus_message_iter_append_check (real);
2766
2767   if (!dbus_message_iter_append_type (real, DBUS_TYPE_DICT))
2768     return FALSE;
2769
2770   len_pos = _DBUS_ALIGN_VALUE (_dbus_string_get_length (&real->message->body), sizeof (dbus_uint32_t));
2771
2772   /* Empty length for now, backfill later */
2773   if (!_dbus_marshal_uint32 (&real->message->body, real->message->byte_order, 0))
2774     {
2775       _dbus_string_set_length (&real->message->body, real->pos);
2776       return FALSE;
2777     }
2778   
2779   dict_real->parent_iter = real;
2780   dict_real->message = real->message;
2781   dict_real->changed_stamp = real->message->changed_stamp;
2782   
2783   dict_real->type = DBUS_MESSAGE_ITER_TYPE_DICT;
2784   dict_real->pos = _dbus_string_get_length (&real->message->body);
2785   dict_real->end = dict_real->end;
2786   
2787   dict_real->container_type = 0;
2788   dict_real->container_start = dict_real->pos;
2789   dict_real->container_length_pos = len_pos;
2790   dict_real->wrote_dict_key = 0;
2791
2792   dbus_message_iter_append_done (dict_real);
2793   
2794   return TRUE;
2795 }
2796
2797
2798 /**
2799  * Appends a boolean array to the message.
2800  *
2801  * @param iter an iterator pointing to the end of the message
2802  * @param value the array
2803  * @param len the length of the array
2804  * @returns #TRUE on success
2805  */
2806 dbus_bool_t
2807 dbus_message_iter_append_boolean_array (DBusMessageIter     *iter,
2808                                         unsigned const char *value,
2809                                         int                  len)
2810 {
2811   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2812
2813   dbus_message_iter_append_check (real);
2814
2815   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2816     return FALSE;
2817   
2818   if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BOOLEAN))
2819     {
2820       _dbus_string_set_length (&real->message->body, real->pos);
2821       return FALSE;
2822     }
2823
2824   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
2825     {
2826       _dbus_string_set_length (&real->message->body, real->pos);
2827       return FALSE;
2828     }
2829
2830   dbus_message_iter_append_done (real);
2831   
2832   return TRUE;
2833 }
2834
2835 /**
2836  * Appends a 32 bit signed integer array to the message.
2837  *
2838  * @param iter an iterator pointing to the end of the message
2839  * @param value the array
2840  * @param len the length of the array
2841  * @returns #TRUE on success
2842  */
2843 dbus_bool_t
2844 dbus_message_iter_append_int32_array (DBusMessageIter    *iter,
2845                                       const dbus_int32_t *value,
2846                                       int                 len)
2847 {
2848   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2849
2850   dbus_message_iter_append_check (real);
2851
2852   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2853     return FALSE;
2854   
2855   if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_INT32))
2856     {
2857       _dbus_string_set_length (&real->message->body, real->pos);
2858       return FALSE;
2859     }
2860
2861   if (!_dbus_marshal_int32_array (&real->message->body, real->message->byte_order, value, len))
2862     {
2863       _dbus_string_set_length (&real->message->body, real->pos);
2864       return FALSE;
2865     }
2866
2867   dbus_message_iter_append_done (real);
2868   
2869   return TRUE;
2870 }
2871
2872 /**
2873  * Appends a 32 bit unsigned integer array to the message.
2874  *
2875  * @param iter an iterator pointing to the end of the message
2876  * @param value the array
2877  * @param len the length of the array
2878  * @returns #TRUE on success
2879  */
2880 dbus_bool_t
2881 dbus_message_iter_append_uint32_array (DBusMessageIter     *iter,
2882                                        const dbus_uint32_t *value,
2883                                        int                  len)
2884 {
2885   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2886
2887   dbus_message_iter_append_check (real);
2888
2889   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2890     return FALSE;
2891   
2892   if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_UINT32))
2893     {
2894       _dbus_string_set_length (&real->message->body, real->pos);
2895       return FALSE;
2896     }
2897
2898   if (!_dbus_marshal_uint32_array (&real->message->body, real->message->byte_order, value, len))
2899     {
2900       _dbus_string_set_length (&real->message->body, real->pos);
2901       return FALSE;
2902     }
2903
2904   dbus_message_iter_append_done (real);
2905   
2906   return TRUE;
2907 }
2908
2909 /**
2910  * Appends a double array to the message.
2911  *
2912  * @param iter an iterator pointing to the end of the message
2913  * @param value the array
2914  * @param len the length of the array
2915  * @returns #TRUE on success
2916  */
2917 dbus_bool_t
2918 dbus_message_iter_append_double_array (DBusMessageIter *iter,
2919                                        const double    *value,
2920                                        int              len)
2921 {
2922   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2923
2924   dbus_message_iter_append_check (real);
2925
2926   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2927     return FALSE;
2928   
2929   if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_DOUBLE))
2930     {
2931       _dbus_string_set_length (&real->message->body, real->pos);
2932       return FALSE;
2933     }
2934
2935   if (!_dbus_marshal_double_array (&real->message->body, real->message->byte_order, value, len))
2936     {
2937       _dbus_string_set_length (&real->message->body, real->pos);
2938       return FALSE;
2939     }
2940
2941   dbus_message_iter_append_done (real);
2942   
2943   return TRUE;
2944 }
2945
2946 /**
2947  * Appends a byte array to the message.
2948  *
2949  * @param iter an iterator pointing to the end of the message
2950  * @param value the array
2951  * @param len the length of the array
2952  * @returns #TRUE on success
2953  */
2954 dbus_bool_t
2955 dbus_message_iter_append_byte_array (DBusMessageIter     *iter,
2956                                      unsigned const char *value,
2957                                      int                  len)
2958 {
2959   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2960
2961   dbus_message_iter_append_check (real);
2962
2963   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
2964     return FALSE;
2965   
2966   if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BYTE))
2967     {
2968       _dbus_string_set_length (&real->message->body, real->pos);
2969       return FALSE;
2970     }
2971
2972   if (!_dbus_marshal_byte_array (&real->message->body, real->message->byte_order, value, len))
2973     {
2974       _dbus_string_set_length (&real->message->body, real->pos);
2975       return FALSE;
2976     }
2977
2978   dbus_message_iter_append_done (real);
2979   
2980   return TRUE;
2981 }
2982
2983 /**
2984  * Appends a string array to the message.
2985  *
2986  * @param iter an iterator pointing to the end of the message
2987  * @param value the array
2988  * @param len the length of the array
2989  * @returns #TRUE on success
2990  */
2991 dbus_bool_t
2992 dbus_message_iter_append_string_array (DBusMessageIter *iter,
2993                                        const char     **value,
2994                                        int              len)
2995 {
2996   DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2997
2998   dbus_message_iter_append_check (real);
2999
3000   if (!dbus_message_iter_append_type (real, DBUS_TYPE_ARRAY))
3001     return FALSE;
3002   
3003   if (!_dbus_string_append_byte (&real->message->body, DBUS_TYPE_BYTE))
3004     {
3005       _dbus_string_set_length (&real->message->body, real->pos);
3006       return FALSE;
3007     }
3008
3009   if (!_dbus_marshal_string_array (&real->message->body, real->message->byte_order, value, len))
3010     {
3011       _dbus_string_set_length (&real->message->body, real->pos);
3012       return FALSE;
3013     }
3014
3015   dbus_message_iter_append_done (real);
3016   
3017   return TRUE;
3018 }
3019
3020 /**
3021  * Sets the message sender.
3022  *
3023  * @param message the message
3024  * @param sender the sender
3025  * @returns #FALSE if not enough memory
3026  */
3027 dbus_bool_t
3028 dbus_message_set_sender (DBusMessage  *message,
3029                          const char   *sender)
3030 {
3031   _dbus_assert (!message->locked);
3032
3033   if (sender == NULL)
3034     {
3035       delete_string_field (message, FIELD_SENDER);
3036       return TRUE;
3037     }
3038   else
3039     {
3040       return set_string_field (message,
3041                                FIELD_SENDER,
3042                                sender);
3043     }
3044 }
3045
3046 /**
3047  * Sets a flag indicating that the message is an error reply
3048  * message, i.e. an "exception" rather than a normal response.
3049  *
3050  * @param message the message
3051  * @param is_error_reply #TRUE if this is an error message.
3052  */
3053 void
3054 dbus_message_set_is_error (DBusMessage *message,
3055                            dbus_bool_t  is_error_reply)
3056 {
3057   char *header;
3058   
3059   _dbus_assert (!message->locked);
3060   
3061   header = _dbus_string_get_data_len (&message->header, 1, 1);
3062   
3063   if (is_error_reply)
3064     *header |= DBUS_HEADER_FLAG_ERROR;
3065   else
3066     *header &= ~DBUS_HEADER_FLAG_ERROR;    
3067 }
3068
3069 /**
3070  * Returns #TRUE if the message is an error
3071  * reply to some previous message we sent.
3072  *
3073  * @param message the message
3074  * @returns #TRUE if the message is an error
3075  */
3076 dbus_bool_t
3077 dbus_message_get_is_error (DBusMessage *message)
3078 {
3079   const char *header;
3080
3081   header = _dbus_string_get_const_data_len (&message->header, 1, 1);
3082
3083   return (*header & DBUS_HEADER_FLAG_ERROR) != 0;
3084 }
3085
3086 /**
3087  * Gets the service which originated this message,
3088  * or #NULL if unknown or inapplicable.
3089  *
3090  * @param message the message
3091  * @returns the service name or #NULL
3092  */
3093 const char*
3094 dbus_message_get_sender (DBusMessage *message)
3095 {
3096   return get_string_field (message, FIELD_SENDER, NULL);
3097 }
3098
3099 /**
3100  * Checks whether the message has the given name.
3101  * If the message has no name or has a different
3102  * name, returns #FALSE.
3103  *
3104  * @param message the message
3105  * @param name the name to check (must not be #NULL)
3106  * 
3107  * @returns #TRUE if the message has the given name
3108  */
3109 dbus_bool_t
3110 dbus_message_name_is (DBusMessage *message,
3111                       const char  *name)
3112 {
3113   const char *n;
3114
3115   _dbus_assert (name != NULL);
3116   
3117   n = dbus_message_get_name (message);
3118
3119   if (n && strcmp (n, name) == 0)
3120     return TRUE;
3121   else
3122     return FALSE;
3123 }
3124
3125 /**
3126  * Checks whether the message was sent to the given service.  If the
3127  * message has no service specified or has a different name, returns
3128  * #FALSE.
3129  *
3130  * @param message the message
3131  * @param service the service to check (must not be #NULL)
3132  * 
3133  * @returns #TRUE if the message has the given destination service
3134  */
3135 dbus_bool_t
3136 dbus_message_service_is (DBusMessage  *message,
3137                          const char   *service)
3138 {
3139   const char *s;
3140
3141   _dbus_assert (service != NULL);
3142   
3143   s = dbus_message_get_service (message);
3144
3145   if (s && strcmp (s, service) == 0)
3146     return TRUE;
3147   else
3148     return FALSE;
3149 }
3150
3151 /**
3152  * Checks whether the message has the given service as its sender.  If
3153  * the message has no sender specified or has a different sender,
3154  * returns #FALSE. Note that if a peer application owns multiple
3155  * services, its messages will have only one of those services as the
3156  * sender (usually the base service). So you can't use this
3157  * function to prove the sender didn't own service Foo, you can
3158  * only use it to prove that it did.
3159  *
3160  * @param message the message
3161  * @param service the service to check (must not be #NULL)
3162  * 
3163  * @returns #TRUE if the message has the given origin service
3164  */
3165 dbus_bool_t
3166 dbus_message_sender_is (DBusMessage  *message,
3167                         const char   *service)
3168 {
3169   const char *s;
3170
3171   _dbus_assert (service != NULL);
3172   
3173   s = dbus_message_get_sender (message);
3174
3175   if (s && strcmp (s, service) == 0)
3176     return TRUE;
3177   else
3178     return FALSE;
3179 }
3180
3181 /**
3182  * Sets a #DBusError based on the contents of the given
3183  * message. The error is only set if the message
3184  * is an error message, as in dbus_message_get_is_error().
3185  * The name of the error is set to the name of the message,
3186  * and the error message is set to the first argument
3187  * if the argument exists and is a string.
3188  *
3189  * The return value indicates whether the error was set (the error is
3190  * set if and only if the message is an error message).
3191  * So you can check for an error reply and convert it to DBusError
3192  * in one go.
3193  *
3194  * @param error the error to set
3195  * @param message the message to set it from
3196  * @returns #TRUE if dbus_message_get_is_error() returns #TRUE for the message
3197  */
3198 dbus_bool_t
3199 dbus_set_error_from_message (DBusError   *error,
3200                              DBusMessage *message)
3201 {
3202   char *str;
3203   
3204   if (!dbus_message_get_is_error (message))
3205     return FALSE;
3206
3207   str = NULL;
3208   dbus_message_get_args (message, NULL,
3209                          DBUS_TYPE_STRING, &str,
3210                          DBUS_TYPE_INVALID);
3211
3212   dbus_set_error (error, dbus_message_get_name (message),
3213                   str ? "%s" : NULL, str);
3214
3215   dbus_free (str);
3216   
3217   return TRUE;
3218 }
3219
3220 /** @} */
3221
3222 /**
3223  * @addtogroup DBusMessageInternals
3224  *
3225  * @{
3226  */
3227 /**
3228  * @typedef DBusMessageLoader
3229  *
3230  * The DBusMessageLoader object encapsulates the process of converting
3231  * a byte stream into a series of DBusMessage. It buffers the incoming
3232  * bytes as efficiently as possible, and generates a queue of
3233  * messages. DBusMessageLoader is typically used as part of a
3234  * DBusTransport implementation. The DBusTransport then hands off
3235  * the loaded messages to a DBusConnection, making the messages
3236  * visible to the application.
3237  *
3238  * @todo write tests for break-loader that a) randomly delete header
3239  * fields and b) set string fields to zero-length and other funky
3240  * values.
3241  * 
3242  */
3243
3244 /* we definitely use signed ints for sizes, so don't exceed
3245  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
3246  * over 128M is pretty nuts anyhow.
3247  */
3248
3249 /**
3250  * The maximum sane message size.
3251  */
3252 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
3253
3254 /**
3255  * Implementation details of DBusMessageLoader.
3256  * All members are private.
3257  */
3258 struct DBusMessageLoader
3259 {
3260   int refcount;        /**< Reference count. */
3261
3262   DBusString data;     /**< Buffered data */
3263   
3264   DBusList *messages;  /**< Complete messages. */
3265
3266   long max_message_size; /**< Maximum size of a message */
3267   
3268   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
3269
3270   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
3271 };
3272
3273 /**
3274  * The initial buffer size of the message loader.
3275  * 
3276  * @todo this should be based on min header size plus some average
3277  * body size, or something. Or rather, the min header size only, if we
3278  * want to try to read only the header, store that in a DBusMessage,
3279  * then read only the body and store that, etc., depends on
3280  * how we optimize _dbus_message_loader_get_buffer() and what
3281  * the exact message format is.
3282  */
3283 #define INITIAL_LOADER_DATA_LEN 32
3284
3285 /**
3286  * Creates a new message loader. Returns #NULL if memory can't
3287  * be allocated.
3288  *
3289  * @returns new loader, or #NULL.
3290  */
3291 DBusMessageLoader*
3292 _dbus_message_loader_new (void)
3293 {
3294   DBusMessageLoader *loader;
3295
3296   loader = dbus_new0 (DBusMessageLoader, 1);
3297   if (loader == NULL)
3298     return NULL;
3299   
3300   loader->refcount = 1;
3301
3302   /* Try to cap message size at something that won't *totally* hose
3303    * the system if we have a couple of them.
3304    */
3305   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
3306   
3307   if (!_dbus_string_init (&loader->data))
3308     {
3309       dbus_free (loader);
3310       return NULL;
3311     }
3312
3313   /* preallocate the buffer for speed, ignore failure */
3314   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
3315   _dbus_string_set_length (&loader->data, 0);
3316   
3317   return loader;
3318 }
3319
3320 /**
3321  * Increments the reference count of the loader.
3322  *
3323  * @param loader the loader.
3324  */
3325 void
3326 _dbus_message_loader_ref (DBusMessageLoader *loader)
3327 {
3328   loader->refcount += 1;
3329 }
3330
3331 /**
3332  * Decrements the reference count of the loader and finalizes the
3333  * loader when the count reaches zero.
3334  *
3335  * @param loader the loader.
3336  */
3337 void
3338 _dbus_message_loader_unref (DBusMessageLoader *loader)
3339 {
3340   loader->refcount -= 1;
3341   if (loader->refcount == 0)
3342     {
3343       _dbus_list_foreach (&loader->messages,
3344                           (DBusForeachFunction) dbus_message_unref,
3345                           NULL);
3346       _dbus_list_clear (&loader->messages);
3347       _dbus_string_free (&loader->data);
3348       dbus_free (loader);
3349     }
3350 }
3351
3352 /**
3353  * Gets the buffer to use for reading data from the network.  Network
3354  * data is read directly into an allocated buffer, which is then used
3355  * in the DBusMessage, to avoid as many extra memcpy's as possible.
3356  * The buffer must always be returned immediately using
3357  * _dbus_message_loader_return_buffer(), even if no bytes are
3358  * successfully read.
3359  *
3360  * @todo this function can be a lot more clever. For example
3361  * it can probably always return a buffer size to read exactly
3362  * the body of the next message, thus avoiding any memory wastage
3363  * or reallocs.
3364  *
3365  * @todo we need to enforce a max length on strings in header fields.
3366  * 
3367  * @param loader the message loader.
3368  * @param buffer the buffer
3369  */
3370 void
3371 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
3372                                  DBusString        **buffer)
3373 {
3374   _dbus_assert (!loader->buffer_outstanding);
3375
3376   *buffer = &loader->data;
3377   
3378   loader->buffer_outstanding = TRUE;
3379 }
3380
3381 /**
3382  * The smallest header size that can occur. 
3383  * (It won't be valid)
3384  */
3385 #define DBUS_MINIMUM_HEADER_SIZE 16
3386
3387 /** Pack four characters as in "abcd" into a uint32 */
3388 #define FOUR_CHARS_TO_UINT32(a, b, c, d)                \
3389                       ((((dbus_uint32_t)a) << 24) |     \
3390                        (((dbus_uint32_t)b) << 16) |     \
3391                        (((dbus_uint32_t)c) << 8)  |     \
3392                        ((dbus_uint32_t)d))
3393
3394 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
3395 #define DBUS_HEADER_FIELD_NAME_AS_UINT32    \
3396   FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
3397
3398 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
3399 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
3400   FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
3401
3402 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
3403 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32   \
3404   FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
3405
3406 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
3407 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32  \
3408   FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
3409
3410 /* FIXME impose max length on name, srvc, sndr */
3411 static dbus_bool_t
3412 decode_header_data (const DBusString   *data,
3413                     int                 header_len,
3414                     int                 byte_order,
3415                     HeaderField         fields[FIELD_LAST],
3416                     int                *message_padding)
3417 {
3418   const char *field;
3419   int pos, new_pos;
3420   int i;
3421   int type;
3422   
3423   if (header_len < 16)
3424     return FALSE;
3425   
3426   i = 0;
3427   while (i < FIELD_LAST)
3428     {
3429       fields[i].offset = -1;
3430       ++i;
3431     }
3432   
3433   fields[FIELD_HEADER_LENGTH].offset = 4;
3434   fields[FIELD_BODY_LENGTH].offset = 8;   
3435   fields[FIELD_CLIENT_SERIAL].offset = 12;
3436   
3437   /* Now handle the named fields. A real named field is at least 4
3438    * bytes for the name, plus a type code (1 byte) plus padding.  So
3439    * if we have less than 8 bytes left, it must be alignment padding,
3440    * not a field. While >= 8 bytes can't be entirely alignment
3441    * padding.
3442    */  
3443   pos = 16;
3444   while ((pos + 7) < header_len)
3445     {
3446       pos = _DBUS_ALIGN_VALUE (pos, 4);
3447       
3448       if ((pos + 4) > header_len)
3449         return FALSE;      
3450       
3451       field =_dbus_string_get_const_data_len (data, pos, 4);
3452       pos += 4;
3453
3454       _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
3455
3456       switch (DBUS_UINT32_FROM_BE (*(int*)field))
3457         {
3458         case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
3459           if (fields[FIELD_SERVICE].offset >= 0)
3460             {
3461               _dbus_verbose ("%s field provided twice\n",
3462                              DBUS_HEADER_FIELD_SERVICE);
3463               return FALSE;
3464             }
3465           
3466           fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3467 #if 0
3468           _dbus_verbose ("Found service name at offset %d\n",
3469                          fields[FIELD_SERVICE].offset);
3470 #endif
3471           break;
3472
3473         case DBUS_HEADER_FIELD_NAME_AS_UINT32:
3474           if (fields[FIELD_NAME].offset >= 0)
3475             {              
3476               _dbus_verbose ("%s field provided twice\n",
3477                              DBUS_HEADER_FIELD_NAME);
3478               return FALSE;
3479             }
3480           
3481           fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3482
3483 #if 0
3484           _dbus_verbose ("Found message name at offset %d\n",
3485                          fields[FIELD_NAME].offset);
3486 #endif
3487           break;
3488         case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
3489           if (fields[FIELD_SENDER].offset >= 0)
3490             {
3491               _dbus_verbose ("%s field provided twice\n",
3492                              DBUS_HEADER_FIELD_SENDER);
3493               return FALSE;
3494             }
3495           
3496           fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3497
3498           _dbus_verbose ("Found sender name at offset %d\n",
3499                          fields[FIELD_NAME].offset);
3500           break;
3501           
3502         case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
3503           if (fields[FIELD_REPLY_SERIAL].offset >= 0)
3504             {
3505               _dbus_verbose ("%s field provided twice\n",
3506                              DBUS_HEADER_FIELD_REPLY);
3507               return FALSE;
3508             }
3509           
3510           fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
3511
3512           _dbus_verbose ("Found reply serial at offset %d\n",
3513                          fields[FIELD_REPLY_SERIAL].offset);
3514           break;
3515
3516         default:
3517           _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c at offset %d\n",
3518                          field[0], field[1], field[2], field[3], pos);
3519         }
3520
3521       if (!_dbus_marshal_validate_type (data, pos, &type, &pos))
3522         {
3523           _dbus_verbose ("Failed to validate type of named header field\n");
3524           return FALSE;
3525         }
3526       
3527       if (!_dbus_marshal_validate_arg (data, byte_order, 0, type, pos, &new_pos))
3528         {
3529           _dbus_verbose ("Failed to validate argument to named header field\n");
3530           return FALSE;
3531         }
3532
3533       if (new_pos > header_len)
3534         {
3535           _dbus_verbose ("Named header field tries to extend beyond header length\n");
3536           return FALSE;
3537         }
3538       
3539       pos = new_pos;
3540     }
3541
3542   if (pos < header_len)
3543     {
3544       /* Alignment padding, verify that it's nul */
3545       _dbus_assert ((header_len - pos) < 8);
3546
3547       if (!_dbus_string_validate_nul (data,
3548                                       pos, (header_len - pos)))
3549         {
3550           _dbus_verbose ("header alignment padding is not nul\n");
3551           return FALSE;
3552         }
3553     }
3554
3555  if (fields[FIELD_NAME].offset < 0)
3556    {
3557      _dbus_verbose ("No %s field provided\n",
3558                     DBUS_HEADER_FIELD_NAME);
3559      return FALSE;
3560    }
3561   
3562   if (message_padding)
3563     *message_padding = header_len - pos;  
3564   
3565   return TRUE;
3566 }
3567
3568 /**
3569  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
3570  * indicating to the loader how many bytes of the buffer were filled
3571  * in. This function must always be called, even if no bytes were
3572  * successfully read.
3573  *
3574  * @param loader the loader.
3575  * @param buffer the buffer.
3576  * @param bytes_read number of bytes that were read into the buffer.
3577  */
3578 void
3579 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
3580                                     DBusString         *buffer,
3581                                     int                 bytes_read)
3582 {
3583   _dbus_assert (loader->buffer_outstanding);
3584   _dbus_assert (buffer == &loader->data);
3585
3586   loader->buffer_outstanding = FALSE;
3587 }
3588
3589 /**
3590  * Converts buffered data into messages.
3591  *
3592  * @param loader the loader.
3593  * @returns #TRUE if we had enough memory to finish.
3594  */
3595 dbus_bool_t
3596 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
3597 {
3598   if (loader->corrupted)
3599     return TRUE;
3600
3601   while (_dbus_string_get_length (&loader->data) >= 16)
3602     {
3603       DBusMessage *message;      
3604       const char *header_data;
3605       int byte_order, header_len, body_len, header_padding;
3606       dbus_uint32_t header_len_unsigned, body_len_unsigned;
3607       
3608       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
3609
3610       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
3611
3612       if (header_data[2] != DBUS_MAJOR_PROTOCOL_VERSION)
3613         {
3614           _dbus_verbose ("Message has protocol version %d ours is %d\n",
3615                          (int) header_data[2], DBUS_MAJOR_PROTOCOL_VERSION);
3616           loader->corrupted = TRUE;
3617           return TRUE;
3618         }
3619       
3620       byte_order = header_data[0];
3621
3622       if (byte_order != DBUS_LITTLE_ENDIAN &&
3623           byte_order != DBUS_BIG_ENDIAN)
3624         {
3625           _dbus_verbose ("Message with bad byte order '%c' received\n",
3626                          byte_order);
3627           loader->corrupted = TRUE;
3628           return TRUE;
3629         }
3630
3631       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
3632       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
3633
3634       if (header_len_unsigned < 16)
3635         {
3636           _dbus_verbose ("Message had broken too-small header length %u\n",
3637                          header_len_unsigned);
3638           loader->corrupted = TRUE;
3639           return TRUE;
3640         }
3641
3642       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
3643           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
3644         {
3645           _dbus_verbose ("Header or body length too large (%u %u)\n",
3646                          header_len_unsigned,
3647                          body_len_unsigned);
3648           loader->corrupted = TRUE;
3649           return TRUE;
3650         }
3651
3652       /* Now that we know the values are in signed range, get
3653        * rid of stupid unsigned, just causes bugs
3654        */
3655       header_len = header_len_unsigned;
3656       body_len = body_len_unsigned;
3657
3658       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
3659         {
3660           
3661           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
3662                          header_len);
3663           loader->corrupted = TRUE;
3664           return TRUE;
3665         }
3666       
3667       if (header_len + body_len > loader->max_message_size)
3668         {
3669           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
3670                          header_len, body_len, loader->max_message_size);
3671           loader->corrupted = TRUE;
3672           return TRUE;
3673         }
3674
3675       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
3676         {
3677           HeaderField fields[FIELD_LAST];
3678           int i;
3679           int next_arg;          
3680
3681 #if 0
3682           _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);
3683 #endif    
3684           if (!decode_header_data (&loader->data, header_len, byte_order,
3685                                    fields, &header_padding))
3686             {
3687               _dbus_verbose ("Header was invalid\n");
3688               loader->corrupted = TRUE;
3689               return TRUE;
3690             }
3691           
3692           next_arg = header_len;
3693           while (next_arg < (header_len + body_len))
3694             {
3695               int type;
3696               int prev = next_arg;
3697
3698               if (!_dbus_marshal_validate_type (&loader->data, next_arg,
3699                                                 &type, &next_arg))
3700                 {
3701                   _dbus_verbose ("invalid typecode at offset %d\n", prev);
3702                   loader->corrupted = TRUE;
3703                   return TRUE;
3704                 }
3705       
3706               if (!_dbus_marshal_validate_arg (&loader->data,
3707                                                byte_order,
3708                                                0,
3709                                                type,
3710                                                next_arg,
3711                                                &next_arg))
3712                 {
3713                   _dbus_verbose ("invalid type data at %d, next_arg\n", next_arg);
3714                   loader->corrupted = TRUE;
3715                   return TRUE;
3716                 }
3717
3718               _dbus_assert (next_arg > prev);
3719             }
3720           
3721           if (next_arg > (header_len + body_len))
3722             {
3723               _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
3724                              next_arg, header_len, body_len,
3725                              header_len + body_len);
3726               loader->corrupted = TRUE;
3727               return TRUE;
3728             }
3729
3730           message = dbus_message_new_empty_header ();
3731           if (message == NULL)
3732             {
3733               _dbus_verbose ("Failed to allocate empty message\n");
3734               return FALSE;
3735             }
3736
3737           message->byte_order = byte_order;
3738           message->header_padding = header_padding;
3739           
3740           /* Copy in the offsets we found */
3741           i = 0;
3742           while (i < FIELD_LAST)
3743             {
3744               message->header_fields[i] = fields[i];
3745               ++i;
3746             }
3747           
3748           if (!_dbus_list_append (&loader->messages, message))
3749             {
3750               _dbus_verbose ("Failed to append new message to loader queue\n");
3751               dbus_message_unref (message);
3752               return FALSE;
3753             }
3754
3755           _dbus_assert (_dbus_string_get_length (&message->header) == 0);
3756           _dbus_assert (_dbus_string_get_length (&message->body) == 0);
3757
3758           _dbus_assert (_dbus_string_get_length (&loader->data) >=
3759                         (header_len + body_len));
3760           
3761           if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
3762             {
3763               _dbus_verbose ("Failed to move header into new message\n");
3764               _dbus_list_remove_last (&loader->messages, message);
3765               dbus_message_unref (message);
3766               return FALSE;
3767             }
3768           
3769           if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
3770             {
3771               dbus_bool_t result;
3772
3773               _dbus_verbose ("Failed to move body into new message\n");
3774               
3775               /* put the header back, we'll try again later */
3776               result = _dbus_string_copy_len (&message->header, 0, header_len,
3777                                               &loader->data, 0);
3778               _dbus_assert (result); /* because DBusString never reallocs smaller */
3779
3780               _dbus_list_remove_last (&loader->messages, message);
3781               dbus_message_unref (message);
3782               return FALSE;
3783             }
3784
3785           _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
3786           _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
3787
3788           /* Fill in caches */
3789           message->reply_serial = get_int_field (message,
3790                                                  FIELD_REPLY_SERIAL);
3791           message->client_serial = get_int_field (message,
3792                                                   FIELD_CLIENT_SERIAL);
3793           
3794           _dbus_verbose ("Loaded message %p\n", message);
3795         }
3796       else
3797         return TRUE;
3798     }
3799
3800   return TRUE;
3801 }
3802
3803 /**
3804  * Peeks at first loaded message, returns #NULL if no messages have
3805  * been queued.
3806  *
3807  * @param loader the loader.
3808  * @returns the next message, or #NULL if none.
3809  */
3810 DBusMessage*
3811 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
3812 {
3813   if (loader->messages)
3814     return loader->messages->data;
3815   else
3816     return NULL;
3817 }
3818
3819 /**
3820  * Pops a loaded message (passing ownership of the message
3821  * to the caller). Returns #NULL if no messages have been
3822  * queued.
3823  *
3824  * @param loader the loader.
3825  * @returns the next message, or #NULL if none.
3826  */
3827 DBusMessage*
3828 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
3829 {
3830   return _dbus_list_pop_first (&loader->messages);
3831 }
3832
3833 /**
3834  * Pops a loaded message inside a list link (passing ownership of the
3835  * message and link to the caller). Returns #NULL if no messages have
3836  * been loaded.
3837  *
3838  * @param loader the loader.
3839  * @returns the next message link, or #NULL if none.
3840  */
3841 DBusList*
3842 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
3843 {
3844   return _dbus_list_pop_first_link (&loader->messages);
3845 }
3846
3847 /**
3848  * Checks whether the loader is confused due to bad data.
3849  * If messages are received that are invalid, the
3850  * loader gets confused and gives up permanently.
3851  * This state is called "corrupted."
3852  *
3853  * @param loader the loader
3854  * @returns #TRUE if the loader is hosed.
3855  */
3856 dbus_bool_t
3857 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
3858 {
3859   return loader->corrupted;
3860 }
3861
3862 /**
3863  * Sets the maximum size message we allow.
3864  *
3865  * @param loader the loader
3866  * @param size the max message size in bytes
3867  */
3868 void
3869 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
3870                                            long                size)
3871 {
3872   if (size > MAX_SANE_MESSAGE_SIZE)
3873     {
3874       _dbus_verbose ("clamping requested max message size %ld to %d\n",
3875                      size, MAX_SANE_MESSAGE_SIZE);
3876       size = MAX_SANE_MESSAGE_SIZE;
3877     }
3878   loader->max_message_size = size;
3879 }
3880
3881 /**
3882  * Gets the maximum allowed message size in bytes.
3883  *
3884  * @param loader the loader
3885  * @returns max size in bytes
3886  */
3887 long
3888 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
3889 {
3890   return loader->max_message_size;
3891 }
3892
3893 /** @} */
3894 #ifdef DBUS_BUILD_TESTS
3895 #include "dbus-test.h"
3896 #include <stdio.h>
3897
3898 static void
3899 message_iter_test (DBusMessage *message)
3900 {
3901   DBusMessageIter iter, dict, array;
3902   char *str;
3903   
3904   dbus_message_iter_init (message, &iter);
3905
3906   /* String tests */
3907   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING)
3908     _dbus_assert_not_reached ("Argument type isn't string");
3909
3910   str = dbus_message_iter_get_string (&iter);
3911   if (strcmp (str, "Test string") != 0)
3912     _dbus_assert_not_reached ("Strings differ");
3913   dbus_free (str);
3914
3915   if (!dbus_message_iter_next (&iter))
3916     _dbus_assert_not_reached ("Reached end of arguments");
3917
3918   /* Signed integer tests */
3919   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_INT32)
3920     _dbus_assert_not_reached ("Argument type isn't int32");
3921
3922   if (dbus_message_iter_get_int32 (&iter) != -0x12345678)
3923     _dbus_assert_not_reached ("Signed integers differ");
3924
3925   if (!dbus_message_iter_next (&iter))
3926     _dbus_assert_not_reached ("Reached end of fields");
3927   
3928   /* Unsigned integer tests */
3929   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
3930     _dbus_assert_not_reached ("Argument type isn't int32");
3931
3932   if (dbus_message_iter_get_uint32 (&iter) != 0xedd1e)
3933     _dbus_assert_not_reached ("Unsigned integers differ");
3934
3935   if (!dbus_message_iter_next (&iter))
3936     _dbus_assert_not_reached ("Reached end of arguments");
3937
3938   /* Double tests */
3939   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DOUBLE)
3940     _dbus_assert_not_reached ("Argument type isn't double");
3941
3942   if (dbus_message_iter_get_double (&iter) != 3.14159)
3943     _dbus_assert_not_reached ("Doubles differ");
3944
3945   if (!dbus_message_iter_next (&iter))
3946     _dbus_assert_not_reached ("Reached end of arguments");
3947
3948   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY)
3949     _dbus_assert_not_reached ("Argument type not an array");
3950
3951   if (dbus_message_iter_get_array_type (&iter) != DBUS_TYPE_UINT32)
3952     _dbus_assert_not_reached ("Array type not uint32");
3953
3954   
3955   if (!dbus_message_iter_init_array_iterator (&iter, &array, NULL))
3956     _dbus_assert_not_reached ("Array init failed");
3957
3958   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_UINT32)
3959     _dbus_assert_not_reached ("Argument type isn't int32");
3960
3961   if (dbus_message_iter_get_uint32 (&array) != 0x12345678)
3962     _dbus_assert_not_reached ("Unsigned integers differ");
3963
3964   if (!dbus_message_iter_next (&array))
3965     _dbus_assert_not_reached ("Reached end of arguments");
3966
3967   if (dbus_message_iter_get_arg_type (&array) != DBUS_TYPE_UINT32)
3968     _dbus_assert_not_reached ("Argument type isn't int32");
3969
3970   if (dbus_message_iter_get_uint32 (&array) != 0x23456781)
3971     _dbus_assert_not_reached ("Unsigned integers differ");
3972
3973   if (dbus_message_iter_next (&array))
3974     _dbus_assert_not_reached ("Didn't reach end of arguments");
3975   
3976   if (!dbus_message_iter_next (&iter))
3977     _dbus_assert_not_reached ("Reached end of arguments");
3978   
3979   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
3980     _dbus_assert_not_reached ("not dict type");
3981      
3982   if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
3983     _dbus_assert_not_reached ("dict iter failed");
3984
3985   str = dbus_message_iter_get_dict_key (&dict);
3986   if (str == NULL || strcmp (str, "test") != 0)
3987     _dbus_assert_not_reached ("wrong dict key");
3988   dbus_free (str);
3989
3990   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
3991     _dbus_assert_not_reached ("wrong dict entry type");
3992
3993   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
3994     _dbus_assert_not_reached ("wrong dict entry value");
3995
3996   if (dbus_message_iter_next (&dict))
3997     _dbus_assert_not_reached ("Didn't reach end of dict");
3998   
3999   if (!dbus_message_iter_next (&iter))
4000     _dbus_assert_not_reached ("Reached end of arguments");
4001   
4002   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
4003     _dbus_assert_not_reached ("wrong type after dict");
4004   
4005   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
4006     _dbus_assert_not_reached ("wrong value after dict");
4007
4008   if (dbus_message_iter_next (&iter))
4009     _dbus_assert_not_reached ("Didn't reach end of arguments");
4010 }
4011
4012
4013 static dbus_bool_t
4014 check_message_handling_type (DBusMessageIter *iter,
4015                              int type)
4016 {
4017   DBusMessageIter child_iter;
4018   
4019   switch (type)
4020     {
4021     case DBUS_TYPE_NIL:
4022       break;
4023     case DBUS_TYPE_BYTE:
4024       dbus_message_iter_get_byte (iter);
4025       break;
4026     case DBUS_TYPE_BOOLEAN:
4027       dbus_message_iter_get_boolean (iter);
4028       break;
4029     case DBUS_TYPE_INT32:
4030       dbus_message_iter_get_int32 (iter);
4031       break;
4032     case DBUS_TYPE_UINT32:
4033       dbus_message_iter_get_uint32 (iter);
4034       break;
4035     case DBUS_TYPE_DOUBLE:
4036       dbus_message_iter_get_double (iter);
4037       break;
4038     case DBUS_TYPE_STRING:
4039       {
4040         char *str;
4041         str = dbus_message_iter_get_string (iter);
4042         if (str == NULL)
4043           {
4044             _dbus_warn ("NULL string in message\n");
4045             return FALSE;
4046           }
4047         dbus_free (str);
4048       }
4049       break;
4050     case DBUS_TYPE_NAMED:
4051       {
4052         char *name;
4053         unsigned char *data;
4054         int len;
4055         
4056         name = dbus_message_iter_get_named (iter, &data, &len);
4057         if (name == NULL)
4058           {
4059             _dbus_warn ("error reading name from named type\n");
4060             return FALSE;
4061           }
4062         dbus_free (data);
4063         dbus_free (name);
4064       }
4065       break;
4066     case DBUS_TYPE_ARRAY:
4067       {
4068         int array_type;
4069
4070         if (!dbus_message_iter_init_array_iterator (iter, &child_iter, &array_type))
4071           {
4072             _dbus_warn ("Failed to init array iterator\n");
4073             return FALSE;
4074           }
4075
4076         while (dbus_message_iter_has_next (&child_iter))
4077           {
4078             if (!check_message_handling_type (&child_iter, array_type))
4079               {
4080                 _dbus_warn ("error in array element\n");
4081                 return FALSE;
4082               }
4083             
4084             if (!dbus_message_iter_next (&child_iter))
4085               break;
4086           }
4087       }
4088       break;
4089     case DBUS_TYPE_DICT:
4090       {
4091         int entry_type;
4092         char *key;
4093         
4094         if (!dbus_message_iter_init_dict_iterator (iter, &child_iter))
4095           {
4096             _dbus_warn ("Failed to init dict iterator\n");
4097             return FALSE;
4098           }
4099
4100         while ((entry_type = dbus_message_iter_get_arg_type (&child_iter)) != DBUS_TYPE_INVALID)
4101           {
4102             key = dbus_message_iter_get_dict_key (&child_iter);
4103             if (key == NULL)
4104               {
4105                 _dbus_warn ("error reading dict key\n");
4106                 return FALSE;
4107               }
4108             dbus_free (key);
4109
4110             if (!check_message_handling_type (&child_iter, entry_type))
4111               {
4112                 _dbus_warn ("error in dict value\n");
4113                 return FALSE;
4114               }
4115             
4116             if (!dbus_message_iter_next (&child_iter))
4117               break;
4118           }
4119       }
4120       break;
4121       
4122     default:
4123       _dbus_warn ("unknown type %d\n", type);
4124       return FALSE;
4125       break;
4126     }
4127   return TRUE;
4128 }
4129   
4130   
4131 static dbus_bool_t
4132 check_message_handling (DBusMessage *message)
4133 {
4134   DBusMessageIter iter;
4135   int type;
4136   dbus_bool_t retval;
4137   dbus_int32_t client_serial;
4138   
4139   retval = FALSE;
4140   
4141   client_serial = dbus_message_get_serial (message);
4142
4143   /* can't use set_serial due to the assertions at the start of it */
4144   set_int_field (message, FIELD_CLIENT_SERIAL,
4145                  client_serial);
4146   
4147   if (client_serial != dbus_message_get_serial (message))
4148     {
4149       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
4150       goto failed;
4151     }
4152   
4153   /* If we implement message_set_arg (message, n, value)
4154    * then we would want to test it here
4155    */
4156
4157   dbus_message_iter_init (message, &iter);
4158   while ((type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
4159     {
4160
4161       if (!check_message_handling_type (&iter, type))
4162         goto failed;
4163
4164       if (!dbus_message_iter_next (&iter))
4165         break;
4166     }
4167   
4168   retval = TRUE;
4169   
4170  failed:
4171   return retval;
4172 }
4173
4174 static dbus_bool_t
4175 check_have_valid_message (DBusMessageLoader *loader)
4176 {
4177   DBusMessage *message;
4178   dbus_bool_t retval;
4179
4180   message = NULL;
4181   retval = FALSE;
4182
4183   if (!_dbus_message_loader_queue_messages (loader))
4184     _dbus_assert_not_reached ("no memory to queue messages");
4185   
4186   if (_dbus_message_loader_get_is_corrupted (loader))
4187     {
4188       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
4189       goto failed;
4190     }
4191   
4192   message = _dbus_message_loader_pop_message (loader);
4193   if (message == NULL)
4194     {
4195       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
4196       goto failed;
4197     }
4198   
4199   if (_dbus_string_get_length (&loader->data) > 0)
4200     {
4201       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
4202       goto failed;
4203     }
4204
4205   /* Verify that we're able to properly deal with the message.
4206    * For example, this would detect improper handling of messages
4207    * in nonstandard byte order.
4208    */
4209   if (!check_message_handling (message))
4210     goto failed;  
4211   
4212   retval = TRUE;
4213
4214  failed:
4215   if (message)
4216     dbus_message_unref (message);
4217
4218   return retval;
4219 }
4220
4221 static dbus_bool_t
4222 check_invalid_message (DBusMessageLoader *loader)
4223 {
4224   dbus_bool_t retval;
4225
4226   retval = FALSE;
4227
4228   if (!_dbus_message_loader_queue_messages (loader))
4229     _dbus_assert_not_reached ("no memory to queue messages");
4230   
4231   if (!_dbus_message_loader_get_is_corrupted (loader))
4232     {
4233       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
4234       goto failed;
4235     }
4236
4237   retval = TRUE;
4238
4239  failed:
4240   return retval;
4241 }
4242
4243 static dbus_bool_t
4244 check_incomplete_message (DBusMessageLoader *loader)
4245 {
4246   DBusMessage *message;
4247   dbus_bool_t retval;
4248
4249   message = NULL;
4250   retval = FALSE;
4251
4252   if (!_dbus_message_loader_queue_messages (loader))
4253     _dbus_assert_not_reached ("no memory to queue messages");
4254   
4255   if (_dbus_message_loader_get_is_corrupted (loader))
4256     {
4257       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
4258       goto failed;
4259     }
4260   
4261   message = _dbus_message_loader_pop_message (loader);
4262   if (message != NULL)
4263     {
4264       _dbus_warn ("loaded message that was expected to be incomplete\n");
4265       goto failed;
4266     }
4267
4268   retval = TRUE;
4269
4270  failed:
4271   if (message)
4272     dbus_message_unref (message);
4273   return retval;
4274 }
4275
4276 static dbus_bool_t
4277 check_loader_results (DBusMessageLoader      *loader,
4278                       DBusMessageValidity     validity)
4279 {
4280   if (!_dbus_message_loader_queue_messages (loader))
4281     _dbus_assert_not_reached ("no memory to queue messages");
4282   
4283   switch (validity)
4284     {
4285     case _DBUS_MESSAGE_VALID:
4286       return check_have_valid_message (loader);
4287     case _DBUS_MESSAGE_INVALID:
4288       return check_invalid_message (loader);
4289     case _DBUS_MESSAGE_INCOMPLETE:
4290       return check_incomplete_message (loader);
4291     case _DBUS_MESSAGE_UNKNOWN:
4292       return TRUE;
4293     }
4294
4295   _dbus_assert_not_reached ("bad DBusMessageValidity");
4296   return FALSE;
4297 }
4298
4299
4300 /**
4301  * Loads the message in the given message file.
4302  *
4303  * @param filename filename to load
4304  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
4305  * @param data string to load message into
4306  * @returns #TRUE if the message was loaded
4307  */
4308 dbus_bool_t
4309 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
4310                                             dbus_bool_t          is_raw,
4311                                             DBusString          *data)
4312 {
4313   dbus_bool_t retval;
4314
4315   retval = FALSE;  
4316
4317   if (is_raw)
4318     {
4319       DBusError error;
4320
4321       _dbus_verbose ("Loading raw %s\n", _dbus_string_get_const_data (filename));
4322       dbus_error_init (&error);
4323       if (!_dbus_file_get_contents (data, filename, &error))
4324         {
4325           _dbus_warn ("Could not load message file %s: %s\n",
4326                       _dbus_string_get_const_data (filename),
4327                       error.message);
4328           dbus_error_free (&error);
4329           goto failed;
4330         }
4331     }
4332   else
4333     {
4334       if (!_dbus_message_data_load (data, filename))
4335         {
4336           _dbus_warn ("Could not load message file %s\n",
4337                       _dbus_string_get_const_data (filename));
4338           goto failed;
4339         }
4340     }
4341
4342   retval = TRUE;
4343   
4344  failed:
4345
4346   return retval;
4347 }
4348
4349 /**
4350  * Tries loading the message in the given message file
4351  * and verifies that DBusMessageLoader can handle it.
4352  *
4353  * @param filename filename to load
4354  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
4355  * @param expected_validity what the message has to be like to return #TRUE
4356  * @returns #TRUE if the message has the expected validity
4357  */
4358 dbus_bool_t
4359 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
4360                                            dbus_bool_t          is_raw,
4361                                            DBusMessageValidity  expected_validity)
4362 {
4363   DBusString data;
4364   dbus_bool_t retval;
4365
4366   retval = FALSE;
4367   
4368   if (!_dbus_string_init (&data))
4369     _dbus_assert_not_reached ("could not allocate string\n");
4370
4371   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
4372                                                    &data))
4373     goto failed;
4374
4375   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
4376
4377  failed:
4378
4379   if (!retval)
4380     {
4381       if (_dbus_string_get_length (&data) > 0)
4382         _dbus_verbose_bytes_of_string (&data, 0,
4383                                        _dbus_string_get_length (&data));
4384       
4385       _dbus_warn ("Failed message loader test on %s\n",
4386                   _dbus_string_get_const_data (filename));
4387     }
4388   
4389   _dbus_string_free (&data);
4390
4391   return retval;
4392 }
4393
4394 /**
4395  * Tries loading the given message data.
4396  *
4397  *
4398  * @param data the message data
4399  * @param expected_validity what the message has to be like to return #TRUE
4400  * @returns #TRUE if the message has the expected validity
4401  */
4402 dbus_bool_t
4403 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
4404                                            DBusMessageValidity  expected_validity)
4405 {
4406   DBusMessageLoader *loader;
4407   dbus_bool_t retval;
4408   int len;
4409   int i;
4410
4411   loader = NULL;
4412   retval = FALSE;
4413
4414   /* Write the data one byte at a time */
4415   
4416   loader = _dbus_message_loader_new ();
4417
4418   len = _dbus_string_get_length (data);
4419   for (i = 0; i < len; i++)
4420     {
4421       DBusString *buffer;
4422
4423       _dbus_message_loader_get_buffer (loader, &buffer);
4424       _dbus_string_append_byte (buffer,
4425                                 _dbus_string_get_byte (data, i));
4426       _dbus_message_loader_return_buffer (loader, buffer, 1);
4427     }
4428   
4429   if (!check_loader_results (loader, expected_validity))
4430     goto failed;
4431
4432   _dbus_message_loader_unref (loader);
4433   loader = NULL;
4434
4435   /* Write the data all at once */
4436   
4437   loader = _dbus_message_loader_new ();
4438
4439   {
4440     DBusString *buffer;
4441     
4442     _dbus_message_loader_get_buffer (loader, &buffer);
4443     _dbus_string_copy (data, 0, buffer,
4444                        _dbus_string_get_length (buffer));
4445     _dbus_message_loader_return_buffer (loader, buffer, 1);
4446   }
4447   
4448   if (!check_loader_results (loader, expected_validity))
4449     goto failed;
4450
4451   _dbus_message_loader_unref (loader);
4452   loader = NULL;  
4453
4454   /* Write the data 2 bytes at a time */
4455   
4456   loader = _dbus_message_loader_new ();
4457
4458   len = _dbus_string_get_length (data);
4459   for (i = 0; i < len; i += 2)
4460     {
4461       DBusString *buffer;
4462
4463       _dbus_message_loader_get_buffer (loader, &buffer);
4464       _dbus_string_append_byte (buffer,
4465                                 _dbus_string_get_byte (data, i));
4466       if ((i+1) < len)
4467         _dbus_string_append_byte (buffer,
4468                                   _dbus_string_get_byte (data, i+1));
4469       _dbus_message_loader_return_buffer (loader, buffer, 1);
4470     }
4471   
4472   if (!check_loader_results (loader, expected_validity))
4473     goto failed;
4474
4475   _dbus_message_loader_unref (loader);
4476   loader = NULL;
4477   
4478   retval = TRUE;
4479   
4480  failed:
4481   
4482   if (loader)
4483     _dbus_message_loader_unref (loader);
4484   
4485   return retval;
4486 }
4487
4488 static dbus_bool_t
4489 process_test_subdir (const DBusString          *test_base_dir,
4490                      const char                *subdir,
4491                      DBusMessageValidity        validity,
4492                      DBusForeachMessageFileFunc function,
4493                      void                      *user_data)
4494 {
4495   DBusString test_directory;
4496   DBusString filename;
4497   DBusDirIter *dir;
4498   dbus_bool_t retval;
4499   DBusError error;
4500
4501   retval = FALSE;
4502   dir = NULL;
4503   
4504   if (!_dbus_string_init (&test_directory))
4505     _dbus_assert_not_reached ("didn't allocate test_directory\n");
4506
4507   _dbus_string_init_const (&filename, subdir);
4508   
4509   if (!_dbus_string_copy (test_base_dir, 0,
4510                           &test_directory, 0))
4511     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
4512   
4513   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
4514     _dbus_assert_not_reached ("couldn't allocate full path");
4515
4516   _dbus_string_free (&filename);
4517   if (!_dbus_string_init (&filename))
4518     _dbus_assert_not_reached ("didn't allocate filename string\n");
4519
4520   dbus_error_init (&error);
4521   dir = _dbus_directory_open (&test_directory, &error);
4522   if (dir == NULL)
4523     {
4524       _dbus_warn ("Could not open %s: %s\n",
4525                   _dbus_string_get_const_data (&test_directory),
4526                   error.message);
4527       dbus_error_free (&error);
4528       goto failed;
4529     }
4530
4531   printf ("Testing:\n");
4532   
4533  next:
4534   while (_dbus_directory_get_next_file (dir, &filename, &error))
4535     {
4536       DBusString full_path;
4537       dbus_bool_t is_raw;
4538       
4539       if (!_dbus_string_init (&full_path))
4540         _dbus_assert_not_reached ("couldn't init string");
4541
4542       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
4543         _dbus_assert_not_reached ("couldn't copy dir to full_path");
4544
4545       if (!_dbus_concat_dir_and_file (&full_path, &filename))
4546         _dbus_assert_not_reached ("couldn't concat file to dir");
4547
4548       if (_dbus_string_ends_with_c_str (&filename, ".message"))
4549         is_raw = FALSE;
4550       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
4551         is_raw = TRUE;
4552       else
4553         {
4554           _dbus_verbose ("Skipping non-.message file %s\n",
4555                          _dbus_string_get_const_data (&filename));
4556           _dbus_string_free (&full_path);
4557           goto next;
4558         }
4559
4560       printf ("    %s\n",
4561               _dbus_string_get_const_data (&filename));
4562       
4563       _dbus_verbose (" expecting %s\n",
4564                      validity == _DBUS_MESSAGE_VALID ? "valid" :
4565                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
4566                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")));
4567       
4568       if (! (*function) (&full_path, is_raw, validity, user_data))
4569         {
4570           _dbus_string_free (&full_path);
4571           goto failed;
4572         }
4573       else
4574         _dbus_string_free (&full_path);
4575     }
4576
4577   if (dbus_error_is_set (&error))
4578     {
4579       _dbus_warn ("Could not get next file in %s: %s\n",
4580                   _dbus_string_get_const_data (&test_directory),
4581                   error.message);
4582       dbus_error_free (&error);
4583       goto failed;
4584     }
4585     
4586   retval = TRUE;
4587   
4588  failed:
4589
4590   if (dir)
4591     _dbus_directory_close (dir);
4592   _dbus_string_free (&test_directory);
4593   _dbus_string_free (&filename);
4594
4595   return retval;
4596 }
4597                      
4598 /**
4599  * Runs the given function on every message file in the test suite.
4600  * The function should return #FALSE on test failure or fatal error.
4601  *
4602  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
4603  * @param func the function to run
4604  * @param user_data data for function
4605  * @returns #FALSE if there's a failure
4606  */
4607 dbus_bool_t
4608 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
4609                                                DBusForeachMessageFileFunc func,
4610                                                void                      *user_data)
4611 {
4612   DBusString test_directory;
4613   dbus_bool_t retval;
4614
4615   retval = FALSE;
4616   
4617   _dbus_string_init_const (&test_directory, test_data_dir);
4618
4619   if (!process_test_subdir (&test_directory, "valid-messages",
4620                             _DBUS_MESSAGE_VALID, func, user_data))
4621     goto failed;
4622
4623   if (!process_test_subdir (&test_directory, "invalid-messages",
4624                             _DBUS_MESSAGE_INVALID, func, user_data))
4625     goto failed;
4626   
4627   if (!process_test_subdir (&test_directory, "incomplete-messages",
4628                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
4629     goto failed;
4630
4631   retval = TRUE;
4632   
4633  failed:
4634
4635   _dbus_string_free (&test_directory);
4636   
4637   return retval;
4638 }
4639
4640 static void
4641 verify_test_message (DBusMessage *message)
4642 {
4643   dbus_int32_t our_int;
4644   char *our_str;
4645   double our_double;
4646   dbus_bool_t our_bool;
4647   dbus_int32_t *our_int_array;
4648   int our_int_array_len;
4649   DBusMessageIter iter, dict;
4650   DBusError error;
4651
4652   dbus_message_iter_init (message, &iter);
4653
4654   dbus_error_init (&error);
4655   if (!dbus_message_iter_get_args (&iter, &error,
4656                                    DBUS_TYPE_INT32, &our_int,
4657                                    DBUS_TYPE_STRING, &our_str,
4658                                    DBUS_TYPE_DOUBLE, &our_double,
4659                                    DBUS_TYPE_BOOLEAN, &our_bool,
4660                                    DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, &our_int_array, &our_int_array_len,
4661                                    0))
4662     {
4663       _dbus_verbose ("error: %s - %s\n", error.name, (error.message != NULL)?error.message: "no message");
4664       _dbus_assert_not_reached ("Could not get arguments");
4665     }
4666
4667   if (our_int != -0x12345678)
4668     _dbus_assert_not_reached ("integers differ!");
4669
4670   if (our_double != 3.14159)
4671     _dbus_assert_not_reached ("doubles differ!");
4672
4673   if (strcmp (our_str, "Test string") != 0)
4674     _dbus_assert_not_reached ("strings differ!");
4675   dbus_free (our_str);
4676
4677   if (!our_bool)
4678     _dbus_assert_not_reached ("booleans differ");
4679
4680   if (our_int_array_len != 4 ||
4681       our_int_array[0] != 0x12345678 ||
4682       our_int_array[1] != 0x23456781 ||
4683       our_int_array[2] != 0x34567812 ||
4684       our_int_array[3] != 0x45678123)
4685     _dbus_assert_not_reached ("array differ");
4686   dbus_free (our_int_array);
4687
4688   if (!dbus_message_iter_next (&iter))
4689     _dbus_assert_not_reached ("Reached end of arguments");
4690
4691   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_DICT)
4692     _dbus_assert_not_reached ("not dict type");
4693      
4694   if (!dbus_message_iter_init_dict_iterator (&iter, &dict))
4695     _dbus_assert_not_reached ("dict iter failed");
4696
4697   our_str = dbus_message_iter_get_dict_key (&dict);
4698   if (our_str == NULL || strcmp (our_str, "test") != 0)
4699     _dbus_assert_not_reached ("wrong dict key");
4700   dbus_free (our_str);
4701
4702   if (dbus_message_iter_get_arg_type (&dict) != DBUS_TYPE_UINT32)
4703     {
4704       _dbus_verbose ("dict entry type: %d\n", dbus_message_iter_get_arg_type (&dict));
4705       _dbus_assert_not_reached ("wrong dict entry type");
4706     }
4707
4708   if (dbus_message_iter_get_uint32 (&dict) != 0xDEADBEEF)
4709     _dbus_assert_not_reached ("wrong dict entry value");
4710
4711   if (dbus_message_iter_next (&dict))
4712     _dbus_assert_not_reached ("Didn't reach end of dict");
4713   
4714   if (!dbus_message_iter_next (&iter))
4715     _dbus_assert_not_reached ("Reached end of arguments");
4716   
4717   if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_UINT32)
4718     _dbus_assert_not_reached ("wrong type after dict");
4719   
4720   if (dbus_message_iter_get_uint32 (&iter) != 0xCAFEBABE)
4721     _dbus_assert_not_reached ("wrong value after dict");
4722
4723   if (dbus_message_iter_next (&iter))
4724     _dbus_assert_not_reached ("Didn't reach end of arguments");
4725 }
4726
4727 /**
4728  * @ingroup DBusMessageInternals
4729  * Unit test for DBusMessage.
4730  *
4731  * @returns #TRUE on success.
4732  */
4733 dbus_bool_t
4734 _dbus_message_test (const char *test_data_dir)
4735 {
4736   DBusMessage *message;
4737   DBusMessageLoader *loader;
4738   DBusMessageIter iter, child_iter;
4739   int i;
4740   const char *data;
4741   DBusMessage *copy;
4742   const char *name1;
4743   const char *name2;
4744   const dbus_uint32_t our_int32_array[] = { 0x12345678, 0x23456781, 0x34567812, 0x45678123 };
4745
4746   _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
4747
4748   /* Test the vararg functions */
4749   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
4750   _dbus_message_set_serial (message, 1);
4751   dbus_message_append_args (message,
4752                             DBUS_TYPE_INT32, -0x12345678,
4753                             DBUS_TYPE_STRING, "Test string",
4754                             DBUS_TYPE_DOUBLE, 3.14159,
4755                             DBUS_TYPE_BOOLEAN, TRUE,
4756                             DBUS_TYPE_ARRAY, DBUS_TYPE_UINT32, our_int32_array, 4,
4757                             0);
4758   
4759   dbus_message_append_iter_init (message, &iter);
4760   dbus_message_iter_append_dict (&iter, &child_iter);
4761   dbus_message_iter_append_dict_key (&child_iter, "test");
4762   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
4763   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
4764   
4765   _dbus_verbose_bytes_of_string (&message->header, 0,
4766                                  _dbus_string_get_length (&message->header));
4767   _dbus_verbose_bytes_of_string (&message->body, 0,
4768                                  _dbus_string_get_length (&message->body));
4769
4770   verify_test_message (message);
4771
4772   copy = dbus_message_copy (message);
4773   
4774   _dbus_assert (message->client_serial == copy->client_serial);
4775   _dbus_assert (message->reply_serial == copy->reply_serial);
4776   _dbus_assert (message->header_padding == copy->header_padding);
4777   
4778   _dbus_assert (_dbus_string_get_length (&message->header) ==
4779                 _dbus_string_get_length (&copy->header));
4780
4781   _dbus_assert (_dbus_string_get_length (&message->body) ==
4782                 _dbus_string_get_length (&copy->body));
4783
4784   verify_test_message (copy);
4785
4786   name1 = dbus_message_get_name (message);
4787   name2 = dbus_message_get_name (copy);
4788
4789   _dbus_assert (strcmp (name1, name2) == 0);
4790   
4791   dbus_message_unref (message);
4792   dbus_message_unref (copy);
4793   
4794   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
4795   _dbus_message_set_serial (message, 1);
4796   dbus_message_set_reply_serial (message, 0x12345678);
4797
4798   dbus_message_append_iter_init (message, &iter);
4799   dbus_message_iter_append_string (&iter, "Test string");
4800   dbus_message_iter_append_int32 (&iter, -0x12345678);
4801   dbus_message_iter_append_uint32 (&iter, 0xedd1e);
4802   dbus_message_iter_append_double (&iter, 3.14159);
4803
4804   dbus_message_iter_append_array (&iter, &child_iter, DBUS_TYPE_UINT32);
4805   dbus_message_iter_append_uint32 (&child_iter, 0x12345678);
4806   dbus_message_iter_append_uint32 (&child_iter, 0x23456781);
4807
4808   dbus_message_iter_append_dict (&iter, &child_iter);
4809   dbus_message_iter_append_dict_key (&child_iter, "test");
4810   dbus_message_iter_append_uint32 (&child_iter, 0xDEADBEEF);
4811   dbus_message_iter_append_uint32 (&iter, 0xCAFEBABE);
4812   
4813   message_iter_test (message);
4814
4815   /* Message loader test */
4816   _dbus_message_lock (message);
4817   loader = _dbus_message_loader_new ();
4818
4819   /* Write the header data one byte at a time */
4820   data = _dbus_string_get_const_data (&message->header);
4821   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
4822     {
4823       DBusString *buffer;
4824
4825       _dbus_message_loader_get_buffer (loader, &buffer);
4826       _dbus_string_append_byte (buffer, data[i]);
4827       _dbus_message_loader_return_buffer (loader, buffer, 1);
4828     }
4829
4830   /* Write the body data one byte at a time */
4831   data = _dbus_string_get_const_data (&message->body);
4832   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
4833     {
4834       DBusString *buffer;
4835
4836       _dbus_message_loader_get_buffer (loader, &buffer);
4837       _dbus_string_append_byte (buffer, data[i]);
4838       _dbus_message_loader_return_buffer (loader, buffer, 1);
4839     }
4840
4841   dbus_message_unref (message);
4842
4843   /* Now pop back the message */
4844   if (!_dbus_message_loader_queue_messages (loader))
4845     _dbus_assert_not_reached ("no memory to queue messages");
4846   
4847   if (_dbus_message_loader_get_is_corrupted (loader))
4848     _dbus_assert_not_reached ("message loader corrupted");
4849   
4850   message = _dbus_message_loader_pop_message (loader);
4851   if (!message)
4852     _dbus_assert_not_reached ("received a NULL message");
4853
4854   if (dbus_message_get_reply_serial (message) != 0x12345678)
4855     _dbus_assert_not_reached ("reply serial fields differ");
4856   
4857   message_iter_test (message);
4858   
4859   dbus_message_unref (message);
4860   _dbus_message_loader_unref (loader);
4861
4862   /* Now load every message in test_data_dir if we have one */
4863   if (test_data_dir == NULL)
4864     return TRUE;
4865
4866   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
4867                                                         (DBusForeachMessageFileFunc)
4868                                                         dbus_internal_do_not_use_try_message_file,
4869                                                         NULL);
4870 }
4871
4872 #endif /* DBUS_BUILD_TESTS */