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