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