2003-02-22 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / dbus / dbus-message.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-message.c  DBusMessage object
3  *
4  * Copyright (C) 2002, 2003  Red Hat Inc.
5  * Copyright (C) 2002, 2003  CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 1.2
8  * 
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  * 
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "dbus-internals.h"
26 #include "dbus-marshal.h"
27 #include "dbus-message.h"
28 #include "dbus-message-internal.h"
29 #include "dbus-memory.h"
30 #include "dbus-list.h"
31 #include "dbus-message-builder.h"
32 #include <string.h>
33
34 /**
35  * @defgroup DBusMessageInternals DBusMessage implementation details
36  * @ingroup DBusInternals
37  * @brief DBusMessage private implementation details.
38  *
39  * The guts of DBusMessage and its methods.
40  *
41  * @{
42  */
43
44 enum
45 {
46   FIELD_HEADER_LENGTH,
47   FIELD_BODY_LENGTH,
48   FIELD_CLIENT_SERIAL,
49   FIELD_NAME,
50   FIELD_SERVICE,
51   FIELD_SENDER,
52   FIELD_REPLY_SERIAL,
53
54   FIELD_LAST
55 };
56
57 static dbus_bool_t field_is_named[FIELD_LAST] =
58 {
59   FALSE, /* FIELD_HEADER_LENGTH */
60   FALSE, /* FIELD_BODY_LENGTH */
61   FALSE, /* FIELD_CLIENT_SERIAL */
62   TRUE,  /* FIELD_NAME */
63   TRUE,  /* FIELD_SERVICE */
64   TRUE,  /* FIELD_SENDER */
65   TRUE   /* FIELD_REPLY_SERIAL */
66 };
67
68 typedef struct
69 {
70   int offset; /**< Offset to start of field (location of name of field
71                * for named fields)
72                */
73 } HeaderField;
74
75 /**
76  * @brief Internals of DBusMessage
77  * 
78  * Object representing a message received from or to be sent to
79  * another application. This is an opaque object, all members
80  * are private.
81  */
82 struct DBusMessage
83 {
84   dbus_atomic_t refcount; /**< Reference count */
85
86   DBusString header; /**< Header network data, stored
87                       * separately from body so we can
88                       * independently realloc it.
89                       */
90
91   HeaderField header_fields[FIELD_LAST]; /**< Track the location
92                                            * of each field in "header"
93                                            */
94   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       return FALSE;
1155   else
1156     return TRUE;
1157 }
1158
1159 /**
1160  * Appends a 32 bit signed integer to the message.
1161  *
1162  * @param message the message
1163  * @param value the integer value
1164  * @returns #TRUE on success
1165  */
1166 dbus_bool_t
1167 dbus_message_append_int32 (DBusMessage  *message,
1168                            dbus_int32_t  value)
1169 {
1170   _dbus_assert (!message->locked);
1171
1172   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
1173       return FALSE;
1174   
1175   if (!_dbus_marshal_int32 (&message->body, message->byte_order, value))
1176     {
1177       _dbus_string_shorten (&message->body, 1);
1178       return FALSE;
1179     }
1180
1181   return TRUE;
1182 }
1183
1184 /**
1185  * Appends a 32 bit unsigned integer to the message.
1186  *
1187  * @param message the message
1188  * @param value the integer value
1189  * @returns #TRUE on success
1190  */
1191 dbus_bool_t
1192 dbus_message_append_uint32 (DBusMessage   *message,
1193                             dbus_uint32_t  value)
1194 {
1195   _dbus_assert (!message->locked);
1196
1197   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
1198       return FALSE;
1199   
1200   if (!_dbus_marshal_uint32 (&message->body, message->byte_order, value))
1201     {
1202       _dbus_string_shorten (&message->body, 1);
1203       return FALSE;
1204     }
1205
1206   return TRUE;      
1207 }
1208
1209 /**
1210  * Appends a double value to the message.
1211  *
1212  * @param message the message
1213  * @param value the double value
1214  * @returns #TRUE on success
1215  */
1216 dbus_bool_t
1217 dbus_message_append_double (DBusMessage *message,
1218                             double       value)
1219 {
1220   _dbus_assert (!message->locked);
1221
1222   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
1223     return FALSE;
1224
1225   if (!_dbus_marshal_double (&message->body, message->byte_order, value))
1226     {
1227       _dbus_string_shorten (&message->body, 1);
1228       return FALSE;
1229     }
1230   
1231   return TRUE;
1232 }
1233
1234 /**
1235  * Appends a UTF-8 string to the message.
1236  *
1237  * @param message the message
1238  * @param value the string
1239  * @returns #TRUE on success
1240  */
1241 dbus_bool_t
1242 dbus_message_append_string (DBusMessage *message,
1243                             const char  *value)
1244 {
1245   _dbus_assert (!message->locked);
1246
1247   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
1248       return FALSE;
1249   
1250   if (!_dbus_marshal_string (&message->body, message->byte_order, value))
1251     {
1252       _dbus_string_shorten (&message->body, 1);
1253       return FALSE;      
1254     }
1255
1256   return TRUE;
1257 }
1258
1259 /**
1260  * Appends a 32 bit signed integer array to the message.
1261  *
1262  * @param message the message
1263  * @param value the array
1264  * @param len the length of the array
1265  * @returns #TRUE on success
1266  */
1267 dbus_bool_t
1268 dbus_message_append_int32_array (DBusMessage        *message,
1269                                  const dbus_int32_t *value,
1270                                  int                 len)
1271 {
1272   _dbus_assert (!message->locked);
1273
1274   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32_ARRAY))
1275     return FALSE;
1276
1277   if (!_dbus_marshal_int32_array (&message->body, message->byte_order,
1278                                   value, len))
1279     {
1280       _dbus_string_shorten (&message->body, 1);
1281       return FALSE;
1282     }
1283
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   _dbus_assert (!message->locked);
1301
1302   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32_ARRAY))
1303     return FALSE;
1304
1305   if (!_dbus_marshal_uint32_array (&message->body, message->byte_order,
1306                                   value, len))
1307     {
1308       _dbus_string_shorten (&message->body, 1);
1309       return FALSE;
1310     }
1311
1312   return TRUE;
1313 }
1314
1315 /**
1316  * Appends a double array to the message.
1317  *
1318  * @param message the message
1319  * @param value the array
1320  * @param len the length of the array
1321  * @returns #TRUE on success
1322  */
1323 dbus_bool_t
1324 dbus_message_append_double_array (DBusMessage  *message,
1325                                   const double *value,
1326                                   int           len)
1327 {
1328   _dbus_assert (!message->locked);
1329
1330   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE_ARRAY))
1331     return FALSE;
1332
1333   if (!_dbus_marshal_double_array (&message->body, message->byte_order,
1334                                    value, len))
1335     {
1336       _dbus_string_shorten (&message->body, 1);
1337       return FALSE;
1338     }
1339
1340   return TRUE;
1341 }
1342
1343 /**
1344  * Appends a byte array to the message.
1345  *
1346  * @param message the message
1347  * @param value the array
1348  * @param len the length of the array
1349  * @returns #TRUE on success
1350  */
1351 dbus_bool_t
1352 dbus_message_append_byte_array (DBusMessage         *message,
1353                                 unsigned const char *value,
1354                                 int                 len)
1355 {
1356   _dbus_assert (!message->locked);
1357
1358   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
1359     return FALSE;
1360   
1361   if (!_dbus_marshal_byte_array (&message->body, message->byte_order, value, len))
1362     {
1363       _dbus_string_shorten (&message->body, 1);
1364       return FALSE;
1365     }
1366       
1367   return TRUE;
1368 }
1369
1370 /**
1371  * Appends a string array to the message.
1372  *
1373  * @param message the message
1374  * @param value the array
1375  * @param len the length of the array
1376  * @returns #TRUE on success
1377  */
1378 dbus_bool_t
1379 dbus_message_append_string_array (DBusMessage *message,
1380                                   const char **value,
1381                                   int          len)
1382 {
1383   _dbus_assert (!message->locked);
1384
1385   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING_ARRAY))
1386     return FALSE;
1387
1388   if (!_dbus_marshal_string_array (&message->body, message->byte_order,
1389                                    value, len))
1390     {
1391       _dbus_string_shorten (&message->body, 1);
1392       return FALSE;
1393     }
1394
1395   return TRUE;
1396 }
1397
1398 /**
1399  * Gets arguments from a message given a variable argument list.
1400  * The variable argument list should contain the type of the
1401  * argumen followed by a pointer to where the value should be
1402  * stored. The list is terminated with 0.
1403  *
1404  * @param message the message
1405  * @param first_arg_type the first argument type
1406  * @param ... location for first argument value, then list of type-location pairs
1407  * @returns result code
1408  */
1409 DBusResultCode
1410 dbus_message_get_args (DBusMessage *message,
1411                        int          first_arg_type,
1412                        ...)
1413 {
1414   DBusResultCode retval;
1415   va_list var_args;
1416
1417   va_start (var_args, first_arg_type);
1418   retval = dbus_message_get_args_valist (message, first_arg_type, var_args);
1419   va_end (var_args);
1420
1421   return retval;
1422 }
1423
1424 /**
1425  * This function takes a va_list for use by language bindings
1426  *
1427  * @todo this function (or some lower-level non-convenience function)
1428  * needs better error handling; should allow the application to
1429  * distinguish between out of memory, and bad data from the remote
1430  * app. It also needs to not leak a bunch of args when it gets
1431  * to the arg that's bad, as that would be a security hole
1432  * (allow one app to force another to leak memory)
1433  *
1434  * @todo We need to free the argument data when an error occurs.
1435  *
1436  * @see dbus_message_get_args
1437  * @param message the message
1438  * @param first_arg_type type of the first argument
1439  * @param var_args return location for first argument, followed by list of type/location pairs
1440  * @returns result code
1441  */
1442 DBusResultCode
1443 dbus_message_get_args_valist (DBusMessage *message,
1444                               int          first_arg_type,
1445                               va_list      var_args)
1446 {
1447   int spec_type, msg_type, i;
1448   DBusMessageIter *iter;
1449
1450   iter = dbus_message_get_args_iter (message);
1451
1452   if (iter == NULL)
1453     return DBUS_RESULT_NO_MEMORY;
1454   
1455   spec_type = first_arg_type;
1456   i = 0;
1457   
1458   while (spec_type != 0)
1459     {
1460       msg_type = dbus_message_iter_get_arg_type (iter);      
1461       
1462       if (msg_type != spec_type)
1463         {
1464           _dbus_verbose ("Argument %d is specified to be of type \"%s\", but "
1465                          "is actually of type \"%s\"\n", i,
1466                          _dbus_type_to_string (spec_type),
1467                          _dbus_type_to_string (msg_type));
1468           dbus_message_iter_unref (iter);
1469
1470           return DBUS_RESULT_INVALID_ARGS;
1471         }
1472
1473       switch (spec_type)
1474         {
1475         case DBUS_TYPE_INT32:
1476           {
1477             dbus_int32_t *ptr;
1478
1479             ptr = va_arg (var_args, dbus_int32_t *);
1480
1481             *ptr = dbus_message_iter_get_int32 (iter);
1482             break;
1483           }
1484         case DBUS_TYPE_UINT32:
1485           {
1486             dbus_uint32_t *ptr;
1487
1488             ptr = va_arg (var_args, dbus_uint32_t *);
1489
1490             *ptr = dbus_message_iter_get_uint32 (iter);
1491             break;
1492           }
1493
1494         case DBUS_TYPE_DOUBLE:
1495           {
1496             double *ptr;
1497
1498             ptr = va_arg (var_args, double *);
1499
1500             *ptr = dbus_message_iter_get_double (iter);
1501             break;
1502           }
1503
1504         case DBUS_TYPE_STRING:
1505           {
1506             char **ptr;
1507
1508             ptr = va_arg (var_args, char **);
1509
1510             *ptr = dbus_message_iter_get_string (iter);
1511
1512             if (!*ptr)
1513               return DBUS_RESULT_NO_MEMORY;
1514             
1515             break;
1516           }
1517
1518         case DBUS_TYPE_INT32_ARRAY:
1519           {
1520             dbus_int32_t **ptr;
1521             int *len;
1522
1523             ptr = va_arg (var_args, dbus_int32_t **);
1524             len = va_arg (var_args, int *);
1525
1526             if (!dbus_message_iter_get_int32_array (iter, ptr, len))
1527               return DBUS_RESULT_NO_MEMORY;
1528             
1529             break;
1530           }
1531
1532         case DBUS_TYPE_UINT32_ARRAY:
1533           {
1534             dbus_uint32_t **ptr;
1535             int *len;
1536
1537             ptr = va_arg (var_args, dbus_uint32_t **);
1538             len = va_arg (var_args, int *);
1539
1540             if (!dbus_message_iter_get_uint32_array (iter, ptr, len))
1541               return DBUS_RESULT_NO_MEMORY;
1542             
1543             break;
1544           }
1545
1546         case DBUS_TYPE_DOUBLE_ARRAY:
1547           {
1548             double **ptr;
1549             int *len;
1550
1551             ptr = va_arg (var_args, double **);
1552             len = va_arg (var_args, int *);
1553
1554             if (!dbus_message_iter_get_double_array (iter, ptr, len))
1555               return DBUS_RESULT_NO_MEMORY;
1556             
1557             break;
1558           }
1559           
1560         case DBUS_TYPE_BYTE_ARRAY:
1561           {
1562             unsigned char **ptr;
1563             int *len;
1564
1565             ptr = va_arg (var_args, unsigned char **);
1566             len = va_arg (var_args, int *);
1567
1568             if (!dbus_message_iter_get_byte_array (iter, ptr, len))
1569               return DBUS_RESULT_NO_MEMORY;
1570             
1571             break;
1572           }
1573         case DBUS_TYPE_STRING_ARRAY:
1574           {
1575             char ***ptr;
1576             int *len;
1577
1578             ptr = va_arg (var_args, char ***);
1579             len = va_arg (var_args, int *);
1580
1581             if (!dbus_message_iter_get_string_array (iter, ptr, len))
1582               return DBUS_RESULT_NO_MEMORY;
1583             break;
1584           }
1585         default:          
1586           _dbus_warn ("Unknown field type %d\n", spec_type);
1587         }
1588       
1589       spec_type = va_arg (var_args, int);
1590       if (spec_type != 0 && !dbus_message_iter_next (iter))
1591         {
1592           _dbus_verbose ("More fields than exist in the message were specified or field is corrupt\n");
1593
1594           dbus_message_iter_unref (iter);  
1595           return DBUS_RESULT_INVALID_ARGS;
1596         }
1597       i++;
1598     }
1599
1600   dbus_message_iter_unref (iter);
1601   return DBUS_RESULT_SUCCESS;
1602 }
1603
1604 /**
1605  * Returns a DBusMessageIter representing the arguments of the
1606  * message passed in.
1607  *
1608  * @todo IMO the message iter should follow the GtkTextIter pattern,
1609  * a static object with a "stamp" value used to detect invalid
1610  * iter uses (uninitialized or after changing the message).
1611  * ref/unref is kind of annoying to deal with, and slower too.
1612  * This implies not ref'ing the message from the iter.
1613  *
1614  * @param message the message
1615  * @returns a new iter.
1616  */
1617 DBusMessageIter *
1618 dbus_message_get_args_iter (DBusMessage *message)
1619 {
1620   DBusMessageIter *iter;
1621   
1622   iter = dbus_new (DBusMessageIter, 1);
1623
1624   dbus_message_ref (message);
1625   
1626   iter->refcount = 1;
1627   iter->message = message;
1628   iter->pos = 0;
1629
1630   return iter;
1631 }
1632
1633 /**
1634  * Increments the reference count of a DBusMessageIter.
1635  *
1636  * @param iter the message iter
1637  * @see dbus_message_iter_unref
1638  */
1639 void
1640 dbus_message_iter_ref (DBusMessageIter *iter)
1641 {
1642   _dbus_assert (iter->refcount > 0);
1643   
1644   iter->refcount += 1;
1645 }
1646
1647 /**
1648  * Decrements the reference count of a DBusMessageIter.
1649  *
1650  * @param iter The message iter
1651  * @see dbus_message_iter_ref
1652  */
1653 void
1654 dbus_message_iter_unref (DBusMessageIter *iter)
1655 {
1656   _dbus_assert (iter->refcount > 0);
1657
1658   iter->refcount -= 1;
1659
1660   if (iter->refcount == 0)
1661     {
1662       dbus_message_unref (iter->message);
1663
1664       dbus_free (iter);
1665     }
1666 }
1667
1668 /**
1669  * Checks if an iterator has any more fields.
1670  *
1671  * @param iter the message iter
1672  * @returns #TRUE if there are more fields
1673  * following
1674  */
1675 dbus_bool_t
1676 dbus_message_iter_has_next (DBusMessageIter *iter)
1677 {
1678   int end_pos;
1679   
1680   if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
1681                                       iter->message->byte_order,
1682                                       iter->pos, &end_pos))
1683     return FALSE;
1684   
1685   if (end_pos >= _dbus_string_get_length (&iter->message->body))
1686     return FALSE;
1687   
1688   return TRUE;  
1689 }
1690
1691 /**
1692  * Moves the iterator to the next field.
1693  *
1694  * @param iter The message iter
1695  * @returns #TRUE if the iterator was moved to the next field
1696  */
1697 dbus_bool_t
1698 dbus_message_iter_next (DBusMessageIter *iter)
1699 {
1700   int end_pos;
1701   
1702   if (!_dbus_marshal_get_arg_end_pos (&iter->message->body,
1703                                       iter->message->byte_order,
1704                                       iter->pos, &end_pos))
1705     return FALSE;
1706
1707   if (end_pos >= _dbus_string_get_length (&iter->message->body))
1708     return FALSE;
1709
1710   iter->pos = end_pos;
1711
1712   return TRUE;
1713 }
1714
1715 /**
1716  * Returns the argument type of the argument that the
1717  * message iterator points at.
1718  *
1719  * @param iter the message iter
1720  * @returns the field type
1721  */
1722 int
1723 dbus_message_iter_get_arg_type (DBusMessageIter *iter)
1724 {
1725   const char *data;
1726
1727   if (iter->pos >= _dbus_string_get_length (&iter->message->body))
1728     return DBUS_TYPE_INVALID;
1729
1730   _dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
1731
1732   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING_ARRAY)
1733     return *data;
1734
1735   return DBUS_TYPE_INVALID;
1736 }
1737
1738 /**
1739  * Returns the string value that an iterator may point to.
1740  * Note that you need to check that the iterator points to
1741  * a string value before using this function.
1742  *
1743  * @see dbus_message_iter_get_field_type
1744  * @param iter the message iter
1745  * @returns the string
1746  */
1747 char *
1748 dbus_message_iter_get_string (DBusMessageIter *iter)
1749 {
1750   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING);
1751
1752   return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
1753                                  iter->pos + 1, NULL);
1754 }
1755
1756 /**
1757  * Returns the 32 bit signed integer value that an iterator may point to.
1758  * Note that you need to check that the iterator points to
1759  * an integer value before using this function.
1760  *
1761  * @see dbus_message_iter_get_field_type
1762  * @param iter the message iter
1763  * @returns the integer
1764  */
1765 int
1766 dbus_message_iter_get_int32 (DBusMessageIter *iter)
1767 {
1768   return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
1769                                 iter->pos + 1, NULL);
1770 }
1771
1772 /**
1773  * Returns the 32 bit unsigned integer value that an iterator may point to.
1774  * Note that you need to check that the iterator points to
1775  * an unsigned integer value before using this function.
1776  *
1777  * @see dbus_message_iter_get_field_type
1778  * @param iter the message iter
1779  * @returns the integer
1780  */
1781 int
1782 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
1783 {
1784   return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
1785                                  iter->pos + 1, NULL);
1786 }
1787
1788 /**
1789  * Returns the double value that an iterator may point to.
1790  * Note that you need to check that the iterator points to
1791  * a string value before using this function.
1792  *
1793  * @see dbus_message_iter_get_field_type
1794  * @param iter the message iter
1795  * @returns the double
1796  */
1797 double
1798 dbus_message_iter_get_double (DBusMessageIter *iter)
1799 {
1800   return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
1801                                  iter->pos + 1, NULL);
1802 }
1803
1804 /**
1805  * Returns the 32 bit signed integer array that the iterator may point
1806  * to. Note that you need to check that the iterator points to an
1807  * array of the correct type prior to using this function.
1808  *
1809  * @param iter the iterator
1810  * @param value return location for the array
1811  * @param len return location for the array length
1812  * @returns #TRUE on success
1813  */
1814 dbus_bool_t
1815 dbus_message_iter_get_int32_array  (DBusMessageIter *iter,
1816                                     dbus_int32_t   **value,
1817                                     int             *len)
1818 {
1819   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_INT32_ARRAY);
1820
1821   *value = _dbus_demarshal_int32_array (&iter->message->body, iter->message->byte_order,
1822                                         iter->pos + 1, NULL, len);
1823   
1824   if (!*value)
1825     return FALSE;
1826   else
1827     return TRUE;
1828 }
1829
1830 /**
1831  * Returns the 32 bit unsigned integer array that the iterator may point
1832  * to. Note that you need to check that the iterator points to an
1833  * array of the correct type prior to using this function.
1834  *
1835  * @param iter the iterator
1836  * @param value return location for the array
1837  * @param len return location for the array length
1838  * @returns #TRUE on success
1839  */
1840 dbus_bool_t
1841 dbus_message_iter_get_uint32_array  (DBusMessageIter *iter,
1842                                      dbus_uint32_t  **value,
1843                                      int             *len)
1844 {
1845   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UINT32_ARRAY);
1846
1847   *value = _dbus_demarshal_uint32_array (&iter->message->body, iter->message->byte_order,
1848                                          iter->pos + 1, NULL, len);
1849   
1850   if (!*value)
1851     return FALSE;
1852   else
1853     return TRUE;
1854 }
1855
1856 /**
1857  * Returns the double array that the iterator may point to. Note that
1858  * you need to check that the iterator points to an array of the
1859  * correct type prior to using this function.
1860  *
1861  * @param iter the iterator
1862  * @param value return location for the array
1863  * @param len return location for the array length
1864  * @returns #TRUE on success
1865  */
1866 dbus_bool_t
1867 dbus_message_iter_get_double_array  (DBusMessageIter *iter,
1868                                      double         **value,
1869                                      int             *len)
1870 {
1871   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_DOUBLE_ARRAY);
1872
1873   *value = _dbus_demarshal_double_array (&iter->message->body, iter->message->byte_order,
1874                                          iter->pos + 1, NULL, len);
1875   
1876   if (!*value)
1877     return FALSE;
1878   else
1879     return TRUE;
1880 }
1881
1882 /**
1883  * Returns the byte array that the iterator may point to.
1884  * Note that you need to check that the iterator points
1885  * to a byte array prior to using this function.
1886  *
1887  * @param iter the iterator
1888  * @param value return location for array values
1889  * @param len return location for length of byte array
1890  * @returns the byte array
1891  */
1892 dbus_bool_t
1893 dbus_message_iter_get_byte_array (DBusMessageIter  *iter,
1894                                   unsigned char   **value,
1895                                   int              *len)
1896 {
1897   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_BYTE_ARRAY);
1898   
1899   *value = _dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
1900                                        iter->pos + 1, NULL, len);
1901
1902   if (!*value)
1903     return FALSE;
1904   else
1905     return TRUE;
1906 }
1907
1908 /**
1909  * Returns the string array that the iterator may point to.
1910  * Note that you need to check that the iterator points
1911  * to a byte array prior to using this function.
1912  *
1913  * The returned value is a #NULL-terminated array of strings.
1914  * Each string is a separate malloc block, and the array
1915  * itself is a malloc block. You can free this type of
1916  * string array with dbus_free_string_array().
1917  *
1918  * @param iter the iterator
1919  * @param value return location for string values
1920  * @param len return location for length of byte array
1921  * @returns the byte array
1922  */
1923 dbus_bool_t
1924 dbus_message_iter_get_string_array (DBusMessageIter *iter,
1925                                     char          ***value,
1926                                     int             *len)
1927 {
1928   _dbus_assert (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_STRING_ARRAY);
1929
1930   *value = _dbus_demarshal_string_array (&iter->message->body, iter->message->byte_order,
1931                                          iter->pos + 1, NULL, len);
1932
1933   if (!*value)
1934     return FALSE;
1935   else
1936     return TRUE;
1937 }
1938
1939 /**
1940  * Sets the message sender.
1941  *
1942  * @param message the message
1943  * @param sender the sender
1944  * @returns #FALSE if not enough memory
1945  */
1946 dbus_bool_t
1947 dbus_message_set_sender (DBusMessage  *message,
1948                          const char   *sender)
1949 {
1950   _dbus_assert (!message->locked);
1951
1952   if (sender == NULL)
1953     {
1954       delete_string_field (message, FIELD_SENDER);
1955       return TRUE;
1956     }
1957   else
1958     {
1959       return set_string_field (message,
1960                                FIELD_SENDER,
1961                                sender);
1962     }
1963 }
1964
1965 /**
1966  * Sets a flag indicating that the message is an error reply
1967  * message, i.e. an "exception" rather than a normal response.
1968  *
1969  * @param message the message
1970  * @param is_error_reply #TRUE if this is an error message.
1971  */
1972 void
1973 dbus_message_set_is_error (DBusMessage *message,
1974                            dbus_bool_t  is_error_reply)
1975 {
1976   char *header;
1977   
1978   _dbus_assert (!message->locked);
1979   
1980   _dbus_string_get_data_len (&message->header, &header, 1, 1);
1981   
1982   if (is_error_reply)
1983     *header |= DBUS_HEADER_FLAG_ERROR;
1984   else
1985     *header &= ~DBUS_HEADER_FLAG_ERROR;    
1986 }
1987
1988 /**
1989  * Returns #TRUE if the message is an error
1990  * reply to some previous message we sent.
1991  *
1992  * @param message the message
1993  * @returns #TRUE if the message is an error
1994  */
1995 dbus_bool_t
1996 dbus_message_get_is_error (DBusMessage *message)
1997 {
1998   const char *header;
1999
2000   _dbus_string_get_const_data_len (&message->header, &header, 1, 1);
2001
2002   return (*header & DBUS_HEADER_FLAG_ERROR) != 0;
2003 }
2004
2005 /**
2006  * Gets the service which originated this message,
2007  * or #NULL if unknown or inapplicable.
2008  *
2009  * @param message the message
2010  * @returns the service name or #NULL
2011  */
2012 const char*
2013 dbus_message_get_sender (DBusMessage *message)
2014 {
2015   return get_string_field (message, FIELD_SENDER, NULL);
2016 }
2017
2018 /**
2019  * Checks whether the message has the given name.
2020  * If the message has no name or has a different
2021  * name, returns #FALSE.
2022  *
2023  * @param message the message
2024  * @param name the name to check (must not be #NULL)
2025  * 
2026  * @returns #TRUE if the message has the given name
2027  */
2028 dbus_bool_t
2029 dbus_message_name_is (DBusMessage *message,
2030                       const char  *name)
2031 {
2032   const char *n;
2033
2034   _dbus_assert (name != NULL);
2035   
2036   n = dbus_message_get_name (message);
2037
2038   if (n && strcmp (n, name) == 0)
2039     return TRUE;
2040   else
2041     return FALSE;
2042 }
2043
2044 /** @} */
2045
2046 /**
2047  * @addtogroup DBusMessageInternals
2048  *
2049  * @{
2050  */
2051 /**
2052  * @typedef DBusMessageLoader
2053  *
2054  * The DBusMessageLoader object encapsulates the process of converting
2055  * a byte stream into a series of DBusMessage. It buffers the incoming
2056  * bytes as efficiently as possible, and generates a queue of
2057  * messages. DBusMessageLoader is typically used as part of a
2058  * DBusTransport implementation. The DBusTransport then hands off
2059  * the loaded messages to a DBusConnection, making the messages
2060  * visible to the application.
2061  * 
2062  */
2063
2064 /* we definitely use signed ints for sizes, so don't exceed
2065  * _DBUS_INT_MAX; and add 16 for paranoia, since a message
2066  * over 128M is pretty nuts anyhow.
2067  */
2068
2069 /**
2070  * The maximum sane message size.
2071  */
2072 #define MAX_SANE_MESSAGE_SIZE (_DBUS_INT_MAX/16)
2073
2074 /**
2075  * Implementation details of DBusMessageLoader.
2076  * All members are private.
2077  */
2078 struct DBusMessageLoader
2079 {
2080   int refcount;        /**< Reference count. */
2081
2082   DBusString data;     /**< Buffered data */
2083   
2084   DBusList *messages;  /**< Complete messages. */
2085
2086   long max_message_size; /**< Maximum size of a message */
2087   
2088   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
2089
2090   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
2091 };
2092
2093 /**
2094  * The initial buffer size of the message loader.
2095  * 
2096  * @todo this should be based on min header size plus some average
2097  * body size, or something. Or rather, the min header size only, if we
2098  * want to try to read only the header, store that in a DBusMessage,
2099  * then read only the body and store that, etc., depends on
2100  * how we optimize _dbus_message_loader_get_buffer() and what
2101  * the exact message format is.
2102  */
2103 #define INITIAL_LOADER_DATA_LEN 32
2104
2105 /**
2106  * Creates a new message loader. Returns #NULL if memory can't
2107  * be allocated.
2108  *
2109  * @returns new loader, or #NULL.
2110  */
2111 DBusMessageLoader*
2112 _dbus_message_loader_new (void)
2113 {
2114   DBusMessageLoader *loader;
2115
2116   loader = dbus_new0 (DBusMessageLoader, 1);
2117   if (loader == NULL)
2118     return NULL;
2119   
2120   loader->refcount = 1;
2121
2122   /* Try to cap message size at something that won't *totally* hose
2123    * the system if we have a couple of them.
2124    */
2125   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
2126   
2127   if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
2128     {
2129       dbus_free (loader);
2130       return NULL;
2131     }
2132
2133   /* preallocate the buffer for speed, ignore failure */
2134   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
2135   _dbus_string_set_length (&loader->data, 0);
2136   
2137   return loader;
2138 }
2139
2140 /**
2141  * Increments the reference count of the loader.
2142  *
2143  * @param loader the loader.
2144  */
2145 void
2146 _dbus_message_loader_ref (DBusMessageLoader *loader)
2147 {
2148   loader->refcount += 1;
2149 }
2150
2151 /**
2152  * Decrements the reference count of the loader and finalizes the
2153  * loader when the count reaches zero.
2154  *
2155  * @param loader the loader.
2156  */
2157 void
2158 _dbus_message_loader_unref (DBusMessageLoader *loader)
2159 {
2160   loader->refcount -= 1;
2161   if (loader->refcount == 0)
2162     {
2163       _dbus_list_foreach (&loader->messages,
2164                           (DBusForeachFunction) dbus_message_unref,
2165                           NULL);
2166       _dbus_list_clear (&loader->messages);
2167       _dbus_string_free (&loader->data);
2168       dbus_free (loader);
2169     }
2170 }
2171
2172 /**
2173  * Gets the buffer to use for reading data from the network.  Network
2174  * data is read directly into an allocated buffer, which is then used
2175  * in the DBusMessage, to avoid as many extra memcpy's as possible.
2176  * The buffer must always be returned immediately using
2177  * _dbus_message_loader_return_buffer(), even if no bytes are
2178  * successfully read.
2179  *
2180  * @todo this function can be a lot more clever. For example
2181  * it can probably always return a buffer size to read exactly
2182  * the body of the next message, thus avoiding any memory wastage
2183  * or reallocs.
2184  * 
2185  * @param loader the message loader.
2186  * @param buffer the buffer
2187  */
2188 void
2189 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
2190                                  DBusString        **buffer)
2191 {
2192   _dbus_assert (!loader->buffer_outstanding);
2193
2194   *buffer = &loader->data;
2195   
2196   loader->buffer_outstanding = TRUE;
2197 }
2198
2199 /**
2200  * The smallest header size that can occur. 
2201  * (It won't be valid)
2202  */
2203 #define DBUS_MINIMUM_HEADER_SIZE 16
2204
2205 /** Pack four characters as in "abcd" into a uint32 */
2206 #define FOUR_CHARS_TO_UINT32(a, b, c, d)                \
2207                       ((((dbus_uint32_t)a) << 24) |     \
2208                        (((dbus_uint32_t)b) << 16) |     \
2209                        (((dbus_uint32_t)c) << 8)  |     \
2210                        ((dbus_uint32_t)d))
2211
2212 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
2213 #define DBUS_HEADER_FIELD_NAME_AS_UINT32    \
2214   FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
2215
2216 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
2217 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
2218   FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
2219
2220 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
2221 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32   \
2222   FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
2223
2224 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
2225 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32  \
2226   FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
2227
2228 static dbus_bool_t
2229 decode_header_data (const DBusString   *data,
2230                     int                 header_len,
2231                     int                 byte_order,
2232                     HeaderField         fields[FIELD_LAST],
2233                     int                *message_padding)
2234 {
2235   const char *field;
2236   int pos, new_pos;
2237   int i;
2238   
2239   if (header_len < 16)
2240     return FALSE;
2241   
2242   i = 0;
2243   while (i < FIELD_LAST)
2244     {
2245       fields[i].offset = -1;
2246       ++i;
2247     }
2248   
2249   fields[FIELD_HEADER_LENGTH].offset = 4;
2250   fields[FIELD_BODY_LENGTH].offset = 8;   
2251   fields[FIELD_CLIENT_SERIAL].offset = 12;
2252   
2253   /* Now handle the named fields. A real named field is at least 4
2254    * bytes for the name, plus a type code (1 byte) plus padding.  So
2255    * if we have less than 8 bytes left, it must be alignment padding,
2256    * not a field. While >= 8 bytes can't be entirely alignment
2257    * padding.
2258    */  
2259   pos = 16;
2260   while ((pos + 7) < header_len)
2261     {
2262       pos = _DBUS_ALIGN_VALUE (pos, 4);
2263       
2264       if ((pos + 4) > header_len)
2265         return FALSE;      
2266       
2267       _dbus_string_get_const_data_len (data, &field, pos, 4);
2268       pos += 4;
2269
2270       _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
2271
2272       /* I believe FROM_BE is right, but if not we'll find out
2273        * I guess. ;-)
2274        */
2275       switch (DBUS_UINT32_FROM_BE (*(int*)field))
2276         {
2277         case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
2278           if (fields[FIELD_SERVICE].offset >= 0)
2279             {
2280               _dbus_verbose ("%s field provided twice\n",
2281                              DBUS_HEADER_FIELD_SERVICE);
2282               return FALSE;
2283             }
2284           
2285           fields[FIELD_SERVICE].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2286           _dbus_verbose ("Found service name at offset %d\n",
2287                          fields[FIELD_SERVICE].offset);
2288           break;
2289
2290         case DBUS_HEADER_FIELD_NAME_AS_UINT32:
2291           if (fields[FIELD_NAME].offset >= 0)
2292             {
2293               _dbus_verbose ("%s field provided twice\n",
2294                              DBUS_HEADER_FIELD_NAME);
2295               return FALSE;
2296             }
2297           
2298           fields[FIELD_NAME].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2299
2300           _dbus_verbose ("Found message name at offset %d\n",
2301                          fields[FIELD_NAME].offset);
2302           break;
2303         case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
2304           if (fields[FIELD_SENDER].offset >= 0)
2305             {
2306               _dbus_verbose ("%s field provided twice\n",
2307                              DBUS_HEADER_FIELD_SENDER);
2308               return FALSE;
2309             }
2310           
2311           fields[FIELD_SENDER].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2312
2313           _dbus_verbose ("Found sender name at offset %d\n",
2314                          fields[FIELD_NAME].offset);
2315           break;
2316           
2317         case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
2318           if (fields[FIELD_REPLY_SERIAL].offset >= 0)
2319             {
2320               _dbus_verbose ("%s field provided twice\n",
2321                              DBUS_HEADER_FIELD_REPLY);
2322               return FALSE;
2323             }
2324           
2325           fields[FIELD_REPLY_SERIAL].offset = _DBUS_ALIGN_VALUE (pos + 1, 4);
2326
2327           _dbus_verbose ("Found reply serial at offset %d\n",
2328                          fields[FIELD_REPLY_SERIAL].offset);
2329           break;
2330
2331         default:
2332           _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c at offset %d\n",
2333                          field[0], field[1], field[2], field[3], pos);
2334         }
2335
2336       if (!_dbus_marshal_validate_arg (data, byte_order, pos, &new_pos))
2337         {
2338           _dbus_verbose ("Failed to validate argument to named header field\n");
2339           return FALSE;
2340         }
2341
2342       if (new_pos > header_len)
2343         {
2344           _dbus_verbose ("Named header field tries to extend beyond header length\n");
2345           return FALSE;
2346         }
2347       
2348       pos = new_pos;
2349     }
2350
2351   if (pos < header_len)
2352     {
2353       /* Alignment padding, verify that it's nul */
2354       _dbus_assert ((header_len - pos) < 8);
2355
2356       if (!_dbus_string_validate_nul (data,
2357                                       pos, (header_len - pos)))
2358         {
2359           _dbus_verbose ("header alignment padding is not nul\n");
2360           return FALSE;
2361         }
2362
2363       if (message_padding)
2364         *message_padding = header_len - pos;
2365     }
2366   
2367   return TRUE;
2368 }
2369
2370 /**
2371  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
2372  * indicating to the loader how many bytes of the buffer were filled
2373  * in. This function must always be called, even if no bytes were
2374  * successfully read.
2375  *
2376  * @todo if we run out of memory in here, we offer no way for calling
2377  * code to handle it, i.e. they can't re-run the message parsing
2378  * attempt. Perhaps much of this code could be moved to pop_message()?
2379  * But then that may need to distinguish NULL return for no messages
2380  * from NULL return for errors.
2381  *
2382  * @param loader the loader.
2383  * @param buffer the buffer.
2384  * @param bytes_read number of bytes that were read into the buffer.
2385  */
2386 void
2387 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
2388                                     DBusString         *buffer,
2389                                     int                 bytes_read)
2390 {
2391   _dbus_assert (loader->buffer_outstanding);
2392   _dbus_assert (buffer == &loader->data);
2393
2394   loader->buffer_outstanding = FALSE;
2395
2396   if (loader->corrupted)
2397     return;
2398
2399   while (_dbus_string_get_length (&loader->data) >= 16)
2400     {
2401       DBusMessage *message;      
2402       const char *header_data;
2403       int byte_order, header_len, body_len, header_padding;
2404       dbus_uint32_t header_len_unsigned, body_len_unsigned;
2405       
2406       _dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
2407
2408       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
2409
2410       if (header_data[2] != DBUS_MAJOR_PROTOCOL_VERSION)
2411         {
2412           _dbus_verbose ("Message has protocol version %d ours is %d\n",
2413                          (int) header_data[2], DBUS_MAJOR_PROTOCOL_VERSION);
2414           loader->corrupted = TRUE;
2415           return;
2416         }
2417       
2418       byte_order = header_data[0];
2419
2420       if (byte_order != DBUS_LITTLE_ENDIAN &&
2421           byte_order != DBUS_BIG_ENDIAN)
2422         {
2423           _dbus_verbose ("Message with bad byte order '%c' received\n",
2424                          byte_order);
2425           loader->corrupted = TRUE;
2426           return;
2427         }
2428
2429       header_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 4);
2430       body_len_unsigned = _dbus_unpack_uint32 (byte_order, header_data + 8);
2431
2432       if (header_len_unsigned < 16)
2433         {
2434           _dbus_verbose ("Message had broken too-small header length %u\n",
2435                          header_len_unsigned);
2436           loader->corrupted = TRUE;
2437           return;
2438         }
2439
2440       if (header_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE ||
2441           body_len_unsigned > (unsigned) MAX_SANE_MESSAGE_SIZE)
2442         {
2443           _dbus_verbose ("Header or body length too large (%u %u)\n",
2444                          header_len_unsigned,
2445                          body_len_unsigned);
2446           loader->corrupted = TRUE;
2447           return;
2448         }
2449
2450       /* Now that we know the values are in signed range, get
2451        * rid of stupid unsigned, just causes bugs
2452        */
2453       header_len = header_len_unsigned;
2454       body_len = body_len_unsigned;
2455       
2456       if (_DBUS_ALIGN_VALUE (header_len, 8) != header_len_unsigned)
2457         {
2458           _dbus_verbose ("header length %d is not aligned to 8 bytes\n",
2459                          header_len);
2460           loader->corrupted = TRUE;
2461           return;
2462         }
2463       
2464       if (header_len + body_len > loader->max_message_size)
2465         {
2466           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %d\n",
2467                          header_len, body_len, loader->max_message_size);
2468           loader->corrupted = TRUE;
2469           return;
2470         }
2471
2472       if (_dbus_string_get_length (&loader->data) >= (header_len + body_len))
2473         {
2474           HeaderField fields[FIELD_LAST];
2475           int i;
2476           int next_arg;          
2477
2478           _dbus_verbose_bytes_of_string (&loader->data, 0, header_len);
2479           if (!decode_header_data (&loader->data, header_len, byte_order,
2480                                    fields, &header_padding))
2481             {
2482               _dbus_verbose ("Header was invalid\n");
2483               loader->corrupted = TRUE;
2484               return;
2485             }
2486           
2487           next_arg = header_len;
2488           while (next_arg < (header_len + body_len))
2489             {
2490               int prev = next_arg;
2491
2492               if (!_dbus_marshal_validate_arg (&loader->data,
2493                                                byte_order,
2494                                                next_arg,
2495                                                &next_arg))
2496                 {
2497                   loader->corrupted = TRUE;
2498                   return;
2499                 }
2500
2501               _dbus_assert (next_arg > prev);
2502             }
2503           
2504           if (next_arg > (header_len + body_len))
2505             {
2506               _dbus_verbose ("end of last arg at %d but message has len %d+%d=%d\n",
2507                              next_arg, header_len, body_len,
2508                              header_len + body_len);
2509               loader->corrupted = TRUE;
2510               return;
2511             }
2512
2513           message = dbus_message_new_empty_header ();
2514           if (message == NULL)
2515             break; /* ugh, postpone this I guess. */
2516
2517           message->byte_order = byte_order;
2518           message->header_padding = header_padding;
2519           
2520           /* Copy in the offsets we found */
2521           i = 0;
2522           while (i < FIELD_LAST)
2523             {
2524               message->header_fields[i] = fields[i];
2525               ++i;
2526             }
2527           
2528           if (!_dbus_list_append (&loader->messages, message))
2529             {
2530               dbus_message_unref (message);
2531               break;
2532             }
2533
2534           _dbus_assert (_dbus_string_get_length (&message->header) == 0);
2535           _dbus_assert (_dbus_string_get_length (&message->body) == 0);
2536
2537           _dbus_assert (_dbus_string_get_length (&loader->data) >=
2538                         (header_len + body_len));
2539           
2540           if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
2541             {
2542               _dbus_list_remove_last (&loader->messages, message);
2543               dbus_message_unref (message);
2544               break;
2545             }
2546           
2547           if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
2548             {
2549               dbus_bool_t result;
2550
2551               /* put the header back, we'll try again later */
2552               result = _dbus_string_copy_len (&message->header, 0, header_len,
2553                                               &loader->data, 0);
2554               _dbus_assert (result); /* because DBusString never reallocs smaller */
2555
2556               _dbus_list_remove_last (&loader->messages, message);
2557               dbus_message_unref (message);
2558               break;
2559             }
2560
2561           _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
2562           _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
2563
2564           _dbus_verbose ("Loaded message %p\n", message);
2565         }
2566       else
2567         break;
2568     }
2569 }
2570
2571 /**
2572  * Pops a loaded message (passing ownership of the message
2573  * to the caller). Returns #NULL if no messages have been
2574  * loaded.
2575  *
2576  * @param loader the loader.
2577  * @returns the next message, or #NULL if none.
2578  */
2579 DBusMessage*
2580 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
2581 {
2582   return _dbus_list_pop_first (&loader->messages);
2583 }
2584
2585
2586 /**
2587  * Checks whether the loader is confused due to bad data.
2588  * If messages are received that are invalid, the
2589  * loader gets confused and gives up permanently.
2590  * This state is called "corrupted."
2591  *
2592  * @param loader the loader
2593  * @returns #TRUE if the loader is hosed.
2594  */
2595 dbus_bool_t
2596 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
2597 {
2598   return loader->corrupted;
2599 }
2600
2601 /**
2602  * Sets the maximum size message we allow.
2603  *
2604  * @param loader the loader
2605  * @param size the max message size in bytes
2606  */
2607 void
2608 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
2609                                            long                size)
2610 {
2611   if (size > MAX_SANE_MESSAGE_SIZE)
2612     {
2613       _dbus_verbose ("clamping requested max message size %ld to %d\n",
2614                      size, MAX_SANE_MESSAGE_SIZE);
2615       size = MAX_SANE_MESSAGE_SIZE;
2616     }
2617   loader->max_message_size = size;
2618 }
2619
2620 /**
2621  * Gets the maximum allowed message size in bytes.
2622  *
2623  * @param loader the loader
2624  * @returns max size in bytes
2625  */
2626 long
2627 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
2628 {
2629   return loader->max_message_size;
2630 }
2631
2632 /** @} */
2633 #ifdef DBUS_BUILD_TESTS
2634 #include "dbus-test.h"
2635 #include <stdio.h>
2636
2637 static void
2638 message_iter_test (DBusMessage *message)
2639 {
2640   DBusMessageIter *iter;
2641   char *str;
2642   
2643   iter = dbus_message_get_args_iter (message);
2644
2645   /* String tests */
2646   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRING)
2647     _dbus_assert_not_reached ("Argument type isn't string");
2648
2649   str = dbus_message_iter_get_string (iter);
2650   if (strcmp (str, "Test string") != 0)
2651     _dbus_assert_not_reached ("Strings differ");
2652   dbus_free (str);
2653
2654   if (!dbus_message_iter_next (iter))
2655     _dbus_assert_not_reached ("Reached end of arguments");
2656
2657   /* Signed integer tests */
2658   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_INT32)
2659     _dbus_assert_not_reached ("Argument type isn't int32");
2660
2661   if (dbus_message_iter_get_int32 (iter) != -0x12345678)
2662     _dbus_assert_not_reached ("Signed integers differ");
2663
2664   if (!dbus_message_iter_next (iter))
2665     _dbus_assert_not_reached ("Reached end of fields");
2666   
2667   /* Unsigned integer tests */
2668   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_UINT32)
2669     _dbus_assert_not_reached ("Argument type isn't int32");
2670
2671   if (dbus_message_iter_get_int32 (iter) != 0xedd1e)
2672     _dbus_assert_not_reached ("Unsigned integers differ");
2673
2674   if (!dbus_message_iter_next (iter))
2675     _dbus_assert_not_reached ("Reached end of arguments");
2676
2677   /* Double tests */
2678   if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_DOUBLE)
2679     _dbus_assert_not_reached ("Argument type isn't double");
2680
2681   if (dbus_message_iter_get_double (iter) != 3.14159)
2682     _dbus_assert_not_reached ("Doubles differ");
2683
2684   if (dbus_message_iter_next (iter))
2685     _dbus_assert_not_reached ("Didn't reach end of arguments");
2686   
2687   dbus_message_iter_unref (iter);
2688 }
2689
2690 static dbus_bool_t
2691 check_message_handling (DBusMessage *message)
2692 {
2693   DBusMessageIter *iter;
2694   int type;
2695   dbus_bool_t retval;
2696   dbus_int32_t client_serial;
2697   
2698   retval = FALSE;
2699   iter = NULL;
2700   
2701   client_serial = _dbus_message_get_client_serial (message);
2702
2703   /* can't use set_client_serial due to the assertions at the start of it */
2704   set_int_field (message, FIELD_CLIENT_SERIAL,
2705                  client_serial);
2706
2707   if (client_serial != _dbus_message_get_client_serial (message))
2708     {
2709       _dbus_warn ("get/set cycle for client_serial did not succeed\n");
2710       goto failed;
2711     }
2712   
2713   /* If we implement message_set_arg (message, n, value)
2714    * then we would want to test it here
2715    */
2716   
2717   iter = dbus_message_get_args_iter (message);
2718   while ((type = dbus_message_iter_get_arg_type (iter)) != DBUS_TYPE_INVALID)
2719     {
2720       switch (type)
2721         {
2722         case DBUS_TYPE_NIL:
2723           break;
2724         case DBUS_TYPE_INT32:
2725           dbus_message_iter_get_int32 (iter);
2726           break;
2727         case DBUS_TYPE_UINT32:
2728           dbus_message_iter_get_uint32 (iter);
2729           break;
2730         case DBUS_TYPE_DOUBLE:
2731           dbus_message_iter_get_double (iter);
2732           break;
2733         case DBUS_TYPE_STRING:
2734           {
2735             char *str;
2736             str = dbus_message_iter_get_string (iter);
2737             dbus_free (str);
2738           }
2739           break;
2740         case DBUS_TYPE_INT32_ARRAY:
2741           {
2742             dbus_int32_t *values;
2743             int len;
2744             
2745             if (!dbus_message_iter_get_int32_array (iter, &values, &len))
2746               return FALSE;
2747
2748             dbus_free (values);
2749           }
2750           break;
2751         case DBUS_TYPE_UINT32_ARRAY:
2752           {
2753             dbus_uint32_t *values;
2754             int len;
2755             
2756             if (!dbus_message_iter_get_uint32_array (iter, &values, &len))
2757               return FALSE;
2758
2759             dbus_free (values);
2760           }
2761           break;
2762         case DBUS_TYPE_DOUBLE_ARRAY:
2763           {
2764             double *values;
2765             int len;
2766             
2767             if (!dbus_message_iter_get_double_array (iter, &values, &len))
2768               return FALSE;
2769
2770             dbus_free (values);
2771           }
2772           break;
2773         case DBUS_TYPE_STRING_ARRAY:
2774           {
2775             char **values;
2776             int len;
2777             
2778             if (!dbus_message_iter_get_string_array (iter, &values, &len))
2779               return FALSE;
2780
2781             dbus_free_string_array (values);
2782           }
2783           break;
2784           
2785         default:
2786           break;
2787         }
2788       
2789       if (!dbus_message_iter_next (iter))
2790         break;
2791     }
2792
2793   retval = TRUE;
2794   
2795  failed:
2796   if (iter)
2797     dbus_message_iter_unref (iter);
2798
2799   return retval;
2800 }
2801
2802 static dbus_bool_t
2803 check_have_valid_message (DBusMessageLoader *loader)
2804 {
2805   DBusMessage *message;
2806   dbus_bool_t retval;
2807
2808   message = NULL;
2809   retval = FALSE;
2810   
2811   if (_dbus_message_loader_get_is_corrupted (loader))
2812     {
2813       _dbus_warn ("loader corrupted on message that was expected to be valid\n");
2814       goto failed;
2815     }
2816   
2817   message = _dbus_message_loader_pop_message (loader);
2818   if (message == NULL)
2819     {
2820       _dbus_warn ("didn't load message that was expected to be valid (message not popped)\n");
2821       goto failed;
2822     }
2823   
2824   if (_dbus_string_get_length (&loader->data) > 0)
2825     {
2826       _dbus_warn ("had leftover bytes from expected-to-be-valid single message\n");
2827       goto failed;
2828     }
2829
2830   /* Verify that we're able to properly deal with the message.
2831    * For example, this would detect improper handling of messages
2832    * in nonstandard byte order.
2833    */
2834   if (!check_message_handling (message))
2835     goto failed;  
2836   
2837   retval = TRUE;
2838
2839  failed:
2840   if (message)
2841     dbus_message_unref (message);
2842   return retval;
2843 }
2844
2845 static dbus_bool_t
2846 check_invalid_message (DBusMessageLoader *loader)
2847 {
2848   dbus_bool_t retval;
2849
2850   retval = FALSE;
2851   
2852   if (!_dbus_message_loader_get_is_corrupted (loader))
2853     {
2854       _dbus_warn ("loader not corrupted on message that was expected to be invalid\n");
2855       goto failed;
2856     }
2857
2858   retval = TRUE;
2859
2860  failed:
2861   return retval;
2862 }
2863
2864 static dbus_bool_t
2865 check_incomplete_message (DBusMessageLoader *loader)
2866 {
2867   DBusMessage *message;
2868   dbus_bool_t retval;
2869
2870   message = NULL;
2871   retval = FALSE;
2872   
2873   if (_dbus_message_loader_get_is_corrupted (loader))
2874     {
2875       _dbus_warn ("loader corrupted on message that was expected to be valid (but incomplete)\n");
2876       goto failed;
2877     }
2878   
2879   message = _dbus_message_loader_pop_message (loader);
2880   if (message != NULL)
2881     {
2882       _dbus_warn ("loaded message that was expected to be incomplete\n");
2883       goto failed;
2884     }
2885
2886   retval = TRUE;
2887
2888  failed:
2889   if (message)
2890     dbus_message_unref (message);
2891   return retval;
2892 }
2893
2894 static dbus_bool_t
2895 check_loader_results (DBusMessageLoader      *loader,
2896                       DBusMessageValidity     validity)
2897 {
2898   switch (validity)
2899     {
2900     case _DBUS_MESSAGE_VALID:
2901       return check_have_valid_message (loader);
2902     case _DBUS_MESSAGE_INVALID:
2903       return check_invalid_message (loader);
2904     case _DBUS_MESSAGE_INCOMPLETE:
2905       return check_incomplete_message (loader);
2906     case _DBUS_MESSAGE_UNKNOWN:
2907       return TRUE;
2908     }
2909
2910   _dbus_assert_not_reached ("bad DBusMessageValidity");
2911   return FALSE;
2912 }
2913
2914
2915 /**
2916  * Loads the message in the given message file.
2917  *
2918  * @param filename filename to load
2919  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
2920  * @param data string to load message into
2921  * @returns #TRUE if the message was loaded
2922  */
2923 dbus_bool_t
2924 dbus_internal_do_not_use_load_message_file (const DBusString    *filename,
2925                                             dbus_bool_t          is_raw,
2926                                             DBusString          *data)
2927 {
2928   dbus_bool_t retval;
2929
2930   retval = FALSE;  
2931
2932   if (is_raw)
2933     {
2934       DBusResultCode result;
2935
2936       result = _dbus_file_get_contents (data, filename);
2937       if (result != DBUS_RESULT_SUCCESS)
2938         {
2939           const char *s;      
2940           _dbus_string_get_const_data (filename, &s);
2941           _dbus_warn ("Could not load message file %s\n", s);
2942           goto failed;
2943         }
2944     }
2945   else
2946     {
2947       if (!_dbus_message_data_load (data, filename))
2948         {
2949           const char *s;      
2950           _dbus_string_get_const_data (filename, &s);
2951           _dbus_warn ("Could not load message file %s\n", s);
2952           goto failed;
2953         }
2954     }
2955
2956   retval = TRUE;
2957   
2958  failed:
2959
2960   return retval;
2961 }
2962
2963 /**
2964  * Tries loading the message in the given message file
2965  * and verifies that DBusMessageLoader can handle it.
2966  *
2967  * @param filename filename to load
2968  * @param is_raw if #TRUE load as binary data, if #FALSE as message builder language
2969  * @param expected_validity what the message has to be like to return #TRUE
2970  * @returns #TRUE if the message has the expected validity
2971  */
2972 dbus_bool_t
2973 dbus_internal_do_not_use_try_message_file (const DBusString    *filename,
2974                                            dbus_bool_t          is_raw,
2975                                            DBusMessageValidity  expected_validity)
2976 {
2977   DBusString data;
2978   dbus_bool_t retval;
2979
2980   retval = FALSE;
2981   
2982   if (!_dbus_string_init (&data, _DBUS_INT_MAX))
2983     _dbus_assert_not_reached ("could not allocate string\n");
2984
2985   if (!dbus_internal_do_not_use_load_message_file (filename, is_raw,
2986                                                    &data))
2987     goto failed;
2988
2989   retval = dbus_internal_do_not_use_try_message_data (&data, expected_validity);
2990
2991  failed:
2992
2993   if (!retval)
2994     {
2995       const char *s;
2996
2997       if (_dbus_string_get_length (&data) > 0)
2998         _dbus_verbose_bytes_of_string (&data, 0,
2999                                        _dbus_string_get_length (&data));
3000       
3001       _dbus_string_get_const_data (filename, &s);
3002       _dbus_warn ("Failed message loader test on %s\n",
3003                   s);
3004     }
3005   
3006   _dbus_string_free (&data);
3007
3008   return retval;
3009 }
3010
3011 /**
3012  * Tries loading the given message data.
3013  *
3014  *
3015  * @param data the message data
3016  * @param expected_validity what the message has to be like to return #TRUE
3017  * @returns #TRUE if the message has the expected validity
3018  */
3019 dbus_bool_t
3020 dbus_internal_do_not_use_try_message_data (const DBusString    *data,
3021                                            DBusMessageValidity  expected_validity)
3022 {
3023   DBusMessageLoader *loader;
3024   dbus_bool_t retval;
3025   int len;
3026   int i;
3027
3028   loader = NULL;
3029   retval = FALSE;
3030
3031   /* Write the data one byte at a time */
3032   
3033   loader = _dbus_message_loader_new ();
3034
3035   len = _dbus_string_get_length (data);
3036   for (i = 0; i < len; i++)
3037     {
3038       DBusString *buffer;
3039
3040       _dbus_message_loader_get_buffer (loader, &buffer);
3041       _dbus_string_append_byte (buffer,
3042                                 _dbus_string_get_byte (data, i));
3043       _dbus_message_loader_return_buffer (loader, buffer, 1);
3044     }
3045   
3046   if (!check_loader_results (loader, expected_validity))
3047     goto failed;
3048
3049   _dbus_message_loader_unref (loader);
3050   loader = NULL;
3051
3052   /* Write the data all at once */
3053   
3054   loader = _dbus_message_loader_new ();
3055
3056   {
3057     DBusString *buffer;
3058     
3059     _dbus_message_loader_get_buffer (loader, &buffer);
3060     _dbus_string_copy (data, 0, buffer,
3061                        _dbus_string_get_length (buffer));
3062     _dbus_message_loader_return_buffer (loader, buffer, 1);
3063   }
3064   
3065   if (!check_loader_results (loader, expected_validity))
3066     goto failed;
3067
3068   _dbus_message_loader_unref (loader);
3069   loader = NULL;  
3070
3071   /* Write the data 2 bytes at a time */
3072   
3073   loader = _dbus_message_loader_new ();
3074
3075   len = _dbus_string_get_length (data);
3076   for (i = 0; i < len; i += 2)
3077     {
3078       DBusString *buffer;
3079
3080       _dbus_message_loader_get_buffer (loader, &buffer);
3081       _dbus_string_append_byte (buffer,
3082                                 _dbus_string_get_byte (data, i));
3083       if ((i+1) < len)
3084         _dbus_string_append_byte (buffer,
3085                                   _dbus_string_get_byte (data, i+1));
3086       _dbus_message_loader_return_buffer (loader, buffer, 1);
3087     }
3088   
3089   if (!check_loader_results (loader, expected_validity))
3090     goto failed;
3091
3092   _dbus_message_loader_unref (loader);
3093   loader = NULL;
3094   
3095   retval = TRUE;
3096   
3097  failed:
3098   
3099   if (loader)
3100     _dbus_message_loader_unref (loader);
3101   
3102   return retval;
3103 }
3104
3105 static dbus_bool_t
3106 process_test_subdir (const DBusString          *test_base_dir,
3107                      const char                *subdir,
3108                      DBusMessageValidity        validity,
3109                      DBusForeachMessageFileFunc function,
3110                      void                      *user_data)
3111 {
3112   DBusString test_directory;
3113   DBusString filename;
3114   DBusDirIter *dir;
3115   dbus_bool_t retval;
3116   DBusResultCode result;
3117
3118   retval = FALSE;
3119   dir = NULL;
3120   
3121   if (!_dbus_string_init (&test_directory, _DBUS_INT_MAX))
3122     _dbus_assert_not_reached ("didn't allocate test_directory\n");
3123
3124   _dbus_string_init_const (&filename, subdir);
3125   
3126   if (!_dbus_string_copy (test_base_dir, 0,
3127                           &test_directory, 0))
3128     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
3129   
3130   if (!_dbus_concat_dir_and_file (&test_directory, &filename))    
3131     _dbus_assert_not_reached ("couldn't allocate full path");
3132
3133   _dbus_string_free (&filename);
3134   if (!_dbus_string_init (&filename, _DBUS_INT_MAX))
3135     _dbus_assert_not_reached ("didn't allocate filename string\n");
3136   
3137   dir = _dbus_directory_open (&test_directory, &result);
3138   if (dir == NULL)
3139     {
3140       const char *s;
3141       _dbus_string_get_const_data (&test_directory, &s);
3142       _dbus_warn ("Could not open %s: %s\n", s,
3143                   dbus_result_to_string (result));
3144       goto failed;
3145     }
3146
3147   printf ("Testing:\n");
3148   
3149   result = DBUS_RESULT_SUCCESS;
3150  next:
3151   while (_dbus_directory_get_next_file (dir, &filename, &result))
3152     {
3153       DBusString full_path;
3154       dbus_bool_t is_raw;
3155       
3156       if (!_dbus_string_init (&full_path, _DBUS_INT_MAX))
3157         _dbus_assert_not_reached ("couldn't init string");
3158
3159       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
3160         _dbus_assert_not_reached ("couldn't copy dir to full_path");
3161
3162       if (!_dbus_concat_dir_and_file (&full_path, &filename))
3163         _dbus_assert_not_reached ("couldn't concat file to dir");
3164
3165       if (_dbus_string_ends_with_c_str (&filename, ".message"))
3166         is_raw = FALSE;
3167       else if (_dbus_string_ends_with_c_str (&filename, ".message-raw"))
3168         is_raw = TRUE;
3169       else
3170         {
3171           const char *filename_c;
3172           _dbus_string_get_const_data (&filename, &filename_c);
3173           _dbus_verbose ("Skipping non-.message file %s\n",
3174                          filename_c);
3175           _dbus_string_free (&full_path);
3176           goto next;
3177         }
3178
3179       {
3180         const char *s;
3181         _dbus_string_get_const_data (&filename, &s);
3182         printf ("    %s\n", s);
3183       }
3184       
3185       _dbus_verbose (" expecting %s\n",
3186                      validity == _DBUS_MESSAGE_VALID ? "valid" :
3187                      (validity == _DBUS_MESSAGE_INVALID ? "invalid" :
3188                       (validity == _DBUS_MESSAGE_INCOMPLETE ? "incomplete" : "unknown")));
3189       
3190       if (! (*function) (&full_path, is_raw, validity, user_data))
3191         {
3192           _dbus_string_free (&full_path);
3193           goto failed;
3194         }
3195       else
3196         _dbus_string_free (&full_path);
3197     }
3198
3199   if (result != DBUS_RESULT_SUCCESS)
3200     {
3201       const char *s;
3202       _dbus_string_get_const_data (&test_directory, &s);
3203       _dbus_warn ("Could not get next file in %s: %s\n",
3204                   s, dbus_result_to_string (result));
3205       goto failed;
3206     }
3207     
3208   retval = TRUE;
3209   
3210  failed:
3211
3212   if (dir)
3213     _dbus_directory_close (dir);
3214   _dbus_string_free (&test_directory);
3215   _dbus_string_free (&filename);
3216
3217   return retval;
3218 }
3219                      
3220 /**
3221  * Runs the given function on every message file in the test suite.
3222  * The function should return #FALSE on test failure or fatal error.
3223  *
3224  * @param test_data_dir root dir of the test suite data files (top_srcdir/test/data)
3225  * @param func the function to run
3226  * @param user_data data for function
3227  * @returns #FALSE if there's a failure
3228  */
3229 dbus_bool_t
3230 dbus_internal_do_not_use_foreach_message_file (const char                *test_data_dir,
3231                                                DBusForeachMessageFileFunc func,
3232                                                void                      *user_data)
3233 {
3234   DBusString test_directory;
3235   dbus_bool_t retval;
3236
3237   retval = FALSE;
3238   
3239   _dbus_string_init_const (&test_directory, test_data_dir);
3240
3241   if (!process_test_subdir (&test_directory, "valid-messages",
3242                             _DBUS_MESSAGE_VALID, func, user_data))
3243     goto failed;
3244
3245   if (!process_test_subdir (&test_directory, "invalid-messages",
3246                             _DBUS_MESSAGE_INVALID, func, user_data))
3247     goto failed;
3248   
3249   if (!process_test_subdir (&test_directory, "incomplete-messages",
3250                             _DBUS_MESSAGE_INCOMPLETE, func, user_data))
3251     goto failed;
3252
3253   retval = TRUE;
3254   
3255  failed:
3256
3257   _dbus_string_free (&test_directory);
3258   
3259   return retval;
3260 }
3261
3262 /**
3263  * @ingroup DBusMessageInternals
3264  * Unit test for DBusMessage.
3265  *
3266  * @returns #TRUE on success.
3267  */
3268 dbus_bool_t
3269 _dbus_message_test (const char *test_data_dir)
3270 {
3271   DBusMessage *message;
3272   DBusMessageLoader *loader;
3273   int i;
3274   const char *data;
3275   dbus_int32_t our_int;
3276   char *our_str;
3277   double our_double;
3278   
3279   /* Test the vararg functions */
3280   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
3281   _dbus_message_set_client_serial (message, 1);
3282   dbus_message_append_args (message,
3283                             DBUS_TYPE_INT32, -0x12345678,
3284                             DBUS_TYPE_STRING, "Test string",
3285                             DBUS_TYPE_DOUBLE, 3.14159,
3286                             0);
3287   _dbus_verbose_bytes_of_string (&message->header, 0,
3288                                  _dbus_string_get_length (&message->header));
3289   _dbus_verbose_bytes_of_string (&message->body, 0,
3290                                  _dbus_string_get_length (&message->body));
3291   
3292   if (dbus_message_get_args (message,
3293                              DBUS_TYPE_INT32, &our_int,
3294                              DBUS_TYPE_STRING, &our_str,
3295                              DBUS_TYPE_DOUBLE, &our_double,
3296                              0) != DBUS_RESULT_SUCCESS)
3297     _dbus_assert_not_reached ("Could not get arguments");
3298
3299   if (our_int != -0x12345678)
3300     _dbus_assert_not_reached ("integers differ!");
3301
3302   if (our_double != 3.14159)
3303     _dbus_assert_not_reached ("doubles differ!");
3304
3305   if (strcmp (our_str, "Test string") != 0)
3306     _dbus_assert_not_reached ("strings differ!");
3307
3308   dbus_free (our_str);
3309   dbus_message_unref (message);
3310   
3311   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
3312   _dbus_message_set_client_serial (message, 1);
3313   _dbus_message_set_reply_serial (message, 0x12345678);
3314
3315   dbus_message_append_string (message, "Test string");
3316   dbus_message_append_int32 (message, -0x12345678);
3317   dbus_message_append_uint32 (message, 0xedd1e);
3318   dbus_message_append_double (message, 3.14159);
3319
3320   message_iter_test (message);
3321
3322   /* Message loader test */
3323   _dbus_message_lock (message);
3324   loader = _dbus_message_loader_new ();
3325
3326   /* Write the header data one byte at a time */
3327   _dbus_string_get_const_data (&message->header, &data);
3328   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
3329     {
3330       DBusString *buffer;
3331
3332       _dbus_message_loader_get_buffer (loader, &buffer);
3333       _dbus_string_append_byte (buffer, data[i]);
3334       _dbus_message_loader_return_buffer (loader, buffer, 1);
3335     }
3336
3337   /* Write the body data one byte at a time */
3338   _dbus_string_get_const_data (&message->body, &data);
3339   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
3340     {
3341       DBusString *buffer;
3342
3343       _dbus_message_loader_get_buffer (loader, &buffer);
3344       _dbus_string_append_byte (buffer, data[i]);
3345       _dbus_message_loader_return_buffer (loader, buffer, 1);
3346     }
3347
3348   dbus_message_unref (message);
3349
3350   /* Now pop back the message */
3351   if (_dbus_message_loader_get_is_corrupted (loader))
3352     _dbus_assert_not_reached ("message loader corrupted");
3353   
3354   message = _dbus_message_loader_pop_message (loader);
3355   if (!message)
3356     _dbus_assert_not_reached ("received a NULL message");
3357
3358   if (_dbus_message_get_reply_serial (message) != 0x12345678)
3359     _dbus_assert_not_reached ("reply serial fields differ");
3360   
3361   message_iter_test (message);
3362   
3363   dbus_message_unref (message);
3364   _dbus_message_loader_unref (loader);
3365
3366   /* Now load every message in test_data_dir if we have one */
3367   if (test_data_dir == NULL)
3368     return TRUE;
3369
3370   return dbus_internal_do_not_use_foreach_message_file (test_data_dir,
3371                                                         (DBusForeachMessageFileFunc)
3372                                                         dbus_internal_do_not_use_try_message_file,
3373                                                         NULL);
3374 }
3375
3376 #endif /* DBUS_BUILD_TESTS */