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