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