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