D-Bus  1.7.8
dbus-message.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-message.c DBusMessage object
3  *
4  * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
5  * Copyright (C) 2002, 2003 CodeFactory AB
6  *
7  * Licensed under the Academic Free License version 2.1
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 #include <config.h>
26 #include "dbus-internals.h"
27 #include "dbus-marshal-recursive.h"
28 #include "dbus-marshal-validate.h"
29 #include "dbus-marshal-byteswap.h"
30 #include "dbus-marshal-header.h"
31 #include "dbus-signature.h"
32 #include "dbus-message-private.h"
33 #include "dbus-object-tree.h"
34 #include "dbus-memory.h"
35 #include "dbus-list.h"
36 #include "dbus-threads-internal.h"
37 #ifdef HAVE_UNIX_FD_PASSING
38 #include "dbus-sysdeps-unix.h"
39 #endif
40 
41 #include <string.h>
42 
43 #define _DBUS_TYPE_IS_STRINGLIKE(type) \
44  (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \
45  type == DBUS_TYPE_OBJECT_PATH)
46 
47 static void dbus_message_finalize (DBusMessage *message);
48 
59 #ifdef DBUS_ENABLE_EMBEDDED_TESTS
60 static dbus_bool_t
61 _dbus_enable_message_cache (void)
62 {
63  static int enabled = -1;
64 
65  if (enabled < 0)
66  {
67  const char *s = _dbus_getenv ("DBUS_MESSAGE_CACHE");
68 
69  enabled = TRUE;
70 
71  if (s && *s)
72  {
73  if (*s == '0')
74  enabled = FALSE;
75  else if (*s == '1')
76  enabled = TRUE;
77  else
78  _dbus_warn ("DBUS_MESSAGE_CACHE should be 0 or 1 if set, not '%s'",
79  s);
80  }
81  }
82 
83  return enabled;
84 }
85 #else
86  /* constant expression, should be optimized away */
87 # define _dbus_enable_message_cache() (TRUE)
88 #endif
89 
90 #ifndef _dbus_message_trace_ref
91 void
92 _dbus_message_trace_ref (DBusMessage *message,
93  int old_refcount,
94  int new_refcount,
95  const char *why)
96 {
97  static int enabled = -1;
98 
99  _dbus_trace_ref ("DBusMessage", message, old_refcount, new_refcount, why,
100  "DBUS_MESSAGE_TRACE", &enabled);
101 }
102 #endif
103 
104 /* Not thread locked, but strictly const/read-only so should be OK
105  */
107 _DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, "");
108 
109 /* these have wacky values to help trap uninitialized iterators;
110  * but has to fit in 3 bits
111  */
112 enum {
113  DBUS_MESSAGE_ITER_TYPE_READER = 3,
114  DBUS_MESSAGE_ITER_TYPE_WRITER = 7
115 };
116 
119 
126 {
129  dbus_uint32_t iter_type : 3;
130  dbus_uint32_t sig_refcount : 8;
131  union
132  {
135  } u;
136 };
137 
138 static void
139 get_const_signature (DBusHeader *header,
140  const DBusString **type_str_p,
141  int *type_pos_p)
142 {
143  if (_dbus_header_get_field_raw (header,
145  type_str_p,
146  type_pos_p))
147  {
148  *type_pos_p += 1; /* skip the signature length which is 1 byte */
149  }
150  else
151  {
152  *type_str_p = &_dbus_empty_signature_str;
153  *type_pos_p = 0;
154  }
155 }
156 
162 static void
163 _dbus_message_byteswap (DBusMessage *message)
164 {
165  const DBusString *type_str;
166  int type_pos;
167  char byte_order;
168 
169  byte_order = _dbus_header_get_byte_order (&message->header);
170 
171  if (byte_order == DBUS_COMPILER_BYTE_ORDER)
172  return;
173 
174  _dbus_verbose ("Swapping message into compiler byte order\n");
175 
176  get_const_signature (&message->header, &type_str, &type_pos);
177 
178  _dbus_marshal_byteswap (type_str, type_pos,
179  byte_order,
180  DBUS_COMPILER_BYTE_ORDER,
181  &message->body, 0);
182 
183  _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
185  DBUS_COMPILER_BYTE_ORDER);
186 }
187 
194 #define ensure_byte_order(message) _dbus_message_byteswap (message)
195 
206 void
208  const DBusString **header,
209  const DBusString **body)
210 {
211  _dbus_assert (message->locked);
212 
213  *header = &message->header.data;
214  *body = &message->body;
215 }
216 
227  const int **fds,
228  unsigned *n_fds)
229 {
230  _dbus_assert (message->locked);
231 
232 #ifdef HAVE_UNIX_FD_PASSING
233  *fds = message->unix_fds;
234  *n_fds = message->n_unix_fds;
235 #else
236  *fds = NULL;
237  *n_fds = 0;
238 #endif
239 }
240 
252 void
254  dbus_uint32_t serial)
255 {
256  _dbus_return_if_fail (message != NULL);
257  _dbus_return_if_fail (!message->locked);
258 
259  _dbus_header_set_serial (&message->header, serial);
260 }
261 
278 void
280  DBusList *link)
281 {
282  /* right now we don't recompute the delta when message
283  * size changes, and that's OK for current purposes
284  * I think, but could be important to change later.
285  * Do recompute it whenever there are no outstanding counters,
286  * since it's basically free.
287  */
288  if (message->counters == NULL)
289  {
290  message->size_counter_delta =
291  _dbus_string_get_length (&message->header.data) +
292  _dbus_string_get_length (&message->body);
293 
294 #ifdef HAVE_UNIX_FD_PASSING
295  message->unix_fd_counter_delta = message->n_unix_fds;
296 #endif
297 
298 #if 0
299  _dbus_verbose ("message has size %ld\n",
300  message->size_counter_delta);
301 #endif
302  }
303 
304  _dbus_list_append_link (&message->counters, link);
305 
307 
308 #ifdef HAVE_UNIX_FD_PASSING
309  _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
310 #endif
311 }
312 
329  DBusCounter *counter)
330 {
331  DBusList *link;
332 
333  link = _dbus_list_alloc_link (counter);
334  if (link == NULL)
335  return FALSE;
336 
337  _dbus_counter_ref (counter);
338  _dbus_message_add_counter_link (message, link);
339 
340  return TRUE;
341 }
342 
350 void
352  DBusCounter *counter)
353 {
354  DBusList *link;
355 
356  link = _dbus_list_find_last (&message->counters,
357  counter);
358  _dbus_assert (link != NULL);
359 
360  _dbus_list_remove_link (&message->counters, link);
361 
362  _dbus_counter_adjust_size (counter, - message->size_counter_delta);
363 
364 #ifdef HAVE_UNIX_FD_PASSING
365  _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
366 #endif
367 
368  _dbus_counter_notify (counter);
369  _dbus_counter_unref (counter);
370 }
371 
382 void
384 {
385  if (!message->locked)
386  {
388  _dbus_string_get_length (&message->body));
389 
390  /* must have a signature if you have a body */
391  _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
392  dbus_message_get_signature (message) != NULL);
393 
394  message->locked = TRUE;
395  }
396 }
397 
398 static dbus_bool_t
399 set_or_delete_string_field (DBusMessage *message,
400  int field,
401  int typecode,
402  const char *value)
403 {
404  if (value == NULL)
405  return _dbus_header_delete_field (&message->header, field);
406  else
407  return _dbus_header_set_field_basic (&message->header,
408  field,
409  typecode,
410  &value);
411 }
412 
413 #if 0
414 /* Probably we don't need to use this */
438 static dbus_bool_t
439 _dbus_message_set_signature (DBusMessage *message,
440  const char *signature)
441 {
442  _dbus_return_val_if_fail (message != NULL, FALSE);
443  _dbus_return_val_if_fail (!message->locked, FALSE);
444  _dbus_return_val_if_fail (signature == NULL ||
445  _dbus_check_is_valid_signature (signature));
446  /* can't delete the signature if you have a message body */
447  _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
448  signature != NULL);
449 
450  return set_or_delete_string_field (message,
453  signature);
454 }
455 #endif
456 
457 /* Message Cache
458  *
459  * We cache some DBusMessage to reduce the overhead of allocating
460  * them. In my profiling this consistently made about an 8%
461  * difference. It avoids the malloc for the message, the malloc for
462  * the slot list, the malloc for the header string and body string,
463  * and the associated free() calls. It does introduce another global
464  * lock which could be a performance issue in certain cases.
465  *
466  * For the echo client/server the round trip time goes from around
467  * .000077 to .000069 with the message cache on my laptop. The sysprof
468  * change is as follows (numbers are cumulative percentage):
469  *
470  * with message cache implemented as array as it is now (0.000069 per):
471  * new_empty_header 1.46
472  * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache)
473  * mutex_unlock 0.25
474  * self 0.41
475  * unref 2.24
476  * self 0.68
477  * list_clear 0.43
478  * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache)
479  * mutex_unlock 0.25
480  *
481  * with message cache implemented as list (0.000070 per roundtrip):
482  * new_empty_header 2.72
483  * list_pop_first 1.88
484  * unref 3.3
485  * list_prepend 1.63
486  *
487  * without cache (0.000077 per roundtrip):
488  * new_empty_header 6.7
489  * string_init_preallocated 3.43
490  * dbus_malloc 2.43
491  * dbus_malloc0 2.59
492  *
493  * unref 4.02
494  * string_free 1.82
495  * dbus_free 1.63
496  * dbus_free 0.71
497  *
498  * If you implement the message_cache with a list, the primary reason
499  * it's slower is that you add another thread lock (on the DBusList
500  * mempool).
501  */
502 
504 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
505 
507 #define MAX_MESSAGE_CACHE_SIZE 5
508 
509 /* Protected by _DBUS_LOCK (message_cache) */
510 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
511 static int message_cache_count = 0;
512 static dbus_bool_t message_cache_shutdown_registered = FALSE;
513 
514 static void
515 dbus_message_cache_shutdown (void *data)
516 {
517  int i;
518 
519  if (!_DBUS_LOCK (message_cache))
520  _dbus_assert_not_reached ("we would have initialized global locks "
521  "before registering a shutdown function");
522 
523  i = 0;
524  while (i < MAX_MESSAGE_CACHE_SIZE)
525  {
526  if (message_cache[i])
527  dbus_message_finalize (message_cache[i]);
528 
529  ++i;
530  }
531 
532  message_cache_count = 0;
533  message_cache_shutdown_registered = FALSE;
534 
535  _DBUS_UNLOCK (message_cache);
536 }
537 
545 static DBusMessage*
546 dbus_message_get_cached (void)
547 {
548  DBusMessage *message;
549  int i;
550 
551  message = NULL;
552 
553  if (!_DBUS_LOCK (message_cache))
554  {
555  /* we'd have initialized global locks before caching anything,
556  * so there can't be anything in the cache */
557  return NULL;
558  }
559 
560  _dbus_assert (message_cache_count >= 0);
561 
562  if (message_cache_count == 0)
563  {
564  _DBUS_UNLOCK (message_cache);
565  return NULL;
566  }
567 
568  /* This is not necessarily true unless count > 0, and
569  * message_cache is uninitialized until the shutdown is
570  * registered
571  */
572  _dbus_assert (message_cache_shutdown_registered);
573 
574  i = 0;
575  while (i < MAX_MESSAGE_CACHE_SIZE)
576  {
577  if (message_cache[i])
578  {
579  message = message_cache[i];
580  message_cache[i] = NULL;
581  message_cache_count -= 1;
582  break;
583  }
584  ++i;
585  }
586  _dbus_assert (message_cache_count >= 0);
588  _dbus_assert (message != NULL);
589 
590  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
591 
592  _dbus_assert (message->counters == NULL);
593 
594  _DBUS_UNLOCK (message_cache);
595 
596  return message;
597 }
598 
599 #ifdef HAVE_UNIX_FD_PASSING
600 static void
601 close_unix_fds(int *fds, unsigned *n_fds)
602 {
603  DBusError e;
604  int i;
605 
606  if (*n_fds <= 0)
607  return;
608 
609  dbus_error_init(&e);
610 
611  for (i = 0; i < *n_fds; i++)
612  {
613  if (!_dbus_close(fds[i], &e))
614  {
615  _dbus_warn("Failed to close file descriptor: %s\n", e.message);
616  dbus_error_free(&e);
617  }
618  }
619 
620  *n_fds = 0;
621 
622  /* We don't free the array here, in case we can recycle it later */
623 }
624 #endif
625 
626 static void
627 free_counter (void *element,
628  void *data)
629 {
630  DBusCounter *counter = element;
631  DBusMessage *message = data;
632 
633  _dbus_counter_adjust_size (counter, - message->size_counter_delta);
634 #ifdef HAVE_UNIX_FD_PASSING
635  _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
636 #endif
637 
638  _dbus_counter_notify (counter);
639  _dbus_counter_unref (counter);
640 }
641 
647 static void
648 dbus_message_cache_or_finalize (DBusMessage *message)
649 {
650  dbus_bool_t was_cached;
651  int i;
652 
653  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
654 
655  /* This calls application code and has to be done first thing
656  * without holding the lock
657  */
659 
660  _dbus_list_foreach (&message->counters,
661  free_counter, message);
662  _dbus_list_clear (&message->counters);
663 
664 #ifdef HAVE_UNIX_FD_PASSING
665  close_unix_fds(message->unix_fds, &message->n_unix_fds);
666 #endif
667 
668  was_cached = FALSE;
669 
670  if (!_DBUS_LOCK (message_cache))
671  {
672  /* The only way to get a non-null message goes through
673  * dbus_message_get_cached() which takes the lock. */
674  _dbus_assert_not_reached ("we would have initialized global locks "
675  "the first time we constructed a message");
676  }
677 
678  if (!message_cache_shutdown_registered)
679  {
680  _dbus_assert (message_cache_count == 0);
681 
682  if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
683  goto out;
684 
685  i = 0;
686  while (i < MAX_MESSAGE_CACHE_SIZE)
687  {
688  message_cache[i] = NULL;
689  ++i;
690  }
691 
692  message_cache_shutdown_registered = TRUE;
693  }
694 
695  _dbus_assert (message_cache_count >= 0);
696 
697  if (!_dbus_enable_message_cache ())
698  goto out;
699 
700  if ((_dbus_string_get_length (&message->header.data) +
701  _dbus_string_get_length (&message->body)) >
703  goto out;
704 
705  if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
706  goto out;
707 
708  /* Find empty slot */
709  i = 0;
710  while (message_cache[i] != NULL)
711  ++i;
712 
714 
715  _dbus_assert (message_cache[i] == NULL);
716  message_cache[i] = message;
717  message_cache_count += 1;
718  was_cached = TRUE;
719 #ifndef DBUS_DISABLE_CHECKS
720  message->in_cache = TRUE;
721 #endif
722 
723  out:
724  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
725 
726  _DBUS_UNLOCK (message_cache);
727 
728  if (!was_cached)
729  dbus_message_finalize (message);
730 }
731 
732 #if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
733 static dbus_bool_t
734 _dbus_message_iter_check (DBusMessageRealIter *iter)
735 {
736  char byte_order;
737 
738  if (iter == NULL)
739  {
740  _dbus_warn_check_failed ("dbus message iterator is NULL\n");
741  return FALSE;
742  }
743 
744  byte_order = _dbus_header_get_byte_order (&iter->message->header);
745 
746  if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
747  {
748  if (iter->u.reader.byte_order != byte_order)
749  {
750  _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
751  return FALSE;
752  }
753  /* because we swap the message into compiler order when you init an iter */
754  _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
755  }
756  else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
757  {
758  if (iter->u.writer.byte_order != byte_order)
759  {
760  _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
761  return FALSE;
762  }
763  /* because we swap the message into compiler order when you init an iter */
764  _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
765  }
766  else
767  {
768  _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
769  return FALSE;
770  }
771 
772  if (iter->changed_stamp != iter->message->changed_stamp)
773  {
774  _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
775  return FALSE;
776  }
777 
778  return TRUE;
779 }
780 #endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */
781 
796  DBusError *error,
797  int first_arg_type,
798  va_list var_args)
799 {
801  int spec_type, msg_type, i, j;
802  dbus_bool_t retval;
803  va_list copy_args;
804 
805  _dbus_assert (_dbus_message_iter_check (real));
806 
807  retval = FALSE;
808 
809  spec_type = first_arg_type;
810  i = 0;
811 
812  /* copy var_args first, then we can do another iteration over it to
813  * free memory and close unix fds if parse failed at some point.
814  */
815  va_copy (copy_args, var_args);
816 
817  while (spec_type != DBUS_TYPE_INVALID)
818  {
819  msg_type = dbus_message_iter_get_arg_type (iter);
820 
821  if (msg_type != spec_type)
822  {
824  "Argument %d is specified to be of type \"%s\", but "
825  "is actually of type \"%s\"\n", i,
826  _dbus_type_to_string (spec_type),
827  _dbus_type_to_string (msg_type));
828 
829  goto out;
830  }
831 
832  if (spec_type == DBUS_TYPE_UNIX_FD)
833  {
834 #ifdef HAVE_UNIX_FD_PASSING
835  DBusBasicValue idx;
836  int *pfd, nfd;
837 
838  pfd = va_arg (var_args, int*);
839  _dbus_assert(pfd);
840 
841  _dbus_type_reader_read_basic(&real->u.reader, &idx);
842 
843  if (idx.u32 >= real->message->n_unix_fds)
844  {
846  "Message refers to file descriptor at index %i,"
847  "but has only %i descriptors attached.\n",
848  idx.u32,
849  real->message->n_unix_fds);
850  goto out;
851  }
852 
853  if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
854  goto out;
855 
856  *pfd = nfd;
857 #else
859  "Platform does not support file desciptor passing.\n");
860  goto out;
861 #endif
862  }
863  else if (dbus_type_is_basic (spec_type))
864  {
865  DBusBasicValue *ptr;
866 
867  ptr = va_arg (var_args, DBusBasicValue*);
868 
869  _dbus_assert (ptr != NULL);
870 
872  ptr);
873  }
874  else if (spec_type == DBUS_TYPE_ARRAY)
875  {
876  int element_type;
877  int spec_element_type;
878  const DBusBasicValue **ptr;
879  int *n_elements_p;
880  DBusTypeReader array;
881 
882  spec_element_type = va_arg (var_args, int);
883  element_type = _dbus_type_reader_get_element_type (&real->u.reader);
884 
885  if (spec_element_type != element_type)
886  {
888  "Argument %d is specified to be an array of \"%s\", but "
889  "is actually an array of \"%s\"\n",
890  i,
891  _dbus_type_to_string (spec_element_type),
892  _dbus_type_to_string (element_type));
893 
894  goto out;
895  }
896 
897  if (dbus_type_is_fixed (spec_element_type) &&
898  element_type != DBUS_TYPE_UNIX_FD)
899  {
900  ptr = va_arg (var_args, const DBusBasicValue**);
901  n_elements_p = va_arg (var_args, int*);
902 
903  _dbus_assert (ptr != NULL);
904  _dbus_assert (n_elements_p != NULL);
905 
906  _dbus_type_reader_recurse (&real->u.reader, &array);
907 
909  (void *) ptr, n_elements_p);
910  }
911  else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
912  {
913  char ***str_array_p;
914  int n_elements;
915  char **str_array;
916 
917  str_array_p = va_arg (var_args, char***);
918  n_elements_p = va_arg (var_args, int*);
919 
920  _dbus_assert (str_array_p != NULL);
921  _dbus_assert (n_elements_p != NULL);
922 
923  /* Count elements in the array */
924  _dbus_type_reader_recurse (&real->u.reader, &array);
925 
926  n_elements = 0;
928  {
929  ++n_elements;
930  _dbus_type_reader_next (&array);
931  }
932 
933  str_array = dbus_new0 (char*, n_elements + 1);
934  if (str_array == NULL)
935  {
936  _DBUS_SET_OOM (error);
937  goto out;
938  }
939 
940  /* Now go through and dup each string */
941  _dbus_type_reader_recurse (&real->u.reader, &array);
942 
943  j = 0;
944  while (j < n_elements)
945  {
946  const char *s;
948  (void *) &s);
949 
950  str_array[j] = _dbus_strdup (s);
951  if (str_array[j] == NULL)
952  {
953  dbus_free_string_array (str_array);
954  _DBUS_SET_OOM (error);
955  goto out;
956  }
957 
958  ++j;
959 
960  if (!_dbus_type_reader_next (&array))
961  _dbus_assert (j == n_elements);
962  }
963 
965  _dbus_assert (j == n_elements);
966  _dbus_assert (str_array[j] == NULL);
967 
968  *str_array_p = str_array;
969  *n_elements_p = n_elements;
970  }
971 #ifndef DBUS_DISABLE_CHECKS
972  else
973  {
974  _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
975  _DBUS_FUNCTION_NAME);
976  goto out;
977  }
978 #endif
979  }
980 #ifndef DBUS_DISABLE_CHECKS
981  else
982  {
983  _dbus_warn ("you can only read arrays and basic types with %s for now\n",
984  _DBUS_FUNCTION_NAME);
985  goto out;
986  }
987 #endif
988 
989  /* how many arguments already handled */
990  i++;
991 
992  spec_type = va_arg (var_args, int);
993  if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
994  {
996  "Message has only %d arguments, but more were expected", i);
997  goto out;
998  }
999  }
1000 
1001  retval = TRUE;
1002 
1003  out:
1004  /* there may memory or unix fd leak in the above iteration if parse failed.
1005  * so we have another iteration over copy_args to free memory and close
1006  * unix fds.
1007  */
1008  if (!retval)
1009  {
1010  spec_type = first_arg_type;
1011  j = 0;
1012 
1013  while (j < i)
1014  {
1015  if (spec_type == DBUS_TYPE_UNIX_FD)
1016  {
1017 #ifdef HAVE_UNIX_FD_PASSING
1018  int *pfd;
1019 
1020  pfd = va_arg (copy_args, int *);
1021  _dbus_assert(pfd);
1022  if (*pfd >= 0)
1023  {
1024  _dbus_close (*pfd, NULL);
1025  *pfd = -1;
1026  }
1027 #endif
1028  }
1029  else if (dbus_type_is_basic (spec_type))
1030  {
1031  /* move the index forward */
1032  va_arg (copy_args, DBusBasicValue *);
1033  }
1034  else if (spec_type == DBUS_TYPE_ARRAY)
1035  {
1036  int spec_element_type;
1037 
1038  spec_element_type = va_arg (copy_args, int);
1039  if (dbus_type_is_fixed (spec_element_type))
1040  {
1041  /* move the index forward */
1042  va_arg (copy_args, const DBusBasicValue **);
1043  va_arg (copy_args, int *);
1044  }
1045  else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
1046  {
1047  char ***str_array_p;
1048 
1049  str_array_p = va_arg (copy_args, char ***);
1050  /* move the index forward */
1051  va_arg (copy_args, int *);
1052  _dbus_assert (str_array_p != NULL);
1053  dbus_free_string_array (*str_array_p);
1054  *str_array_p = NULL;
1055  }
1056  }
1057 
1058  spec_type = va_arg (copy_args, int);
1059  j++;
1060  }
1061  }
1062 
1063  va_end (copy_args);
1064  return retval;
1065 }
1066 
1125 dbus_uint32_t
1127 {
1128  _dbus_return_val_if_fail (message != NULL, 0);
1129 
1130  return _dbus_header_get_serial (&message->header);
1131 }
1132 
1143  dbus_uint32_t reply_serial)
1144 {
1145  _dbus_return_val_if_fail (message != NULL, FALSE);
1146  _dbus_return_val_if_fail (!message->locked, FALSE);
1147  _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
1148 
1149  return _dbus_header_set_field_basic (&message->header,
1152  &reply_serial);
1153 }
1154 
1161 dbus_uint32_t
1163 {
1164  dbus_uint32_t v_UINT32;
1165 
1166  _dbus_return_val_if_fail (message != NULL, 0);
1167 
1168  if (_dbus_header_get_field_basic (&message->header,
1171  &v_UINT32))
1172  return v_UINT32;
1173  else
1174  return 0;
1175 }
1176 
1177 static void
1178 dbus_message_finalize (DBusMessage *message)
1179 {
1180  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1181 
1182  /* This calls application callbacks! */
1184 
1185  _dbus_list_foreach (&message->counters,
1186  free_counter, message);
1187  _dbus_list_clear (&message->counters);
1188 
1189  _dbus_header_free (&message->header);
1190  _dbus_string_free (&message->body);
1191 
1192 #ifdef HAVE_UNIX_FD_PASSING
1193  close_unix_fds(message->unix_fds, &message->n_unix_fds);
1194  dbus_free(message->unix_fds);
1195 #endif
1196 
1197  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1198 
1199  dbus_free (message);
1200 }
1201 
1202 static DBusMessage*
1203 dbus_message_new_empty_header (void)
1204 {
1205  DBusMessage *message;
1206  dbus_bool_t from_cache;
1207 
1208  message = dbus_message_get_cached ();
1209 
1210  if (message != NULL)
1211  {
1212  from_cache = TRUE;
1213  }
1214  else
1215  {
1216  from_cache = FALSE;
1217  message = dbus_new0 (DBusMessage, 1);
1218  if (message == NULL)
1219  return NULL;
1220 #ifndef DBUS_DISABLE_CHECKS
1222 #endif
1223 
1224 #ifdef HAVE_UNIX_FD_PASSING
1225  message->unix_fds = NULL;
1226  message->n_unix_fds_allocated = 0;
1227 #endif
1228  }
1229 
1230  _dbus_atomic_inc (&message->refcount);
1231 
1232  _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
1233 
1234  message->locked = FALSE;
1235 #ifndef DBUS_DISABLE_CHECKS
1236  message->in_cache = FALSE;
1237 #endif
1238  message->counters = NULL;
1239  message->size_counter_delta = 0;
1240  message->changed_stamp = 0;
1241 
1242 #ifdef HAVE_UNIX_FD_PASSING
1243  message->n_unix_fds = 0;
1244  message->n_unix_fds_allocated = 0;
1245  message->unix_fd_counter_delta = 0;
1246 #endif
1247 
1248  if (!from_cache)
1250 
1251  if (from_cache)
1252  {
1253  _dbus_header_reinit (&message->header);
1254  _dbus_string_set_length (&message->body, 0);
1255  }
1256  else
1257  {
1258  if (!_dbus_header_init (&message->header))
1259  {
1260  dbus_free (message);
1261  return NULL;
1262  }
1263 
1264  if (!_dbus_string_init_preallocated (&message->body, 32))
1265  {
1266  _dbus_header_free (&message->header);
1267  dbus_free (message);
1268  return NULL;
1269  }
1270  }
1271 
1272  return message;
1273 }
1274 
1287 DBusMessage*
1288 dbus_message_new (int message_type)
1289 {
1290  DBusMessage *message;
1291 
1292  _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
1293 
1294  message = dbus_message_new_empty_header ();
1295  if (message == NULL)
1296  return NULL;
1297 
1298  if (!_dbus_header_create (&message->header,
1299  DBUS_COMPILER_BYTE_ORDER,
1300  message_type,
1301  NULL, NULL, NULL, NULL, NULL))
1302  {
1303  dbus_message_unref (message);
1304  return NULL;
1305  }
1306 
1307  return message;
1308 }
1309 
1331 DBusMessage*
1332 dbus_message_new_method_call (const char *destination,
1333  const char *path,
1334  const char *iface,
1335  const char *method)
1336 {
1337  DBusMessage *message;
1338 
1339  _dbus_return_val_if_fail (path != NULL, NULL);
1340  _dbus_return_val_if_fail (method != NULL, NULL);
1341  _dbus_return_val_if_fail (destination == NULL ||
1342  _dbus_check_is_valid_bus_name (destination), NULL);
1343  _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1344  _dbus_return_val_if_fail (iface == NULL ||
1345  _dbus_check_is_valid_interface (iface), NULL);
1346  _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
1347 
1348  message = dbus_message_new_empty_header ();
1349  if (message == NULL)
1350  return NULL;
1351 
1352  if (!_dbus_header_create (&message->header,
1353  DBUS_COMPILER_BYTE_ORDER,
1355  destination, path, iface, method, NULL))
1356  {
1357  dbus_message_unref (message);
1358  return NULL;
1359  }
1360 
1361  return message;
1362 }
1363 
1371 DBusMessage*
1373 {
1374  DBusMessage *message;
1375  const char *sender;
1376 
1377  _dbus_return_val_if_fail (method_call != NULL, NULL);
1378 
1379  sender = dbus_message_get_sender (method_call);
1380 
1381  /* sender is allowed to be null here in peer-to-peer case */
1382 
1383  message = dbus_message_new_empty_header ();
1384  if (message == NULL)
1385  return NULL;
1386 
1387  if (!_dbus_header_create (&message->header,
1388  DBUS_COMPILER_BYTE_ORDER,
1390  sender, NULL, NULL, NULL, NULL))
1391  {
1392  dbus_message_unref (message);
1393  return NULL;
1394  }
1395 
1396  dbus_message_set_no_reply (message, TRUE);
1397 
1398  if (!dbus_message_set_reply_serial (message,
1399  dbus_message_get_serial (method_call)))
1400  {
1401  dbus_message_unref (message);
1402  return NULL;
1403  }
1404 
1405  return message;
1406 }
1407 
1422 DBusMessage*
1423 dbus_message_new_signal (const char *path,
1424  const char *iface,
1425  const char *name)
1426 {
1427  DBusMessage *message;
1428 
1429  _dbus_return_val_if_fail (path != NULL, NULL);
1430  _dbus_return_val_if_fail (iface != NULL, NULL);
1431  _dbus_return_val_if_fail (name != NULL, NULL);
1432  _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1433  _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
1434  _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
1435 
1436  message = dbus_message_new_empty_header ();
1437  if (message == NULL)
1438  return NULL;
1439 
1440  if (!_dbus_header_create (&message->header,
1441  DBUS_COMPILER_BYTE_ORDER,
1443  NULL, path, iface, name, NULL))
1444  {
1445  dbus_message_unref (message);
1446  return NULL;
1447  }
1448 
1449  dbus_message_set_no_reply (message, TRUE);
1450 
1451  return message;
1452 }
1453 
1468 DBusMessage*
1470  const char *error_name,
1471  const char *error_message)
1472 {
1473  DBusMessage *message;
1474  const char *sender;
1475  DBusMessageIter iter;
1476 
1477  _dbus_return_val_if_fail (reply_to != NULL, NULL);
1478  _dbus_return_val_if_fail (error_name != NULL, NULL);
1479  _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1480 
1481  sender = dbus_message_get_sender (reply_to);
1482 
1483  /* sender may be NULL for non-message-bus case or
1484  * when the message bus is dealing with an unregistered
1485  * connection.
1486  */
1487  message = dbus_message_new_empty_header ();
1488  if (message == NULL)
1489  return NULL;
1490 
1491  if (!_dbus_header_create (&message->header,
1492  DBUS_COMPILER_BYTE_ORDER,
1494  sender, NULL, NULL, NULL, error_name))
1495  {
1496  dbus_message_unref (message);
1497  return NULL;
1498  }
1499 
1500  dbus_message_set_no_reply (message, TRUE);
1501 
1502  if (!dbus_message_set_reply_serial (message,
1503  dbus_message_get_serial (reply_to)))
1504  {
1505  dbus_message_unref (message);
1506  return NULL;
1507  }
1508 
1509  if (error_message != NULL)
1510  {
1511  dbus_message_iter_init_append (message, &iter);
1512  if (!dbus_message_iter_append_basic (&iter,
1514  &error_message))
1515  {
1516  dbus_message_unref (message);
1517  return NULL;
1518  }
1519  }
1520 
1521  return message;
1522 }
1523 
1540 DBusMessage*
1542  const char *error_name,
1543  const char *error_format,
1544  ...)
1545 {
1546  va_list args;
1547  DBusString str;
1548  DBusMessage *message;
1549 
1550  _dbus_return_val_if_fail (reply_to != NULL, NULL);
1551  _dbus_return_val_if_fail (error_name != NULL, NULL);
1552  _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1553 
1554  if (!_dbus_string_init (&str))
1555  return NULL;
1556 
1557  va_start (args, error_format);
1558 
1559  if (_dbus_string_append_printf_valist (&str, error_format, args))
1560  message = dbus_message_new_error (reply_to, error_name,
1561  _dbus_string_get_const_data (&str));
1562  else
1563  message = NULL;
1564 
1565  _dbus_string_free (&str);
1566 
1567  va_end (args);
1568 
1569  return message;
1570 }
1571 
1572 
1585 DBusMessage *
1587 {
1588  DBusMessage *retval;
1589 
1590  _dbus_return_val_if_fail (message != NULL, NULL);
1591 
1592  retval = dbus_new0 (DBusMessage, 1);
1593  if (retval == NULL)
1594  return NULL;
1595 
1596  _dbus_atomic_inc (&retval->refcount);
1597 
1598  retval->locked = FALSE;
1599 #ifndef DBUS_DISABLE_CHECKS
1600  retval->generation = message->generation;
1601 #endif
1602 
1603  if (!_dbus_header_copy (&message->header, &retval->header))
1604  {
1605  dbus_free (retval);
1606  return NULL;
1607  }
1608 
1609  if (!_dbus_string_init_preallocated (&retval->body,
1610  _dbus_string_get_length (&message->body)))
1611  {
1612  _dbus_header_free (&retval->header);
1613  dbus_free (retval);
1614  return NULL;
1615  }
1616 
1617  if (!_dbus_string_copy (&message->body, 0,
1618  &retval->body, 0))
1619  goto failed_copy;
1620 
1621 #ifdef HAVE_UNIX_FD_PASSING
1622  retval->unix_fds = dbus_new(int, message->n_unix_fds);
1623  if (retval->unix_fds == NULL && message->n_unix_fds > 0)
1624  goto failed_copy;
1625 
1626  retval->n_unix_fds_allocated = message->n_unix_fds;
1627 
1628  for (retval->n_unix_fds = 0;
1629  retval->n_unix_fds < message->n_unix_fds;
1630  retval->n_unix_fds++)
1631  {
1632  retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
1633 
1634  if (retval->unix_fds[retval->n_unix_fds] < 0)
1635  goto failed_copy;
1636  }
1637 
1638 #endif
1639 
1640  _dbus_message_trace_ref (retval, 0, 1, "copy");
1641  return retval;
1642 
1643  failed_copy:
1644  _dbus_header_free (&retval->header);
1645  _dbus_string_free (&retval->body);
1646 
1647 #ifdef HAVE_UNIX_FD_PASSING
1648  close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
1649  dbus_free(retval->unix_fds);
1650 #endif
1651 
1652  dbus_free (retval);
1653 
1654  return NULL;
1655 }
1656 
1657 
1665 DBusMessage *
1667 {
1668  dbus_int32_t old_refcount;
1669 
1670  _dbus_return_val_if_fail (message != NULL, NULL);
1671  _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
1672  _dbus_return_val_if_fail (!message->in_cache, NULL);
1673 
1674  old_refcount = _dbus_atomic_inc (&message->refcount);
1675  _dbus_assert (old_refcount >= 1);
1676  _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
1677 
1678  return message;
1679 }
1680 
1688 void
1690 {
1691  dbus_int32_t old_refcount;
1692 
1693  _dbus_return_if_fail (message != NULL);
1694  _dbus_return_if_fail (message->generation == _dbus_current_generation);
1695  _dbus_return_if_fail (!message->in_cache);
1696 
1697  old_refcount = _dbus_atomic_dec (&message->refcount);
1698 
1699  _dbus_assert (old_refcount >= 1);
1700 
1701  _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
1702 
1703  if (old_refcount == 1)
1704  {
1705  /* Calls application callbacks! */
1706  dbus_message_cache_or_finalize (message);
1707  }
1708 }
1709 
1720 int
1722 {
1723  _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
1724 
1725  return _dbus_header_get_message_type (&message->header);
1726 }
1727 
1792  int first_arg_type,
1793  ...)
1794 {
1795  dbus_bool_t retval;
1796  va_list var_args;
1797 
1798  _dbus_return_val_if_fail (message != NULL, FALSE);
1799 
1800  va_start (var_args, first_arg_type);
1801  retval = dbus_message_append_args_valist (message,
1802  first_arg_type,
1803  var_args);
1804  va_end (var_args);
1805 
1806  return retval;
1807 }
1808 
1824  int first_arg_type,
1825  va_list var_args)
1826 {
1827  int type;
1828  DBusMessageIter iter;
1829 
1830  _dbus_return_val_if_fail (message != NULL, FALSE);
1831 
1832  type = first_arg_type;
1833 
1834  dbus_message_iter_init_append (message, &iter);
1835 
1836  while (type != DBUS_TYPE_INVALID)
1837  {
1838  if (dbus_type_is_basic (type))
1839  {
1840  const DBusBasicValue *value;
1841  value = va_arg (var_args, const DBusBasicValue*);
1842 
1843  if (!dbus_message_iter_append_basic (&iter,
1844  type,
1845  value))
1846  goto failed;
1847  }
1848  else if (type == DBUS_TYPE_ARRAY)
1849  {
1850  int element_type;
1851  DBusMessageIter array;
1852  char buf[2];
1853 
1854  element_type = va_arg (var_args, int);
1855 
1856  buf[0] = element_type;
1857  buf[1] = '\0';
1860  buf,
1861  &array))
1862  goto failed;
1863 
1864  if (dbus_type_is_fixed (element_type) &&
1865  element_type != DBUS_TYPE_UNIX_FD)
1866  {
1867  const DBusBasicValue **value;
1868  int n_elements;
1869 
1870  value = va_arg (var_args, const DBusBasicValue**);
1871  n_elements = va_arg (var_args, int);
1872 
1874  element_type,
1875  value,
1876  n_elements)) {
1877  dbus_message_iter_abandon_container (&iter, &array);
1878  goto failed;
1879  }
1880  }
1881  else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
1882  {
1883  const char ***value_p;
1884  const char **value;
1885  int n_elements;
1886  int i;
1887 
1888  value_p = va_arg (var_args, const char***);
1889  n_elements = va_arg (var_args, int);
1890 
1891  value = *value_p;
1892 
1893  i = 0;
1894  while (i < n_elements)
1895  {
1896  if (!dbus_message_iter_append_basic (&array,
1897  element_type,
1898  &value[i])) {
1899  dbus_message_iter_abandon_container (&iter, &array);
1900  goto failed;
1901  }
1902  ++i;
1903  }
1904  }
1905  else
1906  {
1907  _dbus_warn ("arrays of %s can't be appended with %s for now\n",
1908  _dbus_type_to_string (element_type),
1909  _DBUS_FUNCTION_NAME);
1910  goto failed;
1911  }
1912 
1913  if (!dbus_message_iter_close_container (&iter, &array))
1914  goto failed;
1915  }
1916 #ifndef DBUS_DISABLE_CHECKS
1917  else
1918  {
1919  _dbus_warn ("type %s isn't supported yet in %s\n",
1920  _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
1921  goto failed;
1922  }
1923 #endif
1924 
1925  type = va_arg (var_args, int);
1926  }
1927 
1928  return TRUE;
1929 
1930  failed:
1931  return FALSE;
1932 }
1933 
1980  DBusError *error,
1981  int first_arg_type,
1982  ...)
1983 {
1984  dbus_bool_t retval;
1985  va_list var_args;
1986 
1987  _dbus_return_val_if_fail (message != NULL, FALSE);
1988  _dbus_return_val_if_error_is_set (error, FALSE);
1989 
1990  va_start (var_args, first_arg_type);
1991  retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
1992  va_end (var_args);
1993 
1994  return retval;
1995 }
1996 
2009  DBusError *error,
2010  int first_arg_type,
2011  va_list var_args)
2012 {
2013  DBusMessageIter iter;
2014 
2015  _dbus_return_val_if_fail (message != NULL, FALSE);
2016  _dbus_return_val_if_error_is_set (error, FALSE);
2017 
2018  dbus_message_iter_init (message, &iter);
2019  return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
2020 }
2021 
2022 static void
2023 _dbus_message_iter_init_common (DBusMessage *message,
2024  DBusMessageRealIter *real,
2025  int iter_type)
2026 {
2027  _dbus_assert (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
2028 
2029  /* Since the iterator will read or write who-knows-what from the
2030  * message, we need to get in the right byte order
2031  */
2032  ensure_byte_order (message);
2033 
2034  real->message = message;
2035  real->changed_stamp = message->changed_stamp;
2036  real->iter_type = iter_type;
2037  real->sig_refcount = 0;
2038 }
2039 
2064  DBusMessageIter *iter)
2065 {
2066  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2067  const DBusString *type_str;
2068  int type_pos;
2069 
2070  _dbus_return_val_if_fail (message != NULL, FALSE);
2071  _dbus_return_val_if_fail (iter != NULL, FALSE);
2072 
2073  get_const_signature (&message->header, &type_str, &type_pos);
2074 
2075  _dbus_message_iter_init_common (message, real,
2076  DBUS_MESSAGE_ITER_TYPE_READER);
2077 
2079  _dbus_header_get_byte_order (&message->header),
2080  type_str, type_pos,
2081  &message->body,
2082  0);
2083 
2085 }
2086 
2095 {
2096  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2097 
2098  _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2099  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2100 
2101  return _dbus_type_reader_has_next (&real->u.reader);
2102 }
2103 
2114 {
2115  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2116 
2117  _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2118  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2119 
2120  return _dbus_type_reader_next (&real->u.reader);
2121 }
2122 
2137 int
2139 {
2140  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2141 
2142  _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2143  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2144 
2146 }
2147 
2156 int
2158 {
2159  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2160 
2161  _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2162  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
2163  _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
2164 
2166 }
2167 
2193 void
2195  DBusMessageIter *sub)
2196 {
2197  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2198  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2199 
2200  _dbus_return_if_fail (_dbus_message_iter_check (real));
2201  _dbus_return_if_fail (sub != NULL);
2202 
2203  *real_sub = *real;
2204  _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
2205 }
2206 
2218 char *
2220 {
2221  const DBusString *sig;
2222  DBusString retstr;
2223  char *ret;
2224  int start, len;
2225  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2226 
2227  _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
2228 
2229  if (!_dbus_string_init (&retstr))
2230  return NULL;
2231 
2233  &start, &len);
2234  if (!_dbus_string_append_len (&retstr,
2235  _dbus_string_get_const_data (sig) + start,
2236  len))
2237  return NULL;
2238  if (!_dbus_string_steal_data (&retstr, &ret))
2239  return NULL;
2240  _dbus_string_free (&retstr);
2241  return ret;
2242 }
2243 
2291 void
2293  void *value)
2294 {
2295  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2296 
2297  _dbus_return_if_fail (_dbus_message_iter_check (real));
2298  _dbus_return_if_fail (value != NULL);
2299 
2301  {
2302 #ifdef HAVE_UNIX_FD_PASSING
2303  DBusBasicValue idx;
2304 
2305  _dbus_type_reader_read_basic(&real->u.reader, &idx);
2306 
2307  if (idx.u32 >= real->message->n_unix_fds) {
2308  /* Hmm, we cannot really signal an error here, so let's make
2309  sure to return an invalid fd. */
2310  *((int*) value) = -1;
2311  return;
2312  }
2313 
2314  *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
2315 #else
2316  *((int*) value) = -1;
2317 #endif
2318  }
2319  else
2320  {
2322  value);
2323  }
2324 }
2325 
2344 int
2346 {
2347  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2348 
2349  _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2350 
2352 }
2353 
2389 void
2391  void *value,
2392  int *n_elements)
2393 {
2394  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2395 #ifndef DBUS_DISABLE_CHECKS
2396  int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
2397 
2398  _dbus_return_if_fail (_dbus_message_iter_check (real));
2399  _dbus_return_if_fail (value != NULL);
2400  _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
2401  (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
2402 #endif
2403 
2405  value, n_elements);
2406 }
2407 
2419 void
2421  DBusMessageIter *iter)
2422 {
2423  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2424 
2425  _dbus_return_if_fail (message != NULL);
2426  _dbus_return_if_fail (iter != NULL);
2427 
2428  _dbus_message_iter_init_common (message, real,
2429  DBUS_MESSAGE_ITER_TYPE_WRITER);
2430 
2431  /* We create the signature string and point iterators at it "on demand"
2432  * when a value is actually appended. That means that init() never fails
2433  * due to OOM.
2434  */
2436  _dbus_header_get_byte_order (&message->header),
2437  &message->body,
2438  _dbus_string_get_length (&message->body));
2439 }
2440 
2449 static dbus_bool_t
2450 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
2451 {
2452  DBusString *str;
2453  const DBusString *current_sig;
2454  int current_sig_pos;
2455 
2456  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2457 
2458  if (real->u.writer.type_str != NULL)
2459  {
2460  _dbus_assert (real->sig_refcount > 0);
2461  real->sig_refcount += 1;
2462  return TRUE;
2463  }
2464 
2465  str = dbus_new (DBusString, 1);
2466  if (str == NULL)
2467  return FALSE;
2468 
2471  &current_sig, &current_sig_pos))
2472  current_sig = NULL;
2473 
2474  if (current_sig)
2475  {
2476  int current_len;
2477 
2478  current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
2479  current_sig_pos += 1; /* move on to sig data */
2480 
2481  if (!_dbus_string_init_preallocated (str, current_len + 4))
2482  {
2483  dbus_free (str);
2484  return FALSE;
2485  }
2486 
2487  if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
2488  str, 0))
2489  {
2490  _dbus_string_free (str);
2491  dbus_free (str);
2492  return FALSE;
2493  }
2494  }
2495  else
2496  {
2497  if (!_dbus_string_init_preallocated (str, 4))
2498  {
2499  dbus_free (str);
2500  return FALSE;
2501  }
2502  }
2503 
2504  real->sig_refcount = 1;
2505 
2507  str, _dbus_string_get_length (str));
2508  return TRUE;
2509 }
2510 
2520 static dbus_bool_t
2521 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
2522 {
2523  DBusString *str;
2524  const char *v_STRING;
2525  dbus_bool_t retval;
2526 
2527  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2528  _dbus_assert (real->u.writer.type_str != NULL);
2529  _dbus_assert (real->sig_refcount > 0);
2530 
2531  real->sig_refcount -= 1;
2532 
2533  if (real->sig_refcount > 0)
2534  return TRUE;
2535  _dbus_assert (real->sig_refcount == 0);
2536 
2537  retval = TRUE;
2538 
2539  str = real->u.writer.type_str;
2540 
2541  v_STRING = _dbus_string_get_const_data (str);
2545  &v_STRING))
2546  retval = FALSE;
2547 
2549  _dbus_string_free (str);
2550  dbus_free (str);
2551 
2552  return retval;
2553 }
2554 
2562 static void
2563 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
2564 {
2565  DBusString *str;
2566 
2567  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2568  _dbus_assert (real->u.writer.type_str != NULL);
2569  _dbus_assert (real->sig_refcount > 0);
2570 
2571  real->sig_refcount -= 1;
2572 
2573  if (real->sig_refcount > 0)
2574  return;
2575  _dbus_assert (real->sig_refcount == 0);
2576 
2577  str = real->u.writer.type_str;
2578 
2580  _dbus_string_free (str);
2581  dbus_free (str);
2582 }
2583 
2584 #ifndef DBUS_DISABLE_CHECKS
2585 static dbus_bool_t
2586 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
2587 {
2588  if (!_dbus_message_iter_check (iter))
2589  return FALSE;
2590 
2591  if (iter->message->locked)
2592  {
2593  _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
2594  return FALSE;
2595  }
2596 
2597  return TRUE;
2598 }
2599 #endif /* DBUS_DISABLE_CHECKS */
2600 
2601 #ifdef HAVE_UNIX_FD_PASSING
2602 static int *
2603 expand_fd_array(DBusMessage *m,
2604  unsigned n)
2605 {
2606  _dbus_assert(m);
2607 
2608  /* This makes space for adding n new fds to the array and returns a
2609  pointer to the place were the first fd should be put. */
2610 
2611  if (m->n_unix_fds + n > m->n_unix_fds_allocated)
2612  {
2613  unsigned k;
2614  int *p;
2615 
2616  /* Make twice as much space as necessary */
2617  k = (m->n_unix_fds + n) * 2;
2618 
2619  /* Allocate at least four */
2620  if (k < 4)
2621  k = 4;
2622 
2623  p = dbus_realloc(m->unix_fds, k * sizeof(int));
2624  if (p == NULL)
2625  return NULL;
2626 
2627  m->unix_fds = p;
2628  m->n_unix_fds_allocated = k;
2629  }
2630 
2631  return m->unix_fds + m->n_unix_fds;
2632 }
2633 #endif
2634 
2656  int type,
2657  const void *value)
2658 {
2659  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2660  dbus_bool_t ret;
2661 
2662  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2663  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2664  _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
2665  _dbus_return_val_if_fail (value != NULL, FALSE);
2666 
2667 #ifndef DBUS_DISABLE_CHECKS
2668  switch (type)
2669  {
2670  const char * const *string_p;
2671  const dbus_bool_t *bool_p;
2672 
2673  case DBUS_TYPE_STRING:
2674  string_p = value;
2675  _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
2676  break;
2677 
2678  case DBUS_TYPE_OBJECT_PATH:
2679  string_p = value;
2680  _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
2681  break;
2682 
2683  case DBUS_TYPE_SIGNATURE:
2684  string_p = value;
2685  _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
2686  break;
2687 
2688  case DBUS_TYPE_BOOLEAN:
2689  bool_p = value;
2690  _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
2691  break;
2692 
2693  default:
2694  {
2695  /* nothing to check, all possible values are allowed */
2696  }
2697  }
2698 #endif
2699 
2700  if (!_dbus_message_iter_open_signature (real))
2701  return FALSE;
2702 
2703  if (type == DBUS_TYPE_UNIX_FD)
2704  {
2705 #ifdef HAVE_UNIX_FD_PASSING
2706  int *fds;
2707  dbus_uint32_t u;
2708 
2709  /* First step, include the fd in the fd list of this message */
2710  if (!(fds = expand_fd_array(real->message, 1)))
2711  return FALSE;
2712 
2713  *fds = _dbus_dup(*(int*) value, NULL);
2714  if (*fds < 0)
2715  return FALSE;
2716 
2717  u = real->message->n_unix_fds;
2718 
2719  /* Second step, write the index to the fd */
2720  if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
2721  _dbus_close(*fds, NULL);
2722  return FALSE;
2723  }
2724 
2725  real->message->n_unix_fds += 1;
2726  u += 1;
2727 
2728  /* Final step, update the header accordingly */
2732  &u);
2733 
2734  /* If any of these operations fail the message is
2735  hosed. However, no memory or fds should be leaked since what
2736  has been added to message has been added to the message, and
2737  can hence be accounted for when the message is being
2738  freed. */
2739 #else
2740  ret = FALSE;
2741 #endif
2742  }
2743  else
2744  {
2745  ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
2746  }
2747 
2748  if (!_dbus_message_iter_close_signature (real))
2749  ret = FALSE;
2750 
2751  return ret;
2752 }
2753 
2791  int element_type,
2792  const void *value,
2793  int n_elements)
2794 {
2795  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2796  dbus_bool_t ret;
2797 
2798  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2799  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2800  _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
2801  _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
2802  _dbus_return_val_if_fail (value != NULL, FALSE);
2803  _dbus_return_val_if_fail (n_elements >= 0, FALSE);
2804  _dbus_return_val_if_fail (n_elements <=
2806  FALSE);
2807 
2808 #ifndef DBUS_DISABLE_CHECKS
2809  if (element_type == DBUS_TYPE_BOOLEAN)
2810  {
2811  const dbus_bool_t * const *bools = value;
2812  int i;
2813 
2814  for (i = 0; i < n_elements; i++)
2815  {
2816  _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
2817  }
2818  }
2819 #endif
2820 
2821  ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
2822 
2823  return ret;
2824 }
2825 
2849  int type,
2850  const char *contained_signature,
2851  DBusMessageIter *sub)
2852 {
2853  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2854  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2855  DBusString contained_str;
2856 
2857  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2858  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2859  _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
2860  _dbus_return_val_if_fail (sub != NULL, FALSE);
2861  _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
2862  contained_signature == NULL) ||
2863  (type == DBUS_TYPE_DICT_ENTRY &&
2864  contained_signature == NULL) ||
2865  (type == DBUS_TYPE_VARIANT &&
2866  contained_signature != NULL) ||
2867  (type == DBUS_TYPE_ARRAY &&
2868  contained_signature != NULL), FALSE);
2869 
2870  /* this would fail if the contained_signature is a dict entry, since
2871  * dict entries are invalid signatures standalone (they must be in
2872  * an array)
2873  */
2874  _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
2875  (contained_signature == NULL ||
2876  _dbus_check_is_valid_signature (contained_signature)),
2877  FALSE);
2878 
2879  if (!_dbus_message_iter_open_signature (real))
2880  return FALSE;
2881 
2882  *real_sub = *real;
2883 
2884  if (contained_signature != NULL)
2885  {
2886  _dbus_string_init_const (&contained_str, contained_signature);
2887 
2888  return _dbus_type_writer_recurse (&real->u.writer,
2889  type,
2890  &contained_str, 0,
2891  &real_sub->u.writer);
2892  }
2893  else
2894  {
2895  return _dbus_type_writer_recurse (&real->u.writer,
2896  type,
2897  NULL, 0,
2898  &real_sub->u.writer);
2899  }
2900 }
2901 
2902 
2918  DBusMessageIter *sub)
2919 {
2920  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2921  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2922  dbus_bool_t ret;
2923 
2924  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2925  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2926  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
2927  _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2928 
2929  ret = _dbus_type_writer_unrecurse (&real->u.writer,
2930  &real_sub->u.writer);
2931 
2932  if (!_dbus_message_iter_close_signature (real))
2933  ret = FALSE;
2934 
2935  return ret;
2936 }
2937 
2949 void
2951  DBusMessageIter *sub)
2952 {
2953  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2954 #ifndef DBUS_DISABLE_CHECKS
2955  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2956 
2957  _dbus_return_if_fail (_dbus_message_iter_append_check (real));
2958  _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2959  _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
2960  _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2961 #endif
2962 
2963  _dbus_message_iter_abandon_signature (real);
2964 }
2965 
2982 void
2984  dbus_bool_t no_reply)
2985 {
2986  _dbus_return_if_fail (message != NULL);
2987  _dbus_return_if_fail (!message->locked);
2988 
2989  _dbus_header_toggle_flag (&message->header,
2991  no_reply);
2992 }
2993 
3003 {
3004  _dbus_return_val_if_fail (message != NULL, FALSE);
3005 
3006  return _dbus_header_get_flag (&message->header,
3008 }
3009 
3024 void
3026  dbus_bool_t auto_start)
3027 {
3028  _dbus_return_if_fail (message != NULL);
3029  _dbus_return_if_fail (!message->locked);
3030 
3031  _dbus_header_toggle_flag (&message->header,
3033  !auto_start);
3034 }
3035 
3045 {
3046  _dbus_return_val_if_fail (message != NULL, FALSE);
3047 
3048  return !_dbus_header_get_flag (&message->header,
3050 }
3051 
3052 
3067  const char *object_path)
3068 {
3069  _dbus_return_val_if_fail (message != NULL, FALSE);
3070  _dbus_return_val_if_fail (!message->locked, FALSE);
3071  _dbus_return_val_if_fail (object_path == NULL ||
3072  _dbus_check_is_valid_path (object_path),
3073  FALSE);
3074 
3075  return set_or_delete_string_field (message,
3078  object_path);
3079 }
3080 
3094 const char*
3096 {
3097  const char *v;
3098 
3099  _dbus_return_val_if_fail (message != NULL, NULL);
3100 
3101  v = NULL; /* in case field doesn't exist */
3105  (void *) &v);
3106  return v;
3107 }
3108 
3120  const char *path)
3121 {
3122  const char *msg_path;
3123  msg_path = dbus_message_get_path (message);
3124 
3125  if (msg_path == NULL)
3126  {
3127  if (path == NULL)
3128  return TRUE;
3129  else
3130  return FALSE;
3131  }
3132 
3133  if (path == NULL)
3134  return FALSE;
3135 
3136  if (strcmp (msg_path, path) == 0)
3137  return TRUE;
3138 
3139  return FALSE;
3140 }
3141 
3164  char ***path)
3165 {
3166  const char *v;
3167 
3168  _dbus_return_val_if_fail (message != NULL, FALSE);
3169  _dbus_return_val_if_fail (path != NULL, FALSE);
3170 
3171  *path = NULL;
3172 
3173  v = dbus_message_get_path (message);
3174  if (v != NULL)
3175  {
3176  if (!_dbus_decompose_path (v, strlen (v),
3177  path, NULL))
3178  return FALSE;
3179  }
3180  return TRUE;
3181 }
3182 
3198  const char *iface)
3199 {
3200  _dbus_return_val_if_fail (message != NULL, FALSE);
3201  _dbus_return_val_if_fail (!message->locked, FALSE);
3202  _dbus_return_val_if_fail (iface == NULL ||
3203  _dbus_check_is_valid_interface (iface),
3204  FALSE);
3205 
3206  return set_or_delete_string_field (message,
3209  iface);
3210 }
3211 
3225 const char*
3227 {
3228  const char *v;
3229 
3230  _dbus_return_val_if_fail (message != NULL, NULL);
3231 
3232  v = NULL; /* in case field doesn't exist */
3236  (void *) &v);
3237  return v;
3238 }
3239 
3249  const char *iface)
3250 {
3251  const char *msg_interface;
3252  msg_interface = dbus_message_get_interface (message);
3253 
3254  if (msg_interface == NULL)
3255  {
3256  if (iface == NULL)
3257  return TRUE;
3258  else
3259  return FALSE;
3260  }
3261 
3262  if (iface == NULL)
3263  return FALSE;
3264 
3265  if (strcmp (msg_interface, iface) == 0)
3266  return TRUE;
3267 
3268  return FALSE;
3269 
3270 }
3271 
3286  const char *member)
3287 {
3288  _dbus_return_val_if_fail (message != NULL, FALSE);
3289  _dbus_return_val_if_fail (!message->locked, FALSE);
3290  _dbus_return_val_if_fail (member == NULL ||
3291  _dbus_check_is_valid_member (member),
3292  FALSE);
3293 
3294  return set_or_delete_string_field (message,
3297  member);
3298 }
3299 
3311 const char*
3313 {
3314  const char *v;
3315 
3316  _dbus_return_val_if_fail (message != NULL, NULL);
3317 
3318  v = NULL; /* in case field doesn't exist */
3322  (void *) &v);
3323  return v;
3324 }
3325 
3335  const char *member)
3336 {
3337  const char *msg_member;
3338  msg_member = dbus_message_get_member (message);
3339 
3340  if (msg_member == NULL)
3341  {
3342  if (member == NULL)
3343  return TRUE;
3344  else
3345  return FALSE;
3346  }
3347 
3348  if (member == NULL)
3349  return FALSE;
3350 
3351  if (strcmp (msg_member, member) == 0)
3352  return TRUE;
3353 
3354  return FALSE;
3355 
3356 }
3357 
3371  const char *error_name)
3372 {
3373  _dbus_return_val_if_fail (message != NULL, FALSE);
3374  _dbus_return_val_if_fail (!message->locked, FALSE);
3375  _dbus_return_val_if_fail (error_name == NULL ||
3376  _dbus_check_is_valid_error_name (error_name),
3377  FALSE);
3378 
3379  return set_or_delete_string_field (message,
3382  error_name);
3383 }
3384 
3395 const char*
3397 {
3398  const char *v;
3399 
3400  _dbus_return_val_if_fail (message != NULL, NULL);
3401 
3402  v = NULL; /* in case field doesn't exist */
3406  (void *) &v);
3407  return v;
3408 }
3409 
3425  const char *destination)
3426 {
3427  _dbus_return_val_if_fail (message != NULL, FALSE);
3428  _dbus_return_val_if_fail (!message->locked, FALSE);
3429  _dbus_return_val_if_fail (destination == NULL ||
3430  _dbus_check_is_valid_bus_name (destination),
3431  FALSE);
3432 
3433  return set_or_delete_string_field (message,
3436  destination);
3437 }
3438 
3448 const char*
3450 {
3451  const char *v;
3452 
3453  _dbus_return_val_if_fail (message != NULL, NULL);
3454 
3455  v = NULL; /* in case field doesn't exist */
3459  (void *) &v);
3460  return v;
3461 }
3462 
3479  const char *sender)
3480 {
3481  _dbus_return_val_if_fail (message != NULL, FALSE);
3482  _dbus_return_val_if_fail (!message->locked, FALSE);
3483  _dbus_return_val_if_fail (sender == NULL ||
3484  _dbus_check_is_valid_bus_name (sender),
3485  FALSE);
3486 
3487  return set_or_delete_string_field (message,
3490  sender);
3491 }
3492 
3508 const char*
3510 {
3511  const char *v;
3512 
3513  _dbus_return_val_if_fail (message != NULL, NULL);
3514 
3515  v = NULL; /* in case field doesn't exist */
3519  (void *) &v);
3520  return v;
3521 }
3522 
3541 const char*
3543 {
3544  const DBusString *type_str;
3545  int type_pos;
3546 
3547  _dbus_return_val_if_fail (message != NULL, NULL);
3548 
3549  get_const_signature (&message->header, &type_str, &type_pos);
3550 
3551  return _dbus_string_get_const_data_len (type_str, type_pos, 0);
3552 }
3553 
3554 static dbus_bool_t
3555 _dbus_message_has_type_interface_member (DBusMessage *message,
3556  int type,
3557  const char *iface,
3558  const char *member)
3559 {
3560  const char *n;
3561 
3562  _dbus_assert (message != NULL);
3563  _dbus_assert (iface != NULL);
3564  _dbus_assert (member != NULL);
3565 
3566  if (dbus_message_get_type (message) != type)
3567  return FALSE;
3568 
3569  /* Optimize by checking the short member name first
3570  * instead of the longer interface name
3571  */
3572 
3573  n = dbus_message_get_member (message);
3574 
3575  if (n && strcmp (n, member) == 0)
3576  {
3577  n = dbus_message_get_interface (message);
3578 
3579  if (n == NULL || strcmp (n, iface) == 0)
3580  return TRUE;
3581  }
3582 
3583  return FALSE;
3584 }
3585 
3602  const char *iface,
3603  const char *method)
3604 {
3605  _dbus_return_val_if_fail (message != NULL, FALSE);
3606  _dbus_return_val_if_fail (iface != NULL, FALSE);
3607  _dbus_return_val_if_fail (method != NULL, FALSE);
3608  /* don't check that interface/method are valid since it would be
3609  * expensive, and not catch many common errors
3610  */
3611 
3612  return _dbus_message_has_type_interface_member (message,
3614  iface, method);
3615 }
3616 
3630  const char *iface,
3631  const char *signal_name)
3632 {
3633  _dbus_return_val_if_fail (message != NULL, FALSE);
3634  _dbus_return_val_if_fail (iface != NULL, FALSE);
3635  _dbus_return_val_if_fail (signal_name != NULL, FALSE);
3636  /* don't check that interface/name are valid since it would be
3637  * expensive, and not catch many common errors
3638  */
3639 
3640  return _dbus_message_has_type_interface_member (message,
3642  iface, signal_name);
3643 }
3644 
3657  const char *error_name)
3658 {
3659  const char *n;
3660 
3661  _dbus_return_val_if_fail (message != NULL, FALSE);
3662  _dbus_return_val_if_fail (error_name != NULL, FALSE);
3663  /* don't check that error_name is valid since it would be expensive,
3664  * and not catch many common errors
3665  */
3666 
3668  return FALSE;
3669 
3670  n = dbus_message_get_error_name (message);
3671 
3672  if (n && strcmp (n, error_name) == 0)
3673  return TRUE;
3674  else
3675  return FALSE;
3676 }
3677 
3690  const char *name)
3691 {
3692  const char *s;
3693 
3694  _dbus_return_val_if_fail (message != NULL, FALSE);
3695  _dbus_return_val_if_fail (name != NULL, FALSE);
3696  /* don't check that name is valid since it would be expensive, and
3697  * not catch many common errors
3698  */
3699 
3700  s = dbus_message_get_destination (message);
3701 
3702  if (s && strcmp (s, name) == 0)
3703  return TRUE;
3704  else
3705  return FALSE;
3706 }
3707 
3725  const char *name)
3726 {
3727  const char *s;
3728 
3729  _dbus_return_val_if_fail (message != NULL, FALSE);
3730  _dbus_return_val_if_fail (name != NULL, FALSE);
3731  /* don't check that name is valid since it would be expensive, and
3732  * not catch many common errors
3733  */
3734 
3735  s = dbus_message_get_sender (message);
3736 
3737  if (s && strcmp (s, name) == 0)
3738  return TRUE;
3739  else
3740  return FALSE;
3741 }
3742 
3754  const char *signature)
3755 {
3756  const char *s;
3757 
3758  _dbus_return_val_if_fail (message != NULL, FALSE);
3759  _dbus_return_val_if_fail (signature != NULL, FALSE);
3760  /* don't check that signature is valid since it would be expensive,
3761  * and not catch many common errors
3762  */
3763 
3764  s = dbus_message_get_signature (message);
3765 
3766  if (s && strcmp (s, signature) == 0)
3767  return TRUE;
3768  else
3769  return FALSE;
3770 }
3771 
3796  DBusMessage *message)
3797 {
3798  const char *str;
3799 
3800  _dbus_return_val_if_fail (message != NULL, FALSE);
3801  _dbus_return_val_if_error_is_set (error, FALSE);
3802 
3804  return FALSE;
3805 
3806  str = NULL;
3807  dbus_message_get_args (message, NULL,
3808  DBUS_TYPE_STRING, &str,
3810 
3811  dbus_set_error (error, dbus_message_get_error_name (message),
3812  str ? "%s" : NULL, str);
3813 
3814  return TRUE;
3815 }
3816 
3825 {
3826 #ifdef HAVE_UNIX_FD_PASSING
3827  _dbus_assert(message);
3828 
3829  return message->n_unix_fds > 0;
3830 #else
3831  return FALSE;
3832 #endif
3833 }
3834 
3853 #define INITIAL_LOADER_DATA_LEN 32
3854 
3863 {
3864  DBusMessageLoader *loader;
3865 
3866  loader = dbus_new0 (DBusMessageLoader, 1);
3867  if (loader == NULL)
3868  return NULL;
3869 
3870  loader->refcount = 1;
3871 
3872  loader->corrupted = FALSE;
3873  loader->corruption_reason = DBUS_VALID;
3874 
3875  /* this can be configured by the app, but defaults to the protocol max */
3877 
3878  /* We set a very relatively conservative default here since due to how
3879  SCM_RIGHTS works we need to preallocate an fd array of the maximum
3880  number of unix fds we want to receive in advance. A
3881  try-and-reallocate loop is not possible. */
3882  loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
3883 
3884  if (!_dbus_string_init (&loader->data))
3885  {
3886  dbus_free (loader);
3887  return NULL;
3888  }
3889 
3890  /* preallocate the buffer for speed, ignore failure */
3892  _dbus_string_set_length (&loader->data, 0);
3893 
3894 #ifdef HAVE_UNIX_FD_PASSING
3895  loader->unix_fds = NULL;
3896  loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
3897  loader->unix_fds_outstanding = FALSE;
3898 #endif
3899 
3900  return loader;
3901 }
3902 
3911 {
3912  loader->refcount += 1;
3913 
3914  return loader;
3915 }
3916 
3923 void
3925 {
3926  loader->refcount -= 1;
3927  if (loader->refcount == 0)
3928  {
3929 #ifdef HAVE_UNIX_FD_PASSING
3930  close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
3931  dbus_free(loader->unix_fds);
3932 #endif
3933  _dbus_list_foreach (&loader->messages,
3935  NULL);
3936  _dbus_list_clear (&loader->messages);
3937  _dbus_string_free (&loader->data);
3938  dbus_free (loader);
3939  }
3940 }
3941 
3960 void
3962  DBusString **buffer)
3963 {
3964  _dbus_assert (!loader->buffer_outstanding);
3965 
3966  *buffer = &loader->data;
3967 
3968  loader->buffer_outstanding = TRUE;
3969 }
3970 
3980 void
3982  DBusString *buffer)
3983 {
3984  _dbus_assert (loader->buffer_outstanding);
3985  _dbus_assert (buffer == &loader->data);
3986 
3987  loader->buffer_outstanding = FALSE;
3988 }
3989 
4002  int **fds,
4003  unsigned *max_n_fds)
4004 {
4005 #ifdef HAVE_UNIX_FD_PASSING
4006  _dbus_assert (!loader->unix_fds_outstanding);
4007 
4008  /* Allocate space where we can put the fds we read. We allocate
4009  space for max_message_unix_fds since this is an
4010  upper limit how many fds can be received within a single
4011  message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
4012  we are allocating the maximum possible array size right from the
4013  beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
4014  there is no better way. */
4015 
4016  if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
4017  {
4018  int *a = dbus_realloc(loader->unix_fds,
4019  loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
4020 
4021  if (!a)
4022  return FALSE;
4023 
4024  loader->unix_fds = a;
4025  loader->n_unix_fds_allocated = loader->max_message_unix_fds;
4026  }
4027 
4028  *fds = loader->unix_fds + loader->n_unix_fds;
4029  *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
4030 
4031  loader->unix_fds_outstanding = TRUE;
4032  return TRUE;
4033 #else
4034  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
4035  return FALSE;
4036 #endif
4037 }
4038 
4049 void
4051  int *fds,
4052  unsigned n_fds)
4053 {
4054 #ifdef HAVE_UNIX_FD_PASSING
4055  _dbus_assert(loader->unix_fds_outstanding);
4056  _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
4057  _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
4058 
4059  loader->n_unix_fds += n_fds;
4060  loader->unix_fds_outstanding = FALSE;
4061 #else
4062  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
4063 #endif
4064 }
4065 
4066 /*
4067  * FIXME when we move the header out of the buffer, that memmoves all
4068  * buffered messages. Kind of crappy.
4069  *
4070  * Also we copy the header and body, which is kind of crappy. To
4071  * avoid this, we have to allow header and body to be in a single
4072  * memory block, which is good for messages we read and bad for
4073  * messages we are creating. But we could move_len() the buffer into
4074  * this single memory block, and move_len() will just swap the buffers
4075  * if you're moving the entire buffer replacing the dest string.
4076  *
4077  * We could also have the message loader tell the transport how many
4078  * bytes to read; so it would first ask for some arbitrary number like
4079  * 256, then if the message was incomplete it would use the
4080  * header/body len to ask for exactly the size of the message (or
4081  * blocks the size of a typical kernel buffer for the socket). That
4082  * way we don't get trailing bytes in the buffer that have to be
4083  * memmoved. Though I suppose we also don't have a chance of reading a
4084  * bunch of small messages at once, so the optimization may be stupid.
4085  *
4086  * Another approach would be to keep a "start" index into
4087  * loader->data and only delete it occasionally, instead of after
4088  * each message is loaded.
4089  *
4090  * load_message() returns FALSE if not enough memory OR the loader was corrupted
4091  */
4092 static dbus_bool_t
4093 load_message (DBusMessageLoader *loader,
4094  DBusMessage *message,
4095  int byte_order,
4096  int fields_array_len,
4097  int header_len,
4098  int body_len)
4099 {
4100  dbus_bool_t oom;
4101  DBusValidity validity;
4102  const DBusString *type_str;
4103  int type_pos;
4104  DBusValidationMode mode;
4105  dbus_uint32_t n_unix_fds = 0;
4106 
4107  mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
4108 
4109  oom = FALSE;
4110 
4111 #if 0
4112  _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
4113 #endif
4114 
4115  /* 1. VALIDATE AND COPY OVER HEADER */
4116  _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
4117  _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
4118 
4119  if (!_dbus_header_load (&message->header,
4120  mode,
4121  &validity,
4122  byte_order,
4123  fields_array_len,
4124  header_len,
4125  body_len,
4126  &loader->data, 0,
4127  _dbus_string_get_length (&loader->data)))
4128  {
4129  _dbus_verbose ("Failed to load header for new message code %d\n", validity);
4130 
4131  /* assert here so we can catch any code that still uses DBUS_VALID to indicate
4132  oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
4133  _dbus_assert (validity != DBUS_VALID);
4134 
4135  if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
4136  oom = TRUE;
4137  else
4138  {
4139  loader->corrupted = TRUE;
4140  loader->corruption_reason = validity;
4141  }
4142  goto failed;
4143  }
4144 
4145  _dbus_assert (validity == DBUS_VALID);
4146 
4147  /* 2. VALIDATE BODY */
4148  if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
4149  {
4150  get_const_signature (&message->header, &type_str, &type_pos);
4151 
4152  /* Because the bytes_remaining arg is NULL, this validates that the
4153  * body is the right length
4154  */
4155  validity = _dbus_validate_body_with_reason (type_str,
4156  type_pos,
4157  byte_order,
4158  NULL,
4159  &loader->data,
4160  header_len,
4161  body_len);
4162  if (validity != DBUS_VALID)
4163  {
4164  _dbus_verbose ("Failed to validate message body code %d\n", validity);
4165 
4166  loader->corrupted = TRUE;
4167  loader->corruption_reason = validity;
4168 
4169  goto failed;
4170  }
4171  }
4172 
4173  /* 3. COPY OVER UNIX FDS */
4177  &n_unix_fds);
4178 
4179 #ifdef HAVE_UNIX_FD_PASSING
4180 
4181  if (n_unix_fds > loader->n_unix_fds)
4182  {
4183  _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
4184  n_unix_fds, loader->n_unix_fds);
4185 
4186  loader->corrupted = TRUE;
4187  loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4188  goto failed;
4189  }
4190 
4191  /* If this was a recycled message there might still be
4192  some memory allocated for the fds */
4193  dbus_free(message->unix_fds);
4194 
4195  if (n_unix_fds > 0)
4196  {
4197  message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
4198  if (message->unix_fds == NULL)
4199  {
4200  _dbus_verbose ("Failed to allocate file descriptor array\n");
4201  oom = TRUE;
4202  goto failed;
4203  }
4204 
4205  message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
4206  loader->n_unix_fds -= n_unix_fds;
4207  memmove(loader->unix_fds + n_unix_fds, loader->unix_fds, loader->n_unix_fds);
4208  }
4209  else
4210  message->unix_fds = NULL;
4211 
4212 #else
4213 
4214  if (n_unix_fds > 0)
4215  {
4216  _dbus_verbose ("Hmm, message claims to come with file descriptors "
4217  "but that's not supported on our platform, disconnecting.\n");
4218 
4219  loader->corrupted = TRUE;
4220  loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4221  goto failed;
4222  }
4223 
4224 #endif
4225 
4226  /* 3. COPY OVER BODY AND QUEUE MESSAGE */
4227 
4228  if (!_dbus_list_append (&loader->messages, message))
4229  {
4230  _dbus_verbose ("Failed to append new message to loader queue\n");
4231  oom = TRUE;
4232  goto failed;
4233  }
4234 
4235  _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4236  _dbus_assert (_dbus_string_get_length (&loader->data) >=
4237  (header_len + body_len));
4238 
4239  if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
4240  {
4241  _dbus_verbose ("Failed to move body into new message\n");
4242  oom = TRUE;
4243  goto failed;
4244  }
4245 
4246  _dbus_string_delete (&loader->data, 0, header_len + body_len);
4247 
4248  /* don't waste more than 2k of memory */
4249  _dbus_string_compact (&loader->data, 2048);
4250 
4251  _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
4252  _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4253 
4254  _dbus_verbose ("Loaded message %p\n", message);
4255 
4256  _dbus_assert (!oom);
4257  _dbus_assert (!loader->corrupted);
4258  _dbus_assert (loader->messages != NULL);
4259  _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4260 
4261  return TRUE;
4262 
4263  failed:
4264 
4265  /* Clean up */
4266 
4267  /* does nothing if the message isn't in the list */
4268  _dbus_list_remove_last (&loader->messages, message);
4269 
4270  if (oom)
4271  _dbus_assert (!loader->corrupted);
4272  else
4273  _dbus_assert (loader->corrupted);
4274 
4275  _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
4276 
4277  return FALSE;
4278 }
4279 
4296 {
4297  while (!loader->corrupted &&
4298  _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
4299  {
4300  DBusValidity validity;
4301  int byte_order, fields_array_len, header_len, body_len;
4302 
4304  &validity,
4305  &byte_order,
4306  &fields_array_len,
4307  &header_len,
4308  &body_len,
4309  &loader->data, 0,
4310  _dbus_string_get_length (&loader->data)))
4311  {
4312  DBusMessage *message;
4313 
4314  _dbus_assert (validity == DBUS_VALID);
4315 
4316  message = dbus_message_new_empty_header ();
4317  if (message == NULL)
4318  return FALSE;
4319 
4320  if (!load_message (loader, message,
4321  byte_order, fields_array_len,
4322  header_len, body_len))
4323  {
4324  dbus_message_unref (message);
4325  /* load_message() returns false if corrupted or OOM; if
4326  * corrupted then return TRUE for not OOM
4327  */
4328  return loader->corrupted;
4329  }
4330 
4331  _dbus_assert (loader->messages != NULL);
4332  _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4333  }
4334  else
4335  {
4336  _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
4337  validity);
4338  if (validity != DBUS_VALID)
4339  {
4340  loader->corrupted = TRUE;
4341  loader->corruption_reason = validity;
4342  }
4343  return TRUE;
4344  }
4345  }
4346 
4347  return TRUE;
4348 }
4349 
4357 DBusMessage*
4359 {
4360  if (loader->messages)
4361  return loader->messages->data;
4362  else
4363  return NULL;
4364 }
4365 
4374 DBusMessage*
4376 {
4377  return _dbus_list_pop_first (&loader->messages);
4378 }
4379 
4388 DBusList*
4390 {
4391  return _dbus_list_pop_first_link (&loader->messages);
4392 }
4393 
4400 void
4402  DBusList *link)
4403 {
4404  _dbus_list_prepend_link (&loader->messages, link);
4405 }
4406 
4418 {
4419  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4420  (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4421  return loader->corrupted;
4422 }
4423 
4432 {
4433  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4434  (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4435 
4436  return loader->corruption_reason;
4437 }
4438 
4445 void
4447  long size)
4448 {
4449  if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
4450  {
4451  _dbus_verbose ("clamping requested max message size %ld to %d\n",
4454  }
4455  loader->max_message_size = size;
4456 }
4457 
4464 long
4466 {
4467  return loader->max_message_size;
4468 }
4469 
4476 void
4478  long n)
4479 {
4481  {
4482  _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
4485  }
4486  loader->max_message_unix_fds = n;
4487 }
4488 
4495 long
4497 {
4498  return loader->max_message_unix_fds;
4499 }
4500 
4501 static DBusDataSlotAllocator slot_allocator =
4502  _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
4503 
4519 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
4520 {
4521  return _dbus_data_slot_allocator_alloc (&slot_allocator,
4522  slot_p);
4523 }
4524 
4536 void
4537 dbus_message_free_data_slot (dbus_int32_t *slot_p)
4538 {
4539  _dbus_return_if_fail (*slot_p >= 0);
4540 
4541  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
4542 }
4543 
4559  dbus_int32_t slot,
4560  void *data,
4561  DBusFreeFunction free_data_func)
4562 {
4563  DBusFreeFunction old_free_func;
4564  void *old_data;
4565  dbus_bool_t retval;
4566 
4567  _dbus_return_val_if_fail (message != NULL, FALSE);
4568  _dbus_return_val_if_fail (slot >= 0, FALSE);
4569 
4570  retval = _dbus_data_slot_list_set (&slot_allocator,
4571  &message->slot_list,
4572  slot, data, free_data_func,
4573  &old_free_func, &old_data);
4574 
4575  if (retval)
4576  {
4577  /* Do the actual free outside the message lock */
4578  if (old_free_func)
4579  (* old_free_func) (old_data);
4580  }
4581 
4582  return retval;
4583 }
4584 
4593 void*
4595  dbus_int32_t slot)
4596 {
4597  void *res;
4598 
4599  _dbus_return_val_if_fail (message != NULL, NULL);
4600 
4601  res = _dbus_data_slot_list_get (&slot_allocator,
4602  &message->slot_list,
4603  slot);
4604 
4605  return res;
4606 }
4607 
4621 int
4622 dbus_message_type_from_string (const char *type_str)
4623 {
4624  if (strcmp (type_str, "method_call") == 0)
4626  if (strcmp (type_str, "method_return") == 0)
4628  else if (strcmp (type_str, "signal") == 0)
4629  return DBUS_MESSAGE_TYPE_SIGNAL;
4630  else if (strcmp (type_str, "error") == 0)
4631  return DBUS_MESSAGE_TYPE_ERROR;
4632  else
4634 }
4635 
4649 const char *
4651 {
4652  switch (type)
4653  {
4655  return "method_call";
4657  return "method_return";
4659  return "signal";
4661  return "error";
4662  default:
4663  return "invalid";
4664  }
4665 }
4666 
4681  char **marshalled_data_p,
4682  int *len_p)
4683 {
4684  DBusString tmp;
4685  dbus_bool_t was_locked;
4686 
4687  _dbus_return_val_if_fail (msg != NULL, FALSE);
4688  _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
4689  _dbus_return_val_if_fail (len_p != NULL, FALSE);
4690 
4691  if (!_dbus_string_init (&tmp))
4692  return FALSE;
4693 
4694  /* Ensure the message is locked, to ensure the length header is filled in. */
4695  was_locked = msg->locked;
4696 
4697  if (!was_locked)
4698  dbus_message_lock (msg);
4699 
4700  if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
4701  goto fail;
4702 
4703  *len_p = _dbus_string_get_length (&tmp);
4704 
4705  if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
4706  goto fail;
4707 
4708  *len_p = _dbus_string_get_length (&tmp);
4709 
4710  if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
4711  goto fail;
4712 
4713  _dbus_string_free (&tmp);
4714 
4715  if (!was_locked)
4716  msg->locked = FALSE;
4717 
4718  return TRUE;
4719 
4720  fail:
4721  _dbus_string_free (&tmp);
4722 
4723  if (!was_locked)
4724  msg->locked = FALSE;
4725 
4726  return FALSE;
4727 }
4728 
4741 DBusMessage *
4742 dbus_message_demarshal (const char *str,
4743  int len,
4744  DBusError *error)
4745 {
4746  DBusMessageLoader *loader;
4747  DBusString *buffer;
4748  DBusMessage *msg;
4749 
4750  _dbus_return_val_if_fail (str != NULL, NULL);
4751 
4752  loader = _dbus_message_loader_new ();
4753 
4754  if (loader == NULL)
4755  return NULL;
4756 
4757  _dbus_message_loader_get_buffer (loader, &buffer);
4758  _dbus_string_append_len (buffer, str, len);
4759  _dbus_message_loader_return_buffer (loader, buffer);
4760 
4762  goto fail_oom;
4763 
4765  goto fail_corrupt;
4766 
4767  msg = _dbus_message_loader_pop_message (loader);
4768 
4769  if (!msg)
4770  goto fail_oom;
4771 
4772  _dbus_message_loader_unref (loader);
4773  return msg;
4774 
4775  fail_corrupt:
4776  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
4777  _dbus_validity_to_error_message (loader->corruption_reason));
4778  _dbus_message_loader_unref (loader);
4779  return NULL;
4780 
4781  fail_oom:
4782  _DBUS_SET_OOM (error);
4783  _dbus_message_loader_unref (loader);
4784  return NULL;
4785 }
4786 
4799 int
4801  int len)
4802 {
4803  DBusString str;
4804  int byte_order, fields_array_len, header_len, body_len;
4805  DBusValidity validity = DBUS_VALID;
4806  int have_message;
4807 
4808  if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
4809  return 0;
4810 
4811  if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
4813  _dbus_string_init_const_len (&str, buf, len);
4814 
4815  validity = DBUS_VALID;
4816  have_message
4818  &validity, &byte_order,
4819  &fields_array_len,
4820  &header_len,
4821  &body_len,
4822  &str, 0,
4823  len);
4824  _dbus_string_free (&str);
4825 
4826  if (validity == DBUS_VALID)
4827  {
4828  _dbus_assert (have_message || (header_len + body_len) > len);
4829  (void) have_message; /* unused unless asserting */
4830  return header_len + body_len;
4831  }
4832  else
4833  {
4834  return -1; /* broken! */
4835  }
4836 }
4837 
4840 /* tests in dbus-message-util.c */