2003-03-31 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
2386 /**
2387  * @addtogroup DBusMessageInternals
2388  *
2389  * @{
2390  */
2391 /**
2392  * @typedef DBusMessageLoader
2393  *
2394  * The DBusMessageLoader object encapsulates the process of converting
2395  * a byte stream into a series of DBusMessage. It buffers the incoming
2396  * bytes as efficiently as possible, and generates a queue of
2397  * messages. DBusMessageLoader is typically used as part of a
2398  * DBusTransport implementation. The DBusTransport then hands off
2399  * the loaded messages to a DBusConnection, making the messages
2400  * visible to the application.
2401  *
2402  * @todo write tests for break-loader that a) randomly delete header
2403  * fields and b) set string fields to zero-length and other funky
2404  * values.
2405  * 
2406  */
2407
2408 /* we definitely use signed ints for sizes, so don't exceed
2409  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
2410  * over 128M is pretty nuts anyhow.
2411  */
2412
2413 /**
2414  * The maximum sane message size.
2415  */
2416 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
2417
2418 /**
2419  * Implementation details of DBusMessageLoader.
2420  * All members are private.
2421  */
2422 struct DBusMessageLoader
2423 {
2424   int refcount;        /**< Reference count. */
2425
2426   DBusString data;     /**< Buffered data */
2427   
2428   DBusList *messages;  /**< Complete messages. */
2429
2430   long max_message_size; /**< Maximum size of a message */
2431   
2432   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
2433
2434   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
2435 };
2436
2437 /**
2438  * The initial buffer size of the message loader.
2439  * 
2440  * @todo this should be based on min header size plus some average
2441  * body size, or something. Or rather, the min header size only, if we
2442  * want to try to read only the header, store that in a DBusMessage,
2443  * then read only the body and store that, etc., depends on
2444  * how we optimize _dbus_message_loader_get_buffer() and what
2445  * the exact message format is.
2446  */
2447 #define INITIAL_LOADER_DATA_LEN 32
2448
2449 /**
2450  * Creates a new message loader. Returns #NULL if memory can't
2451  * be allocated.
2452  *
2453  * @returns new loader, or #NULL.
2454  */
2455 DBusMessageLoader*
2456 _dbus_message_loader_new (void)
2457 {
2458   DBusMessageLoader *loader;
2459
2460   loader = dbus_new0 (DBusMessageLoader, 1);
2461   if (loader == NULL)
2462     return NULL;
2463   
2464   loader->refcount = 1;
2465
2466   /* Try to cap message size at something that won't *totally* hose
2467    * the system if we have a couple of them.
2468    */
2469   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
2470   
2471   if (!_dbus_string_init (&loader->data))
2472     {
2473       dbus_free (loader);
2474       return NULL;
2475     }
2476
2477   /* preallocate the buffer for speed, ignore failure */
2478   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
2479   _dbus_string_set_length (&loader->data, 0);
2480   
2481   return loader;
2482 }
2483
2484 /**
2485  * Increments the reference count of the loader.
2486  *
2487  * @param loader the loader.
2488  */
2489 void
2490 _dbus_message_loader_ref (DBusMessageLoader *loader)
2491 {
2492   loader->refcount += 1;
2493 }
2494
2495 /**
2496  * Decrements the reference count of the loader and finalizes the
2497  * loader when the count reaches zero.
2498  *
2499  * @param loader the loader.
2500  */
2501 void
2502 _dbus_message_loader_unref (DBusMessageLoader *loader)
2503 {
2504   loader->refcount -= 1;
2505   if (loader->refcount == 0)
2506     {
2507       _dbus_list_foreach (&loader->messages,
2508                           (DBusForeachFunction) dbus_message_unref,
2509                           NULL);
2510       _dbus_list_clear (&loader->messages);
2511       _dbus_string_free (&loader->data);
2512       dbus_free (loader);
2513     }
2514 }
2515
2516 /**
2517  * Gets the buffer to use for reading data from the network.  Network
2518  * data is read directly into an allocated buffer, which is then used
2519  * in the DBusMessage, to avoid as many extra memcpy's as possible.
2520  * The buffer must always be returned immediately using
2521  * _dbus_message_loader_return_buffer(), even if no bytes are
2522  * successfully read.
2523  *
2524  * @todo this function can be a lot more clever. For example
2525  * it can probably always return a buffer size to read exactly
2526  * the body of the next message, thus avoiding any memory wastage
2527  * or reallocs.
2528  *
2529  * @todo we need to enforce a max length on strings in header fields.
2530  * 
2531  * @param loader the message loader.
2532  * @param buffer the buffer
2533  */
2534 void
2535 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
2536                                  DBusString        **buffer)
2537 {
2538   _dbus_assert (!loader->buffer_outstanding);
2539
2540   *buffer = &loader->data;
2541   
2542   loader->buffer_outstanding = TRUE;
2543 }
2544
2545 /**
2546  * The smallest header size that can occur. 
2547  * (It won't be valid)
2548  */
2549 #define DBUS_MINIMUM_HEADER_SIZE 16
2550
2551 /** Pack four characters as in "abcd" into a uint32 */
2552 #define FOUR_CHARS_TO_UINT32(a, b, c, d)                \
2553                       ((((dbus_uint32_t)a) << 24) |     \
2554                        (((dbus_uint32_t)b) << 16) |     \
2555                        (((dbus_uint32_t)c) << 8)  |     \
2556                        ((dbus_uint32_t)d))
2557
2558 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
2559 #define DBUS_HEADER_FIELD_NAME_AS_UINT32    \
2560   FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
2561
2562 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
2563 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
2564   FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
2565
2566 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
2567 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32   \
2568   FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
2569
2570 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
2571 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32  \
2572   FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
2573
2574 /* FIXME impose max length on name, srvc, sndr */
2575 static dbus_bool_t
2576 decode_header_data (const DBusString   *data,
2577                     int                 header_len,
2578                     int                 byte_order,
2579                     HeaderField         fields[FIELD_LAST],
2580                     int                *message_padding)
2581 {
2582   const char *field;
2583   int pos, new_pos;
2584   int i;
2585   
2586   if (header_len < 16)
2587     return FALSE;
2588   
2589   i = 0;
2590   while (i < FIELD_LAST)
2591     {
2592       fields[i].offset = -1;
2593       ++i;
2594     }
2595   
2596   fields[FIELD_HEADER_LENGTH].offset = 4;
2597   fields[FIELD_BODY_LENGTH].offset = 8;   
2598   fields[FIELD_CLIENT_SERIAL].offset = 12;
2599   
2600   /* Now handle the named fields. A real named field is at least 4
2601    * bytes for the name, plus a type code (1 byte) plus padding.  So
2602    * if we have less than 8 bytes left, it must be alignment padding,
2603    * not a field. While >= 8 bytes can't be entirely alignment
2604    * padding.
2605    */  
2606   pos = 16;
2607   while ((pos + 7) < header_len)
2608     {
2609       pos = _DBUS_ALIGN_VALUE (pos, 4);
2610       
2611       if ((pos + 4) > header_len)
2612         return FALSE;      
2613       
2614       field =_dbus_string_get_const_data_len (data, pos, 4);
2615       pos += 4;
2616
2617       _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
2618
2619       /* I believe FROM_BE is right, but if not we'll find out
2620        * I guess. ;-)
2621        */
2622       switch (DBUS_UINT32_FROM_BE (*(int*)field))
2623         {
2624         case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
2625           if (fields[FIELD_SERVICE].offset >= 0)
2626             {
2627               _dbus_verbose ("%s field provided twice\n",
2628                              DBUS_HEADER_FIELD_SERVICE);
2629               return FALSE;
2630             }
2631           
2632           fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2633 #if 0
2634           _dbus_verbose ("Found service name at offset %d\n",
2635                          fields[FIELD_SERVICE].offset);
2636 #endif
2637           break;
2638
2639         case DBUS_HEADER_FIELD_NAME_AS_UINT32:
2640           if (fields[FIELD_NAME].offset >= 0)
2641             {              
2642               _dbus_verbose ("%s field provided twice\n",
2643                              DBUS_HEADER_FIELD_NAME);
2644               return FALSE;
2645             }
2646           
2647           fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2648
2649 #if 0
2650           _dbus_verbose ("Found message name at offset %d\n",
2651                          fields[FIELD_NAME].offset);
2652 #endif
2653           break;
2654         case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
2655           if (fields[FIELD_SENDER].offset >= 0)
2656             {
2657               _dbus_verbose ("%s field provided twice\n",
2658                              DBUS_HEADER_FIELD_SENDER);
2659               return FALSE;
2660             }
2661           
2662           fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2663
2664           _dbus_verbose ("Found sender name at offset %d\n",
2665                          fields[FIELD_NAME].offset);
2666           break;
2667           
2668         case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
2669           if (fields[FIELD_REPLY_SERIAL].offset >= 0)
2670             {
2671               _dbus_verbose ("%s field provided twice\n",
2672                              DBUS_HEADER_FIELD_REPLY);
2673               return FALSE;
2674             }
2675           
2676           fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2677
2678           _dbus_verbose ("Found reply serial at offset %d\n",
2679                          fields[FIELD_REPLY_SERIAL].offset);
2680           break;
2681
2682         default:
2683           _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c at offset %d\n",
2684                          field[0], field[1], field[2], field[3], pos);
2685         }
2686
2687       if (!_dbus_marshal_validate_arg (data, byte_order, pos, &new_pos))
2688         {
2689           _dbus_verbose ("Failed to validate argument to named header field\n");
2690           return FALSE;
2691         }
2692
2693       if (new_pos > header_len)
2694         {
2695           _dbus_verbose ("Named header field tries to extend beyond header length\n");
2696           return FALSE;
2697         }
2698       
2699       pos = new_pos;
2700     }
2701
2702   if (pos < header_len)
2703     {
2704       /* Alignment padding, verify that it's nul */
2705       _dbus_assert ((header_len - pos) < 8);
2706
2707       if (!_dbus_string_validate_nul (data,
2708                                       pos, (header_len - pos)))
2709         {
2710           _dbus_verbose ("header alignment padding is not nul\n");
2711           return FALSE;
2712         }
2713     }
2714
2715  if (fields[FIELD_NAME].offset < 0)
2716    {
2717      _dbus_verbose ("No %s field provided\n",
2718                     DBUS_HEADER_FIELD_NAME);
2719      return FALSE;
2720    }
2721   
2722   if (message_padding)
2723     *message_padding = header_len - pos;  
2724   
2725   return TRUE;
2726 }
2727
2728 /**
2729  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
2730  * indicating to the loader how many bytes of the buffer were filled
2731  * in. This function must always be called, even if no bytes were
2732  * successfully read.
2733  *
2734  * @param loader the loader.
2735  * @param buffer the buffer.
2736  * @param bytes_read number of bytes that were read into the buffer.
2737  */
2738 void
2739 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
2740                                     DBusString         *buffer,
2741                                     int                 bytes_read)
2742 {
2743   _dbus_assert (loader->buffer_outstanding);
2744   _dbus_assert (buffer == &loader->data);
2745
2746   loader->buffer_outstanding = FALSE;
2747 }
2748
2749 /**
2750  * Converts buffered data into messages.
2751  *
2752  * @param loader the loader.
2753  * @returns #TRUE if we had enough memory to finish.
2754  */
2755 dbus_bool_t
2756 _dbus_message_loader_queue_messages (DBusMessageLoader *loader)
2757 {
2758   if (loader->corrupted)
2759     return TRUE;
2760
2761   while (_dbus_string_get_length (&loader->data) >= 16)
2762     {
2763       DBusMessage *message;      
2764       const char *header_data;
2765       int byte_order, header_len, body_len, header_padding;
2766       dbus_uint32_t header_len_unsigned, body_len_unsigned;
2767       
2768       header_data = _dbus_string_get_const_data_len (&loader->data, 0, 16);
2769
2770       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
2771
2772       if (header_data[2] != DBUS_MAJOR_PROTOCOL_VERSION)
2773         {
2774           _dbus_verbose ("Message has protocol version %d ours is %d\n",
2775                          (int) header_data[2], DBUS_MAJOR_PROTOCOL_VERSION);
2776           loader->corrupted = TRUE;
2777           return TRUE;
2778         }
2779       
2780       byte_order = header_data[0];
2781
2782       if (byte_order != DBUS_LITTLE_ENDIAN &&
2783           byte_order != DBUS_BIG_ENDIAN)
2784         {
2785           _dbus_verbose ("Message with bad byte order '%c' received\n",
2786                          byte_order);
2787           loader->corrupted = TRUE;
2788           return TRUE;
2789         }
2790
2791       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
2792       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
2793
2794       if (header_len_unsigned < 16)
2795         {
2796           _dbus_verbose ("Message had broken too-small header length %u\n",
2797                          header_len_unsigned);
2798           loader->corrupted = TRUE;
2799           return TRUE;
2800         }
2801
2802       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
2803           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
2804         {
2805           _dbus_verbose ("Header or body length too large (%u %u)\n",
2806                          header_len_unsigned,
2807                          body_len_unsigned);
2808           loader->corrupted = TRUE;
2809           return TRUE;
2810         }
2811
2812       /* Now that we know the values are in signed range, get
2813        * rid of stupid unsigned, just causes bugs
2814        */
2815       header_len = header_len_unsigned;
2816       body_len = body_len_unsigned;
2817
2818       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
2819         {
2820           
2821           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
2822                          header_len);
2823           loader->corrupted = TRUE;
2824           return TRUE;
2825         }
2826       
2827       if (header_len + body_len > loader->max_message_size)
2828         {
2829           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %ld\n",
2830                          header_len, body_len, loader->max_message_size);
2831           loader->corrupted = TRUE;
2832           return TRUE;
2833         }
2834
2835       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
2836         {
2837           HeaderField fields[FIELD_LAST];
2838           int i;
2839           int next_arg;          
2840
2841 #if 0
2842           _dbus_verbose_bytes_of_string (&loader->data, 0, header_len + body_len);
2843 #endif    
2844           if (!decode_header_data (&loader->data, header_len, byte_order,
2845                                    fields, &header_padding))
2846             {
2847               _dbus_verbose ("Header was invalid\n");
2848               loader->corrupted = TRUE;
2849               return TRUE;
2850             }
2851           
2852           next_arg = header_len;
2853           while (next_arg < (header_len + body_len))
2854             {
2855               int prev = next_arg;
2856
2857               if (!_dbus_marshal_validate_arg (&loader->data,
2858                                                byte_order,
2859                                                next_arg,
2860                                                &next_arg))
2861                 {
2862                   loader->corrupted = TRUE;
2863                   return TRUE;
2864                 }
2865
2866               _dbus_assert (next_arg > prev);
2867             }
2868           
2869           if (next_arg > (header_len + body_len))
2870             {
2871               _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
2872                              next_arg, header_len, body_len,
2873                              header_len + body_len);
2874               loader->corrupted = TRUE;
2875               return TRUE;
2876             }
2877
2878           message = dbus_message_new_empty_header ();
2879           if (message == NULL)
2880             return FALSE;
2881
2882           message->byte_order = byte_order;
2883           message->header_padding = header_padding;
2884           
2885           /* Copy in the offsets we found */
2886           i = 0;
2887           while (i < FIELD_LAST)
2888             {
2889               message->header_fields[i] = fields[i];
2890               ++i;
2891             }
2892           
2893           if (!_dbus_list_append (&loader->messages, message))
2894             {
2895               dbus_message_unref (message);
2896               return FALSE;
2897             }
2898
2899           _dbus_assert (_dbus_string_get_length (&message->header) == 0);
2900           _dbus_assert (_dbus_string_get_length (&message->body) == 0);
2901
2902           _dbus_assert (_dbus_string_get_length (&loader->data) >=
2903                         (header_len + body_len));
2904           
2905           if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
2906             {
2907               _dbus_list_remove_last (&loader->messages, message);
2908               dbus_message_unref (message);
2909               return FALSE;
2910             }
2911           
2912           if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
2913             {
2914               dbus_bool_t result;
2915
2916               /* put the header back, we'll try again later */
2917               result = _dbus_string_copy_len (&message->header, 0, header_len,
2918                                               &loader->data, 0);
2919               _dbus_assert (result); /* because DBusString never reallocs smaller */
2920
2921               _dbus_list_remove_last (&loader->messages, message);
2922               dbus_message_unref (message);
2923               return FALSE;
2924             }
2925
2926           _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
2927           _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
2928
2929           /* Fill in caches */
2930           message->reply_serial = get_int_field (message,
2931                                                  FIELD_REPLY_SERIAL);
2932           message->client_serial = get_int_field (message,
2933                                                   FIELD_CLIENT_SERIAL);
2934           
2935           _dbus_verbose ("Loaded message %p\n", message);
2936         }
2937       else
2938         return TRUE;
2939     }
2940
2941   return TRUE;
2942 }
2943
2944 /**
2945  * Peeks at first loaded message, returns #NULL if no messages have
2946  * been queued.
2947  *
2948  * @param loader the loader.
2949  * @returns the next message, or #NULL if none.
2950  */
2951 DBusMessage*
2952 _dbus_message_loader_peek_message (DBusMessageLoader *loader)
2953 {
2954   if (loader->messages)
2955     return loader->messages->data;
2956   else
2957     return NULL;
2958 }
2959
2960 /**
2961  * Pops a loaded message (passing ownership of the message
2962  * to the caller). Returns #NULL if no messages have been
2963  * queued.
2964  *
2965  * @param loader the loader.
2966  * @returns the next message, or #NULL if none.
2967  */
2968 DBusMessage*
2969 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
2970 {
2971   return _dbus_list_pop_first (&loader->messages);
2972 }
2973
2974 /**
2975  * Pops a loaded message inside a list link (passing ownership of the
2976  * message and link to the caller). Returns #NULL if no messages have
2977  * been loaded.
2978  *
2979  * @param loader the loader.
2980  * @returns the next message link, or #NULL if none.
2981  */
2982 DBusList*
2983 _dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
2984 {
2985   return _dbus_list_pop_first_link (&loader->messages);
2986 }
2987
2988 /**
2989  * Checks whether the loader is confused due to bad data.
2990  * If messages are received that are invalid, the
2991  * loader gets confused and gives up permanently.
2992  * This state is called "corrupted."
2993  *
2994  * @param loader the loader
2995  * @returns #TRUE if the loader is hosed.
2996  */
2997 dbus_bool_t
2998 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
2999 {
3000   return loader->corrupted;
3001 }
3002
3003 /**
3004  * Sets the maximum size message we allow.
3005  *
3006  * @param loader the loader
3007  * @param size the max message size in bytes
3008  */
3009 void
3010 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
3011                                            long                size)
3012 {
3013   if (size > MAX_SANE_MESSAGE_SIZE)
3014     {
3015       _dbus_verbose ("clamping requested max message size %ld to %d\n",
3016                      size, MAX_SANE_MESSAGE_SIZE);
3017       size = MAX_SANE_MESSAGE_SIZE;
3018     }
3019   loader->max_message_size = size;
3020 }
3021
3022 /**
3023  * Gets the maximum allowed message size in bytes.
3024  *
3025  * @param loader the loader
3026  * @returns max size in bytes
3027  */
3028 long
3029 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
3030 {
3031   return loader->max_message_size;
3032 }
3033
3034 /** @} */
3035 #ifdef DBUS_BUILD_TESTS
3036 #include "dbus-test.h"
3037 #include <stdio.h>
3038
3039 static void
3040 message_iter_test (DBusMessage *message)
3041 {
3042   DBusMessageIter *iter;
3043   char *str;
3044   
3045   iter = dbus_message_get_args_iter (message);
3046
3047   /* String tests */
3048   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRING)
3049     _dbus_assert_not_reached ("Argument type isn't string");
3050
3051   str = dbus_message_iter_get_string (iter);
3052   if (strcmp (str, "Test string") != 0)
3053     _dbus_assert_not_reached ("Strings differ");
3054   dbus_free (str);
3055
3056   if (!dbus_message_iter_next (iter))
3057     _dbus_assert_not_reached ("Reached end of arguments");
3058
3059   /* Signed integer tests */
3060   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT32)
3061     _dbus_assert_not_reached ("Argument type isn't int32");
3062
3063   if (dbus_message_iter_get_int32 (iter) != -0x12345678)
3064     _dbus_assert_not_reached ("Signed integers differ");
3065
3066   if (!dbus_message_iter_next (iter))
3067     _dbus_assert_not_reached ("Reached end of fields");
3068   
3069   /* Unsigned integer tests */
3070   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT32)
3071     _dbus_assert_not_reached ("Argument type isn't int32");
3072
3073   if (dbus_message_iter_get_uint32 (iter) != 0xedd1e)
3074     _dbus_assert_not_reached ("Unsigned integers differ");
3075
3076   if (!dbus_message_iter_next (iter))
3077     _dbus_assert_not_reached ("Reached end of arguments");
3078
3079   /* Double tests */
3080   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_DOUBLE)
3081     _dbus_assert_not_reached ("Argument type isn't double");
3082
3083   if (dbus_message_iter_get_double (iter) != 3.14159)
3084     _dbus_assert_not_reached ("Doubles differ");
3085
3086   if (dbus_message_iter_next (iter))
3087     _dbus_assert_not_reached ("Didn't reach end of arguments");
3088   
3089   dbus_message_iter_unref (iter);
3090 }
3091
3092 static dbus_bool_t
3093 check_message_handling (DBusMessage *message)
3094 {
3095   DBusMessageIter *iter;
3096   int type;
3097   dbus_bool_t retval;
3098   dbus_int32_t client_serial;
3099   
3100   retval = FALSE;
3101   iter = NULL;
3102   
3103   client_serial = dbus_message_get_serial (message);
3104
3105   /* can't use set_serial due to the assertions at the start of it */
3106   set_int_field (message, FIELD_CLIENT_SERIAL,
3107                  client_serial);
3108   
3109   if (client_serial != dbus_message_get_serial (message))
3110     {
3111       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
3112       goto failed;
3113     }
3114   
3115   /* If we implement message_set_arg (message, n, value)
3116    * then we would want to test it here
3117    */
3118
3119   iter = dbus_message_get_args_iter (message);
3120   while ((type = dbus_message_iter_get_arg_type (iter)) != DBUS_TYPE_INVALID)
3121     {
3122       switch (type)
3123         {
3124         case DBUS_TYPE_NIL:
3125           break;
3126         case DBUS_TYPE_INT32:
3127           dbus_message_iter_get_int32 (iter);
3128           break;
3129         case DBUS_TYPE_UINT32:
3130           dbus_message_iter_get_uint32 (iter);
3131           break;
3132         case DBUS_TYPE_DOUBLE:
3133           dbus_message_iter_get_double (iter);
3134           break;
3135         case DBUS_TYPE_STRING:
3136           {
3137             char *str;
3138             str = dbus_message_iter_get_string (iter);
3139             dbus_free (str);
3140           }
3141           break;
3142         case DBUS_TYPE_BOOLEAN_ARRAY:
3143           {
3144             unsigned char *values;
3145             int len;
3146             
3147             if (!dbus_message_iter_get_boolean_array (iter, &values, &len))
3148               return FALSE;
3149
3150             dbus_free (values);
3151           }
3152           break;
3153         case DBUS_TYPE_INT32_ARRAY:
3154           {
3155             dbus_int32_t *values;
3156             int len;
3157             
3158             if (!dbus_message_iter_get_int32_array (iter, &values, &len))
3159               return FALSE;
3160
3161             dbus_free (values);
3162           }
3163           break;
3164         case DBUS_TYPE_UINT32_ARRAY:
3165           {
3166             dbus_uint32_t *values;
3167             int len;
3168             
3169             if (!dbus_message_iter_get_uint32_array (iter, &values, &len))
3170               return FALSE;
3171
3172             dbus_free (values);
3173           }
3174           break;
3175         case DBUS_TYPE_DOUBLE_ARRAY:
3176           {
3177             double *values;
3178             int len;
3179             
3180             if (!dbus_message_iter_get_double_array (iter, &values, &len))
3181               return FALSE;
3182
3183             dbus_free (values);
3184           }
3185           break;
3186         case DBUS_TYPE_STRING_ARRAY:
3187           {
3188             char **values;
3189             int len;
3190             
3191             if (!dbus_message_iter_get_string_array (iter, &values, &len))
3192               return FALSE;
3193
3194             dbus_free_string_array (values);
3195           }
3196           break;
3197
3198         case DBUS_TYPE_DICT:
3199           {
3200             DBusDict *dict;
3201
3202             if (!dbus_message_iter_get_dict (iter, &dict))
3203               return FALSE;
3204             dbus_dict_unref (dict);
3205           }
3206           break;
3207
3208         default:
3209           break;
3210         }
3211       
3212       if (!dbus_message_iter_next (iter))
3213         break;
3214     }
3215
3216   retval = TRUE;
3217   
3218  failed:
3219   if (iter)
3220     dbus_message_iter_unref (iter);
3221
3222   return retval;
3223 }
3224
3225 static dbus_bool_t
3226 check_have_valid_message (DBusMessageLoader *loader)
3227 {
3228   DBusMessage *message;
3229   dbus_bool_t retval;
3230
3231   message = NULL;
3232   retval = FALSE;
3233
3234   if (!_dbus_message_loader_queue_messages (loader))
3235     _dbus_assert_not_reached ("no memory to queue messages");
3236   
3237   if (_dbus_message_loader_get_is_corrupted (loader))
3238     {
3239       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
3240       goto failed;
3241     }
3242   
3243   message = _dbus_message_loader_pop_message (loader);
3244   if (message == NULL)
3245     {
3246       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
3247       goto failed;
3248     }
3249   
3250   if (_dbus_string_get_length (&loader->data) > 0)
3251     {
3252       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
3253       goto failed;
3254     }
3255
3256   /* Verify that we're able to properly deal with the message.
3257    * For example, this would detect improper handling of messages
3258    * in nonstandard byte order.
3259    */
3260   if (!check_message_handling (message))
3261     goto failed;  
3262   
3263   retval = TRUE;
3264
3265  failed:
3266   if (message)
3267     dbus_message_unref (message);
3268
3269   return retval;
3270 }
3271
3272 static dbus_bool_t
3273 check_invalid_message (DBusMessageLoader *loader)
3274 {
3275   dbus_bool_t retval;
3276
3277   retval = FALSE;
3278
3279   if (!_dbus_message_loader_queue_messages (loader))
3280     _dbus_assert_not_reached ("no memory to queue messages");
3281   
3282   if (!_dbus_message_loader_get_is_corrupted (loader))
3283     {
3284       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
3285       goto failed;
3286     }
3287
3288   retval = TRUE;
3289
3290  failed:
3291   return retval;
3292 }
3293
3294 static dbus_bool_t
3295 check_incomplete_message (DBusMessageLoader *loader)
3296 {
3297   DBusMessage *message;
3298   dbus_bool_t retval;
3299
3300   message = NULL;
3301   retval = FALSE;
3302
3303   if (!_dbus_message_loader_queue_messages (loader))
3304     _dbus_assert_not_reached ("no memory to queue messages");
3305   
3306   if (_dbus_message_loader_get_is_corrupted (loader))
3307     {
3308       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
3309       goto failed;
3310     }
3311   
3312   message = _dbus_message_loader_pop_message (loader);
3313   if (message != NULL)
3314     {
3315       _dbus_warn ("loaded message that was expected to be incomplete\n");
3316       goto failed;
3317     }
3318
3319   retval = TRUE;
3320
3321  failed:
3322   if (message)
3323     dbus_message_unref (message);
3324   return retval;
3325 }
3326
3327 static dbus_bool_t
3328 check_loader_results (DBusMessageLoader      *loader,
3329                       DBusMessageValidity     validity)
3330 {
3331   if (!_dbus_message_loader_queue_messages (loader))
3332     _dbus_assert_not_reached ("no memory to queue messages");
3333   
3334   switch (validity)
3335     {
3336     case _DBUS_MESSAGE_VALID:
3337       return check_have_valid_message (loader);
3338     case _DBUS_MESSAGE_INVALID:
3339       return check_invalid_message (loader);
3340     case _DBUS_MESSAGE_INCOMPLETE:
3341       return check_incomplete_message (loader);
3342     case _DBUS_MESSAGE_UNKNOWN:
3343       return TRUE;
3344     }
3345
3346   _dbus_assert_not_reached ("bad DBusMessageValidity");
3347   return FALSE;
3348 }
3349
3350
3351 /**
3352  * Loads the message in the given message file.
3353  *
3354  * @param filename filename to load
3355  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
3356  * @param data string to load message into
3357  * @returns #TRUE if the message was loaded
3358  */
3359 dbus_bool_t
3360 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
3361                                             dbus_bool_t          is_raw,
3362                                             DBusString          *data)
3363 {
3364   dbus_bool_t retval;
3365
3366   retval = FALSE;  
3367
3368   if (is_raw)
3369     {
3370       DBusError error;
3371
3372       dbus_error_init (&error);
3373       if (!_dbus_file_get_contents (data, filename, &error))
3374         {
3375           _dbus_warn ("Could not load message file %s: %s\n",
3376                       _dbus_string_get_const_data (filename),
3377                       error.message);
3378           dbus_error_free (&error);
3379           goto failed;
3380         }
3381     }
3382   else
3383     {
3384       if (!_dbus_message_data_load (data, filename))
3385         {
3386           _dbus_warn ("Could not load message file %s\n",
3387                       _dbus_string_get_const_data (filename));
3388           goto failed;
3389         }
3390     }
3391
3392   retval = TRUE;
3393   
3394  failed:
3395
3396   return retval;
3397 }
3398
3399 /**
3400  * Tries loading the message in the given message file
3401  * and verifies that DBusMessageLoader can handle it.
3402  *
3403  * @param filename filename to load
3404  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
3405  * @param expected_validity what the message has to be like to return #TRUE
3406  * @returns #TRUE if the message has the expected validity
3407  */
3408 dbus_bool_t
3409 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
3410                                            dbus_bool_t          is_raw,
3411                                            DBusMessageValidity  expected_validity)
3412 {
3413   DBusString data;
3414   dbus_bool_t retval;
3415
3416   retval = FALSE;
3417   
3418   if (!_dbus_string_init (&data))
3419     _dbus_assert_not_reached ("could not allocate string\n");
3420
3421   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
3422                                                    &data))
3423     goto failed;
3424
3425   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
3426
3427  failed:
3428
3429   if (!retval)
3430     {
3431       if (_dbus_string_get_length (&data) > 0)
3432         _dbus_verbose_bytes_of_string (&data, 0,
3433                                        _dbus_string_get_length (&data));
3434       
3435       _dbus_warn ("Failed message loader test on %s\n",
3436                   _dbus_string_get_const_data (filename));
3437     }
3438   
3439   _dbus_string_free (&data);
3440
3441   return retval;
3442 }
3443
3444 /**
3445  * Tries loading the given message data.
3446  *
3447  *
3448  * @param data the message data
3449  * @param expected_validity what the message has to be like to return #TRUE
3450  * @returns #TRUE if the message has the expected validity
3451  */
3452 dbus_bool_t
3453 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
3454                                            DBusMessageValidity  expected_validity)
3455 {
3456   DBusMessageLoader *loader;
3457   dbus_bool_t retval;
3458   int len;
3459   int i;
3460
3461   loader = NULL;
3462   retval = FALSE;
3463
3464   /* Write the data one byte at a time */
3465   
3466   loader = _dbus_message_loader_new ();
3467
3468   len = _dbus_string_get_length (data);
3469   for (i = 0; i < len; i++)
3470     {
3471       DBusString *buffer;
3472
3473       _dbus_message_loader_get_buffer (loader, &buffer);
3474       _dbus_string_append_byte (buffer,
3475                                 _dbus_string_get_byte (data, i));
3476       _dbus_message_loader_return_buffer (loader, buffer, 1);
3477     }
3478   
3479   if (!check_loader_results (loader, expected_validity))
3480     goto failed;
3481
3482   _dbus_message_loader_unref (loader);
3483   loader = NULL;
3484
3485   /* Write the data all at once */
3486   
3487   loader = _dbus_message_loader_new ();
3488
3489   {
3490     DBusString *buffer;
3491     
3492     _dbus_message_loader_get_buffer (loader, &buffer);
3493     _dbus_string_copy (data, 0, buffer,
3494                        _dbus_string_get_length (buffer));
3495     _dbus_message_loader_return_buffer (loader, buffer, 1);
3496   }
3497   
3498   if (!check_loader_results (loader, expected_validity))
3499     goto failed;
3500
3501   _dbus_message_loader_unref (loader);
3502   loader = NULL;  
3503
3504   /* Write the data 2 bytes at a time */
3505   
3506   loader = _dbus_message_loader_new ();
3507
3508   len = _dbus_string_get_length (data);
3509   for (i = 0; i < len; i += 2)
3510     {
3511       DBusString *buffer;
3512
3513       _dbus_message_loader_get_buffer (loader, &buffer);
3514       _dbus_string_append_byte (buffer,
3515                                 _dbus_string_get_byte (data, i));
3516       if ((i+1) < len)
3517         _dbus_string_append_byte (buffer,
3518                                   _dbus_string_get_byte (data, i+1));
3519       _dbus_message_loader_return_buffer (loader, buffer, 1);
3520     }
3521   
3522   if (!check_loader_results (loader, expected_validity))
3523     goto failed;
3524
3525   _dbus_message_loader_unref (loader);
3526   loader = NULL;
3527   
3528   retval = TRUE;
3529   
3530  failed:
3531   
3532   if (loader)
3533     _dbus_message_loader_unref (loader);
3534   
3535   return retval;
3536 }
3537
3538 static dbus_bool_t
3539 process_test_subdir (const DBusString          *test_base_dir,
3540                      const char                *subdir,
3541                      DBusMessageValidity        validity,
3542                      DBusForeachMessageFileFunc function,
3543                      void                      *user_data)
3544 {
3545   DBusString test_directory;
3546   DBusString filename;
3547   DBusDirIter *dir;
3548   dbus_bool_t retval;
3549   DBusError error;
3550
3551   retval = FALSE;
3552   dir = NULL;
3553   
3554   if (!_dbus_string_init (&test_directory))
3555     _dbus_assert_not_reached ("didn't allocate test_directory\n");
3556
3557   _dbus_string_init_const (&filename, subdir);
3558   
3559   if (!_dbus_string_copy (test_base_dir, 0,
3560                           &test_directory, 0))
3561     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
3562   
3563   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
3564     _dbus_assert_not_reached ("couldn't allocate full path");
3565
3566   _dbus_string_free (&filename);
3567   if (!_dbus_string_init (&filename))
3568     _dbus_assert_not_reached ("didn't allocate filename string\n");
3569
3570   dbus_error_init (&error);
3571   dir = _dbus_directory_open (&test_directory, &error);
3572   if (dir == NULL)
3573     {
3574       _dbus_warn ("Could not open %s: %s\n",
3575                   _dbus_string_get_const_data (&test_directory),
3576                   error.message);
3577       dbus_error_free (&error);
3578       goto failed;
3579     }
3580
3581   printf ("Testing:\n");
3582   
3583  next:
3584   while (_dbus_directory_get_next_file (dir, &filename, &error))
3585     {
3586       DBusString full_path;
3587       dbus_bool_t is_raw;
3588       
3589       if (!_dbus_string_init (&full_path))
3590         _dbus_assert_not_reached ("couldn't init string");
3591
3592       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
3593         _dbus_assert_not_reached ("couldn't copy dir to full_path");
3594
3595       if (!_dbus_concat_dir_and_file (&full_path, &filename))
3596         _dbus_assert_not_reached ("couldn't concat file to dir");
3597
3598       if (_dbus_string_ends_with_c_str (&filename, ".message"))
3599         is_raw = FALSE;
3600       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
3601         is_raw = TRUE;
3602       else
3603         {
3604           _dbus_verbose ("Skipping non-.message file %s\n",
3605                          _dbus_string_get_const_data (&filename));
3606           _dbus_string_free (&full_path);
3607           goto next;
3608         }
3609
3610       printf ("    %s\n",
3611               _dbus_string_get_const_data (&filename));
3612       
3613       _dbus_verbose (" expecting %s\n",
3614                      validity == _DBUS_MESSAGE_VALID ? "valid" :
3615                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
3616                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")));
3617       
3618       if (! (*function) (&full_path, is_raw, validity, user_data))
3619         {
3620           _dbus_string_free (&full_path);
3621           goto failed;
3622         }
3623       else
3624         _dbus_string_free (&full_path);
3625     }
3626
3627   if (dbus_error_is_set (&error))
3628     {
3629       _dbus_warn ("Could not get next file in %s: %s\n",
3630                   _dbus_string_get_const_data (&test_directory),
3631                   error.message);
3632       dbus_error_free (&error);
3633       goto failed;
3634     }
3635     
3636   retval = TRUE;
3637   
3638  failed:
3639
3640   if (dir)
3641     _dbus_directory_close (dir);
3642   _dbus_string_free (&test_directory);
3643   _dbus_string_free (&filename);
3644
3645   return retval;
3646 }
3647                      
3648 /**
3649  * Runs the given function on every message file in the test suite.
3650  * The function should return #FALSE on test failure or fatal error.
3651  *
3652  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
3653  * @param func the function to run
3654  * @param user_data data for function
3655  * @returns #FALSE if there's a failure
3656  */
3657 dbus_bool_t
3658 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
3659                                                DBusForeachMessageFileFunc func,
3660                                                void                      *user_data)
3661 {
3662   DBusString test_directory;
3663   dbus_bool_t retval;
3664
3665   retval = FALSE;
3666   
3667   _dbus_string_init_const (&test_directory, test_data_dir);
3668
3669   if (!process_test_subdir (&test_directory, "valid-messages",
3670                             _DBUS_MESSAGE_VALID, func, user_data))
3671     goto failed;
3672
3673   if (!process_test_subdir (&test_directory, "invalid-messages",
3674                             _DBUS_MESSAGE_INVALID, func, user_data))
3675     goto failed;
3676   
3677   if (!process_test_subdir (&test_directory, "incomplete-messages",
3678                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
3679     goto failed;
3680
3681   retval = TRUE;
3682   
3683  failed:
3684
3685   _dbus_string_free (&test_directory);
3686   
3687   return retval;
3688 }
3689
3690 static void
3691 verify_test_message (DBusMessage *message)
3692 {
3693   dbus_int32_t our_int;
3694   char *our_str;
3695   double our_double;
3696   dbus_bool_t our_bool;
3697   
3698   if (!dbus_message_get_args (message, NULL,
3699                               DBUS_TYPE_INT32, &our_int,
3700                               DBUS_TYPE_STRING, &our_str,
3701                               DBUS_TYPE_DOUBLE, &our_double,
3702                               DBUS_TYPE_BOOLEAN, &our_bool,
3703                               0))
3704     _dbus_assert_not_reached ("Could not get arguments");
3705
3706   if (our_int != -0x12345678)
3707     _dbus_assert_not_reached ("integers differ!");
3708
3709   if (our_double != 3.14159)
3710     _dbus_assert_not_reached ("doubles differ!");
3711
3712   if (strcmp (our_str, "Test string") != 0)
3713     _dbus_assert_not_reached ("strings differ!");
3714
3715   if (!our_bool)
3716     _dbus_assert_not_reached ("booleans differ");
3717   
3718   dbus_free (our_str);
3719 }
3720
3721 /**
3722  * @ingroup DBusMessageInternals
3723  * Unit test for DBusMessage.
3724  *
3725  * @returns #TRUE on success.
3726  */
3727 dbus_bool_t
3728 _dbus_message_test (const char *test_data_dir)
3729 {
3730   DBusMessage *message;
3731   DBusMessageLoader *loader;
3732   int i;
3733   const char *data;
3734   DBusMessage *copy;
3735   const char *name1;
3736   const char *name2;
3737   
3738   /* Test the vararg functions */
3739   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
3740   _dbus_message_set_serial (message, 1);
3741   dbus_message_append_args (message,
3742                             DBUS_TYPE_INT32, -0x12345678,
3743                             DBUS_TYPE_STRING, "Test string",
3744                             DBUS_TYPE_DOUBLE, 3.14159,
3745                             DBUS_TYPE_BOOLEAN, TRUE,
3746                             0);
3747   _dbus_verbose_bytes_of_string (&message->header, 0,
3748                                  _dbus_string_get_length (&message->header));
3749   _dbus_verbose_bytes_of_string (&message->body, 0,
3750                                  _dbus_string_get_length (&message->body));
3751
3752   verify_test_message (message);
3753
3754   copy = dbus_message_copy (message);
3755   
3756   _dbus_assert (message->client_serial == copy->client_serial);
3757   _dbus_assert (message->reply_serial == copy->reply_serial);
3758   _dbus_assert (message->header_padding == copy->header_padding);
3759   
3760   _dbus_assert (_dbus_string_get_length (&message->header) ==
3761                 _dbus_string_get_length (&copy->header));
3762
3763   _dbus_assert (_dbus_string_get_length (&message->body) ==
3764                 _dbus_string_get_length (&copy->body));
3765
3766   verify_test_message (copy);
3767
3768   name1 = dbus_message_get_name (message);
3769   name2 = dbus_message_get_name (copy);
3770
3771   _dbus_assert (strcmp (name1, name2) == 0);
3772   
3773   dbus_message_unref (message);
3774   dbus_message_unref (copy);
3775   
3776   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
3777   _dbus_message_set_serial (message, 1);
3778   dbus_message_set_reply_serial (message, 0x12345678);
3779
3780   dbus_message_append_string (message, "Test string");
3781   dbus_message_append_int32 (message, -0x12345678);
3782   dbus_message_append_uint32 (message, 0xedd1e);
3783   dbus_message_append_double (message, 3.14159);
3784
3785   message_iter_test (message);
3786
3787   /* Message loader test */
3788   _dbus_message_lock (message);
3789   loader = _dbus_message_loader_new ();
3790
3791   /* Write the header data one byte at a time */
3792   data = _dbus_string_get_const_data (&message->header);
3793   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
3794     {
3795       DBusString *buffer;
3796
3797       _dbus_message_loader_get_buffer (loader, &buffer);
3798       _dbus_string_append_byte (buffer, data[i]);
3799       _dbus_message_loader_return_buffer (loader, buffer, 1);
3800     }
3801
3802   /* Write the body data one byte at a time */
3803   data = _dbus_string_get_const_data (&message->body);
3804   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
3805     {
3806       DBusString *buffer;
3807
3808       _dbus_message_loader_get_buffer (loader, &buffer);
3809       _dbus_string_append_byte (buffer, data[i]);
3810       _dbus_message_loader_return_buffer (loader, buffer, 1);
3811     }
3812
3813   dbus_message_unref (message);
3814
3815   /* Now pop back the message */
3816   if (!_dbus_message_loader_queue_messages (loader))
3817     _dbus_assert_not_reached ("no memory to queue messages");
3818   
3819   if (_dbus_message_loader_get_is_corrupted (loader))
3820     _dbus_assert_not_reached ("message loader corrupted");
3821   
3822   message = _dbus_message_loader_pop_message (loader);
3823   if (!message)
3824     _dbus_assert_not_reached ("received a NULL message");
3825
3826   if (dbus_message_get_reply_serial (message) != 0x12345678)
3827     _dbus_assert_not_reached ("reply serial fields differ");
3828   
3829   message_iter_test (message);
3830   
3831   dbus_message_unref (message);
3832   _dbus_message_loader_unref (loader);
3833
3834   /* Now load every message in test_data_dir if we have one */
3835   if (test_data_dir == NULL)
3836     return TRUE;
3837
3838   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
3839                                                         (DBusForeachMessageFileFunc)
3840                                                         dbus_internal_do_not_use_try_message_file,
3841                                                         NULL);
3842 }
3843
3844 #endif /* DBUS_BUILD_TESTS */