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