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