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