add more verbose debug spew
[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_argument_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_INT32:
1050           if (!dbus_message_append_int32 (message, va_arg (var_args, dbus_int32_t)))
1051             goto enomem;
1052           break;
1053         case DBUS_TYPE_UINT32:
1054           if (!dbus_message_append_uint32 (message, va_arg (var_args, dbus_uint32_t)))
1055             goto enomem;            
1056           break;
1057         case DBUS_TYPE_DOUBLE:
1058           if (!dbus_message_append_double (message, va_arg (var_args, double)))
1059             goto enomem;
1060           break;
1061         case DBUS_TYPE_STRING:
1062           if (!dbus_message_append_string (message, va_arg (var_args, const char *)))
1063             goto enomem;
1064           break;
1065         case DBUS_TYPE_BYTE_ARRAY:
1066           {
1067             int len;
1068             unsigned char *data;
1069
1070             data = va_arg (var_args, unsigned char *);
1071             len = va_arg (var_args, int);
1072
1073             if (!dbus_message_append_byte_array (message, data, len))
1074               goto enomem;
1075           }
1076           break;
1077         case DBUS_TYPE_STRING_ARRAY:
1078           {
1079             int len;
1080             const char **data;
1081             
1082             data = va_arg (var_args, const char **);
1083             len = va_arg (var_args, int);
1084
1085             if (!dbus_message_append_string_array (message, data, len))
1086               goto enomem;
1087           }
1088           break;
1089           
1090         default:
1091           _dbus_warn ("Unknown field type %d\n", type);
1092         }
1093
1094       type = va_arg (var_args, int);
1095     }
1096
1097   return TRUE;
1098
1099  enomem:
1100   _dbus_string_set_length (&message->body, old_len);
1101   return FALSE;
1102 }
1103
1104 /**
1105  * Appends a 32 bit signed integer to the message.
1106  *
1107  * @param message the message
1108  * @param value the integer value
1109  * @returns #TRUE on success
1110  */
1111 dbus_bool_t
1112 dbus_message_append_int32 (DBusMessage  *message,
1113                            dbus_int32_t  value)
1114 {
1115   _dbus_assert (!message->locked);
1116
1117   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
1118     {
1119       _dbus_string_shorten (&message->body, 1);
1120       return FALSE;
1121     }
1122   
1123   return _dbus_marshal_int32 (&message->body,
1124                               message->byte_order, value);
1125 }
1126
1127 /**
1128  * Appends a 32 bit unsigned integer to the message.
1129  *
1130  * @param message the message
1131  * @param value the integer value
1132  * @returns #TRUE on success
1133  */
1134 dbus_bool_t
1135 dbus_message_append_uint32 (DBusMessage   *message,
1136                             dbus_uint32_t  value)
1137 {
1138   _dbus_assert (!message->locked);
1139
1140   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
1141     {
1142       _dbus_string_shorten (&message->body, 1);
1143       return FALSE;
1144     }
1145   
1146   return _dbus_marshal_uint32 (&message->body,
1147                                message->byte_order, value);
1148 }
1149
1150 /**
1151  * Appends a double value to the message.
1152  *
1153  * @param message the message
1154  * @param value the double value
1155  * @returns #TRUE on success
1156  */
1157 dbus_bool_t
1158 dbus_message_append_double (DBusMessage *message,
1159                             double       value)
1160 {
1161   _dbus_assert (!message->locked);
1162
1163   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
1164     {
1165       _dbus_string_shorten (&message->body, 1);
1166       return FALSE;
1167     }
1168   
1169   return _dbus_marshal_double (&message->body,
1170                                message->byte_order, value);
1171 }
1172
1173 /**
1174  * Appends a UTF-8 string to the message.
1175  *
1176  * @param message the message
1177  * @param value the string
1178  * @returns #TRUE on success
1179  */
1180 dbus_bool_t
1181 dbus_message_append_string (DBusMessage *message,
1182                             const char  *value)
1183 {
1184   _dbus_assert (!message->locked);
1185
1186   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
1187     {
1188       _dbus_string_shorten (&message->body, 1);
1189       return FALSE;
1190     }
1191   
1192   return _dbus_marshal_string (&message->body,
1193                                message->byte_order, value);
1194 }
1195
1196 /**
1197  * Appends a byte array to the message.
1198  *
1199  * @param message the message
1200  * @param value the array
1201  * @param len the length of the array
1202  * @returns #TRUE on success
1203  */
1204 dbus_bool_t
1205 dbus_message_append_byte_array (DBusMessage         *message,
1206                                 unsigned const char *value,
1207                                 int                 len)
1208 {
1209   _dbus_assert (!message->locked);
1210
1211   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
1212     {
1213       _dbus_string_shorten (&message->body, 1);
1214       return FALSE;
1215     }
1216   
1217   return _dbus_marshal_byte_array (&message->body,
1218                                    message->byte_order, value, len);
1219 }
1220
1221 /**
1222  * Appends a string array to the message.
1223  *
1224  * @param message the message
1225  * @param value the array
1226  * @param len the length of the array
1227  * @returns #TRUE on success
1228  */
1229 dbus_bool_t
1230 dbus_message_append_string_array (DBusMessage *message,
1231                                   const char **value,
1232                                   int          len)
1233 {
1234   _dbus_assert (!message->locked);
1235
1236   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING_ARRAY))
1237     {
1238       _dbus_string_shorten (&message->body, 1);
1239       return FALSE;
1240     }
1241   
1242   return _dbus_marshal_string_array (&message->body,
1243                                      message->byte_order, value, len);
1244 }
1245
1246 /**
1247  * Gets arguments from a message given a variable argument list.
1248  * The variable argument list should contain the type of the
1249  * argumen followed by a pointer to where the value should be
1250  * stored. The list is terminated with 0.
1251  *
1252  * @param message the message
1253  * @param first_arg_type the first argument type
1254  * @param ... location for first argument value, then list of type-location pairs
1255  * @returns result code
1256  */
1257 DBusResultCode
1258 dbus_message_get_args (DBusMessage *message,
1259                        int          first_arg_type,
1260                        ...)
1261 {
1262   DBusResultCode retval;
1263   va_list var_args;
1264
1265   va_start (var_args, first_arg_type);
1266   retval = dbus_message_get_args_valist (message, first_arg_type, var_args);
1267   va_end (var_args);
1268
1269   return retval;
1270 }
1271
1272 /**
1273  * This function takes a va_list for use by language bindings
1274  *
1275  * @todo this function (or some lower-level non-convenience function)
1276  * needs better error handling; should allow the application to
1277  * distinguish between out of memory, and bad data from the remote
1278  * app. It also needs to not leak a bunch of args when it gets
1279  * to the arg that's bad, as that would be a security hole
1280  * (allow one app to force another to leak memory)
1281  *
1282  * @todo We need to free the argument data when an error occurs.
1283  *
1284  * @see dbus_message_get_args
1285  * @param message the message
1286  * @param first_arg_type type of the first argument
1287  * @param var_args return location for first argument, followed by list of type/location pairs
1288  * @returns result code
1289  */
1290 DBusResultCode
1291 dbus_message_get_args_valist (DBusMessage *message,
1292                               int          first_arg_type,
1293                               va_list      var_args)
1294 {
1295   int spec_type, msg_type, i;
1296   DBusMessageIter *iter;
1297
1298   iter = dbus_message_get_args_iter (message);
1299
1300   if (iter == NULL)
1301     return DBUS_RESULT_NO_MEMORY;
1302   
1303   spec_type = first_arg_type;
1304   i = 0;
1305   
1306   while (spec_type != 0)
1307     {
1308       msg_type = dbus_message_iter_get_arg_type (iter);      
1309       
1310       if (msg_type != spec_type)
1311         {
1312           _dbus_verbose ("Argument %d is specified to be of type \"%s\", but "
1313                          "is actually of type \"%s\"\n", i,
1314                          _dbus_type_to_string (spec_type),
1315                          _dbus_type_to_string (msg_type));
1316           dbus_message_iter_unref (iter);
1317
1318           return DBUS_RESULT_INVALID_ARGS;
1319         }
1320
1321       switch (spec_type)
1322         {
1323         case DBUS_TYPE_INT32:
1324           {
1325             dbus_int32_t *ptr;
1326
1327             ptr = va_arg (var_args, dbus_int32_t *);
1328
1329             *ptr = dbus_message_iter_get_int32 (iter);
1330             break;
1331           }
1332         case DBUS_TYPE_UINT32:
1333           {
1334             dbus_uint32_t *ptr;
1335
1336             ptr = va_arg (var_args, dbus_uint32_t *);
1337
1338             *ptr = dbus_message_iter_get_uint32 (iter);
1339             break;
1340           }
1341
1342         case DBUS_TYPE_DOUBLE:
1343           {
1344             double *ptr;
1345
1346             ptr = va_arg (var_args, double *);
1347
1348             *ptr = dbus_message_iter_get_double (iter);
1349             break;
1350           }
1351
1352         case DBUS_TYPE_STRING:
1353           {
1354             char **ptr;
1355
1356             ptr = va_arg (var_args, char **);
1357
1358             *ptr = dbus_message_iter_get_string (iter);
1359
1360             if (!*ptr)
1361               return DBUS_RESULT_NO_MEMORY;
1362             
1363             break;
1364           }
1365
1366         case DBUS_TYPE_BYTE_ARRAY:
1367           {
1368             unsigned char **ptr;
1369             int *len;
1370
1371             ptr = va_arg (var_args, unsigned char **);
1372             len = va_arg (var_args, int *);
1373
1374             *ptr = dbus_message_iter_get_byte_array (iter, len);
1375
1376             if (!*ptr)
1377               return DBUS_RESULT_NO_MEMORY;
1378             
1379             break;
1380           }
1381         case DBUS_TYPE_STRING_ARRAY:
1382           {
1383             char ***ptr;
1384             int *len;
1385
1386             ptr = va_arg (var_args, char ***);
1387             len = va_arg (var_args, int *);
1388
1389             *ptr = dbus_message_iter_get_string_array (iter, len);
1390             
1391             if (!*ptr)
1392               return DBUS_RESULT_NO_MEMORY;
1393             
1394             break;
1395           }
1396         default:          
1397           _dbus_warn ("Unknown field type %d\n", spec_type);
1398         }
1399       
1400       spec_type = va_arg (var_args, int);
1401       if (spec_type != 0 && !dbus_message_iter_next (iter))
1402         {
1403           _dbus_verbose ("More fields than exist in the message were specified or field is corrupt\n");
1404
1405           dbus_message_iter_unref (iter);  
1406           return DBUS_RESULT_INVALID_ARGS;
1407         }
1408       i++;
1409     }
1410
1411   dbus_message_iter_unref (iter);
1412   return DBUS_RESULT_SUCCESS;
1413 }
1414
1415 /**
1416  * Returns a DBusMessageIter representing the arguments of the
1417  * message passed in.
1418  *
1419  * @todo IMO the message iter should follow the GtkTextIter pattern,
1420  * a static object with a "stamp" value used to detect invalid
1421  * iter uses (uninitialized or after changing the message).
1422  * ref/unref is kind of annoying to deal with, and slower too.
1423  * This implies not ref'ing the message from the iter.
1424  *
1425  * @param message the message
1426  * @returns a new iter.
1427  */
1428 DBusMessageIter *
1429 dbus_message_get_args_iter (DBusMessage *message)
1430 {
1431   DBusMessageIter *iter;
1432   
1433   iter = dbus_new (DBusMessageIter, 1);
1434
1435   dbus_message_ref (message);
1436   
1437   iter->refcount = 1;
1438   iter->message = message;
1439   iter->pos = 0;
1440
1441   return iter;
1442 }
1443
1444 /**
1445  * Increments the reference count of a DBusMessageIter.
1446  *
1447  * @param iter the message iter
1448  * @see dbus_message_iter_unref
1449  */
1450 void
1451 dbus_message_iter_ref (DBusMessageIter *iter)
1452 {
1453   _dbus_assert (iter->refcount > 0);
1454   
1455   iter->refcount += 1;
1456 }
1457
1458 /**
1459  * Decrements the reference count of a DBusMessageIter.
1460  *
1461  * @param iter The message iter
1462  * @see dbus_message_iter_ref
1463  */
1464 void
1465 dbus_message_iter_unref (DBusMessageIter *iter)
1466 {
1467   _dbus_assert (iter->refcount > 0);
1468
1469   iter->refcount -= 1;
1470
1471   if (iter->refcount == 0)
1472     {
1473       dbus_message_unref (iter->message);
1474
1475       dbus_free (iter);
1476     }
1477 }
1478
1479 /**
1480  * Checks if an iterator has any more fields.
1481  *
1482  * @param iter the message iter
1483  * @returns #TRUE if there are more fields
1484  * following
1485  */
1486 dbus_bool_t
1487 dbus_message_iter_has_next (DBusMessageIter *iter)
1488 {
1489   int end_pos;
1490   
1491   if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
1492                                       iter->message->byte_order,
1493                                       iter->pos, &end_pos))
1494     return FALSE;
1495   
1496   if (end_pos >= _dbus_string_get_length (&iter->message->body))
1497     return FALSE;
1498   
1499   return TRUE;  
1500 }
1501
1502 /**
1503  * Moves the iterator to the next field.
1504  *
1505  * @param iter The message iter
1506  * @returns #TRUE if the iterator was moved to the next field
1507  */
1508 dbus_bool_t
1509 dbus_message_iter_next (DBusMessageIter *iter)
1510 {
1511   int end_pos;
1512   
1513   if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
1514                                       iter->message->byte_order,
1515                                       iter->pos, &end_pos))
1516     return FALSE;
1517
1518   if (end_pos >= _dbus_string_get_length (&iter->message->body))
1519     return FALSE;
1520
1521   iter->pos = end_pos;
1522
1523   return TRUE;
1524 }
1525
1526 /**
1527  * Returns the argument type of the argument that the
1528  * message iterator points at.
1529  *
1530  * @param iter the message iter
1531  * @returns the field type
1532  */
1533 int
1534 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
1535 {
1536   const char *data;
1537
1538   if (iter->pos >= _dbus_string_get_length (&iter->message->body))
1539     return DBUS_TYPE_INVALID;
1540
1541   _dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
1542
1543   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING_ARRAY)
1544     return *data;
1545
1546   return DBUS_TYPE_INVALID;
1547 }
1548
1549 /**
1550  * Returns the string value that an iterator may point to.
1551  * Note that you need to check that the iterator points to
1552  * a string value before using this function.
1553  *
1554  * @see dbus_message_iter_get_field_type
1555  * @param iter the message iter
1556  * @returns the string
1557  */
1558 char *
1559 dbus_message_iter_get_string (DBusMessageIter *iter)
1560 {
1561   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING);
1562
1563   return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
1564                                  iter->pos + 1, NULL);
1565 }
1566
1567 /**
1568  * Returns the 32 bit signed integer value that an iterator may point to.
1569  * Note that you need to check that the iterator points to
1570  * an integer value before using this function.
1571  *
1572  * @see dbus_message_iter_get_field_type
1573  * @param iter the message iter
1574  * @returns the integer
1575  */
1576 int
1577 dbus_message_iter_get_int32 (DBusMessageIter *iter)
1578 {
1579   return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
1580                                 iter->pos + 1, NULL);
1581 }
1582
1583 /**
1584  * Returns the 32 bit unsigned integer value that an iterator may point to.
1585  * Note that you need to check that the iterator points to
1586  * an unsigned integer value before using this function.
1587  *
1588  * @see dbus_message_iter_get_field_type
1589  * @param iter the message iter
1590  * @returns the integer
1591  */
1592 int
1593 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
1594 {
1595   return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
1596                                  iter->pos + 1, NULL);
1597 }
1598
1599 /**
1600  * Returns the double value that an iterator may point to.
1601  * Note that you need to check that the iterator points to
1602  * a string value before using this function.
1603  *
1604  * @see dbus_message_iter_get_field_type
1605  * @param iter the message iter
1606  * @returns the double
1607  */
1608 double
1609 dbus_message_iter_get_double (DBusMessageIter *iter)
1610 {
1611   return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
1612                                  iter->pos + 1, NULL);
1613 }
1614
1615 /**
1616  * Returns the byte array that the iterator may point to.
1617  * Note that you need to check that the iterator points
1618  * to a byte array prior to using this function.
1619  *
1620  * @todo this function should probably take "unsigned char **" as
1621  * an out param argument, and return boolean or result code.
1622  *
1623  * @param iter the iterator
1624  * @param len return location for length of byte array
1625  * @returns the byte array
1626  */
1627 unsigned char *
1628 dbus_message_iter_get_byte_array (DBusMessageIter *iter,
1629                                   int             *len)
1630 {
1631   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BYTE_ARRAY);
1632
1633   return _dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
1634                                      iter->pos + 1, NULL, len);
1635 }
1636
1637 /**
1638  * Returns the string array that the iterator may point to.
1639  * Note that you need to check that the iterator points
1640  * to a byte array prior to using this function.
1641  *
1642  * @todo this function should probably take "char **" as
1643  * an out param argument, and return boolean or result code.
1644  *
1645  * @param iter the iterator
1646  * @param len return location for length of byte array
1647  * @returns the byte array
1648  */
1649 char **
1650 dbus_message_iter_get_string_array (DBusMessageIter *iter,
1651                                     int             *len)
1652 {
1653   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING_ARRAY);
1654
1655   return _dbus_demarshal_string_array (&iter->message->body, iter->message->byte_order,
1656                                        iter->pos + 1, NULL, len);
1657 }
1658
1659 /**
1660  * Sets the message sender.
1661  *
1662  * @param message the message
1663  * @param sender the sender
1664  * @returns #FALSE if not enough memory
1665  */
1666 dbus_bool_t
1667 dbus_message_set_sender (DBusMessage  *message,
1668                          const char   *sender)
1669 {
1670   _dbus_assert (!message->locked);
1671
1672   if (sender == NULL)
1673     {
1674       delete_string_field (message, FIELD_SENDER);
1675       return TRUE;
1676     }
1677   else
1678     {
1679       return set_string_field (message,
1680                                FIELD_SENDER,
1681                                sender);
1682     }
1683 }
1684
1685 /**
1686  * Sets a flag indicating that the message is an error reply
1687  * message, i.e. an "exception" rather than a normal response.
1688  *
1689  * @param message the message
1690  * @param is_error_reply #TRUE if this is an error message.
1691  */
1692 void
1693 dbus_message_set_is_error (DBusMessage *message,
1694                            dbus_bool_t  is_error_reply)
1695 {
1696   char *header;
1697   
1698   _dbus_assert (!message->locked);
1699   
1700   _dbus_string_get_data_len (&message->header, &header, 1, 1);
1701   
1702   if (is_error_reply)
1703     *header |= DBUS_HEADER_FLAG_ERROR;
1704   else
1705     *header &= ~DBUS_HEADER_FLAG_ERROR;    
1706 }
1707
1708 /**
1709  * Returns #TRUE if the message is an error
1710  * reply to some previous message we sent.
1711  *
1712  * @param message the message
1713  * @returns #TRUE if the message is an error
1714  */
1715 dbus_bool_t
1716 dbus_message_get_is_error (DBusMessage *message)
1717 {
1718   const char *header;
1719
1720   _dbus_string_get_const_data_len (&message->header, &header, 1, 1);
1721
1722   return (*header & DBUS_HEADER_FLAG_ERROR) != 0;
1723 }
1724
1725 /**
1726  * Gets the service which originated this message,
1727  * or #NULL if unknown or inapplicable.
1728  *
1729  * @param message the message
1730  * @returns the service name or #NULL
1731  */
1732 const char*
1733 dbus_message_get_sender (DBusMessage *message)
1734 {
1735   return get_string_field (message, FIELD_SENDER, NULL);
1736 }
1737
1738 dbus_bool_t
1739 dbus_message_name_is (DBusMessage *message,
1740                       const char  *name)
1741 {
1742   if (dbus_message_get_name (message) &&
1743       strcmp (dbus_message_get_name (message), name) == 0)
1744     return TRUE;
1745   else
1746     return FALSE;
1747 }
1748
1749 /** @} */
1750
1751 /**
1752  * @addtogroup DBusMessageInternals
1753  *
1754  * @{
1755  */
1756 /**
1757  * @typedef DBusMessageLoader
1758  *
1759  * The DBusMessageLoader object encapsulates the process of converting
1760  * a byte stream into a series of DBusMessage. It buffers the incoming
1761  * bytes as efficiently as possible, and generates a queue of
1762  * messages. DBusMessageLoader is typically used as part of a
1763  * DBusTransport implementation. The DBusTransport then hands off
1764  * the loaded messages to a DBusConnection, making the messages
1765  * visible to the application.
1766  * 
1767  */
1768
1769 /* we definitely use signed ints for sizes, so don't exceed
1770  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
1771  * over 128M is pretty nuts anyhow.
1772  */
1773
1774 /**
1775  * The maximum sane message size.
1776  */
1777 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
1778
1779 /**
1780  * Implementation details of DBusMessageLoader.
1781  * All members are private.
1782  */
1783 struct DBusMessageLoader
1784 {
1785   int refcount;        /**< Reference count. */
1786
1787   DBusString data;     /**< Buffered data */
1788   
1789   DBusList *messages;  /**< Complete messages. */
1790
1791   long max_message_size; /**< Maximum size of a message */
1792   
1793   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
1794
1795   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
1796 };
1797
1798 /**
1799  * The initial buffer size of the message loader.
1800  * 
1801  * @todo this should be based on min header size plus some average
1802  * body size, or something. Or rather, the min header size only, if we
1803  * want to try to read only the header, store that in a DBusMessage,
1804  * then read only the body and store that, etc., depends on
1805  * how we optimize _dbus_message_loader_get_buffer() and what
1806  * the exact message format is.
1807  */
1808 #define INITIAL_LOADER_DATA_LEN 32
1809
1810 /**
1811  * Creates a new message loader. Returns #NULL if memory can't
1812  * be allocated.
1813  *
1814  * @returns new loader, or #NULL.
1815  */
1816 DBusMessageLoader*
1817 _dbus_message_loader_new (void)
1818 {
1819   DBusMessageLoader *loader;
1820
1821   loader = dbus_new0 (DBusMessageLoader, 1);
1822   if (loader == NULL)
1823     return NULL;
1824   
1825   loader->refcount = 1;
1826
1827   /* Try to cap message size at something that won't *totally* hose
1828    * the system if we have a couple of them.
1829    */
1830   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
1831   
1832   if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
1833     {
1834       dbus_free (loader);
1835       return NULL;
1836     }
1837
1838   /* preallocate the buffer for speed, ignore failure */
1839   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
1840   _dbus_string_set_length (&loader->data, 0);
1841   
1842   return loader;
1843 }
1844
1845 /**
1846  * Increments the reference count of the loader.
1847  *
1848  * @param loader the loader.
1849  */
1850 void
1851 _dbus_message_loader_ref (DBusMessageLoader *loader)
1852 {
1853   loader->refcount += 1;
1854 }
1855
1856 /**
1857  * Decrements the reference count of the loader and finalizes the
1858  * loader when the count reaches zero.
1859  *
1860  * @param loader the loader.
1861  */
1862 void
1863 _dbus_message_loader_unref (DBusMessageLoader *loader)
1864 {
1865   loader->refcount -= 1;
1866   if (loader->refcount == 0)
1867     {
1868       _dbus_list_foreach (&loader->messages,
1869                           (DBusForeachFunction) dbus_message_unref,
1870                           NULL);
1871       _dbus_list_clear (&loader->messages);
1872       _dbus_string_free (&loader->data);
1873       dbus_free (loader);
1874     }
1875 }
1876
1877 /**
1878  * Gets the buffer to use for reading data from the network.  Network
1879  * data is read directly into an allocated buffer, which is then used
1880  * in the DBusMessage, to avoid as many extra memcpy's as possible.
1881  * The buffer must always be returned immediately using
1882  * _dbus_message_loader_return_buffer(), even if no bytes are
1883  * successfully read.
1884  *
1885  * @todo this function can be a lot more clever. For example
1886  * it can probably always return a buffer size to read exactly
1887  * the body of the next message, thus avoiding any memory wastage
1888  * or reallocs.
1889  * 
1890  * @param loader the message loader.
1891  * @param buffer the buffer
1892  */
1893 void
1894 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
1895                                  DBusString        **buffer)
1896 {
1897   _dbus_assert (!loader->buffer_outstanding);
1898
1899   *buffer = &loader->data;
1900   
1901   loader->buffer_outstanding = TRUE;
1902 }
1903
1904 /**
1905  * The smallest header size that can occur. 
1906  * (It won't be valid)
1907  */
1908 #define DBUS_MINIMUM_HEADER_SIZE 16
1909
1910 /** Pack four characters as in "abcd" into a uint32 */
1911 #define FOUR_CHARS_TO_UINT32(a, b, c, d)                \
1912                       ((((dbus_uint32_t)a) << 24) |     \
1913                        (((dbus_uint32_t)b) << 16) |     \
1914                        (((dbus_uint32_t)c) << 8)  |     \
1915                        ((dbus_uint32_t)d))
1916
1917 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
1918 #define DBUS_HEADER_FIELD_NAME_AS_UINT32    \
1919   FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
1920
1921 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
1922 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
1923   FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
1924
1925 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
1926 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32   \
1927   FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
1928
1929 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
1930 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32  \
1931   FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
1932
1933 static dbus_bool_t
1934 decode_header_data (const DBusString   *data,
1935                     int                 header_len,
1936                     int                 byte_order,
1937                     HeaderField         fields[FIELD_LAST])
1938 {
1939   const char *field;
1940   int pos, new_pos;
1941   int i;
1942   
1943   if (header_len < 16)
1944     return FALSE;
1945   
1946   i = 0;
1947   while (i < FIELD_LAST)
1948     {
1949       fields[i].offset = -1;
1950       ++i;
1951     }
1952   
1953   fields[FIELD_HEADER_LENGTH].offset = 4;
1954   fields[FIELD_BODY_LENGTH].offset = 8;   
1955   fields[FIELD_CLIENT_SERIAL].offset = 12;
1956   
1957   /* Now handle the named fields. A real named field is at least 4
1958    * bytes for the name, plus a type code (1 byte) plus padding.  So
1959    * if we have less than 8 bytes left, it must be alignment padding,
1960    * not a field. While >= 8 bytes can't be entirely alignment
1961    * padding.
1962    */  
1963   pos = 16;
1964   while ((pos + 7) < header_len)
1965     {
1966       pos = _DBUS_ALIGN_VALUE (pos, 4);
1967       
1968       if ((pos + 4) > header_len)
1969         return FALSE;      
1970       
1971       _dbus_string_get_const_data_len (data, &field, pos, 4);
1972       pos += 4;
1973
1974       _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
1975
1976       /* I believe FROM_BE is right, but if not we'll find out
1977        * I guess. ;-)
1978        */
1979       switch (DBUS_UINT32_FROM_BE (*(int*)field))
1980         {
1981         case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
1982           if (fields[FIELD_SERVICE].offset >= 0)
1983             {
1984               _dbus_verbose ("%s field provided twice\n",
1985                              DBUS_HEADER_FIELD_SERVICE);
1986               return FALSE;
1987             }
1988           
1989           fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
1990           _dbus_verbose ("Found service name at offset %d\n",
1991                          fields[FIELD_SERVICE].offset);
1992           break;
1993
1994         case DBUS_HEADER_FIELD_NAME_AS_UINT32:
1995           if (fields[FIELD_NAME].offset >= 0)
1996             {
1997               _dbus_verbose ("%s field provided twice\n",
1998                              DBUS_HEADER_FIELD_NAME);
1999               return FALSE;
2000             }
2001           
2002           fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2003
2004           _dbus_verbose ("Found message name at offset %d\n",
2005                          fields[FIELD_NAME].offset);
2006           break;
2007         case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
2008           if (fields[FIELD_SENDER].offset >= 0)
2009             {
2010               _dbus_verbose ("%s field provided twice\n",
2011                              DBUS_HEADER_FIELD_SENDER);
2012               return FALSE;
2013             }
2014           
2015           fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2016
2017           _dbus_verbose ("Found sender name at offset %d\n",
2018                          fields[FIELD_NAME].offset);
2019           break;
2020           
2021         case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
2022           if (fields[FIELD_REPLY_SERIAL].offset >= 0)
2023             {
2024               _dbus_verbose ("%s field provided twice\n",
2025                              DBUS_HEADER_FIELD_REPLY);
2026               return FALSE;
2027             }
2028           
2029           fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2030
2031           _dbus_verbose ("Found reply serial at offset %d\n",
2032                          fields[FIELD_REPLY_SERIAL].offset);
2033           break;
2034
2035         default:
2036           _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c\n",
2037                          field[0], field[1], field[2], field[3]);
2038         }
2039
2040       if (!_dbus_marshal_validate_arg (data, byte_order, pos, &new_pos))
2041         {
2042           _dbus_verbose ("Failed to validate argument to named header field\n");
2043           return FALSE;
2044         }
2045
2046       if (new_pos > header_len)
2047         {
2048           _dbus_verbose ("Named header field tries to extend beyond header length\n");
2049           return FALSE;
2050         }
2051       
2052       pos = new_pos;
2053     }
2054
2055   if (pos < header_len)
2056     {
2057       /* Alignment padding, verify that it's nul */
2058       _dbus_assert ((header_len - pos) < 8);
2059
2060       if (!_dbus_string_validate_nul (data,
2061                                       pos, (header_len - pos)))
2062         {
2063           _dbus_verbose ("header alignment padding is not nul\n");
2064           return FALSE;
2065         }
2066     }
2067   
2068   return TRUE;
2069 }
2070
2071 /**
2072  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
2073  * indicating to the loader how many bytes of the buffer were filled
2074  * in. This function must always be called, even if no bytes were
2075  * successfully read.
2076  *
2077  * @todo if we run out of memory in here, we offer no way for calling
2078  * code to handle it, i.e. they can't re-run the message parsing
2079  * attempt. Perhaps much of this code could be moved to pop_message()?
2080  * But then that may need to distinguish NULL return for no messages
2081  * from NULL return for errors.
2082  *
2083  * @param loader the loader.
2084  * @param buffer the buffer.
2085  * @param bytes_read number of bytes that were read into the buffer.
2086  */
2087 void
2088 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
2089                                     DBusString         *buffer,
2090                                     int                 bytes_read)
2091 {
2092   _dbus_assert (loader->buffer_outstanding);
2093   _dbus_assert (buffer == &loader->data);
2094
2095   loader->buffer_outstanding = FALSE;
2096
2097   if (loader->corrupted)
2098     return;
2099
2100   while (_dbus_string_get_length (&loader->data) >= 16)
2101     {
2102       DBusMessage *message;      
2103       const char *header_data;
2104       int byte_order, header_len, body_len;
2105       dbus_uint32_t header_len_unsigned, body_len_unsigned;
2106       
2107       _dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
2108
2109       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
2110
2111       if (header_data[2] != DBUS_MAJOR_PROTOCOL_VERSION)
2112         {
2113           _dbus_verbose ("Message has protocol version %d ours is %d\n",
2114                          (int) header_data[2], DBUS_MAJOR_PROTOCOL_VERSION);
2115           loader->corrupted = TRUE;
2116           return;
2117         }
2118       
2119       byte_order = header_data[0];
2120
2121       if (byte_order != DBUS_LITTLE_ENDIAN &&
2122           byte_order != DBUS_BIG_ENDIAN)
2123         {
2124           _dbus_verbose ("Message with bad byte order '%c' received\n",
2125                          byte_order);
2126           loader->corrupted = TRUE;
2127           return;
2128         }
2129
2130       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
2131       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
2132
2133       if (header_len_unsigned < 16)
2134         {
2135           _dbus_verbose ("Message had broken too-small header length %u\n",
2136                          header_len_unsigned);
2137           loader->corrupted = TRUE;
2138           return;
2139         }
2140
2141       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
2142           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
2143         {
2144           _dbus_verbose ("Header or body length too large (%u %u)\n",
2145                          header_len_unsigned,
2146                          body_len_unsigned);
2147           loader->corrupted = TRUE;
2148           return;
2149         }      
2150
2151       /* Now that we know the values are in signed range, get
2152        * rid of stupid unsigned, just causes bugs
2153        */
2154       header_len = header_len_unsigned;
2155       body_len = body_len_unsigned;
2156       
2157       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
2158         {
2159           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
2160                          header_len);
2161           loader->corrupted = TRUE;
2162           return;
2163         }
2164       
2165       if (header_len + body_len > loader->max_message_size)
2166         {
2167           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %d\n",
2168                          header_len, body_len, loader->max_message_size);
2169           loader->corrupted = TRUE;
2170           return;
2171         }
2172
2173       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
2174         {
2175           HeaderField fields[FIELD_LAST];
2176           int i;
2177           int next_arg;          
2178
2179           if (!decode_header_data (&loader->data, header_len, byte_order,
2180                                    fields))
2181             {
2182               _dbus_verbose ("Header was invalid\n");
2183               loader->corrupted = TRUE;
2184               return;
2185             }
2186           
2187           next_arg = header_len;
2188           while (next_arg < (header_len + body_len))
2189             {
2190               int prev = next_arg;
2191
2192               if (!_dbus_marshal_validate_arg (&loader->data,
2193                                                byte_order,
2194                                                next_arg,
2195                                                &next_arg))
2196                 {
2197                   loader->corrupted = TRUE;
2198                   return;
2199                 }
2200
2201               _dbus_assert (next_arg > prev);
2202             }
2203           
2204           if (next_arg > (header_len + body_len))
2205             {
2206               _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
2207                              next_arg, header_len, body_len,
2208                              header_len + body_len);
2209               loader->corrupted = TRUE;
2210               return;
2211             }
2212
2213           message = dbus_message_new_empty_header ();
2214           if (message == NULL)
2215             break; /* ugh, postpone this I guess. */
2216
2217           message->byte_order = byte_order;
2218           
2219           /* Copy in the offsets we found */
2220           i = 0;
2221           while (i < FIELD_LAST)
2222             {
2223               message->header_fields[i] = fields[i];
2224               ++i;
2225             }
2226           
2227           if (!_dbus_list_append (&loader->messages, message))
2228             {
2229               dbus_message_unref (message);
2230               break;
2231             }
2232
2233           _dbus_assert (_dbus_string_get_length (&message->header) == 0);
2234           _dbus_assert (_dbus_string_get_length (&message->body) == 0);
2235
2236           _dbus_assert (_dbus_string_get_length (&loader->data) >=
2237                         (header_len + body_len));
2238           
2239           if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
2240             {
2241               _dbus_list_remove_last (&loader->messages, message);
2242               dbus_message_unref (message);
2243               break;
2244             }
2245           
2246           if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
2247             {
2248               dbus_bool_t result;
2249
2250               /* put the header back, we'll try again later */
2251               result = _dbus_string_copy_len (&message->header, 0, header_len,
2252                                               &loader->data, 0);
2253               _dbus_assert (result); /* because DBusString never reallocs smaller */
2254
2255               _dbus_list_remove_last (&loader->messages, message);
2256               dbus_message_unref (message);
2257               break;
2258             }
2259
2260           _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
2261           _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
2262
2263           _dbus_verbose ("Loaded message %p\n", message);
2264         }
2265       else
2266         break;
2267     }
2268 }
2269
2270 /**
2271  * Pops a loaded message (passing ownership of the message
2272  * to the caller). Returns #NULL if no messages have been
2273  * loaded.
2274  *
2275  * @param loader the loader.
2276  * @returns the next message, or #NULL if none.
2277  */
2278 DBusMessage*
2279 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
2280 {
2281   return _dbus_list_pop_first (&loader->messages);
2282 }
2283
2284
2285 /**
2286  * Checks whether the loader is confused due to bad data.
2287  * If messages are received that are invalid, the
2288  * loader gets confused and gives up permanently.
2289  * This state is called "corrupted."
2290  *
2291  * @param loader the loader
2292  * @returns #TRUE if the loader is hosed.
2293  */
2294 dbus_bool_t
2295 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
2296 {
2297   return loader->corrupted;
2298 }
2299
2300 /**
2301  * Sets the maximum size message we allow.
2302  *
2303  * @param loader the loader
2304  * @param size the max message size in bytes
2305  */
2306 void
2307 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
2308                                            long                size)
2309 {
2310   if (size > MAX_SANE_MESSAGE_SIZE)
2311     {
2312       _dbus_verbose ("clamping requested max message size %ld to %d\n",
2313                      size, MAX_SANE_MESSAGE_SIZE);
2314       size = MAX_SANE_MESSAGE_SIZE;
2315     }
2316   loader->max_message_size = size;
2317 }
2318
2319 /**
2320  * Gets the maximum allowed message size in bytes.
2321  *
2322  * @param loader the loader
2323  * @returns max size in bytes
2324  */
2325 long
2326 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
2327 {
2328   return loader->max_message_size;
2329 }
2330
2331 /** @} */
2332 #ifdef DBUS_BUILD_TESTS
2333 #include "dbus-test.h"
2334 #include <stdio.h>
2335
2336 static void
2337 message_iter_test (DBusMessage *message)
2338 {
2339   DBusMessageIter *iter;
2340   char *str;
2341   
2342   iter = dbus_message_get_args_iter (message);
2343
2344   /* String tests */
2345   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRING)
2346     _dbus_assert_not_reached ("Argument type isn't string");
2347
2348   str = dbus_message_iter_get_string (iter);
2349   if (strcmp (str, "Test string") != 0)
2350     _dbus_assert_not_reached ("Strings differ");
2351   dbus_free (str);
2352
2353   if (!dbus_message_iter_next (iter))
2354     _dbus_assert_not_reached ("Reached end of arguments");
2355
2356   /* Signed integer tests */
2357   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT32)
2358     _dbus_assert_not_reached ("Argument type isn't int32");
2359
2360   if (dbus_message_iter_get_int32 (iter) != -0x12345678)
2361     _dbus_assert_not_reached ("Signed integers differ");
2362
2363   if (!dbus_message_iter_next (iter))
2364     _dbus_assert_not_reached ("Reached end of fields");
2365   
2366   /* Unsigned integer tests */
2367   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT32)
2368     _dbus_assert_not_reached ("Argument type isn't int32");
2369
2370   if (dbus_message_iter_get_int32 (iter) != 0xedd1e)
2371     _dbus_assert_not_reached ("Unsigned integers differ");
2372
2373   if (!dbus_message_iter_next (iter))
2374     _dbus_assert_not_reached ("Reached end of arguments");
2375
2376   /* Double tests */
2377   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_DOUBLE)
2378     _dbus_assert_not_reached ("Argument type isn't double");
2379
2380   if (dbus_message_iter_get_double (iter) != 3.14159)
2381     _dbus_assert_not_reached ("Doubles differ");
2382
2383   if (dbus_message_iter_next (iter))
2384     _dbus_assert_not_reached ("Didn't reach end of arguments");
2385   
2386   dbus_message_iter_unref (iter);
2387 }
2388
2389 static dbus_bool_t
2390 check_message_handling (DBusMessage *message)
2391 {
2392   DBusMessageIter *iter;
2393   int type;
2394   dbus_bool_t retval;
2395   dbus_int32_t client_serial;
2396   
2397   retval = FALSE;
2398   iter = NULL;
2399   
2400   client_serial = _dbus_message_get_client_serial (message);
2401
2402   /* can't use set_client_serial due to the assertions at the start of it */
2403   set_int_field (message, FIELD_CLIENT_SERIAL,
2404                  client_serial);
2405
2406   if (client_serial != _dbus_message_get_client_serial (message))
2407     {
2408       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
2409       goto failed;
2410     }
2411   
2412   /* If we implement message_set_arg (message, n, value)
2413    * then we would want to test it here
2414    */
2415   
2416   iter = dbus_message_get_args_iter (message);
2417   while ((type = dbus_message_iter_get_arg_type (iter)) != DBUS_TYPE_INVALID)
2418     {
2419       switch (type)
2420         {
2421         case DBUS_TYPE_STRING:
2422           {
2423             char *str;
2424             str = dbus_message_iter_get_string (iter);
2425             dbus_free (str);
2426           }
2427           break;
2428         }
2429       
2430       if (!dbus_message_iter_next (iter))
2431         break;
2432     }
2433
2434   retval = TRUE;
2435   
2436  failed:
2437   if (iter)
2438     dbus_message_iter_unref (iter);
2439
2440   return retval;
2441 }
2442
2443 static dbus_bool_t
2444 check_have_valid_message (DBusMessageLoader *loader)
2445 {
2446   DBusMessage *message;
2447   dbus_bool_t retval;
2448
2449   message = NULL;
2450   retval = FALSE;
2451   
2452   if (_dbus_message_loader_get_is_corrupted (loader))
2453     {
2454       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
2455       goto failed;
2456     }
2457   
2458   message = _dbus_message_loader_pop_message (loader);
2459   if (message == NULL)
2460     {
2461       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
2462       goto failed;
2463     }
2464   
2465   if (_dbus_string_get_length (&loader->data) > 0)
2466     {
2467       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
2468       goto failed;
2469     }
2470
2471   /* Verify that we're able to properly deal with the message.
2472    * For example, this would detect improper handling of messages
2473    * in nonstandard byte order.
2474    */
2475   if (!check_message_handling (message))
2476     goto failed;  
2477   
2478   retval = TRUE;
2479
2480  failed:
2481   if (message)
2482     dbus_message_unref (message);
2483   return retval;
2484 }
2485
2486 static dbus_bool_t
2487 check_invalid_message (DBusMessageLoader *loader)
2488 {
2489   dbus_bool_t retval;
2490
2491   retval = FALSE;
2492   
2493   if (!_dbus_message_loader_get_is_corrupted (loader))
2494     {
2495       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
2496       goto failed;
2497     }
2498
2499   retval = TRUE;
2500
2501  failed:
2502   return retval;
2503 }
2504
2505 static dbus_bool_t
2506 check_incomplete_message (DBusMessageLoader *loader)
2507 {
2508   DBusMessage *message;
2509   dbus_bool_t retval;
2510
2511   message = NULL;
2512   retval = FALSE;
2513   
2514   if (_dbus_message_loader_get_is_corrupted (loader))
2515     {
2516       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
2517       goto failed;
2518     }
2519   
2520   message = _dbus_message_loader_pop_message (loader);
2521   if (message != NULL)
2522     {
2523       _dbus_warn ("loaded message that was expected to be incomplete\n");
2524       goto failed;
2525     }
2526
2527   retval = TRUE;
2528
2529  failed:
2530   if (message)
2531     dbus_message_unref (message);
2532   return retval;
2533 }
2534
2535 static dbus_bool_t
2536 check_loader_results (DBusMessageLoader      *loader,
2537                       DBusMessageValidity     validity)
2538 {
2539   switch (validity)
2540     {
2541     case _DBUS_MESSAGE_VALID:
2542       return check_have_valid_message (loader);
2543     case _DBUS_MESSAGE_INVALID:
2544       return check_invalid_message (loader);
2545     case _DBUS_MESSAGE_INCOMPLETE:
2546       return check_incomplete_message (loader);
2547     case _DBUS_MESSAGE_UNKNOWN:
2548       return TRUE;
2549     }
2550
2551   _dbus_assert_not_reached ("bad DBusMessageValidity");
2552   return FALSE;
2553 }
2554
2555
2556 /**
2557  * Loads the message in the given message file.
2558  *
2559  * @param filename filename to load
2560  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
2561  * @param data string to load message into
2562  * @returns #TRUE if the message was loaded
2563  */
2564 dbus_bool_t
2565 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
2566                                             dbus_bool_t          is_raw,
2567                                             DBusString          *data)
2568 {
2569   dbus_bool_t retval;
2570
2571   retval = FALSE;  
2572
2573   if (is_raw)
2574     {
2575       DBusResultCode result;
2576
2577       result = _dbus_file_get_contents (data, filename);
2578       if (result != DBUS_RESULT_SUCCESS)
2579         {
2580           const char *s;      
2581           _dbus_string_get_const_data (filename, &s);
2582           _dbus_warn ("Could not load message file %s\n", s);
2583           goto failed;
2584         }
2585     }
2586   else
2587     {
2588       if (!_dbus_message_data_load (data, filename))
2589         {
2590           const char *s;      
2591           _dbus_string_get_const_data (filename, &s);
2592           _dbus_warn ("Could not load message file %s\n", s);
2593           goto failed;
2594         }
2595     }
2596
2597   retval = TRUE;
2598   
2599  failed:
2600
2601   return retval;
2602 }
2603
2604 /**
2605  * Tries loading the message in the given message file
2606  * and verifies that DBusMessageLoader can handle it.
2607  *
2608  * @param filename filename to load
2609  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
2610  * @param expected_validity what the message has to be like to return #TRUE
2611  * @returns #TRUE if the message has the expected validity
2612  */
2613 dbus_bool_t
2614 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
2615                                            dbus_bool_t          is_raw,
2616                                            DBusMessageValidity  expected_validity)
2617 {
2618   DBusString data;
2619   dbus_bool_t retval;
2620
2621   retval = FALSE;
2622   
2623   if (!_dbus_string_init (&data, _DBUS_INT_MAX))
2624     _dbus_assert_not_reached ("could not allocate string\n");
2625
2626   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
2627                                                    &data))
2628     goto failed;
2629
2630   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
2631
2632  failed:
2633
2634   if (!retval)
2635     {
2636       const char *s;
2637
2638       if (_dbus_string_get_length (&data) > 0)
2639         _dbus_verbose_bytes_of_string (&data, 0,
2640                                        _dbus_string_get_length (&data));
2641       
2642       _dbus_string_get_const_data (filename, &s);
2643       _dbus_warn ("Failed message loader test on %s\n",
2644                   s);
2645     }
2646   
2647   _dbus_string_free (&data);
2648
2649   return retval;
2650 }
2651
2652 /**
2653  * Tries loading the given message data.
2654  *
2655  *
2656  * @param data the message data
2657  * @param expected_validity what the message has to be like to return #TRUE
2658  * @returns #TRUE if the message has the expected validity
2659  */
2660 dbus_bool_t
2661 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
2662                                            DBusMessageValidity  expected_validity)
2663 {
2664   DBusMessageLoader *loader;
2665   dbus_bool_t retval;
2666   int len;
2667   int i;
2668
2669   loader = NULL;
2670   retval = FALSE;
2671
2672   /* Write the data one byte at a time */
2673   
2674   loader = _dbus_message_loader_new ();
2675
2676   len = _dbus_string_get_length (data);
2677   for (i = 0; i < len; i++)
2678     {
2679       DBusString *buffer;
2680
2681       _dbus_message_loader_get_buffer (loader, &buffer);
2682       _dbus_string_append_byte (buffer,
2683                                 _dbus_string_get_byte (data, i));
2684       _dbus_message_loader_return_buffer (loader, buffer, 1);
2685     }
2686   
2687   if (!check_loader_results (loader, expected_validity))
2688     goto failed;
2689
2690   _dbus_message_loader_unref (loader);
2691   loader = NULL;
2692
2693   /* Write the data all at once */
2694   
2695   loader = _dbus_message_loader_new ();
2696
2697   {
2698     DBusString *buffer;
2699     
2700     _dbus_message_loader_get_buffer (loader, &buffer);
2701     _dbus_string_copy (data, 0, buffer,
2702                        _dbus_string_get_length (buffer));
2703     _dbus_message_loader_return_buffer (loader, buffer, 1);
2704   }
2705   
2706   if (!check_loader_results (loader, expected_validity))
2707     goto failed;
2708
2709   _dbus_message_loader_unref (loader);
2710   loader = NULL;  
2711
2712   /* Write the data 2 bytes at a time */
2713   
2714   loader = _dbus_message_loader_new ();
2715
2716   len = _dbus_string_get_length (data);
2717   for (i = 0; i < len; i += 2)
2718     {
2719       DBusString *buffer;
2720
2721       _dbus_message_loader_get_buffer (loader, &buffer);
2722       _dbus_string_append_byte (buffer,
2723                                 _dbus_string_get_byte (data, i));
2724       if ((i+1) < len)
2725         _dbus_string_append_byte (buffer,
2726                                   _dbus_string_get_byte (data, i+1));
2727       _dbus_message_loader_return_buffer (loader, buffer, 1);
2728     }
2729   
2730   if (!check_loader_results (loader, expected_validity))
2731     goto failed;
2732
2733   _dbus_message_loader_unref (loader);
2734   loader = NULL;
2735   
2736   retval = TRUE;
2737   
2738  failed:
2739   
2740   if (loader)
2741     _dbus_message_loader_unref (loader);
2742   
2743   return retval;
2744 }
2745
2746 static dbus_bool_t
2747 process_test_subdir (const DBusString          *test_base_dir,
2748                      const char                *subdir,
2749                      DBusMessageValidity        validity,
2750                      DBusForeachMessageFileFunc function,
2751                      void                      *user_data)
2752 {
2753   DBusString test_directory;
2754   DBusString filename;
2755   DBusDirIter *dir;
2756   dbus_bool_t retval;
2757   DBusResultCode result;
2758
2759   retval = FALSE;
2760   dir = NULL;
2761   
2762   if (!_dbus_string_init (&test_directory, _DBUS_INT_MAX))
2763     _dbus_assert_not_reached ("didn't allocate test_directory\n");
2764
2765   _dbus_string_init_const (&filename, subdir);
2766   
2767   if (!_dbus_string_copy (test_base_dir, 0,
2768                           &test_directory, 0))
2769     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
2770   
2771   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
2772     _dbus_assert_not_reached ("couldn't allocate full path");
2773
2774   _dbus_string_free (&filename);
2775   if (!_dbus_string_init (&filename, _DBUS_INT_MAX))
2776     _dbus_assert_not_reached ("didn't allocate filename string\n");
2777   
2778   dir = _dbus_directory_open (&test_directory, &result);
2779   if (dir == NULL)
2780     {
2781       const char *s;
2782       _dbus_string_get_const_data (&test_directory, &s);
2783       _dbus_warn ("Could not open %s: %s\n", s,
2784                   dbus_result_to_string (result));
2785       goto failed;
2786     }
2787
2788   printf ("Testing:\n");
2789   
2790   result = DBUS_RESULT_SUCCESS;
2791  next:
2792   while (_dbus_directory_get_next_file (dir, &filename, &result))
2793     {
2794       DBusString full_path;
2795       dbus_bool_t is_raw;
2796       
2797       if (!_dbus_string_init (&full_path, _DBUS_INT_MAX))
2798         _dbus_assert_not_reached ("couldn't init string");
2799
2800       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
2801         _dbus_assert_not_reached ("couldn't copy dir to full_path");
2802
2803       if (!_dbus_concat_dir_and_file (&full_path, &filename))
2804         _dbus_assert_not_reached ("couldn't concat file to dir");
2805
2806       if (_dbus_string_ends_with_c_str (&filename, ".message"))
2807         is_raw = FALSE;
2808       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
2809         is_raw = TRUE;
2810       else
2811         {
2812           const char *filename_c;
2813           _dbus_string_get_const_data (&filename, &filename_c);
2814           _dbus_verbose ("Skipping non-.message file %s\n",
2815                          filename_c);
2816           _dbus_string_free (&full_path);
2817           goto next;
2818         }
2819
2820       {
2821         const char *s;
2822         _dbus_string_get_const_data (&filename, &s);
2823         printf ("    %s\n", s);
2824       }
2825       
2826       _dbus_verbose (" expecting %s\n",
2827                      validity == _DBUS_MESSAGE_VALID ? "valid" :
2828                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
2829                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")));
2830       
2831       if (! (*function) (&full_path, is_raw, validity, user_data))
2832         {
2833           _dbus_string_free (&full_path);
2834           goto failed;
2835         }
2836       else
2837         _dbus_string_free (&full_path);
2838     }
2839
2840   if (result != DBUS_RESULT_SUCCESS)
2841     {
2842       const char *s;
2843       _dbus_string_get_const_data (&test_directory, &s);
2844       _dbus_warn ("Could not get next file in %s: %s\n",
2845                   s, dbus_result_to_string (result));
2846       goto failed;
2847     }
2848     
2849   retval = TRUE;
2850   
2851  failed:
2852
2853   if (dir)
2854     _dbus_directory_close (dir);
2855   _dbus_string_free (&test_directory);
2856   _dbus_string_free (&filename);
2857
2858   return retval;
2859 }
2860                      
2861 /**
2862  * Runs the given function on every message file in the test suite.
2863  * The function should return #FALSE on test failure or fatal error.
2864  *
2865  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
2866  * @param func the function to run
2867  * @param user_data data for function
2868  * @returns #FALSE if there's a failure
2869  */
2870 dbus_bool_t
2871 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
2872                                                DBusForeachMessageFileFunc func,
2873                                                void                      *user_data)
2874 {
2875   DBusString test_directory;
2876   dbus_bool_t retval;
2877
2878   retval = FALSE;
2879   
2880   _dbus_string_init_const (&test_directory, test_data_dir);
2881
2882   if (!process_test_subdir (&test_directory, "valid-messages",
2883                             _DBUS_MESSAGE_VALID, func, user_data))
2884     goto failed;
2885
2886   if (!process_test_subdir (&test_directory, "invalid-messages",
2887                             _DBUS_MESSAGE_INVALID, func, user_data))
2888     goto failed;
2889   
2890   if (!process_test_subdir (&test_directory, "incomplete-messages",
2891                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
2892     goto failed;
2893
2894   retval = TRUE;
2895   
2896  failed:
2897
2898   _dbus_string_free (&test_directory);
2899   
2900   return retval;
2901 }
2902
2903 /**
2904  * @ingroup DBusMessageInternals
2905  * Unit test for DBusMessage.
2906  *
2907  * @returns #TRUE on success.
2908  */
2909 dbus_bool_t
2910 _dbus_message_test (const char *test_data_dir)
2911 {
2912   DBusMessage *message;
2913   DBusMessageLoader *loader;
2914   int i;
2915   const char *data;
2916   dbus_int32_t our_int;
2917   char *our_str;
2918   double our_double;
2919   
2920   /* Test the vararg functions */
2921   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
2922   _dbus_message_set_client_serial (message, 1);
2923   dbus_message_append_args (message,
2924                             DBUS_TYPE_INT32, -0x12345678,
2925                             DBUS_TYPE_STRING, "Test string",
2926                             DBUS_TYPE_DOUBLE, 3.14159,
2927                             0);
2928   _dbus_verbose_bytes_of_string (&message->header, 0,
2929                                  _dbus_string_get_length (&message->header));
2930   _dbus_verbose_bytes_of_string (&message->body, 0,
2931                                  _dbus_string_get_length (&message->body));
2932   
2933   if (dbus_message_get_args (message,
2934                              DBUS_TYPE_INT32, &our_int,
2935                              DBUS_TYPE_STRING, &our_str,
2936                              DBUS_TYPE_DOUBLE, &our_double,
2937                              0) != DBUS_RESULT_SUCCESS)
2938     _dbus_assert_not_reached ("Could not get arguments");
2939
2940   if (our_int != -0x12345678)
2941     _dbus_assert_not_reached ("integers differ!");
2942
2943   if (our_double != 3.14159)
2944     _dbus_assert_not_reached ("doubles differ!");
2945
2946   if (strcmp (our_str, "Test string") != 0)
2947     _dbus_assert_not_reached ("strings differ!");
2948
2949   dbus_free (our_str);
2950   dbus_message_unref (message);
2951   
2952   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
2953   _dbus_message_set_client_serial (message, 1);
2954   _dbus_message_set_reply_serial (message, 0x12345678);
2955
2956   dbus_message_append_string (message, "Test string");
2957   dbus_message_append_int32 (message, -0x12345678);
2958   dbus_message_append_uint32 (message, 0xedd1e);
2959   dbus_message_append_double (message, 3.14159);
2960
2961   message_iter_test (message);
2962
2963   /* Message loader test */
2964   _dbus_message_lock (message);
2965   loader = _dbus_message_loader_new ();
2966
2967   /* Write the header data one byte at a time */
2968   _dbus_string_get_const_data (&message->header, &data);
2969   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
2970     {
2971       DBusString *buffer;
2972
2973       _dbus_message_loader_get_buffer (loader, &buffer);
2974       _dbus_string_append_byte (buffer, data[i]);
2975       _dbus_message_loader_return_buffer (loader, buffer, 1);
2976     }
2977
2978   /* Write the body data one byte at a time */
2979   _dbus_string_get_const_data (&message->body, &data);
2980   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
2981     {
2982       DBusString *buffer;
2983
2984       _dbus_message_loader_get_buffer (loader, &buffer);
2985       _dbus_string_append_byte (buffer, data[i]);
2986       _dbus_message_loader_return_buffer (loader, buffer, 1);
2987     }
2988
2989   dbus_message_unref (message);
2990
2991   /* Now pop back the message */
2992   if (_dbus_message_loader_get_is_corrupted (loader))
2993     _dbus_assert_not_reached ("message loader corrupted");
2994   
2995   message = _dbus_message_loader_pop_message (loader);
2996   if (!message)
2997     _dbus_assert_not_reached ("received a NULL message");
2998
2999   if (_dbus_message_get_reply_serial (message) != 0x12345678)
3000     _dbus_assert_not_reached ("reply serial fields differ");
3001   
3002   message_iter_test (message);
3003   
3004   dbus_message_unref (message);
3005   _dbus_message_loader_unref (loader);
3006
3007   /* Now load every message in test_data_dir if we have one */
3008   if (test_data_dir == NULL)
3009     return TRUE;
3010
3011   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
3012                                                         (DBusForeachMessageFileFunc)
3013                                                         dbus_internal_do_not_use_try_message_file,
3014                                                         NULL);
3015 }
3016
3017 #endif /* DBUS_BUILD_TESTS */