2003-04-03 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / dbus / dbus-message.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-message.c  DBusMessage object
3  *
4  * Copyright (C) 2002, 2003  Red Hat Inc.
5  * Copyright (C) 2002, 2003  CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 1.2
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "dbus-internals.h"
26 #include "dbus-marshal.h"
27 #include "dbus-message.h"
28 #include "dbus-message-internal.h"
29 #include "dbus-memory.h"
30 #include "dbus-list.h"
31 #include "dbus-message-builder.h"
32 #include <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   unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
108 };
109
110 /**
111  * @brief Internals of DBusMessageIter
112  * 
113  * Object representing a position in a message. All fields are internal.
114  */
115 struct DBusMessageIter
116 {
117   int refcount; /**< Reference count */
118
119   int pos; /**< Current position in the string */
120   
121   DBusMessage *message; /**< Message used */
122 };
123
124 /**
125  * Gets the data to be sent over the network for this message.
126  * The header and then the body should be written out.
127  * This function is guaranteed to always return the same
128  * data once a message is locked (with _dbus_message_lock()).
129  *
130  * @param message the message.
131  * @param header return location for message header data.
132  * @param body return location for message body data.
133  */
134 void
135 _dbus_message_get_network_data (DBusMessage          *message,
136                                 const DBusString    **header,
137                                 const DBusString    **body)
138 {
139   _dbus_assert (message->locked);
140   
141   *header = &message->header;
142   *body = &message->body;
143 }
144
145 static void
146 clear_header_padding (DBusMessage *message)
147 {
148   _dbus_string_shorten (&message->header,
149                         message->header_padding);
150   message->header_padding = 0;
151 }              
152
153 static dbus_bool_t
154 append_header_padding (DBusMessage *message)
155 {
156   int old_len;
157   old_len = _dbus_string_get_length (&message->header);
158   if (!_dbus_string_align_length (&message->header, 8))
159     return FALSE;
160
161   message->header_padding = _dbus_string_get_length (&message->header) - old_len;
162
163   return TRUE;
164 }
165
166 static void
167 adjust_field_offsets (DBusMessage *message,
168                       int          offsets_after,
169                       int          delta)
170 {
171   int i;
172
173   if (delta == 0)
174     return;
175   
176   i = 0;
177   while (i < FIELD_LAST)
178     {
179       if (message->header_fields[i].offset > offsets_after)
180         message->header_fields[i].offset += delta;
181
182       ++i;
183     }
184 }
185
186 static const char*
187 get_string_field (DBusMessage *message,
188                   int          field,
189                   int         *len)
190 {
191   int offset;
192   const char *data;
193
194   offset = message->header_fields[field].offset;
195
196   _dbus_assert (field < FIELD_LAST);
197   
198   if (offset < 0)
199     return NULL;
200
201   /* offset points to string length, string data follows it */
202   /* FIXME _dbus_demarshal_const_string() that returned
203    * a reference to the string plus its len might be nice.
204    */
205   
206   if (len)
207     *len = _dbus_demarshal_uint32 (&message->header,
208                                    message->byte_order,
209                                    offset,
210                                    NULL);
211
212   data = _dbus_string_get_const_data (&message->header);
213   
214   return data + (offset + 4); 
215 }
216
217 static dbus_int32_t
218 get_int_field (DBusMessage *message,
219                int          field)
220 {
221   int offset;
222
223   _dbus_assert (field < FIELD_LAST);
224   
225   offset = message->header_fields[field].offset;
226   
227   if (offset < 0)
228     return -1; /* useless if -1 is a valid value of course */
229   
230   return _dbus_demarshal_int32 (&message->header,
231                                 message->byte_order,
232                                 offset,
233                                 NULL);
234 }
235
236 static dbus_bool_t
237 append_int_field (DBusMessage *message,
238                   int          field,
239                   const char  *name,
240                   int          value)
241 {
242   int orig_len;
243
244   _dbus_assert (!message->locked);
245
246   clear_header_padding (message);
247   
248   orig_len = _dbus_string_get_length (&message->header);
249   
250   if (!_dbus_string_align_length (&message->header, 4))
251     goto failed;  
252   
253   if (!_dbus_string_append_len (&message->header, name, 4))
254     goto failed;
255
256   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_INT32))
257     goto failed;
258
259   if (!_dbus_string_align_length (&message->header, 4))
260     goto failed;
261   
262   message->header_fields[FIELD_REPLY_SERIAL].offset =
263     _dbus_string_get_length (&message->header);
264   
265   if (!_dbus_marshal_int32 (&message->header, message->byte_order,
266                             value))
267     goto failed;
268
269   if (!append_header_padding (message))
270     goto failed;
271   
272   return TRUE;
273   
274  failed:
275   message->header_fields[field].offset = -1;
276   _dbus_string_set_length (&message->header, orig_len);
277
278   /* this must succeed because it was allocated on function entry and
279    * DBusString doesn't ever realloc smaller
280    */
281   if (!append_header_padding (message))
282     _dbus_assert_not_reached ("failed to reappend header padding");
283   return FALSE;
284 }
285
286 static dbus_bool_t
287 append_string_field (DBusMessage *message,
288                      int          field,
289                      const char  *name,
290                      const char  *value)
291 {
292   int orig_len;
293
294   _dbus_assert (!message->locked);
295
296   clear_header_padding (message);
297   
298   orig_len = _dbus_string_get_length (&message->header);
299
300   if (!_dbus_string_align_length (&message->header, 4))
301     goto failed;
302   
303   if (!_dbus_string_append_len (&message->header, name, 4))
304     goto failed;
305   
306   if (!_dbus_string_append_byte (&message->header, DBUS_TYPE_STRING))
307     goto failed;
308
309   if (!_dbus_string_align_length (&message->header, 4))
310     goto failed;
311   
312   message->header_fields[field].offset =
313     _dbus_string_get_length (&message->header);
314   
315   if (!_dbus_marshal_string (&message->header, message->byte_order,
316                              value))
317     goto failed;
318
319   if (!append_header_padding (message))
320     goto failed;
321   
322   return TRUE;
323   
324  failed:
325   message->header_fields[field].offset = -1;
326   _dbus_string_set_length (&message->header, orig_len);
327
328   /* this must succeed because it was allocated on function entry and
329    * DBusString doesn't ever realloc smaller
330    */
331   if (!append_header_padding (message))
332     _dbus_assert_not_reached ("failed to reappend header padding");
333   
334   return FALSE;
335 }
336
337 static void
338 delete_int_field (DBusMessage *message,
339                   int          field)
340 {
341   int offset = message->header_fields[field].offset;
342
343   _dbus_assert (!message->locked);
344   _dbus_assert (field_is_named[field]);
345   
346   if (offset < 0)
347     return;  
348
349   clear_header_padding (message);
350   
351   /* The field typecode and name take up 8 bytes */
352   _dbus_string_delete (&message->header,
353                        offset - 8,
354                        12);
355
356   message->header_fields[field].offset = -1;
357   
358   adjust_field_offsets (message,
359                         offset - 8,
360                         - 12);
361
362   append_header_padding (message);
363 }
364
365 static void
366 delete_string_field (DBusMessage *message,
367                      int          field)
368 {
369   int offset = message->header_fields[field].offset;
370   int len;
371   int delete_len;
372   
373   _dbus_assert (!message->locked);
374   _dbus_assert (field_is_named[field]);
375   
376   if (offset < 0)
377     return;
378
379   clear_header_padding (message);
380   
381   get_string_field (message, field, &len);
382   
383   /* The field typecode and name take up 8 bytes, and the nul
384    * termination is 1 bytes, string length integer is 4 bytes
385    */
386   delete_len = 8 + 4 + 1 + len;
387   
388   _dbus_string_delete (&message->header,
389                        offset - 8,
390                        delete_len);
391
392   message->header_fields[field].offset = -1;
393   
394   adjust_field_offsets (message,
395                         offset - 8,
396                         - delete_len);
397
398   append_header_padding (message);
399 }
400
401 static dbus_bool_t
402 set_int_field (DBusMessage *message,
403                int          field,
404                int          value)
405 {
406   int offset = message->header_fields[field].offset;
407
408   _dbus_assert (!message->locked);
409   
410   if (offset < 0)
411     {
412       /* need to append the field */
413
414       switch (field)
415         {
416         case FIELD_REPLY_SERIAL:
417           return append_int_field (message, field,
418                                    DBUS_HEADER_FIELD_REPLY,
419                                    value);
420         default:
421           _dbus_assert_not_reached ("appending an int field we don't support appending");
422           return FALSE;
423         }
424     }
425   else
426     {
427       _dbus_marshal_set_int32 (&message->header,
428                                message->byte_order,
429                                offset, value);
430
431       return TRUE;
432     }
433 }
434
435 static dbus_bool_t
436 set_uint_field (DBusMessage  *message,
437                 int           field,
438                 dbus_uint32_t value)
439 {
440   int offset = message->header_fields[field].offset;
441
442   _dbus_assert (!message->locked);
443   
444   if (offset < 0)
445     {
446       /* need to append the field */
447
448       switch (field)
449         {
450         default:
451           _dbus_assert_not_reached ("appending a uint field we don't support appending");
452           return FALSE;
453         }
454     }
455   else
456     {
457       _dbus_marshal_set_uint32 (&message->header,
458                                 message->byte_order,
459                                 offset, value);
460
461       return TRUE;
462     }
463 }
464
465 static dbus_bool_t
466 set_string_field (DBusMessage *message,
467                   int          field,
468                   const char  *value)
469 {
470   int offset = message->header_fields[field].offset;
471
472   _dbus_assert (!message->locked);
473   _dbus_assert (value != NULL);
474   
475   if (offset < 0)
476     {      
477       /* need to append the field */
478
479       switch (field)
480         {
481         case FIELD_SENDER:
482           return append_string_field (message, field,
483                                       DBUS_HEADER_FIELD_SENDER,
484                                       value);
485         default:
486           _dbus_assert_not_reached ("appending a string field we don't support appending");
487           return FALSE;
488         }
489     }
490   else
491     {
492       DBusString v;
493       int old_len;
494       int new_len;
495       int len;
496       
497       clear_header_padding (message);
498       
499       old_len = _dbus_string_get_length (&message->header);
500
501       len = strlen (value);
502       
503       _dbus_string_init_const_len (&v, value,
504                                    len + 1); /* include nul */
505       if (!_dbus_marshal_set_string (&message->header,
506                                      message->byte_order,
507                                      offset, &v,
508                                      len))
509         goto failed;
510       
511       new_len = _dbus_string_get_length (&message->header);
512
513       adjust_field_offsets (message,
514                             offset,
515                             new_len - old_len);
516
517       if (!append_header_padding (message))
518         goto failed;
519       
520       return TRUE;
521
522     failed:
523       /* this must succeed because it was allocated on function entry and
524        * DBusString doesn't ever realloc smaller
525        */
526       if (!append_header_padding (message))
527         _dbus_assert_not_reached ("failed to reappend header padding");
528
529       return FALSE;
530     }
531 }
532
533 /**
534  * Sets the serial number of a message. 
535  * This can only be done once on a message.
536  * 
537  * @param message the message
538  * @param serial the serial
539  */
540 void
541 _dbus_message_set_serial (DBusMessage  *message,
542                           dbus_int32_t  serial)
543 {
544   _dbus_assert (!message->locked);
545   _dbus_assert (dbus_message_get_serial (message) < 0);
546   
547   set_int_field (message, FIELD_CLIENT_SERIAL,
548                  serial);
549   message->client_serial = serial;
550 }
551
552 /**
553  * Sets the reply serial of a message (the client serial
554  * of the message this is a reply to).
555  *
556  * @param message the message
557  * @param reply_serial the client serial
558  * @returns #FALSE if not enough memory
559  */
560 dbus_bool_t
561 dbus_message_set_reply_serial (DBusMessage  *message,
562                                 dbus_int32_t  reply_serial)
563 {
564   _dbus_assert (!message->locked);
565
566   if (set_int_field (message, FIELD_REPLY_SERIAL,
567                      reply_serial))
568     {
569       message->reply_serial = reply_serial;
570       return TRUE;
571     }
572   else
573     return FALSE;
574 }
575
576 /**
577  * Returns the serial of a message or -1 if none has been specified.
578  * The message's serial number is provided by the application sending
579  * the message and is used to identify replies to this message.
580  *
581  * @param message the message
582  * @returns the client serial
583  */
584 dbus_int32_t
585 dbus_message_get_serial (DBusMessage *message)
586 {
587   return message->client_serial;
588 }
589
590 /**
591  * Returns the serial that the message is
592  * a reply to or -1 if none.
593  *
594  * @param message the message
595  * @returns the reply serial
596  */
597 dbus_int32_t
598 dbus_message_get_reply_serial  (DBusMessage *message)
599 {
600   return message->reply_serial;
601 }
602
603 /**
604  * Adds a counter to be incremented immediately with the
605  * size of this message, and decremented by the size
606  * of this message when this message if finalized.
607  *
608  * @param message the message
609  * @param counter the counter
610  */
611 void
612 _dbus_message_add_size_counter (DBusMessage *message,
613                                 DBusCounter *counter)
614 {
615   _dbus_assert (message->size_counter == NULL); /* If this fails we may need to keep a list of
616                                                  * counters instead of just one
617                                                  */
618
619   message->size_counter = counter;
620   _dbus_counter_ref (message->size_counter);
621
622   /* When we can change message size, we may want to
623    * update this each time we do so, or we may want to
624    * just KISS like this.
625    */
626   message->size_counter_delta =
627     _dbus_string_get_length (&message->header) +
628     _dbus_string_get_length (&message->body);
629
630 #if 0
631   _dbus_verbose ("message has size %ld\n",
632                  message->size_counter_delta);
633 #endif
634   
635   _dbus_counter_adjust (message->size_counter, message->size_counter_delta);
636 }
637
638 static dbus_bool_t
639 dbus_message_create_header (DBusMessage *message,
640                             const char  *service,
641                             const char  *name)
642 {
643   unsigned int flags;
644   
645   if (!_dbus_string_append_byte (&message->header, message->byte_order))
646     return FALSE;
647
648   flags = 0;
649   if (!_dbus_string_append_byte (&message->header, flags))
650     return FALSE;
651
652   if (!_dbus_string_append_byte (&message->header, DBUS_MAJOR_PROTOCOL_VERSION))
653     return FALSE;
654
655   if (!_dbus_string_append_byte (&message->header, 0))
656     return FALSE;
657
658   message->header_fields[FIELD_HEADER_LENGTH].offset = 4;
659   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
660     return FALSE;
661
662   message->header_fields[FIELD_BODY_LENGTH].offset = 8;
663   if (!_dbus_marshal_uint32 (&message->header, message->byte_order, 0))
664     return FALSE;
665
666   message->header_fields[FIELD_CLIENT_SERIAL].offset = 12;
667   if (!_dbus_marshal_int32 (&message->header, message->byte_order, -1))
668     return FALSE;
669   
670   /* Marshal message service */
671   if (service != NULL)
672     {
673       if (!append_string_field (message,
674                                 FIELD_SERVICE,
675                                 DBUS_HEADER_FIELD_SERVICE,
676                                 service))
677         return FALSE;
678     }
679
680   _dbus_assert (name != NULL);
681   if (!append_string_field (message,
682                             FIELD_NAME,
683                             DBUS_HEADER_FIELD_NAME,
684                             name))
685     return FALSE;
686   
687   return TRUE;
688 }
689
690 /**
691  * Locks a message. Allows checking that applications don't keep a
692  * reference to a message in the outgoing queue and change it
693  * underneath us. Messages are locked when they enter the outgoing
694  * queue (dbus_connection_send_message()), and the library complains
695  * if the message is modified while locked.
696  *
697  * @param message the message to lock.
698  */
699 void
700 _dbus_message_lock (DBusMessage  *message)
701 {
702   if (!message->locked)
703     {
704       /* Fill in our lengths */
705       set_uint_field (message,
706                       FIELD_HEADER_LENGTH,
707                       _dbus_string_get_length (&message->header));
708
709       set_uint_field (message,
710                       FIELD_BODY_LENGTH,
711                       _dbus_string_get_length (&message->body));
712
713       message->locked = TRUE;
714     }
715 }
716
717 /** @} */
718
719 /**
720  * @defgroup DBusMessage DBusMessage
721  * @ingroup  DBus
722  * @brief Message to be sent or received over a DBusConnection.
723  *
724  * A DBusMessage is the most basic unit of communication over a
725  * DBusConnection. A DBusConnection represents a stream of messages
726  * received from a remote application, and a stream of messages
727  * sent to a remote application.
728  *
729  * @{
730  */
731
732 /**
733  * @typedef DBusMessage
734  *
735  * Opaque data type representing a message received from or to be
736  * sent to another application.
737  */
738
739 static DBusMessage*
740 dbus_message_new_empty_header (void)
741 {
742   DBusMessage *message;
743   int i;
744   
745   message = dbus_new0 (DBusMessage, 1);
746   if (message == NULL)
747     return NULL;
748   
749   message->refcount = 1;
750   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
751   message->client_serial = -1;
752   message->reply_serial = -1;
753   
754   i = 0;
755   while (i < FIELD_LAST)
756     {
757       message->header_fields[i].offset = -1;
758       ++i;
759     }
760   
761   if (!_dbus_string_init (&message->header))
762     {
763       dbus_free (message);
764       return NULL;
765     }
766   
767   if (!_dbus_string_init (&message->body))
768     {
769       _dbus_string_free (&message->header);
770       dbus_free (message);
771       return NULL;
772     }
773   
774   return message;
775 }
776
777
778 /**
779  * Constructs a new message. Returns #NULL if memory can't be
780  * allocated for the message. The service may be #NULL in which case
781  * no service is set; this is appropriate when using D-BUS in a
782  * peer-to-peer context (no message bus).
783  *
784  * @todo reverse the arguments, first 'name' then 'service'
785  * as 'name' is more fundamental
786  *
787  * @param service service that the message should be sent to or #NULL
788  * @param name name of the message
789  * @returns a new DBusMessage, free with dbus_message_unref()
790  * @see dbus_message_unref()
791  */
792 DBusMessage*
793 dbus_message_new (const char *service,
794                   const char *name)
795 {
796   DBusMessage *message;
797
798   message = dbus_message_new_empty_header ();
799   if (message == NULL)
800     return NULL;
801   
802   if (!dbus_message_create_header (message, service, name))
803     {
804       dbus_message_unref (message);
805       return NULL;
806     }
807   
808   return message;
809 }
810
811 /**
812  * Constructs a message that is a reply to some other
813  * message. Returns #NULL if memory can't be allocated
814  * for the message.
815  *
816  * @param original_message the message which the created
817  * message is a reply to.
818  * @returns a new DBusMessage, free with dbus_message_unref()
819  * @see dbus_message_new(), dbus_message_unref()
820  */ 
821 DBusMessage*
822 dbus_message_new_reply (DBusMessage *original_message)
823 {
824   DBusMessage *message;
825   const char *sender, *name;
826
827   sender = get_string_field (original_message,
828                              FIELD_SENDER, NULL);
829   name = get_string_field (original_message,
830                            FIELD_NAME, NULL);
831
832   /* sender is allowed to be null here in peer-to-peer case */
833   
834   message = dbus_message_new (sender, name);
835   
836   if (message == NULL)
837     return NULL;
838
839   if (!dbus_message_set_reply_serial (message,
840                                       dbus_message_get_serial (original_message)))
841     {
842       dbus_message_unref (message);
843       return NULL;
844     }
845
846   return message;
847 }
848
849 /**
850  * Creates a new message that is an error reply to a certain message.
851  *
852  * @param original_message the original message
853  * @param error_name the error name
854  * @param error_message the error message string
855  * @returns a new error message
856  */
857 DBusMessage*
858 dbus_message_new_error_reply (DBusMessage *original_message,
859                               const char  *error_name,
860                               const char  *error_message)
861 {
862   DBusMessage *message;
863   const char *sender;
864
865   sender = get_string_field (original_message,
866                              FIELD_SENDER, NULL);
867   
868   _dbus_assert (sender != NULL);
869   
870   message = dbus_message_new (sender, error_name);
871   
872   if (message == NULL)
873     return NULL;
874
875   if (!dbus_message_set_reply_serial (message,
876                                       dbus_message_get_serial (original_message)))
877     {
878       dbus_message_unref (message);
879       return NULL;
880     }
881
882   if (!dbus_message_append_string (message, error_message))
883     {
884       dbus_message_unref (message);
885       return NULL;
886     }
887
888   dbus_message_set_is_error (message, TRUE);
889   
890   return message;
891 }
892
893 /**
894  * Creates a new message that is an exact replica of the message
895  * specified, except that its refcount is set to 1.
896  *
897  * @param message the message.
898  * @returns the new message.
899  */
900 DBusMessage *
901 dbus_message_copy (const DBusMessage *message)
902 {
903   DBusMessage *retval;
904   int i;
905   
906   retval = dbus_new0 (DBusMessage, 1);
907   if (retval == NULL)
908     return NULL;
909   
910   retval->refcount = 1;
911   retval->byte_order = message->byte_order;
912   retval->client_serial = message->client_serial;
913   retval->reply_serial = message->reply_serial;
914   retval->header_padding = message->header_padding;
915   retval->locked = FALSE;
916   
917   if (!_dbus_string_init (&retval->header))
918     {
919       dbus_free (retval);
920       return NULL;
921     }
922   
923   if (!_dbus_string_init (&retval->body))
924     {
925       _dbus_string_free (&retval->header);
926       dbus_free (retval);
927       return NULL;
928     }
929
930   if (!_dbus_string_copy (&message->header, 0,
931                           &retval->header, 0))
932     {
933       _dbus_string_free (&retval->header);
934       _dbus_string_free (&retval->body);
935       dbus_free (retval);
936
937       return NULL;
938     }
939
940   if (!_dbus_string_copy (&message->body, 0,
941                           &retval->body, 0))
942     {
943       _dbus_string_free (&retval->header);
944       _dbus_string_free (&retval->body);
945       dbus_free (retval);
946
947       return NULL;
948     }
949
950   for (i = 0; i < FIELD_LAST; i++)
951     {
952       retval->header_fields[i].offset = message->header_fields[i].offset;
953     }
954   
955   return retval;
956 }
957
958
959 /**
960  * Increments the reference count of a DBusMessage.
961  *
962  * @param message The message
963  * @see dbus_message_unref
964  */
965 void
966 dbus_message_ref (DBusMessage *message)
967 {
968   dbus_atomic_t refcount;
969
970   refcount = _dbus_atomic_inc (&message->refcount);
971   _dbus_assert (refcount > 1);
972 }
973
974 /**
975  * Decrements the reference count of a DBusMessage.
976  *
977  * @param message The message
978  * @see dbus_message_ref
979  */
980 void
981 dbus_message_unref (DBusMessage *message)
982 {
983   dbus_atomic_t refcount;
984
985   refcount = _dbus_atomic_dec (&message->refcount);
986   
987   _dbus_assert (refcount >= 0);
988
989   if (refcount == 0)
990     {
991       if (message->size_counter != NULL)
992         {
993           _dbus_counter_adjust (message->size_counter,
994                                 - message->size_counter_delta);
995           _dbus_counter_unref (message->size_counter);
996         }
997       
998       _dbus_string_free (&message->header);
999       _dbus_string_free (&message->body);
1000       
1001       dbus_free (message);
1002     }
1003 }
1004
1005 /**
1006  * Gets the name of a message.
1007  *
1008  * @param message the message
1009  * @returns the message name (should not be freed)
1010  */
1011 const char*
1012 dbus_message_get_name (DBusMessage *message)
1013 {
1014   return get_string_field (message, FIELD_NAME, NULL);
1015 }
1016
1017 /**
1018  * Gets the destination service of a message.
1019  *
1020  * @todo I think if we have set_sender/get_sender,
1021  * this function might be better named set_destination/
1022  * get_destination for clarity, as the sender
1023  * is also a service name.
1024  * 
1025  * @param message the message
1026  * @returns the message destination service (should not be freed)
1027  */
1028 const char*
1029 dbus_message_get_service (DBusMessage *message)
1030 {
1031   return get_string_field (message, FIELD_SERVICE, NULL);
1032 }
1033
1034 /**
1035  * Appends fields to a message given a variable argument
1036  * list. The variable argument list should contain the type
1037  * of the argument followed by the value to add. Array values
1038  * are specified by a pointer to the array followed by an int
1039  * giving the length of the array. The list is terminated
1040  * with 0.
1041  *
1042  * @param message the message
1043  * @param first_arg_type type of the first argument
1044  * @param ... value of first argument, list of additional type-value pairs
1045  * @returns #TRUE on success
1046  */
1047 dbus_bool_t
1048 dbus_message_append_args (DBusMessage *message,
1049                           int first_arg_type,
1050                           ...)
1051 {
1052   dbus_bool_t retval;
1053   va_list var_args;
1054
1055   va_start (var_args, first_arg_type);
1056   retval = dbus_message_append_args_valist (message,
1057                                             first_arg_type,
1058                                             var_args);
1059   va_end (var_args);
1060
1061   return retval;
1062 }
1063
1064 /**
1065  * This function takes a va_list for use by language bindings
1066  *
1067  * @see dbus_message_append_args.  
1068  * @param message the message
1069  * @param first_arg_type type of first argument
1070  * @param var_args value of first argument, then list of type/value pairs
1071  * @returns #TRUE on success
1072  */
1073 dbus_bool_t
1074 dbus_message_append_args_valist (DBusMessage *message,
1075                                  int          first_arg_type,
1076                                  va_list      var_args)
1077 {
1078   int type, old_len;
1079
1080   old_len = _dbus_string_get_length (&message->body);
1081   
1082   type = first_arg_type;
1083
1084   while (type != 0)
1085     {
1086       switch (type)
1087         {
1088         case DBUS_TYPE_NIL:
1089           if (!dbus_message_append_nil (message))
1090             goto enomem;
1091         case DBUS_TYPE_BOOLEAN:
1092           if (!dbus_message_append_boolean (message, va_arg (var_args, dbus_bool_t)))
1093             goto enomem;
1094           break;
1095         case DBUS_TYPE_INT32:
1096           if (!dbus_message_append_int32 (message, va_arg (var_args, dbus_int32_t)))
1097             goto enomem;
1098           break;
1099         case DBUS_TYPE_UINT32:
1100           if (!dbus_message_append_uint32 (message, va_arg (var_args, dbus_uint32_t)))
1101             goto enomem;            
1102           break;
1103         case DBUS_TYPE_DOUBLE:
1104           if (!dbus_message_append_double (message, va_arg (var_args, double)))
1105             goto enomem;
1106           break;
1107         case DBUS_TYPE_STRING:
1108           if (!dbus_message_append_string (message, va_arg (var_args, const char *)))
1109             goto enomem;
1110           break;
1111         case DBUS_TYPE_BOOLEAN_ARRAY:
1112           {
1113             int len;
1114             unsigned char *data;
1115
1116             data = va_arg (var_args, unsigned char *);
1117             len = va_arg (var_args, int);
1118
1119             if (!dbus_message_append_boolean_array (message, data, len))
1120               goto enomem;
1121           }
1122           break;
1123         case DBUS_TYPE_INT32_ARRAY:
1124           {
1125             int len;
1126             dbus_int32_t *data;
1127
1128             data = va_arg (var_args, dbus_int32_t *);
1129             len = va_arg (var_args, int);
1130
1131             if (!dbus_message_append_int32_array (message, data, len))
1132               goto enomem;
1133           }
1134           break;
1135         case DBUS_TYPE_UINT32_ARRAY:
1136           {
1137             int len;
1138             dbus_uint32_t *data;
1139
1140             data = va_arg (var_args, dbus_uint32_t *);
1141             len = va_arg (var_args, int);
1142
1143             if (!dbus_message_append_uint32_array (message, data, len))
1144               goto enomem;
1145           }
1146           break;
1147         case DBUS_TYPE_DOUBLE_ARRAY:
1148           {
1149             int len;
1150             double *data;
1151
1152             data = va_arg (var_args, double *);
1153             len = va_arg (var_args, int);
1154
1155             if (!dbus_message_append_double_array (message, data, len))
1156               goto enomem;
1157           }
1158           break;
1159         case DBUS_TYPE_BYTE_ARRAY:
1160           {
1161             int len;
1162             unsigned char *data;
1163
1164             data = va_arg (var_args, unsigned char *);
1165             len = va_arg (var_args, int);
1166
1167             if (!dbus_message_append_byte_array (message, data, len))
1168               goto enomem;
1169           }
1170           break;
1171         case DBUS_TYPE_STRING_ARRAY:
1172           {
1173             int len;
1174             const char **data;
1175             
1176             data = va_arg (var_args, const char **);
1177             len = va_arg (var_args, int);
1178
1179             if (!dbus_message_append_string_array (message, data, len))
1180               goto enomem;
1181           }
1182           break;
1183         case DBUS_TYPE_DICT:
1184           {
1185             DBusDict *dict;
1186
1187             dict = va_arg (var_args, DBusDict *);
1188
1189             if (!dbus_message_append_dict (message, dict))
1190               goto enomem;
1191             break;
1192           }
1193         default:
1194           _dbus_warn ("Unknown field type %d\n", type);
1195         }
1196
1197       type = va_arg (var_args, int);
1198     }
1199
1200   return TRUE;
1201
1202  enomem:
1203   return FALSE;
1204 }
1205
1206 /**
1207  * Appends a nil value to the message
1208  *
1209  * @param message the message
1210  * @returns #TRUE on success
1211  */
1212 dbus_bool_t
1213 dbus_message_append_nil (DBusMessage *message)
1214 {
1215   _dbus_assert (!message->locked);
1216
1217   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_NIL))
1218       return FALSE;
1219   else
1220     return TRUE;
1221 }
1222
1223 /**
1224  * Appends a boolean value to the message
1225  *
1226  * @param message the message
1227  * @param value the boolean value
1228  * @returns #TRUE on success
1229  */
1230 dbus_bool_t
1231 dbus_message_append_boolean (DBusMessage  *message,
1232                              dbus_bool_t   value)
1233 {
1234   _dbus_assert (!message->locked);
1235   
1236   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BOOLEAN))
1237     return FALSE;
1238
1239   if (!_dbus_string_append_byte (&message->body, (value != FALSE)))
1240     {
1241       _dbus_string_shorten (&message->body, 1);
1242       return FALSE;
1243     }
1244
1245   return TRUE;
1246 }
1247
1248 /**
1249  * Appends a 32 bit signed integer to the message.
1250  *
1251  * @param message the message
1252  * @param value the integer value
1253  * @returns #TRUE on success
1254  */
1255 dbus_bool_t
1256 dbus_message_append_int32 (DBusMessage  *message,
1257                            dbus_int32_t  value)
1258 {
1259   _dbus_assert (!message->locked);
1260
1261   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
1262       return FALSE;
1263   
1264   if (!_dbus_marshal_int32 (&message->body, message->byte_order, value))
1265     {
1266       _dbus_string_shorten (&message->body, 1);
1267       return FALSE;
1268     }
1269
1270   return TRUE;
1271 }
1272
1273 /**
1274  * Appends a 32 bit unsigned integer to the message.
1275  *
1276  * @param message the message
1277  * @param value the integer value
1278  * @returns #TRUE on success
1279  */
1280 dbus_bool_t
1281 dbus_message_append_uint32 (DBusMessage   *message,
1282                             dbus_uint32_t  value)
1283 {
1284   _dbus_assert (!message->locked);
1285
1286   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
1287       return FALSE;
1288   
1289   if (!_dbus_marshal_uint32 (&message->body, message->byte_order, value))
1290     {
1291       _dbus_string_shorten (&message->body, 1);
1292       return FALSE;
1293     }
1294
1295   return TRUE;      
1296 }
1297
1298 /**
1299  * Appends a double value to the message.
1300  *
1301  * @param message the message
1302  * @param value the double value
1303  * @returns #TRUE on success
1304  */
1305 dbus_bool_t
1306 dbus_message_append_double (DBusMessage *message,
1307                             double       value)
1308 {
1309   _dbus_assert (!message->locked);
1310
1311   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
1312     return FALSE;
1313
1314   if (!_dbus_marshal_double (&message->body, message->byte_order, value))
1315     {
1316       _dbus_string_shorten (&message->body, 1);
1317       return FALSE;
1318     }
1319   
1320   return TRUE;
1321 }
1322
1323 /**
1324  * Appends a UTF-8 string to the message.
1325  *
1326  * @param message the message
1327  * @param value the string
1328  * @returns #TRUE on success
1329  */
1330 dbus_bool_t
1331 dbus_message_append_string (DBusMessage *message,
1332                             const char  *value)
1333 {
1334   _dbus_assert (!message->locked);
1335
1336   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
1337       return FALSE;
1338   
1339   if (!_dbus_marshal_string (&message->body, message->byte_order, value))
1340     {
1341       _dbus_string_shorten (&message->body, 1);
1342       return FALSE;      
1343     }
1344
1345   return TRUE;
1346 }
1347
1348 /**
1349  * Appends a boolean array to the message.
1350  *
1351  * @param message the message
1352  * @param value the array
1353  * @param len the length of the array
1354  * @returns #TRUE on success
1355  */
1356 dbus_bool_t
1357 dbus_message_append_boolean_array (DBusMessage         *message,
1358                                    unsigned const char *value,
1359                                    int                  len)
1360 {
1361   _dbus_assert (!message->locked);
1362
1363   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BOOLEAN_ARRAY))
1364     return FALSE;
1365
1366   if (!_dbus_marshal_byte_array (&message->body, message->byte_order, value, len))
1367     {
1368       _dbus_string_shorten (&message->body, 1);
1369       return FALSE;
1370     }
1371
1372   return TRUE;
1373 }
1374
1375 /**
1376  * Appends a 32 bit signed integer array to the message.
1377  *
1378  * @param message the message
1379  * @param value the array
1380  * @param len the length of the array
1381  * @returns #TRUE on success
1382  */
1383 dbus_bool_t
1384 dbus_message_append_int32_array (DBusMessage        *message,
1385                                  const dbus_int32_t *value,
1386                                  int                 len)
1387 {
1388   _dbus_assert (!message->locked);
1389
1390   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32_ARRAY))
1391     return FALSE;
1392
1393   if (!_dbus_marshal_int32_array (&message->body, message->byte_order,
1394                                   value, len))
1395     {
1396       _dbus_string_shorten (&message->body, 1);
1397       return FALSE;
1398     }
1399
1400   return TRUE;
1401 }
1402
1403 /**
1404  * Appends a 32 bit unsigned integer array to the message.
1405  *
1406  * @param message the message
1407  * @param value the array
1408  * @param len the length of the array
1409  * @returns #TRUE on success
1410  */
1411 dbus_bool_t
1412 dbus_message_append_uint32_array (DBusMessage         *message,
1413                                   const dbus_uint32_t *value,
1414                                   int                  len)
1415 {
1416   _dbus_assert (!message->locked);
1417
1418   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32_ARRAY))
1419     return FALSE;
1420
1421   if (!_dbus_marshal_uint32_array (&message->body, message->byte_order,
1422                                   value, len))
1423     {
1424       _dbus_string_shorten (&message->body, 1);
1425       return FALSE;
1426     }
1427
1428   return TRUE;
1429 }
1430
1431 /**
1432  * Appends a double array to the message.
1433  *
1434  * @param message the message
1435  * @param value the array
1436  * @param len the length of the array
1437  * @returns #TRUE on success
1438  */
1439 dbus_bool_t
1440 dbus_message_append_double_array (DBusMessage  *message,
1441                                   const double *value,
1442                                   int           len)
1443 {
1444   _dbus_assert (!message->locked);
1445
1446   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE_ARRAY))
1447     return FALSE;
1448
1449   if (!_dbus_marshal_double_array (&message->body, message->byte_order,
1450                                    value, len))
1451     {
1452       _dbus_string_shorten (&message->body, 1);
1453       return FALSE;
1454     }
1455
1456   return TRUE;
1457 }
1458
1459 /**
1460  * Appends a byte array to the message.
1461  *
1462  * @param message the message
1463  * @param value the array
1464  * @param len the length of the array
1465  * @returns #TRUE on success
1466  */
1467 dbus_bool_t
1468 dbus_message_append_byte_array (DBusMessage         *message,
1469                                 unsigned const char *value,
1470                                 int                 len)
1471 {
1472   _dbus_assert (!message->locked);
1473
1474   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
1475     return FALSE;
1476   
1477   if (!_dbus_marshal_byte_array (&message->body, message->byte_order, value, len))
1478     {
1479       _dbus_string_shorten (&message->body, 1);
1480       return FALSE;
1481     }
1482       
1483   return TRUE;
1484 }
1485
1486 /**
1487  * Appends a string array to the message.
1488  *
1489  * @param message the message
1490  * @param value the array
1491  * @param len the length of the array
1492  * @returns #TRUE on success
1493  */
1494 dbus_bool_t
1495 dbus_message_append_string_array (DBusMessage  *message,
1496                                   const char  **value,
1497                                   int           len)
1498 {
1499   _dbus_assert (!message->locked);
1500
1501   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING_ARRAY))
1502     return FALSE;
1503
1504   if (!_dbus_marshal_string_array (&message->body, message->byte_order,
1505                                    (const char **)value, len))
1506     {
1507       _dbus_string_shorten (&message->body, 1);
1508       return FALSE;
1509     }
1510
1511   return TRUE;
1512 }
1513
1514 /**
1515  * Appends a dict to the message.
1516  *
1517  * @param message the message
1518  * @param dict the dict
1519  * @returns #TRUE on success
1520  */
1521 dbus_bool_t
1522 dbus_message_append_dict (DBusMessage *message,
1523                           DBusDict    *dict)
1524 {
1525   _dbus_assert (!message->locked);
1526
1527   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DICT))
1528     return FALSE;
1529
1530   if (!_dbus_marshal_dict (&message->body, message->byte_order, dict))
1531     {
1532       _dbus_string_shorten (&message->body, 1);
1533       return FALSE;
1534     }
1535
1536   return TRUE;
1537 }
1538
1539 /**
1540  * Gets arguments from a message given a variable argument list.
1541  * The variable argument list should contain the type of the
1542  * argumen followed by a pointer to where the value should be
1543  * stored. The list is terminated with 0.
1544  *
1545  * @param message the message
1546  * @param error error to be filled in on failure
1547  * @param first_arg_type the first argument type
1548  * @param ... location for first argument value, then list of type-location pairs
1549  * @returns #FALSE if the error was set
1550  */
1551 dbus_bool_t
1552 dbus_message_get_args (DBusMessage *message,
1553                        DBusError   *error,
1554                        int          first_arg_type,
1555                        ...)
1556 {
1557   dbus_bool_t retval;
1558   va_list var_args;
1559
1560   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1561   
1562   va_start (var_args, first_arg_type);
1563   retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
1564   va_end (var_args);
1565
1566   return retval;
1567 }
1568
1569 /**
1570  * This function takes a va_list for use by language bindings
1571  *
1572  * @todo this function (or some lower-level non-convenience function)
1573  * needs better error handling; should allow the application to
1574  * distinguish between out of memory, and bad data from the remote
1575  * app. It also needs to not leak a bunch of args when it gets
1576  * to the arg that's bad, as that would be a security hole
1577  * (allow one app to force another to leak memory)
1578  *
1579  * @todo We need to free the argument data when an error occurs.
1580  *
1581  * @see dbus_message_get_args
1582  * @param message the message
1583  * @param error error to be filled in
1584  * @param first_arg_type type of the first argument
1585  * @param var_args return location for first argument, followed by list of type/location pairs
1586  * @returns #FALSE if error was set
1587  */
1588 dbus_bool_t
1589 dbus_message_get_args_valist (DBusMessage *message,
1590                               DBusError   *error,
1591                               int          first_arg_type,
1592                               va_list      var_args)
1593 {
1594   int spec_type, msg_type, i;
1595   DBusMessageIter *iter;
1596   dbus_bool_t retval;
1597
1598   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1599   
1600   iter = dbus_message_get_args_iter (message);
1601
1602   if (iter == NULL)
1603     {
1604       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1605       return FALSE;
1606     }
1607
1608   retval = FALSE;
1609   
1610   spec_type = first_arg_type;
1611   i = 0;
1612   
1613   while (spec_type != 0)
1614     {
1615       msg_type = dbus_message_iter_get_arg_type (iter);      
1616       
1617       if (msg_type != spec_type)
1618         {
1619           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1620                           "Argument %d is specified to be of type \"%s\", but "
1621                           "is actually of type \"%s\"\n", i,
1622                           _dbus_type_to_string (spec_type),
1623                           _dbus_type_to_string (msg_type));
1624
1625           goto out;
1626         }
1627
1628       switch (spec_type)
1629         {
1630         case DBUS_TYPE_NIL:
1631           break;
1632         case DBUS_TYPE_BOOLEAN:
1633           {
1634             dbus_bool_t *ptr;
1635
1636             ptr = va_arg (var_args, dbus_bool_t *);
1637
1638             *ptr = dbus_message_iter_get_boolean (iter);
1639             break;
1640           }
1641         case DBUS_TYPE_INT32:
1642           {
1643             dbus_int32_t *ptr;
1644
1645             ptr = va_arg (var_args, dbus_int32_t *);
1646
1647             *ptr = dbus_message_iter_get_int32 (iter);
1648             break;
1649           }
1650         case DBUS_TYPE_UINT32:
1651           {
1652             dbus_uint32_t *ptr;
1653
1654             ptr = va_arg (var_args, dbus_uint32_t *);
1655
1656             *ptr = dbus_message_iter_get_uint32 (iter);
1657             break;
1658           }
1659
1660         case DBUS_TYPE_DOUBLE:
1661           {
1662             double *ptr;
1663
1664             ptr = va_arg (var_args, double *);
1665
1666             *ptr = dbus_message_iter_get_double (iter);
1667             break;
1668           }
1669
1670         case DBUS_TYPE_STRING:
1671           {
1672             char **ptr;
1673
1674             ptr = va_arg (var_args, char **);
1675
1676             *ptr = dbus_message_iter_get_string (iter);
1677
1678             if (!*ptr)
1679               {
1680                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1681                 goto out;
1682               }
1683             
1684             break;
1685           }
1686
1687         case DBUS_TYPE_BOOLEAN_ARRAY:
1688           {
1689             unsigned char **ptr;
1690             int *len;
1691
1692             ptr = va_arg (var_args, unsigned char **);
1693             len = va_arg (var_args, int *);
1694
1695             if (!dbus_message_iter_get_boolean_array (iter, ptr, len))
1696               {
1697                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1698                 goto out;
1699               }
1700             break;
1701           }
1702           
1703         case DBUS_TYPE_INT32_ARRAY:
1704           {
1705             dbus_int32_t **ptr;
1706             int *len;
1707
1708             ptr = va_arg (var_args, dbus_int32_t **);
1709             len = va_arg (var_args, int *);
1710
1711             if (!dbus_message_iter_get_int32_array (iter, ptr, len))
1712               {
1713                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1714                 goto out;
1715               }
1716             
1717             break;
1718           }
1719
1720         case DBUS_TYPE_UINT32_ARRAY:
1721           {
1722             dbus_uint32_t **ptr;
1723             int *len;
1724
1725             ptr = va_arg (var_args, dbus_uint32_t **);
1726             len = va_arg (var_args, int *);
1727
1728             if (!dbus_message_iter_get_uint32_array (iter, ptr, len))
1729               {
1730                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1731                 goto out;
1732               }
1733             
1734             break;
1735           }
1736
1737         case DBUS_TYPE_DOUBLE_ARRAY:
1738           {
1739             double **ptr;
1740             int *len;
1741
1742             ptr = va_arg (var_args, double **);
1743             len = va_arg (var_args, int *);
1744
1745             if (!dbus_message_iter_get_double_array (iter, ptr, len))
1746               {
1747                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1748                 goto out;
1749               }
1750             break;
1751           }
1752           
1753         case DBUS_TYPE_BYTE_ARRAY:
1754           {
1755             unsigned char **ptr;
1756             int *len;
1757
1758             ptr = va_arg (var_args, unsigned char **);
1759             len = va_arg (var_args, int *);
1760
1761             if (!dbus_message_iter_get_byte_array (iter, ptr, len))
1762               {
1763                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1764                 goto out;
1765               }
1766             break;
1767           }
1768         case DBUS_TYPE_STRING_ARRAY:
1769           {
1770             char ***ptr;
1771             int *len;
1772
1773             ptr = va_arg (var_args, char ***);
1774             len = va_arg (var_args, int *);
1775
1776             if (!dbus_message_iter_get_string_array (iter, ptr, len))
1777               {
1778                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1779                 goto out;
1780               }
1781             break;
1782           }
1783         case DBUS_TYPE_DICT:
1784           {
1785             DBusDict **dict;
1786
1787             dict = va_arg (var_args, DBusDict **);
1788
1789             if (!dbus_message_iter_get_dict (iter, dict))
1790               {
1791                 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
1792                 goto out;
1793               }
1794             break;
1795           }
1796         default:          
1797           _dbus_warn ("Unknown field type %d\n", spec_type);
1798         }
1799       
1800       spec_type = va_arg (var_args, int);
1801       if (spec_type != 0 && !dbus_message_iter_next (iter))
1802         {
1803           dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1804                           "Message has only %d arguments, but more were expected", i);
1805           goto out;
1806         }
1807
1808       i++;
1809     }
1810   
1811   retval = TRUE;
1812   
1813  out:
1814   dbus_message_iter_unref (iter);
1815   return retval;
1816 }
1817
1818 /**
1819  * Returns a DBusMessageIter representing the arguments of the
1820  * message passed in.
1821  *
1822  * @todo IMO the message iter should follow the GtkTextIter pattern,
1823  * a static object with a "stamp" value used to detect invalid
1824  * iter uses (uninitialized or after changing the message).
1825  * ref/unref is kind of annoying to deal with, and slower too.
1826  * This implies not ref'ing the message from the iter.
1827  *
1828  * @todo I'd also name this dbus_message_iter_new() or
1829  * for the static object dbus_message_iter_init() rather
1830  * than making it a method on the message
1831  *
1832  * @param message the message
1833  * @returns a new iter.
1834  */
1835 DBusMessageIter *
1836 dbus_message_get_args_iter (DBusMessage *message)
1837 {
1838   DBusMessageIter *iter;
1839   
1840   iter = dbus_new (DBusMessageIter, 1);
1841
1842   if (iter != NULL)
1843     {
1844       dbus_message_ref (message);
1845   
1846       iter->refcount = 1;
1847       iter->message = message;
1848       iter->pos = 0;
1849     }
1850   
1851   return iter;
1852 }
1853
1854 /**
1855  * Increments the reference count of a DBusMessageIter.
1856  *
1857  * @param iter the message iter
1858  * @see dbus_message_iter_unref
1859  */
1860 void
1861 dbus_message_iter_ref (DBusMessageIter *iter)
1862 {
1863   _dbus_assert (iter->refcount > 0);
1864   
1865   iter->refcount += 1;
1866 }
1867
1868 /**
1869  * Decrements the reference count of a DBusMessageIter.
1870  *
1871  * @param iter The message iter
1872  * @see dbus_message_iter_ref
1873  */
1874 void
1875 dbus_message_iter_unref (DBusMessageIter *iter)
1876 {
1877   _dbus_assert (iter->refcount > 0);
1878
1879   iter->refcount -= 1;
1880
1881   if (iter->refcount == 0)
1882     {
1883       dbus_message_unref (iter->message);
1884
1885       dbus_free (iter);
1886     }
1887 }
1888
1889 /**
1890  * Checks if an iterator has any more fields.
1891  *
1892  * @param iter the message iter
1893  * @returns #TRUE if there are more fields
1894  * following
1895  */
1896 dbus_bool_t
1897 dbus_message_iter_has_next (DBusMessageIter *iter)
1898 {
1899   int end_pos;
1900   
1901   if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
1902                                       iter->message->byte_order,
1903                                       iter->pos, &end_pos))
1904     return FALSE;
1905   
1906   if (end_pos >= _dbus_string_get_length (&iter->message->body))
1907     return FALSE;
1908   
1909   return TRUE;  
1910 }
1911
1912 /**
1913  * Moves the iterator to the next field.
1914  *
1915  * @param iter The message iter
1916  * @returns #TRUE if the iterator was moved to the next field
1917  */
1918 dbus_bool_t
1919 dbus_message_iter_next (DBusMessageIter *iter)
1920 {
1921   int end_pos;
1922   
1923   if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
1924                                       iter->message->byte_order,
1925                                       iter->pos, &end_pos))
1926     return FALSE;
1927
1928   if (end_pos >= _dbus_string_get_length (&iter->message->body))
1929     return FALSE;
1930
1931   iter->pos = end_pos;
1932
1933   return TRUE;
1934 }
1935
1936 /**
1937  * Returns the argument type of the argument that the
1938  * message iterator points at.
1939  *
1940  * @param iter the message iter
1941  * @returns the field type
1942  */
1943 int
1944 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
1945 {
1946   const char *data;
1947
1948   if (iter->pos >= _dbus_string_get_length (&iter->message->body))
1949     return DBUS_TYPE_INVALID;
1950
1951   data = _dbus_string_get_const_data_len (&iter->message->body, iter->pos, 1);
1952
1953   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_DICT)
1954     return *data;
1955
1956   return DBUS_TYPE_INVALID;
1957 }
1958
1959 /**
1960  * Returns the string value that an iterator may point to.
1961  * Note that you need to check that the iterator points to
1962  * a string value before using this function.
1963  *
1964  * @see dbus_message_iter_get_arg_type
1965  * @param iter the message iter
1966  * @returns the string
1967  */
1968 char *
1969 dbus_message_iter_get_string (DBusMessageIter *iter)
1970 {
1971   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING);
1972
1973   return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
1974                                  iter->pos + 1, NULL);
1975 }
1976
1977 /**
1978  * Returns the boolean value that an iterator may point to.
1979  * Note that you need to check that the iterator points to
1980  * a boolean value before using this function.
1981  *
1982  * @see dbus_message_iter_get_arg_type
1983  * @param iter the message iter
1984  * @returns the string
1985  */
1986 dbus_bool_t
1987 dbus_message_iter_get_boolean (DBusMessageIter *iter)
1988 {
1989   unsigned char value;
1990   
1991   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN);
1992
1993   value = _dbus_string_get_byte (&iter->message->body, iter->pos + 1);
1994   
1995   return value;
1996 }
1997
1998 /**
1999  * Returns the 32 bit signed integer value that an iterator may point to.
2000  * Note that you need to check that the iterator points to
2001  * an integer value before using this function.
2002  *
2003  * @see dbus_message_iter_get_arg_type
2004  * @param iter the message iter
2005  * @returns the integer
2006  */
2007 int
2008 dbus_message_iter_get_int32 (DBusMessageIter *iter)
2009 {
2010   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT32);
2011   
2012   return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
2013                                 iter->pos + 1, NULL);
2014 }
2015
2016 /**
2017  * Returns the 32 bit unsigned integer value that an iterator may point to.
2018  * Note that you need to check that the iterator points to
2019  * an unsigned integer value before using this function.
2020  *
2021  * @see dbus_message_iter_get_arg_type
2022  * @param iter the message iter
2023  * @returns the integer
2024  */
2025 int
2026 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
2027 {
2028   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT32);
2029   
2030   return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
2031                                  iter->pos + 1, NULL);
2032 }
2033
2034 /**
2035  * Returns the double value that an iterator may point to.
2036  * Note that you need to check that the iterator points to
2037  * a string value before using this function.
2038  *
2039  * @see dbus_message_iter_get_arg_type
2040  * @param iter the message iter
2041  * @returns the double
2042  */
2043 double
2044 dbus_message_iter_get_double (DBusMessageIter *iter)
2045 {
2046   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DOUBLE);
2047   
2048   return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
2049                                  iter->pos + 1, NULL);
2050 }
2051
2052 /**
2053  * Returns the boolean array that the iterator may point to. Note that
2054  * you need to check that the iterator points to an array of the
2055  * correct type prior to using this function.
2056  *
2057  * @param iter the iterator
2058  * @param value return location for the array
2059  * @param len return location for the array length
2060  * @returns #TRUE on success
2061  */
2062 dbus_bool_t
2063 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
2064                                      unsigned char    **value,
2065                                      int               *len)
2066 {
2067   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN_ARRAY);
2068
2069   if (!_dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
2070                                    iter->pos + 1, NULL, value, len))
2071     return FALSE;
2072   else
2073     return TRUE;
2074 }
2075
2076 /**
2077  * Returns the 32 bit signed integer array that the iterator may point
2078  * to. Note that you need to check that the iterator points to an
2079  * array of the correct type prior to using this function.
2080  *
2081  * @param iter the iterator
2082  * @param value return location for the array
2083  * @param len return location for the array length
2084  * @returns #TRUE on success
2085  */
2086 dbus_bool_t
2087 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
2088                                     dbus_int32_t   **value,
2089                                     int             *len)
2090 {
2091   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT32_ARRAY);
2092
2093   if (!_dbus_demarshal_int32_array (&iter->message->body, iter->message->byte_order,
2094                                     iter->pos + 1, NULL, value, len))
2095     return FALSE;
2096   else
2097     return TRUE;
2098 }
2099
2100 /**
2101  * Returns the 32 bit unsigned integer array that the iterator may point
2102  * to. Note that you need to check that the iterator points to an
2103  * array of the correct type prior to using this function.
2104  *
2105  * @param iter the iterator
2106  * @param value return location for the array
2107  * @param len return location for the array length
2108  * @returns #TRUE on success
2109  */
2110 dbus_bool_t
2111 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
2112                                      dbus_uint32_t  **value,
2113                                      int             *len)
2114 {
2115   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT32_ARRAY);
2116
2117   if (!_dbus_demarshal_uint32_array (&iter->message->body, iter->message->byte_order,
2118                                      iter->pos + 1, NULL, value, len))
2119     return FALSE;
2120   else
2121     return TRUE;
2122 }
2123
2124 /**
2125  * Returns the double array that the iterator may point to. Note that
2126  * you need to check that the iterator points to an array of the
2127  * correct type prior to using this function.
2128  *
2129  * @param iter the iterator
2130  * @param value return location for the array
2131  * @param len return location for the array length
2132  * @returns #TRUE on success
2133  */
2134 dbus_bool_t
2135 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
2136                                      double         **value,
2137                                      int             *len)
2138 {
2139   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DOUBLE_ARRAY);
2140
2141   if (!_dbus_demarshal_double_array (&iter->message->body, iter->message->byte_order,
2142                                      iter->pos + 1, NULL, value, len))
2143     return FALSE;
2144   else
2145     return TRUE;
2146 }
2147
2148 /**
2149  * Returns the byte array that the iterator may point to.
2150  * Note that you need to check that the iterator points
2151  * to a byte array prior to using this function.
2152  *
2153  * @param iter the iterator
2154  * @param value return location for array values
2155  * @param len return location for length of byte array
2156  * @returns #TRUE on success
2157  */
2158 dbus_bool_t
2159 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
2160                                   unsigned char   **value,
2161                                   int              *len)
2162 {
2163   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BYTE_ARRAY);
2164
2165   if (!_dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
2166                                    iter->pos + 1, NULL, value, len))
2167     return FALSE;
2168   else
2169     return TRUE;
2170 }
2171
2172 /**
2173  * Returns the string array that the iterator may point to.
2174  * Note that you need to check that the iterator points
2175  * to a byte array prior to using this function.
2176  *
2177  * The returned value is a #NULL-terminated array of strings.
2178  * Each string is a separate malloc block, and the array
2179  * itself is a malloc block. You can free this type of
2180  * string array with dbus_free_string_array().
2181  *
2182  * @param iter the iterator
2183  * @param value return location for string values
2184  * @param len return location for length of byte array
2185  * @returns #TRUE on success
2186  */
2187 dbus_bool_t
2188 dbus_message_iter_get_string_array (DBusMessageIter *iter,
2189                                     char          ***value,
2190                                     int             *len)
2191 {
2192   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING_ARRAY);
2193
2194   if (!_dbus_demarshal_string_array (&iter->message->body, iter->message->byte_order,
2195                                      iter->pos + 1, NULL, value, len))
2196     return FALSE;
2197   else
2198     return TRUE;
2199 }
2200
2201 /**
2202  * Returns the dict that the iterator may point to.
2203  * Note that you need to check that the iterator points
2204  * to a dict prior to using this function.
2205  *
2206  * @param iter the iterator
2207  * @param dict return location for dict
2208  * @returns #TRUE on success
2209  */
2210 dbus_bool_t
2211 dbus_message_iter_get_dict (DBusMessageIter *iter,
2212                             DBusDict       **dict)
2213 {
2214   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DICT);
2215
2216   if (!_dbus_demarshal_dict (&iter->message->body, iter->message->byte_order,
2217                              iter->pos + 1, NULL, dict))
2218     return FALSE;
2219   else
2220     return TRUE;
2221 }
2222
2223 /**
2224  * Sets the message sender.
2225  *
2226  * @param message the message
2227  * @param sender the sender
2228  * @returns #FALSE if not enough memory
2229  */
2230 dbus_bool_t
2231 dbus_message_set_sender (DBusMessage  *message,
2232                          const char   *sender)
2233 {
2234   _dbus_assert (!message->locked);
2235
2236   if (sender == NULL)
2237     {
2238       delete_string_field (message, FIELD_SENDER);
2239       return TRUE;
2240     }
2241   else
2242     {
2243       return set_string_field (message,
2244                                FIELD_SENDER,
2245                                sender);
2246     }
2247 }
2248
2249 /**
2250  * Sets a flag indicating that the message is an error reply
2251  * message, i.e. an "exception" rather than a normal response.
2252  *
2253  * @param message the message
2254  * @param is_error_reply #TRUE if this is an error message.
2255  */
2256 void
2257 dbus_message_set_is_error (DBusMessage *message,
2258                            dbus_bool_t  is_error_reply)
2259 {
2260   char *header;
2261   
2262   _dbus_assert (!message->locked);
2263   
2264   header = _dbus_string_get_data_len (&message->header, 1, 1);
2265   
2266   if (is_error_reply)
2267     *header |= DBUS_HEADER_FLAG_ERROR;
2268   else
2269     *header &= ~DBUS_HEADER_FLAG_ERROR;    
2270 }
2271
2272 /**
2273  * Returns #TRUE if the message is an error
2274  * reply to some previous message we sent.
2275  *
2276  * @param message the message
2277  * @returns #TRUE if the message is an error
2278  */
2279 dbus_bool_t
2280 dbus_message_get_is_error (DBusMessage *message)
2281 {
2282   const char *header;
2283
2284   header = _dbus_string_get_const_data_len (&message->header, 1, 1);
2285
2286   return (*header & DBUS_HEADER_FLAG_ERROR) != 0;
2287 }
2288
2289 /**
2290  * Gets the service which originated this message,
2291  * or #NULL if unknown or inapplicable.
2292  *
2293  * @param message the message
2294  * @returns the service name or #NULL
2295  */
2296 const char*
2297 dbus_message_get_sender (DBusMessage *message)
2298 {
2299   return get_string_field (message, FIELD_SENDER, NULL);
2300 }
2301
2302 /**
2303  * Checks whether the message has the given name.
2304  * If the message has no name or has a different
2305  * name, returns #FALSE.
2306  *
2307  * @param message the message
2308  * @param name the name to check (must not be #NULL)
2309  * 
2310  * @returns #TRUE if the message has the given name
2311  */
2312 dbus_bool_t
2313 dbus_message_name_is (DBusMessage *message,
2314                       const char  *name)
2315 {
2316   const char *n;
2317
2318   _dbus_assert (name != NULL);
2319   
2320   n = dbus_message_get_name (message);
2321
2322   if (n && strcmp (n, name) == 0)
2323     return TRUE;
2324   else
2325     return FALSE;
2326 }
2327
2328 /**
2329  * Checks whether the message was sent to the given service.  If the
2330  * message has no service specified or has a different name, returns
2331  * #FALSE.
2332  *
2333  * @param message the message
2334  * @param service the service to check (must not be #NULL)
2335  * 
2336  * @returns #TRUE if the message has the given destination service
2337  */
2338 dbus_bool_t
2339 dbus_message_service_is (DBusMessage  *message,
2340                          const char   *service)
2341 {
2342   const char *s;
2343
2344   _dbus_assert (service != NULL);
2345   
2346   s = dbus_message_get_service (message);
2347
2348   if (s && strcmp (s, service) == 0)
2349     return TRUE;
2350   else
2351     return FALSE;
2352 }
2353
2354 /**
2355  * Checks whether the message has the given service as its sender.  If
2356  * the message has no sender specified or has a different sender,
2357  * returns #FALSE. Note that if a peer application owns multiple
2358  * services, its messages will have only one of those services as the
2359  * sender (usually the base service). So you can't use this
2360  * function to prove the sender didn't own service Foo, you can
2361  * only use it to prove that it did.
2362  *
2363  * @param message the message
2364  * @param service the service to check (must not be #NULL)
2365  * 
2366  * @returns #TRUE if the message has the given origin service
2367  */
2368 dbus_bool_t
2369 dbus_message_sender_is (DBusMessage  *message,
2370                         const char   *service)
2371 {
2372   const char *s;
2373
2374   _dbus_assert (service != NULL);
2375   
2376   s = dbus_message_get_sender (message);
2377
2378   if (s && strcmp (s, service) == 0)
2379     return TRUE;
2380   else
2381     return FALSE;
2382 }
2383
2384 /**
2385  * Sets a #DBusError based on the contents of the given
2386  * message. The error is only set if the message
2387  * is an error message, as in dbus_message_get_is_error().
2388  * The name of the error is set to the name of the message,
2389  * and the error message is set to the first argument
2390  * if the argument exists and is a string.
2391  *
2392  * The return value indicates whether the error was set (the error is
2393  * set if and only if the message is an error message).
2394  * So you can check for an error reply and convert it to DBusError
2395  * in one go.
2396  *
2397  * @param error the error to set
2398  * @param message the message to set it from
2399  * @returns #TRUE if dbus_message_get_is_error() returns #TRUE for the message
2400  */
2401 dbus_bool_t
2402 dbus_set_error_from_message (DBusError   *error,
2403                              DBusMessage *message)
2404 {
2405   char *str;
2406   
2407   if (!dbus_message_get_is_error (message))
2408     return FALSE;
2409
2410   str = NULL;
2411   dbus_message_get_args (message, NULL,
2412                          DBUS_TYPE_STRING, &str,
2413                          DBUS_TYPE_INVALID);
2414
2415   dbus_set_error (error, dbus_message_get_name (message),
2416                   str ? "%s" : NULL, str);
2417
2418   dbus_free (str);
2419   
2420   return TRUE;
2421 }
2422
2423 /** @} */
2424
2425 /**
2426  * @addtogroup DBusMessageInternals
2427  *
2428  * @{
2429  */
2430 /**
2431  * @typedef DBusMessageLoader
2432  *
2433  * The DBusMessageLoader object encapsulates the process of converting
2434  * a byte stream into a series of DBusMessage. It buffers the incoming
2435  * bytes as efficiently as possible, and generates a queue of
2436  * messages. DBusMessageLoader is typically used as part of a
2437  * DBusTransport implementation. The DBusTransport then hands off
2438  * the loaded messages to a DBusConnection, making the messages
2439  * visible to the application.
2440  *
2441  * @todo write tests for break-loader that a) randomly delete header
2442  * fields and b) set string fields to zero-length and other funky
2443  * values.
2444  * 
2445  */
2446
2447 /* we definitely use signed ints for sizes, so don't exceed
2448  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
2449  * over 128M is pretty nuts anyhow.
2450  */
2451
2452 /**
2453  * The maximum sane message size.
2454  */
2455 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
2456
2457 /**
2458  * Implementation details of DBusMessageLoader.
2459  * All members are private.
2460  */
2461 struct DBusMessageLoader
2462 {
2463   int refcount;        /**< Reference count. */
2464
2465   DBusString data;     /**< Buffered data */
2466   
2467   DBusList *messages;  /**< Complete messages. */
2468
2469   long max_message_size; /**< Maximum size of a message */
2470   
2471   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
2472
2473   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
2474 };
2475
2476 /**
2477  * The initial buffer size of the message loader.
2478  * 
2479  * @todo this should be based on min header size plus some average
2480  * body size, or something. Or rather, the min header size only, if we
2481  * want to try to read only the header, store that in a DBusMessage,
2482  * then read only the body and store that, etc., depends on
2483  * how we optimize _dbus_message_loader_get_buffer() and what
2484  * the exact message format is.
2485  */
2486 #define INITIAL_LOADER_DATA_LEN 32
2487
2488 /**
2489  * Creates a new message loader. Returns #NULL if memory can't
2490  * be allocated.
2491  *
2492  * @returns new loader, or #NULL.
2493  */
2494 DBusMessageLoader*
2495 _dbus_message_loader_new (void)
2496 {
2497   DBusMessageLoader *loader;
2498
2499   loader = dbus_new0 (DBusMessageLoader, 1);
2500   if (loader == NULL)
2501     return NULL;
2502   
2503   loader->refcount = 1;
2504
2505   /* Try to cap message size at something that won't *totally* hose
2506    * the system if we have a couple of them.
2507    */
2508   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
2509   
2510   if (!_dbus_string_init (&loader->data))
2511     {
2512       dbus_free (loader);
2513       return NULL;
2514     }
2515
2516   /* preallocate the buffer for speed, ignore failure */
2517   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
2518   _dbus_string_set_length (&loader->data, 0);
2519   
2520   return loader;
2521 }
2522
2523 /**
2524  * Increments the reference count of the loader.
2525  *
2526  * @param loader the loader.
2527  */
2528 void
2529 _dbus_message_loader_ref (DBusMessageLoader *loader)
2530 {
2531   loader->refcount += 1;
2532 }
2533
2534 /**
2535  * Decrements the reference count of the loader and finalizes the
2536  * loader when the count reaches zero.
2537  *
2538  * @param loader the loader.
2539  */
2540 void
2541 _dbus_message_loader_unref (DBusMessageLoader *loader)
2542 {
2543   loader->refcount -= 1;
2544   if (loader->refcount == 0)
2545     {
2546       _dbus_list_foreach (&loader->messages,
2547                           (DBusForeachFunction) dbus_message_unref,
2548                           NULL);
2549       _dbus_list_clear (&loader->messages);
2550       _dbus_string_free (&loader->data);
2551       dbus_free (loader);
2552     }
2553 }
2554
2555 /**
2556  * Gets the buffer to use for reading data from the network.  Network
2557  * data is read directly into an allocated buffer, which is then used
2558  * in the DBusMessage, to avoid as many extra memcpy's as possible.
2559  * The buffer must always be returned immediately using
2560  * _dbus_message_loader_return_buffer(), even if no bytes are
2561  * successfully read.
2562  *
2563  * @todo this function can be a lot more clever. For example
2564  * it can probably always return a buffer size to read exactly
2565  * the body of the next message, thus avoiding any memory wastage
2566  * or reallocs.
2567  *
2568  * @todo we need to enforce a max length on strings in header fields.
2569  * 
2570  * @param loader the message loader.
2571  * @param buffer the buffer
2572  */
2573 void
2574 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
2575                                  DBusString        **buffer)
2576 {
2577   _dbus_assert (!loader->buffer_outstanding);
2578
2579   *buffer = &loader->data;
2580   
2581   loader->buffer_outstanding = TRUE;
2582 }
2583
2584 /**
2585  * The smallest header size that can occur. 
2586  * (It won't be valid)
2587  */
2588 #define DBUS_MINIMUM_HEADER_SIZE 16
2589
2590 /** Pack four characters as in "abcd" into a uint32 */
2591 #define FOUR_CHARS_TO_UINT32(a, b, c, d)                \
2592                       ((((dbus_uint32_t)a) << 24) |     \
2593                        (((dbus_uint32_t)b) << 16) |     \
2594                        (((dbus_uint32_t)c) << 8)  |     \
2595                        ((dbus_uint32_t)d))
2596
2597 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
2598 #define DBUS_HEADER_FIELD_NAME_AS_UINT32    \
2599   FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
2600
2601 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
2602 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
2603   FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
2604
2605 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
2606 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32   \
2607   FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
2608
2609 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
2610 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32  \
2611   FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
2612
2613 /* FIXME impose max length on name, srvc, sndr */
2614 static dbus_bool_t
2615 decode_header_data (const DBusString   *data,
2616                     int                 header_len,
2617                     int                 byte_order,
2618                     HeaderField         fields[FIELD_LAST],
2619                     int                *message_padding)
2620 {
2621   const char *field;
2622   int pos, new_pos;
2623   int i;
2624   
2625   if (header_len < 16)
2626     return FALSE;
2627   
2628   i = 0;
2629   while (i < FIELD_LAST)
2630     {
2631       fields[i].offset = -1;
2632       ++i;
2633     }
2634   
2635   fields[FIELD_HEADER_LENGTH].offset = 4;
2636   fields[FIELD_BODY_LENGTH].offset = 8;   
2637   fields[FIELD_CLIENT_SERIAL].offset = 12;
2638   
2639   /* Now handle the named fields. A real named field is at least 4
2640    * bytes for the name, plus a type code (1 byte) plus padding.  So
2641    * if we have less than 8 bytes left, it must be alignment padding,
2642    * not a field. While >= 8 bytes can't be entirely alignment
2643    * padding.
2644    */  
2645   pos = 16;
2646   while ((pos + 7) < header_len)
2647     {
2648       pos = _DBUS_ALIGN_VALUE (pos, 4);
2649       
2650       if ((pos + 4) > header_len)
2651         return FALSE;      
2652       
2653       field =_dbus_string_get_const_data_len (data, pos, 4);
2654       pos += 4;
2655
2656       _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
2657
2658       /* I believe FROM_BE is right, but if not we'll find out
2659        * I guess. ;-)
2660        */
2661       switch (DBUS_UINT32_FROM_BE (*(int*)field))
2662         {
2663         case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
2664           if (fields[FIELD_SERVICE].offset >= 0)
2665             {
2666               _dbus_verbose ("%s field provided twice\n",
2667                              DBUS_HEADER_FIELD_SERVICE);
2668               return FALSE;
2669             }
2670           
2671           fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2672 #if 0
2673           _dbus_verbose ("Found service name at offset %d\n",
2674                          fields[FIELD_SERVICE].offset);
2675 #endif
2676           break;
2677
2678         case DBUS_HEADER_FIELD_NAME_AS_UINT32:
2679           if (fields[FIELD_NAME].offset >= 0)
2680             {              
2681               _dbus_verbose ("%s field provided twice\n",
2682                              DBUS_HEADER_FIELD_NAME);
2683               return FALSE;
2684             }
2685           
2686           fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2687
2688 #if 0
2689           _dbus_verbose ("Found message name at offset %d\n",
2690                          fields[FIELD_NAME].offset);
2691 #endif
2692           break;
2693         case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
2694           if (fields[FIELD_SENDER].offset >= 0)
2695             {
2696               _dbus_verbose ("%s field provided twice\n",
2697                              DBUS_HEADER_FIELD_SENDER);
2698               return FALSE;
2699             }
2700           
2701           fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2702
2703           _dbus_verbose ("Found sender name at offset %d\n",
2704                          fields[FIELD_NAME].offset);
2705           break;
2706           
2707         case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
2708           if (fields[FIELD_REPLY_SERIAL].offset >= 0)
2709             {
2710               _dbus_verbose ("%s field provided twice\n",
2711                              DBUS_HEADER_FIELD_REPLY);
2712               return FALSE;
2713             }
2714           
2715           fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2716
2717           _dbus_verbose ("Found reply serial at offset %d\n",
2718                          fields[FIELD_REPLY_SERIAL].offset);
2719           break;
2720
2721         default:
2722           _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c at offset %d\n",
2723                          field[0], field[1], field[2], field[3], pos);
2724         }
2725
2726       if (!_dbus_marshal_validate_arg (data, byte_order, pos, &new_pos))
2727         {
2728           _dbus_verbose ("Failed to validate argument to named header field\n");
2729           return FALSE;
2730         }
2731
2732       if (new_pos > header_len)
2733         {
2734           _dbus_verbose ("Named header field tries to extend beyond header length\n");
2735           return FALSE;
2736         }
2737       
2738       pos = new_pos;
2739     }
2740
2741   if (pos < header_len)
2742     {
2743       /* Alignment padding, verify that it's nul */
2744       _dbus_assert ((header_len - pos) < 8);
2745
2746       if (!_dbus_string_validate_nul (data,
2747                                       pos, (header_len - pos)))
2748         {
2749           _dbus_verbose ("header alignment padding is not nul\n");
2750           return FALSE;
2751         }
2752     }
2753
2754  if (fields[FIELD_NAME].offset < 0)
2755    {
2756      _dbus_verbose ("No %s field provided\n",
2757                     DBUS_HEADER_FIELD_NAME);
2758      return FALSE;
2759    }
2760   
2761   if (message_padding)
2762     *message_padding = header_len - pos;  
2763   
2764   return TRUE;
2765 }
2766
2767 /**
2768  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
2769  * indicating to the loader how many bytes of the buffer were filled
2770  * in. This function must always be called, even if no bytes were
2771  * successfully read.
2772  *
2773  * @param loader the loader.
2774  * @param buffer the buffer.
2775  * @param bytes_read number of bytes that were read into the buffer.
2776  */
2777 void
2778 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
2779                                     DBusString         *buffer,
2780                                     int                 bytes_read)
2781 {
2782   _dbus_assert (loader->buffer_outstanding);
2783   _dbus_assert (buffer == &loader->data);
2784
2785   loader->buffer_outstanding = FALSE;
2786 }
2787
2788 /**
2789  * Converts buffered data into messages.
2790  *
2791  * @param loader the loader.
2792  * @returns #TRUE if we had enough memory to finish.
2793  */
2794 dbus_bool_t
2795 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
2796 {
2797   if (loader->corrupted)
2798     return TRUE;
2799
2800   while (_dbus_string_get_length (&loader->data) >= 16)
2801     {
2802       DBusMessage *message;      
2803       const char *header_data;
2804       int byte_order, header_len, body_len, header_padding;
2805       dbus_uint32_t header_len_unsigned, body_len_unsigned;
2806       
2807       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
2808
2809       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
2810
2811       if (header_data[2] != DBUS_MAJOR_PROTOCOL_VERSION)
2812         {
2813           _dbus_verbose ("Message has protocol version %d ours is %d\n",
2814                          (int) header_data[2], DBUS_MAJOR_PROTOCOL_VERSION);
2815           loader->corrupted = TRUE;
2816           return TRUE;
2817         }
2818       
2819       byte_order = header_data[0];
2820
2821       if (byte_order != DBUS_LITTLE_ENDIAN &&
2822           byte_order != DBUS_BIG_ENDIAN)
2823         {
2824           _dbus_verbose ("Message with bad byte order '%c' received\n",
2825                          byte_order);
2826           loader->corrupted = TRUE;
2827           return TRUE;
2828         }
2829
2830       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
2831       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
2832
2833       if (header_len_unsigned < 16)
2834         {
2835           _dbus_verbose ("Message had broken too-small header length %u\n",
2836                          header_len_unsigned);
2837           loader->corrupted = TRUE;
2838           return TRUE;
2839         }
2840
2841       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
2842           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
2843         {
2844           _dbus_verbose ("Header or body length too large (%u %u)\n",
2845                          header_len_unsigned,
2846                          body_len_unsigned);
2847           loader->corrupted = TRUE;
2848           return TRUE;
2849         }
2850
2851       /* Now that we know the values are in signed range, get
2852        * rid of stupid unsigned, just causes bugs
2853        */
2854       header_len = header_len_unsigned;
2855       body_len = body_len_unsigned;
2856
2857       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
2858         {
2859           
2860           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
2861                          header_len);
2862           loader->corrupted = TRUE;
2863           return TRUE;
2864         }
2865       
2866       if (header_len + body_len > loader->max_message_size)
2867         {
2868           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
2869                          header_len, body_len, loader->max_message_size);
2870           loader->corrupted = TRUE;
2871           return TRUE;
2872         }
2873
2874       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
2875         {
2876           HeaderField fields[FIELD_LAST];
2877           int i;
2878           int next_arg;          
2879
2880 #if 0
2881           _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);
2882 #endif    
2883           if (!decode_header_data (&loader->data, header_len, byte_order,
2884                                    fields, &header_padding))
2885             {
2886               _dbus_verbose ("Header was invalid\n");
2887               loader->corrupted = TRUE;
2888               return TRUE;
2889             }
2890           
2891           next_arg = header_len;
2892           while (next_arg < (header_len + body_len))
2893             {
2894               int prev = next_arg;
2895
2896               if (!_dbus_marshal_validate_arg (&loader->data,
2897                                                byte_order,
2898                                                next_arg,
2899                                                &next_arg))
2900                 {
2901                   loader->corrupted = TRUE;
2902                   return TRUE;
2903                 }
2904
2905               _dbus_assert (next_arg > prev);
2906             }
2907           
2908           if (next_arg > (header_len + body_len))
2909             {
2910               _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
2911                              next_arg, header_len, body_len,
2912                              header_len + body_len);
2913               loader->corrupted = TRUE;
2914               return TRUE;
2915             }
2916
2917           message = dbus_message_new_empty_header ();
2918           if (message == NULL)
2919             return FALSE;
2920
2921           message->byte_order = byte_order;
2922           message->header_padding = header_padding;
2923           
2924           /* Copy in the offsets we found */
2925           i = 0;
2926           while (i < FIELD_LAST)
2927             {
2928               message->header_fields[i] = fields[i];
2929               ++i;
2930             }
2931           
2932           if (!_dbus_list_append (&loader->messages, message))
2933             {
2934               dbus_message_unref (message);
2935               return FALSE;
2936             }
2937
2938           _dbus_assert (_dbus_string_get_length (&message->header) == 0);
2939           _dbus_assert (_dbus_string_get_length (&message->body) == 0);
2940
2941           _dbus_assert (_dbus_string_get_length (&loader->data) >=
2942                         (header_len + body_len));
2943           
2944           if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
2945             {
2946               _dbus_list_remove_last (&loader->messages, message);
2947               dbus_message_unref (message);
2948               return FALSE;
2949             }
2950           
2951           if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
2952             {
2953               dbus_bool_t result;
2954
2955               /* put the header back, we'll try again later */
2956               result = _dbus_string_copy_len (&message->header, 0, header_len,
2957                                               &loader->data, 0);
2958               _dbus_assert (result); /* because DBusString never reallocs smaller */
2959
2960               _dbus_list_remove_last (&loader->messages, message);
2961               dbus_message_unref (message);
2962               return FALSE;
2963             }
2964
2965           _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
2966           _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
2967
2968           /* Fill in caches */
2969           message->reply_serial = get_int_field (message,
2970                                                  FIELD_REPLY_SERIAL);
2971           message->client_serial = get_int_field (message,
2972                                                   FIELD_CLIENT_SERIAL);
2973           
2974           _dbus_verbose ("Loaded message %p\n", message);
2975         }
2976       else
2977         return TRUE;
2978     }
2979
2980   return TRUE;
2981 }
2982
2983 /**
2984  * Peeks at first loaded message, returns #NULL if no messages have
2985  * been queued.
2986  *
2987  * @param loader the loader.
2988  * @returns the next message, or #NULL if none.
2989  */
2990 DBusMessage*
2991 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
2992 {
2993   if (loader->messages)
2994     return loader->messages->data;
2995   else
2996     return NULL;
2997 }
2998
2999 /**
3000  * Pops a loaded message (passing ownership of the message
3001  * to the caller). Returns #NULL if no messages have been
3002  * queued.
3003  *
3004  * @param loader the loader.
3005  * @returns the next message, or #NULL if none.
3006  */
3007 DBusMessage*
3008 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
3009 {
3010   return _dbus_list_pop_first (&loader->messages);
3011 }
3012
3013 /**
3014  * Pops a loaded message inside a list link (passing ownership of the
3015  * message and link to the caller). Returns #NULL if no messages have
3016  * been loaded.
3017  *
3018  * @param loader the loader.
3019  * @returns the next message link, or #NULL if none.
3020  */
3021 DBusList*
3022 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
3023 {
3024   return _dbus_list_pop_first_link (&loader->messages);
3025 }
3026
3027 /**
3028  * Checks whether the loader is confused due to bad data.
3029  * If messages are received that are invalid, the
3030  * loader gets confused and gives up permanently.
3031  * This state is called "corrupted."
3032  *
3033  * @param loader the loader
3034  * @returns #TRUE if the loader is hosed.
3035  */
3036 dbus_bool_t
3037 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
3038 {
3039   return loader->corrupted;
3040 }
3041
3042 /**
3043  * Sets the maximum size message we allow.
3044  *
3045  * @param loader the loader
3046  * @param size the max message size in bytes
3047  */
3048 void
3049 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
3050                                            long                size)
3051 {
3052   if (size > MAX_SANE_MESSAGE_SIZE)
3053     {
3054       _dbus_verbose ("clamping requested max message size %ld to %d\n",
3055                      size, MAX_SANE_MESSAGE_SIZE);
3056       size = MAX_SANE_MESSAGE_SIZE;
3057     }
3058   loader->max_message_size = size;
3059 }
3060
3061 /**
3062  * Gets the maximum allowed message size in bytes.
3063  *
3064  * @param loader the loader
3065  * @returns max size in bytes
3066  */
3067 long
3068 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
3069 {
3070   return loader->max_message_size;
3071 }
3072
3073 /** @} */
3074 #ifdef DBUS_BUILD_TESTS
3075 #include "dbus-test.h"
3076 #include <stdio.h>
3077
3078 static void
3079 message_iter_test (DBusMessage *message)
3080 {
3081   DBusMessageIter *iter;
3082   char *str;
3083   
3084   iter = dbus_message_get_args_iter (message);
3085
3086   /* String tests */
3087   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRING)
3088     _dbus_assert_not_reached ("Argument type isn't string");
3089
3090   str = dbus_message_iter_get_string (iter);
3091   if (strcmp (str, "Test string") != 0)
3092     _dbus_assert_not_reached ("Strings differ");
3093   dbus_free (str);
3094
3095   if (!dbus_message_iter_next (iter))
3096     _dbus_assert_not_reached ("Reached end of arguments");
3097
3098   /* Signed integer tests */
3099   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT32)
3100     _dbus_assert_not_reached ("Argument type isn't int32");
3101
3102   if (dbus_message_iter_get_int32 (iter) != -0x12345678)
3103     _dbus_assert_not_reached ("Signed integers differ");
3104
3105   if (!dbus_message_iter_next (iter))
3106     _dbus_assert_not_reached ("Reached end of fields");
3107   
3108   /* Unsigned integer tests */
3109   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT32)
3110     _dbus_assert_not_reached ("Argument type isn't int32");
3111
3112   if (dbus_message_iter_get_uint32 (iter) != 0xedd1e)
3113     _dbus_assert_not_reached ("Unsigned integers differ");
3114
3115   if (!dbus_message_iter_next (iter))
3116     _dbus_assert_not_reached ("Reached end of arguments");
3117
3118   /* Double tests */
3119   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_DOUBLE)
3120     _dbus_assert_not_reached ("Argument type isn't double");
3121
3122   if (dbus_message_iter_get_double (iter) != 3.14159)
3123     _dbus_assert_not_reached ("Doubles differ");
3124
3125   if (dbus_message_iter_next (iter))
3126     _dbus_assert_not_reached ("Didn't reach end of arguments");
3127   
3128   dbus_message_iter_unref (iter);
3129 }
3130
3131 static dbus_bool_t
3132 check_message_handling (DBusMessage *message)
3133 {
3134   DBusMessageIter *iter;
3135   int type;
3136   dbus_bool_t retval;
3137   dbus_int32_t client_serial;
3138   
3139   retval = FALSE;
3140   iter = NULL;
3141   
3142   client_serial = dbus_message_get_serial (message);
3143
3144   /* can't use set_serial due to the assertions at the start of it */
3145   set_int_field (message, FIELD_CLIENT_SERIAL,
3146                  client_serial);
3147   
3148   if (client_serial != dbus_message_get_serial (message))
3149     {
3150       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
3151       goto failed;
3152     }
3153   
3154   /* If we implement message_set_arg (message, n, value)
3155    * then we would want to test it here
3156    */
3157
3158   iter = dbus_message_get_args_iter (message);
3159   while ((type = dbus_message_iter_get_arg_type (iter)) != DBUS_TYPE_INVALID)
3160     {
3161       switch (type)
3162         {
3163         case DBUS_TYPE_NIL:
3164           break;
3165         case DBUS_TYPE_INT32:
3166           dbus_message_iter_get_int32 (iter);
3167           break;
3168         case DBUS_TYPE_UINT32:
3169           dbus_message_iter_get_uint32 (iter);
3170           break;
3171         case DBUS_TYPE_DOUBLE:
3172           dbus_message_iter_get_double (iter);
3173           break;
3174         case DBUS_TYPE_STRING:
3175           {
3176             char *str;
3177             str = dbus_message_iter_get_string (iter);
3178             dbus_free (str);
3179           }
3180           break;
3181         case DBUS_TYPE_BOOLEAN_ARRAY:
3182           {
3183             unsigned char *values;
3184             int len;
3185             
3186             if (!dbus_message_iter_get_boolean_array (iter, &values, &len))
3187               return FALSE;
3188
3189             dbus_free (values);
3190           }
3191           break;
3192         case DBUS_TYPE_INT32_ARRAY:
3193           {
3194             dbus_int32_t *values;
3195             int len;
3196             
3197             if (!dbus_message_iter_get_int32_array (iter, &values, &len))
3198               return FALSE;
3199
3200             dbus_free (values);
3201           }
3202           break;
3203         case DBUS_TYPE_UINT32_ARRAY:
3204           {
3205             dbus_uint32_t *values;
3206             int len;
3207             
3208             if (!dbus_message_iter_get_uint32_array (iter, &values, &len))
3209               return FALSE;
3210
3211             dbus_free (values);
3212           }
3213           break;
3214         case DBUS_TYPE_DOUBLE_ARRAY:
3215           {
3216             double *values;
3217             int len;
3218             
3219             if (!dbus_message_iter_get_double_array (iter, &values, &len))
3220               return FALSE;
3221
3222             dbus_free (values);
3223           }
3224           break;
3225         case DBUS_TYPE_STRING_ARRAY:
3226           {
3227             char **values;
3228             int len;
3229             
3230             if (!dbus_message_iter_get_string_array (iter, &values, &len))
3231               return FALSE;
3232
3233             dbus_free_string_array (values);
3234           }
3235           break;
3236
3237         case DBUS_TYPE_DICT:
3238           {
3239             DBusDict *dict;
3240
3241             if (!dbus_message_iter_get_dict (iter, &dict))
3242               return FALSE;
3243             dbus_dict_unref (dict);
3244           }
3245           break;
3246
3247         default:
3248           break;
3249         }
3250       
3251       if (!dbus_message_iter_next (iter))
3252         break;
3253     }
3254
3255   retval = TRUE;
3256   
3257  failed:
3258   if (iter)
3259     dbus_message_iter_unref (iter);
3260
3261   return retval;
3262 }
3263
3264 static dbus_bool_t
3265 check_have_valid_message (DBusMessageLoader *loader)
3266 {
3267   DBusMessage *message;
3268   dbus_bool_t retval;
3269
3270   message = NULL;
3271   retval = FALSE;
3272
3273   if (!_dbus_message_loader_queue_messages (loader))
3274     _dbus_assert_not_reached ("no memory to queue messages");
3275   
3276   if (_dbus_message_loader_get_is_corrupted (loader))
3277     {
3278       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
3279       goto failed;
3280     }
3281   
3282   message = _dbus_message_loader_pop_message (loader);
3283   if (message == NULL)
3284     {
3285       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
3286       goto failed;
3287     }
3288   
3289   if (_dbus_string_get_length (&loader->data) > 0)
3290     {
3291       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
3292       goto failed;
3293     }
3294
3295   /* Verify that we're able to properly deal with the message.
3296    * For example, this would detect improper handling of messages
3297    * in nonstandard byte order.
3298    */
3299   if (!check_message_handling (message))
3300     goto failed;  
3301   
3302   retval = TRUE;
3303
3304  failed:
3305   if (message)
3306     dbus_message_unref (message);
3307
3308   return retval;
3309 }
3310
3311 static dbus_bool_t
3312 check_invalid_message (DBusMessageLoader *loader)
3313 {
3314   dbus_bool_t retval;
3315
3316   retval = FALSE;
3317
3318   if (!_dbus_message_loader_queue_messages (loader))
3319     _dbus_assert_not_reached ("no memory to queue messages");
3320   
3321   if (!_dbus_message_loader_get_is_corrupted (loader))
3322     {
3323       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
3324       goto failed;
3325     }
3326
3327   retval = TRUE;
3328
3329  failed:
3330   return retval;
3331 }
3332
3333 static dbus_bool_t
3334 check_incomplete_message (DBusMessageLoader *loader)
3335 {
3336   DBusMessage *message;
3337   dbus_bool_t retval;
3338
3339   message = NULL;
3340   retval = FALSE;
3341
3342   if (!_dbus_message_loader_queue_messages (loader))
3343     _dbus_assert_not_reached ("no memory to queue messages");
3344   
3345   if (_dbus_message_loader_get_is_corrupted (loader))
3346     {
3347       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
3348       goto failed;
3349     }
3350   
3351   message = _dbus_message_loader_pop_message (loader);
3352   if (message != NULL)
3353     {
3354       _dbus_warn ("loaded message that was expected to be incomplete\n");
3355       goto failed;
3356     }
3357
3358   retval = TRUE;
3359
3360  failed:
3361   if (message)
3362     dbus_message_unref (message);
3363   return retval;
3364 }
3365
3366 static dbus_bool_t
3367 check_loader_results (DBusMessageLoader      *loader,
3368                       DBusMessageValidity     validity)
3369 {
3370   if (!_dbus_message_loader_queue_messages (loader))
3371     _dbus_assert_not_reached ("no memory to queue messages");
3372   
3373   switch (validity)
3374     {
3375     case _DBUS_MESSAGE_VALID:
3376       return check_have_valid_message (loader);
3377     case _DBUS_MESSAGE_INVALID:
3378       return check_invalid_message (loader);
3379     case _DBUS_MESSAGE_INCOMPLETE:
3380       return check_incomplete_message (loader);
3381     case _DBUS_MESSAGE_UNKNOWN:
3382       return TRUE;
3383     }
3384
3385   _dbus_assert_not_reached ("bad DBusMessageValidity");
3386   return FALSE;
3387 }
3388
3389
3390 /**
3391  * Loads the message in the given message file.
3392  *
3393  * @param filename filename to load
3394  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
3395  * @param data string to load message into
3396  * @returns #TRUE if the message was loaded
3397  */
3398 dbus_bool_t
3399 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
3400                                             dbus_bool_t          is_raw,
3401                                             DBusString          *data)
3402 {
3403   dbus_bool_t retval;
3404
3405   retval = FALSE;  
3406
3407   if (is_raw)
3408     {
3409       DBusError error;
3410
3411       dbus_error_init (&error);
3412       if (!_dbus_file_get_contents (data, filename, &error))
3413         {
3414           _dbus_warn ("Could not load message file %s: %s\n",
3415                       _dbus_string_get_const_data (filename),
3416                       error.message);
3417           dbus_error_free (&error);
3418           goto failed;
3419         }
3420     }
3421   else
3422     {
3423       if (!_dbus_message_data_load (data, filename))
3424         {
3425           _dbus_warn ("Could not load message file %s\n",
3426                       _dbus_string_get_const_data (filename));
3427           goto failed;
3428         }
3429     }
3430
3431   retval = TRUE;
3432   
3433  failed:
3434
3435   return retval;
3436 }
3437
3438 /**
3439  * Tries loading the message in the given message file
3440  * and verifies that DBusMessageLoader can handle it.
3441  *
3442  * @param filename filename to load
3443  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
3444  * @param expected_validity what the message has to be like to return #TRUE
3445  * @returns #TRUE if the message has the expected validity
3446  */
3447 dbus_bool_t
3448 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
3449                                            dbus_bool_t          is_raw,
3450                                            DBusMessageValidity  expected_validity)
3451 {
3452   DBusString data;
3453   dbus_bool_t retval;
3454
3455   retval = FALSE;
3456   
3457   if (!_dbus_string_init (&data))
3458     _dbus_assert_not_reached ("could not allocate string\n");
3459
3460   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
3461                                                    &data))
3462     goto failed;
3463
3464   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
3465
3466  failed:
3467
3468   if (!retval)
3469     {
3470       if (_dbus_string_get_length (&data) > 0)
3471         _dbus_verbose_bytes_of_string (&data, 0,
3472                                        _dbus_string_get_length (&data));
3473       
3474       _dbus_warn ("Failed message loader test on %s\n",
3475                   _dbus_string_get_const_data (filename));
3476     }
3477   
3478   _dbus_string_free (&data);
3479
3480   return retval;
3481 }
3482
3483 /**
3484  * Tries loading the given message data.
3485  *
3486  *
3487  * @param data the message data
3488  * @param expected_validity what the message has to be like to return #TRUE
3489  * @returns #TRUE if the message has the expected validity
3490  */
3491 dbus_bool_t
3492 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
3493                                            DBusMessageValidity  expected_validity)
3494 {
3495   DBusMessageLoader *loader;
3496   dbus_bool_t retval;
3497   int len;
3498   int i;
3499
3500   loader = NULL;
3501   retval = FALSE;
3502
3503   /* Write the data one byte at a time */
3504   
3505   loader = _dbus_message_loader_new ();
3506
3507   len = _dbus_string_get_length (data);
3508   for (i = 0; i < len; i++)
3509     {
3510       DBusString *buffer;
3511
3512       _dbus_message_loader_get_buffer (loader, &buffer);
3513       _dbus_string_append_byte (buffer,
3514                                 _dbus_string_get_byte (data, i));
3515       _dbus_message_loader_return_buffer (loader, buffer, 1);
3516     }
3517   
3518   if (!check_loader_results (loader, expected_validity))
3519     goto failed;
3520
3521   _dbus_message_loader_unref (loader);
3522   loader = NULL;
3523
3524   /* Write the data all at once */
3525   
3526   loader = _dbus_message_loader_new ();
3527
3528   {
3529     DBusString *buffer;
3530     
3531     _dbus_message_loader_get_buffer (loader, &buffer);
3532     _dbus_string_copy (data, 0, buffer,
3533                        _dbus_string_get_length (buffer));
3534     _dbus_message_loader_return_buffer (loader, buffer, 1);
3535   }
3536   
3537   if (!check_loader_results (loader, expected_validity))
3538     goto failed;
3539
3540   _dbus_message_loader_unref (loader);
3541   loader = NULL;  
3542
3543   /* Write the data 2 bytes at a time */
3544   
3545   loader = _dbus_message_loader_new ();
3546
3547   len = _dbus_string_get_length (data);
3548   for (i = 0; i < len; i += 2)
3549     {
3550       DBusString *buffer;
3551
3552       _dbus_message_loader_get_buffer (loader, &buffer);
3553       _dbus_string_append_byte (buffer,
3554                                 _dbus_string_get_byte (data, i));
3555       if ((i+1) < len)
3556         _dbus_string_append_byte (buffer,
3557                                   _dbus_string_get_byte (data, i+1));
3558       _dbus_message_loader_return_buffer (loader, buffer, 1);
3559     }
3560   
3561   if (!check_loader_results (loader, expected_validity))
3562     goto failed;
3563
3564   _dbus_message_loader_unref (loader);
3565   loader = NULL;
3566   
3567   retval = TRUE;
3568   
3569  failed:
3570   
3571   if (loader)
3572     _dbus_message_loader_unref (loader);
3573   
3574   return retval;
3575 }
3576
3577 static dbus_bool_t
3578 process_test_subdir (const DBusString          *test_base_dir,
3579                      const char                *subdir,
3580                      DBusMessageValidity        validity,
3581                      DBusForeachMessageFileFunc function,
3582                      void                      *user_data)
3583 {
3584   DBusString test_directory;
3585   DBusString filename;
3586   DBusDirIter *dir;
3587   dbus_bool_t retval;
3588   DBusError error;
3589
3590   retval = FALSE;
3591   dir = NULL;
3592   
3593   if (!_dbus_string_init (&test_directory))
3594     _dbus_assert_not_reached ("didn't allocate test_directory\n");
3595
3596   _dbus_string_init_const (&filename, subdir);
3597   
3598   if (!_dbus_string_copy (test_base_dir, 0,
3599                           &test_directory, 0))
3600     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
3601   
3602   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
3603     _dbus_assert_not_reached ("couldn't allocate full path");
3604
3605   _dbus_string_free (&filename);
3606   if (!_dbus_string_init (&filename))
3607     _dbus_assert_not_reached ("didn't allocate filename string\n");
3608
3609   dbus_error_init (&error);
3610   dir = _dbus_directory_open (&test_directory, &error);
3611   if (dir == NULL)
3612     {
3613       _dbus_warn ("Could not open %s: %s\n",
3614                   _dbus_string_get_const_data (&test_directory),
3615                   error.message);
3616       dbus_error_free (&error);
3617       goto failed;
3618     }
3619
3620   printf ("Testing:\n");
3621   
3622  next:
3623   while (_dbus_directory_get_next_file (dir, &filename, &error))
3624     {
3625       DBusString full_path;
3626       dbus_bool_t is_raw;
3627       
3628       if (!_dbus_string_init (&full_path))
3629         _dbus_assert_not_reached ("couldn't init string");
3630
3631       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
3632         _dbus_assert_not_reached ("couldn't copy dir to full_path");
3633
3634       if (!_dbus_concat_dir_and_file (&full_path, &filename))
3635         _dbus_assert_not_reached ("couldn't concat file to dir");
3636
3637       if (_dbus_string_ends_with_c_str (&filename, ".message"))
3638         is_raw = FALSE;
3639       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
3640         is_raw = TRUE;
3641       else
3642         {
3643           _dbus_verbose ("Skipping non-.message file %s\n",
3644                          _dbus_string_get_const_data (&filename));
3645           _dbus_string_free (&full_path);
3646           goto next;
3647         }
3648
3649       printf ("    %s\n",
3650               _dbus_string_get_const_data (&filename));
3651       
3652       _dbus_verbose (" expecting %s\n",
3653                      validity == _DBUS_MESSAGE_VALID ? "valid" :
3654                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
3655                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")));
3656       
3657       if (! (*function) (&full_path, is_raw, validity, user_data))
3658         {
3659           _dbus_string_free (&full_path);
3660           goto failed;
3661         }
3662       else
3663         _dbus_string_free (&full_path);
3664     }
3665
3666   if (dbus_error_is_set (&error))
3667     {
3668       _dbus_warn ("Could not get next file in %s: %s\n",
3669                   _dbus_string_get_const_data (&test_directory),
3670                   error.message);
3671       dbus_error_free (&error);
3672       goto failed;
3673     }
3674     
3675   retval = TRUE;
3676   
3677  failed:
3678
3679   if (dir)
3680     _dbus_directory_close (dir);
3681   _dbus_string_free (&test_directory);
3682   _dbus_string_free (&filename);
3683
3684   return retval;
3685 }
3686                      
3687 /**
3688  * Runs the given function on every message file in the test suite.
3689  * The function should return #FALSE on test failure or fatal error.
3690  *
3691  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
3692  * @param func the function to run
3693  * @param user_data data for function
3694  * @returns #FALSE if there's a failure
3695  */
3696 dbus_bool_t
3697 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
3698                                                DBusForeachMessageFileFunc func,
3699                                                void                      *user_data)
3700 {
3701   DBusString test_directory;
3702   dbus_bool_t retval;
3703
3704   retval = FALSE;
3705   
3706   _dbus_string_init_const (&test_directory, test_data_dir);
3707
3708   if (!process_test_subdir (&test_directory, "valid-messages",
3709                             _DBUS_MESSAGE_VALID, func, user_data))
3710     goto failed;
3711
3712   if (!process_test_subdir (&test_directory, "invalid-messages",
3713                             _DBUS_MESSAGE_INVALID, func, user_data))
3714     goto failed;
3715   
3716   if (!process_test_subdir (&test_directory, "incomplete-messages",
3717                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
3718     goto failed;
3719
3720   retval = TRUE;
3721   
3722  failed:
3723
3724   _dbus_string_free (&test_directory);
3725   
3726   return retval;
3727 }
3728
3729 static void
3730 verify_test_message (DBusMessage *message)
3731 {
3732   dbus_int32_t our_int;
3733   char *our_str;
3734   double our_double;
3735   dbus_bool_t our_bool;
3736   
3737   if (!dbus_message_get_args (message, NULL,
3738                               DBUS_TYPE_INT32, &our_int,
3739                               DBUS_TYPE_STRING, &our_str,
3740                               DBUS_TYPE_DOUBLE, &our_double,
3741                               DBUS_TYPE_BOOLEAN, &our_bool,
3742                               0))
3743     _dbus_assert_not_reached ("Could not get arguments");
3744
3745   if (our_int != -0x12345678)
3746     _dbus_assert_not_reached ("integers differ!");
3747
3748   if (our_double != 3.14159)
3749     _dbus_assert_not_reached ("doubles differ!");
3750
3751   if (strcmp (our_str, "Test string") != 0)
3752     _dbus_assert_not_reached ("strings differ!");
3753
3754   if (!our_bool)
3755     _dbus_assert_not_reached ("booleans differ");
3756   
3757   dbus_free (our_str);
3758 }
3759
3760 /**
3761  * @ingroup DBusMessageInternals
3762  * Unit test for DBusMessage.
3763  *
3764  * @returns #TRUE on success.
3765  */
3766 dbus_bool_t
3767 _dbus_message_test (const char *test_data_dir)
3768 {
3769   DBusMessage *message;
3770   DBusMessageLoader *loader;
3771   int i;
3772   const char *data;
3773   DBusMessage *copy;
3774   const char *name1;
3775   const char *name2;
3776   
3777   /* Test the vararg functions */
3778   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
3779   _dbus_message_set_serial (message, 1);
3780   dbus_message_append_args (message,
3781                             DBUS_TYPE_INT32, -0x12345678,
3782                             DBUS_TYPE_STRING, "Test string",
3783                             DBUS_TYPE_DOUBLE, 3.14159,
3784                             DBUS_TYPE_BOOLEAN, TRUE,
3785                             0);
3786   _dbus_verbose_bytes_of_string (&message->header, 0,
3787                                  _dbus_string_get_length (&message->header));
3788   _dbus_verbose_bytes_of_string (&message->body, 0,
3789                                  _dbus_string_get_length (&message->body));
3790
3791   verify_test_message (message);
3792
3793   copy = dbus_message_copy (message);
3794   
3795   _dbus_assert (message->client_serial == copy->client_serial);
3796   _dbus_assert (message->reply_serial == copy->reply_serial);
3797   _dbus_assert (message->header_padding == copy->header_padding);
3798   
3799   _dbus_assert (_dbus_string_get_length (&message->header) ==
3800                 _dbus_string_get_length (&copy->header));
3801
3802   _dbus_assert (_dbus_string_get_length (&message->body) ==
3803                 _dbus_string_get_length (&copy->body));
3804
3805   verify_test_message (copy);
3806
3807   name1 = dbus_message_get_name (message);
3808   name2 = dbus_message_get_name (copy);
3809
3810   _dbus_assert (strcmp (name1, name2) == 0);
3811   
3812   dbus_message_unref (message);
3813   dbus_message_unref (copy);
3814   
3815   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
3816   _dbus_message_set_serial (message, 1);
3817   dbus_message_set_reply_serial (message, 0x12345678);
3818
3819   dbus_message_append_string (message, "Test string");
3820   dbus_message_append_int32 (message, -0x12345678);
3821   dbus_message_append_uint32 (message, 0xedd1e);
3822   dbus_message_append_double (message, 3.14159);
3823
3824   message_iter_test (message);
3825
3826   /* Message loader test */
3827   _dbus_message_lock (message);
3828   loader = _dbus_message_loader_new ();
3829
3830   /* Write the header data one byte at a time */
3831   data = _dbus_string_get_const_data (&message->header);
3832   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
3833     {
3834       DBusString *buffer;
3835
3836       _dbus_message_loader_get_buffer (loader, &buffer);
3837       _dbus_string_append_byte (buffer, data[i]);
3838       _dbus_message_loader_return_buffer (loader, buffer, 1);
3839     }
3840
3841   /* Write the body data one byte at a time */
3842   data = _dbus_string_get_const_data (&message->body);
3843   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
3844     {
3845       DBusString *buffer;
3846
3847       _dbus_message_loader_get_buffer (loader, &buffer);
3848       _dbus_string_append_byte (buffer, data[i]);
3849       _dbus_message_loader_return_buffer (loader, buffer, 1);
3850     }
3851
3852   dbus_message_unref (message);
3853
3854   /* Now pop back the message */
3855   if (!_dbus_message_loader_queue_messages (loader))
3856     _dbus_assert_not_reached ("no memory to queue messages");
3857   
3858   if (_dbus_message_loader_get_is_corrupted (loader))
3859     _dbus_assert_not_reached ("message loader corrupted");
3860   
3861   message = _dbus_message_loader_pop_message (loader);
3862   if (!message)
3863     _dbus_assert_not_reached ("received a NULL message");
3864
3865   if (dbus_message_get_reply_serial (message) != 0x12345678)
3866     _dbus_assert_not_reached ("reply serial fields differ");
3867   
3868   message_iter_test (message);
3869   
3870   dbus_message_unref (message);
3871   _dbus_message_loader_unref (loader);
3872
3873   /* Now load every message in test_data_dir if we have one */
3874   if (test_data_dir == NULL)
3875     return TRUE;
3876
3877   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
3878                                                         (DBusForeachMessageFileFunc)
3879                                                         dbus_internal_do_not_use_try_message_file,
3880                                                         NULL);
3881 }
3882
3883 #endif /* DBUS_BUILD_TESTS */