2003-02-26 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / dbus / dbus-message.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-message.c  DBusMessage object
3  *
4  * Copyright (C) 2002, 2003  Red Hat Inc.
5  * Copyright (C) 2002, 2003  CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 1.2
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "dbus-internals.h"
26 #include "dbus-marshal.h"
27 #include "dbus-message.h"
28 #include "dbus-message-internal.h"
29 #include "dbus-memory.h"
30 #include "dbus-list.h"
31 #include "dbus-message-builder.h"
32 #include <string.h>
33
34 /**
35  * @defgroup DBusMessageInternals DBusMessage implementation details
36  * @ingroup DBusInternals
37  * @brief DBusMessage private implementation details.
38  *
39  * The guts of DBusMessage and its methods.
40  *
41  * @{
42  */
43
44 enum
45 {
46   FIELD_HEADER_LENGTH,
47   FIELD_BODY_LENGTH,
48   FIELD_CLIENT_SERIAL,
49   FIELD_NAME,
50   FIELD_SERVICE,
51   FIELD_SENDER,
52   FIELD_REPLY_SERIAL,
53
54   FIELD_LAST
55 };
56
57 static dbus_bool_t field_is_named[FIELD_LAST] =
58 {
59   FALSE, /* FIELD_HEADER_LENGTH */
60   FALSE, /* FIELD_BODY_LENGTH */
61   FALSE, /* FIELD_CLIENT_SERIAL */
62   TRUE,  /* FIELD_NAME */
63   TRUE,  /* FIELD_SERVICE */
64   TRUE,  /* FIELD_SENDER */
65   TRUE   /* FIELD_REPLY_SERIAL */
66 };
67
68 typedef struct
69 {
70   int offset; /**< Offset to start of field (location of name of field
71                * for named fields)
72                */
73 } HeaderField;
74
75 /**
76  * @brief Internals of DBusMessage
77  * 
78  * Object representing a message received from or to be sent to
79  * another application. This is an opaque object, all members
80  * are private.
81  */
82 struct DBusMessage
83 {
84   dbus_atomic_t refcount; /**< Reference count */
85
86   DBusString header; /**< Header network data, stored
87                       * separately from body so we can
88                       * independently realloc it.
89                       */
90
91   HeaderField header_fields[FIELD_LAST]; /**< Track the location
92                                            * of each field in "header"
93                                            */
94   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   dbus_message_ref (message);
1729   
1730   iter->refcount = 1;
1731   iter->message = message;
1732   iter->pos = 0;
1733
1734   return iter;
1735 }
1736
1737 /**
1738  * Increments the reference count of a DBusMessageIter.
1739  *
1740  * @param iter the message iter
1741  * @see dbus_message_iter_unref
1742  */
1743 void
1744 dbus_message_iter_ref (DBusMessageIter *iter)
1745 {
1746   _dbus_assert (iter->refcount > 0);
1747   
1748   iter->refcount += 1;
1749 }
1750
1751 /**
1752  * Decrements the reference count of a DBusMessageIter.
1753  *
1754  * @param iter The message iter
1755  * @see dbus_message_iter_ref
1756  */
1757 void
1758 dbus_message_iter_unref (DBusMessageIter *iter)
1759 {
1760   _dbus_assert (iter->refcount > 0);
1761
1762   iter->refcount -= 1;
1763
1764   if (iter->refcount == 0)
1765     {
1766       dbus_message_unref (iter->message);
1767
1768       dbus_free (iter);
1769     }
1770 }
1771
1772 /**
1773  * Checks if an iterator has any more fields.
1774  *
1775  * @param iter the message iter
1776  * @returns #TRUE if there are more fields
1777  * following
1778  */
1779 dbus_bool_t
1780 dbus_message_iter_has_next (DBusMessageIter *iter)
1781 {
1782   int end_pos;
1783   
1784   if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
1785                                       iter->message->byte_order,
1786                                       iter->pos, &end_pos))
1787     return FALSE;
1788   
1789   if (end_pos >= _dbus_string_get_length (&iter->message->body))
1790     return FALSE;
1791   
1792   return TRUE;  
1793 }
1794
1795 /**
1796  * Moves the iterator to the next field.
1797  *
1798  * @param iter The message iter
1799  * @returns #TRUE if the iterator was moved to the next field
1800  */
1801 dbus_bool_t
1802 dbus_message_iter_next (DBusMessageIter *iter)
1803 {
1804   int end_pos;
1805   
1806   if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
1807                                       iter->message->byte_order,
1808                                       iter->pos, &end_pos))
1809     return FALSE;
1810
1811   if (end_pos >= _dbus_string_get_length (&iter->message->body))
1812     return FALSE;
1813
1814   iter->pos = end_pos;
1815
1816   return TRUE;
1817 }
1818
1819 /**
1820  * Returns the argument type of the argument that the
1821  * message iterator points at.
1822  *
1823  * @param iter the message iter
1824  * @returns the field type
1825  */
1826 int
1827 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
1828 {
1829   const char *data;
1830
1831   if (iter->pos >= _dbus_string_get_length (&iter->message->body))
1832     return DBUS_TYPE_INVALID;
1833
1834   _dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
1835
1836   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING_ARRAY)
1837     return *data;
1838
1839   return DBUS_TYPE_INVALID;
1840 }
1841
1842 /**
1843  * Returns the string value that an iterator may point to.
1844  * Note that you need to check that the iterator points to
1845  * a string value before using this function.
1846  *
1847  * @see dbus_message_iter_get_arg_type
1848  * @param iter the message iter
1849  * @returns the string
1850  */
1851 char *
1852 dbus_message_iter_get_string (DBusMessageIter *iter)
1853 {
1854   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING);
1855
1856   return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
1857                                  iter->pos + 1, NULL);
1858 }
1859
1860 /**
1861  * Returns the boolean value that an iterator may point to.
1862  * Note that you need to check that the iterator points to
1863  * a boolean value before using this function.
1864  *
1865  * @see dbus_message_iter_get_arg_type
1866  * @param iter the message iter
1867  * @returns the string
1868  */
1869 dbus_bool_t
1870 dbus_message_iter_get_boolean (DBusMessageIter *iter)
1871 {
1872   unsigned char value;
1873   
1874   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN);
1875
1876   value = _dbus_string_get_byte (&iter->message->body, iter->pos + 1);
1877   iter->pos += 2;
1878   
1879   return value;
1880 }
1881
1882 /**
1883  * Returns the 32 bit signed integer value that an iterator may point to.
1884  * Note that you need to check that the iterator points to
1885  * an integer value before using this function.
1886  *
1887  * @see dbus_message_iter_get_arg_type
1888  * @param iter the message iter
1889  * @returns the integer
1890  */
1891 int
1892 dbus_message_iter_get_int32 (DBusMessageIter *iter)
1893 {
1894   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT32);
1895   
1896   return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
1897                                 iter->pos + 1, NULL);
1898 }
1899
1900 /**
1901  * Returns the 32 bit unsigned integer value that an iterator may point to.
1902  * Note that you need to check that the iterator points to
1903  * an unsigned integer value before using this function.
1904  *
1905  * @see dbus_message_iter_get_arg_type
1906  * @param iter the message iter
1907  * @returns the integer
1908  */
1909 int
1910 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
1911 {
1912   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT32);
1913   
1914   return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
1915                                  iter->pos + 1, NULL);
1916 }
1917
1918 /**
1919  * Returns the double value that an iterator may point to.
1920  * Note that you need to check that the iterator points to
1921  * a string value before using this function.
1922  *
1923  * @see dbus_message_iter_get_arg_type
1924  * @param iter the message iter
1925  * @returns the double
1926  */
1927 double
1928 dbus_message_iter_get_double (DBusMessageIter *iter)
1929 {
1930   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DOUBLE);
1931   
1932   return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
1933                                  iter->pos + 1, NULL);
1934 }
1935
1936 /**
1937  * Returns the boolean array that the iterator may point to. Note that
1938  * you need to check that the iterator points to an array of the
1939  * correct type prior to using this function.
1940  *
1941  * @param iter the iterator
1942  * @param value return location for the array
1943  * @param len return location for the array length
1944  * @returns #TRUE on success
1945  */
1946 dbus_bool_t
1947 dbus_message_iter_get_boolean_array (DBusMessageIter   *iter,
1948                                      unsigned char    **value,
1949                                      int               *len)
1950 {
1951   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BOOLEAN_ARRAY);
1952
1953   *value = _dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
1954                                        iter->pos + 1, NULL, len);
1955   
1956   if (!*value)
1957     return FALSE;
1958   else
1959     return TRUE;
1960 }
1961
1962 /**
1963  * Returns the 32 bit signed integer array that the iterator may point
1964  * to. Note that you need to check that the iterator points to an
1965  * array of the correct type prior to using this function.
1966  *
1967  * @param iter the iterator
1968  * @param value return location for the array
1969  * @param len return location for the array length
1970  * @returns #TRUE on success
1971  */
1972 dbus_bool_t
1973 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
1974                                     dbus_int32_t   **value,
1975                                     int             *len)
1976 {
1977   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT32_ARRAY);
1978
1979   *value = _dbus_demarshal_int32_array (&iter->message->body, iter->message->byte_order,
1980                                         iter->pos + 1, NULL, len);
1981   
1982   if (!*value)
1983     return FALSE;
1984   else
1985     return TRUE;
1986 }
1987
1988 /**
1989  * Returns the 32 bit unsigned integer array that the iterator may point
1990  * to. Note that you need to check that the iterator points to an
1991  * array of the correct type prior to using this function.
1992  *
1993  * @param iter the iterator
1994  * @param value return location for the array
1995  * @param len return location for the array length
1996  * @returns #TRUE on success
1997  */
1998 dbus_bool_t
1999 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
2000                                      dbus_uint32_t  **value,
2001                                      int             *len)
2002 {
2003   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT32_ARRAY);
2004
2005   *value = _dbus_demarshal_uint32_array (&iter->message->body, iter->message->byte_order,
2006                                          iter->pos + 1, NULL, len);
2007   
2008   if (!*value)
2009     return FALSE;
2010   else
2011     return TRUE;
2012 }
2013
2014 /**
2015  * Returns the double array that the iterator may point to. Note that
2016  * you need to check that the iterator points to an array of the
2017  * correct type prior to using this function.
2018  *
2019  * @param iter the iterator
2020  * @param value return location for the array
2021  * @param len return location for the array length
2022  * @returns #TRUE on success
2023  */
2024 dbus_bool_t
2025 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
2026                                      double         **value,
2027                                      int             *len)
2028 {
2029   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DOUBLE_ARRAY);
2030
2031   *value = _dbus_demarshal_double_array (&iter->message->body, iter->message->byte_order,
2032                                          iter->pos + 1, NULL, len);
2033   
2034   if (!*value)
2035     return FALSE;
2036   else
2037     return TRUE;
2038 }
2039
2040 /**
2041  * Returns the byte array that the iterator may point to.
2042  * Note that you need to check that the iterator points
2043  * to a byte array prior to using this function.
2044  *
2045  * @param iter the iterator
2046  * @param value return location for array values
2047  * @param len return location for length of byte array
2048  * @returns the byte array
2049  */
2050 dbus_bool_t
2051 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
2052                                   unsigned char   **value,
2053                                   int              *len)
2054 {
2055   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BYTE_ARRAY);
2056   
2057   *value = _dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
2058                                        iter->pos + 1, NULL, len);
2059
2060   if (!*value)
2061     return FALSE;
2062   else
2063     return TRUE;
2064 }
2065
2066 /**
2067  * Returns the string array that the iterator may point to.
2068  * Note that you need to check that the iterator points
2069  * to a byte array prior to using this function.
2070  *
2071  * The returned value is a #NULL-terminated array of strings.
2072  * Each string is a separate malloc block, and the array
2073  * itself is a malloc block. You can free this type of
2074  * string array with dbus_free_string_array().
2075  *
2076  * @param iter the iterator
2077  * @param value return location for string values
2078  * @param len return location for length of byte array
2079  * @returns the byte array
2080  */
2081 dbus_bool_t
2082 dbus_message_iter_get_string_array (DBusMessageIter *iter,
2083                                     char          ***value,
2084                                     int             *len)
2085 {
2086   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING_ARRAY);
2087
2088   *value = _dbus_demarshal_string_array (&iter->message->body, iter->message->byte_order,
2089                                          iter->pos + 1, NULL, len);
2090
2091   if (!*value)
2092     return FALSE;
2093   else
2094     return TRUE;
2095 }
2096
2097 /**
2098  * Sets the message sender.
2099  *
2100  * @param message the message
2101  * @param sender the sender
2102  * @returns #FALSE if not enough memory
2103  */
2104 dbus_bool_t
2105 dbus_message_set_sender (DBusMessage  *message,
2106                          const char   *sender)
2107 {
2108   _dbus_assert (!message->locked);
2109
2110   if (sender == NULL)
2111     {
2112       delete_string_field (message, FIELD_SENDER);
2113       return TRUE;
2114     }
2115   else
2116     {
2117       return set_string_field (message,
2118                                FIELD_SENDER,
2119                                sender);
2120     }
2121 }
2122
2123 /**
2124  * Sets a flag indicating that the message is an error reply
2125  * message, i.e. an "exception" rather than a normal response.
2126  *
2127  * @param message the message
2128  * @param is_error_reply #TRUE if this is an error message.
2129  */
2130 void
2131 dbus_message_set_is_error (DBusMessage *message,
2132                            dbus_bool_t  is_error_reply)
2133 {
2134   char *header;
2135   
2136   _dbus_assert (!message->locked);
2137   
2138   _dbus_string_get_data_len (&message->header, &header, 1, 1);
2139   
2140   if (is_error_reply)
2141     *header |= DBUS_HEADER_FLAG_ERROR;
2142   else
2143     *header &= ~DBUS_HEADER_FLAG_ERROR;    
2144 }
2145
2146 /**
2147  * Returns #TRUE if the message is an error
2148  * reply to some previous message we sent.
2149  *
2150  * @param message the message
2151  * @returns #TRUE if the message is an error
2152  */
2153 dbus_bool_t
2154 dbus_message_get_is_error (DBusMessage *message)
2155 {
2156   const char *header;
2157
2158   _dbus_string_get_const_data_len (&message->header, &header, 1, 1);
2159
2160   return (*header & DBUS_HEADER_FLAG_ERROR) != 0;
2161 }
2162
2163 /**
2164  * Gets the service which originated this message,
2165  * or #NULL if unknown or inapplicable.
2166  *
2167  * @param message the message
2168  * @returns the service name or #NULL
2169  */
2170 const char*
2171 dbus_message_get_sender (DBusMessage *message)
2172 {
2173   return get_string_field (message, FIELD_SENDER, NULL);
2174 }
2175
2176 /**
2177  * Checks whether the message has the given name.
2178  * If the message has no name or has a different
2179  * name, returns #FALSE.
2180  *
2181  * @param message the message
2182  * @param name the name to check (must not be #NULL)
2183  * 
2184  * @returns #TRUE if the message has the given name
2185  */
2186 dbus_bool_t
2187 dbus_message_name_is (DBusMessage *message,
2188                       const char  *name)
2189 {
2190   const char *n;
2191
2192   _dbus_assert (name != NULL);
2193   
2194   n = dbus_message_get_name (message);
2195
2196   if (n && strcmp (n, name) == 0)
2197     return TRUE;
2198   else
2199     return FALSE;
2200 }
2201
2202 /** @} */
2203
2204 /**
2205  * @addtogroup DBusMessageInternals
2206  *
2207  * @{
2208  */
2209 /**
2210  * @typedef DBusMessageLoader
2211  *
2212  * The DBusMessageLoader object encapsulates the process of converting
2213  * a byte stream into a series of DBusMessage. It buffers the incoming
2214  * bytes as efficiently as possible, and generates a queue of
2215  * messages. DBusMessageLoader is typically used as part of a
2216  * DBusTransport implementation. The DBusTransport then hands off
2217  * the loaded messages to a DBusConnection, making the messages
2218  * visible to the application.
2219  * 
2220  */
2221
2222 /* we definitely use signed ints for sizes, so don't exceed
2223  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
2224  * over 128M is pretty nuts anyhow.
2225  */
2226
2227 /**
2228  * The maximum sane message size.
2229  */
2230 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
2231
2232 /**
2233  * Implementation details of DBusMessageLoader.
2234  * All members are private.
2235  */
2236 struct DBusMessageLoader
2237 {
2238   int refcount;        /**< Reference count. */
2239
2240   DBusString data;     /**< Buffered data */
2241   
2242   DBusList *messages;  /**< Complete messages. */
2243
2244   long max_message_size; /**< Maximum size of a message */
2245   
2246   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
2247
2248   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
2249 };
2250
2251 /**
2252  * The initial buffer size of the message loader.
2253  * 
2254  * @todo this should be based on min header size plus some average
2255  * body size, or something. Or rather, the min header size only, if we
2256  * want to try to read only the header, store that in a DBusMessage,
2257  * then read only the body and store that, etc., depends on
2258  * how we optimize _dbus_message_loader_get_buffer() and what
2259  * the exact message format is.
2260  */
2261 #define INITIAL_LOADER_DATA_LEN 32
2262
2263 /**
2264  * Creates a new message loader. Returns #NULL if memory can't
2265  * be allocated.
2266  *
2267  * @returns new loader, or #NULL.
2268  */
2269 DBusMessageLoader*
2270 _dbus_message_loader_new (void)
2271 {
2272   DBusMessageLoader *loader;
2273
2274   loader = dbus_new0 (DBusMessageLoader, 1);
2275   if (loader == NULL)
2276     return NULL;
2277   
2278   loader->refcount = 1;
2279
2280   /* Try to cap message size at something that won't *totally* hose
2281    * the system if we have a couple of them.
2282    */
2283   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
2284   
2285   if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
2286     {
2287       dbus_free (loader);
2288       return NULL;
2289     }
2290
2291   /* preallocate the buffer for speed, ignore failure */
2292   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
2293   _dbus_string_set_length (&loader->data, 0);
2294   
2295   return loader;
2296 }
2297
2298 /**
2299  * Increments the reference count of the loader.
2300  *
2301  * @param loader the loader.
2302  */
2303 void
2304 _dbus_message_loader_ref (DBusMessageLoader *loader)
2305 {
2306   loader->refcount += 1;
2307 }
2308
2309 /**
2310  * Decrements the reference count of the loader and finalizes the
2311  * loader when the count reaches zero.
2312  *
2313  * @param loader the loader.
2314  */
2315 void
2316 _dbus_message_loader_unref (DBusMessageLoader *loader)
2317 {
2318   loader->refcount -= 1;
2319   if (loader->refcount == 0)
2320     {
2321       _dbus_list_foreach (&loader->messages,
2322                           (DBusForeachFunction) dbus_message_unref,
2323                           NULL);
2324       _dbus_list_clear (&loader->messages);
2325       _dbus_string_free (&loader->data);
2326       dbus_free (loader);
2327     }
2328 }
2329
2330 /**
2331  * Gets the buffer to use for reading data from the network.  Network
2332  * data is read directly into an allocated buffer, which is then used
2333  * in the DBusMessage, to avoid as many extra memcpy's as possible.
2334  * The buffer must always be returned immediately using
2335  * _dbus_message_loader_return_buffer(), even if no bytes are
2336  * successfully read.
2337  *
2338  * @todo this function can be a lot more clever. For example
2339  * it can probably always return a buffer size to read exactly
2340  * the body of the next message, thus avoiding any memory wastage
2341  * or reallocs.
2342  * 
2343  * @param loader the message loader.
2344  * @param buffer the buffer
2345  */
2346 void
2347 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
2348                                  DBusString        **buffer)
2349 {
2350   _dbus_assert (!loader->buffer_outstanding);
2351
2352   *buffer = &loader->data;
2353   
2354   loader->buffer_outstanding = TRUE;
2355 }
2356
2357 /**
2358  * The smallest header size that can occur. 
2359  * (It won't be valid)
2360  */
2361 #define DBUS_MINIMUM_HEADER_SIZE 16
2362
2363 /** Pack four characters as in "abcd" into a uint32 */
2364 #define FOUR_CHARS_TO_UINT32(a, b, c, d)                \
2365                       ((((dbus_uint32_t)a) << 24) |     \
2366                        (((dbus_uint32_t)b) << 16) |     \
2367                        (((dbus_uint32_t)c) << 8)  |     \
2368                        ((dbus_uint32_t)d))
2369
2370 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
2371 #define DBUS_HEADER_FIELD_NAME_AS_UINT32    \
2372   FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
2373
2374 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
2375 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
2376   FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
2377
2378 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
2379 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32   \
2380   FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
2381
2382 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
2383 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32  \
2384   FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
2385
2386 static dbus_bool_t
2387 decode_header_data (const DBusString   *data,
2388                     int                 header_len,
2389                     int                 byte_order,
2390                     HeaderField         fields[FIELD_LAST],
2391                     int                *message_padding)
2392 {
2393   const char *field;
2394   int pos, new_pos;
2395   int i;
2396   
2397   if (header_len < 16)
2398     return FALSE;
2399   
2400   i = 0;
2401   while (i < FIELD_LAST)
2402     {
2403       fields[i].offset = -1;
2404       ++i;
2405     }
2406   
2407   fields[FIELD_HEADER_LENGTH].offset = 4;
2408   fields[FIELD_BODY_LENGTH].offset = 8;   
2409   fields[FIELD_CLIENT_SERIAL].offset = 12;
2410   
2411   /* Now handle the named fields. A real named field is at least 4
2412    * bytes for the name, plus a type code (1 byte) plus padding.  So
2413    * if we have less than 8 bytes left, it must be alignment padding,
2414    * not a field. While >= 8 bytes can't be entirely alignment
2415    * padding.
2416    */  
2417   pos = 16;
2418   while ((pos + 7) < header_len)
2419     {
2420       pos = _DBUS_ALIGN_VALUE (pos, 4);
2421       
2422       if ((pos + 4) > header_len)
2423         return FALSE;      
2424       
2425       _dbus_string_get_const_data_len (data, &field, pos, 4);
2426       pos += 4;
2427
2428       _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
2429
2430       /* I believe FROM_BE is right, but if not we'll find out
2431        * I guess. ;-)
2432        */
2433       switch (DBUS_UINT32_FROM_BE (*(int*)field))
2434         {
2435         case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
2436           if (fields[FIELD_SERVICE].offset >= 0)
2437             {
2438               _dbus_verbose ("%s field provided twice\n",
2439                              DBUS_HEADER_FIELD_SERVICE);
2440               return FALSE;
2441             }
2442           
2443           fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2444           _dbus_verbose ("Found service name at offset %d\n",
2445                          fields[FIELD_SERVICE].offset);
2446           break;
2447
2448         case DBUS_HEADER_FIELD_NAME_AS_UINT32:
2449           if (fields[FIELD_NAME].offset >= 0)
2450             {
2451               _dbus_verbose ("%s field provided twice\n",
2452                              DBUS_HEADER_FIELD_NAME);
2453               return FALSE;
2454             }
2455           
2456           fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2457
2458           _dbus_verbose ("Found message name at offset %d\n",
2459                          fields[FIELD_NAME].offset);
2460           break;
2461         case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
2462           if (fields[FIELD_SENDER].offset >= 0)
2463             {
2464               _dbus_verbose ("%s field provided twice\n",
2465                              DBUS_HEADER_FIELD_SENDER);
2466               return FALSE;
2467             }
2468           
2469           fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2470
2471           _dbus_verbose ("Found sender name at offset %d\n",
2472                          fields[FIELD_NAME].offset);
2473           break;
2474           
2475         case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
2476           if (fields[FIELD_REPLY_SERIAL].offset >= 0)
2477             {
2478               _dbus_verbose ("%s field provided twice\n",
2479                              DBUS_HEADER_FIELD_REPLY);
2480               return FALSE;
2481             }
2482           
2483           fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2484
2485           _dbus_verbose ("Found reply serial at offset %d\n",
2486                          fields[FIELD_REPLY_SERIAL].offset);
2487           break;
2488
2489         default:
2490           _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c at offset %d\n",
2491                          field[0], field[1], field[2], field[3], pos);
2492         }
2493
2494       if (!_dbus_marshal_validate_arg (data, byte_order, pos, &new_pos))
2495         {
2496           _dbus_verbose ("Failed to validate argument to named header field\n");
2497           return FALSE;
2498         }
2499
2500       if (new_pos > header_len)
2501         {
2502           _dbus_verbose ("Named header field tries to extend beyond header length\n");
2503           return FALSE;
2504         }
2505       
2506       pos = new_pos;
2507     }
2508
2509   if (pos < header_len)
2510     {
2511       /* Alignment padding, verify that it's nul */
2512       _dbus_assert ((header_len - pos) < 8);
2513
2514       if (!_dbus_string_validate_nul (data,
2515                                       pos, (header_len - pos)))
2516         {
2517           _dbus_verbose ("header alignment padding is not nul\n");
2518           return FALSE;
2519         }
2520
2521       if (message_padding)
2522         *message_padding = header_len - pos;
2523     }
2524   
2525   return TRUE;
2526 }
2527
2528 /**
2529  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
2530  * indicating to the loader how many bytes of the buffer were filled
2531  * in. This function must always be called, even if no bytes were
2532  * successfully read.
2533  *
2534  * @todo if we run out of memory in here, we offer no way for calling
2535  * code to handle it, i.e. they can't re-run the message parsing
2536  * attempt. Perhaps much of this code could be moved to pop_message()?
2537  * But then that may need to distinguish NULL return for no messages
2538  * from NULL return for errors.
2539  *
2540  * @param loader the loader.
2541  * @param buffer the buffer.
2542  * @param bytes_read number of bytes that were read into the buffer.
2543  */
2544 void
2545 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
2546                                     DBusString         *buffer,
2547                                     int                 bytes_read)
2548 {
2549   _dbus_assert (loader->buffer_outstanding);
2550   _dbus_assert (buffer == &loader->data);
2551
2552   loader->buffer_outstanding = FALSE;
2553
2554   if (loader->corrupted)
2555     return;
2556
2557   while (_dbus_string_get_length (&loader->data) >= 16)
2558     {
2559       DBusMessage *message;      
2560       const char *header_data;
2561       int byte_order, header_len, body_len, header_padding;
2562       dbus_uint32_t header_len_unsigned, body_len_unsigned;
2563       
2564       _dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
2565
2566       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
2567
2568       if (header_data[2] != DBUS_MAJOR_PROTOCOL_VERSION)
2569         {
2570           _dbus_verbose ("Message has protocol version %d ours is %d\n",
2571                          (int) header_data[2], DBUS_MAJOR_PROTOCOL_VERSION);
2572           loader->corrupted = TRUE;
2573           return;
2574         }
2575       
2576       byte_order = header_data[0];
2577
2578       if (byte_order != DBUS_LITTLE_ENDIAN &&
2579           byte_order != DBUS_BIG_ENDIAN)
2580         {
2581           _dbus_verbose ("Message with bad byte order '%c' received\n",
2582                          byte_order);
2583           loader->corrupted = TRUE;
2584           return;
2585         }
2586
2587       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
2588       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
2589
2590       if (header_len_unsigned < 16)
2591         {
2592           _dbus_verbose ("Message had broken too-small header length %u\n",
2593                          header_len_unsigned);
2594           loader->corrupted = TRUE;
2595           return;
2596         }
2597
2598       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
2599           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
2600         {
2601           _dbus_verbose ("Header or body length too large (%u %u)\n",
2602                          header_len_unsigned,
2603                          body_len_unsigned);
2604           loader->corrupted = TRUE;
2605           return;
2606         }
2607
2608       /* Now that we know the values are in signed range, get
2609        * rid of stupid unsigned, just causes bugs
2610        */
2611       header_len = header_len_unsigned;
2612       body_len = body_len_unsigned;
2613       
2614       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
2615         {
2616           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
2617                          header_len);
2618           loader->corrupted = TRUE;
2619           return;
2620         }
2621       
2622       if (header_len + body_len > loader->max_message_size)
2623         {
2624           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %d\n",
2625                          header_len, body_len, loader->max_message_size);
2626           loader->corrupted = TRUE;
2627           return;
2628         }
2629
2630       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
2631         {
2632           HeaderField fields[FIELD_LAST];
2633           int i;
2634           int next_arg;          
2635
2636           _dbus_verbose_bytes_of_string (&loader->data, 0, header_len);
2637           if (!decode_header_data (&loader->data, header_len, byte_order,
2638                                    fields, &header_padding))
2639             {
2640               _dbus_verbose ("Header was invalid\n");
2641               loader->corrupted = TRUE;
2642               return;
2643             }
2644           
2645           next_arg = header_len;
2646           while (next_arg < (header_len + body_len))
2647             {
2648               int prev = next_arg;
2649
2650               if (!_dbus_marshal_validate_arg (&loader->data,
2651                                                byte_order,
2652                                                next_arg,
2653                                                &next_arg))
2654                 {
2655                   loader->corrupted = TRUE;
2656                   return;
2657                 }
2658
2659               _dbus_assert (next_arg > prev);
2660             }
2661           
2662           if (next_arg > (header_len + body_len))
2663             {
2664               _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
2665                              next_arg, header_len, body_len,
2666                              header_len + body_len);
2667               loader->corrupted = TRUE;
2668               return;
2669             }
2670
2671           message = dbus_message_new_empty_header ();
2672           if (message == NULL)
2673             break; /* ugh, postpone this I guess. */
2674
2675           message->byte_order = byte_order;
2676           message->header_padding = header_padding;
2677           
2678           /* Copy in the offsets we found */
2679           i = 0;
2680           while (i < FIELD_LAST)
2681             {
2682               message->header_fields[i] = fields[i];
2683               ++i;
2684             }
2685           
2686           if (!_dbus_list_append (&loader->messages, message))
2687             {
2688               dbus_message_unref (message);
2689               break;
2690             }
2691
2692           _dbus_assert (_dbus_string_get_length (&message->header) == 0);
2693           _dbus_assert (_dbus_string_get_length (&message->body) == 0);
2694
2695           _dbus_assert (_dbus_string_get_length (&loader->data) >=
2696                         (header_len + body_len));
2697           
2698           if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
2699             {
2700               _dbus_list_remove_last (&loader->messages, message);
2701               dbus_message_unref (message);
2702               break;
2703             }
2704           
2705           if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
2706             {
2707               dbus_bool_t result;
2708
2709               /* put the header back, we'll try again later */
2710               result = _dbus_string_copy_len (&message->header, 0, header_len,
2711                                               &loader->data, 0);
2712               _dbus_assert (result); /* because DBusString never reallocs smaller */
2713
2714               _dbus_list_remove_last (&loader->messages, message);
2715               dbus_message_unref (message);
2716               break;
2717             }
2718
2719           _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
2720           _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
2721
2722           _dbus_verbose ("Loaded message %p\n", message);
2723         }
2724       else
2725         break;
2726     }
2727 }
2728
2729 /**
2730  * Pops a loaded message (passing ownership of the message
2731  * to the caller). Returns #NULL if no messages have been
2732  * loaded.
2733  *
2734  * @param loader the loader.
2735  * @returns the next message, or #NULL if none.
2736  */
2737 DBusMessage*
2738 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
2739 {
2740   return _dbus_list_pop_first (&loader->messages);
2741 }
2742
2743
2744 /**
2745  * Checks whether the loader is confused due to bad data.
2746  * If messages are received that are invalid, the
2747  * loader gets confused and gives up permanently.
2748  * This state is called "corrupted."
2749  *
2750  * @param loader the loader
2751  * @returns #TRUE if the loader is hosed.
2752  */
2753 dbus_bool_t
2754 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
2755 {
2756   return loader->corrupted;
2757 }
2758
2759 /**
2760  * Sets the maximum size message we allow.
2761  *
2762  * @param loader the loader
2763  * @param size the max message size in bytes
2764  */
2765 void
2766 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
2767                                            long                size)
2768 {
2769   if (size > MAX_SANE_MESSAGE_SIZE)
2770     {
2771       _dbus_verbose ("clamping requested max message size %ld to %d\n",
2772                      size, MAX_SANE_MESSAGE_SIZE);
2773       size = MAX_SANE_MESSAGE_SIZE;
2774     }
2775   loader->max_message_size = size;
2776 }
2777
2778 /**
2779  * Gets the maximum allowed message size in bytes.
2780  *
2781  * @param loader the loader
2782  * @returns max size in bytes
2783  */
2784 long
2785 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
2786 {
2787   return loader->max_message_size;
2788 }
2789
2790 /** @} */
2791 #ifdef DBUS_BUILD_TESTS
2792 #include "dbus-test.h"
2793 #include <stdio.h>
2794
2795 static void
2796 message_iter_test (DBusMessage *message)
2797 {
2798   DBusMessageIter *iter;
2799   char *str;
2800   
2801   iter = dbus_message_get_args_iter (message);
2802
2803   /* String tests */
2804   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRING)
2805     _dbus_assert_not_reached ("Argument type isn't string");
2806
2807   str = dbus_message_iter_get_string (iter);
2808   if (strcmp (str, "Test string") != 0)
2809     _dbus_assert_not_reached ("Strings differ");
2810   dbus_free (str);
2811
2812   if (!dbus_message_iter_next (iter))
2813     _dbus_assert_not_reached ("Reached end of arguments");
2814
2815   /* Signed integer tests */
2816   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT32)
2817     _dbus_assert_not_reached ("Argument type isn't int32");
2818
2819   if (dbus_message_iter_get_int32 (iter) != -0x12345678)
2820     _dbus_assert_not_reached ("Signed integers differ");
2821
2822   if (!dbus_message_iter_next (iter))
2823     _dbus_assert_not_reached ("Reached end of fields");
2824   
2825   /* Unsigned integer tests */
2826   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT32)
2827     _dbus_assert_not_reached ("Argument type isn't int32");
2828
2829   if (dbus_message_iter_get_uint32 (iter) != 0xedd1e)
2830     _dbus_assert_not_reached ("Unsigned integers differ");
2831
2832   if (!dbus_message_iter_next (iter))
2833     _dbus_assert_not_reached ("Reached end of arguments");
2834
2835   /* Double tests */
2836   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_DOUBLE)
2837     _dbus_assert_not_reached ("Argument type isn't double");
2838
2839   if (dbus_message_iter_get_double (iter) != 3.14159)
2840     _dbus_assert_not_reached ("Doubles differ");
2841
2842   if (dbus_message_iter_next (iter))
2843     _dbus_assert_not_reached ("Didn't reach end of arguments");
2844   
2845   dbus_message_iter_unref (iter);
2846 }
2847
2848 static dbus_bool_t
2849 check_message_handling (DBusMessage *message)
2850 {
2851   DBusMessageIter *iter;
2852   int type;
2853   dbus_bool_t retval;
2854   dbus_int32_t client_serial;
2855   
2856   retval = FALSE;
2857   iter = NULL;
2858   
2859   client_serial = _dbus_message_get_client_serial (message);
2860
2861   /* can't use set_client_serial due to the assertions at the start of it */
2862   set_int_field (message, FIELD_CLIENT_SERIAL,
2863                  client_serial);
2864
2865   if (client_serial != _dbus_message_get_client_serial (message))
2866     {
2867       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
2868       goto failed;
2869     }
2870   
2871   /* If we implement message_set_arg (message, n, value)
2872    * then we would want to test it here
2873    */
2874   
2875   iter = dbus_message_get_args_iter (message);
2876   while ((type = dbus_message_iter_get_arg_type (iter)) != DBUS_TYPE_INVALID)
2877     {
2878       switch (type)
2879         {
2880         case DBUS_TYPE_NIL:
2881           break;
2882         case DBUS_TYPE_INT32:
2883           dbus_message_iter_get_int32 (iter);
2884           break;
2885         case DBUS_TYPE_UINT32:
2886           dbus_message_iter_get_uint32 (iter);
2887           break;
2888         case DBUS_TYPE_DOUBLE:
2889           dbus_message_iter_get_double (iter);
2890           break;
2891         case DBUS_TYPE_STRING:
2892           {
2893             char *str;
2894             str = dbus_message_iter_get_string (iter);
2895             dbus_free (str);
2896           }
2897           break;
2898         case DBUS_TYPE_INT32_ARRAY:
2899           {
2900             dbus_int32_t *values;
2901             int len;
2902             
2903             if (!dbus_message_iter_get_int32_array (iter, &values, &len))
2904               return FALSE;
2905
2906             dbus_free (values);
2907           }
2908           break;
2909         case DBUS_TYPE_UINT32_ARRAY:
2910           {
2911             dbus_uint32_t *values;
2912             int len;
2913             
2914             if (!dbus_message_iter_get_uint32_array (iter, &values, &len))
2915               return FALSE;
2916
2917             dbus_free (values);
2918           }
2919           break;
2920         case DBUS_TYPE_DOUBLE_ARRAY:
2921           {
2922             double *values;
2923             int len;
2924             
2925             if (!dbus_message_iter_get_double_array (iter, &values, &len))
2926               return FALSE;
2927
2928             dbus_free (values);
2929           }
2930           break;
2931         case DBUS_TYPE_STRING_ARRAY:
2932           {
2933             char **values;
2934             int len;
2935             
2936             if (!dbus_message_iter_get_string_array (iter, &values, &len))
2937               return FALSE;
2938
2939             dbus_free_string_array (values);
2940           }
2941           break;
2942           
2943         default:
2944           break;
2945         }
2946       
2947       if (!dbus_message_iter_next (iter))
2948         break;
2949     }
2950
2951   retval = TRUE;
2952   
2953  failed:
2954   if (iter)
2955     dbus_message_iter_unref (iter);
2956
2957   return retval;
2958 }
2959
2960 static dbus_bool_t
2961 check_have_valid_message (DBusMessageLoader *loader)
2962 {
2963   DBusMessage *message;
2964   dbus_bool_t retval;
2965
2966   message = NULL;
2967   retval = FALSE;
2968   
2969   if (_dbus_message_loader_get_is_corrupted (loader))
2970     {
2971       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
2972       goto failed;
2973     }
2974   
2975   message = _dbus_message_loader_pop_message (loader);
2976   if (message == NULL)
2977     {
2978       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
2979       goto failed;
2980     }
2981   
2982   if (_dbus_string_get_length (&loader->data) > 0)
2983     {
2984       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
2985       goto failed;
2986     }
2987
2988   /* Verify that we're able to properly deal with the message.
2989    * For example, this would detect improper handling of messages
2990    * in nonstandard byte order.
2991    */
2992   if (!check_message_handling (message))
2993     goto failed;  
2994   
2995   retval = TRUE;
2996
2997  failed:
2998   if (message)
2999     dbus_message_unref (message);
3000   return retval;
3001 }
3002
3003 static dbus_bool_t
3004 check_invalid_message (DBusMessageLoader *loader)
3005 {
3006   dbus_bool_t retval;
3007
3008   retval = FALSE;
3009   
3010   if (!_dbus_message_loader_get_is_corrupted (loader))
3011     {
3012       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
3013       goto failed;
3014     }
3015
3016   retval = TRUE;
3017
3018  failed:
3019   return retval;
3020 }
3021
3022 static dbus_bool_t
3023 check_incomplete_message (DBusMessageLoader *loader)
3024 {
3025   DBusMessage *message;
3026   dbus_bool_t retval;
3027
3028   message = NULL;
3029   retval = FALSE;
3030   
3031   if (_dbus_message_loader_get_is_corrupted (loader))
3032     {
3033       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
3034       goto failed;
3035     }
3036   
3037   message = _dbus_message_loader_pop_message (loader);
3038   if (message != NULL)
3039     {
3040       _dbus_warn ("loaded message that was expected to be incomplete\n");
3041       goto failed;
3042     }
3043
3044   retval = TRUE;
3045
3046  failed:
3047   if (message)
3048     dbus_message_unref (message);
3049   return retval;
3050 }
3051
3052 static dbus_bool_t
3053 check_loader_results (DBusMessageLoader      *loader,
3054                       DBusMessageValidity     validity)
3055 {
3056   switch (validity)
3057     {
3058     case _DBUS_MESSAGE_VALID:
3059       return check_have_valid_message (loader);
3060     case _DBUS_MESSAGE_INVALID:
3061       return check_invalid_message (loader);
3062     case _DBUS_MESSAGE_INCOMPLETE:
3063       return check_incomplete_message (loader);
3064     case _DBUS_MESSAGE_UNKNOWN:
3065       return TRUE;
3066     }
3067
3068   _dbus_assert_not_reached ("bad DBusMessageValidity");
3069   return FALSE;
3070 }
3071
3072
3073 /**
3074  * Loads the message in the given message file.
3075  *
3076  * @param filename filename to load
3077  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
3078  * @param data string to load message into
3079  * @returns #TRUE if the message was loaded
3080  */
3081 dbus_bool_t
3082 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
3083                                             dbus_bool_t          is_raw,
3084                                             DBusString          *data)
3085 {
3086   dbus_bool_t retval;
3087
3088   retval = FALSE;  
3089
3090   if (is_raw)
3091     {
3092       DBusResultCode result;
3093
3094       result = _dbus_file_get_contents (data, filename);
3095       if (result != DBUS_RESULT_SUCCESS)
3096         {
3097           const char *s;      
3098           _dbus_string_get_const_data (filename, &s);
3099           _dbus_warn ("Could not load message file %s\n", s);
3100           goto failed;
3101         }
3102     }
3103   else
3104     {
3105       if (!_dbus_message_data_load (data, filename))
3106         {
3107           const char *s;      
3108           _dbus_string_get_const_data (filename, &s);
3109           _dbus_warn ("Could not load message file %s\n", s);
3110           goto failed;
3111         }
3112     }
3113
3114   retval = TRUE;
3115   
3116  failed:
3117
3118   return retval;
3119 }
3120
3121 /**
3122  * Tries loading the message in the given message file
3123  * and verifies that DBusMessageLoader can handle it.
3124  *
3125  * @param filename filename to load
3126  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
3127  * @param expected_validity what the message has to be like to return #TRUE
3128  * @returns #TRUE if the message has the expected validity
3129  */
3130 dbus_bool_t
3131 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
3132                                            dbus_bool_t          is_raw,
3133                                            DBusMessageValidity  expected_validity)
3134 {
3135   DBusString data;
3136   dbus_bool_t retval;
3137
3138   retval = FALSE;
3139   
3140   if (!_dbus_string_init (&data, _DBUS_INT_MAX))
3141     _dbus_assert_not_reached ("could not allocate string\n");
3142
3143   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
3144                                                    &data))
3145     goto failed;
3146
3147   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
3148
3149  failed:
3150
3151   if (!retval)
3152     {
3153       const char *s;
3154
3155       if (_dbus_string_get_length (&data) > 0)
3156         _dbus_verbose_bytes_of_string (&data, 0,
3157                                        _dbus_string_get_length (&data));
3158       
3159       _dbus_string_get_const_data (filename, &s);
3160       _dbus_warn ("Failed message loader test on %s\n",
3161                   s);
3162     }
3163   
3164   _dbus_string_free (&data);
3165
3166   return retval;
3167 }
3168
3169 /**
3170  * Tries loading the given message data.
3171  *
3172  *
3173  * @param data the message data
3174  * @param expected_validity what the message has to be like to return #TRUE
3175  * @returns #TRUE if the message has the expected validity
3176  */
3177 dbus_bool_t
3178 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
3179                                            DBusMessageValidity  expected_validity)
3180 {
3181   DBusMessageLoader *loader;
3182   dbus_bool_t retval;
3183   int len;
3184   int i;
3185
3186   loader = NULL;
3187   retval = FALSE;
3188
3189   /* Write the data one byte at a time */
3190   
3191   loader = _dbus_message_loader_new ();
3192
3193   len = _dbus_string_get_length (data);
3194   for (i = 0; i < len; i++)
3195     {
3196       DBusString *buffer;
3197
3198       _dbus_message_loader_get_buffer (loader, &buffer);
3199       _dbus_string_append_byte (buffer,
3200                                 _dbus_string_get_byte (data, i));
3201       _dbus_message_loader_return_buffer (loader, buffer, 1);
3202     }
3203   
3204   if (!check_loader_results (loader, expected_validity))
3205     goto failed;
3206
3207   _dbus_message_loader_unref (loader);
3208   loader = NULL;
3209
3210   /* Write the data all at once */
3211   
3212   loader = _dbus_message_loader_new ();
3213
3214   {
3215     DBusString *buffer;
3216     
3217     _dbus_message_loader_get_buffer (loader, &buffer);
3218     _dbus_string_copy (data, 0, buffer,
3219                        _dbus_string_get_length (buffer));
3220     _dbus_message_loader_return_buffer (loader, buffer, 1);
3221   }
3222   
3223   if (!check_loader_results (loader, expected_validity))
3224     goto failed;
3225
3226   _dbus_message_loader_unref (loader);
3227   loader = NULL;  
3228
3229   /* Write the data 2 bytes at a time */
3230   
3231   loader = _dbus_message_loader_new ();
3232
3233   len = _dbus_string_get_length (data);
3234   for (i = 0; i < len; i += 2)
3235     {
3236       DBusString *buffer;
3237
3238       _dbus_message_loader_get_buffer (loader, &buffer);
3239       _dbus_string_append_byte (buffer,
3240                                 _dbus_string_get_byte (data, i));
3241       if ((i+1) < len)
3242         _dbus_string_append_byte (buffer,
3243                                   _dbus_string_get_byte (data, i+1));
3244       _dbus_message_loader_return_buffer (loader, buffer, 1);
3245     }
3246   
3247   if (!check_loader_results (loader, expected_validity))
3248     goto failed;
3249
3250   _dbus_message_loader_unref (loader);
3251   loader = NULL;
3252   
3253   retval = TRUE;
3254   
3255  failed:
3256   
3257   if (loader)
3258     _dbus_message_loader_unref (loader);
3259   
3260   return retval;
3261 }
3262
3263 static dbus_bool_t
3264 process_test_subdir (const DBusString          *test_base_dir,
3265                      const char                *subdir,
3266                      DBusMessageValidity        validity,
3267                      DBusForeachMessageFileFunc function,
3268                      void                      *user_data)
3269 {
3270   DBusString test_directory;
3271   DBusString filename;
3272   DBusDirIter *dir;
3273   dbus_bool_t retval;
3274   DBusResultCode result;
3275
3276   retval = FALSE;
3277   dir = NULL;
3278   
3279   if (!_dbus_string_init (&test_directory, _DBUS_INT_MAX))
3280     _dbus_assert_not_reached ("didn't allocate test_directory\n");
3281
3282   _dbus_string_init_const (&filename, subdir);
3283   
3284   if (!_dbus_string_copy (test_base_dir, 0,
3285                           &test_directory, 0))
3286     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
3287   
3288   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
3289     _dbus_assert_not_reached ("couldn't allocate full path");
3290
3291   _dbus_string_free (&filename);
3292   if (!_dbus_string_init (&filename, _DBUS_INT_MAX))
3293     _dbus_assert_not_reached ("didn't allocate filename string\n");
3294   
3295   dir = _dbus_directory_open (&test_directory, &result);
3296   if (dir == NULL)
3297     {
3298       const char *s;
3299       _dbus_string_get_const_data (&test_directory, &s);
3300       _dbus_warn ("Could not open %s: %s\n", s,
3301                   dbus_result_to_string (result));
3302       goto failed;
3303     }
3304
3305   printf ("Testing:\n");
3306   
3307   result = DBUS_RESULT_SUCCESS;
3308  next:
3309   while (_dbus_directory_get_next_file (dir, &filename, &result))
3310     {
3311       DBusString full_path;
3312       dbus_bool_t is_raw;
3313       
3314       if (!_dbus_string_init (&full_path, _DBUS_INT_MAX))
3315         _dbus_assert_not_reached ("couldn't init string");
3316
3317       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
3318         _dbus_assert_not_reached ("couldn't copy dir to full_path");
3319
3320       if (!_dbus_concat_dir_and_file (&full_path, &filename))
3321         _dbus_assert_not_reached ("couldn't concat file to dir");
3322
3323       if (_dbus_string_ends_with_c_str (&filename, ".message"))
3324         is_raw = FALSE;
3325       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
3326         is_raw = TRUE;
3327       else
3328         {
3329           const char *filename_c;
3330           _dbus_string_get_const_data (&filename, &filename_c);
3331           _dbus_verbose ("Skipping non-.message file %s\n",
3332                          filename_c);
3333           _dbus_string_free (&full_path);
3334           goto next;
3335         }
3336
3337       {
3338         const char *s;
3339         _dbus_string_get_const_data (&filename, &s);
3340         printf ("    %s\n", s);
3341       }
3342       
3343       _dbus_verbose (" expecting %s\n",
3344                      validity == _DBUS_MESSAGE_VALID ? "valid" :
3345                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
3346                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")));
3347       
3348       if (! (*function) (&full_path, is_raw, validity, user_data))
3349         {
3350           _dbus_string_free (&full_path);
3351           goto failed;
3352         }
3353       else
3354         _dbus_string_free (&full_path);
3355     }
3356
3357   if (result != DBUS_RESULT_SUCCESS)
3358     {
3359       const char *s;
3360       _dbus_string_get_const_data (&test_directory, &s);
3361       _dbus_warn ("Could not get next file in %s: %s\n",
3362                   s, dbus_result_to_string (result));
3363       goto failed;
3364     }
3365     
3366   retval = TRUE;
3367   
3368  failed:
3369
3370   if (dir)
3371     _dbus_directory_close (dir);
3372   _dbus_string_free (&test_directory);
3373   _dbus_string_free (&filename);
3374
3375   return retval;
3376 }
3377                      
3378 /**
3379  * Runs the given function on every message file in the test suite.
3380  * The function should return #FALSE on test failure or fatal error.
3381  *
3382  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
3383  * @param func the function to run
3384  * @param user_data data for function
3385  * @returns #FALSE if there's a failure
3386  */
3387 dbus_bool_t
3388 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
3389                                                DBusForeachMessageFileFunc func,
3390                                                void                      *user_data)
3391 {
3392   DBusString test_directory;
3393   dbus_bool_t retval;
3394
3395   retval = FALSE;
3396   
3397   _dbus_string_init_const (&test_directory, test_data_dir);
3398
3399   if (!process_test_subdir (&test_directory, "valid-messages",
3400                             _DBUS_MESSAGE_VALID, func, user_data))
3401     goto failed;
3402
3403   if (!process_test_subdir (&test_directory, "invalid-messages",
3404                             _DBUS_MESSAGE_INVALID, func, user_data))
3405     goto failed;
3406   
3407   if (!process_test_subdir (&test_directory, "incomplete-messages",
3408                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
3409     goto failed;
3410
3411   retval = TRUE;
3412   
3413  failed:
3414
3415   _dbus_string_free (&test_directory);
3416   
3417   return retval;
3418 }
3419
3420 /**
3421  * @ingroup DBusMessageInternals
3422  * Unit test for DBusMessage.
3423  *
3424  * @returns #TRUE on success.
3425  */
3426 dbus_bool_t
3427 _dbus_message_test (const char *test_data_dir)
3428 {
3429   DBusMessage *message;
3430   DBusMessageLoader *loader;
3431   int i;
3432   const char *data;
3433   dbus_int32_t our_int;
3434   char *our_str;
3435   double our_double;
3436   dbus_bool_t our_bool;
3437   
3438   /* Test the vararg functions */
3439   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
3440   _dbus_message_set_client_serial (message, 1);
3441   dbus_message_append_args (message,
3442                             DBUS_TYPE_INT32, -0x12345678,
3443                             DBUS_TYPE_STRING, "Test string",
3444                             DBUS_TYPE_DOUBLE, 3.14159,
3445                             DBUS_TYPE_BOOLEAN, TRUE,
3446                             0);
3447   _dbus_verbose_bytes_of_string (&message->header, 0,
3448                                  _dbus_string_get_length (&message->header));
3449   _dbus_verbose_bytes_of_string (&message->body, 0,
3450                                  _dbus_string_get_length (&message->body));
3451   
3452   if (dbus_message_get_args (message,
3453                              DBUS_TYPE_INT32, &our_int,
3454                              DBUS_TYPE_STRING, &our_str,
3455                              DBUS_TYPE_DOUBLE, &our_double,
3456                              DBUS_TYPE_BOOLEAN, &our_bool,
3457                              0) != DBUS_RESULT_SUCCESS)
3458     _dbus_assert_not_reached ("Could not get arguments");
3459
3460   if (our_int != -0x12345678)
3461     _dbus_assert_not_reached ("integers differ!");
3462
3463   if (our_double != 3.14159)
3464     _dbus_assert_not_reached ("doubles differ!");
3465
3466   if (strcmp (our_str, "Test string") != 0)
3467     _dbus_assert_not_reached ("strings differ!");
3468
3469   if (!our_bool)
3470     _dbus_assert_not_reached ("booleans differ");
3471   
3472   dbus_free (our_str);
3473   dbus_message_unref (message);
3474   
3475   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
3476   _dbus_message_set_client_serial (message, 1);
3477   _dbus_message_set_reply_serial (message, 0x12345678);
3478
3479   dbus_message_append_string (message, "Test string");
3480   dbus_message_append_int32 (message, -0x12345678);
3481   dbus_message_append_uint32 (message, 0xedd1e);
3482   dbus_message_append_double (message, 3.14159);
3483
3484   message_iter_test (message);
3485
3486   /* Message loader test */
3487   _dbus_message_lock (message);
3488   loader = _dbus_message_loader_new ();
3489
3490   /* Write the header data one byte at a time */
3491   _dbus_string_get_const_data (&message->header, &data);
3492   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
3493     {
3494       DBusString *buffer;
3495
3496       _dbus_message_loader_get_buffer (loader, &buffer);
3497       _dbus_string_append_byte (buffer, data[i]);
3498       _dbus_message_loader_return_buffer (loader, buffer, 1);
3499     }
3500
3501   /* Write the body data one byte at a time */
3502   _dbus_string_get_const_data (&message->body, &data);
3503   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
3504     {
3505       DBusString *buffer;
3506
3507       _dbus_message_loader_get_buffer (loader, &buffer);
3508       _dbus_string_append_byte (buffer, data[i]);
3509       _dbus_message_loader_return_buffer (loader, buffer, 1);
3510     }
3511
3512   dbus_message_unref (message);
3513
3514   /* Now pop back the message */
3515   if (_dbus_message_loader_get_is_corrupted (loader))
3516     _dbus_assert_not_reached ("message loader corrupted");
3517   
3518   message = _dbus_message_loader_pop_message (loader);
3519   if (!message)
3520     _dbus_assert_not_reached ("received a NULL message");
3521
3522   if (_dbus_message_get_reply_serial (message) != 0x12345678)
3523     _dbus_assert_not_reached ("reply serial fields differ");
3524   
3525   message_iter_test (message);
3526   
3527   dbus_message_unref (message);
3528   _dbus_message_loader_unref (loader);
3529
3530   /* Now load every message in test_data_dir if we have one */
3531   if (test_data_dir == NULL)
3532     return TRUE;
3533
3534   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
3535                                                         (DBusForeachMessageFileFunc)
3536                                                         dbus_internal_do_not_use_try_message_file,
3537                                                         NULL);
3538 }
3539
3540 #endif /* DBUS_BUILD_TESTS */