D-Bus  1.10.6
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 {
130  dbus_uint32_t iter_type : 3;
131  dbus_uint32_t sig_refcount : 8;
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 {
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  unsigned 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 
1126 dbus_uint32_t
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 
1162 dbus_uint32_t
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 {
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 {
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 {
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 {
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 {
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 {
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;
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_STATIC_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 
2337 int
2339 {
2340  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2341  DBusTypeReader array;
2342  int element_type;
2343  int n_elements = 0;
2344 
2345  _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2346  _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
2347  == DBUS_TYPE_ARRAY, 0);
2348 
2349  element_type = _dbus_type_reader_get_element_type (&real->u.reader);
2350  _dbus_type_reader_recurse (&real->u.reader, &array);
2351  if (dbus_type_is_fixed (element_type))
2352  {
2353  int alignment = _dbus_type_get_alignment (element_type);
2354  int total_len = _dbus_type_reader_get_array_length (&array);
2355  n_elements = total_len / alignment;
2356  }
2357  else
2358  {
2360  {
2361  ++n_elements;
2362  _dbus_type_reader_next (&array);
2363  }
2364  }
2365 
2366  return n_elements;
2367 }
2368 
2381 int
2383 {
2384  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2385 
2386  _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2387 
2389 }
2390 
2426 void
2428  void *value,
2429  int *n_elements)
2430 {
2431  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2432 #ifndef DBUS_DISABLE_CHECKS
2433  int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
2434 
2435  _dbus_return_if_fail (_dbus_message_iter_check (real));
2436  _dbus_return_if_fail (value != NULL);
2437  _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
2438  (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
2439 #endif
2440 
2442  value, n_elements);
2443 }
2444 
2456 void
2458  DBusMessageIter *iter)
2459 {
2460  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2461 
2462  _dbus_return_if_fail (message != NULL);
2463  _dbus_return_if_fail (iter != NULL);
2464 
2465  _dbus_message_iter_init_common (message, real,
2466  DBUS_MESSAGE_ITER_TYPE_WRITER);
2467 
2468  /* We create the signature string and point iterators at it "on demand"
2469  * when a value is actually appended. That means that init() never fails
2470  * due to OOM.
2471  */
2473  _dbus_header_get_byte_order (&message->header),
2474  &message->body,
2475  _dbus_string_get_length (&message->body));
2476 }
2477 
2486 static dbus_bool_t
2487 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
2488 {
2489  DBusString *str;
2490  const DBusString *current_sig;
2491  int current_sig_pos;
2492 
2493  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2494 
2495  if (real->u.writer.type_str != NULL)
2496  {
2497  _dbus_assert (real->sig_refcount > 0);
2498  real->sig_refcount += 1;
2499  return TRUE;
2500  }
2501 
2502  str = dbus_new (DBusString, 1);
2503  if (str == NULL)
2504  return FALSE;
2505 
2508  &current_sig, &current_sig_pos))
2509  current_sig = NULL;
2510 
2511  if (current_sig)
2512  {
2513  int current_len;
2514 
2515  current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
2516  current_sig_pos += 1; /* move on to sig data */
2517 
2518  if (!_dbus_string_init_preallocated (str, current_len + 4))
2519  {
2520  dbus_free (str);
2521  return FALSE;
2522  }
2523 
2524  if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
2525  str, 0))
2526  {
2527  _dbus_string_free (str);
2528  dbus_free (str);
2529  return FALSE;
2530  }
2531  }
2532  else
2533  {
2534  if (!_dbus_string_init_preallocated (str, 4))
2535  {
2536  dbus_free (str);
2537  return FALSE;
2538  }
2539  }
2540 
2541  real->sig_refcount = 1;
2542 
2544  str, _dbus_string_get_length (str));
2545  return TRUE;
2546 }
2547 
2557 static dbus_bool_t
2558 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
2559 {
2560  DBusString *str;
2561  const char *v_STRING;
2562  dbus_bool_t retval;
2563 
2564  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2565  _dbus_assert (real->u.writer.type_str != NULL);
2566  _dbus_assert (real->sig_refcount > 0);
2567 
2568  real->sig_refcount -= 1;
2569 
2570  if (real->sig_refcount > 0)
2571  return TRUE;
2572  _dbus_assert (real->sig_refcount == 0);
2573 
2574  retval = TRUE;
2575 
2576  str = real->u.writer.type_str;
2577 
2578  v_STRING = _dbus_string_get_const_data (str);
2582  &v_STRING))
2583  retval = FALSE;
2584 
2586  _dbus_string_free (str);
2587  dbus_free (str);
2588 
2589  return retval;
2590 }
2591 
2599 static void
2600 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
2601 {
2602  DBusString *str;
2603 
2604  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2605  _dbus_assert (real->u.writer.type_str != NULL);
2606  _dbus_assert (real->sig_refcount > 0);
2607 
2608  real->sig_refcount -= 1;
2609 
2610  if (real->sig_refcount > 0)
2611  return;
2612  _dbus_assert (real->sig_refcount == 0);
2613 
2614  str = real->u.writer.type_str;
2615 
2617  _dbus_string_free (str);
2618  dbus_free (str);
2619 }
2620 
2621 #ifndef DBUS_DISABLE_CHECKS
2622 static dbus_bool_t
2623 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
2624 {
2625  if (!_dbus_message_iter_check (iter))
2626  return FALSE;
2627 
2628  if (iter->message->locked)
2629  {
2630  _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
2631  return FALSE;
2632  }
2633 
2634  return TRUE;
2635 }
2636 #endif /* DBUS_DISABLE_CHECKS */
2637 
2638 #ifdef HAVE_UNIX_FD_PASSING
2639 static int *
2640 expand_fd_array(DBusMessage *m,
2641  unsigned n)
2642 {
2643  _dbus_assert(m);
2644 
2645  /* This makes space for adding n new fds to the array and returns a
2646  pointer to the place were the first fd should be put. */
2647 
2648  if (m->n_unix_fds + n > m->n_unix_fds_allocated)
2649  {
2650  unsigned k;
2651  int *p;
2652 
2653  /* Make twice as much space as necessary */
2654  k = (m->n_unix_fds + n) * 2;
2655 
2656  /* Allocate at least four */
2657  if (k < 4)
2658  k = 4;
2659 
2660  p = dbus_realloc(m->unix_fds, k * sizeof(int));
2661  if (p == NULL)
2662  return NULL;
2663 
2664  m->unix_fds = p;
2665  m->n_unix_fds_allocated = k;
2666  }
2667 
2668  return m->unix_fds + m->n_unix_fds;
2669 }
2670 #endif
2671 
2693  int type,
2694  const void *value)
2695 {
2696  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2697  dbus_bool_t ret;
2698 
2699  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2700  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2701  _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
2702  _dbus_return_val_if_fail (value != NULL, FALSE);
2703 
2704 #ifndef DBUS_DISABLE_CHECKS
2705  switch (type)
2706  {
2707  const char * const *string_p;
2708  const dbus_bool_t *bool_p;
2709 
2710  case DBUS_TYPE_STRING:
2711  string_p = value;
2712  _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
2713  break;
2714 
2715  case DBUS_TYPE_OBJECT_PATH:
2716  string_p = value;
2717  _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
2718  break;
2719 
2720  case DBUS_TYPE_SIGNATURE:
2721  string_p = value;
2722  _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
2723  break;
2724 
2725  case DBUS_TYPE_BOOLEAN:
2726  bool_p = value;
2727  _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
2728  break;
2729 
2730  default:
2731  {
2732  /* nothing to check, all possible values are allowed */
2733  }
2734  }
2735 #endif
2736 
2737  if (!_dbus_message_iter_open_signature (real))
2738  return FALSE;
2739 
2740  if (type == DBUS_TYPE_UNIX_FD)
2741  {
2742 #ifdef HAVE_UNIX_FD_PASSING
2743  int *fds;
2744  dbus_uint32_t u;
2745 
2746  /* First step, include the fd in the fd list of this message */
2747  if (!(fds = expand_fd_array(real->message, 1)))
2748  return FALSE;
2749 
2750  *fds = _dbus_dup(*(int*) value, NULL);
2751  if (*fds < 0)
2752  return FALSE;
2753 
2754  u = real->message->n_unix_fds;
2755 
2756  /* Second step, write the index to the fd */
2757  if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
2758  _dbus_close(*fds, NULL);
2759  return FALSE;
2760  }
2761 
2762  real->message->n_unix_fds += 1;
2763  u += 1;
2764 
2765  /* Final step, update the header accordingly */
2769  &u);
2770 
2771  /* If any of these operations fail the message is
2772  hosed. However, no memory or fds should be leaked since what
2773  has been added to message has been added to the message, and
2774  can hence be accounted for when the message is being
2775  freed. */
2776 #else
2777  ret = FALSE;
2778 #endif
2779  }
2780  else
2781  {
2782  ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
2783  }
2784 
2785  if (!_dbus_message_iter_close_signature (real))
2786  ret = FALSE;
2787 
2788  return ret;
2789 }
2790 
2828  int element_type,
2829  const void *value,
2830  int n_elements)
2831 {
2832  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2833  dbus_bool_t ret;
2834 
2835  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2836  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2837  _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
2838  _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
2839  _dbus_return_val_if_fail (value != NULL, FALSE);
2840  _dbus_return_val_if_fail (n_elements >= 0, FALSE);
2841  _dbus_return_val_if_fail (n_elements <=
2843  FALSE);
2844 
2845 #ifndef DBUS_DISABLE_CHECKS
2846  if (element_type == DBUS_TYPE_BOOLEAN)
2847  {
2848  const dbus_bool_t * const *bools = value;
2849  int i;
2850 
2851  for (i = 0; i < n_elements; i++)
2852  {
2853  _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
2854  }
2855  }
2856 #endif
2857 
2858  ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
2859 
2860  return ret;
2861 }
2862 
2886  int type,
2887  const char *contained_signature,
2888  DBusMessageIter *sub)
2889 {
2890  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2891  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2892  DBusString contained_str;
2893 
2894  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2895  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2896  _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
2897  _dbus_return_val_if_fail (sub != NULL, FALSE);
2898  _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
2899  contained_signature == NULL) ||
2900  (type == DBUS_TYPE_DICT_ENTRY &&
2901  contained_signature == NULL) ||
2902  (type == DBUS_TYPE_VARIANT &&
2903  contained_signature != NULL) ||
2904  (type == DBUS_TYPE_ARRAY &&
2905  contained_signature != NULL), FALSE);
2906 
2907  /* this would fail if the contained_signature is a dict entry, since
2908  * dict entries are invalid signatures standalone (they must be in
2909  * an array)
2910  */
2911  _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
2912  (contained_signature == NULL ||
2913  _dbus_check_is_valid_signature (contained_signature)),
2914  FALSE);
2915 
2916  if (!_dbus_message_iter_open_signature (real))
2917  return FALSE;
2918 
2919  *real_sub = *real;
2920 
2921  if (contained_signature != NULL)
2922  {
2923  _dbus_string_init_const (&contained_str, contained_signature);
2924 
2925  return _dbus_type_writer_recurse (&real->u.writer,
2926  type,
2927  &contained_str, 0,
2928  &real_sub->u.writer);
2929  }
2930  else
2931  {
2932  return _dbus_type_writer_recurse (&real->u.writer,
2933  type,
2934  NULL, 0,
2935  &real_sub->u.writer);
2936  }
2937 }
2938 
2939 
2955  DBusMessageIter *sub)
2956 {
2957  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2958  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2959  dbus_bool_t ret;
2960 
2961  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2962  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2963  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
2964  _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2965 
2966  ret = _dbus_type_writer_unrecurse (&real->u.writer,
2967  &real_sub->u.writer);
2968 
2969  if (!_dbus_message_iter_close_signature (real))
2970  ret = FALSE;
2971 
2972  return ret;
2973 }
2974 
2986 void
2988  DBusMessageIter *sub)
2989 {
2990  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2991 #ifndef DBUS_DISABLE_CHECKS
2992  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2993 
2994  _dbus_return_if_fail (_dbus_message_iter_append_check (real));
2995  _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2996  _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
2997  _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2998 #endif
2999 
3000  _dbus_message_iter_abandon_signature (real);
3001 }
3002 
3019 void
3021  dbus_bool_t no_reply)
3022 {
3023  _dbus_return_if_fail (message != NULL);
3024  _dbus_return_if_fail (!message->locked);
3025 
3026  _dbus_header_toggle_flag (&message->header,
3028  no_reply);
3029 }
3030 
3040 {
3041  _dbus_return_val_if_fail (message != NULL, FALSE);
3042 
3043  return _dbus_header_get_flag (&message->header,
3045 }
3046 
3061 void
3063  dbus_bool_t auto_start)
3064 {
3065  _dbus_return_if_fail (message != NULL);
3066  _dbus_return_if_fail (!message->locked);
3067 
3068  _dbus_header_toggle_flag (&message->header,
3070  !auto_start);
3071 }
3072 
3082 {
3083  _dbus_return_val_if_fail (message != NULL, FALSE);
3084 
3085  return !_dbus_header_get_flag (&message->header,
3087 }
3088 
3089 
3104  const char *object_path)
3105 {
3106  _dbus_return_val_if_fail (message != NULL, FALSE);
3107  _dbus_return_val_if_fail (!message->locked, FALSE);
3108  _dbus_return_val_if_fail (object_path == NULL ||
3109  _dbus_check_is_valid_path (object_path),
3110  FALSE);
3111 
3112  return set_or_delete_string_field (message,
3115  object_path);
3116 }
3117 
3131 const char*
3133 {
3134  const char *v;
3135 
3136  _dbus_return_val_if_fail (message != NULL, NULL);
3137 
3138  v = NULL; /* in case field doesn't exist */
3142  (void *) &v);
3143  return v;
3144 }
3145 
3157  const char *path)
3158 {
3159  const char *msg_path;
3160  msg_path = dbus_message_get_path (message);
3161 
3162  if (msg_path == NULL)
3163  {
3164  if (path == NULL)
3165  return TRUE;
3166  else
3167  return FALSE;
3168  }
3169 
3170  if (path == NULL)
3171  return FALSE;
3172 
3173  if (strcmp (msg_path, path) == 0)
3174  return TRUE;
3175 
3176  return FALSE;
3177 }
3178 
3201  char ***path)
3202 {
3203  const char *v;
3204 
3205  _dbus_return_val_if_fail (message != NULL, FALSE);
3206  _dbus_return_val_if_fail (path != NULL, FALSE);
3207 
3208  *path = NULL;
3209 
3210  v = dbus_message_get_path (message);
3211  if (v != NULL)
3212  {
3213  if (!_dbus_decompose_path (v, strlen (v),
3214  path, NULL))
3215  return FALSE;
3216  }
3217  return TRUE;
3218 }
3219 
3235  const char *iface)
3236 {
3237  _dbus_return_val_if_fail (message != NULL, FALSE);
3238  _dbus_return_val_if_fail (!message->locked, FALSE);
3239  _dbus_return_val_if_fail (iface == NULL ||
3240  _dbus_check_is_valid_interface (iface),
3241  FALSE);
3242 
3243  return set_or_delete_string_field (message,
3246  iface);
3247 }
3248 
3262 const char*
3264 {
3265  const char *v;
3266 
3267  _dbus_return_val_if_fail (message != NULL, NULL);
3268 
3269  v = NULL; /* in case field doesn't exist */
3273  (void *) &v);
3274  return v;
3275 }
3276 
3286  const char *iface)
3287 {
3288  const char *msg_interface;
3289  msg_interface = dbus_message_get_interface (message);
3290 
3291  if (msg_interface == NULL)
3292  {
3293  if (iface == NULL)
3294  return TRUE;
3295  else
3296  return FALSE;
3297  }
3298 
3299  if (iface == NULL)
3300  return FALSE;
3301 
3302  if (strcmp (msg_interface, iface) == 0)
3303  return TRUE;
3304 
3305  return FALSE;
3306 
3307 }
3308 
3323  const char *member)
3324 {
3325  _dbus_return_val_if_fail (message != NULL, FALSE);
3326  _dbus_return_val_if_fail (!message->locked, FALSE);
3327  _dbus_return_val_if_fail (member == NULL ||
3328  _dbus_check_is_valid_member (member),
3329  FALSE);
3330 
3331  return set_or_delete_string_field (message,
3334  member);
3335 }
3336 
3348 const char*
3350 {
3351  const char *v;
3352 
3353  _dbus_return_val_if_fail (message != NULL, NULL);
3354 
3355  v = NULL; /* in case field doesn't exist */
3359  (void *) &v);
3360  return v;
3361 }
3362 
3372  const char *member)
3373 {
3374  const char *msg_member;
3375  msg_member = dbus_message_get_member (message);
3376 
3377  if (msg_member == NULL)
3378  {
3379  if (member == NULL)
3380  return TRUE;
3381  else
3382  return FALSE;
3383  }
3384 
3385  if (member == NULL)
3386  return FALSE;
3387 
3388  if (strcmp (msg_member, member) == 0)
3389  return TRUE;
3390 
3391  return FALSE;
3392 
3393 }
3394 
3408  const char *error_name)
3409 {
3410  _dbus_return_val_if_fail (message != NULL, FALSE);
3411  _dbus_return_val_if_fail (!message->locked, FALSE);
3412  _dbus_return_val_if_fail (error_name == NULL ||
3413  _dbus_check_is_valid_error_name (error_name),
3414  FALSE);
3415 
3416  return set_or_delete_string_field (message,
3419  error_name);
3420 }
3421 
3432 const char*
3434 {
3435  const char *v;
3436 
3437  _dbus_return_val_if_fail (message != NULL, NULL);
3438 
3439  v = NULL; /* in case field doesn't exist */
3443  (void *) &v);
3444  return v;
3445 }
3446 
3462  const char *destination)
3463 {
3464  _dbus_return_val_if_fail (message != NULL, FALSE);
3465  _dbus_return_val_if_fail (!message->locked, FALSE);
3466  _dbus_return_val_if_fail (destination == NULL ||
3467  _dbus_check_is_valid_bus_name (destination),
3468  FALSE);
3469 
3470  return set_or_delete_string_field (message,
3473  destination);
3474 }
3475 
3485 const char*
3487 {
3488  const char *v;
3489 
3490  _dbus_return_val_if_fail (message != NULL, NULL);
3491 
3492  v = NULL; /* in case field doesn't exist */
3496  (void *) &v);
3497  return v;
3498 }
3499 
3516  const char *sender)
3517 {
3518  _dbus_return_val_if_fail (message != NULL, FALSE);
3519  _dbus_return_val_if_fail (!message->locked, FALSE);
3520  _dbus_return_val_if_fail (sender == NULL ||
3521  _dbus_check_is_valid_bus_name (sender),
3522  FALSE);
3523 
3524  return set_or_delete_string_field (message,
3527  sender);
3528 }
3529 
3545 const char*
3547 {
3548  const char *v;
3549 
3550  _dbus_return_val_if_fail (message != NULL, NULL);
3551 
3552  v = NULL; /* in case field doesn't exist */
3556  (void *) &v);
3557  return v;
3558 }
3559 
3578 const char*
3580 {
3581  const DBusString *type_str;
3582  int type_pos;
3583 
3584  _dbus_return_val_if_fail (message != NULL, NULL);
3585 
3586  get_const_signature (&message->header, &type_str, &type_pos);
3587 
3588  return _dbus_string_get_const_data_len (type_str, type_pos, 0);
3589 }
3590 
3591 static dbus_bool_t
3592 _dbus_message_has_type_interface_member (DBusMessage *message,
3593  int type,
3594  const char *iface,
3595  const char *member)
3596 {
3597  const char *n;
3598 
3599  _dbus_assert (message != NULL);
3600  _dbus_assert (iface != NULL);
3601  _dbus_assert (member != NULL);
3602 
3603  if (dbus_message_get_type (message) != type)
3604  return FALSE;
3605 
3606  /* Optimize by checking the short member name first
3607  * instead of the longer interface name
3608  */
3609 
3610  n = dbus_message_get_member (message);
3611 
3612  if (n && strcmp (n, member) == 0)
3613  {
3614  n = dbus_message_get_interface (message);
3615 
3616  if (n == NULL || strcmp (n, iface) == 0)
3617  return TRUE;
3618  }
3619 
3620  return FALSE;
3621 }
3622 
3639  const char *iface,
3640  const char *method)
3641 {
3642  _dbus_return_val_if_fail (message != NULL, FALSE);
3643  _dbus_return_val_if_fail (iface != NULL, FALSE);
3644  _dbus_return_val_if_fail (method != NULL, FALSE);
3645  /* don't check that interface/method are valid since it would be
3646  * expensive, and not catch many common errors
3647  */
3648 
3649  return _dbus_message_has_type_interface_member (message,
3651  iface, method);
3652 }
3653 
3667  const char *iface,
3668  const char *signal_name)
3669 {
3670  _dbus_return_val_if_fail (message != NULL, FALSE);
3671  _dbus_return_val_if_fail (iface != NULL, FALSE);
3672  _dbus_return_val_if_fail (signal_name != NULL, FALSE);
3673  /* don't check that interface/name are valid since it would be
3674  * expensive, and not catch many common errors
3675  */
3676 
3677  return _dbus_message_has_type_interface_member (message,
3679  iface, signal_name);
3680 }
3681 
3694  const char *error_name)
3695 {
3696  const char *n;
3697 
3698  _dbus_return_val_if_fail (message != NULL, FALSE);
3699  _dbus_return_val_if_fail (error_name != NULL, FALSE);
3700  /* don't check that error_name is valid since it would be expensive,
3701  * and not catch many common errors
3702  */
3703 
3705  return FALSE;
3706 
3707  n = dbus_message_get_error_name (message);
3708 
3709  if (n && strcmp (n, error_name) == 0)
3710  return TRUE;
3711  else
3712  return FALSE;
3713 }
3714 
3727  const char *name)
3728 {
3729  const char *s;
3730 
3731  _dbus_return_val_if_fail (message != NULL, FALSE);
3732  _dbus_return_val_if_fail (name != NULL, FALSE);
3733  /* don't check that name is valid since it would be expensive, and
3734  * not catch many common errors
3735  */
3736 
3737  s = dbus_message_get_destination (message);
3738 
3739  if (s && strcmp (s, name) == 0)
3740  return TRUE;
3741  else
3742  return FALSE;
3743 }
3744 
3762  const char *name)
3763 {
3764  const char *s;
3765 
3766  _dbus_return_val_if_fail (message != NULL, FALSE);
3767  _dbus_return_val_if_fail (name != NULL, FALSE);
3768  /* don't check that name is valid since it would be expensive, and
3769  * not catch many common errors
3770  */
3771 
3772  s = dbus_message_get_sender (message);
3773 
3774  if (s && strcmp (s, name) == 0)
3775  return TRUE;
3776  else
3777  return FALSE;
3778 }
3779 
3791  const char *signature)
3792 {
3793  const char *s;
3794 
3795  _dbus_return_val_if_fail (message != NULL, FALSE);
3796  _dbus_return_val_if_fail (signature != NULL, FALSE);
3797  /* don't check that signature is valid since it would be expensive,
3798  * and not catch many common errors
3799  */
3800 
3801  s = dbus_message_get_signature (message);
3802 
3803  if (s && strcmp (s, signature) == 0)
3804  return TRUE;
3805  else
3806  return FALSE;
3807 }
3808 
3833  DBusMessage *message)
3834 {
3835  const char *str;
3836 
3837  _dbus_return_val_if_fail (message != NULL, FALSE);
3838  _dbus_return_val_if_error_is_set (error, FALSE);
3839 
3841  return FALSE;
3842 
3843  str = NULL;
3844  dbus_message_get_args (message, NULL,
3845  DBUS_TYPE_STRING, &str,
3847 
3848  dbus_set_error (error, dbus_message_get_error_name (message),
3849  str ? "%s" : NULL, str);
3850 
3851  return TRUE;
3852 }
3853 
3862 {
3863 #ifdef HAVE_UNIX_FD_PASSING
3864  _dbus_assert(message);
3865 
3866  return message->n_unix_fds > 0;
3867 #else
3868  return FALSE;
3869 #endif
3870 }
3871 
3890 #define INITIAL_LOADER_DATA_LEN 32
3891 
3900 {
3901  DBusMessageLoader *loader;
3902 
3903  loader = dbus_new0 (DBusMessageLoader, 1);
3904  if (loader == NULL)
3905  return NULL;
3906 
3907  loader->refcount = 1;
3908 
3909  loader->corrupted = FALSE;
3910  loader->corruption_reason = DBUS_VALID;
3911 
3912  /* this can be configured by the app, but defaults to the protocol max */
3914 
3915  /* We set a very relatively conservative default here since due to how
3916  SCM_RIGHTS works we need to preallocate an fd array of the maximum
3917  number of unix fds we want to receive in advance. A
3918  try-and-reallocate loop is not possible. */
3919  loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
3920 
3921  if (!_dbus_string_init (&loader->data))
3922  {
3923  dbus_free (loader);
3924  return NULL;
3925  }
3926 
3927  /* preallocate the buffer for speed, ignore failure */
3929  _dbus_string_set_length (&loader->data, 0);
3930 
3931 #ifdef HAVE_UNIX_FD_PASSING
3932  loader->unix_fds = NULL;
3933  loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
3934  loader->unix_fds_outstanding = FALSE;
3935 #endif
3936 
3937  return loader;
3938 }
3939 
3948 {
3949  loader->refcount += 1;
3950 
3951  return loader;
3952 }
3953 
3960 void
3962 {
3963  loader->refcount -= 1;
3964  if (loader->refcount == 0)
3965  {
3966 #ifdef HAVE_UNIX_FD_PASSING
3967  close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
3968  dbus_free(loader->unix_fds);
3969 #endif
3970  _dbus_list_foreach (&loader->messages,
3972  NULL);
3973  _dbus_list_clear (&loader->messages);
3974  _dbus_string_free (&loader->data);
3975  dbus_free (loader);
3976  }
3977 }
3978 
3997 void
3999  DBusString **buffer)
4000 {
4001  _dbus_assert (!loader->buffer_outstanding);
4002 
4003  *buffer = &loader->data;
4004 
4005  loader->buffer_outstanding = TRUE;
4006 }
4007 
4017 void
4019  DBusString *buffer)
4020 {
4021  _dbus_assert (loader->buffer_outstanding);
4022  _dbus_assert (buffer == &loader->data);
4023 
4024  loader->buffer_outstanding = FALSE;
4025 }
4026 
4039  int **fds,
4040  unsigned *max_n_fds)
4041 {
4042 #ifdef HAVE_UNIX_FD_PASSING
4043  _dbus_assert (!loader->unix_fds_outstanding);
4044 
4045  /* Allocate space where we can put the fds we read. We allocate
4046  space for max_message_unix_fds since this is an
4047  upper limit how many fds can be received within a single
4048  message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
4049  we are allocating the maximum possible array size right from the
4050  beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
4051  there is no better way. */
4052 
4053  if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
4054  {
4055  int *a = dbus_realloc(loader->unix_fds,
4056  loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
4057 
4058  if (!a)
4059  return FALSE;
4060 
4061  loader->unix_fds = a;
4062  loader->n_unix_fds_allocated = loader->max_message_unix_fds;
4063  }
4064 
4065  *fds = loader->unix_fds + loader->n_unix_fds;
4066  *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
4067 
4068  loader->unix_fds_outstanding = TRUE;
4069  return TRUE;
4070 #else
4071  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
4072  return FALSE;
4073 #endif
4074 }
4075 
4086 void
4088  int *fds,
4089  unsigned n_fds)
4090 {
4091 #ifdef HAVE_UNIX_FD_PASSING
4092  _dbus_assert(loader->unix_fds_outstanding);
4093  _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
4094  _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
4095 
4096  loader->n_unix_fds += n_fds;
4097  loader->unix_fds_outstanding = FALSE;
4098 
4099  if (n_fds && loader->unix_fds_change)
4100  loader->unix_fds_change (loader->unix_fds_change_data);
4101 #else
4102  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
4103 #endif
4104 }
4105 
4106 /*
4107  * FIXME when we move the header out of the buffer, that memmoves all
4108  * buffered messages. Kind of crappy.
4109  *
4110  * Also we copy the header and body, which is kind of crappy. To
4111  * avoid this, we have to allow header and body to be in a single
4112  * memory block, which is good for messages we read and bad for
4113  * messages we are creating. But we could move_len() the buffer into
4114  * this single memory block, and move_len() will just swap the buffers
4115  * if you're moving the entire buffer replacing the dest string.
4116  *
4117  * We could also have the message loader tell the transport how many
4118  * bytes to read; so it would first ask for some arbitrary number like
4119  * 256, then if the message was incomplete it would use the
4120  * header/body len to ask for exactly the size of the message (or
4121  * blocks the size of a typical kernel buffer for the socket). That
4122  * way we don't get trailing bytes in the buffer that have to be
4123  * memmoved. Though I suppose we also don't have a chance of reading a
4124  * bunch of small messages at once, so the optimization may be stupid.
4125  *
4126  * Another approach would be to keep a "start" index into
4127  * loader->data and only delete it occasionally, instead of after
4128  * each message is loaded.
4129  *
4130  * load_message() returns FALSE if not enough memory OR the loader was corrupted
4131  */
4132 static dbus_bool_t
4133 load_message (DBusMessageLoader *loader,
4134  DBusMessage *message,
4135  int byte_order,
4136  int fields_array_len,
4137  int header_len,
4138  int body_len)
4139 {
4140  dbus_bool_t oom;
4141  DBusValidity validity;
4142  const DBusString *type_str;
4143  int type_pos;
4144  DBusValidationMode mode;
4145  dbus_uint32_t n_unix_fds = 0;
4146 
4147  mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
4148 
4149  oom = FALSE;
4150 
4151 #if 0
4152  _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
4153 #endif
4154 
4155  /* 1. VALIDATE AND COPY OVER HEADER */
4156  _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
4157  _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
4158 
4159  if (!_dbus_header_load (&message->header,
4160  mode,
4161  &validity,
4162  byte_order,
4163  fields_array_len,
4164  header_len,
4165  body_len,
4166  &loader->data, 0,
4167  _dbus_string_get_length (&loader->data)))
4168  {
4169  _dbus_verbose ("Failed to load header for new message code %d\n", validity);
4170 
4171  /* assert here so we can catch any code that still uses DBUS_VALID to indicate
4172  oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
4173  _dbus_assert (validity != DBUS_VALID);
4174 
4175  if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
4176  oom = TRUE;
4177  else
4178  {
4179  loader->corrupted = TRUE;
4180  loader->corruption_reason = validity;
4181  }
4182  goto failed;
4183  }
4184 
4185  _dbus_assert (validity == DBUS_VALID);
4186 
4187  /* 2. VALIDATE BODY */
4188  if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
4189  {
4190  get_const_signature (&message->header, &type_str, &type_pos);
4191 
4192  /* Because the bytes_remaining arg is NULL, this validates that the
4193  * body is the right length
4194  */
4195  validity = _dbus_validate_body_with_reason (type_str,
4196  type_pos,
4197  byte_order,
4198  NULL,
4199  &loader->data,
4200  header_len,
4201  body_len);
4202  if (validity != DBUS_VALID)
4203  {
4204  _dbus_verbose ("Failed to validate message body code %d\n", validity);
4205 
4206  loader->corrupted = TRUE;
4207  loader->corruption_reason = validity;
4208 
4209  goto failed;
4210  }
4211  }
4212 
4213  /* 3. COPY OVER UNIX FDS */
4217  &n_unix_fds);
4218 
4219 #ifdef HAVE_UNIX_FD_PASSING
4220 
4221  if (n_unix_fds > loader->n_unix_fds)
4222  {
4223  _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
4224  n_unix_fds, loader->n_unix_fds);
4225 
4226  loader->corrupted = TRUE;
4227  loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4228  goto failed;
4229  }
4230 
4231  /* If this was a recycled message there might still be
4232  some memory allocated for the fds */
4233  dbus_free(message->unix_fds);
4234 
4235  if (n_unix_fds > 0)
4236  {
4237  message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
4238  if (message->unix_fds == NULL)
4239  {
4240  _dbus_verbose ("Failed to allocate file descriptor array\n");
4241  oom = TRUE;
4242  goto failed;
4243  }
4244 
4245  message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
4246  loader->n_unix_fds -= n_unix_fds;
4247  memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
4248 
4249  if (loader->unix_fds_change)
4250  loader->unix_fds_change (loader->unix_fds_change_data);
4251  }
4252  else
4253  message->unix_fds = NULL;
4254 
4255 #else
4256 
4257  if (n_unix_fds > 0)
4258  {
4259  _dbus_verbose ("Hmm, message claims to come with file descriptors "
4260  "but that's not supported on our platform, disconnecting.\n");
4261 
4262  loader->corrupted = TRUE;
4263  loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4264  goto failed;
4265  }
4266 
4267 #endif
4268 
4269  /* 3. COPY OVER BODY AND QUEUE MESSAGE */
4270 
4271  if (!_dbus_list_append (&loader->messages, message))
4272  {
4273  _dbus_verbose ("Failed to append new message to loader queue\n");
4274  oom = TRUE;
4275  goto failed;
4276  }
4277 
4278  _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4279  _dbus_assert (_dbus_string_get_length (&loader->data) >=
4280  (header_len + body_len));
4281 
4282  if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
4283  {
4284  _dbus_verbose ("Failed to move body into new message\n");
4285  oom = TRUE;
4286  goto failed;
4287  }
4288 
4289  _dbus_string_delete (&loader->data, 0, header_len + body_len);
4290 
4291  /* don't waste more than 2k of memory */
4292  _dbus_string_compact (&loader->data, 2048);
4293 
4294  _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
4295  _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4296 
4297  _dbus_verbose ("Loaded message %p\n", message);
4298 
4299  _dbus_assert (!oom);
4300  _dbus_assert (!loader->corrupted);
4301  _dbus_assert (loader->messages != NULL);
4302  _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4303 
4304  return TRUE;
4305 
4306  failed:
4307 
4308  /* Clean up */
4309 
4310  /* does nothing if the message isn't in the list */
4311  _dbus_list_remove_last (&loader->messages, message);
4312 
4313  if (oom)
4314  _dbus_assert (!loader->corrupted);
4315  else
4316  _dbus_assert (loader->corrupted);
4317 
4318  _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
4319 
4320  return FALSE;
4321 }
4322 
4339 {
4340  while (!loader->corrupted &&
4341  _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
4342  {
4343  DBusValidity validity;
4344  int byte_order, fields_array_len, header_len, body_len;
4345 
4347  &validity,
4348  &byte_order,
4349  &fields_array_len,
4350  &header_len,
4351  &body_len,
4352  &loader->data, 0,
4353  _dbus_string_get_length (&loader->data)))
4354  {
4356 
4357  _dbus_assert (validity == DBUS_VALID);
4358 
4359  message = dbus_message_new_empty_header ();
4360  if (message == NULL)
4361  return FALSE;
4362 
4363  if (!load_message (loader, message,
4364  byte_order, fields_array_len,
4365  header_len, body_len))
4366  {
4367  dbus_message_unref (message);
4368  /* load_message() returns false if corrupted or OOM; if
4369  * corrupted then return TRUE for not OOM
4370  */
4371  return loader->corrupted;
4372  }
4373 
4374  _dbus_assert (loader->messages != NULL);
4375  _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4376  }
4377  else
4378  {
4379  _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
4380  validity);
4381  if (validity != DBUS_VALID)
4382  {
4383  loader->corrupted = TRUE;
4384  loader->corruption_reason = validity;
4385  }
4386  return TRUE;
4387  }
4388  }
4389 
4390  return TRUE;
4391 }
4392 
4400 DBusMessage*
4402 {
4403  if (loader->messages)
4404  return loader->messages->data;
4405  else
4406  return NULL;
4407 }
4408 
4417 DBusMessage*
4419 {
4420  return _dbus_list_pop_first (&loader->messages);
4421 }
4422 
4431 DBusList*
4433 {
4434  return _dbus_list_pop_first_link (&loader->messages);
4435 }
4436 
4443 void
4445  DBusList *link)
4446 {
4447  _dbus_list_prepend_link (&loader->messages, link);
4448 }
4449 
4461 {
4462  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4463  (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4464  return loader->corrupted;
4465 }
4466 
4475 {
4476  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4477  (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4478 
4479  return loader->corruption_reason;
4480 }
4481 
4488 void
4490  long size)
4491 {
4492  if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
4493  {
4494  _dbus_verbose ("clamping requested max message size %ld to %d\n",
4497  }
4498  loader->max_message_size = size;
4499 }
4500 
4507 long
4509 {
4510  return loader->max_message_size;
4511 }
4512 
4519 void
4521  long n)
4522 {
4524  {
4525  _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
4528  }
4529  loader->max_message_unix_fds = n;
4530 }
4531 
4538 long
4540 {
4541  return loader->max_message_unix_fds;
4542 }
4543 
4549 int
4551 {
4552 #ifdef HAVE_UNIX_FD_PASSING
4553  return loader->n_unix_fds;
4554 #else
4555  return 0;
4556 #endif
4557 }
4558 
4567 void
4569  void (* callback) (void *),
4570  void *data)
4571 {
4572 #ifdef HAVE_UNIX_FD_PASSING
4573  loader->unix_fds_change = callback;
4574  loader->unix_fds_change_data = data;
4575 #endif
4576 }
4577 
4578 static DBusDataSlotAllocator slot_allocator =
4579  _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
4580 
4596 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
4597 {
4598  return _dbus_data_slot_allocator_alloc (&slot_allocator,
4599  slot_p);
4600 }
4601 
4613 void
4614 dbus_message_free_data_slot (dbus_int32_t *slot_p)
4615 {
4616  _dbus_return_if_fail (*slot_p >= 0);
4617 
4618  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
4619 }
4620 
4636  dbus_int32_t slot,
4637  void *data,
4638  DBusFreeFunction free_data_func)
4639 {
4640  DBusFreeFunction old_free_func;
4641  void *old_data;
4642  dbus_bool_t retval;
4643 
4644  _dbus_return_val_if_fail (message != NULL, FALSE);
4645  _dbus_return_val_if_fail (slot >= 0, FALSE);
4646 
4647  retval = _dbus_data_slot_list_set (&slot_allocator,
4648  &message->slot_list,
4649  slot, data, free_data_func,
4650  &old_free_func, &old_data);
4651 
4652  if (retval)
4653  {
4654  /* Do the actual free outside the message lock */
4655  if (old_free_func)
4656  (* old_free_func) (old_data);
4657  }
4658 
4659  return retval;
4660 }
4661 
4670 void*
4672  dbus_int32_t slot)
4673 {
4674  void *res;
4675 
4676  _dbus_return_val_if_fail (message != NULL, NULL);
4677 
4678  res = _dbus_data_slot_list_get (&slot_allocator,
4679  &message->slot_list,
4680  slot);
4681 
4682  return res;
4683 }
4684 
4698 int
4699 dbus_message_type_from_string (const char *type_str)
4700 {
4701  if (strcmp (type_str, "method_call") == 0)
4703  if (strcmp (type_str, "method_return") == 0)
4705  else if (strcmp (type_str, "signal") == 0)
4706  return DBUS_MESSAGE_TYPE_SIGNAL;
4707  else if (strcmp (type_str, "error") == 0)
4708  return DBUS_MESSAGE_TYPE_ERROR;
4709  else
4711 }
4712 
4726 const char *
4728 {
4729  switch (type)
4730  {
4732  return "method_call";
4734  return "method_return";
4736  return "signal";
4738  return "error";
4739  default:
4740  return "invalid";
4741  }
4742 }
4743 
4758  char **marshalled_data_p,
4759  int *len_p)
4760 {
4761  DBusString tmp;
4762  dbus_bool_t was_locked;
4763 
4764  _dbus_return_val_if_fail (msg != NULL, FALSE);
4765  _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
4766  _dbus_return_val_if_fail (len_p != NULL, FALSE);
4767 
4768  if (!_dbus_string_init (&tmp))
4769  return FALSE;
4770 
4771  /* Ensure the message is locked, to ensure the length header is filled in. */
4772  was_locked = msg->locked;
4773 
4774  if (!was_locked)
4775  dbus_message_lock (msg);
4776 
4777  if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
4778  goto fail;
4779 
4780  *len_p = _dbus_string_get_length (&tmp);
4781 
4782  if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
4783  goto fail;
4784 
4785  *len_p = _dbus_string_get_length (&tmp);
4786 
4787  if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
4788  goto fail;
4789 
4790  _dbus_string_free (&tmp);
4791 
4792  if (!was_locked)
4793  msg->locked = FALSE;
4794 
4795  return TRUE;
4796 
4797  fail:
4798  _dbus_string_free (&tmp);
4799 
4800  if (!was_locked)
4801  msg->locked = FALSE;
4802 
4803  return FALSE;
4804 }
4805 
4818 DBusMessage *
4819 dbus_message_demarshal (const char *str,
4820  int len,
4821  DBusError *error)
4822 {
4823  DBusMessageLoader *loader;
4824  DBusString *buffer;
4825  DBusMessage *msg;
4826 
4827  _dbus_return_val_if_fail (str != NULL, NULL);
4828 
4829  loader = _dbus_message_loader_new ();
4830 
4831  if (loader == NULL)
4832  return NULL;
4833 
4834  _dbus_message_loader_get_buffer (loader, &buffer);
4835 
4836  if (!_dbus_string_append_len (buffer, str, len))
4837  goto fail_oom;
4838 
4839  _dbus_message_loader_return_buffer (loader, buffer);
4840 
4842  goto fail_oom;
4843 
4845  goto fail_corrupt;
4846 
4847  msg = _dbus_message_loader_pop_message (loader);
4848 
4849  if (!msg)
4850  goto fail_oom;
4851 
4852  _dbus_message_loader_unref (loader);
4853  return msg;
4854 
4855  fail_corrupt:
4856  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
4857  _dbus_validity_to_error_message (loader->corruption_reason));
4858  _dbus_message_loader_unref (loader);
4859  return NULL;
4860 
4861  fail_oom:
4862  _DBUS_SET_OOM (error);
4863  _dbus_message_loader_unref (loader);
4864  return NULL;
4865 }
4866 
4879 int
4881  int len)
4882 {
4883  DBusString str;
4884  int byte_order, fields_array_len, header_len, body_len;
4885  DBusValidity validity = DBUS_VALID;
4886  int have_message;
4887 
4888  if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
4889  return 0;
4890 
4891  if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
4893  _dbus_string_init_const_len (&str, buf, len);
4894 
4895  validity = DBUS_VALID;
4896  have_message
4898  &validity, &byte_order,
4899  &fields_array_len,
4900  &header_len,
4901  &body_len,
4902  &str, 0,
4903  len);
4904  _dbus_string_free (&str);
4905 
4906  if (validity == DBUS_VALID)
4907  {
4908  _dbus_assert (have_message || (header_len + body_len) > len);
4909  (void) have_message; /* unused unless asserting */
4910  return header_len + body_len;
4911  }
4912  else
4913  {
4914  return -1; /* broken! */
4915  }
4916 }
4917 
4939 void
4941  dbus_bool_t allow)
4942 {
4943  _dbus_return_if_fail (message != NULL);
4944  _dbus_return_if_fail (!message->locked);
4945 
4946  _dbus_header_toggle_flag (&message->header,
4948  allow);
4949 }
4950 
4959 {
4960  _dbus_return_val_if_fail (message != NULL, FALSE);
4961 
4962  return _dbus_header_get_flag (&message->header,
4964 }
4965 
4968 /* 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...
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...
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...
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&#39;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&#39;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&#39;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_PRIVATE_EXPORT 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&#39;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&#39;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
dbus_bool_t dbus_message_get_allow_interactive_authorization(DBusMessage *message)
Returns whether the flag controlled by dbus_message_set_allow_interactive_authorization() has been se...
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.
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:1072
int _dbus_dup(int fd, DBusError *error)
Duplicates a file descriptor.
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&#39;s copied to the d...
Definition: dbus-string.c:1283
#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_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:389
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&#39;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&#39;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:1193
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&#39;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&#39;s in the cache (this is a debug feature)
int dbus_message_iter_get_element_count(DBusMessageIter *iter)
Returns the number of elements in the array-typed value pointed to by the iterator.
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
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_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()
#define DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION
If set on a method call, this flag means that the caller is prepared to wait for interactive authoriz...
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:259
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&#39;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:1137
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&#39;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&#39;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.
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
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.
void dbus_message_set_allow_interactive_authorization(DBusMessage *message, dbus_bool_t allow)
Sets a flag indicating that the caller of the method is prepared to wait for interactive authorizatio...
#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:802
DBUS_PRIVATE_EXPORT 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:1375
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:641
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...
DBUS_PRIVATE_EXPORT 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.
char * _dbus_strdup(const char *str)
Duplicates a string.
#define MAX_MESSAGE_SIZE_TO_CACHE
Avoid caching huge messages.
Definition: dbus-message.c:505
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:185
#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...