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