2003-01-21 Anders Carlsson <andersca@codefactory.se>
[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 <string.h>
32
33 /**
34  * @defgroup DBusMessageInternals DBusMessage implementation details
35  * @ingroup DBusInternals
36  * @brief DBusMessage private implementation details.
37  *
38  * The guts of DBusMessage and its methods.
39  *
40  * @{
41  */
42
43 /**
44  * @brief Internals of DBusMessage
45  * 
46  * Object representing a message received from or to be sent to
47  * another application. This is an opaque object, all members
48  * are private.
49  */
50 struct DBusMessage
51 {
52   int refcount; /**< Reference count */
53
54   DBusString header; /**< Header network data, stored
55                       * separately from body so we can
56                       * independently realloc it.
57                       */
58
59   DBusString body;   /**< Body network data. */
60
61   char byte_order; /**< Message byte order. */
62   
63   char *name; /**< Message name. */
64   char *service; /**< Message destination service. */
65   char *sender; /**< Message sender service. */
66   
67   dbus_int32_t client_serial; /**< Client serial or -1 if not set */
68   dbus_int32_t reply_serial; /**< Reply serial or -1 if not set */
69
70   DBusCounter *size_counter; /**< Counter for the size of the message, or #NULL */
71   long size_counter_delta;   /**< Size we incremented the size counter by. */
72   
73   unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
74 };
75
76 /**
77  * @brief Internals of DBusMessageIter
78  * 
79  * Object representing a position in a message. All fields are internal.
80  */
81 struct DBusMessageIter
82 {
83   int refcount; /**< Reference count */
84
85   int pos; /**< Current position in the string */
86   
87   DBusMessage *message; /**< Message used */
88 };
89
90 /**
91  * Gets the data to be sent over the network for this message.
92  * The header and then the body should be written out.
93  * This function is guaranteed to always return the same
94  * data once a message is locked (with _dbus_message_lock()).
95  *
96  * @param message the message.
97  * @param header return location for message header data.
98  * @param body return location for message body data.
99  */
100 void
101 _dbus_message_get_network_data (DBusMessage          *message,
102                                 const DBusString    **header,
103                                 const DBusString    **body)
104 {
105   _dbus_assert (message->locked);
106   
107   *header = &message->header;
108   *body = &message->body;
109 }
110
111 /**
112  * Sets the client serial of a message. 
113  * This can only be done once on a message.
114  *
115  * @param message the message
116  * @param client_serial the client serial
117  */
118 void
119 _dbus_message_set_client_serial (DBusMessage  *message,
120                                  dbus_int32_t  client_serial)
121 {
122   _dbus_assert (message->client_serial == -1);
123   
124   message->client_serial = client_serial;
125 }
126
127 /**
128  * Returns the serial that the message is
129  * a reply to.
130  *
131  * @param message the message
132  * @returns the reply serial
133  */
134 dbus_int32_t
135 _dbus_message_get_reply_serial  (DBusMessage *message)
136 {
137   return message->client_serial;
138 }
139
140 /**
141  * Sets the message sender. This can only
142  * be done once on a message.
143  *
144  * @param message the message
145  * @param sender the sender
146  */
147 void
148 _dbus_message_set_sender (DBusMessage  *message,
149                           const char   *sender)
150 {
151   _dbus_assert (message->sender == NULL);
152
153   message->sender = _dbus_strdup (sender);
154 }
155
156 /**
157  * Adds a counter to be incremented immediately with the
158  * size of this message, and decremented by the size
159  * of this message when this message if finalized.
160  *
161  * @param message the message
162  * @param counter the counter
163  */
164 void
165 _dbus_message_add_size_counter (DBusMessage *message,
166                                 DBusCounter *counter)
167 {
168   _dbus_assert (message->size_counter == NULL); /* If this fails we may need to keep a list of
169                                                  * counters instead of just one
170                                                  */
171
172   message->size_counter = counter;
173   _dbus_counter_ref (message->size_counter);
174
175   /* When we can change message size, we may want to
176    * update this each time we do so, or we may want to
177    * just KISS like this.
178    */
179   message->size_counter_delta =
180     _dbus_string_get_length (&message->header) +
181     _dbus_string_get_length (&message->body);
182
183   _dbus_verbose ("message has size %ld\n",
184                  message->size_counter_delta);
185   
186   _dbus_counter_adjust (message->size_counter, message->size_counter_delta);
187 }
188
189 static void
190 dbus_message_write_header (DBusMessage *message)
191 {
192   char *len_data;
193   
194   _dbus_assert (message->client_serial != -1);
195   
196   _dbus_string_append_byte (&message->header, DBUS_COMPILER_BYTE_ORDER);
197   _dbus_string_append_len (&message->header, "\0\0\0", 3);
198
199   /* We just lengthen the string here and pack in the real length later */
200   _dbus_string_lengthen (&message->header, 4);
201   
202   _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER,
203                        _dbus_string_get_length (&message->body));
204
205   /* Marshal client serial */
206   _dbus_assert (message->client_serial >= 0);
207   _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER,
208                        message->client_serial);
209
210   /* Marshal message service */
211   if (message->service)
212     {
213       _dbus_string_align_length (&message->header, 4);
214       _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_SERVICE, 4);
215       _dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
216       
217       _dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER,
218                             message->service);
219     }
220
221   /* Marshal message name */
222   _dbus_assert (message->name != NULL);
223   _dbus_string_align_length (&message->header, 4);
224   _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_NAME, 4);
225   _dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
226
227   _dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER, message->name);
228
229   /* Marshal reply serial */
230   if (message->reply_serial != -1)
231     {
232       _dbus_string_align_length (&message->header, 4);
233       _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_REPLY, 4);
234
235       _dbus_string_append_byte (&message->header, DBUS_TYPE_INT32);
236       _dbus_marshal_int32 (&message->header, DBUS_COMPILER_BYTE_ORDER,
237                            message->reply_serial);
238     }
239
240   /* Marshal sender */
241   if (message->sender)
242     {
243       _dbus_string_align_length (&message->header, 4);
244       _dbus_string_append_len (&message->header, DBUS_HEADER_FIELD_SENDER, 4);
245       _dbus_string_append_byte (&message->header, DBUS_TYPE_STRING);
246
247       _dbus_marshal_string (&message->header, DBUS_COMPILER_BYTE_ORDER,
248                             message->sender);
249     }
250   
251   /* Fill in the length */
252   _dbus_string_get_data_len (&message->header, &len_data, 4, 4);
253   _dbus_pack_int32 (_dbus_string_get_length (&message->header),
254                     DBUS_COMPILER_BYTE_ORDER, len_data);
255 }
256
257 /**
258  * Locks a message. Allows checking that applications don't keep a
259  * reference to a message in the outgoing queue and change it
260  * underneath us. Messages are locked when they enter the outgoing
261  * queue (dbus_connection_send_message()), and the library complains
262  * if the message is modified while locked.
263  *
264  * @param message the message to lock.
265  */
266 void
267 _dbus_message_lock (DBusMessage  *message)
268 {
269   if (!message->locked)
270     dbus_message_write_header (message);
271   
272   message->locked = TRUE;
273 }
274
275 /** @} */
276
277 /**
278  * @defgroup DBusMessage DBusMessage
279  * @ingroup  DBus
280  * @brief Message to be sent or received over a DBusConnection.
281  *
282  * A DBusMessage is the most basic unit of communication over a
283  * DBusConnection. A DBusConnection represents a stream of messages
284  * received from a remote application, and a stream of messages
285  * sent to a remote application.
286  *
287  * @{
288  */
289
290 /**
291  * @typedef DBusMessage
292  *
293  * Opaque data type representing a message received from or to be
294  * sent to another application.
295  */
296
297 /**
298  * Constructs a new message. Returns #NULL if memory
299  * can't be allocated for the message.
300  *
301  * @todo use DBusString internally to store service and name.
302  *
303  * @param service service that the message should be sent to
304  * @param name name of the message
305  * @returns a new DBusMessage, free with dbus_message_unref()
306  * @see dbus_message_unref()
307  */
308 DBusMessage*
309 dbus_message_new (const char *service,
310                   const char *name)
311 {
312   DBusMessage *message;
313
314   message = dbus_new0 (DBusMessage, 1);
315   if (message == NULL)
316     return NULL;
317   
318   message->refcount = 1;
319   message->byte_order = DBUS_COMPILER_BYTE_ORDER;
320
321   message->service = _dbus_strdup (service);
322   message->name = _dbus_strdup (name);
323   
324   message->client_serial = -1;
325   message->reply_serial = -1;
326   
327   if (!_dbus_string_init (&message->header, _DBUS_INT_MAX))
328     {
329       dbus_free (message->service);
330       dbus_free (message->name);
331       dbus_free (message);
332       return NULL;
333     }
334
335   if (!_dbus_string_init (&message->body, _DBUS_INT_MAX))
336     {
337       dbus_free (message->service);
338       dbus_free (message->name);
339       _dbus_string_free (&message->header);
340       dbus_free (message);
341       return NULL;
342     }
343   
344   return message;
345 }
346
347 /**
348  * Constructs a message that is a reply to some other
349  * message. Returns #NULL if memory can't be allocated
350  * for the message.
351  *
352  * @param name the name of the message
353  * @param original_message the message which the created
354  * message is a reply to.
355  * @returns a new DBusMessage, free with dbus_message_unref()
356  * @see dbus_message_new(), dbus_message_unref()
357  */ 
358 DBusMessage*
359 dbus_message_new_reply (const char  *name,
360                         DBusMessage *original_message)
361 {
362   DBusMessage *message;
363
364   _dbus_assert (original_message->sender != NULL);
365   
366   message = dbus_message_new (original_message->sender, name);
367   
368   if (message == NULL)
369     return NULL;
370
371   message->reply_serial = original_message->client_serial;
372
373   return message;
374 }
375
376
377 /**
378  * Increments the reference count of a DBusMessage.
379  *
380  * @param message The message
381  * @see dbus_message_unref
382  */
383 void
384 dbus_message_ref (DBusMessage *message)
385 {
386   _dbus_assert (message->refcount > 0);
387   
388   message->refcount += 1;
389 }
390
391 /**
392  * Decrements the reference count of a DBusMessage.
393  *
394  * @param message The message
395  * @see dbus_message_ref
396  */
397 void
398 dbus_message_unref (DBusMessage *message)
399 {
400   _dbus_assert (message->refcount > 0);
401
402   message->refcount -= 1;
403   if (message->refcount == 0)
404     {
405       if (message->size_counter != NULL)
406         {
407           _dbus_counter_adjust (message->size_counter,
408                                 - message->size_counter_delta);
409           _dbus_counter_unref (message->size_counter);
410         }
411       
412       _dbus_string_free (&message->header);
413       _dbus_string_free (&message->body);
414
415       dbus_free (message->service);
416       dbus_free (message->name);
417       dbus_free (message);
418     }
419 }
420
421 /**
422  * Gets the name of a message.
423  *
424  * @param message the message
425  * @returns the message name (should not be freed)
426  */
427 const char*
428 dbus_message_get_name (DBusMessage *message)
429 {
430   return message->name;
431 }
432
433 /**
434  * Gets the destination service of a message.
435  *
436  * @param message the message
437  * @returns the message destination service (should not be freed)
438  */
439 const char*
440 dbus_message_get_service (DBusMessage *message)
441 {
442   return message->service;
443 }
444
445 /**
446  * Appends fields to a message given a variable argument
447  * list. The variable argument list should contain the type
448  * of the field followed by the value to add.
449  * The list is terminated with 0.
450  *
451  * @param message the message
452  * @param first_field_type type of the first field
453  * @param ... value of first field, list of additional type-value pairs
454  * @returns #TRUE on success
455  */
456 dbus_bool_t
457 dbus_message_append_fields (DBusMessage *message,
458                             int first_field_type,
459                             ...)
460 {
461   dbus_bool_t retval;
462   va_list var_args;
463
464   va_start (var_args, first_field_type);
465   retval = dbus_message_append_fields_valist (message,
466                                               first_field_type,
467                                               var_args);
468   va_end (var_args);
469
470   return retval;
471 }
472
473 /**
474  * This function takes a va_list for use by language bindings
475  *
476  * @see dbus_message_append_fields.  
477  * @param message the message
478  * @param first_field_type type of first field
479  * @param var_args value of first field, then list of type/value pairs
480  * @returns #TRUE on success
481  */
482 dbus_bool_t
483 dbus_message_append_fields_valist (DBusMessage *message,
484                                    int          first_field_type,
485                                    va_list      var_args)
486 {
487   int type, old_len;
488
489   old_len = _dbus_string_get_length (&message->body);
490   
491   type = first_field_type;
492
493   while (type != 0)
494     {
495       switch (type)
496         {
497         case DBUS_TYPE_INT32:
498           if (!dbus_message_append_int32 (message, va_arg (var_args, dbus_int32_t)))
499             goto enomem;
500           break;
501         case DBUS_TYPE_UINT32:
502           if (!dbus_message_append_uint32 (message, va_arg (var_args, dbus_uint32_t)))
503             goto enomem;            
504           break;
505         case DBUS_TYPE_DOUBLE:
506           if (!dbus_message_append_double (message, va_arg (var_args, double)))
507             goto enomem;
508           break;
509         case DBUS_TYPE_STRING:
510           if (!dbus_message_append_string (message, va_arg (var_args, const char *)))
511             goto enomem;
512           break;
513         case DBUS_TYPE_BYTE_ARRAY:
514           {
515             int len;
516             unsigned char *data;
517
518             data = va_arg (var_args, unsigned char *);
519             len = va_arg (var_args, int);
520
521             if (!dbus_message_append_byte_array (message, data, len))
522               goto enomem;
523           }
524           break;
525         default:
526           _dbus_warn ("Unknown field type %d\n", type);
527         }
528
529       type = va_arg (var_args, int);
530     }
531
532   return TRUE;
533
534  enomem:
535   _dbus_string_set_length (&message->body, old_len);
536   return FALSE;
537 }
538
539 /**
540  * Appends a 32 bit signed integer to the message.
541  *
542  * @param message the message
543  * @param value the integer value
544  * @returns #TRUE on success
545  */
546 dbus_bool_t
547 dbus_message_append_int32 (DBusMessage  *message,
548                            dbus_int32_t  value)
549 {
550   _dbus_assert (!message->locked);
551
552   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_INT32))
553     {
554       _dbus_string_shorten (&message->body, 1);
555       return FALSE;
556     }
557   
558   return _dbus_marshal_int32 (&message->body,
559                               DBUS_COMPILER_BYTE_ORDER, value);
560 }
561
562 /**
563  * Appends a 32 bit unsigned integer to the message.
564  *
565  * @param message the message
566  * @param value the integer value
567  * @returns #TRUE on success
568  */
569 dbus_bool_t
570 dbus_message_append_uint32 (DBusMessage   *message,
571                             dbus_uint32_t  value)
572 {
573   _dbus_assert (!message->locked);
574
575   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_UINT32))
576     {
577       _dbus_string_shorten (&message->body, 1);
578       return FALSE;
579     }
580   
581   return _dbus_marshal_uint32 (&message->body,
582                                DBUS_COMPILER_BYTE_ORDER, value);
583 }
584
585 /**
586  * Appends a double value to the message.
587  *
588  * @param message the message
589  * @param value the double value
590  * @returns #TRUE on success
591  */
592 dbus_bool_t
593 dbus_message_append_double (DBusMessage *message,
594                             double       value)
595 {
596   _dbus_assert (!message->locked);
597
598   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_DOUBLE))
599     {
600       _dbus_string_shorten (&message->body, 1);
601       return FALSE;
602     }
603   
604   return _dbus_marshal_double (&message->body,
605                                DBUS_COMPILER_BYTE_ORDER, value);
606 }
607
608 /**
609  * Appends a UTF-8 string to the message.
610  *
611  * @param message the message
612  * @param value the string
613  * @returns #TRUE on success
614  */
615 dbus_bool_t
616 dbus_message_append_string (DBusMessage *message,
617                             const char  *value)
618 {
619   _dbus_assert (!message->locked);
620
621   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_STRING))
622     {
623       _dbus_string_shorten (&message->body, 1);
624       return FALSE;
625     }
626   
627   return _dbus_marshal_string (&message->body,
628                                DBUS_COMPILER_BYTE_ORDER, value);
629 }
630
631 /**
632  * Appends a byte array to the message.
633  *
634  * @param message the message
635  * @param value the array
636  * @param len the length of the array
637  * @returns #TRUE on success
638  */
639 dbus_bool_t
640 dbus_message_append_byte_array (DBusMessage         *message,
641                                 unsigned const char *value,
642                                 int                 len)
643 {
644   _dbus_assert (!message->locked);
645
646   if (!_dbus_string_append_byte (&message->body, DBUS_TYPE_BYTE_ARRAY))
647     {
648       _dbus_string_shorten (&message->body, 1);
649       return FALSE;
650     }
651   
652   return _dbus_marshal_byte_array (&message->body,
653                                    DBUS_COMPILER_BYTE_ORDER, value, len);
654 }
655
656 /**
657  * Gets fields from a message given a variable argument list.
658  * The variable argument list should contain the type of the
659  * field followed by a pointer to where the value should be
660  * stored. The list is terminated with 0.
661  *
662  * @param message the message
663  * @param first_field_type the first field type
664  * @param ... location for first field value, then list of type-location pairs
665  * @returns result code
666  */
667 DBusResultCode
668 dbus_message_get_fields (DBusMessage *message,
669                          int          first_field_type,
670                          ...)
671 {
672   DBusResultCode retval;
673   va_list var_args;
674
675   va_start (var_args, first_field_type);
676   retval = dbus_message_get_fields_valist (message, first_field_type, var_args);
677   va_end (var_args);
678
679   return retval;
680 }
681
682 /**
683  * This function takes a va_list for use by language bindings
684  *
685  * @todo this function (or some lower-level non-convenience function)
686  * needs better error handling; should allow the application to
687  * distinguish between out of memory, and bad data from the remote
688  * app. It also needs to not leak a bunch of args when it gets
689  * to the arg that's bad, as that would be a security hole
690  * (allow one app to force another to leak memory)
691  *
692  * @todo We need to free the field data when an error occurs.
693  *
694  * @see dbus_message_get_fields
695  * @param message the message
696  * @param first_field_type type of the first field
697  * @param var_args return location for first field, followed by list of type/location pairs
698  * @returns result code
699  */
700 DBusResultCode
701 dbus_message_get_fields_valist (DBusMessage *message,
702                                 int          first_field_type,
703                                 va_list      var_args)
704 {
705   int spec_type, msg_type, i;
706   DBusMessageIter *iter;
707
708   iter = dbus_message_get_fields_iter (message);
709
710   if (iter == NULL)
711     return FALSE;
712   
713   spec_type = first_field_type;
714   i = 0;
715   
716   while (spec_type != 0)
717     {
718       msg_type = dbus_message_iter_get_field_type (iter);      
719       
720       if (msg_type != spec_type)
721         {
722           _dbus_verbose ("Field %d is specified to be of type \"%s\", but "
723                          "is actually of type \"%s\"\n", i,
724                          _dbus_type_to_string (spec_type),
725                          _dbus_type_to_string (msg_type));
726           dbus_message_iter_unref (iter);
727
728           return DBUS_RESULT_INVALID_FIELDS;
729         }
730
731       switch (spec_type)
732         {
733         case DBUS_TYPE_INT32:
734           {
735             dbus_int32_t *ptr;
736
737             ptr = va_arg (var_args, dbus_int32_t *);
738
739             *ptr = dbus_message_iter_get_int32 (iter);
740             break;
741           }
742         case DBUS_TYPE_UINT32:
743           {
744             dbus_uint32_t *ptr;
745
746             ptr = va_arg (var_args, dbus_uint32_t *);
747
748             *ptr = dbus_message_iter_get_uint32 (iter);
749             break;
750           }
751
752         case DBUS_TYPE_DOUBLE:
753           {
754             double *ptr;
755
756             ptr = va_arg (var_args, double *);
757
758             *ptr = dbus_message_iter_get_double (iter);
759             break;
760           }
761
762         case DBUS_TYPE_STRING:
763           {
764             char **ptr;
765
766             ptr = va_arg (var_args, char **);
767
768             *ptr = dbus_message_iter_get_string (iter);
769
770             if (!*ptr)
771               return DBUS_RESULT_NO_MEMORY;
772             
773             break;
774           }
775
776         case DBUS_TYPE_BYTE_ARRAY:
777           {
778             char **ptr;
779             int *len;
780
781             ptr = va_arg (var_args, char **);
782             len = va_arg (var_args, int *);
783
784             *ptr = dbus_message_iter_get_byte_array (iter, len);
785
786             if (!*ptr)
787               return DBUS_RESULT_NO_MEMORY;
788             
789             break;
790           }
791         default:          
792           _dbus_warn ("Unknown field type %d\n", spec_type);
793         }
794       
795       spec_type = va_arg (var_args, int);
796       if (spec_type != 0 && !dbus_message_iter_next (iter))
797         {
798           _dbus_verbose ("More fields than exist in the message were specified\n");
799
800           dbus_message_iter_unref (iter);  
801           return DBUS_RESULT_INVALID_FIELDS;
802         }
803       i++;
804     }
805
806   dbus_message_iter_unref (iter);
807   return DBUS_RESULT_SUCCESS;
808 }
809
810 /**
811  * Returns a DBusMessageIter representing the fields of the
812  * message passed in.
813  *
814  * @todo IMO the message iter should follow the GtkTextIter pattern,
815  * a static object with a "stamp" value used to detect invalid
816  * iter uses (uninitialized or after changing the message).
817  * ref/unref is kind of annoying to deal with, and slower too.
818  * This implies not ref'ing the message from the iter.
819  *
820  * @param message the message
821  * @returns a new iter.
822  */
823 DBusMessageIter *
824 dbus_message_get_fields_iter (DBusMessage *message)
825 {
826   DBusMessageIter *iter;
827   
828   iter = dbus_new (DBusMessageIter, 1);
829
830   dbus_message_ref (message);
831   
832   iter->refcount = 1;
833   iter->message = message;
834   iter->pos = 0;
835
836   return iter;
837 }
838
839 /**
840  * Increments the reference count of a DBusMessageIter.
841  *
842  * @param iter the message iter
843  * @see dbus_message_iter_unref
844  */
845 void
846 dbus_message_iter_ref (DBusMessageIter *iter)
847 {
848   _dbus_assert (iter->refcount > 0);
849   
850   iter->refcount += 1;
851 }
852
853 /**
854  * Decrements the reference count of a DBusMessageIter.
855  *
856  * @param iter The message iter
857  * @see dbus_message_iter_ref
858  */
859 void
860 dbus_message_iter_unref (DBusMessageIter *iter)
861 {
862   _dbus_assert (iter->refcount > 0);
863
864   iter->refcount -= 1;
865
866   if (iter->refcount == 0)
867     {
868       dbus_message_unref (iter->message);
869
870       dbus_free (iter);
871     }
872 }
873
874 /**
875  * Checks if an iterator has any more fields.
876  *
877  * @param iter the message iter
878  * @returns #TRUE if there are more fields
879  * following
880  */
881 dbus_bool_t
882 dbus_message_iter_has_next (DBusMessageIter *iter)
883 {
884   int end_pos;
885   
886   if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
887                                         iter->pos, &end_pos))
888     return FALSE;
889   
890   if (end_pos >= _dbus_string_get_length (&iter->message->body))
891     return FALSE;
892   
893   return TRUE;  
894 }
895
896 /**
897  * Moves the iterator to the next field.
898  *
899  * @param iter The message iter
900  * @returns #TRUE if the iterator was moved to the next field
901  */
902 dbus_bool_t
903 dbus_message_iter_next (DBusMessageIter *iter)
904 {
905   int end_pos;
906   
907   if (!_dbus_marshal_get_field_end_pos (&iter->message->body, iter->message->byte_order,
908                                         iter->pos, &end_pos))
909     return FALSE;
910
911   if (end_pos >= _dbus_string_get_length (&iter->message->body))
912     return FALSE;
913
914   iter->pos = end_pos;
915
916   return TRUE;
917 }
918
919 /**
920  * Returns the field type of the field that the
921  * message iterator points at.
922  *
923  * @param iter the message iter
924  * @returns the field type
925  */
926 int
927 dbus_message_iter_get_field_type (DBusMessageIter *iter)
928 {
929   const char *data;
930
931   if (iter->pos >= _dbus_string_get_length (&iter->message->body))
932     return DBUS_TYPE_INVALID;
933
934   _dbus_string_get_const_data_len (&iter->message->body, &data, iter->pos, 1);
935
936   if (*data > DBUS_TYPE_INVALID && *data <= DBUS_TYPE_STRING)
937     return *data;
938
939   return DBUS_TYPE_INVALID;
940 }
941
942 /**
943  * Returns the string value that an iterator may point to.
944  * Note that you need to check that the iterator points to
945  * a string value before using this function.
946  *
947  * @see dbus_message_iter_get_field_type
948  * @param iter the message iter
949  * @returns the string
950  */
951 char *
952 dbus_message_iter_get_string (DBusMessageIter *iter)
953 {
954   _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_STRING);
955
956   return _dbus_demarshal_string (&iter->message->body, iter->message->byte_order,
957                                  iter->pos + 1, NULL);
958 }
959
960 /**
961  * Returns the 32 bit signed integer value that an iterator may point to.
962  * Note that you need to check that the iterator points to
963  * a string value before using this function.
964  *
965  * @see dbus_message_iter_get_field_type
966  * @param iter the message iter
967  * @returns the integer
968  */
969 int
970 dbus_message_iter_get_int32 (DBusMessageIter *iter)
971 {
972   return _dbus_demarshal_int32 (&iter->message->body, iter->message->byte_order,
973                                 iter->pos + 1, NULL);
974 }
975
976 /**
977  * Returns the 32 bit unsigned integer value that an iterator may point to.
978  * Note that you need to check that the iterator points to
979  * a string value before using this function.
980  *
981  * @see dbus_message_iter_get_field_type
982  * @param iter the message iter
983  * @returns the integer
984  */
985 int
986 dbus_message_iter_get_uint32 (DBusMessageIter *iter)
987 {
988   return _dbus_demarshal_uint32 (&iter->message->body, iter->message->byte_order,
989                                  iter->pos + 1, NULL);
990 }
991
992 /**
993  * Returns the double value that an iterator may point to.
994  * Note that you need to check that the iterator points to
995  * a string value before using this function.
996  *
997  * @see dbus_message_iter_get_field_type
998  * @param iter the message iter
999  * @returns the double
1000  */
1001 double
1002 dbus_message_iter_get_double (DBusMessageIter *iter)
1003 {
1004   return _dbus_demarshal_double (&iter->message->body, iter->message->byte_order,
1005                                  iter->pos + 1, NULL);
1006 }
1007
1008 /**
1009  * Returns the byte array that the iterator may point to.
1010  * Note that you need to check that the iterator points
1011  * to a byte array prior to using this function.
1012  *
1013  * @todo this function should probably take "unsigned char **" as
1014  * an out param argument, and return boolean or result code.
1015  *
1016  * @param iter the iterator
1017  * @param len return location for length of byte array
1018  * @returns the byte array
1019  */
1020 unsigned char *
1021 dbus_message_iter_get_byte_array (DBusMessageIter *iter,
1022                                   int             *len)
1023 {
1024   _dbus_assert (dbus_message_iter_get_field_type (iter) == DBUS_TYPE_BYTE_ARRAY);
1025
1026   return _dbus_demarshal_byte_array (&iter->message->body, iter->message->byte_order,
1027                                      iter->pos + 1, NULL, len);
1028 }
1029
1030 /** @} */
1031
1032 /**
1033  * @addtogroup DBusMessageInternals
1034  *
1035  * @{
1036  */
1037 /**
1038  * @typedef DBusMessageLoader
1039  *
1040  * The DBusMessageLoader object encapsulates the process of converting
1041  * a byte stream into a series of DBusMessage. It buffers the incoming
1042  * bytes as efficiently as possible, and generates a queue of
1043  * messages. DBusMessageLoader is typically used as part of a
1044  * DBusTransport implementation. The DBusTransport then hands off
1045  * the loaded messages to a DBusConnection, making the messages
1046  * visible to the application.
1047  * 
1048  */
1049
1050 /**
1051  * Implementation details of DBusMessageLoader.
1052  * All members are private.
1053  */
1054 struct DBusMessageLoader
1055 {
1056   int refcount;        /**< Reference count. */
1057
1058   DBusString data;     /**< Buffered data */
1059   
1060   DBusList *messages;  /**< Complete messages. */
1061
1062   long max_message_size; /**< Maximum size of a message */
1063   
1064   unsigned int buffer_outstanding : 1; /**< Someone is using the buffer to read */
1065
1066   unsigned int corrupted : 1; /**< We got broken data, and are no longer working */
1067 };
1068
1069 /**
1070  * The initial buffer size of the message loader.
1071  * 
1072  * @todo this should be based on min header size plus some average
1073  * body size, or something. Or rather, the min header size only, if we
1074  * want to try to read only the header, store that in a DBusMessage,
1075  * then read only the body and store that, etc., depends on
1076  * how we optimize _dbus_message_loader_get_buffer() and what
1077  * the exact message format is.
1078  */
1079 #define INITIAL_LOADER_DATA_LEN 32
1080
1081 /**
1082  * Creates a new message loader. Returns #NULL if memory can't
1083  * be allocated.
1084  *
1085  * @returns new loader, or #NULL.
1086  */
1087 DBusMessageLoader*
1088 _dbus_message_loader_new (void)
1089 {
1090   DBusMessageLoader *loader;
1091
1092   loader = dbus_new0 (DBusMessageLoader, 1);
1093   if (loader == NULL)
1094     return NULL;
1095   
1096   loader->refcount = 1;
1097
1098   /* Try to cap message size at something that won't *totally* hose
1099    * the system if we have a couple of them.
1100    */
1101   loader->max_message_size = _DBUS_ONE_MEGABYTE * 32;
1102   
1103   if (!_dbus_string_init (&loader->data, _DBUS_INT_MAX))
1104     {
1105       dbus_free (loader);
1106       return NULL;
1107     }
1108
1109   /* preallocate the buffer for speed, ignore failure */
1110   _dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
1111   _dbus_string_set_length (&loader->data, 0);
1112   
1113   return loader;
1114 }
1115
1116 /**
1117  * Increments the reference count of the loader.
1118  *
1119  * @param loader the loader.
1120  */
1121 void
1122 _dbus_message_loader_ref (DBusMessageLoader *loader)
1123 {
1124   loader->refcount += 1;
1125 }
1126
1127 /**
1128  * Decrements the reference count of the loader and finalizes the
1129  * loader when the count reaches zero.
1130  *
1131  * @param loader the loader.
1132  */
1133 void
1134 _dbus_message_loader_unref (DBusMessageLoader *loader)
1135 {
1136   loader->refcount -= 1;
1137   if (loader->refcount == 0)
1138     {
1139       _dbus_list_foreach (&loader->messages,
1140                           (DBusForeachFunction) dbus_message_unref,
1141                           NULL);
1142       _dbus_list_clear (&loader->messages);
1143       _dbus_string_free (&loader->data);
1144       dbus_free (loader);
1145     }
1146 }
1147
1148 /**
1149  * Gets the buffer to use for reading data from the network.  Network
1150  * data is read directly into an allocated buffer, which is then used
1151  * in the DBusMessage, to avoid as many extra memcpy's as possible.
1152  * The buffer must always be returned immediately using
1153  * _dbus_message_loader_return_buffer(), even if no bytes are
1154  * successfully read.
1155  *
1156  * @todo this function can be a lot more clever. For example
1157  * it can probably always return a buffer size to read exactly
1158  * the body of the next message, thus avoiding any memory wastage
1159  * or reallocs.
1160  * 
1161  * @param loader the message loader.
1162  * @param buffer the buffer
1163  */
1164 void
1165 _dbus_message_loader_get_buffer (DBusMessageLoader  *loader,
1166                                  DBusString        **buffer)
1167 {
1168   _dbus_assert (!loader->buffer_outstanding);
1169
1170   *buffer = &loader->data;
1171   
1172   loader->buffer_outstanding = TRUE;
1173 }
1174
1175 /**
1176  * The smallest header size that can occur. 
1177  * (It won't be valid)
1178  */
1179 #define DBUS_MINIMUM_HEADER_SIZE 16
1180
1181 /** Pack four characters as in "abcd" into a uint32 */
1182 #define FOUR_CHARS_TO_UINT32(a, b, c, d)                \
1183                       ((((dbus_uint32_t)a) << 24) |     \
1184                        (((dbus_uint32_t)b) << 16) |     \
1185                        (((dbus_uint32_t)c) << 8)  |     \
1186                        ((dbus_uint32_t)d))
1187
1188 /** DBUS_HEADER_FIELD_NAME packed into a dbus_uint32_t */
1189 #define DBUS_HEADER_FIELD_NAME_AS_UINT32    \
1190   FOUR_CHARS_TO_UINT32 ('n', 'a', 'm', 'e')
1191
1192 /** DBUS_HEADER_FIELD_SERVICE packed into a dbus_uint32_t */
1193 #define DBUS_HEADER_FIELD_SERVICE_AS_UINT32 \
1194   FOUR_CHARS_TO_UINT32 ('s', 'r', 'v', 'c')
1195
1196 /** DBUS_HEADER_FIELD_REPLY packed into a dbus_uint32_t */
1197 #define DBUS_HEADER_FIELD_REPLY_AS_UINT32   \
1198   FOUR_CHARS_TO_UINT32 ('r', 'p', 'l', 'y')
1199
1200 /** DBUS_HEADER_FIELD_SENDER Packed into a dbus_uint32_t */
1201 #define DBUS_HEADER_FIELD_SENDER_AS_UINT32  \
1202   FOUR_CHARS_TO_UINT32 ('s', 'n', 'd', 'r')
1203
1204
1205 /* FIXME should be using DBusString for the stuff we demarshal.  char*
1206  * evil. Also, out of memory handling here seems suboptimal.
1207  * Should probably report it as a distinct error from "corrupt message,"
1208  * so we can postpone parsing this message. Also, we aren't
1209  * checking for demarshal failure everywhere.
1210  */
1211 static dbus_bool_t
1212 decode_header_data (DBusString   *data,
1213                     int           header_len,
1214                     int           byte_order,
1215                     dbus_int32_t *client_serial,
1216                     dbus_int32_t *reply_serial,
1217                     char        **service,
1218                     char        **name,
1219                     char        **sender)
1220 {
1221   const char *field;
1222   int pos, new_pos;
1223   
1224   /* First demarshal the client serial */
1225   *client_serial = _dbus_demarshal_int32 (data, byte_order, 12, &pos);
1226
1227   *service = NULL;
1228   *name = NULL;
1229   *sender = NULL;
1230   
1231   /* Now handle the fields */
1232   while (pos < header_len)
1233     {
1234       pos = _DBUS_ALIGN_VALUE (pos, 4);
1235       
1236       if ((pos + 4) > header_len)
1237         return FALSE;      
1238       
1239       _dbus_string_get_const_data_len (data, &field, pos, 4);
1240       pos += 4;
1241
1242       _dbus_assert (_DBUS_ALIGN_ADDRESS (field, 4) == field);
1243
1244       /* I believe FROM_BE is right, but if not we'll find out
1245        * I guess. ;-)
1246        */
1247       switch (DBUS_UINT32_FROM_BE (*(int*)field))
1248         {
1249         case DBUS_HEADER_FIELD_SERVICE_AS_UINT32:
1250           if (*service != NULL)
1251             {
1252               _dbus_verbose ("%s field provided twice\n",
1253                              DBUS_HEADER_FIELD_SERVICE);
1254               goto failed;
1255             }
1256           
1257           *service = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
1258           /* FIXME check for demarshal failure SECURITY */
1259           break;
1260         case DBUS_HEADER_FIELD_NAME_AS_UINT32:
1261           if (*name != NULL)
1262             {
1263               _dbus_verbose ("%s field provided twice\n",
1264                              DBUS_HEADER_FIELD_NAME);
1265               goto failed;
1266             }
1267           
1268           *name = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
1269           /* FIXME check for demarshal failure SECURITY */
1270           break;
1271         case DBUS_HEADER_FIELD_SENDER_AS_UINT32:
1272           if (*sender != NULL)
1273             {
1274               _dbus_verbose ("%s field provided twice\n",
1275                              DBUS_HEADER_FIELD_NAME);
1276               goto failed;
1277             }
1278
1279           *sender = _dbus_demarshal_string (data, byte_order, pos + 1, &new_pos);
1280           /* FIXME check for demarshal failure SECURITY */
1281           break;
1282         case DBUS_HEADER_FIELD_REPLY_AS_UINT32:
1283           *reply_serial = _dbus_demarshal_int32 (data, byte_order, pos + 1, &new_pos);
1284
1285           break;
1286         default:
1287           _dbus_verbose ("Ignoring an unknown header field: %c%c%c%c\n",
1288                          field[0], field[1], field[2], field[3]);
1289           
1290           if (!_dbus_marshal_get_field_end_pos (data, byte_order, pos, &new_pos))
1291             goto failed;
1292         }
1293
1294       if (new_pos > header_len)
1295         return FALSE;
1296       
1297       pos = new_pos;
1298     }
1299   
1300   return TRUE;
1301
1302  failed:
1303   dbus_free (*service);
1304   dbus_free (*name);
1305   return FALSE;
1306 }
1307
1308 /**
1309  * Returns a buffer obtained from _dbus_message_loader_get_buffer(),
1310  * indicating to the loader how many bytes of the buffer were filled
1311  * in. This function must always be called, even if no bytes were
1312  * successfully read.
1313  *
1314  * @param loader the loader.
1315  * @param buffer the buffer.
1316  * @param bytes_read number of bytes that were read into the buffer.
1317  */
1318 void
1319 _dbus_message_loader_return_buffer (DBusMessageLoader  *loader,
1320                                     DBusString         *buffer,
1321                                     int                 bytes_read)
1322 {
1323   _dbus_assert (loader->buffer_outstanding);
1324   _dbus_assert (buffer == &loader->data);
1325
1326   loader->buffer_outstanding = FALSE;
1327
1328   if (loader->corrupted)
1329     return;
1330
1331   while (_dbus_string_get_length (&loader->data) >= 16)
1332     {
1333       DBusMessage *message;      
1334       const char *header_data;
1335       int byte_order, header_len, body_len;
1336       
1337       _dbus_string_get_const_data_len (&loader->data, &header_data, 0, 16);
1338
1339       _dbus_assert (_DBUS_ALIGN_ADDRESS (header_data, 4) == header_data);
1340       
1341       byte_order = header_data[0];
1342
1343       if (byte_order != DBUS_LITTLE_ENDIAN &&
1344           byte_order != DBUS_BIG_ENDIAN)
1345         {
1346           _dbus_verbose ("Message with bad byte order '%c' received\n",
1347                          byte_order);
1348           loader->corrupted = TRUE;
1349           return;
1350         }
1351
1352       header_len = _dbus_unpack_int32 (byte_order, header_data + 4);
1353       body_len = _dbus_unpack_int32 (byte_order, header_data + 8);
1354
1355       if (header_len + body_len > loader->max_message_size)
1356         {
1357           _dbus_verbose ("Message claimed length header = %d body = %d exceeds max message length %d\n",
1358                          header_len, body_len, loader->max_message_size);
1359           loader->corrupted = TRUE;
1360           return;
1361         }
1362
1363       if (_dbus_string_get_length (&loader->data) >= header_len + body_len)
1364         {
1365           dbus_int32_t client_serial, reply_serial;
1366           char *service, *name, *sender;
1367
1368           /* FIXME right now if this doesn't have enough memory, the
1369            * loader becomes corrupted. Instead we should just not
1370            * parse this message for now.
1371            */
1372           if (!decode_header_data (&loader->data, header_len, byte_order,
1373                                    &client_serial, &reply_serial, &service, &name, &sender))
1374             {
1375               loader->corrupted = TRUE;
1376               return;
1377             }
1378
1379
1380           message = dbus_message_new (service, name);
1381           message->reply_serial = reply_serial;
1382           message->client_serial = client_serial;
1383           _dbus_message_set_sender (message, sender);
1384           
1385           dbus_free (service);
1386           dbus_free (name);
1387           dbus_free (sender);
1388           
1389           if (message == NULL)
1390             break; /* ugh, postpone this I guess. */
1391                   
1392           if (!_dbus_list_append (&loader->messages, message))
1393             {
1394               dbus_message_unref (message);
1395               break;
1396             }
1397
1398           _dbus_assert (_dbus_string_get_length (&message->header) == 0);
1399           _dbus_assert (_dbus_string_get_length (&message->body) == 0);
1400
1401           if (!_dbus_string_move_len (&loader->data, 0, header_len, &message->header, 0))
1402             {
1403               _dbus_list_remove_last (&loader->messages, message);
1404               dbus_message_unref (message);
1405               break;
1406             }
1407
1408           if (!_dbus_string_move_len (&loader->data, 0, body_len, &message->body, 0))
1409             {
1410               dbus_bool_t result;
1411
1412               /* put the header back, we'll try again later */
1413               result = _dbus_string_copy_len (&message->header, 0, header_len,
1414                                               &loader->data, 0);
1415               _dbus_assert (result); /* because DBusString never reallocs smaller */
1416
1417               _dbus_list_remove_last (&loader->messages, message);
1418               dbus_message_unref (message);
1419               break;
1420             }
1421
1422           _dbus_assert (_dbus_string_get_length (&message->header) == header_len);
1423           _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
1424           
1425           _dbus_verbose ("Loaded message %p\n", message);         
1426         }
1427       else
1428         break;
1429     }
1430 }
1431
1432 /**
1433  * Pops a loaded message (passing ownership of the message
1434  * to the caller). Returns #NULL if no messages have been
1435  * loaded.
1436  *
1437  * @param loader the loader.
1438  * @returns the next message, or #NULL if none.
1439  */
1440 DBusMessage*
1441 _dbus_message_loader_pop_message (DBusMessageLoader *loader)
1442 {
1443   return _dbus_list_pop_first (&loader->messages);
1444 }
1445
1446
1447 /**
1448  * Checks whether the loader is confused due to bad data.
1449  * If messages are received that are invalid, the
1450  * loader gets confused and gives up permanently.
1451  * This state is called "corrupted."
1452  *
1453  * @param loader the loader
1454  * @returns #TRUE if the loader is hosed.
1455  */
1456 dbus_bool_t
1457 _dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
1458 {
1459   return loader->corrupted;
1460 }
1461
1462 /**
1463  * Sets the maximum size message we allow.
1464  *
1465  * @param loader the loader
1466  * @param size the max message size in bytes
1467  */
1468 void
1469 _dbus_message_loader_set_max_message_size (DBusMessageLoader  *loader,
1470                                            long                size)
1471 {
1472   loader->max_message_size = size;
1473 }
1474
1475 /**
1476  * Gets the maximum allowed message size in bytes.
1477  *
1478  * @param loader the loader
1479  * @returns max size in bytes
1480  */
1481 long
1482 _dbus_message_loader_get_max_message_size (DBusMessageLoader  *loader)
1483 {
1484   return loader->max_message_size;
1485 }
1486
1487 /** @} */
1488 #ifdef DBUS_BUILD_TESTS
1489 #include "dbus-test.h"
1490 #include <stdio.h>
1491
1492 static void
1493 message_iter_test (DBusMessage *message)
1494 {
1495   DBusMessageIter *iter;
1496   char *str;
1497   
1498   iter = dbus_message_get_fields_iter (message);
1499
1500   /* String tests */
1501   if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_STRING)
1502     _dbus_assert_not_reached ("Field type isn't string");
1503
1504   str = dbus_message_iter_get_string (iter);
1505   if (strcmp (str, "Test string") != 0)
1506     _dbus_assert_not_reached ("Strings differ");
1507   dbus_free (str);
1508
1509   if (!dbus_message_iter_next (iter))
1510     _dbus_assert_not_reached ("Reached end of fields");
1511
1512   /* Signed integer tests */
1513   if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_INT32)
1514     _dbus_assert_not_reached ("Field type isn't int32");
1515
1516   if (dbus_message_iter_get_int32 (iter) != -0x12345678)
1517     _dbus_assert_not_reached ("Signed integers differ");
1518
1519   if (!dbus_message_iter_next (iter))
1520     _dbus_assert_not_reached ("Reached end of fields");
1521   
1522   /* Unsigned integer tests */
1523   if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_UINT32)
1524     _dbus_assert_not_reached ("Field type isn't int32");
1525
1526   if (dbus_message_iter_get_int32 (iter) != 0xedd1e)
1527     _dbus_assert_not_reached ("Unsigned integers differ");
1528
1529   if (!dbus_message_iter_next (iter))
1530     _dbus_assert_not_reached ("Reached end of fields");
1531
1532   /* Double tests */
1533   if (dbus_message_iter_get_field_type (iter) != DBUS_TYPE_DOUBLE)
1534     _dbus_assert_not_reached ("Field type isn't double");
1535
1536   if (dbus_message_iter_get_double (iter) != 3.14159)
1537     _dbus_assert_not_reached ("Doubles differ");
1538
1539   if (dbus_message_iter_next (iter))
1540     _dbus_assert_not_reached ("Didn't reach end of fields");
1541   
1542   dbus_message_iter_unref (iter);
1543 }
1544
1545 /**
1546  * @ingroup DBusMessageInternals
1547  * Unit test for DBusMessage.
1548  *
1549  * @returns #TRUE on success.
1550  */
1551 dbus_bool_t
1552 _dbus_message_test (void)
1553 {
1554   DBusMessage *message;
1555   DBusMessageLoader *loader;
1556   int i;
1557   const char *data;
1558   dbus_int32_t our_int;
1559   char *our_str;
1560   double our_double;
1561   
1562   /* Test the vararg functions */
1563   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
1564   message->client_serial = 1;
1565   dbus_message_append_fields (message,
1566                               DBUS_TYPE_INT32, -0x12345678,
1567                               DBUS_TYPE_STRING, "Test string",
1568                               DBUS_TYPE_DOUBLE, 3.14159,
1569                               0);
1570
1571   if (dbus_message_get_fields (message,
1572                                DBUS_TYPE_INT32, &our_int,
1573                                DBUS_TYPE_STRING, &our_str,
1574                                DBUS_TYPE_DOUBLE, &our_double,
1575                                0) != DBUS_RESULT_SUCCESS)
1576     _dbus_assert_not_reached ("Could not get fields");
1577
1578   if (our_int != -0x12345678)
1579     _dbus_assert_not_reached ("integers differ!");
1580
1581   if (our_double != 3.14159)
1582     _dbus_assert_not_reached ("doubles differ!");
1583
1584   if (strcmp (our_str, "Test string") != 0)
1585     _dbus_assert_not_reached ("strings differ!");
1586   
1587   message = dbus_message_new ("org.freedesktop.DBus.Test", "testMessage");
1588   message->client_serial = 1;
1589   message->reply_serial = 0x12345678;
1590
1591   dbus_message_append_string (message, "Test string");
1592   dbus_message_append_int32 (message, -0x12345678);
1593   dbus_message_append_uint32 (message, 0xedd1e);
1594   dbus_message_append_double (message, 3.14159);
1595
1596   message_iter_test (message);
1597
1598   /* Message loader test */
1599   _dbus_message_lock (message);
1600   loader = _dbus_message_loader_new ();
1601
1602   /* Write the header data one byte at a time */
1603   _dbus_string_get_const_data (&message->header, &data);
1604   for (i = 0; i < _dbus_string_get_length (&message->header); i++)
1605     {
1606       DBusString *buffer;
1607
1608       _dbus_message_loader_get_buffer (loader, &buffer);
1609       _dbus_string_append_byte (buffer, data[i]);
1610       _dbus_message_loader_return_buffer (loader, buffer, 1);
1611     }
1612
1613   /* Write the body data one byte at a time */
1614   _dbus_string_get_const_data (&message->body, &data);
1615   for (i = 0; i < _dbus_string_get_length (&message->body); i++)
1616     {
1617       DBusString *buffer;
1618
1619       _dbus_message_loader_get_buffer (loader, &buffer);
1620       _dbus_string_append_byte (buffer, data[i]);
1621       _dbus_message_loader_return_buffer (loader, buffer, 1);
1622     }
1623
1624   dbus_message_unref (message);
1625
1626   /* Now pop back the message */
1627   if (_dbus_message_loader_get_is_corrupted (loader))
1628     _dbus_assert_not_reached ("message loader corrupted");
1629   
1630   message = _dbus_message_loader_pop_message (loader);
1631   if (!message)
1632     _dbus_assert_not_reached ("received a NULL message");
1633
1634   if (message->reply_serial != 0x12345678)
1635     _dbus_assert_not_reached ("reply serial fields differ");
1636   
1637   message_iter_test (message);
1638   
1639   dbus_message_unref (message);
1640   _dbus_message_loader_unref (loader);
1641
1642   return TRUE;
1643 }
1644
1645 #endif /* DBUS_BUILD_TESTS */