D-Bus  1.10.18
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 {
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 {
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 {
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 {
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 {
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 {
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 {
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;
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  goto failed;
1939  }
1940 
1941  if (!dbus_message_iter_close_container (&iter, &array))
1942  goto failed;
1943  }
1944 #ifndef DBUS_DISABLE_CHECKS
1945  else
1946  {
1947  _dbus_warn ("type %s isn't supported yet in %s\n",
1948  _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
1949  goto failed;
1950  }
1951 #endif
1952 
1953  type = va_arg (var_args, int);
1954  }
1955 
1956  return TRUE;
1957 
1958  failed:
1959  return FALSE;
1960 }
1961 
2008  DBusError *error,
2009  int first_arg_type,
2010  ...)
2011 {
2012  dbus_bool_t retval;
2013  va_list var_args;
2014 
2015  _dbus_return_val_if_fail (message != NULL, FALSE);
2016  _dbus_return_val_if_error_is_set (error, FALSE);
2017 
2018  va_start (var_args, first_arg_type);
2019  retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
2020  va_end (var_args);
2021 
2022  return retval;
2023 }
2024 
2037  DBusError *error,
2038  int first_arg_type,
2039  va_list var_args)
2040 {
2041  DBusMessageIter iter;
2042 
2043  _dbus_return_val_if_fail (message != NULL, FALSE);
2044  _dbus_return_val_if_error_is_set (error, FALSE);
2045 
2046  dbus_message_iter_init (message, &iter);
2047  return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
2048 }
2049 
2050 static void
2051 _dbus_message_iter_init_common (DBusMessage *message,
2052  DBusMessageRealIter *real,
2053  int iter_type)
2054 {
2055  /* If these static assertions fail on your platform, report it as a bug. */
2056  _DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
2057  _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <=
2058  _DBUS_ALIGNOF (DBusMessageIter));
2059  /* A failure of these two assertions would indicate that we've broken
2060  * ABI on this platform since 1.10.0. */
2061  _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) ==
2062  sizeof (DBusMessageIter));
2063  _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) ==
2064  _DBUS_ALIGNOF (DBusMessageIter));
2065  /* If this static assertion fails, it means the DBusMessageIter struct
2066  * is not "packed", which might result in "iter = other_iter" not copying
2067  * every byte. */
2068  _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) ==
2069  4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int));
2070 
2071  /* Since the iterator will read or write who-knows-what from the
2072  * message, we need to get in the right byte order
2073  */
2074  ensure_byte_order (message);
2075 
2076  real->message = message;
2077  real->changed_stamp = message->changed_stamp;
2078  real->iter_type = iter_type;
2079  real->sig_refcount = 0;
2080 }
2081 
2106  DBusMessageIter *iter)
2107 {
2108  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2109  const DBusString *type_str;
2110  int type_pos;
2111 
2112  _dbus_return_val_if_fail (message != NULL, FALSE);
2113  _dbus_return_val_if_fail (iter != NULL, FALSE);
2114 
2115  get_const_signature (&message->header, &type_str, &type_pos);
2116 
2117  _dbus_message_iter_init_common (message, real,
2118  DBUS_MESSAGE_ITER_TYPE_READER);
2119 
2121  _dbus_header_get_byte_order (&message->header),
2122  type_str, type_pos,
2123  &message->body,
2124  0);
2125 
2127 }
2128 
2137 {
2138  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2139 
2140  _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2141  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2142 
2143  return _dbus_type_reader_has_next (&real->u.reader);
2144 }
2145 
2156 {
2157  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2158 
2159  _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2160  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2161 
2162  return _dbus_type_reader_next (&real->u.reader);
2163 }
2164 
2179 int
2181 {
2182  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2183 
2184  _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2185  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2186 
2188 }
2189 
2198 int
2200 {
2201  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2202 
2203  _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2204  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
2205  _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
2206 
2208 }
2209 
2235 void
2237  DBusMessageIter *sub)
2238 {
2239  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2240  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2241 
2242  _dbus_return_if_fail (_dbus_message_iter_check (real));
2243  _dbus_return_if_fail (sub != NULL);
2244 
2245  *real_sub = *real;
2246  _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
2247 }
2248 
2260 char *
2262 {
2263  const DBusString *sig;
2264  DBusString retstr;
2265  char *ret;
2266  int start, len;
2267  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2268 
2269  _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
2270 
2271  if (!_dbus_string_init (&retstr))
2272  return NULL;
2273 
2275  &start, &len);
2276  if (!_dbus_string_append_len (&retstr,
2277  _dbus_string_get_const_data (sig) + start,
2278  len))
2279  return NULL;
2280  if (!_dbus_string_steal_data (&retstr, &ret))
2281  return NULL;
2282  _dbus_string_free (&retstr);
2283  return ret;
2284 }
2285 
2333 void
2335  void *value)
2336 {
2337  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2338 
2339  _dbus_return_if_fail (_dbus_message_iter_check (real));
2340  _dbus_return_if_fail (value != NULL);
2341 
2343  {
2344 #ifdef HAVE_UNIX_FD_PASSING
2345  DBusBasicValue idx;
2346 
2347  _dbus_type_reader_read_basic(&real->u.reader, &idx);
2348 
2349  if (idx.u32 >= real->message->n_unix_fds) {
2350  /* Hmm, we cannot really signal an error here, so let's make
2351  sure to return an invalid fd. */
2352  *((int*) value) = -1;
2353  return;
2354  }
2355 
2356  *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
2357 #else
2358  *((int*) value) = -1;
2359 #endif
2360  }
2361  else
2362  {
2364  value);
2365  }
2366 }
2367 
2378 int
2380 {
2381  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2382  DBusTypeReader array;
2383  int element_type;
2384  int n_elements = 0;
2385 
2386  _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2387  _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
2388  == DBUS_TYPE_ARRAY, 0);
2389 
2390  element_type = _dbus_type_reader_get_element_type (&real->u.reader);
2391  _dbus_type_reader_recurse (&real->u.reader, &array);
2392  if (dbus_type_is_fixed (element_type))
2393  {
2394  int alignment = _dbus_type_get_alignment (element_type);
2395  int total_len = _dbus_type_reader_get_array_length (&array);
2396  n_elements = total_len / alignment;
2397  }
2398  else
2399  {
2401  {
2402  ++n_elements;
2403  _dbus_type_reader_next (&array);
2404  }
2405  }
2406 
2407  return n_elements;
2408 }
2409 
2422 int
2424 {
2425  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2426 
2427  _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2428 
2430 }
2431 
2467 void
2469  void *value,
2470  int *n_elements)
2471 {
2472  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2473 #ifndef DBUS_DISABLE_CHECKS
2474  int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
2475 
2476  _dbus_return_if_fail (_dbus_message_iter_check (real));
2477  _dbus_return_if_fail (value != NULL);
2478  _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
2479  (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
2480 #endif
2481 
2483  value, n_elements);
2484 }
2485 
2497 void
2499  DBusMessageIter *iter)
2500 {
2501  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2502 
2503  _dbus_return_if_fail (message != NULL);
2504  _dbus_return_if_fail (iter != NULL);
2505 
2506  _dbus_message_iter_init_common (message, real,
2507  DBUS_MESSAGE_ITER_TYPE_WRITER);
2508 
2509  /* We create the signature string and point iterators at it "on demand"
2510  * when a value is actually appended. That means that init() never fails
2511  * due to OOM.
2512  */
2514  _dbus_header_get_byte_order (&message->header),
2515  &message->body,
2516  _dbus_string_get_length (&message->body));
2517 }
2518 
2527 static dbus_bool_t
2528 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
2529 {
2530  DBusString *str;
2531  const DBusString *current_sig;
2532  int current_sig_pos;
2533 
2534  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2535 
2536  if (real->u.writer.type_str != NULL)
2537  {
2538  _dbus_assert (real->sig_refcount > 0);
2539  real->sig_refcount += 1;
2540  return TRUE;
2541  }
2542 
2543  str = dbus_new (DBusString, 1);
2544  if (str == NULL)
2545  return FALSE;
2546 
2549  &current_sig, &current_sig_pos))
2550  current_sig = NULL;
2551 
2552  if (current_sig)
2553  {
2554  int current_len;
2555 
2556  current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
2557  current_sig_pos += 1; /* move on to sig data */
2558 
2559  if (!_dbus_string_init_preallocated (str, current_len + 4))
2560  {
2561  dbus_free (str);
2562  return FALSE;
2563  }
2564 
2565  if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
2566  str, 0))
2567  {
2568  _dbus_string_free (str);
2569  dbus_free (str);
2570  return FALSE;
2571  }
2572  }
2573  else
2574  {
2575  if (!_dbus_string_init_preallocated (str, 4))
2576  {
2577  dbus_free (str);
2578  return FALSE;
2579  }
2580  }
2581 
2582  real->sig_refcount = 1;
2583 
2585  str, _dbus_string_get_length (str));
2586  return TRUE;
2587 }
2588 
2598 static dbus_bool_t
2599 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
2600 {
2601  DBusString *str;
2602  const char *v_STRING;
2603  dbus_bool_t retval;
2604 
2605  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2606  _dbus_assert (real->u.writer.type_str != NULL);
2607  _dbus_assert (real->sig_refcount > 0);
2608 
2609  real->sig_refcount -= 1;
2610 
2611  if (real->sig_refcount > 0)
2612  return TRUE;
2613  _dbus_assert (real->sig_refcount == 0);
2614 
2615  retval = TRUE;
2616 
2617  str = real->u.writer.type_str;
2618 
2619  v_STRING = _dbus_string_get_const_data (str);
2623  &v_STRING))
2624  retval = FALSE;
2625 
2627  _dbus_string_free (str);
2628  dbus_free (str);
2629 
2630  return retval;
2631 }
2632 
2640 static void
2641 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
2642 {
2643  DBusString *str;
2644 
2645  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2646  _dbus_assert (real->u.writer.type_str != NULL);
2647  _dbus_assert (real->sig_refcount > 0);
2648 
2649  real->sig_refcount -= 1;
2650 
2651  if (real->sig_refcount > 0)
2652  return;
2653  _dbus_assert (real->sig_refcount == 0);
2654 
2655  str = real->u.writer.type_str;
2656 
2658  _dbus_string_free (str);
2659  dbus_free (str);
2660 }
2661 
2662 #ifndef DBUS_DISABLE_CHECKS
2663 static dbus_bool_t
2664 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
2665 {
2666  if (!_dbus_message_iter_check (iter))
2667  return FALSE;
2668 
2669  if (iter->message->locked)
2670  {
2671  _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
2672  return FALSE;
2673  }
2674 
2675  return TRUE;
2676 }
2677 #endif /* DBUS_DISABLE_CHECKS */
2678 
2679 #ifdef HAVE_UNIX_FD_PASSING
2680 static int *
2681 expand_fd_array(DBusMessage *m,
2682  unsigned n)
2683 {
2684  _dbus_assert(m);
2685 
2686  /* This makes space for adding n new fds to the array and returns a
2687  pointer to the place were the first fd should be put. */
2688 
2689  if (m->n_unix_fds + n > m->n_unix_fds_allocated)
2690  {
2691  unsigned k;
2692  int *p;
2693 
2694  /* Make twice as much space as necessary */
2695  k = (m->n_unix_fds + n) * 2;
2696 
2697  /* Allocate at least four */
2698  if (k < 4)
2699  k = 4;
2700 
2701  p = dbus_realloc(m->unix_fds, k * sizeof(int));
2702  if (p == NULL)
2703  return NULL;
2704 
2705  m->unix_fds = p;
2706  m->n_unix_fds_allocated = k;
2707  }
2708 
2709  return m->unix_fds + m->n_unix_fds;
2710 }
2711 #endif
2712 
2734  int type,
2735  const void *value)
2736 {
2737  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2738  dbus_bool_t ret;
2739 
2740  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2741  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2742  _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
2743  _dbus_return_val_if_fail (value != NULL, FALSE);
2744 
2745 #ifndef DBUS_DISABLE_CHECKS
2746  switch (type)
2747  {
2748  const char * const *string_p;
2749  const dbus_bool_t *bool_p;
2750 
2751  case DBUS_TYPE_STRING:
2752  string_p = value;
2753  _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
2754  break;
2755 
2756  case DBUS_TYPE_OBJECT_PATH:
2757  string_p = value;
2758  _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
2759  break;
2760 
2761  case DBUS_TYPE_SIGNATURE:
2762  string_p = value;
2763  _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
2764  break;
2765 
2766  case DBUS_TYPE_BOOLEAN:
2767  bool_p = value;
2768  _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
2769  break;
2770 
2771  default:
2772  {
2773  /* nothing to check, all possible values are allowed */
2774  }
2775  }
2776 #endif
2777 
2778  if (!_dbus_message_iter_open_signature (real))
2779  return FALSE;
2780 
2781  if (type == DBUS_TYPE_UNIX_FD)
2782  {
2783 #ifdef HAVE_UNIX_FD_PASSING
2784  int *fds;
2785  dbus_uint32_t u;
2786 
2787  /* First step, include the fd in the fd list of this message */
2788  if (!(fds = expand_fd_array(real->message, 1)))
2789  return FALSE;
2790 
2791  *fds = _dbus_dup(*(int*) value, NULL);
2792  if (*fds < 0)
2793  return FALSE;
2794 
2795  u = real->message->n_unix_fds;
2796 
2797  /* Second step, write the index to the fd */
2798  if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
2799  _dbus_close(*fds, NULL);
2800  return FALSE;
2801  }
2802 
2803  real->message->n_unix_fds += 1;
2804  u += 1;
2805 
2806  /* Final step, update the header accordingly */
2810  &u);
2811 
2812  /* If any of these operations fail the message is
2813  hosed. However, no memory or fds should be leaked since what
2814  has been added to message has been added to the message, and
2815  can hence be accounted for when the message is being
2816  freed. */
2817 #else
2818  ret = FALSE;
2819 #endif
2820  }
2821  else
2822  {
2823  ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
2824  }
2825 
2826  if (!_dbus_message_iter_close_signature (real))
2827  ret = FALSE;
2828 
2829  return ret;
2830 }
2831 
2869  int element_type,
2870  const void *value,
2871  int n_elements)
2872 {
2873  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2874  dbus_bool_t ret;
2875 
2876  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2877  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2878  _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
2879  _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
2880  _dbus_return_val_if_fail (value != NULL, FALSE);
2881  _dbus_return_val_if_fail (n_elements >= 0, FALSE);
2882  _dbus_return_val_if_fail (n_elements <=
2884  FALSE);
2885 
2886 #ifndef DBUS_DISABLE_CHECKS
2887  if (element_type == DBUS_TYPE_BOOLEAN)
2888  {
2889  const dbus_bool_t * const *bools = value;
2890  int i;
2891 
2892  for (i = 0; i < n_elements; i++)
2893  {
2894  _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
2895  }
2896  }
2897 #endif
2898 
2899  ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
2900 
2901  return ret;
2902 }
2903 
2927  int type,
2928  const char *contained_signature,
2929  DBusMessageIter *sub)
2930 {
2931  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2932  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2933  DBusString contained_str;
2934 
2935  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2936  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2937  _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
2938  _dbus_return_val_if_fail (sub != NULL, FALSE);
2939  _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
2940  contained_signature == NULL) ||
2941  (type == DBUS_TYPE_DICT_ENTRY &&
2942  contained_signature == NULL) ||
2943  (type == DBUS_TYPE_VARIANT &&
2944  contained_signature != NULL) ||
2945  (type == DBUS_TYPE_ARRAY &&
2946  contained_signature != NULL), FALSE);
2947 
2948  /* this would fail if the contained_signature is a dict entry, since
2949  * dict entries are invalid signatures standalone (they must be in
2950  * an array)
2951  */
2952  _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
2953  (contained_signature == NULL ||
2954  _dbus_check_is_valid_signature (contained_signature)),
2955  FALSE);
2956 
2957  if (!_dbus_message_iter_open_signature (real))
2958  return FALSE;
2959 
2960  *real_sub = *real;
2961 
2962  if (contained_signature != NULL)
2963  {
2964  _dbus_string_init_const (&contained_str, contained_signature);
2965 
2966  return _dbus_type_writer_recurse (&real->u.writer,
2967  type,
2968  &contained_str, 0,
2969  &real_sub->u.writer);
2970  }
2971  else
2972  {
2973  return _dbus_type_writer_recurse (&real->u.writer,
2974  type,
2975  NULL, 0,
2976  &real_sub->u.writer);
2977  }
2978 }
2979 
2980 
2996  DBusMessageIter *sub)
2997 {
2998  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2999  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3000  dbus_bool_t ret;
3001 
3002  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
3003  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3004  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
3005  _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3006 
3007  ret = _dbus_type_writer_unrecurse (&real->u.writer,
3008  &real_sub->u.writer);
3009 
3010  if (!_dbus_message_iter_close_signature (real))
3011  ret = FALSE;
3012 
3013  return ret;
3014 }
3015 
3027 void
3029  DBusMessageIter *sub)
3030 {
3031  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3032 #ifndef DBUS_DISABLE_CHECKS
3033  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3034 
3035  _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3036  _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3037  _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3038  _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3039 #endif
3040 
3041  _dbus_message_iter_abandon_signature (real);
3042 }
3043 
3060 void
3062  dbus_bool_t no_reply)
3063 {
3064  _dbus_return_if_fail (message != NULL);
3065  _dbus_return_if_fail (!message->locked);
3066 
3067  _dbus_header_toggle_flag (&message->header,
3069  no_reply);
3070 }
3071 
3081 {
3082  _dbus_return_val_if_fail (message != NULL, FALSE);
3083 
3084  return _dbus_header_get_flag (&message->header,
3086 }
3087 
3102 void
3104  dbus_bool_t auto_start)
3105 {
3106  _dbus_return_if_fail (message != NULL);
3107  _dbus_return_if_fail (!message->locked);
3108 
3109  _dbus_header_toggle_flag (&message->header,
3111  !auto_start);
3112 }
3113 
3123 {
3124  _dbus_return_val_if_fail (message != NULL, FALSE);
3125 
3126  return !_dbus_header_get_flag (&message->header,
3128 }
3129 
3130 
3145  const char *object_path)
3146 {
3147  _dbus_return_val_if_fail (message != NULL, FALSE);
3148  _dbus_return_val_if_fail (!message->locked, FALSE);
3149  _dbus_return_val_if_fail (object_path == NULL ||
3150  _dbus_check_is_valid_path (object_path),
3151  FALSE);
3152 
3153  return set_or_delete_string_field (message,
3156  object_path);
3157 }
3158 
3172 const char*
3174 {
3175  const char *v;
3176 
3177  _dbus_return_val_if_fail (message != NULL, NULL);
3178 
3179  v = NULL; /* in case field doesn't exist */
3183  (void *) &v);
3184  return v;
3185 }
3186 
3198  const char *path)
3199 {
3200  const char *msg_path;
3201  msg_path = dbus_message_get_path (message);
3202 
3203  if (msg_path == NULL)
3204  {
3205  if (path == NULL)
3206  return TRUE;
3207  else
3208  return FALSE;
3209  }
3210 
3211  if (path == NULL)
3212  return FALSE;
3213 
3214  if (strcmp (msg_path, path) == 0)
3215  return TRUE;
3216 
3217  return FALSE;
3218 }
3219 
3242  char ***path)
3243 {
3244  const char *v;
3245 
3246  _dbus_return_val_if_fail (message != NULL, FALSE);
3247  _dbus_return_val_if_fail (path != NULL, FALSE);
3248 
3249  *path = NULL;
3250 
3251  v = dbus_message_get_path (message);
3252  if (v != NULL)
3253  {
3254  if (!_dbus_decompose_path (v, strlen (v),
3255  path, NULL))
3256  return FALSE;
3257  }
3258  return TRUE;
3259 }
3260 
3276  const char *iface)
3277 {
3278  _dbus_return_val_if_fail (message != NULL, FALSE);
3279  _dbus_return_val_if_fail (!message->locked, FALSE);
3280  _dbus_return_val_if_fail (iface == NULL ||
3281  _dbus_check_is_valid_interface (iface),
3282  FALSE);
3283 
3284  return set_or_delete_string_field (message,
3287  iface);
3288 }
3289 
3303 const char*
3305 {
3306  const char *v;
3307 
3308  _dbus_return_val_if_fail (message != NULL, NULL);
3309 
3310  v = NULL; /* in case field doesn't exist */
3314  (void *) &v);
3315  return v;
3316 }
3317 
3327  const char *iface)
3328 {
3329  const char *msg_interface;
3330  msg_interface = dbus_message_get_interface (message);
3331 
3332  if (msg_interface == NULL)
3333  {
3334  if (iface == NULL)
3335  return TRUE;
3336  else
3337  return FALSE;
3338  }
3339 
3340  if (iface == NULL)
3341  return FALSE;
3342 
3343  if (strcmp (msg_interface, iface) == 0)
3344  return TRUE;
3345 
3346  return FALSE;
3347 
3348 }
3349 
3364  const char *member)
3365 {
3366  _dbus_return_val_if_fail (message != NULL, FALSE);
3367  _dbus_return_val_if_fail (!message->locked, FALSE);
3368  _dbus_return_val_if_fail (member == NULL ||
3369  _dbus_check_is_valid_member (member),
3370  FALSE);
3371 
3372  return set_or_delete_string_field (message,
3375  member);
3376 }
3377 
3389 const char*
3391 {
3392  const char *v;
3393 
3394  _dbus_return_val_if_fail (message != NULL, NULL);
3395 
3396  v = NULL; /* in case field doesn't exist */
3400  (void *) &v);
3401  return v;
3402 }
3403 
3413  const char *member)
3414 {
3415  const char *msg_member;
3416  msg_member = dbus_message_get_member (message);
3417 
3418  if (msg_member == NULL)
3419  {
3420  if (member == NULL)
3421  return TRUE;
3422  else
3423  return FALSE;
3424  }
3425 
3426  if (member == NULL)
3427  return FALSE;
3428 
3429  if (strcmp (msg_member, member) == 0)
3430  return TRUE;
3431 
3432  return FALSE;
3433 
3434 }
3435 
3449  const char *error_name)
3450 {
3451  _dbus_return_val_if_fail (message != NULL, FALSE);
3452  _dbus_return_val_if_fail (!message->locked, FALSE);
3453  _dbus_return_val_if_fail (error_name == NULL ||
3454  _dbus_check_is_valid_error_name (error_name),
3455  FALSE);
3456 
3457  return set_or_delete_string_field (message,
3460  error_name);
3461 }
3462 
3473 const char*
3475 {
3476  const char *v;
3477 
3478  _dbus_return_val_if_fail (message != NULL, NULL);
3479 
3480  v = NULL; /* in case field doesn't exist */
3484  (void *) &v);
3485  return v;
3486 }
3487 
3503  const char *destination)
3504 {
3505  _dbus_return_val_if_fail (message != NULL, FALSE);
3506  _dbus_return_val_if_fail (!message->locked, FALSE);
3507  _dbus_return_val_if_fail (destination == NULL ||
3508  _dbus_check_is_valid_bus_name (destination),
3509  FALSE);
3510 
3511  return set_or_delete_string_field (message,
3514  destination);
3515 }
3516 
3526 const char*
3528 {
3529  const char *v;
3530 
3531  _dbus_return_val_if_fail (message != NULL, NULL);
3532 
3533  v = NULL; /* in case field doesn't exist */
3537  (void *) &v);
3538  return v;
3539 }
3540 
3557  const char *sender)
3558 {
3559  _dbus_return_val_if_fail (message != NULL, FALSE);
3560  _dbus_return_val_if_fail (!message->locked, FALSE);
3561  _dbus_return_val_if_fail (sender == NULL ||
3562  _dbus_check_is_valid_bus_name (sender),
3563  FALSE);
3564 
3565  return set_or_delete_string_field (message,
3568  sender);
3569 }
3570 
3586 const char*
3588 {
3589  const char *v;
3590 
3591  _dbus_return_val_if_fail (message != NULL, NULL);
3592 
3593  v = NULL; /* in case field doesn't exist */
3597  (void *) &v);
3598  return v;
3599 }
3600 
3619 const char*
3621 {
3622  const DBusString *type_str;
3623  int type_pos;
3624 
3625  _dbus_return_val_if_fail (message != NULL, NULL);
3626 
3627  get_const_signature (&message->header, &type_str, &type_pos);
3628 
3629  return _dbus_string_get_const_data_len (type_str, type_pos, 0);
3630 }
3631 
3632 static dbus_bool_t
3633 _dbus_message_has_type_interface_member (DBusMessage *message,
3634  int type,
3635  const char *iface,
3636  const char *member)
3637 {
3638  const char *n;
3639 
3640  _dbus_assert (message != NULL);
3641  _dbus_assert (iface != NULL);
3642  _dbus_assert (member != NULL);
3643 
3644  if (dbus_message_get_type (message) != type)
3645  return FALSE;
3646 
3647  /* Optimize by checking the short member name first
3648  * instead of the longer interface name
3649  */
3650 
3651  n = dbus_message_get_member (message);
3652 
3653  if (n && strcmp (n, member) == 0)
3654  {
3655  n = dbus_message_get_interface (message);
3656 
3657  if (n == NULL || strcmp (n, iface) == 0)
3658  return TRUE;
3659  }
3660 
3661  return FALSE;
3662 }
3663 
3680  const char *iface,
3681  const char *method)
3682 {
3683  _dbus_return_val_if_fail (message != NULL, FALSE);
3684  _dbus_return_val_if_fail (iface != NULL, FALSE);
3685  _dbus_return_val_if_fail (method != NULL, FALSE);
3686  /* don't check that interface/method are valid since it would be
3687  * expensive, and not catch many common errors
3688  */
3689 
3690  return _dbus_message_has_type_interface_member (message,
3692  iface, method);
3693 }
3694 
3708  const char *iface,
3709  const char *signal_name)
3710 {
3711  _dbus_return_val_if_fail (message != NULL, FALSE);
3712  _dbus_return_val_if_fail (iface != NULL, FALSE);
3713  _dbus_return_val_if_fail (signal_name != NULL, FALSE);
3714  /* don't check that interface/name are valid since it would be
3715  * expensive, and not catch many common errors
3716  */
3717 
3718  return _dbus_message_has_type_interface_member (message,
3720  iface, signal_name);
3721 }
3722 
3735  const char *error_name)
3736 {
3737  const char *n;
3738 
3739  _dbus_return_val_if_fail (message != NULL, FALSE);
3740  _dbus_return_val_if_fail (error_name != NULL, FALSE);
3741  /* don't check that error_name is valid since it would be expensive,
3742  * and not catch many common errors
3743  */
3744 
3746  return FALSE;
3747 
3748  n = dbus_message_get_error_name (message);
3749 
3750  if (n && strcmp (n, error_name) == 0)
3751  return TRUE;
3752  else
3753  return FALSE;
3754 }
3755 
3768  const char *name)
3769 {
3770  const char *s;
3771 
3772  _dbus_return_val_if_fail (message != NULL, FALSE);
3773  _dbus_return_val_if_fail (name != NULL, FALSE);
3774  /* don't check that name is valid since it would be expensive, and
3775  * not catch many common errors
3776  */
3777 
3778  s = dbus_message_get_destination (message);
3779 
3780  if (s && strcmp (s, name) == 0)
3781  return TRUE;
3782  else
3783  return FALSE;
3784 }
3785 
3803  const char *name)
3804 {
3805  const char *s;
3806 
3807  _dbus_return_val_if_fail (message != NULL, FALSE);
3808  _dbus_return_val_if_fail (name != NULL, FALSE);
3809  /* don't check that name is valid since it would be expensive, and
3810  * not catch many common errors
3811  */
3812 
3813  s = dbus_message_get_sender (message);
3814 
3815  if (s && strcmp (s, name) == 0)
3816  return TRUE;
3817  else
3818  return FALSE;
3819 }
3820 
3832  const char *signature)
3833 {
3834  const char *s;
3835 
3836  _dbus_return_val_if_fail (message != NULL, FALSE);
3837  _dbus_return_val_if_fail (signature != NULL, FALSE);
3838  /* don't check that signature is valid since it would be expensive,
3839  * and not catch many common errors
3840  */
3841 
3842  s = dbus_message_get_signature (message);
3843 
3844  if (s && strcmp (s, signature) == 0)
3845  return TRUE;
3846  else
3847  return FALSE;
3848 }
3849 
3874  DBusMessage *message)
3875 {
3876  const char *str;
3877 
3878  _dbus_return_val_if_fail (message != NULL, FALSE);
3879  _dbus_return_val_if_error_is_set (error, FALSE);
3880 
3882  return FALSE;
3883 
3884  str = NULL;
3885  dbus_message_get_args (message, NULL,
3886  DBUS_TYPE_STRING, &str,
3888 
3889  dbus_set_error (error, dbus_message_get_error_name (message),
3890  str ? "%s" : NULL, str);
3891 
3892  return TRUE;
3893 }
3894 
3903 {
3904 #ifdef HAVE_UNIX_FD_PASSING
3905  _dbus_assert(message);
3906 
3907  return message->n_unix_fds > 0;
3908 #else
3909  return FALSE;
3910 #endif
3911 }
3912 
3931 #define INITIAL_LOADER_DATA_LEN 32
3932 
3941 {
3942  DBusMessageLoader *loader;
3943 
3944  loader = dbus_new0 (DBusMessageLoader, 1);
3945  if (loader == NULL)
3946  return NULL;
3947 
3948  loader->refcount = 1;
3949 
3950  loader->corrupted = FALSE;
3951  loader->corruption_reason = DBUS_VALID;
3952 
3953  /* this can be configured by the app, but defaults to the protocol max */
3955 
3956  /* We set a very relatively conservative default here since due to how
3957  SCM_RIGHTS works we need to preallocate an fd array of the maximum
3958  number of unix fds we want to receive in advance. A
3959  try-and-reallocate loop is not possible. */
3960  loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
3961 
3962  if (!_dbus_string_init (&loader->data))
3963  {
3964  dbus_free (loader);
3965  return NULL;
3966  }
3967 
3968  /* preallocate the buffer for speed, ignore failure */
3970  _dbus_string_set_length (&loader->data, 0);
3971 
3972 #ifdef HAVE_UNIX_FD_PASSING
3973  loader->unix_fds = NULL;
3974  loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
3975  loader->unix_fds_outstanding = FALSE;
3976 #endif
3977 
3978  return loader;
3979 }
3980 
3989 {
3990  loader->refcount += 1;
3991 
3992  return loader;
3993 }
3994 
4001 void
4003 {
4004  loader->refcount -= 1;
4005  if (loader->refcount == 0)
4006  {
4007 #ifdef HAVE_UNIX_FD_PASSING
4008  close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
4009  dbus_free(loader->unix_fds);
4010 #endif
4011  _dbus_list_foreach (&loader->messages,
4013  NULL);
4014  _dbus_list_clear (&loader->messages);
4015  _dbus_string_free (&loader->data);
4016  dbus_free (loader);
4017  }
4018 }
4019 
4038 void
4040  DBusString **buffer)
4041 {
4042  _dbus_assert (!loader->buffer_outstanding);
4043 
4044  *buffer = &loader->data;
4045 
4046  loader->buffer_outstanding = TRUE;
4047 }
4048 
4058 void
4060  DBusString *buffer)
4061 {
4062  _dbus_assert (loader->buffer_outstanding);
4063  _dbus_assert (buffer == &loader->data);
4064 
4065  loader->buffer_outstanding = FALSE;
4066 }
4067 
4080  int **fds,
4081  unsigned *max_n_fds)
4082 {
4083 #ifdef HAVE_UNIX_FD_PASSING
4084  _dbus_assert (!loader->unix_fds_outstanding);
4085 
4086  /* Allocate space where we can put the fds we read. We allocate
4087  space for max_message_unix_fds since this is an
4088  upper limit how many fds can be received within a single
4089  message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
4090  we are allocating the maximum possible array size right from the
4091  beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
4092  there is no better way. */
4093 
4094  if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
4095  {
4096  int *a = dbus_realloc(loader->unix_fds,
4097  loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
4098 
4099  if (!a)
4100  return FALSE;
4101 
4102  loader->unix_fds = a;
4103  loader->n_unix_fds_allocated = loader->max_message_unix_fds;
4104  }
4105 
4106  *fds = loader->unix_fds + loader->n_unix_fds;
4107  *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
4108 
4109  loader->unix_fds_outstanding = TRUE;
4110  return TRUE;
4111 #else
4112  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
4113  return FALSE;
4114 #endif
4115 }
4116 
4127 void
4129  int *fds,
4130  unsigned n_fds)
4131 {
4132 #ifdef HAVE_UNIX_FD_PASSING
4133  _dbus_assert(loader->unix_fds_outstanding);
4134  _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
4135  _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
4136 
4137  loader->n_unix_fds += n_fds;
4138  loader->unix_fds_outstanding = FALSE;
4139 
4140  if (n_fds && loader->unix_fds_change)
4141  loader->unix_fds_change (loader->unix_fds_change_data);
4142 #else
4143  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
4144 #endif
4145 }
4146 
4147 /*
4148  * FIXME when we move the header out of the buffer, that memmoves all
4149  * buffered messages. Kind of crappy.
4150  *
4151  * Also we copy the header and body, which is kind of crappy. To
4152  * avoid this, we have to allow header and body to be in a single
4153  * memory block, which is good for messages we read and bad for
4154  * messages we are creating. But we could move_len() the buffer into
4155  * this single memory block, and move_len() will just swap the buffers
4156  * if you're moving the entire buffer replacing the dest string.
4157  *
4158  * We could also have the message loader tell the transport how many
4159  * bytes to read; so it would first ask for some arbitrary number like
4160  * 256, then if the message was incomplete it would use the
4161  * header/body len to ask for exactly the size of the message (or
4162  * blocks the size of a typical kernel buffer for the socket). That
4163  * way we don't get trailing bytes in the buffer that have to be
4164  * memmoved. Though I suppose we also don't have a chance of reading a
4165  * bunch of small messages at once, so the optimization may be stupid.
4166  *
4167  * Another approach would be to keep a "start" index into
4168  * loader->data and only delete it occasionally, instead of after
4169  * each message is loaded.
4170  *
4171  * load_message() returns FALSE if not enough memory OR the loader was corrupted
4172  */
4173 static dbus_bool_t
4174 load_message (DBusMessageLoader *loader,
4175  DBusMessage *message,
4176  int byte_order,
4177  int fields_array_len,
4178  int header_len,
4179  int body_len)
4180 {
4181  dbus_bool_t oom;
4182  DBusValidity validity;
4183  const DBusString *type_str;
4184  int type_pos;
4185  DBusValidationMode mode;
4186  dbus_uint32_t n_unix_fds = 0;
4187 
4188  mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
4189 
4190  oom = FALSE;
4191 
4192 #if 0
4193  _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
4194 #endif
4195 
4196  /* 1. VALIDATE AND COPY OVER HEADER */
4197  _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
4198  _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
4199 
4200  if (!_dbus_header_load (&message->header,
4201  mode,
4202  &validity,
4203  byte_order,
4204  fields_array_len,
4205  header_len,
4206  body_len,
4207  &loader->data, 0,
4208  _dbus_string_get_length (&loader->data)))
4209  {
4210  _dbus_verbose ("Failed to load header for new message code %d\n", validity);
4211 
4212  /* assert here so we can catch any code that still uses DBUS_VALID to indicate
4213  oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
4214  _dbus_assert (validity != DBUS_VALID);
4215 
4216  if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
4217  oom = TRUE;
4218  else
4219  {
4220  loader->corrupted = TRUE;
4221  loader->corruption_reason = validity;
4222  }
4223  goto failed;
4224  }
4225 
4226  _dbus_assert (validity == DBUS_VALID);
4227 
4228  /* 2. VALIDATE BODY */
4229  if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
4230  {
4231  get_const_signature (&message->header, &type_str, &type_pos);
4232 
4233  /* Because the bytes_remaining arg is NULL, this validates that the
4234  * body is the right length
4235  */
4236  validity = _dbus_validate_body_with_reason (type_str,
4237  type_pos,
4238  byte_order,
4239  NULL,
4240  &loader->data,
4241  header_len,
4242  body_len);
4243  if (validity != DBUS_VALID)
4244  {
4245  _dbus_verbose ("Failed to validate message body code %d\n", validity);
4246 
4247  loader->corrupted = TRUE;
4248  loader->corruption_reason = validity;
4249 
4250  goto failed;
4251  }
4252  }
4253 
4254  /* 3. COPY OVER UNIX FDS */
4258  &n_unix_fds);
4259 
4260 #ifdef HAVE_UNIX_FD_PASSING
4261 
4262  if (n_unix_fds > loader->n_unix_fds)
4263  {
4264  _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
4265  n_unix_fds, loader->n_unix_fds);
4266 
4267  loader->corrupted = TRUE;
4268  loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4269  goto failed;
4270  }
4271 
4272  /* If this was a recycled message there might still be
4273  some memory allocated for the fds */
4274  dbus_free(message->unix_fds);
4275 
4276  if (n_unix_fds > 0)
4277  {
4278  message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
4279  if (message->unix_fds == NULL)
4280  {
4281  _dbus_verbose ("Failed to allocate file descriptor array\n");
4282  oom = TRUE;
4283  goto failed;
4284  }
4285 
4286  message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
4287  loader->n_unix_fds -= n_unix_fds;
4288  memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
4289 
4290  if (loader->unix_fds_change)
4291  loader->unix_fds_change (loader->unix_fds_change_data);
4292  }
4293  else
4294  message->unix_fds = NULL;
4295 
4296 #else
4297 
4298  if (n_unix_fds > 0)
4299  {
4300  _dbus_verbose ("Hmm, message claims to come with file descriptors "
4301  "but that's not supported on our platform, disconnecting.\n");
4302 
4303  loader->corrupted = TRUE;
4304  loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4305  goto failed;
4306  }
4307 
4308 #endif
4309 
4310  /* 3. COPY OVER BODY AND QUEUE MESSAGE */
4311 
4312  if (!_dbus_list_append (&loader->messages, message))
4313  {
4314  _dbus_verbose ("Failed to append new message to loader queue\n");
4315  oom = TRUE;
4316  goto failed;
4317  }
4318 
4319  _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4320  _dbus_assert (_dbus_string_get_length (&loader->data) >=
4321  (header_len + body_len));
4322 
4323  if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
4324  {
4325  _dbus_verbose ("Failed to move body into new message\n");
4326  oom = TRUE;
4327  goto failed;
4328  }
4329 
4330  _dbus_string_delete (&loader->data, 0, header_len + body_len);
4331 
4332  /* don't waste more than 2k of memory */
4333  _dbus_string_compact (&loader->data, 2048);
4334 
4335  _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
4336  _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4337 
4338  _dbus_verbose ("Loaded message %p\n", message);
4339 
4340  _dbus_assert (!oom);
4341  _dbus_assert (!loader->corrupted);
4342  _dbus_assert (loader->messages != NULL);
4343  _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4344 
4345  return TRUE;
4346 
4347  failed:
4348 
4349  /* Clean up */
4350 
4351  /* does nothing if the message isn't in the list */
4352  _dbus_list_remove_last (&loader->messages, message);
4353 
4354  if (oom)
4355  _dbus_assert (!loader->corrupted);
4356  else
4357  _dbus_assert (loader->corrupted);
4358 
4359  _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
4360 
4361  return FALSE;
4362 }
4363 
4380 {
4381  while (!loader->corrupted &&
4382  _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
4383  {
4384  DBusValidity validity;
4385  int byte_order, fields_array_len, header_len, body_len;
4386 
4388  &validity,
4389  &byte_order,
4390  &fields_array_len,
4391  &header_len,
4392  &body_len,
4393  &loader->data, 0,
4394  _dbus_string_get_length (&loader->data)))
4395  {
4397 
4398  _dbus_assert (validity == DBUS_VALID);
4399 
4400  message = dbus_message_new_empty_header ();
4401  if (message == NULL)
4402  return FALSE;
4403 
4404  if (!load_message (loader, message,
4405  byte_order, fields_array_len,
4406  header_len, body_len))
4407  {
4408  dbus_message_unref (message);
4409  /* load_message() returns false if corrupted or OOM; if
4410  * corrupted then return TRUE for not OOM
4411  */
4412  return loader->corrupted;
4413  }
4414 
4415  _dbus_assert (loader->messages != NULL);
4416  _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4417  }
4418  else
4419  {
4420  _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
4421  validity);
4422  if (validity != DBUS_VALID)
4423  {
4424  loader->corrupted = TRUE;
4425  loader->corruption_reason = validity;
4426  }
4427  return TRUE;
4428  }
4429  }
4430 
4431  return TRUE;
4432 }
4433 
4441 DBusMessage*
4443 {
4444  if (loader->messages)
4445  return loader->messages->data;
4446  else
4447  return NULL;
4448 }
4449 
4458 DBusMessage*
4460 {
4461  return _dbus_list_pop_first (&loader->messages);
4462 }
4463 
4472 DBusList*
4474 {
4475  return _dbus_list_pop_first_link (&loader->messages);
4476 }
4477 
4484 void
4486  DBusList *link)
4487 {
4488  _dbus_list_prepend_link (&loader->messages, link);
4489 }
4490 
4502 {
4503  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4504  (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4505  return loader->corrupted;
4506 }
4507 
4516 {
4517  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4518  (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4519 
4520  return loader->corruption_reason;
4521 }
4522 
4529 void
4531  long size)
4532 {
4533  if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
4534  {
4535  _dbus_verbose ("clamping requested max message size %ld to %d\n",
4538  }
4539  loader->max_message_size = size;
4540 }
4541 
4548 long
4550 {
4551  return loader->max_message_size;
4552 }
4553 
4560 void
4562  long n)
4563 {
4565  {
4566  _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
4569  }
4570  loader->max_message_unix_fds = n;
4571 }
4572 
4579 long
4581 {
4582  return loader->max_message_unix_fds;
4583 }
4584 
4590 int
4592 {
4593 #ifdef HAVE_UNIX_FD_PASSING
4594  return loader->n_unix_fds;
4595 #else
4596  return 0;
4597 #endif
4598 }
4599 
4608 void
4610  void (* callback) (void *),
4611  void *data)
4612 {
4613 #ifdef HAVE_UNIX_FD_PASSING
4614  loader->unix_fds_change = callback;
4615  loader->unix_fds_change_data = data;
4616 #endif
4617 }
4618 
4619 static DBusDataSlotAllocator slot_allocator =
4620  _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
4621 
4637 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
4638 {
4639  return _dbus_data_slot_allocator_alloc (&slot_allocator,
4640  slot_p);
4641 }
4642 
4654 void
4655 dbus_message_free_data_slot (dbus_int32_t *slot_p)
4656 {
4657  _dbus_return_if_fail (*slot_p >= 0);
4658 
4659  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
4660 }
4661 
4677  dbus_int32_t slot,
4678  void *data,
4679  DBusFreeFunction free_data_func)
4680 {
4681  DBusFreeFunction old_free_func;
4682  void *old_data;
4683  dbus_bool_t retval;
4684 
4685  _dbus_return_val_if_fail (message != NULL, FALSE);
4686  _dbus_return_val_if_fail (slot >= 0, FALSE);
4687 
4688  retval = _dbus_data_slot_list_set (&slot_allocator,
4689  &message->slot_list,
4690  slot, data, free_data_func,
4691  &old_free_func, &old_data);
4692 
4693  if (retval)
4694  {
4695  /* Do the actual free outside the message lock */
4696  if (old_free_func)
4697  (* old_free_func) (old_data);
4698  }
4699 
4700  return retval;
4701 }
4702 
4711 void*
4713  dbus_int32_t slot)
4714 {
4715  void *res;
4716 
4717  _dbus_return_val_if_fail (message != NULL, NULL);
4718 
4719  res = _dbus_data_slot_list_get (&slot_allocator,
4720  &message->slot_list,
4721  slot);
4722 
4723  return res;
4724 }
4725 
4739 int
4740 dbus_message_type_from_string (const char *type_str)
4741 {
4742  if (strcmp (type_str, "method_call") == 0)
4744  if (strcmp (type_str, "method_return") == 0)
4746  else if (strcmp (type_str, "signal") == 0)
4747  return DBUS_MESSAGE_TYPE_SIGNAL;
4748  else if (strcmp (type_str, "error") == 0)
4749  return DBUS_MESSAGE_TYPE_ERROR;
4750  else
4752 }
4753 
4767 const char *
4769 {
4770  switch (type)
4771  {
4773  return "method_call";
4775  return "method_return";
4777  return "signal";
4779  return "error";
4780  default:
4781  return "invalid";
4782  }
4783 }
4784 
4799  char **marshalled_data_p,
4800  int *len_p)
4801 {
4802  DBusString tmp;
4803  dbus_bool_t was_locked;
4804 
4805  _dbus_return_val_if_fail (msg != NULL, FALSE);
4806  _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
4807  _dbus_return_val_if_fail (len_p != NULL, FALSE);
4808 
4809  if (!_dbus_string_init (&tmp))
4810  return FALSE;
4811 
4812  /* Ensure the message is locked, to ensure the length header is filled in. */
4813  was_locked = msg->locked;
4814 
4815  if (!was_locked)
4816  dbus_message_lock (msg);
4817 
4818  if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
4819  goto fail;
4820 
4821  *len_p = _dbus_string_get_length (&tmp);
4822 
4823  if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
4824  goto fail;
4825 
4826  *len_p = _dbus_string_get_length (&tmp);
4827 
4828  if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
4829  goto fail;
4830 
4831  _dbus_string_free (&tmp);
4832 
4833  if (!was_locked)
4834  msg->locked = FALSE;
4835 
4836  return TRUE;
4837 
4838  fail:
4839  _dbus_string_free (&tmp);
4840 
4841  if (!was_locked)
4842  msg->locked = FALSE;
4843 
4844  return FALSE;
4845 }
4846 
4859 DBusMessage *
4860 dbus_message_demarshal (const char *str,
4861  int len,
4862  DBusError *error)
4863 {
4864  DBusMessageLoader *loader;
4865  DBusString *buffer;
4866  DBusMessage *msg;
4867 
4868  _dbus_return_val_if_fail (str != NULL, NULL);
4869 
4870  loader = _dbus_message_loader_new ();
4871 
4872  if (loader == NULL)
4873  return NULL;
4874 
4875  _dbus_message_loader_get_buffer (loader, &buffer);
4876 
4877  if (!_dbus_string_append_len (buffer, str, len))
4878  goto fail_oom;
4879 
4880  _dbus_message_loader_return_buffer (loader, buffer);
4881 
4883  goto fail_oom;
4884 
4886  goto fail_corrupt;
4887 
4888  msg = _dbus_message_loader_pop_message (loader);
4889 
4890  if (!msg)
4891  goto fail_oom;
4892 
4893  _dbus_message_loader_unref (loader);
4894  return msg;
4895 
4896  fail_corrupt:
4897  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
4898  _dbus_validity_to_error_message (loader->corruption_reason));
4899  _dbus_message_loader_unref (loader);
4900  return NULL;
4901 
4902  fail_oom:
4903  _DBUS_SET_OOM (error);
4904  _dbus_message_loader_unref (loader);
4905  return NULL;
4906 }
4907 
4920 int
4922  int len)
4923 {
4924  DBusString str;
4925  int byte_order, fields_array_len, header_len, body_len;
4926  DBusValidity validity = DBUS_VALID;
4927  int have_message;
4928 
4929  if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
4930  return 0;
4931 
4932  if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
4934  _dbus_string_init_const_len (&str, buf, len);
4935 
4936  validity = DBUS_VALID;
4937  have_message
4939  &validity, &byte_order,
4940  &fields_array_len,
4941  &header_len,
4942  &body_len,
4943  &str, 0,
4944  len);
4945  _dbus_string_free (&str);
4946 
4947  if (validity == DBUS_VALID)
4948  {
4949  _dbus_assert (have_message || (header_len + body_len) > len);
4950  (void) have_message; /* unused unless asserting */
4951  return header_len + body_len;
4952  }
4953  else
4954  {
4955  return -1; /* broken! */
4956  }
4957 }
4958 
4980 void
4982  dbus_bool_t allow)
4983 {
4984  _dbus_return_if_fail (message != NULL);
4985  _dbus_return_if_fail (!message->locked);
4986 
4987  _dbus_header_toggle_flag (&message->header,
4989  allow);
4990 }
4991 
5000 {
5001  _dbus_return_val_if_fail (message != NULL, FALSE);
5002 
5003  return _dbus_header_get_flag (&message->header,
5005 }
5006 
5009 /* 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
long _dbus_message_loader_get_max_message_size(DBusMessageLoader *loader)
Gets the maximum allowed message size in bytes.
void dbus_message_set_no_reply(DBusMessage *message, dbus_bool_t no_reply)
Sets a flag indicating that the message does not want a reply; if this flag is set, the other end of the connection may (but is not required to) optimize by not sending method return or error replies.
void _dbus_message_loader_putback_message_link(DBusMessageLoader *loader, DBusList *link)
Returns a popped message link, used to undo a pop.
dbus_bool_t _dbus_header_copy(const DBusHeader *header, DBusHeader *dest)
Initializes dest with a copy of the given header.
int dbus_message_iter_get_arg_type(DBusMessageIter *iter)
Returns the argument type of the argument that the message iterator points to.
dbus_uint32_t sig_refcount
depth of open_signature()
Definition: dbus-message.c:131
void _dbus_message_loader_return_buffer(DBusMessageLoader *loader, DBusString *buffer)
Returns a buffer obtained from _dbus_message_loader_get_buffer(), indicating to the loader how many b...
void _dbus_type_writer_remove_types(DBusTypeWriter *writer)
Removes type string from the writer.
void * dbus_realloc(void *memory, size_t bytes)
Resizes a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:601
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:701
void _dbus_message_loader_return_unix_fds(DBusMessageLoader *loader, int *fds, unsigned n_fds)
Returns a buffer obtained from _dbus_message_loader_get_unix_fds().
dbus_uint32_t dbus_message_get_serial(DBusMessage *message)
Returns the serial of a message or 0 if none has been specified.
DBusList * messages
Complete messages.
The type writer is an iterator for writing to a block of values.
void dbus_message_iter_recurse(DBusMessageIter *iter, DBusMessageIter *sub)
Recurses into a container value when reading values from a message, initializing a sub-iterator to us...
void _dbus_type_reader_recurse(DBusTypeReader *reader, DBusTypeReader *sub)
Initialize a new reader pointing to the first type and corresponding value that&#39;s a child of the curr...
DBusMessage * _dbus_message_loader_pop_message(DBusMessageLoader *loader)
Pops a loaded message (passing ownership of the message to the caller).
DBusList * _dbus_list_find_last(DBusList **list, void *data)
Finds a value in the list.
Definition: dbus-list.c:472
dbus_bool_t dbus_message_set_interface(DBusMessage *message, const char *iface)
Sets the interface this message is being sent to (for DBUS_MESSAGE_TYPE_METHOD_CALL) or the interface...
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn&#39;t supported (like ENOSYS on UNIX).
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:58
void dbus_message_free_data_slot(dbus_int32_t *slot_p)
Deallocates a global ID for message data slots.
#define DBUS_HEADER_FIELD_SIGNATURE
Header field code for the type signature of a message.
const char * dbus_message_get_error_name(DBusMessage *message)
Gets the error name (DBUS_MESSAGE_TYPE_ERROR only) or NULL if none.
dbus_bool_t dbus_message_iter_close_container(DBusMessageIter *iter, DBusMessageIter *sub)
Closes a container-typed value appended to the message; may write out more information to the message...
dbus_bool_t dbus_message_is_error(DBusMessage *message, const char *error_name)
Checks whether the message is an error reply with the given error name.
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition: dbus-list.c:527
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can&#39;t appear in a type string...
#define DBUS_TYPE_DICT_ENTRY
Type code used to represent a dict entry; however, this type code does not appear in type signatures...
const char * dbus_message_get_sender(DBusMessage *message)
Gets the unique name of the connection which originated this message, or NULL if unknown or inapplica...
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_message_iter_get_args_valist(DBusMessageIter *iter, DBusError *error, int first_arg_type, va_list var_args)
Implementation of the varargs arg-getting functions.
Definition: dbus-message.c: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 "critical" warning to stderr when an assertion fails; differs from _dbus_warn primarily in t...
const char * dbus_message_get_signature(DBusMessage *message)
Gets the type signature of the message, i.e.
void dbus_message_iter_init_append(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for appending arguments to the end of a message.
void dbus_error_free(DBusError *error)
Frees an error that&#39;s been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:211
void dbus_message_set_auto_start(DBusMessage *message, dbus_bool_t auto_start)
Sets a flag indicating that an owner for the destination name will be automatically started before th...
union DBusMessageRealIter::@6 u
the type writer or reader that does all the work
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...
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 "basic type" is a somewhat arbitrary concept, but the intent is to include those types that are ful...
void _dbus_message_loader_set_max_message_size(DBusMessageLoader *loader, long size)
Sets the maximum size message we allow.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:35
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:190
DBusHeader header
Header network data and associated cache.
dbus_bool_t dbus_message_set_sender(DBusMessage *message, const char *sender)
Sets the message sender.
dbus_bool_t dbus_message_is_signal(DBusMessage *message, const char *iface, const char *signal_name)
Checks whether the message is a signal with the given interface and member fields.
DBusString data
Buffered data.
void _dbus_type_reader_read_basic(const DBusTypeReader *reader, void *value)
Reads a basic-typed value, as with _dbus_marshal_read_basic().
unsigned int locked
Message being sent, no modifications allowed.
#define ensure_byte_order(message)
byte-swap the message if it doesn&#39;t match our byte order.
Definition: dbus-message.c:218
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 "level".
DBusList * counters
0-N DBusCounter used to track message size/unix fds.
DBusMessageLoader * _dbus_message_loader_new(void)
Creates a new message loader.
long size_counter_delta
Size we incremented the size counters by.
#define CHANGED_STAMP_BITS
How many bits are in the changed_stamp used to validate iterators.
void _dbus_header_byteswap(DBusHeader *header, int new_order)
Swaps the header into the given order if required.
dbus_bool_t _dbus_header_have_message_untrusted(int max_message_length, DBusValidity *validity, int *byte_order, int *fields_array_len, int *header_len, int *body_len, const DBusString *str, int start, int len)
Given data long enough to contain the length of the message body and the fields array, check whether the data is long enough to contain the entire message (assuming the claimed lengths are accurate).
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type()
#define DBUS_HEADER_FIELD_UNIX_FDS
Header field code for the number of unix file descriptors associated with this message.
int _dbus_current_generation
_dbus_current_generation is used to track each time that dbus_shutdown() is called, so we can reinit things after it&#39;s been called.
Definition: dbus-memory.c:781
dbus_bool_t dbus_message_get_args(DBusMessage *message, DBusError *error, int first_arg_type,...)
Gets arguments from a message given a variable argument list.
Object representing an exception.
Definition: dbus-errors.h:48
unsigned int in_cache
Has been "freed" since it&#39;s in the cache (this is a debug feature)
int dbus_message_iter_get_element_count(DBusMessageIter *iter)
Returns the number of elements in the array-typed value pointed to by the iterator.
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:649
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
void _dbus_message_loader_set_pending_fds_function(DBusMessageLoader *loader, void(*callback)(void *), void *data)
Register a function to be called whenever the number of pending file descriptors in the loader change...
dbus_bool_t dbus_message_append_args(DBusMessage *message, int first_arg_type,...)
Appends fields to a message given a variable argument list.
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type()
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
dbus_uint32_t dbus_message_get_reply_serial(DBusMessage *message)
Returns the serial that the message is a reply to or 0 if none.
#define INITIAL_LOADER_DATA_LEN
The initial buffer size of the message loader.
dbus_bool_t dbus_message_has_signature(DBusMessage *message, const char *signature)
Checks whether the message has the given signature; see dbus_message_get_signature() for more details...
void _dbus_data_slot_list_clear(DBusDataSlotList *list)
Frees all data slots contained in the list, calling application-provided free functions if they exist...
dbus_bool_t _dbus_message_loader_get_is_corrupted(DBusMessageLoader *loader)
Checks whether the loader is confused due to bad data.
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition: dbus-protocol.h:86
void _dbus_header_reinit(DBusHeader *header)
Re-initializes a header that was previously initialized and never freed.
the data is valid
DBusMessage * dbus_message_new_method_call(const char *destination, const char *path, const char *iface, const char *method)
Constructs a new message to invoke a method on a remote object.
#define DBUS_HEADER_FIELD_DESTINATION
Header field code for the destination bus name of a message.
dbus_uint32_t byte_order
byte order of the block
dbus_bool_t _dbus_header_delete_field(DBusHeader *header, int field)
Deletes a field, if it exists.
dbus_bool_t dbus_message_has_destination(DBusMessage *message, const char *name)
Checks whether the message was sent to the given name.
#define DBUS_MESSAGE_TYPE_INVALID
This value is never a valid message type, see dbus_message_get_type()
#define DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION
If set on a method call, this flag means that the caller is prepared to wait for interactive authoriz...
dbus_bool_t dbus_message_get_auto_start(DBusMessage *message)
Returns TRUE if the message will cause an owner for destination name to be auto-started.
dbus_uint32_t byte_order
byte order to write values with
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init().
Definition: dbus-string.c:259
The type reader is an iterator for reading values from a block of values.
void * _dbus_data_slot_list_get(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot)
Retrieves data previously set with _dbus_data_slot_list_set_data().
long _dbus_message_loader_get_max_message_unix_fds(DBusMessageLoader *loader)
Gets the maximum allowed number of unix fds per message.
#define TRUE
Expands to "1".
dbus_bool_t dbus_message_marshal(DBusMessage *msg, char **marshalled_data_p, int *len_p)
Turn a DBusMessage into the marshalled form as described in the D-Bus specification.
dbus_bool_t _dbus_header_set_field_basic(DBusHeader *header, int field, int type, const void *value)
Sets the value of a field with basic type.
void _dbus_data_slot_list_init(DBusDataSlotList *list)
Initializes a slot list.
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
DBusMessage * dbus_message_copy(const DBusMessage *message)
Creates a new message that is an exact replica of the message specified, except that its refcount is ...
int dbus_message_iter_get_element_type(DBusMessageIter *iter)
Returns the element type of the array that the message iterator points to.
void _dbus_message_get_network_data(DBusMessage *message, const DBusString **header, const DBusString **body)
Gets the data to be sent over the network for this message.
Definition: dbus-message.c: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.
_DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str,"")
An static string representing an empty signature.
void dbus_message_iter_get_basic(DBusMessageIter *iter, void *value)
Reads a basic-typed value from the message iterator.
void * dbus_message_get_data(DBusMessage *message, dbus_int32_t slot)
Retrieves data previously set with dbus_message_set_data().
void _dbus_type_reader_init(DBusTypeReader *reader, int byte_order, const DBusString *type_str, int type_pos, const DBusString *value_str, int value_pos)
Initializes a type reader.
void _dbus_header_free(DBusHeader *header)
Frees a header.
DBusList * _dbus_message_loader_pop_message_link(DBusMessageLoader *loader)
Pops a loaded message inside a list link (passing ownership of the message and link to the caller)...
#define DBUS_MAXIMUM_ARRAY_LENGTH
Max length of a marshaled array in bytes (64M, 2^26) We use signed int for lengths so must be INT_MAX...
dbus_bool_t dbus_message_set_destination(DBusMessage *message, const char *destination)
Sets the message&#39;s destination.
void dbus_error_init(DBusError *error)
Initializes a DBusError structure.
Definition: dbus-errors.c:188
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_bool_t _dbus_message_loader_get_unix_fds(DBusMessageLoader *loader, int **fds, unsigned *max_n_fds)
Gets the buffer to use for reading unix fds from the network.
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:749
#define DBUS_TYPE_BOOLEAN
Type code marking a boolean.
Definition: dbus-protocol.h:70
void _dbus_message_loader_get_buffer(DBusMessageLoader *loader, DBusString **buffer)
Gets the buffer to use for reading data from the network.
dbus_bool_t _dbus_string_append_len(DBusString *str, const char *buffer, int len)
Appends block of bytes with the given length to a DBusString.
Definition: dbus-string.c:1137
dbus_uint32_t iter_type
whether this is a reader or writer iter
Definition: dbus-message.c:130
void _dbus_header_set_serial(DBusHeader *header, dbus_uint32_t serial)
Sets the serial number of a header.
int _dbus_type_reader_get_element_type(const DBusTypeReader *reader)
Gets the type of an element of the array the reader is currently pointing to.
char _dbus_header_get_byte_order(const DBusHeader *header)
Returns the header&#39;s byte order.
dbus_bool_t dbus_message_iter_open_container(DBusMessageIter *iter, int type, const char *contained_signature, DBusMessageIter *sub)
Appends a container-typed value to the message; you are required to append the contents of the contai...
dbus_bool_t _dbus_type_reader_has_next(const DBusTypeReader *reader)
Check whether there&#39;s another value on this "level".
A simple value union that lets you access bytes as if they were various types; useful when dealing wi...
Definition: dbus-types.h:137
dbus_uint32_t container_type
what are we inside? (e.g.
int _dbus_type_reader_get_array_length(const DBusTypeReader *reader)
Returns the number of bytes in the array.
dbus_bool_t _dbus_header_get_field_raw(DBusHeader *header, int field, const DBusString **str, int *pos)
Gets the raw marshaled data for a field.
dbus_bool_t dbus_message_iter_append_basic(DBusMessageIter *iter, int type, const void *value)
Appends a basic-typed value to the message.
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
int dbus_message_iter_get_array_len(DBusMessageIter *iter)
Returns the number of bytes in the array as marshaled in the wire protocol.
void(* DBusForeachFunction)(void *element, void *data)
Used to iterate over each item in a collection, such as a DBusList.
int _dbus_type_reader_get_current_type(const DBusTypeReader *reader)
Gets the type of the value the reader is currently pointing to; or for a types-only reader gets the t...
#define FALSE
Expands to "0".
Message header data and some cached details of it.
void dbus_message_set_allow_interactive_authorization(DBusMessage *message, dbus_bool_t allow)
Sets a flag indicating that the caller of the method is prepared to wait for interactive authorizatio...
#define DBUS_HEADER_FIELD_PATH
Header field code for the path - the path is the object emitting a signal or the object receiving a m...
int dbus_message_get_type(DBusMessage *message)
Gets the type of a message.
#define DBUS_HEADER_FIELD_REPLY_SERIAL
Header field code for a reply serial, used to match a DBUS_MESSAGE_TYPE_METHOD_RETURN message with th...
unsigned int buffer_outstanding
Someone is using the buffer to read.
int generation
_dbus_current_generation when message was created
void _dbus_list_prepend_link(DBusList **list, DBusList *link)
Prepends a link to the list.
Definition: dbus-list.c:333
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:802
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_register_shutdown_func(DBusShutdownFunction function, void *data)
Register a cleanup function to be called exactly once the next time dbus_shutdown() is called...
Definition: dbus-memory.c:810
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
#define _DBUS_LOCK_NAME(name)
Expands to name of a global lock variable.
const char * _dbus_type_to_string(int typecode)
Returns a string describing the given type.
DBusMessage * _dbus_message_loader_peek_message(DBusMessageLoader *loader)
Peeks at first loaded message, returns NULL if no messages have been queued.
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition: dbus-string.c:1375
dbus_bool_t _dbus_string_steal_data(DBusString *str, char **data_return)
Like _dbus_string_get_data(), but removes the gotten data from the original string.
Definition: dbus-string.c:641
void _dbus_type_reader_get_signature(const DBusTypeReader *reader, const DBusString **str_p, int *start_p, int *len_p)
Gets the string and range of said string containing the signature of the current value.
dbus_bool_t dbus_message_append_args_valist(DBusMessage *message, int first_arg_type, va_list var_args)
Like dbus_message_append_args() but takes a va_list for use by language bindings. ...
int dbus_message_demarshal_bytes_needed(const char *buf, int len)
Returns the number of bytes required to be in the buffer to demarshal a D-Bus message.
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_bool_t _dbus_message_loader_queue_messages(DBusMessageLoader *loader)
Converts buffered data into messages, if we have enough data.
void _dbus_message_get_unix_fds(DBusMessage *message, const int **fds, unsigned *n_fds)
Gets the unix fds to be sent over the network for this message.
Definition: dbus-message.c: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 "container type" can contain basic types, or nested container types.
DBusMessage * dbus_message_new_error(DBusMessage *reply_to, const char *error_name, const char *error_message)
Creates a new message that is an error reply to another message.
void _dbus_counter_adjust_size(DBusCounter *counter, long delta)
Adjusts the value of the size counter by the given delta which may be positive or negative...