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