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