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