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