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