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