D-Bus  1.8.4
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 {
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  DBUS_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 
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 
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,
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);
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 
4276 
4277  return FALSE;
4278 }
4279 
4296 {
4297  while (!loader->corrupted &&
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 
4520 {
4521  return _dbus_data_slot_allocator_alloc (&slot_allocator,
4522  slot_p);
4523 }
4524 
4536 void
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 */
dbus_bool_t dbus_type_is_fixed(int typecode)
Tells you whether values of this type can change length if you set them to some other value...
void _dbus_type_reader_read_fixed_multi(const DBusTypeReader *reader, void *value, int *n_elements)
Reads a block of fixed-length basic values, from the current point in an array to the end of the arra...
int dbus_message_type_from_string(const char *type_str)
Utility function to convert a machine-readable (not translated) string into a D-Bus message type...
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
DBusMessage * dbus_message_ref(DBusMessage *message)
Increments the reference count of a DBusMessage.
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition: dbus-message.c:383
const char * message
public error message field
Definition: dbus-errors.h:51
dbus_bool_t dbus_message_has_path(DBusMessage *message, const char *path)
Checks if the message has a particular object path.
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
dbus_uint32_t changed_stamp
Incremented when iterators are invalidated.
#define NULL
A null pointer, defined appropriately for C or C++.
dbus_bool_t dbus_message_is_method_call(DBusMessage *message, const char *iface, const char *method)
Checks whether the message is a method call with the given interface and member fields.
dbus_bool_t _dbus_header_load(DBusHeader *header, DBusValidationMode mode, DBusValidity *validity, int byte_order, int fields_array_len, int header_len, int body_len, const DBusString *str, int start, int len)
Creates a message header from potentially-untrusted data.
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition: dbus-memory.h:64
long _dbus_message_loader_get_max_message_size(DBusMessageLoader *loader)
Gets the maximum allowed message size in bytes.
void dbus_message_set_no_reply(DBusMessage *message, dbus_bool_t no_reply)
Sets a flag indicating that the message does not want a reply; if this flag is set, the other end of the connection may (but is not required to) optimize by not sending method return or error replies.
void _dbus_message_loader_putback_message_link(DBusMessageLoader *loader, DBusList *link)
Returns a popped message link, used to undo a pop.
dbus_bool_t _dbus_header_copy(const DBusHeader *header, DBusHeader *dest)
Initializes dest with a copy of the given header.
int dbus_message_iter_get_arg_type(DBusMessageIter *iter)
Returns the argument type of the argument that the message iterator points to.
dbus_uint32_t sig_refcount
depth of open_signature()
Definition: dbus-message.c:130
void _dbus_message_loader_return_buffer(DBusMessageLoader *loader, DBusString *buffer)
Returns a buffer obtained from _dbus_message_loader_get_buffer(), indicating to the loader how many b...
void _dbus_type_writer_remove_types(DBusTypeWriter *writer)
Removes type string from the writer.
void * dbus_realloc(void *memory, size_t bytes)
Resizes a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:601
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:701
void _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader, int *fds, unsigned n_fds)
Returns a buffer obtained from _dbus_message_loader_get_unix_fds().
dbus_uint32_t dbus_message_get_serial(DBusMessage *message)
Returns the serial of a message or 0 if none has been specified.
DBusList * messages
Complete messages.
The type writer is an iterator for writing to a block of values.
void dbus_message_iter_recurse(DBusMessageIter *iter, DBusMessageIter *sub)
Recurses into a container value when reading values from a message, initializing a sub-iterator to us...
void _dbus_type_reader_recurse(DBusTypeReader *reader, DBusTypeReader *sub)
Initialize a new reader pointing to the first type and corresponding value that's a child of the curr...
DBusMessage * _dbus_message_loader_pop_message(DBusMessageLoader *loader)
Pops a loaded message (passing ownership of the message to the caller).
DBusList * _dbus_list_find_last(DBusList **list, void *data)
Finds a value in the list.
Definition: dbus-list.c:472
dbus_bool_t dbus_message_set_interface(DBusMessage *message, const char *iface)
Sets the interface this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or the interface...
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn't supported (like ENOSYS on UNIX).
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:58
void dbus_message_free_data_slot(dbus_int32_t *slot_p)
Deallocates a global ID for message data slots.
#define DBUS_HEADER_FIELD_SIGNATURE
Header field code for the type signature of a message.
const char * dbus_message_get_error_name(DBusMessage *message)
Gets the error name (DBUS_MESSAGE_TYPE_ERROR only) or NULL if none.
dbus_bool_t dbus_message_iter_close_container(DBusMessageIter *iter, DBusMessageIter *sub)
Closes a container-typed value appended to the message; may write out more information to the message...
dbus_bool_t dbus_message_is_error(DBusMessage *message, const char *error_name)
Checks whether the message is an error reply with the given error name.
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition: dbus-list.c:527
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string...
#define DBUS_TYPE_DICT_ENTRY
Type code used to represent a dict entry; however, this type code does not appear in type signatures...
const char * dbus_message_get_sender(DBusMessage *message)
Gets the unique name of the connection which originated this message, or NULL if unknown or inapplica...
dbus_bool_t _dbus_message_iter_get_args_valist(DBusMessageIter *iter, DBusError *error, int first_arg_type, va_list var_args)
Implementation of the varargs arg-getting functions.
Definition: dbus-message.c:795
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
DBusString body
Body network data.
dbus_uint32_t _dbus_header_get_serial(DBusHeader *header)
See dbus_message_get_serial()
dbus_bool_t _dbus_header_get_flag(DBusHeader *header, dbus_uint32_t flag)
Gets a message flag bit, returning TRUE if the bit is set.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define DBUS_HEADER_FLAG_NO_REPLY_EXPECTED
If set, this flag means that the sender of a message does not care about getting a reply...
void _dbus_list_append_link(DBusList **list, DBusList *link)
Appends a link to the list.
Definition: dbus-list.c:315
Internals of DBusCounter.
dbus_bool_t dbus_message_allocate_data_slot(dbus_int32_t *slot_p)
Allocates an integer ID to be used for storing application-specific data on any DBusMessage.
void * data
Data stored at this element.
Definition: dbus-list.h:38
#define MAX_MESSAGE_CACHE_SIZE
Avoid caching too many messages.
Definition: dbus-message.c:507
DBusMessage * dbus_message_new(int message_type)
Constructs a new message of the given message type.
#define DBUS_ERROR_INCONSISTENT_MESSAGE
The message meta data does not match the payload.
dbus_bool_t _dbus_header_init(DBusHeader *header)
Initializes a header, but doesn't prepare it for use; to make the header valid, you have to call _dbu...
void _dbus_warn_check_failed(const char *format,...)
Prints a "critical" warning to stderr when an assertion fails; differs from _dbus_warn primarily in t...
const char * dbus_message_get_signature(DBusMessage *message)
Gets the type signature of the message, i.e.
void dbus_message_iter_init_append(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for appending arguments to the end of a message.
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
void dbus_message_set_auto_start(DBusMessage *message, dbus_bool_t auto_start)
Sets a flag indicating that an owner for the destination name will be automatically started before th...
union DBusMessageRealIter::@6 u
the type writer or reader that does all the work
void _dbus_message_loader_unref(DBusMessageLoader *loader)
Decrements the reference count of the loader and finalizes the loader when the count reaches zero...
DBusCounter * _dbus_counter_ref(DBusCounter *counter)
Increments refcount of the counter.
DBusString data
Header network data, stored separately from body so we can independently realloc it.
unsigned char _dbus_string_get_byte(const DBusString *str, int start)
Gets the byte at the given position.
Definition: dbus-string.c:545
dbus_bool_t dbus_message_has_interface(DBusMessage *message, const char *iface)
Checks if the message has an interface.
int _dbus_dup(int fd, DBusError *error)
Duplicates a file descriptor.
DBusValidity _dbus_message_loader_get_corruption_reason(DBusMessageLoader *loader)
Checks what kind of bad data confused the loader.
dbus_bool_t _dbus_type_writer_write_basic(DBusTypeWriter *writer, int type, const void *value)
Writes out a basic type.
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type()
DBusList * _dbus_list_alloc_link(void *data)
Allocates a linked list node.
Definition: dbus-list.c:242
#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS
The maximum total number of unix fds in a message.
const char * dbus_message_get_path(DBusMessage *message)
Gets the object path this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitt...
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:175
#define DBUS_MESSAGE_TYPE_METHOD_RETURN
Message type of a method return message, see dbus_message_get_type()
DBusMessage * dbus_message_new_signal(const char *path, const char *iface, const char *name)
Constructs a new message representing a signal emission.
dbus_bool_t _dbus_string_append_printf_valist(DBusString *str, const char *format, va_list args)
Appends a printf-style formatted string to the DBusString.
Definition: dbus-string.c:1055
DBusTypeReader reader
reader
Definition: dbus-message.c:134
DBusValidationMode
This is used rather than a bool for high visibility.
dbus_bool_t dbus_message_iter_has_next(DBusMessageIter *iter)
Checks if an iterator has any more fields.
DBusMessage * message
Message used.
Definition: dbus-message.c:127
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1265
#define DBUS_HEADER_FIELD_INTERFACE
Header field code for the interface containing a member (method or signal).
#define DBUS_DICT_ENTRY_BEGIN_CHAR
Code marking the start of a dict entry type in a type signature.
DBusList * _dbus_list_pop_first_link(DBusList **list)
Removes the first link in the list and returns it.
Definition: dbus-list.c:628
dbus_bool_t dbus_message_has_member(DBusMessage *message, const char *member)
Checks if the message has an interface member.
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
DBusMessageIter struct; contains no public fields.
Definition: dbus-message.h:51
dbus_bool_t dbus_message_iter_init(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for reading the arguments of the message passed in. ...
dbus_bool_t _dbus_message_add_counter(DBusMessage *message, DBusCounter *counter)
Adds a counter to be incremented immediately with the size/unix fds of this message, and decremented by the size/unix fds of this message when this message if finalized.
Definition: dbus-message.c:328
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:185
const char * dbus_message_get_destination(DBusMessage *message)
Gets the destination of a message or NULL if there is none set.
void _dbus_message_add_counter_link(DBusMessage *message, DBusList *link)
Adds a counter to be incremented immediately with the size/unix fds of this message, and decremented by the size/unix fds of this message when this message if finalized.
Definition: dbus-message.c:279
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
DBusString * type_str
where to write typecodes (or read type expectations)
dbus_bool_t dbus_message_iter_append_fixed_array(DBusMessageIter *iter, int element_type, const void *value, int n_elements)
Appends a block of fixed-length values to an array.
dbus_bool_t dbus_message_set_error_name(DBusMessage *message, const char *error_name)
Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
const char * dbus_message_get_member(DBusMessage *message)
Gets the interface member being invoked (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted (DBUS_MESSAGE_TYPE...
dbus_bool_t _dbus_list_remove_last(DBusList **list, void *data)
Removes a value from the list.
Definition: dbus-list.c:446
Internals of DBusMessage.
Internals of DBusMessageIter.
Definition: dbus-message.c:125
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:59
dbus_uint32_t changed_stamp
stamp to detect invalid iters
Definition: dbus-message.c:128
void _dbus_type_writer_init_types_delayed(DBusTypeWriter *writer, int byte_order, DBusString *value_str, int value_pos)
Initialize a write iterator, with the signature to be provided later.
dbus_bool_t _dbus_string_compact(DBusString *str, int max_waste)
Compacts the string to avoid wasted memory.
Definition: dbus-string.c:372
int _dbus_header_get_message_type(DBusHeader *header)
Gets the type of the message.
#define DBUS_HEADER_FIELD_ERROR_NAME
Header field code for an error name (found in DBUS_MESSAGE_TYPE_ERROR messages).
#define DBUS_MINIMUM_HEADER_SIZE
The smallest header size that can occur.
dbus_bool_t _dbus_type_writer_unrecurse(DBusTypeWriter *writer, DBusTypeWriter *sub)
Closes a container created by _dbus_type_writer_recurse() and writes any additional information to th...
dbus_bool_t dbus_type_is_basic(int typecode)
A "basic type" is a somewhat arbitrary concept, but the intent is to include those types that are ful...
void _dbus_message_loader_set_max_message_size(DBusMessageLoader *loader, long size)
Sets the maximum size message we allow.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:190
DBusHeader header
Header network data and associated cache.
dbus_bool_t dbus_message_set_sender(DBusMessage *message, const char *sender)
Sets the message sender.
dbus_bool_t dbus_message_is_signal(DBusMessage *message, const char *iface, const char *signal_name)
Checks whether the message is a signal with the given interface and member fields.
DBusString data
Buffered data.
void _dbus_type_reader_read_basic(const DBusTypeReader *reader, void *value)
Reads a basic-typed value, as with _dbus_marshal_read_basic().
unsigned int locked
Message being sent, no modifications allowed.
#define ensure_byte_order(message)
byte-swap the message if it doesn't match our byte order.
Definition: dbus-message.c:194
DBusMessageLoader * _dbus_message_loader_ref(DBusMessageLoader *loader)
Increments the reference count of the loader.
dbus_bool_t _dbus_header_get_field_basic(DBusHeader *header, int field, int type, void *value)
Gets the value of a field with basic type.
dbus_bool_t dbus_message_get_path_decomposed(DBusMessage *message, char ***path)
Gets the object path this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitt...
can't determine validity due to OOM
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
Definition: dbus-string.c:1175
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc...
Definition: dbus-string.c:132
void _dbus_counter_unref(DBusCounter *counter)
Decrements refcount of the counter and possibly finalizes the counter.
void _dbus_message_remove_counter(DBusMessage *message, DBusCounter *counter)
Removes a counter tracking the size/unix fds of this message, and decrements the counter by the size/...
Definition: dbus-message.c:351
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:270
dbus_bool_t _dbus_decompose_path(const char *data, int len, char ***path, int *path_len)
Decompose an object path.
void * _dbus_memdup(const void *mem, size_t n_bytes)
Duplicates a block of memory.
dbus_bool_t _dbus_data_slot_list_set(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot, void *data, DBusFreeFunction free_data_func, DBusFreeFunction *old_free_func, void **old_data)
Stores a pointer in the data slot list, along with an optional function to be used for freeing the da...
dbus_bool_t dbus_message_set_path(DBusMessage *message, const char *object_path)
Sets the object path this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or the one a s...
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition: dbus-list.c:759
long max_message_size
Maximum size of a message.
void _dbus_counter_adjust_unix_fd(DBusCounter *counter, long delta)
Adjusts the value of the unix fd counter by the given delta which may be positive or negative...
int _dbus_string_get_length(const DBusString *str)
Gets the length of a string (not including nul termination).
Definition: dbus-string.c:722
dbus_bool_t _dbus_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
DBusList * counters
0-N DBusCounter used to track message size/unix fds.
DBusMessageLoader * _dbus_message_loader_new(void)
Creates a new message loader.
long size_counter_delta
Size we incremented the size counters by.
#define CHANGED_STAMP_BITS
How many bits are in the changed_stamp used to validate iterators.
void _dbus_header_byteswap(DBusHeader *header, int new_order)
Swaps the header into the given order if required.
dbus_bool_t _dbus_header_have_message_untrusted(int max_message_length, DBusValidity *validity, int *byte_order, int *fields_array_len, int *header_len, int *body_len, const DBusString *str, int start, int len)
Given data long enough to contain the length of the message body and the fields array, check whether the data is long enough to contain the entire message (assuming the claimed lengths are accurate).
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type()
#define DBUS_HEADER_FIELD_UNIX_FDS
Header field code for the number of unix file descriptors associated with this message.
int _dbus_current_generation
_dbus_current_generation is used to track each time that dbus_shutdown() is called, so we can reinit things after it's been called.
Definition: dbus-memory.c:781
dbus_bool_t dbus_message_get_args(DBusMessage *message, DBusError *error, int first_arg_type,...)
Gets arguments from a message given a variable argument list.
Object representing an exception.
Definition: dbus-errors.h:48
unsigned int in_cache
Has been "freed" since it's in the cache (this is a debug feature)
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:649
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
dbus_bool_t dbus_message_append_args(DBusMessage *message, int first_arg_type,...)
Appends fields to a message given a variable argument list.
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type()
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
dbus_uint32_t dbus_message_get_reply_serial(DBusMessage *message)
Returns the serial that the message is a reply to or 0 if none.
#define INITIAL_LOADER_DATA_LEN
The initial buffer size of the message loader.
dbus_bool_t dbus_message_has_signature(DBusMessage *message, const char *signature)
Checks whether the message has the given signature; see dbus_message_get_signature() for more details...
void _dbus_data_slot_list_clear(DBusDataSlotList *list)
Frees all data slots contained in the list, calling application-provided free functions if they exist...
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
dbus_bool_t _dbus_message_loader_get_is_corrupted(DBusMessageLoader *loader)
Checks whether the loader is confused due to bad data.
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition: dbus-protocol.h:86
DBusValidity _dbus_validate_body_with_reason(const DBusString *expected_signature, int expected_signature_start, int byte_order, int *bytes_remaining, const DBusString *value_str, int value_pos, int len)
Verifies that the range of value_str from value_pos to value_end is a legitimate value of type expect...
void _dbus_header_reinit(DBusHeader *header)
Re-initializes a header that was previously initialized and never freed.
the data is valid
DBusMessage * dbus_message_new_method_call(const char *destination, const char *path, const char *iface, const char *method)
Constructs a new message to invoke a method on a remote object.
#define DBUS_HEADER_FIELD_DESTINATION
Header field code for the destination bus name of a message.
dbus_uint32_t byte_order
byte order of the block
dbus_bool_t _dbus_header_delete_field(DBusHeader *header, int field)
Deletes a field, if it exists.
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
dbus_bool_t dbus_message_has_destination(DBusMessage *message, const char *name)
Checks whether the message was sent to the given name.
#define DBUS_MESSAGE_TYPE_INVALID
This value is never a valid message type, see dbus_message_get_type()
dbus_bool_t dbus_message_get_auto_start(DBusMessage *message)
Returns TRUE if the message will cause an owner for destination name to be auto-started.
dbus_uint32_t byte_order
byte order to write values with
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:242
The type reader is an iterator for reading values from a block of values.
void * _dbus_data_slot_list_get(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot)
Retrieves data previously set with _dbus_data_slot_list_set_data().
long _dbus_message_loader_get_max_message_unix_fds(DBusMessageLoader *loader)
Gets the maximum allowed number of unix fds per message.
#define TRUE
Expands to "1".
dbus_bool_t dbus_message_marshal(DBusMessage *msg, char **marshalled_data_p, int *len_p)
Turn a DBusMessage into the marshalled form as described in the D-Bus specification.
dbus_bool_t _dbus_header_set_field_basic(DBusHeader *header, int field, int type, const void *value)
Sets the value of a field with basic type.
void _dbus_data_slot_list_init(DBusDataSlotList *list)
Initializes a slot list.
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
DBusMessage * dbus_message_copy(const DBusMessage *message)
Creates a new message that is an exact replica of the message specified, except that its refcount is ...
int dbus_message_iter_get_element_type(DBusMessageIter *iter)
Returns the element type of the array that the message iterator points to.
void _dbus_message_get_network_data(DBusMessage *message, const DBusString **header, const DBusString **body)
Gets the data to be sent over the network for this message.
Definition: dbus-message.c:207
#define DBUS_HEADER_FIELD_MEMBER
Header field code for a member (method or signal).
long max_message_unix_fds
Maximum unix fds in a message.
unsigned int corrupted
We got broken data, and are no longer working.
dbus_bool_t dbus_message_get_args_valist(DBusMessage *message, DBusError *error, int first_arg_type, va_list var_args)
Like dbus_message_get_args but takes a va_list for use by language bindings.
#define DBUS_HEADER_FIELD_SENDER
Header field code for the sender of a message; usually initialized by the message bus...
void _dbus_type_writer_add_types(DBusTypeWriter *writer, DBusString *type_str, int type_pos)
Adds type string to the writer, if it had none.
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
dbus_bool_t dbus_set_error_from_message(DBusError *error, DBusMessage *message)
Sets a DBusError based on the contents of the given message.
DBusMessage * dbus_message_demarshal(const char *str, int len, DBusError *error)
Demarshal a D-Bus message from the format described in the D-Bus specification.
void dbus_message_iter_get_fixed_array(DBusMessageIter *iter, void *value, int *n_elements)
Reads a block of fixed-length values from the message iterator.
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
dbus_bool_t _dbus_header_create(DBusHeader *header, int byte_order, int message_type, const char *destination, const char *path, const char *interface, const char *member, const char *error_name)
Fills in the primary fields of the header, so the header is ready for use.
const char * dbus_message_get_interface(DBusMessage *message)
Gets the interface this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or being emitted...
An allocator that tracks a set of slot IDs.
Definition: dbus-dataslot.h:55
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:60
dbus_bool_t dbus_message_set_reply_serial(DBusMessage *message, dbus_uint32_t reply_serial)
Sets the reply serial of a message (the serial of the message this is a reply to).
void _dbus_counter_notify(DBusCounter *counter)
Calls the notify function from _dbus_counter_set_notify(), if that function has been specified and th...
dbus_bool_t dbus_message_has_sender(DBusMessage *message, const char *name)
Checks whether the message has the given unique name as its sender.
dbus_bool_t dbus_message_iter_next(DBusMessageIter *iter)
Moves the iterator to the next field, if any.
_DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,"")
An static string representing an empty signature.
void dbus_message_iter_get_basic(DBusMessageIter *iter, void *value)
Reads a basic-typed value from the message iterator.
void * dbus_message_get_data(DBusMessage *message, dbus_int32_t slot)
Retrieves data previously set with dbus_message_set_data().
void _dbus_type_reader_init(DBusTypeReader *reader, int byte_order, const DBusString *type_str, int type_pos, const DBusString *value_str, int value_pos)
Initializes a type reader.
void _dbus_header_free(DBusHeader *header)
Frees a header.
DBusList * _dbus_message_loader_pop_message_link(DBusMessageLoader *loader)
Pops a loaded message inside a list link (passing ownership of the message and link to the caller)...
#define DBUS_MAXIMUM_ARRAY_LENGTH
Max length of a marshaled array in bytes (64M, 2^26) We use signed int for lengths so must be INT_MAX...
dbus_bool_t dbus_message_set_destination(DBusMessage *message, const char *destination)
Sets the message's destination.
void dbus_error_init(DBusError *error)
Initializes a DBusError structure.
Definition: dbus-errors.c:188
DBusAtomic refcount
Reference count.
dbus_bool_t dbus_message_get_no_reply(DBusMessage *message)
Returns TRUE if the message does not expect a reply.
const char * _dbus_string_get_const_data_len(const DBusString *str, int start, int len)
const version of _dbus_string_get_data_len().
Definition: dbus-string.c:497
A node in a linked list.
Definition: dbus-list.h:34
dbus_bool_t _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader, int **fds, unsigned *max_n_fds)
Gets the buffer to use for reading unix fds from the network.
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:749
#define DBUS_TYPE_BOOLEAN
Type code marking a boolean.
Definition: dbus-protocol.h:70
void _dbus_message_loader_get_buffer(DBusMessageLoader *loader, DBusString **buffer)
Gets the buffer to use for reading data from the network.
dbus_bool_t _dbus_string_append_len(DBusString *str, const char *buffer, int len)
Appends block of bytes with the given length to a DBusString.
Definition: dbus-string.c:1119
dbus_uint32_t iter_type
whether this is a reader or writer iter
Definition: dbus-message.c:129
void _dbus_header_set_serial(DBusHeader *header, dbus_uint32_t serial)
Sets the serial number of a header.
int _dbus_type_reader_get_element_type(const DBusTypeReader *reader)
Gets the type of an element of the array the reader is currently pointing to.
char _dbus_header_get_byte_order(const DBusHeader *header)
Returns the header's byte order.
dbus_bool_t dbus_message_iter_open_container(DBusMessageIter *iter, int type, const char *contained_signature, DBusMessageIter *sub)
Appends a container-typed value to the message; you are required to append the contents of the contai...
dbus_bool_t _dbus_type_reader_has_next(const DBusTypeReader *reader)
Check whether there's another value on this "level".
A simple value union that lets you access bytes as if they were various types; useful when dealing wi...
Definition: dbus-types.h:137
dbus_uint32_t container_type
what are we inside? (e.g.
int _dbus_type_reader_get_array_length(const DBusTypeReader *reader)
Returns the number of bytes in the array.
dbus_bool_t _dbus_header_get_field_raw(DBusHeader *header, int field, const DBusString **str, int *pos)
Gets the raw marshaled data for a field.
dbus_bool_t dbus_message_iter_append_basic(DBusMessageIter *iter, int type, const void *value)
Appends a basic-typed value to the message.
int dbus_message_iter_get_array_len(DBusMessageIter *iter)
Returns the number of bytes in the array as marshaled in the wire protocol.
void(* DBusForeachFunction)(void *element, void *data)
Used to iterate over each item in a collection, such as a DBusList.
int _dbus_type_reader_get_current_type(const DBusTypeReader *reader)
Gets the type of the value the reader is currently pointing to; or for a types-only reader gets the t...
#define FALSE
Expands to "0".
Message header data and some cached details of it.
#define DBUS_HEADER_FIELD_PATH
Header field code for the path - the path is the object emitting a signal or the object receiving a m...
int dbus_message_get_type(DBusMessage *message)
Gets the type of a message.
#define DBUS_HEADER_FIELD_REPLY_SERIAL
Header field code for a reply serial, used to match a DBUS_MESSAGE_TYPE_METHOD_RETURN message with th...
unsigned int buffer_outstanding
Someone is using the buffer to read.
int generation
_dbus_current_generation when message was created
void _dbus_list_prepend_link(DBusList **list, DBusList *link)
Prepends a link to the list.
Definition: dbus-list.c:333
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:785
dbus_bool_t _dbus_register_shutdown_func(DBusShutdownFunction function, void *data)
Register a cleanup function to be called exactly once the next time dbus_shutdown() is called...
Definition: dbus-memory.c:810
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
#define _DBUS_LOCK_NAME(name)
Expands to name of a global lock variable.
const char * _dbus_type_to_string(int typecode)
Returns a string describing the given type.
DBusMessage * _dbus_message_loader_peek_message(DBusMessageLoader *loader)
Peeks at first loaded message, returns NULL if no messages have been queued.
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition: dbus-string.c:1357
dbus_bool_t _dbus_string_steal_data(DBusString *str, char **data_return)
Like _dbus_string_get_data(), but removes the gotten data from the original string.
Definition: dbus-string.c:624
void _dbus_type_reader_get_signature(const DBusTypeReader *reader, const DBusString **str_p, int *start_p, int *len_p)
Gets the string and range of said string containing the signature of the current value.
dbus_bool_t dbus_message_append_args_valist(DBusMessage *message, int first_arg_type, va_list var_args)
Like dbus_message_append_args() but takes a va_list for use by language bindings. ...
int dbus_message_demarshal_bytes_needed(const char *buf, int len)
Returns the number of bytes required to be in the buffer to demarshal a D-Bus message.
char * dbus_message_iter_get_signature(DBusMessageIter *iter)
Returns the current signature of a message iterator.
dbus_bool_t _dbus_type_writer_write_fixed_multi(DBusTypeWriter *writer, int element_type, const void *value, int n_elements)
Writes a block of fixed-length basic values, i.e.
void dbus_message_iter_abandon_container(DBusMessageIter *iter, DBusMessageIter *sub)
Abandons creation of a contained-typed value and frees resources created by dbus_message_iter_open_co...
void _dbus_verbose_bytes_of_string(const DBusString *str, int start, int len)
Dump the given part of the string to verbose log.
dbus_bool_t _dbus_data_slot_allocator_alloc(DBusDataSlotAllocator *allocator, dbus_int32_t *slot_id_p)
Allocates an integer ID to be used for storing data in a DBusDataSlotList.
Definition: dbus-dataslot.c:69
dbus_bool_t dbus_message_contains_unix_fds(DBusMessage *message)
Checks whether a message contains unix fds.
#define DBUS_HEADER_FLAG_NO_AUTO_START
If set, this flag means that even if the message bus knows how to start an owner for the destination ...
dbus_bool_t _dbus_message_loader_queue_messages(DBusMessageLoader *loader)
Converts buffered data into messages, if we have enough data.
void _dbus_message_get_unix_fds(DBusMessage *message, const int **fds, unsigned *n_fds)
Gets the unix fds to be sent over the network for this message.
Definition: dbus-message.c:226
int refcount
Reference count.
int dbus_int32_t
A 32-bit signed integer on all platforms.
char * _dbus_strdup(const char *str)
Duplicates a string.
#define MAX_MESSAGE_SIZE_TO_CACHE
Avoid caching huge messages.
Definition: dbus-message.c:504
#define DBUS_ERROR_INVALID_ARGS
Invalid arguments passed to a method call.
void _dbus_data_slot_allocator_free(DBusDataSlotAllocator *allocator, dbus_int32_t *slot_id_p)
Deallocates an ID previously allocated with _dbus_data_slot_allocator_alloc().
int _dbus_type_get_alignment(int typecode)
Gets the alignment requirement for the given type; will be 1, 4, or 8.
DBusValidity corruption_reason
why we were corrupted
void _dbus_message_loader_set_max_message_unix_fds(DBusMessageLoader *loader, long n)
Sets the maximum unix fds per message we allow.
dbus_bool_t dbus_message_set_member(DBusMessage *message, const char *member)
Sets the interface member being invoked (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted (DBUS_MESSAGE_TYPE...
const char * _dbus_string_get_const_data(const DBusString *str)
Gets the raw character buffer from a const string.
Definition: dbus-string.c:451
const char * dbus_message_type_to_string(int type)
Utility function to convert a D-Bus message type into a machine-readable string (not translated)...
void dbus_message_unref(DBusMessage *message)
Decrements the reference count of a DBusMessage, freeing the message if the count reaches 0...
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:210
Implementation details of DBusMessageLoader.
dbus_bool_t _dbus_type_writer_recurse(DBusTypeWriter *writer, int container_type, const DBusString *contained_type, int contained_type_start, DBusTypeWriter *sub)
Opens a new container and writes out the initial information for that container.
dbus_uint32_t u32
as int32
Definition: dbus-types.h:143
DBusMessage * dbus_message_new_error_printf(DBusMessage *reply_to, const char *error_name, const char *error_format,...)
Creates a new message that is an error reply to another message, allowing you to use printf formattin...
dbus_bool_t dbus_message_set_data(DBusMessage *message, dbus_int32_t slot, void *data, DBusFreeFunction free_data_func)
Stores a pointer on a DBusMessage, along with an optional function to be used for freeing the data wh...
void dbus_message_set_serial(DBusMessage *message, dbus_uint32_t serial)
Sets the serial number of a message.
Definition: dbus-message.c:253
void _dbus_header_toggle_flag(DBusHeader *header, dbus_uint32_t flag, dbus_bool_t value)
Toggles a message flag bit, turning on the bit if value = TRUE and flipping it off if value = FALSE...
void _dbus_header_update_lengths(DBusHeader *header, int body_len)
Fills in the correct body length.
DBusMessage * dbus_message_new_method_return(DBusMessage *method_call)
Constructs a message that is a reply to a method call.
DBusTypeWriter writer
writer
Definition: dbus-message.c:133
void _dbus_data_slot_list_free(DBusDataSlotList *list)
Frees the data slot list and all data slots contained in it, calling application-provided free functi...
#define DBUS_MAXIMUM_MESSAGE_LENGTH
The maximum total message size including header and body; similar rationale to max array size...
DBusDataSlotList slot_list
Data stored by allocated integer ID.
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:542
void _dbus_marshal_byteswap(const DBusString *signature, int signature_start, int old_byte_order, int new_byte_order, DBusString *value_str, int value_pos)
Byteswaps the marshaled data in the given value_str.
dbus_bool_t dbus_type_is_container(int typecode)
A "container type" can contain basic types, or nested container types.
DBusMessage * dbus_message_new_error(DBusMessage *reply_to, const char *error_name, const char *error_message)
Creates a new message that is an error reply to another message.
void _dbus_counter_adjust_size(DBusCounter *counter, long delta)
Adjusts the value of the size counter by the given delta which may be positive or negative...