D-Bus  1.10.24
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 
144 typedef struct
145 {
146  void *dummy1;
147  void *dummy2;
148  dbus_uint32_t dummy3;
149  int dummy4;
150  int dummy5;
151  int dummy6;
152  int dummy7;
153  int dummy8;
154  int dummy9;
155  int dummy10;
156  int dummy11;
157  int pad1;
158  int pad2;
159  void *pad3;
161 
162 static void
163 get_const_signature (DBusHeader *header,
164  const DBusString **type_str_p,
165  int *type_pos_p)
166 {
167  if (_dbus_header_get_field_raw (header,
169  type_str_p,
170  type_pos_p))
171  {
172  *type_pos_p += 1; /* skip the signature length which is 1 byte */
173  }
174  else
175  {
176  *type_str_p = &_dbus_empty_signature_str;
177  *type_pos_p = 0;
178  }
179 }
180 
186 static void
187 _dbus_message_byteswap (DBusMessage *message)
188 {
189  const DBusString *type_str;
190  int type_pos;
191  char byte_order;
192 
193  byte_order = _dbus_header_get_byte_order (&message->header);
194 
195  if (byte_order == DBUS_COMPILER_BYTE_ORDER)
196  return;
197 
198  _dbus_verbose ("Swapping message into compiler byte order\n");
199 
200  get_const_signature (&message->header, &type_str, &type_pos);
201 
202  _dbus_marshal_byteswap (type_str, type_pos,
203  byte_order,
204  DBUS_COMPILER_BYTE_ORDER,
205  &message->body, 0);
206 
207  _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
209  DBUS_COMPILER_BYTE_ORDER);
210 }
211 
218 #define ensure_byte_order(message) _dbus_message_byteswap (message)
219 
230 void
232  const DBusString **header,
233  const DBusString **body)
234 {
235  _dbus_assert (message->locked);
236 
237  *header = &message->header.data;
238  *body = &message->body;
239 }
240 
251  const int **fds,
252  unsigned *n_fds)
253 {
254  _dbus_assert (message->locked);
255 
256 #ifdef HAVE_UNIX_FD_PASSING
257  *fds = message->unix_fds;
258  *n_fds = message->n_unix_fds;
259 #else
260  *fds = NULL;
261  *n_fds = 0;
262 #endif
263 }
264 
276 void
278  dbus_uint32_t serial)
279 {
280  _dbus_return_if_fail (message != NULL);
281  _dbus_return_if_fail (!message->locked);
282 
283  _dbus_header_set_serial (&message->header, serial);
284 }
285 
302 void
304  DBusList *link)
305 {
306  /* right now we don't recompute the delta when message
307  * size changes, and that's OK for current purposes
308  * I think, but could be important to change later.
309  * Do recompute it whenever there are no outstanding counters,
310  * since it's basically free.
311  */
312  if (message->counters == NULL)
313  {
314  message->size_counter_delta =
315  _dbus_string_get_length (&message->header.data) +
316  _dbus_string_get_length (&message->body);
317 
318 #ifdef HAVE_UNIX_FD_PASSING
319  message->unix_fd_counter_delta = message->n_unix_fds;
320 #endif
321 
322 #if 0
323  _dbus_verbose ("message has size %ld\n",
324  message->size_counter_delta);
325 #endif
326  }
327 
328  _dbus_list_append_link (&message->counters, link);
329 
331 
332 #ifdef HAVE_UNIX_FD_PASSING
333  _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
334 #endif
335 }
336 
353  DBusCounter *counter)
354 {
355  DBusList *link;
356 
357  link = _dbus_list_alloc_link (counter);
358  if (link == NULL)
359  return FALSE;
360 
361  _dbus_counter_ref (counter);
362  _dbus_message_add_counter_link (message, link);
363 
364  return TRUE;
365 }
366 
374 void
376  DBusCounter *counter)
377 {
378  DBusList *link;
379 
380  link = _dbus_list_find_last (&message->counters,
381  counter);
382  _dbus_assert (link != NULL);
383 
384  _dbus_list_remove_link (&message->counters, link);
385 
386  _dbus_counter_adjust_size (counter, - message->size_counter_delta);
387 
388 #ifdef HAVE_UNIX_FD_PASSING
389  _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
390 #endif
391 
392  _dbus_counter_notify (counter);
393  _dbus_counter_unref (counter);
394 }
395 
406 void
408 {
409  if (!message->locked)
410  {
412  _dbus_string_get_length (&message->body));
413 
414  /* must have a signature if you have a body */
415  _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
416  dbus_message_get_signature (message) != NULL);
417 
418  message->locked = TRUE;
419  }
420 }
421 
422 static dbus_bool_t
423 set_or_delete_string_field (DBusMessage *message,
424  int field,
425  int typecode,
426  const char *value)
427 {
428  if (value == NULL)
429  return _dbus_header_delete_field (&message->header, field);
430  else
431  return _dbus_header_set_field_basic (&message->header,
432  field,
433  typecode,
434  &value);
435 }
436 
437 #if 0
438 /* Probably we don't need to use this */
462 static dbus_bool_t
463 _dbus_message_set_signature (DBusMessage *message,
464  const char *signature)
465 {
466  _dbus_return_val_if_fail (message != NULL, FALSE);
467  _dbus_return_val_if_fail (!message->locked, FALSE);
468  _dbus_return_val_if_fail (signature == NULL ||
469  _dbus_check_is_valid_signature (signature));
470  /* can't delete the signature if you have a message body */
471  _dbus_return_val_if_fail (_dbus_string_get_length (&message->body) == 0 ||
472  signature != NULL);
473 
474  return set_or_delete_string_field (message,
477  signature);
478 }
479 #endif
480 
481 /* Message Cache
482  *
483  * We cache some DBusMessage to reduce the overhead of allocating
484  * them. In my profiling this consistently made about an 8%
485  * difference. It avoids the malloc for the message, the malloc for
486  * the slot list, the malloc for the header string and body string,
487  * and the associated free() calls. It does introduce another global
488  * lock which could be a performance issue in certain cases.
489  *
490  * For the echo client/server the round trip time goes from around
491  * .000077 to .000069 with the message cache on my laptop. The sysprof
492  * change is as follows (numbers are cumulative percentage):
493  *
494  * with message cache implemented as array as it is now (0.000069 per):
495  * new_empty_header 1.46
496  * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache)
497  * mutex_unlock 0.25
498  * self 0.41
499  * unref 2.24
500  * self 0.68
501  * list_clear 0.43
502  * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache)
503  * mutex_unlock 0.25
504  *
505  * with message cache implemented as list (0.000070 per roundtrip):
506  * new_empty_header 2.72
507  * list_pop_first 1.88
508  * unref 3.3
509  * list_prepend 1.63
510  *
511  * without cache (0.000077 per roundtrip):
512  * new_empty_header 6.7
513  * string_init_preallocated 3.43
514  * dbus_malloc 2.43
515  * dbus_malloc0 2.59
516  *
517  * unref 4.02
518  * string_free 1.82
519  * dbus_free 1.63
520  * dbus_free 0.71
521  *
522  * If you implement the message_cache with a list, the primary reason
523  * it's slower is that you add another thread lock (on the DBusList
524  * mempool).
525  */
526 
528 #define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
529 
531 #define MAX_MESSAGE_CACHE_SIZE 5
532 
533 /* Protected by _DBUS_LOCK (message_cache) */
534 static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
535 static int message_cache_count = 0;
536 static dbus_bool_t message_cache_shutdown_registered = FALSE;
537 
538 static void
539 dbus_message_cache_shutdown (void *data)
540 {
541  int i;
542 
543  if (!_DBUS_LOCK (message_cache))
544  _dbus_assert_not_reached ("we would have initialized global locks "
545  "before registering a shutdown function");
546 
547  i = 0;
548  while (i < MAX_MESSAGE_CACHE_SIZE)
549  {
550  if (message_cache[i])
551  dbus_message_finalize (message_cache[i]);
552 
553  ++i;
554  }
555 
556  message_cache_count = 0;
557  message_cache_shutdown_registered = FALSE;
558 
559  _DBUS_UNLOCK (message_cache);
560 }
561 
569 static DBusMessage*
570 dbus_message_get_cached (void)
571 {
572  DBusMessage *message;
573  int i;
574 
575  message = NULL;
576 
577  if (!_DBUS_LOCK (message_cache))
578  {
579  /* we'd have initialized global locks before caching anything,
580  * so there can't be anything in the cache */
581  return NULL;
582  }
583 
584  _dbus_assert (message_cache_count >= 0);
585 
586  if (message_cache_count == 0)
587  {
588  _DBUS_UNLOCK (message_cache);
589  return NULL;
590  }
591 
592  /* This is not necessarily true unless count > 0, and
593  * message_cache is uninitialized until the shutdown is
594  * registered
595  */
596  _dbus_assert (message_cache_shutdown_registered);
597 
598  i = 0;
599  while (i < MAX_MESSAGE_CACHE_SIZE)
600  {
601  if (message_cache[i])
602  {
603  message = message_cache[i];
604  message_cache[i] = NULL;
605  message_cache_count -= 1;
606  break;
607  }
608  ++i;
609  }
610  _dbus_assert (message_cache_count >= 0);
612  _dbus_assert (message != NULL);
613 
614  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
615 
616  _dbus_assert (message->counters == NULL);
617 
618  _DBUS_UNLOCK (message_cache);
619 
620  return message;
621 }
622 
623 #ifdef HAVE_UNIX_FD_PASSING
624 static void
625 close_unix_fds(int *fds, unsigned *n_fds)
626 {
627  DBusError e;
628  unsigned int i;
629 
630  if (*n_fds <= 0)
631  return;
632 
633  dbus_error_init(&e);
634 
635  for (i = 0; i < *n_fds; i++)
636  {
637  if (!_dbus_close(fds[i], &e))
638  {
639  _dbus_warn("Failed to close file descriptor: %s\n", e.message);
640  dbus_error_free(&e);
641  }
642  }
643 
644  *n_fds = 0;
645 
646  /* We don't free the array here, in case we can recycle it later */
647 }
648 #endif
649 
650 static void
651 free_counter (void *element,
652  void *data)
653 {
654  DBusCounter *counter = element;
655  DBusMessage *message = data;
656 
657  _dbus_counter_adjust_size (counter, - message->size_counter_delta);
658 #ifdef HAVE_UNIX_FD_PASSING
659  _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
660 #endif
661 
662  _dbus_counter_notify (counter);
663  _dbus_counter_unref (counter);
664 }
665 
671 static void
672 dbus_message_cache_or_finalize (DBusMessage *message)
673 {
674  dbus_bool_t was_cached;
675  int i;
676 
677  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
678 
679  /* This calls application code and has to be done first thing
680  * without holding the lock
681  */
683 
684  _dbus_list_foreach (&message->counters,
685  free_counter, message);
686  _dbus_list_clear (&message->counters);
687 
688 #ifdef HAVE_UNIX_FD_PASSING
689  close_unix_fds(message->unix_fds, &message->n_unix_fds);
690 #endif
691 
692  was_cached = FALSE;
693 
694  if (!_DBUS_LOCK (message_cache))
695  {
696  /* The only way to get a non-null message goes through
697  * dbus_message_get_cached() which takes the lock. */
698  _dbus_assert_not_reached ("we would have initialized global locks "
699  "the first time we constructed a message");
700  }
701 
702  if (!message_cache_shutdown_registered)
703  {
704  _dbus_assert (message_cache_count == 0);
705 
706  if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
707  goto out;
708 
709  i = 0;
710  while (i < MAX_MESSAGE_CACHE_SIZE)
711  {
712  message_cache[i] = NULL;
713  ++i;
714  }
715 
716  message_cache_shutdown_registered = TRUE;
717  }
718 
719  _dbus_assert (message_cache_count >= 0);
720 
721  if (!_dbus_enable_message_cache ())
722  goto out;
723 
724  if ((_dbus_string_get_length (&message->header.data) +
725  _dbus_string_get_length (&message->body)) >
727  goto out;
728 
729  if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
730  goto out;
731 
732  /* Find empty slot */
733  i = 0;
734  while (message_cache[i] != NULL)
735  ++i;
736 
738 
739  _dbus_assert (message_cache[i] == NULL);
740  message_cache[i] = message;
741  message_cache_count += 1;
742  was_cached = TRUE;
743 #ifndef DBUS_DISABLE_CHECKS
744  message->in_cache = TRUE;
745 #endif
746 
747  out:
748  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
749 
750  _DBUS_UNLOCK (message_cache);
751 
752  if (!was_cached)
753  dbus_message_finalize (message);
754 }
755 
756 #if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
757 static dbus_bool_t
758 _dbus_message_iter_check (DBusMessageRealIter *iter)
759 {
760  char byte_order;
761 
762  if (iter == NULL)
763  {
764  _dbus_warn_check_failed ("dbus message iterator is NULL\n");
765  return FALSE;
766  }
767 
768  byte_order = _dbus_header_get_byte_order (&iter->message->header);
769 
770  if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
771  {
772  if (iter->u.reader.byte_order != byte_order)
773  {
774  _dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
775  return FALSE;
776  }
777  /* because we swap the message into compiler order when you init an iter */
778  _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
779  }
780  else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
781  {
782  if (iter->u.writer.byte_order != byte_order)
783  {
784  _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
785  return FALSE;
786  }
787  /* because we swap the message into compiler order when you init an iter */
788  _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
789  }
790  else
791  {
792  _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted\n");
793  return FALSE;
794  }
795 
796  if (iter->changed_stamp != iter->message->changed_stamp)
797  {
798  _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)\n");
799  return FALSE;
800  }
801 
802  return TRUE;
803 }
804 #endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */
805 
820  DBusError *error,
821  int first_arg_type,
822  va_list var_args)
823 {
825  int spec_type, msg_type, i, j;
826  dbus_bool_t retval;
827  va_list copy_args;
828 
829  _dbus_assert (_dbus_message_iter_check (real));
830 
831  retval = FALSE;
832 
833  spec_type = first_arg_type;
834  i = 0;
835 
836  /* copy var_args first, then we can do another iteration over it to
837  * free memory and close unix fds if parse failed at some point.
838  */
839  DBUS_VA_COPY (copy_args, var_args);
840 
841  while (spec_type != DBUS_TYPE_INVALID)
842  {
843  msg_type = dbus_message_iter_get_arg_type (iter);
844 
845  if (msg_type != spec_type)
846  {
848  "Argument %d is specified to be of type \"%s\", but "
849  "is actually of type \"%s\"\n", i,
850  _dbus_type_to_string (spec_type),
851  _dbus_type_to_string (msg_type));
852 
853  goto out;
854  }
855 
856  if (spec_type == DBUS_TYPE_UNIX_FD)
857  {
858 #ifdef HAVE_UNIX_FD_PASSING
859  DBusBasicValue idx;
860  int *pfd, nfd;
861 
862  pfd = va_arg (var_args, int*);
863  _dbus_assert(pfd);
864 
865  _dbus_type_reader_read_basic(&real->u.reader, &idx);
866 
867  if (idx.u32 >= real->message->n_unix_fds)
868  {
870  "Message refers to file descriptor at index %i,"
871  "but has only %i descriptors attached.\n",
872  idx.u32,
873  real->message->n_unix_fds);
874  goto out;
875  }
876 
877  if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
878  goto out;
879 
880  *pfd = nfd;
881 #else
883  "Platform does not support file desciptor passing.\n");
884  goto out;
885 #endif
886  }
887  else if (dbus_type_is_basic (spec_type))
888  {
889  DBusBasicValue *ptr;
890 
891  ptr = va_arg (var_args, DBusBasicValue*);
892 
893  _dbus_assert (ptr != NULL);
894 
896  ptr);
897  }
898  else if (spec_type == DBUS_TYPE_ARRAY)
899  {
900  int element_type;
901  int spec_element_type;
902  const DBusBasicValue **ptr;
903  int *n_elements_p;
904  DBusTypeReader array;
905 
906  spec_element_type = va_arg (var_args, int);
907  element_type = _dbus_type_reader_get_element_type (&real->u.reader);
908 
909  if (spec_element_type != element_type)
910  {
912  "Argument %d is specified to be an array of \"%s\", but "
913  "is actually an array of \"%s\"\n",
914  i,
915  _dbus_type_to_string (spec_element_type),
916  _dbus_type_to_string (element_type));
917 
918  goto out;
919  }
920 
921  if (dbus_type_is_fixed (spec_element_type) &&
922  element_type != DBUS_TYPE_UNIX_FD)
923  {
924  ptr = va_arg (var_args, const DBusBasicValue**);
925  n_elements_p = va_arg (var_args, int*);
926 
927  _dbus_assert (ptr != NULL);
928  _dbus_assert (n_elements_p != NULL);
929 
930  _dbus_type_reader_recurse (&real->u.reader, &array);
931 
933  (void *) ptr, n_elements_p);
934  }
935  else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
936  {
937  char ***str_array_p;
938  int n_elements;
939  char **str_array;
940 
941  str_array_p = va_arg (var_args, char***);
942  n_elements_p = va_arg (var_args, int*);
943 
944  _dbus_assert (str_array_p != NULL);
945  _dbus_assert (n_elements_p != NULL);
946 
947  /* Count elements in the array */
948  _dbus_type_reader_recurse (&real->u.reader, &array);
949 
950  n_elements = 0;
952  {
953  ++n_elements;
954  _dbus_type_reader_next (&array);
955  }
956 
957  str_array = dbus_new0 (char*, n_elements + 1);
958  if (str_array == NULL)
959  {
960  _DBUS_SET_OOM (error);
961  goto out;
962  }
963 
964  /* Now go through and dup each string */
965  _dbus_type_reader_recurse (&real->u.reader, &array);
966 
967  j = 0;
968  while (j < n_elements)
969  {
970  const char *s;
972  (void *) &s);
973 
974  str_array[j] = _dbus_strdup (s);
975  if (str_array[j] == NULL)
976  {
977  dbus_free_string_array (str_array);
978  _DBUS_SET_OOM (error);
979  goto out;
980  }
981 
982  ++j;
983 
984  if (!_dbus_type_reader_next (&array))
985  _dbus_assert (j == n_elements);
986  }
987 
989  _dbus_assert (j == n_elements);
990  _dbus_assert (str_array[j] == NULL);
991 
992  *str_array_p = str_array;
993  *n_elements_p = n_elements;
994  }
995 #ifndef DBUS_DISABLE_CHECKS
996  else
997  {
998  _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now\n",
999  _DBUS_FUNCTION_NAME);
1000  goto out;
1001  }
1002 #endif
1003  }
1004 #ifndef DBUS_DISABLE_CHECKS
1005  else
1006  {
1007  _dbus_warn ("you can only read arrays and basic types with %s for now\n",
1008  _DBUS_FUNCTION_NAME);
1009  goto out;
1010  }
1011 #endif
1012 
1013  /* how many arguments already handled */
1014  i++;
1015 
1016  spec_type = va_arg (var_args, int);
1017  if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
1018  {
1020  "Message has only %d arguments, but more were expected", i);
1021  goto out;
1022  }
1023  }
1024 
1025  retval = TRUE;
1026 
1027  out:
1028  /* there may memory or unix fd leak in the above iteration if parse failed.
1029  * so we have another iteration over copy_args to free memory and close
1030  * unix fds.
1031  */
1032  if (!retval)
1033  {
1034  spec_type = first_arg_type;
1035  j = 0;
1036 
1037  while (j < i)
1038  {
1039  if (spec_type == DBUS_TYPE_UNIX_FD)
1040  {
1041 #ifdef HAVE_UNIX_FD_PASSING
1042  int *pfd;
1043 
1044  pfd = va_arg (copy_args, int *);
1045  _dbus_assert(pfd);
1046  if (*pfd >= 0)
1047  {
1048  _dbus_close (*pfd, NULL);
1049  *pfd = -1;
1050  }
1051 #endif
1052  }
1053  else if (dbus_type_is_basic (spec_type))
1054  {
1055  /* move the index forward */
1056  va_arg (copy_args, DBusBasicValue *);
1057  }
1058  else if (spec_type == DBUS_TYPE_ARRAY)
1059  {
1060  int spec_element_type;
1061 
1062  spec_element_type = va_arg (copy_args, int);
1063  if (dbus_type_is_fixed (spec_element_type))
1064  {
1065  /* move the index forward */
1066  va_arg (copy_args, const DBusBasicValue **);
1067  va_arg (copy_args, int *);
1068  }
1069  else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
1070  {
1071  char ***str_array_p;
1072 
1073  str_array_p = va_arg (copy_args, char ***);
1074  /* move the index forward */
1075  va_arg (copy_args, int *);
1076  _dbus_assert (str_array_p != NULL);
1077  dbus_free_string_array (*str_array_p);
1078  *str_array_p = NULL;
1079  }
1080  }
1081 
1082  spec_type = va_arg (copy_args, int);
1083  j++;
1084  }
1085  }
1086 
1087  va_end (copy_args);
1088  return retval;
1089 }
1090 
1149 dbus_uint32_t
1151 {
1152  _dbus_return_val_if_fail (message != NULL, 0);
1153 
1154  return _dbus_header_get_serial (&message->header);
1155 }
1156 
1167  dbus_uint32_t reply_serial)
1168 {
1169  DBusBasicValue value;
1170 
1171  _dbus_return_val_if_fail (message != NULL, FALSE);
1172  _dbus_return_val_if_fail (!message->locked, FALSE);
1173  _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
1174 
1175  value.u32 = reply_serial;
1176 
1177  return _dbus_header_set_field_basic (&message->header,
1180  &value);
1181 }
1182 
1189 dbus_uint32_t
1191 {
1192  dbus_uint32_t v_UINT32;
1193 
1194  _dbus_return_val_if_fail (message != NULL, 0);
1195 
1196  if (_dbus_header_get_field_basic (&message->header,
1199  &v_UINT32))
1200  return v_UINT32;
1201  else
1202  return 0;
1203 }
1204 
1205 static void
1206 dbus_message_finalize (DBusMessage *message)
1207 {
1208  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1209 
1210  /* This calls application callbacks! */
1212 
1213  _dbus_list_foreach (&message->counters,
1214  free_counter, message);
1215  _dbus_list_clear (&message->counters);
1216 
1217  _dbus_header_free (&message->header);
1218  _dbus_string_free (&message->body);
1219 
1220 #ifdef HAVE_UNIX_FD_PASSING
1221  close_unix_fds(message->unix_fds, &message->n_unix_fds);
1222  dbus_free(message->unix_fds);
1223 #endif
1224 
1225  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1226 
1227  dbus_free (message);
1228 }
1229 
1230 static DBusMessage*
1231 dbus_message_new_empty_header (void)
1232 {
1233  DBusMessage *message;
1234  dbus_bool_t from_cache;
1235 
1236  message = dbus_message_get_cached ();
1237 
1238  if (message != NULL)
1239  {
1240  from_cache = TRUE;
1241  }
1242  else
1243  {
1244  from_cache = FALSE;
1245  message = dbus_new0 (DBusMessage, 1);
1246  if (message == NULL)
1247  return NULL;
1248 #ifndef DBUS_DISABLE_CHECKS
1250 #endif
1251 
1252 #ifdef HAVE_UNIX_FD_PASSING
1253  message->unix_fds = NULL;
1254  message->n_unix_fds_allocated = 0;
1255 #endif
1256  }
1257 
1258  _dbus_atomic_inc (&message->refcount);
1259 
1260  _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
1261 
1262  message->locked = FALSE;
1263 #ifndef DBUS_DISABLE_CHECKS
1264  message->in_cache = FALSE;
1265 #endif
1266  message->counters = NULL;
1267  message->size_counter_delta = 0;
1268  message->changed_stamp = 0;
1269 
1270 #ifdef HAVE_UNIX_FD_PASSING
1271  message->n_unix_fds = 0;
1272  message->n_unix_fds_allocated = 0;
1273  message->unix_fd_counter_delta = 0;
1274 #endif
1275 
1276  if (!from_cache)
1278 
1279  if (from_cache)
1280  {
1281  _dbus_header_reinit (&message->header);
1282  _dbus_string_set_length (&message->body, 0);
1283  }
1284  else
1285  {
1286  if (!_dbus_header_init (&message->header))
1287  {
1288  dbus_free (message);
1289  return NULL;
1290  }
1291 
1292  if (!_dbus_string_init_preallocated (&message->body, 32))
1293  {
1294  _dbus_header_free (&message->header);
1295  dbus_free (message);
1296  return NULL;
1297  }
1298  }
1299 
1300  return message;
1301 }
1302 
1315 DBusMessage*
1316 dbus_message_new (int message_type)
1317 {
1318  DBusMessage *message;
1319 
1320  _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
1321 
1322  message = dbus_message_new_empty_header ();
1323  if (message == NULL)
1324  return NULL;
1325 
1326  if (!_dbus_header_create (&message->header,
1327  DBUS_COMPILER_BYTE_ORDER,
1328  message_type,
1329  NULL, NULL, NULL, NULL, NULL))
1330  {
1331  dbus_message_unref (message);
1332  return NULL;
1333  }
1334 
1335  return message;
1336 }
1337 
1359 DBusMessage*
1360 dbus_message_new_method_call (const char *destination,
1361  const char *path,
1362  const char *iface,
1363  const char *method)
1364 {
1365  DBusMessage *message;
1366 
1367  _dbus_return_val_if_fail (path != NULL, NULL);
1368  _dbus_return_val_if_fail (method != NULL, NULL);
1369  _dbus_return_val_if_fail (destination == NULL ||
1370  _dbus_check_is_valid_bus_name (destination), NULL);
1371  _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1372  _dbus_return_val_if_fail (iface == NULL ||
1373  _dbus_check_is_valid_interface (iface), NULL);
1374  _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
1375 
1376  message = dbus_message_new_empty_header ();
1377  if (message == NULL)
1378  return NULL;
1379 
1380  if (!_dbus_header_create (&message->header,
1381  DBUS_COMPILER_BYTE_ORDER,
1383  destination, path, iface, method, NULL))
1384  {
1385  dbus_message_unref (message);
1386  return NULL;
1387  }
1388 
1389  return message;
1390 }
1391 
1399 DBusMessage*
1401 {
1402  DBusMessage *message;
1403  const char *sender;
1404 
1405  _dbus_return_val_if_fail (method_call != NULL, NULL);
1406 
1407  sender = dbus_message_get_sender (method_call);
1408 
1409  /* sender is allowed to be null here in peer-to-peer case */
1410 
1411  message = dbus_message_new_empty_header ();
1412  if (message == NULL)
1413  return NULL;
1414 
1415  if (!_dbus_header_create (&message->header,
1416  DBUS_COMPILER_BYTE_ORDER,
1418  sender, NULL, NULL, NULL, NULL))
1419  {
1420  dbus_message_unref (message);
1421  return NULL;
1422  }
1423 
1424  dbus_message_set_no_reply (message, TRUE);
1425 
1426  if (!dbus_message_set_reply_serial (message,
1427  dbus_message_get_serial (method_call)))
1428  {
1429  dbus_message_unref (message);
1430  return NULL;
1431  }
1432 
1433  return message;
1434 }
1435 
1450 DBusMessage*
1451 dbus_message_new_signal (const char *path,
1452  const char *iface,
1453  const char *name)
1454 {
1455  DBusMessage *message;
1456 
1457  _dbus_return_val_if_fail (path != NULL, NULL);
1458  _dbus_return_val_if_fail (iface != NULL, NULL);
1459  _dbus_return_val_if_fail (name != NULL, NULL);
1460  _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1461  _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
1462  _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
1463 
1464  message = dbus_message_new_empty_header ();
1465  if (message == NULL)
1466  return NULL;
1467 
1468  if (!_dbus_header_create (&message->header,
1469  DBUS_COMPILER_BYTE_ORDER,
1471  NULL, path, iface, name, NULL))
1472  {
1473  dbus_message_unref (message);
1474  return NULL;
1475  }
1476 
1477  dbus_message_set_no_reply (message, TRUE);
1478 
1479  return message;
1480 }
1481 
1496 DBusMessage*
1498  const char *error_name,
1499  const char *error_message)
1500 {
1501  DBusMessage *message;
1502  const char *sender;
1503  DBusMessageIter iter;
1504 
1505  _dbus_return_val_if_fail (reply_to != NULL, NULL);
1506  _dbus_return_val_if_fail (error_name != NULL, NULL);
1507  _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1508 
1509  sender = dbus_message_get_sender (reply_to);
1510 
1511  /* sender may be NULL for non-message-bus case or
1512  * when the message bus is dealing with an unregistered
1513  * connection.
1514  */
1515  message = dbus_message_new_empty_header ();
1516  if (message == NULL)
1517  return NULL;
1518 
1519  if (!_dbus_header_create (&message->header,
1520  DBUS_COMPILER_BYTE_ORDER,
1522  sender, NULL, NULL, NULL, error_name))
1523  {
1524  dbus_message_unref (message);
1525  return NULL;
1526  }
1527 
1528  dbus_message_set_no_reply (message, TRUE);
1529 
1530  if (!dbus_message_set_reply_serial (message,
1531  dbus_message_get_serial (reply_to)))
1532  {
1533  dbus_message_unref (message);
1534  return NULL;
1535  }
1536 
1537  if (error_message != NULL)
1538  {
1539  dbus_message_iter_init_append (message, &iter);
1540  if (!dbus_message_iter_append_basic (&iter,
1542  &error_message))
1543  {
1544  dbus_message_unref (message);
1545  return NULL;
1546  }
1547  }
1548 
1549  return message;
1550 }
1551 
1568 DBusMessage*
1570  const char *error_name,
1571  const char *error_format,
1572  ...)
1573 {
1574  va_list args;
1575  DBusString str;
1576  DBusMessage *message;
1577 
1578  _dbus_return_val_if_fail (reply_to != NULL, NULL);
1579  _dbus_return_val_if_fail (error_name != NULL, NULL);
1580  _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1581 
1582  if (!_dbus_string_init (&str))
1583  return NULL;
1584 
1585  va_start (args, error_format);
1586 
1587  if (_dbus_string_append_printf_valist (&str, error_format, args))
1588  message = dbus_message_new_error (reply_to, error_name,
1589  _dbus_string_get_const_data (&str));
1590  else
1591  message = NULL;
1592 
1593  _dbus_string_free (&str);
1594 
1595  va_end (args);
1596 
1597  return message;
1598 }
1599 
1600 
1613 DBusMessage *
1615 {
1616  DBusMessage *retval;
1617 
1618  _dbus_return_val_if_fail (message != NULL, NULL);
1619 
1620  retval = dbus_new0 (DBusMessage, 1);
1621  if (retval == NULL)
1622  return NULL;
1623 
1624  _dbus_atomic_inc (&retval->refcount);
1625 
1626  retval->locked = FALSE;
1627 #ifndef DBUS_DISABLE_CHECKS
1628  retval->generation = message->generation;
1629 #endif
1630 
1631  if (!_dbus_header_copy (&message->header, &retval->header))
1632  {
1633  dbus_free (retval);
1634  return NULL;
1635  }
1636 
1637  if (!_dbus_string_init_preallocated (&retval->body,
1638  _dbus_string_get_length (&message->body)))
1639  {
1640  _dbus_header_free (&retval->header);
1641  dbus_free (retval);
1642  return NULL;
1643  }
1644 
1645  if (!_dbus_string_copy (&message->body, 0,
1646  &retval->body, 0))
1647  goto failed_copy;
1648 
1649 #ifdef HAVE_UNIX_FD_PASSING
1650  retval->unix_fds = dbus_new(int, message->n_unix_fds);
1651  if (retval->unix_fds == NULL && message->n_unix_fds > 0)
1652  goto failed_copy;
1653 
1654  retval->n_unix_fds_allocated = message->n_unix_fds;
1655 
1656  for (retval->n_unix_fds = 0;
1657  retval->n_unix_fds < message->n_unix_fds;
1658  retval->n_unix_fds++)
1659  {
1660  retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
1661 
1662  if (retval->unix_fds[retval->n_unix_fds] < 0)
1663  goto failed_copy;
1664  }
1665 
1666 #endif
1667 
1668  _dbus_message_trace_ref (retval, 0, 1, "copy");
1669  return retval;
1670 
1671  failed_copy:
1672  _dbus_header_free (&retval->header);
1673  _dbus_string_free (&retval->body);
1674 
1675 #ifdef HAVE_UNIX_FD_PASSING
1676  close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
1677  dbus_free(retval->unix_fds);
1678 #endif
1679 
1680  dbus_free (retval);
1681 
1682  return NULL;
1683 }
1684 
1685 
1693 DBusMessage *
1695 {
1696  dbus_int32_t old_refcount;
1697 
1698  _dbus_return_val_if_fail (message != NULL, NULL);
1699  _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
1700  _dbus_return_val_if_fail (!message->in_cache, NULL);
1701 
1702  old_refcount = _dbus_atomic_inc (&message->refcount);
1703  _dbus_assert (old_refcount >= 1);
1704  _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
1705 
1706  return message;
1707 }
1708 
1716 void
1718 {
1719  dbus_int32_t old_refcount;
1720 
1721  _dbus_return_if_fail (message != NULL);
1722  _dbus_return_if_fail (message->generation == _dbus_current_generation);
1723  _dbus_return_if_fail (!message->in_cache);
1724 
1725  old_refcount = _dbus_atomic_dec (&message->refcount);
1726 
1727  _dbus_assert (old_refcount >= 1);
1728 
1729  _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
1730 
1731  if (old_refcount == 1)
1732  {
1733  /* Calls application callbacks! */
1734  dbus_message_cache_or_finalize (message);
1735  }
1736 }
1737 
1748 int
1750 {
1751  _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
1752 
1753  return _dbus_header_get_message_type (&message->header);
1754 }
1755 
1820  int first_arg_type,
1821  ...)
1822 {
1823  dbus_bool_t retval;
1824  va_list var_args;
1825 
1826  _dbus_return_val_if_fail (message != NULL, FALSE);
1827 
1828  va_start (var_args, first_arg_type);
1829  retval = dbus_message_append_args_valist (message,
1830  first_arg_type,
1831  var_args);
1832  va_end (var_args);
1833 
1834  return retval;
1835 }
1836 
1852  int first_arg_type,
1853  va_list var_args)
1854 {
1855  int type;
1856  DBusMessageIter iter;
1857 
1858  _dbus_return_val_if_fail (message != NULL, FALSE);
1859 
1860  type = first_arg_type;
1861 
1862  dbus_message_iter_init_append (message, &iter);
1863 
1864  while (type != DBUS_TYPE_INVALID)
1865  {
1866  if (dbus_type_is_basic (type))
1867  {
1868  const DBusBasicValue *value;
1869  value = va_arg (var_args, const DBusBasicValue*);
1870 
1871  if (!dbus_message_iter_append_basic (&iter,
1872  type,
1873  value))
1874  goto failed;
1875  }
1876  else if (type == DBUS_TYPE_ARRAY)
1877  {
1878  int element_type;
1879  DBusMessageIter array;
1880  char buf[2];
1881 
1882  element_type = va_arg (var_args, int);
1883 
1884  buf[0] = element_type;
1885  buf[1] = '\0';
1888  buf,
1889  &array))
1890  goto failed;
1891 
1892  if (dbus_type_is_fixed (element_type) &&
1893  element_type != DBUS_TYPE_UNIX_FD)
1894  {
1895  const DBusBasicValue **value;
1896  int n_elements;
1897 
1898  value = va_arg (var_args, const DBusBasicValue**);
1899  n_elements = va_arg (var_args, int);
1900 
1902  element_type,
1903  value,
1904  n_elements)) {
1905  dbus_message_iter_abandon_container (&iter, &array);
1906  goto failed;
1907  }
1908  }
1909  else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
1910  {
1911  const char ***value_p;
1912  const char **value;
1913  int n_elements;
1914  int i;
1915 
1916  value_p = va_arg (var_args, const char***);
1917  n_elements = va_arg (var_args, int);
1918 
1919  value = *value_p;
1920 
1921  i = 0;
1922  while (i < n_elements)
1923  {
1924  if (!dbus_message_iter_append_basic (&array,
1925  element_type,
1926  &value[i])) {
1927  dbus_message_iter_abandon_container (&iter, &array);
1928  goto failed;
1929  }
1930  ++i;
1931  }
1932  }
1933  else
1934  {
1935  _dbus_warn ("arrays of %s can't be appended with %s for now\n",
1936  _dbus_type_to_string (element_type),
1937  _DBUS_FUNCTION_NAME);
1938  dbus_message_iter_abandon_container (&iter, &array);
1939  goto failed;
1940  }
1941 
1942  if (!dbus_message_iter_close_container (&iter, &array))
1943  goto failed;
1944  }
1945 #ifndef DBUS_DISABLE_CHECKS
1946  else
1947  {
1948  _dbus_warn ("type %s isn't supported yet in %s\n",
1949  _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
1950  goto failed;
1951  }
1952 #endif
1953 
1954  type = va_arg (var_args, int);
1955  }
1956 
1957  return TRUE;
1958 
1959  failed:
1960  return FALSE;
1961 }
1962 
2009  DBusError *error,
2010  int first_arg_type,
2011  ...)
2012 {
2013  dbus_bool_t retval;
2014  va_list var_args;
2015 
2016  _dbus_return_val_if_fail (message != NULL, FALSE);
2017  _dbus_return_val_if_error_is_set (error, FALSE);
2018 
2019  va_start (var_args, first_arg_type);
2020  retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
2021  va_end (var_args);
2022 
2023  return retval;
2024 }
2025 
2038  DBusError *error,
2039  int first_arg_type,
2040  va_list var_args)
2041 {
2042  DBusMessageIter iter;
2043 
2044  _dbus_return_val_if_fail (message != NULL, FALSE);
2045  _dbus_return_val_if_error_is_set (error, FALSE);
2046 
2047  dbus_message_iter_init (message, &iter);
2048  return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
2049 }
2050 
2051 static void
2052 _dbus_message_iter_init_common (DBusMessage *message,
2053  DBusMessageRealIter *real,
2054  int iter_type)
2055 {
2056  /* If these static assertions fail on your platform, report it as a bug. */
2057  _DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
2058  _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <=
2059  _DBUS_ALIGNOF (DBusMessageIter));
2060  /* A failure of these two assertions would indicate that we've broken
2061  * ABI on this platform since 1.10.0. */
2062  _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) ==
2063  sizeof (DBusMessageIter));
2064  _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) ==
2065  _DBUS_ALIGNOF (DBusMessageIter));
2066  /* If this static assertion fails, it means the DBusMessageIter struct
2067  * is not "packed", which might result in "iter = other_iter" not copying
2068  * every byte. */
2069  _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) ==
2070  4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int));
2071 
2072  /* Since the iterator will read or write who-knows-what from the
2073  * message, we need to get in the right byte order
2074  */
2075  ensure_byte_order (message);
2076 
2077  real->message = message;
2078  real->changed_stamp = message->changed_stamp;
2079  real->iter_type = iter_type;
2080  real->sig_refcount = 0;
2081 }
2082 
2107  DBusMessageIter *iter)
2108 {
2109  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2110  const DBusString *type_str;
2111  int type_pos;
2112 
2113  _dbus_return_val_if_fail (message != NULL, FALSE);
2114  _dbus_return_val_if_fail (iter != NULL, FALSE);
2115 
2116  get_const_signature (&message->header, &type_str, &type_pos);
2117 
2118  _dbus_message_iter_init_common (message, real,
2119  DBUS_MESSAGE_ITER_TYPE_READER);
2120 
2122  _dbus_header_get_byte_order (&message->header),
2123  type_str, type_pos,
2124  &message->body,
2125  0);
2126 
2128 }
2129 
2138 {
2139  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2140 
2141  _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2142  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2143 
2144  return _dbus_type_reader_has_next (&real->u.reader);
2145 }
2146 
2157 {
2158  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2159 
2160  _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2161  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2162 
2163  return _dbus_type_reader_next (&real->u.reader);
2164 }
2165 
2180 int
2182 {
2183  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2184 
2185  _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2186  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2187 
2189 }
2190 
2199 int
2201 {
2202  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2203 
2204  _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2205  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
2206  _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
2207 
2209 }
2210 
2236 void
2238  DBusMessageIter *sub)
2239 {
2240  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2241  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2242 
2243  _dbus_return_if_fail (_dbus_message_iter_check (real));
2244  _dbus_return_if_fail (sub != NULL);
2245 
2246  *real_sub = *real;
2247  _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
2248 }
2249 
2261 char *
2263 {
2264  const DBusString *sig;
2265  DBusString retstr;
2266  char *ret;
2267  int start, len;
2268  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2269 
2270  _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
2271 
2272  if (!_dbus_string_init (&retstr))
2273  return NULL;
2274 
2276  &start, &len);
2277  if (!_dbus_string_append_len (&retstr,
2278  _dbus_string_get_const_data (sig) + start,
2279  len))
2280  return NULL;
2281  if (!_dbus_string_steal_data (&retstr, &ret))
2282  return NULL;
2283  _dbus_string_free (&retstr);
2284  return ret;
2285 }
2286 
2334 void
2336  void *value)
2337 {
2338  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2339 
2340  _dbus_return_if_fail (_dbus_message_iter_check (real));
2341  _dbus_return_if_fail (value != NULL);
2342 
2344  {
2345 #ifdef HAVE_UNIX_FD_PASSING
2346  DBusBasicValue idx;
2347 
2348  _dbus_type_reader_read_basic(&real->u.reader, &idx);
2349 
2350  if (idx.u32 >= real->message->n_unix_fds) {
2351  /* Hmm, we cannot really signal an error here, so let's make
2352  sure to return an invalid fd. */
2353  *((int*) value) = -1;
2354  return;
2355  }
2356 
2357  *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
2358 #else
2359  *((int*) value) = -1;
2360 #endif
2361  }
2362  else
2363  {
2365  value);
2366  }
2367 }
2368 
2379 int
2381 {
2382  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2383  DBusTypeReader array;
2384  int element_type;
2385  int n_elements = 0;
2386 
2387  _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2388  _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
2389  == DBUS_TYPE_ARRAY, 0);
2390 
2391  element_type = _dbus_type_reader_get_element_type (&real->u.reader);
2392  _dbus_type_reader_recurse (&real->u.reader, &array);
2393  if (dbus_type_is_fixed (element_type))
2394  {
2395  int alignment = _dbus_type_get_alignment (element_type);
2396  int total_len = _dbus_type_reader_get_array_length (&array);
2397  n_elements = total_len / alignment;
2398  }
2399  else
2400  {
2402  {
2403  ++n_elements;
2404  _dbus_type_reader_next (&array);
2405  }
2406  }
2407 
2408  return n_elements;
2409 }
2410 
2423 int
2425 {
2426  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2427 
2428  _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2429 
2431 }
2432 
2468 void
2470  void *value,
2471  int *n_elements)
2472 {
2473  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2474 #ifndef DBUS_DISABLE_CHECKS
2475  int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
2476 
2477  _dbus_return_if_fail (_dbus_message_iter_check (real));
2478  _dbus_return_if_fail (value != NULL);
2479  _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
2480  (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
2481 #endif
2482 
2484  value, n_elements);
2485 }
2486 
2498 void
2500  DBusMessageIter *iter)
2501 {
2502  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2503 
2504  _dbus_return_if_fail (message != NULL);
2505  _dbus_return_if_fail (iter != NULL);
2506 
2507  _dbus_message_iter_init_common (message, real,
2508  DBUS_MESSAGE_ITER_TYPE_WRITER);
2509 
2510  /* We create the signature string and point iterators at it "on demand"
2511  * when a value is actually appended. That means that init() never fails
2512  * due to OOM.
2513  */
2515  _dbus_header_get_byte_order (&message->header),
2516  &message->body,
2517  _dbus_string_get_length (&message->body));
2518 }
2519 
2528 static dbus_bool_t
2529 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
2530 {
2531  DBusString *str;
2532  const DBusString *current_sig;
2533  int current_sig_pos;
2534 
2535  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2536 
2537  if (real->u.writer.type_str != NULL)
2538  {
2539  _dbus_assert (real->sig_refcount > 0);
2540  real->sig_refcount += 1;
2541  return TRUE;
2542  }
2543 
2544  str = dbus_new (DBusString, 1);
2545  if (str == NULL)
2546  return FALSE;
2547 
2550  &current_sig, &current_sig_pos))
2551  current_sig = NULL;
2552 
2553  if (current_sig)
2554  {
2555  int current_len;
2556 
2557  current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
2558  current_sig_pos += 1; /* move on to sig data */
2559 
2560  if (!_dbus_string_init_preallocated (str, current_len + 4))
2561  {
2562  dbus_free (str);
2563  return FALSE;
2564  }
2565 
2566  if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
2567  str, 0))
2568  {
2569  _dbus_string_free (str);
2570  dbus_free (str);
2571  return FALSE;
2572  }
2573  }
2574  else
2575  {
2576  if (!_dbus_string_init_preallocated (str, 4))
2577  {
2578  dbus_free (str);
2579  return FALSE;
2580  }
2581  }
2582 
2583  real->sig_refcount = 1;
2584 
2586  str, _dbus_string_get_length (str));
2587  return TRUE;
2588 }
2589 
2599 static dbus_bool_t
2600 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
2601 {
2602  DBusString *str;
2603  const char *v_STRING;
2604  dbus_bool_t retval;
2605 
2606  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2607  _dbus_assert (real->u.writer.type_str != NULL);
2608  _dbus_assert (real->sig_refcount > 0);
2609 
2610  real->sig_refcount -= 1;
2611 
2612  if (real->sig_refcount > 0)
2613  return TRUE;
2614  _dbus_assert (real->sig_refcount == 0);
2615 
2616  retval = TRUE;
2617 
2618  str = real->u.writer.type_str;
2619 
2620  v_STRING = _dbus_string_get_const_data (str);
2624  &v_STRING))
2625  retval = FALSE;
2626 
2628  _dbus_string_free (str);
2629  dbus_free (str);
2630 
2631  return retval;
2632 }
2633 
2641 static void
2642 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
2643 {
2644  DBusString *str;
2645 
2646  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2647  _dbus_assert (real->u.writer.type_str != NULL);
2648  _dbus_assert (real->sig_refcount > 0);
2649 
2650  real->sig_refcount -= 1;
2651 
2652  if (real->sig_refcount > 0)
2653  return;
2654  _dbus_assert (real->sig_refcount == 0);
2655 
2656  str = real->u.writer.type_str;
2657 
2659  _dbus_string_free (str);
2660  dbus_free (str);
2661 }
2662 
2663 #ifndef DBUS_DISABLE_CHECKS
2664 static dbus_bool_t
2665 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
2666 {
2667  if (!_dbus_message_iter_check (iter))
2668  return FALSE;
2669 
2670  if (iter->message->locked)
2671  {
2672  _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
2673  return FALSE;
2674  }
2675 
2676  return TRUE;
2677 }
2678 #endif /* DBUS_DISABLE_CHECKS */
2679 
2680 #ifdef HAVE_UNIX_FD_PASSING
2681 static int *
2682 expand_fd_array(DBusMessage *m,
2683  unsigned n)
2684 {
2685  _dbus_assert(m);
2686 
2687  /* This makes space for adding n new fds to the array and returns a
2688  pointer to the place were the first fd should be put. */
2689 
2690  if (m->n_unix_fds + n > m->n_unix_fds_allocated)
2691  {
2692  unsigned k;
2693  int *p;
2694 
2695  /* Make twice as much space as necessary */
2696  k = (m->n_unix_fds + n) * 2;
2697 
2698  /* Allocate at least four */
2699  if (k < 4)
2700  k = 4;
2701 
2702  p = dbus_realloc(m->unix_fds, k * sizeof(int));
2703  if (p == NULL)
2704  return NULL;
2705 
2706  m->unix_fds = p;
2707  m->n_unix_fds_allocated = k;
2708  }
2709 
2710  return m->unix_fds + m->n_unix_fds;
2711 }
2712 #endif
2713 
2735  int type,
2736  const void *value)
2737 {
2738  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2739  dbus_bool_t ret;
2740 
2741  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2742  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2743  _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
2744  _dbus_return_val_if_fail (value != NULL, FALSE);
2745 
2746 #ifndef DBUS_DISABLE_CHECKS
2747  switch (type)
2748  {
2749  const char * const *string_p;
2750  const dbus_bool_t *bool_p;
2751 
2752  case DBUS_TYPE_STRING:
2753  string_p = value;
2754  _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
2755  break;
2756 
2757  case DBUS_TYPE_OBJECT_PATH:
2758  string_p = value;
2759  _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
2760  break;
2761 
2762  case DBUS_TYPE_SIGNATURE:
2763  string_p = value;
2764  _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
2765  break;
2766 
2767  case DBUS_TYPE_BOOLEAN:
2768  bool_p = value;
2769  _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
2770  break;
2771 
2772  default:
2773  {
2774  /* nothing to check, all possible values are allowed */
2775  }
2776  }
2777 #endif
2778 
2779  if (!_dbus_message_iter_open_signature (real))
2780  return FALSE;
2781 
2782  if (type == DBUS_TYPE_UNIX_FD)
2783  {
2784 #ifdef HAVE_UNIX_FD_PASSING
2785  int *fds;
2786  dbus_uint32_t u;
2787 
2788  ret = FALSE;
2789 
2790  /* First step, include the fd in the fd list of this message */
2791  if (!(fds = expand_fd_array(real->message, 1)))
2792  goto out;
2793 
2794  *fds = _dbus_dup(*(int*) value, NULL);
2795  if (*fds < 0)
2796  goto out;
2797 
2798  u = real->message->n_unix_fds;
2799 
2800  /* Second step, write the index to the fd */
2801  if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
2802  _dbus_close(*fds, NULL);
2803  goto out;
2804  }
2805 
2806  real->message->n_unix_fds += 1;
2807  u += 1;
2808 
2809  /* Final step, update the header accordingly */
2813  &u);
2814 
2815  /* If any of these operations fail the message is
2816  hosed. However, no memory or fds should be leaked since what
2817  has been added to message has been added to the message, and
2818  can hence be accounted for when the message is being
2819  freed. */
2820 #else
2821  ret = FALSE;
2822  /* This is redundant (we could just fall through), but it avoids
2823  * -Wunused-label in builds that don't HAVE_UNIX_FD_PASSING */
2824  goto out;
2825 #endif
2826  }
2827  else
2828  {
2829  ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
2830  }
2831 
2832 out:
2833  if (!_dbus_message_iter_close_signature (real))
2834  ret = FALSE;
2835 
2836  return ret;
2837 }
2838 
2876  int element_type,
2877  const void *value,
2878  int n_elements)
2879 {
2880  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2881  dbus_bool_t ret;
2882 
2883  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2884  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2885  _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
2886  _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
2887  _dbus_return_val_if_fail (value != NULL, FALSE);
2888  _dbus_return_val_if_fail (n_elements >= 0, FALSE);
2889  _dbus_return_val_if_fail (n_elements <=
2891  FALSE);
2892 
2893 #ifndef DBUS_DISABLE_CHECKS
2894  if (element_type == DBUS_TYPE_BOOLEAN)
2895  {
2896  const dbus_bool_t * const *bools = value;
2897  int i;
2898 
2899  for (i = 0; i < n_elements; i++)
2900  {
2901  _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
2902  }
2903  }
2904 #endif
2905 
2906  ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
2907 
2908  return ret;
2909 }
2910 
2934  int type,
2935  const char *contained_signature,
2936  DBusMessageIter *sub)
2937 {
2938  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2939  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2940  DBusString contained_str;
2941  dbus_bool_t ret;
2942 
2943  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2944  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2945  _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
2946  _dbus_return_val_if_fail (sub != NULL, FALSE);
2947  _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
2948  contained_signature == NULL) ||
2949  (type == DBUS_TYPE_DICT_ENTRY &&
2950  contained_signature == NULL) ||
2951  (type == DBUS_TYPE_VARIANT &&
2952  contained_signature != NULL) ||
2953  (type == DBUS_TYPE_ARRAY &&
2954  contained_signature != NULL), FALSE);
2955 
2956  /* this would fail if the contained_signature is a dict entry, since
2957  * dict entries are invalid signatures standalone (they must be in
2958  * an array)
2959  */
2960  _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
2961  (contained_signature == NULL ||
2962  _dbus_check_is_valid_signature (contained_signature)),
2963  FALSE);
2964 
2965  if (!_dbus_message_iter_open_signature (real))
2966  return FALSE;
2967 
2968  ret = FALSE;
2969  *real_sub = *real;
2970 
2971  if (contained_signature != NULL)
2972  {
2973  _dbus_string_init_const (&contained_str, contained_signature);
2974 
2975  ret = _dbus_type_writer_recurse (&real->u.writer,
2976  type,
2977  &contained_str, 0,
2978  &real_sub->u.writer);
2979  }
2980  else
2981  {
2982  ret = _dbus_type_writer_recurse (&real->u.writer,
2983  type,
2984  NULL, 0,
2985  &real_sub->u.writer);
2986  }
2987 
2988  if (!ret)
2989  _dbus_message_iter_abandon_signature (real);
2990 
2991  return ret;
2992 }
2993 
2994 
3010  DBusMessageIter *sub)
3011 {
3012  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3013  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3014  dbus_bool_t ret;
3015 
3016  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
3017  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3018  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
3019  _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3020 
3021  ret = _dbus_type_writer_unrecurse (&real->u.writer,
3022  &real_sub->u.writer);
3023 
3024  if (!_dbus_message_iter_close_signature (real))
3025  ret = FALSE;
3026 
3027  return ret;
3028 }
3029 
3041 void
3043  DBusMessageIter *sub)
3044 {
3045  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3046 #ifndef DBUS_DISABLE_CHECKS
3047  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3048 
3049  _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3050  _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3051  _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3052  _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3053 #endif
3054 
3055  _dbus_message_iter_abandon_signature (real);
3056 }
3057 
3074 void
3076  dbus_bool_t no_reply)
3077 {
3078  _dbus_return_if_fail (message != NULL);
3079  _dbus_return_if_fail (!message->locked);
3080 
3081  _dbus_header_toggle_flag (&message->header,
3083  no_reply);
3084 }
3085 
3095 {
3096  _dbus_return_val_if_fail (message != NULL, FALSE);
3097 
3098  return _dbus_header_get_flag (&message->header,
3100 }
3101 
3116 void
3118  dbus_bool_t auto_start)
3119 {
3120  _dbus_return_if_fail (message != NULL);
3121  _dbus_return_if_fail (!message->locked);
3122 
3123  _dbus_header_toggle_flag (&message->header,
3125  !auto_start);
3126 }
3127 
3137 {
3138  _dbus_return_val_if_fail (message != NULL, FALSE);
3139 
3140  return !_dbus_header_get_flag (&message->header,
3142 }
3143 
3144 
3159  const char *object_path)
3160 {
3161  _dbus_return_val_if_fail (message != NULL, FALSE);
3162  _dbus_return_val_if_fail (!message->locked, FALSE);
3163  _dbus_return_val_if_fail (object_path == NULL ||
3164  _dbus_check_is_valid_path (object_path),
3165  FALSE);
3166 
3167  return set_or_delete_string_field (message,
3170  object_path);
3171 }
3172 
3186 const char*
3188 {
3189  const char *v;
3190 
3191  _dbus_return_val_if_fail (message != NULL, NULL);
3192 
3193  v = NULL; /* in case field doesn't exist */
3197  (void *) &v);
3198  return v;
3199 }
3200 
3212  const char *path)
3213 {
3214  const char *msg_path;
3215  msg_path = dbus_message_get_path (message);
3216 
3217  if (msg_path == NULL)
3218  {
3219  if (path == NULL)
3220  return TRUE;
3221  else
3222  return FALSE;
3223  }
3224 
3225  if (path == NULL)
3226  return FALSE;
3227 
3228  if (strcmp (msg_path, path) == 0)
3229  return TRUE;
3230 
3231  return FALSE;
3232 }
3233 
3256  char ***path)
3257 {
3258  const char *v;
3259 
3260  _dbus_return_val_if_fail (message != NULL, FALSE);
3261  _dbus_return_val_if_fail (path != NULL, FALSE);
3262 
3263  *path = NULL;
3264 
3265  v = dbus_message_get_path (message);
3266  if (v != NULL)
3267  {
3268  if (!_dbus_decompose_path (v, strlen (v),
3269  path, NULL))
3270  return FALSE;
3271  }
3272  return TRUE;
3273 }
3274 
3290  const char *iface)
3291 {
3292  _dbus_return_val_if_fail (message != NULL, FALSE);
3293  _dbus_return_val_if_fail (!message->locked, FALSE);
3294  _dbus_return_val_if_fail (iface == NULL ||
3295  _dbus_check_is_valid_interface (iface),
3296  FALSE);
3297 
3298  return set_or_delete_string_field (message,
3301  iface);
3302 }
3303 
3317 const char*
3319 {
3320  const char *v;
3321 
3322  _dbus_return_val_if_fail (message != NULL, NULL);
3323 
3324  v = NULL; /* in case field doesn't exist */
3328  (void *) &v);
3329  return v;
3330 }
3331 
3341  const char *iface)
3342 {
3343  const char *msg_interface;
3344  msg_interface = dbus_message_get_interface (message);
3345 
3346  if (msg_interface == NULL)
3347  {
3348  if (iface == NULL)
3349  return TRUE;
3350  else
3351  return FALSE;
3352  }
3353 
3354  if (iface == NULL)
3355  return FALSE;
3356 
3357  if (strcmp (msg_interface, iface) == 0)
3358  return TRUE;
3359 
3360  return FALSE;
3361 
3362 }
3363 
3378  const char *member)
3379 {
3380  _dbus_return_val_if_fail (message != NULL, FALSE);
3381  _dbus_return_val_if_fail (!message->locked, FALSE);
3382  _dbus_return_val_if_fail (member == NULL ||
3383  _dbus_check_is_valid_member (member),
3384  FALSE);
3385 
3386  return set_or_delete_string_field (message,
3389  member);
3390 }
3391 
3403 const char*
3405 {
3406  const char *v;
3407 
3408  _dbus_return_val_if_fail (message != NULL, NULL);
3409 
3410  v = NULL; /* in case field doesn't exist */
3414  (void *) &v);
3415  return v;
3416 }
3417 
3427  const char *member)
3428 {
3429  const char *msg_member;
3430  msg_member = dbus_message_get_member (message);
3431 
3432  if (msg_member == NULL)
3433  {
3434  if (member == NULL)
3435  return TRUE;
3436  else
3437  return FALSE;
3438  }
3439 
3440  if (member == NULL)
3441  return FALSE;
3442 
3443  if (strcmp (msg_member, member) == 0)
3444  return TRUE;
3445 
3446  return FALSE;
3447 
3448 }
3449 
3463  const char *error_name)
3464 {
3465  _dbus_return_val_if_fail (message != NULL, FALSE);
3466  _dbus_return_val_if_fail (!message->locked, FALSE);
3467  _dbus_return_val_if_fail (error_name == NULL ||
3468  _dbus_check_is_valid_error_name (error_name),
3469  FALSE);
3470 
3471  return set_or_delete_string_field (message,
3474  error_name);
3475 }
3476 
3487 const char*
3489 {
3490  const char *v;
3491 
3492  _dbus_return_val_if_fail (message != NULL, NULL);
3493 
3494  v = NULL; /* in case field doesn't exist */
3498  (void *) &v);
3499  return v;
3500 }
3501 
3517  const char *destination)
3518 {
3519  _dbus_return_val_if_fail (message != NULL, FALSE);
3520  _dbus_return_val_if_fail (!message->locked, FALSE);
3521  _dbus_return_val_if_fail (destination == NULL ||
3522  _dbus_check_is_valid_bus_name (destination),
3523  FALSE);
3524 
3525  return set_or_delete_string_field (message,
3528  destination);
3529 }
3530 
3540 const char*
3542 {
3543  const char *v;
3544 
3545  _dbus_return_val_if_fail (message != NULL, NULL);
3546 
3547  v = NULL; /* in case field doesn't exist */
3551  (void *) &v);
3552  return v;
3553 }
3554 
3571  const char *sender)
3572 {
3573  _dbus_return_val_if_fail (message != NULL, FALSE);
3574  _dbus_return_val_if_fail (!message->locked, FALSE);
3575  _dbus_return_val_if_fail (sender == NULL ||
3576  _dbus_check_is_valid_bus_name (sender),
3577  FALSE);
3578 
3579  return set_or_delete_string_field (message,
3582  sender);
3583 }
3584 
3600 const char*
3602 {
3603  const char *v;
3604 
3605  _dbus_return_val_if_fail (message != NULL, NULL);
3606 
3607  v = NULL; /* in case field doesn't exist */
3611  (void *) &v);
3612  return v;
3613 }
3614 
3633 const char*
3635 {
3636  const DBusString *type_str;
3637  int type_pos;
3638 
3639  _dbus_return_val_if_fail (message != NULL, NULL);
3640 
3641  get_const_signature (&message->header, &type_str, &type_pos);
3642 
3643  return _dbus_string_get_const_data_len (type_str, type_pos, 0);
3644 }
3645 
3646 static dbus_bool_t
3647 _dbus_message_has_type_interface_member (DBusMessage *message,
3648  int type,
3649  const char *iface,
3650  const char *member)
3651 {
3652  const char *n;
3653 
3654  _dbus_assert (message != NULL);
3655  _dbus_assert (iface != NULL);
3656  _dbus_assert (member != NULL);
3657 
3658  if (dbus_message_get_type (message) != type)
3659  return FALSE;
3660 
3661  /* Optimize by checking the short member name first
3662  * instead of the longer interface name
3663  */
3664 
3665  n = dbus_message_get_member (message);
3666 
3667  if (n && strcmp (n, member) == 0)
3668  {
3669  n = dbus_message_get_interface (message);
3670 
3671  if (n == NULL || strcmp (n, iface) == 0)
3672  return TRUE;
3673  }
3674 
3675  return FALSE;
3676 }
3677 
3694  const char *iface,
3695  const char *method)
3696 {
3697  _dbus_return_val_if_fail (message != NULL, FALSE);
3698  _dbus_return_val_if_fail (iface != NULL, FALSE);
3699  _dbus_return_val_if_fail (method != NULL, FALSE);
3700  /* don't check that interface/method are valid since it would be
3701  * expensive, and not catch many common errors
3702  */
3703 
3704  return _dbus_message_has_type_interface_member (message,
3706  iface, method);
3707 }
3708 
3722  const char *iface,
3723  const char *signal_name)
3724 {
3725  _dbus_return_val_if_fail (message != NULL, FALSE);
3726  _dbus_return_val_if_fail (iface != NULL, FALSE);
3727  _dbus_return_val_if_fail (signal_name != NULL, FALSE);
3728  /* don't check that interface/name are valid since it would be
3729  * expensive, and not catch many common errors
3730  */
3731 
3732  return _dbus_message_has_type_interface_member (message,
3734  iface, signal_name);
3735 }
3736 
3749  const char *error_name)
3750 {
3751  const char *n;
3752 
3753  _dbus_return_val_if_fail (message != NULL, FALSE);
3754  _dbus_return_val_if_fail (error_name != NULL, FALSE);
3755  /* don't check that error_name is valid since it would be expensive,
3756  * and not catch many common errors
3757  */
3758 
3760  return FALSE;
3761 
3762  n = dbus_message_get_error_name (message);
3763 
3764  if (n && strcmp (n, error_name) == 0)
3765  return TRUE;
3766  else
3767  return FALSE;
3768 }
3769 
3782  const char *name)
3783 {
3784  const char *s;
3785 
3786  _dbus_return_val_if_fail (message != NULL, FALSE);
3787  _dbus_return_val_if_fail (name != NULL, FALSE);
3788  /* don't check that name is valid since it would be expensive, and
3789  * not catch many common errors
3790  */
3791 
3792  s = dbus_message_get_destination (message);
3793 
3794  if (s && strcmp (s, name) == 0)
3795  return TRUE;
3796  else
3797  return FALSE;
3798 }
3799 
3817  const char *name)
3818 {
3819  const char *s;
3820 
3821  _dbus_return_val_if_fail (message != NULL, FALSE);
3822  _dbus_return_val_if_fail (name != NULL, FALSE);
3823  /* don't check that name is valid since it would be expensive, and
3824  * not catch many common errors
3825  */
3826 
3827  s = dbus_message_get_sender (message);
3828 
3829  if (s && strcmp (s, name) == 0)
3830  return TRUE;
3831  else
3832  return FALSE;
3833 }
3834 
3846  const char *signature)
3847 {
3848  const char *s;
3849 
3850  _dbus_return_val_if_fail (message != NULL, FALSE);
3851  _dbus_return_val_if_fail (signature != NULL, FALSE);
3852  /* don't check that signature is valid since it would be expensive,
3853  * and not catch many common errors
3854  */
3855 
3856  s = dbus_message_get_signature (message);
3857 
3858  if (s && strcmp (s, signature) == 0)
3859  return TRUE;
3860  else
3861  return FALSE;
3862 }
3863 
3888  DBusMessage *message)
3889 {
3890  const char *str;
3891 
3892  _dbus_return_val_if_fail (message != NULL, FALSE);
3893  _dbus_return_val_if_error_is_set (error, FALSE);
3894 
3896  return FALSE;
3897 
3898  str = NULL;
3899  dbus_message_get_args (message, NULL,
3900  DBUS_TYPE_STRING, &str,
3902 
3903  dbus_set_error (error, dbus_message_get_error_name (message),
3904  str ? "%s" : NULL, str);
3905 
3906  return TRUE;
3907 }
3908 
3917 {
3918 #ifdef HAVE_UNIX_FD_PASSING
3919  _dbus_assert(message);
3920 
3921  return message->n_unix_fds > 0;
3922 #else
3923  return FALSE;
3924 #endif
3925 }
3926 
3945 #define INITIAL_LOADER_DATA_LEN 32
3946 
3955 {
3956  DBusMessageLoader *loader;
3957 
3958  loader = dbus_new0 (DBusMessageLoader, 1);
3959  if (loader == NULL)
3960  return NULL;
3961 
3962  loader->refcount = 1;
3963 
3964  loader->corrupted = FALSE;
3965  loader->corruption_reason = DBUS_VALID;
3966 
3967  /* this can be configured by the app, but defaults to the protocol max */
3969 
3970  /* We set a very relatively conservative default here since due to how
3971  SCM_RIGHTS works we need to preallocate an fd array of the maximum
3972  number of unix fds we want to receive in advance. A
3973  try-and-reallocate loop is not possible. */
3974  loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
3975 
3976  if (!_dbus_string_init (&loader->data))
3977  {
3978  dbus_free (loader);
3979  return NULL;
3980  }
3981 
3982  /* preallocate the buffer for speed, ignore failure */
3984  _dbus_string_set_length (&loader->data, 0);
3985 
3986 #ifdef HAVE_UNIX_FD_PASSING
3987  loader->unix_fds = NULL;
3988  loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
3989  loader->unix_fds_outstanding = FALSE;
3990 #endif
3991 
3992  return loader;
3993 }
3994 
4003 {
4004  loader->refcount += 1;
4005 
4006  return loader;
4007 }
4008 
4015 void
4017 {
4018  loader->refcount -= 1;
4019  if (loader->refcount == 0)
4020  {
4021 #ifdef HAVE_UNIX_FD_PASSING
4022  close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
4023  dbus_free(loader->unix_fds);
4024 #endif
4025  _dbus_list_foreach (&loader->messages,
4027  NULL);
4028  _dbus_list_clear (&loader->messages);
4029  _dbus_string_free (&loader->data);
4030  dbus_free (loader);
4031  }
4032 }
4033 
4052 void
4054  DBusString **buffer)
4055 {
4056  _dbus_assert (!loader->buffer_outstanding);
4057 
4058  *buffer = &loader->data;
4059 
4060  loader->buffer_outstanding = TRUE;
4061 }
4062 
4072 void
4074  DBusString *buffer)
4075 {
4076  _dbus_assert (loader->buffer_outstanding);
4077  _dbus_assert (buffer == &loader->data);
4078 
4079  loader->buffer_outstanding = FALSE;
4080 }
4081 
4094  int **fds,
4095  unsigned *max_n_fds)
4096 {
4097 #ifdef HAVE_UNIX_FD_PASSING
4098  _dbus_assert (!loader->unix_fds_outstanding);
4099 
4100  /* Allocate space where we can put the fds we read. We allocate
4101  space for max_message_unix_fds since this is an
4102  upper limit how many fds can be received within a single
4103  message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
4104  we are allocating the maximum possible array size right from the
4105  beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
4106  there is no better way. */
4107 
4108  if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
4109  {
4110  int *a = dbus_realloc(loader->unix_fds,
4111  loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
4112 
4113  if (!a)
4114  return FALSE;
4115 
4116  loader->unix_fds = a;
4117  loader->n_unix_fds_allocated = loader->max_message_unix_fds;
4118  }
4119 
4120  *fds = loader->unix_fds + loader->n_unix_fds;
4121  *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
4122 
4123  loader->unix_fds_outstanding = TRUE;
4124  return TRUE;
4125 #else
4126  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
4127  return FALSE;
4128 #endif
4129 }
4130 
4141 void
4143  int *fds,
4144  unsigned n_fds)
4145 {
4146 #ifdef HAVE_UNIX_FD_PASSING
4147  _dbus_assert(loader->unix_fds_outstanding);
4148  _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
4149  _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
4150 
4151  loader->n_unix_fds += n_fds;
4152  loader->unix_fds_outstanding = FALSE;
4153 
4154  if (n_fds && loader->unix_fds_change)
4155  loader->unix_fds_change (loader->unix_fds_change_data);
4156 #else
4157  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
4158 #endif
4159 }
4160 
4161 /*
4162  * FIXME when we move the header out of the buffer, that memmoves all
4163  * buffered messages. Kind of crappy.
4164  *
4165  * Also we copy the header and body, which is kind of crappy. To
4166  * avoid this, we have to allow header and body to be in a single
4167  * memory block, which is good for messages we read and bad for
4168  * messages we are creating. But we could move_len() the buffer into
4169  * this single memory block, and move_len() will just swap the buffers
4170  * if you're moving the entire buffer replacing the dest string.
4171  *
4172  * We could also have the message loader tell the transport how many
4173  * bytes to read; so it would first ask for some arbitrary number like
4174  * 256, then if the message was incomplete it would use the
4175  * header/body len to ask for exactly the size of the message (or
4176  * blocks the size of a typical kernel buffer for the socket). That
4177  * way we don't get trailing bytes in the buffer that have to be
4178  * memmoved. Though I suppose we also don't have a chance of reading a
4179  * bunch of small messages at once, so the optimization may be stupid.
4180  *
4181  * Another approach would be to keep a "start" index into
4182  * loader->data and only delete it occasionally, instead of after
4183  * each message is loaded.
4184  *
4185  * load_message() returns FALSE if not enough memory OR the loader was corrupted
4186  */
4187 static dbus_bool_t
4188 load_message (DBusMessageLoader *loader,
4189  DBusMessage *message,
4190  int byte_order,
4191  int fields_array_len,
4192  int header_len,
4193  int body_len)
4194 {
4195  dbus_bool_t oom;
4196  DBusValidity validity;
4197  const DBusString *type_str;
4198  int type_pos;
4199  DBusValidationMode mode;
4200  dbus_uint32_t n_unix_fds = 0;
4201 
4202  mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
4203 
4204  oom = FALSE;
4205 
4206 #if 0
4207  _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
4208 #endif
4209 
4210  /* 1. VALIDATE AND COPY OVER HEADER */
4211  _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
4212  _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
4213 
4214  if (!_dbus_header_load (&message->header,
4215  mode,
4216  &validity,
4217  byte_order,
4218  fields_array_len,
4219  header_len,
4220  body_len,
4221  &loader->data, 0,
4222  _dbus_string_get_length (&loader->data)))
4223  {
4224  _dbus_verbose ("Failed to load header for new message code %d\n", validity);
4225 
4226  /* assert here so we can catch any code that still uses DBUS_VALID to indicate
4227  oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
4228  _dbus_assert (validity != DBUS_VALID);
4229 
4230  if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
4231  oom = TRUE;
4232  else
4233  {
4234  loader->corrupted = TRUE;
4235  loader->corruption_reason = validity;
4236  }
4237  goto failed;
4238  }
4239 
4240  _dbus_assert (validity == DBUS_VALID);
4241 
4242  /* 2. VALIDATE BODY */
4243  if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
4244  {
4245  get_const_signature (&message->header, &type_str, &type_pos);
4246 
4247  /* Because the bytes_remaining arg is NULL, this validates that the
4248  * body is the right length
4249  */
4250  validity = _dbus_validate_body_with_reason (type_str,
4251  type_pos,
4252  byte_order,
4253  NULL,
4254  &loader->data,
4255  header_len,
4256  body_len);
4257  if (validity != DBUS_VALID)
4258  {
4259  _dbus_verbose ("Failed to validate message body code %d\n", validity);
4260 
4261  loader->corrupted = TRUE;
4262  loader->corruption_reason = validity;
4263 
4264  goto failed;
4265  }
4266  }
4267 
4268  /* 3. COPY OVER UNIX FDS */
4272  &n_unix_fds);
4273 
4274 #ifdef HAVE_UNIX_FD_PASSING
4275 
4276  if (n_unix_fds > loader->n_unix_fds)
4277  {
4278  _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
4279  n_unix_fds, loader->n_unix_fds);
4280 
4281  loader->corrupted = TRUE;
4282  loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4283  goto failed;
4284  }
4285 
4286  /* If this was a recycled message there might still be
4287  some memory allocated for the fds */
4288  dbus_free(message->unix_fds);
4289 
4290  if (n_unix_fds > 0)
4291  {
4292  message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
4293  if (message->unix_fds == NULL)
4294  {
4295  _dbus_verbose ("Failed to allocate file descriptor array\n");
4296  oom = TRUE;
4297  goto failed;
4298  }
4299 
4300  message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
4301  loader->n_unix_fds -= n_unix_fds;
4302  memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
4303 
4304  if (loader->unix_fds_change)
4305  loader->unix_fds_change (loader->unix_fds_change_data);
4306  }
4307  else
4308  message->unix_fds = NULL;
4309 
4310 #else
4311 
4312  if (n_unix_fds > 0)
4313  {
4314  _dbus_verbose ("Hmm, message claims to come with file descriptors "
4315  "but that's not supported on our platform, disconnecting.\n");
4316 
4317  loader->corrupted = TRUE;
4318  loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4319  goto failed;
4320  }
4321 
4322 #endif
4323 
4324  /* 3. COPY OVER BODY AND QUEUE MESSAGE */
4325 
4326  if (!_dbus_list_append (&loader->messages, message))
4327  {
4328  _dbus_verbose ("Failed to append new message to loader queue\n");
4329  oom = TRUE;
4330  goto failed;
4331  }
4332 
4333  _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4334  _dbus_assert (_dbus_string_get_length (&loader->data) >=
4335  (header_len + body_len));
4336 
4337  if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
4338  {
4339  _dbus_verbose ("Failed to move body into new message\n");
4340  oom = TRUE;
4341  goto failed;
4342  }
4343 
4344  _dbus_string_delete (&loader->data, 0, header_len + body_len);
4345 
4346  /* don't waste more than 2k of memory */
4347  _dbus_string_compact (&loader->data, 2048);
4348 
4349  _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
4350  _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4351 
4352  _dbus_verbose ("Loaded message %p\n", message);
4353 
4354  _dbus_assert (!oom);
4355  _dbus_assert (!loader->corrupted);
4356  _dbus_assert (loader->messages != NULL);
4357  _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4358 
4359  return TRUE;
4360 
4361  failed:
4362 
4363  /* Clean up */
4364 
4365  /* does nothing if the message isn't in the list */
4366  _dbus_list_remove_last (&loader->messages, message);
4367 
4368  if (oom)
4369  _dbus_assert (!loader->corrupted);
4370  else
4371  _dbus_assert (loader->corrupted);
4372 
4373  _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
4374 
4375  return FALSE;
4376 }
4377 
4394 {
4395  while (!loader->corrupted &&
4396  _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
4397  {
4398  DBusValidity validity;
4399  int byte_order, fields_array_len, header_len, body_len;
4400 
4402  &validity,
4403  &byte_order,
4404  &fields_array_len,
4405  &header_len,
4406  &body_len,
4407  &loader->data, 0,
4408  _dbus_string_get_length (&loader->data)))
4409  {
4410  DBusMessage *message;
4411 
4412  _dbus_assert (validity == DBUS_VALID);
4413 
4414  message = dbus_message_new_empty_header ();
4415  if (message == NULL)
4416  return FALSE;
4417 
4418  if (!load_message (loader, message,
4419  byte_order, fields_array_len,
4420  header_len, body_len))
4421  {
4422  dbus_message_unref (message);
4423  /* load_message() returns false if corrupted or OOM; if
4424  * corrupted then return TRUE for not OOM
4425  */
4426  return loader->corrupted;
4427  }
4428 
4429  _dbus_assert (loader->messages != NULL);
4430  _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4431  }
4432  else
4433  {
4434  _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
4435  validity);
4436  if (validity != DBUS_VALID)
4437  {
4438  loader->corrupted = TRUE;
4439  loader->corruption_reason = validity;
4440  }
4441  return TRUE;
4442  }
4443  }
4444 
4445  return TRUE;
4446 }
4447 
4455 DBusMessage*
4457 {
4458  if (loader->messages)
4459  return loader->messages->data;
4460  else
4461  return NULL;
4462 }
4463 
4472 DBusMessage*
4474 {
4475  return _dbus_list_pop_first (&loader->messages);
4476 }
4477 
4486 DBusList*
4488 {
4489  return _dbus_list_pop_first_link (&loader->messages);
4490 }
4491 
4498 void
4500  DBusList *link)
4501 {
4502  _dbus_list_prepend_link (&loader->messages, link);
4503 }
4504 
4516 {
4517  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4518  (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4519  return loader->corrupted;
4520 }
4521 
4530 {
4531  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4532  (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4533 
4534  return loader->corruption_reason;
4535 }
4536 
4543 void
4545  long size)
4546 {
4547  if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
4548  {
4549  _dbus_verbose ("clamping requested max message size %ld to %d\n",
4552  }
4553  loader->max_message_size = size;
4554 }
4555 
4562 long
4564 {
4565  return loader->max_message_size;
4566 }
4567 
4574 void
4576  long n)
4577 {
4579  {
4580  _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
4583  }
4584  loader->max_message_unix_fds = n;
4585 }
4586 
4593 long
4595 {
4596  return loader->max_message_unix_fds;
4597 }
4598 
4604 int
4606 {
4607 #ifdef HAVE_UNIX_FD_PASSING
4608  return loader->n_unix_fds;
4609 #else
4610  return 0;
4611 #endif
4612 }
4613 
4622 void
4624  void (* callback) (void *),
4625  void *data)
4626 {
4627 #ifdef HAVE_UNIX_FD_PASSING
4628  loader->unix_fds_change = callback;
4629  loader->unix_fds_change_data = data;
4630 #endif
4631 }
4632 
4633 static DBusDataSlotAllocator slot_allocator =
4634  _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
4635 
4651 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
4652 {
4653  return _dbus_data_slot_allocator_alloc (&slot_allocator,
4654  slot_p);
4655 }
4656 
4668 void
4669 dbus_message_free_data_slot (dbus_int32_t *slot_p)
4670 {
4671  _dbus_return_if_fail (*slot_p >= 0);
4672 
4673  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
4674 }
4675 
4691  dbus_int32_t slot,
4692  void *data,
4693  DBusFreeFunction free_data_func)
4694 {
4695  DBusFreeFunction old_free_func;
4696  void *old_data;
4697  dbus_bool_t retval;
4698 
4699  _dbus_return_val_if_fail (message != NULL, FALSE);
4700  _dbus_return_val_if_fail (slot >= 0, FALSE);
4701 
4702  retval = _dbus_data_slot_list_set (&slot_allocator,
4703  &message->slot_list,
4704  slot, data, free_data_func,
4705  &old_free_func, &old_data);
4706 
4707  if (retval)
4708  {
4709  /* Do the actual free outside the message lock */
4710  if (old_free_func)
4711  (* old_free_func) (old_data);
4712  }
4713 
4714  return retval;
4715 }
4716 
4725 void*
4727  dbus_int32_t slot)
4728 {
4729  void *res;
4730 
4731  _dbus_return_val_if_fail (message != NULL, NULL);
4732 
4733  res = _dbus_data_slot_list_get (&slot_allocator,
4734  &message->slot_list,
4735  slot);
4736 
4737  return res;
4738 }
4739 
4753 int
4754 dbus_message_type_from_string (const char *type_str)
4755 {
4756  if (strcmp (type_str, "method_call") == 0)
4758  if (strcmp (type_str, "method_return") == 0)
4760  else if (strcmp (type_str, "signal") == 0)
4761  return DBUS_MESSAGE_TYPE_SIGNAL;
4762  else if (strcmp (type_str, "error") == 0)
4763  return DBUS_MESSAGE_TYPE_ERROR;
4764  else
4766 }
4767 
4781 const char *
4783 {
4784  switch (type)
4785  {
4787  return "method_call";
4789  return "method_return";
4791  return "signal";
4793  return "error";
4794  default:
4795  return "invalid";
4796  }
4797 }
4798 
4813  char **marshalled_data_p,
4814  int *len_p)
4815 {
4816  DBusString tmp;
4817  dbus_bool_t was_locked;
4818 
4819  _dbus_return_val_if_fail (msg != NULL, FALSE);
4820  _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
4821  _dbus_return_val_if_fail (len_p != NULL, FALSE);
4822 
4823  if (!_dbus_string_init (&tmp))
4824  return FALSE;
4825 
4826  /* Ensure the message is locked, to ensure the length header is filled in. */
4827  was_locked = msg->locked;
4828 
4829  if (!was_locked)
4830  dbus_message_lock (msg);
4831 
4832  if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
4833  goto fail;
4834 
4835  *len_p = _dbus_string_get_length (&tmp);
4836 
4837  if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
4838  goto fail;
4839 
4840  *len_p = _dbus_string_get_length (&tmp);
4841 
4842  if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
4843  goto fail;
4844 
4845  _dbus_string_free (&tmp);
4846 
4847  if (!was_locked)
4848  msg->locked = FALSE;
4849 
4850  return TRUE;
4851 
4852  fail:
4853  _dbus_string_free (&tmp);
4854 
4855  if (!was_locked)
4856  msg->locked = FALSE;
4857 
4858  return FALSE;
4859 }
4860 
4873 DBusMessage *
4874 dbus_message_demarshal (const char *str,
4875  int len,
4876  DBusError *error)
4877 {
4878  DBusMessageLoader *loader;
4879  DBusString *buffer;
4880  DBusMessage *msg;
4881 
4882  _dbus_return_val_if_fail (str != NULL, NULL);
4883 
4884  loader = _dbus_message_loader_new ();
4885 
4886  if (loader == NULL)
4887  return NULL;
4888 
4889  _dbus_message_loader_get_buffer (loader, &buffer);
4890 
4891  if (!_dbus_string_append_len (buffer, str, len))
4892  goto fail_oom;
4893 
4894  _dbus_message_loader_return_buffer (loader, buffer);
4895 
4897  goto fail_oom;
4898 
4900  goto fail_corrupt;
4901 
4902  msg = _dbus_message_loader_pop_message (loader);
4903 
4904  if (!msg)
4905  goto fail_oom;
4906 
4907  _dbus_message_loader_unref (loader);
4908  return msg;
4909 
4910  fail_corrupt:
4911  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
4912  _dbus_validity_to_error_message (loader->corruption_reason));
4913  _dbus_message_loader_unref (loader);
4914  return NULL;
4915 
4916  fail_oom:
4917  _DBUS_SET_OOM (error);
4918  _dbus_message_loader_unref (loader);
4919  return NULL;
4920 }
4921 
4934 int
4936  int len)
4937 {
4938  DBusString str;
4939  int byte_order, fields_array_len, header_len, body_len;
4940  DBusValidity validity = DBUS_VALID;
4941  int have_message;
4942 
4943  if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
4944  return 0;
4945 
4946  if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
4948  _dbus_string_init_const_len (&str, buf, len);
4949 
4950  validity = DBUS_VALID;
4951  have_message
4953  &validity, &byte_order,
4954  &fields_array_len,
4955  &header_len,
4956  &body_len,
4957  &str, 0,
4958  len);
4959  _dbus_string_free (&str);
4960 
4961  if (validity == DBUS_VALID)
4962  {
4963  _dbus_assert (have_message || (header_len + body_len) > len);
4964  (void) have_message; /* unused unless asserting */
4965  return header_len + body_len;
4966  }
4967  else
4968  {
4969  return -1; /* broken! */
4970  }
4971 }
4972 
4994 void
4996  dbus_bool_t allow)
4997 {
4998  _dbus_return_if_fail (message != NULL);
4999  _dbus_return_if_fail (!message->locked);
5000 
5001  _dbus_header_toggle_flag (&message->header,
5003  allow);
5004 }
5005 
5014 {
5015  _dbus_return_val_if_fail (message != NULL, FALSE);
5016 
5017  return _dbus_header_get_flag (&message->header,
5019 }
5020 
5023 /* 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:407
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_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
DBUS_PRIVATE_EXPORT 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
DBUS_PRIVATE_EXPORT 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
DBUS_PRIVATE_EXPORT 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...
DBUS_PRIVATE_EXPORT 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:819
#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:531
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 &quot;critical&quot; 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
Layout of a DBusMessageIter on the stack in dbus 1.10.0.
Definition: dbus-message.c:144
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...
DBUS_PRIVATE_EXPORT 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:352
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:303
#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).
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 &quot;basic type&quot; 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:218
DBUS_PRIVATE_EXPORT 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.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
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:375
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 &quot;level&quot;.
DBusList * counters
0-N DBusCounter used to track message size/unix fds.
DBUS_PRIVATE_EXPORT 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 &quot;freed&quot; 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_PRIVATE_EXPORT 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 &quot;1&quot;.
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:231
#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.
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
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
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_PRIVATE_EXPORT 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
DBUS_PRIVATE_EXPORT 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_STRING_DEFINE_STATIC(_dbus_header_signature_str, DBUS_HEADER_SIGNATURE)
Static DBusString containing the signature of a message header.
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 &quot;level&quot;.
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 &quot;0&quot;.
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.
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
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_PRIVATE_EXPORT dbus_bool_t _dbus_message_loader_queue_messages(DBusMessageLoader *loader)
Converts buffered data into messages, if we have enough data.
DBUS_PRIVATE_EXPORT 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:250
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:528
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:277
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 &quot;container type&quot; 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...