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