D-Bus  1.10.10
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  _dbus_return_val_if_fail (message != NULL, FALSE);
1170  _dbus_return_val_if_fail (!message->locked, FALSE);
1171  _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
1172 
1173  return _dbus_header_set_field_basic (&message->header,
1176  &reply_serial);
1177 }
1178 
1185 dbus_uint32_t
1187 {
1188  dbus_uint32_t v_UINT32;
1189 
1190  _dbus_return_val_if_fail (message != NULL, 0);
1191 
1192  if (_dbus_header_get_field_basic (&message->header,
1195  &v_UINT32))
1196  return v_UINT32;
1197  else
1198  return 0;
1199 }
1200 
1201 static void
1202 dbus_message_finalize (DBusMessage *message)
1203 {
1204  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1205 
1206  /* This calls application callbacks! */
1208 
1209  _dbus_list_foreach (&message->counters,
1210  free_counter, message);
1211  _dbus_list_clear (&message->counters);
1212 
1213  _dbus_header_free (&message->header);
1214  _dbus_string_free (&message->body);
1215 
1216 #ifdef HAVE_UNIX_FD_PASSING
1217  close_unix_fds(message->unix_fds, &message->n_unix_fds);
1218  dbus_free(message->unix_fds);
1219 #endif
1220 
1221  _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1222 
1223  dbus_free (message);
1224 }
1225 
1226 static DBusMessage*
1227 dbus_message_new_empty_header (void)
1228 {
1230  dbus_bool_t from_cache;
1231 
1232  message = dbus_message_get_cached ();
1233 
1234  if (message != NULL)
1235  {
1236  from_cache = TRUE;
1237  }
1238  else
1239  {
1240  from_cache = FALSE;
1241  message = dbus_new0 (DBusMessage, 1);
1242  if (message == NULL)
1243  return NULL;
1244 #ifndef DBUS_DISABLE_CHECKS
1246 #endif
1247 
1248 #ifdef HAVE_UNIX_FD_PASSING
1249  message->unix_fds = NULL;
1250  message->n_unix_fds_allocated = 0;
1251 #endif
1252  }
1253 
1254  _dbus_atomic_inc (&message->refcount);
1255 
1256  _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
1257 
1258  message->locked = FALSE;
1259 #ifndef DBUS_DISABLE_CHECKS
1260  message->in_cache = FALSE;
1261 #endif
1262  message->counters = NULL;
1263  message->size_counter_delta = 0;
1264  message->changed_stamp = 0;
1265 
1266 #ifdef HAVE_UNIX_FD_PASSING
1267  message->n_unix_fds = 0;
1268  message->n_unix_fds_allocated = 0;
1269  message->unix_fd_counter_delta = 0;
1270 #endif
1271 
1272  if (!from_cache)
1274 
1275  if (from_cache)
1276  {
1277  _dbus_header_reinit (&message->header);
1278  _dbus_string_set_length (&message->body, 0);
1279  }
1280  else
1281  {
1282  if (!_dbus_header_init (&message->header))
1283  {
1284  dbus_free (message);
1285  return NULL;
1286  }
1287 
1288  if (!_dbus_string_init_preallocated (&message->body, 32))
1289  {
1290  _dbus_header_free (&message->header);
1291  dbus_free (message);
1292  return NULL;
1293  }
1294  }
1295 
1296  return message;
1297 }
1298 
1311 DBusMessage*
1312 dbus_message_new (int message_type)
1313 {
1315 
1316  _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
1317 
1318  message = dbus_message_new_empty_header ();
1319  if (message == NULL)
1320  return NULL;
1321 
1322  if (!_dbus_header_create (&message->header,
1323  DBUS_COMPILER_BYTE_ORDER,
1324  message_type,
1325  NULL, NULL, NULL, NULL, NULL))
1326  {
1327  dbus_message_unref (message);
1328  return NULL;
1329  }
1330 
1331  return message;
1332 }
1333 
1355 DBusMessage*
1356 dbus_message_new_method_call (const char *destination,
1357  const char *path,
1358  const char *iface,
1359  const char *method)
1360 {
1362 
1363  _dbus_return_val_if_fail (path != NULL, NULL);
1364  _dbus_return_val_if_fail (method != NULL, NULL);
1365  _dbus_return_val_if_fail (destination == NULL ||
1366  _dbus_check_is_valid_bus_name (destination), NULL);
1367  _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1368  _dbus_return_val_if_fail (iface == NULL ||
1369  _dbus_check_is_valid_interface (iface), NULL);
1370  _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
1371 
1372  message = dbus_message_new_empty_header ();
1373  if (message == NULL)
1374  return NULL;
1375 
1376  if (!_dbus_header_create (&message->header,
1377  DBUS_COMPILER_BYTE_ORDER,
1379  destination, path, iface, method, NULL))
1380  {
1381  dbus_message_unref (message);
1382  return NULL;
1383  }
1384 
1385  return message;
1386 }
1387 
1395 DBusMessage*
1397 {
1399  const char *sender;
1400 
1401  _dbus_return_val_if_fail (method_call != NULL, NULL);
1402 
1403  sender = dbus_message_get_sender (method_call);
1404 
1405  /* sender is allowed to be null here in peer-to-peer case */
1406 
1407  message = dbus_message_new_empty_header ();
1408  if (message == NULL)
1409  return NULL;
1410 
1411  if (!_dbus_header_create (&message->header,
1412  DBUS_COMPILER_BYTE_ORDER,
1414  sender, NULL, NULL, NULL, NULL))
1415  {
1416  dbus_message_unref (message);
1417  return NULL;
1418  }
1419 
1420  dbus_message_set_no_reply (message, TRUE);
1421 
1422  if (!dbus_message_set_reply_serial (message,
1423  dbus_message_get_serial (method_call)))
1424  {
1425  dbus_message_unref (message);
1426  return NULL;
1427  }
1428 
1429  return message;
1430 }
1431 
1446 DBusMessage*
1447 dbus_message_new_signal (const char *path,
1448  const char *iface,
1449  const char *name)
1450 {
1452 
1453  _dbus_return_val_if_fail (path != NULL, NULL);
1454  _dbus_return_val_if_fail (iface != NULL, NULL);
1455  _dbus_return_val_if_fail (name != NULL, NULL);
1456  _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1457  _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
1458  _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
1459 
1460  message = dbus_message_new_empty_header ();
1461  if (message == NULL)
1462  return NULL;
1463 
1464  if (!_dbus_header_create (&message->header,
1465  DBUS_COMPILER_BYTE_ORDER,
1467  NULL, path, iface, name, NULL))
1468  {
1469  dbus_message_unref (message);
1470  return NULL;
1471  }
1472 
1473  dbus_message_set_no_reply (message, TRUE);
1474 
1475  return message;
1476 }
1477 
1492 DBusMessage*
1494  const char *error_name,
1495  const char *error_message)
1496 {
1498  const char *sender;
1499  DBusMessageIter iter;
1500 
1501  _dbus_return_val_if_fail (reply_to != NULL, NULL);
1502  _dbus_return_val_if_fail (error_name != NULL, NULL);
1503  _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1504 
1505  sender = dbus_message_get_sender (reply_to);
1506 
1507  /* sender may be NULL for non-message-bus case or
1508  * when the message bus is dealing with an unregistered
1509  * connection.
1510  */
1511  message = dbus_message_new_empty_header ();
1512  if (message == NULL)
1513  return NULL;
1514 
1515  if (!_dbus_header_create (&message->header,
1516  DBUS_COMPILER_BYTE_ORDER,
1518  sender, NULL, NULL, NULL, error_name))
1519  {
1520  dbus_message_unref (message);
1521  return NULL;
1522  }
1523 
1524  dbus_message_set_no_reply (message, TRUE);
1525 
1526  if (!dbus_message_set_reply_serial (message,
1527  dbus_message_get_serial (reply_to)))
1528  {
1529  dbus_message_unref (message);
1530  return NULL;
1531  }
1532 
1533  if (error_message != NULL)
1534  {
1535  dbus_message_iter_init_append (message, &iter);
1536  if (!dbus_message_iter_append_basic (&iter,
1538  &error_message))
1539  {
1540  dbus_message_unref (message);
1541  return NULL;
1542  }
1543  }
1544 
1545  return message;
1546 }
1547 
1564 DBusMessage*
1566  const char *error_name,
1567  const char *error_format,
1568  ...)
1569 {
1570  va_list args;
1571  DBusString str;
1573 
1574  _dbus_return_val_if_fail (reply_to != NULL, NULL);
1575  _dbus_return_val_if_fail (error_name != NULL, NULL);
1576  _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1577 
1578  if (!_dbus_string_init (&str))
1579  return NULL;
1580 
1581  va_start (args, error_format);
1582 
1583  if (_dbus_string_append_printf_valist (&str, error_format, args))
1584  message = dbus_message_new_error (reply_to, error_name,
1585  _dbus_string_get_const_data (&str));
1586  else
1587  message = NULL;
1588 
1589  _dbus_string_free (&str);
1590 
1591  va_end (args);
1592 
1593  return message;
1594 }
1595 
1596 
1609 DBusMessage *
1611 {
1612  DBusMessage *retval;
1613 
1614  _dbus_return_val_if_fail (message != NULL, NULL);
1615 
1616  retval = dbus_new0 (DBusMessage, 1);
1617  if (retval == NULL)
1618  return NULL;
1619 
1620  _dbus_atomic_inc (&retval->refcount);
1621 
1622  retval->locked = FALSE;
1623 #ifndef DBUS_DISABLE_CHECKS
1624  retval->generation = message->generation;
1625 #endif
1626 
1627  if (!_dbus_header_copy (&message->header, &retval->header))
1628  {
1629  dbus_free (retval);
1630  return NULL;
1631  }
1632 
1633  if (!_dbus_string_init_preallocated (&retval->body,
1634  _dbus_string_get_length (&message->body)))
1635  {
1636  _dbus_header_free (&retval->header);
1637  dbus_free (retval);
1638  return NULL;
1639  }
1640 
1641  if (!_dbus_string_copy (&message->body, 0,
1642  &retval->body, 0))
1643  goto failed_copy;
1644 
1645 #ifdef HAVE_UNIX_FD_PASSING
1646  retval->unix_fds = dbus_new(int, message->n_unix_fds);
1647  if (retval->unix_fds == NULL && message->n_unix_fds > 0)
1648  goto failed_copy;
1649 
1650  retval->n_unix_fds_allocated = message->n_unix_fds;
1651 
1652  for (retval->n_unix_fds = 0;
1653  retval->n_unix_fds < message->n_unix_fds;
1654  retval->n_unix_fds++)
1655  {
1656  retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
1657 
1658  if (retval->unix_fds[retval->n_unix_fds] < 0)
1659  goto failed_copy;
1660  }
1661 
1662 #endif
1663 
1664  _dbus_message_trace_ref (retval, 0, 1, "copy");
1665  return retval;
1666 
1667  failed_copy:
1668  _dbus_header_free (&retval->header);
1669  _dbus_string_free (&retval->body);
1670 
1671 #ifdef HAVE_UNIX_FD_PASSING
1672  close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
1673  dbus_free(retval->unix_fds);
1674 #endif
1675 
1676  dbus_free (retval);
1677 
1678  return NULL;
1679 }
1680 
1681 
1689 DBusMessage *
1691 {
1692  dbus_int32_t old_refcount;
1693 
1694  _dbus_return_val_if_fail (message != NULL, NULL);
1695  _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
1696  _dbus_return_val_if_fail (!message->in_cache, NULL);
1697 
1698  old_refcount = _dbus_atomic_inc (&message->refcount);
1699  _dbus_assert (old_refcount >= 1);
1700  _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
1701 
1702  return message;
1703 }
1704 
1712 void
1714 {
1715  dbus_int32_t old_refcount;
1716 
1717  _dbus_return_if_fail (message != NULL);
1718  _dbus_return_if_fail (message->generation == _dbus_current_generation);
1719  _dbus_return_if_fail (!message->in_cache);
1720 
1721  old_refcount = _dbus_atomic_dec (&message->refcount);
1722 
1723  _dbus_assert (old_refcount >= 1);
1724 
1725  _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
1726 
1727  if (old_refcount == 1)
1728  {
1729  /* Calls application callbacks! */
1730  dbus_message_cache_or_finalize (message);
1731  }
1732 }
1733 
1744 int
1746 {
1747  _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
1748 
1749  return _dbus_header_get_message_type (&message->header);
1750 }
1751 
1816  int first_arg_type,
1817  ...)
1818 {
1819  dbus_bool_t retval;
1820  va_list var_args;
1821 
1822  _dbus_return_val_if_fail (message != NULL, FALSE);
1823 
1824  va_start (var_args, first_arg_type);
1825  retval = dbus_message_append_args_valist (message,
1826  first_arg_type,
1827  var_args);
1828  va_end (var_args);
1829 
1830  return retval;
1831 }
1832 
1848  int first_arg_type,
1849  va_list var_args)
1850 {
1851  int type;
1852  DBusMessageIter iter;
1853 
1854  _dbus_return_val_if_fail (message != NULL, FALSE);
1855 
1856  type = first_arg_type;
1857 
1858  dbus_message_iter_init_append (message, &iter);
1859 
1860  while (type != DBUS_TYPE_INVALID)
1861  {
1862  if (dbus_type_is_basic (type))
1863  {
1864  const DBusBasicValue *value;
1865  value = va_arg (var_args, const DBusBasicValue*);
1866 
1867  if (!dbus_message_iter_append_basic (&iter,
1868  type,
1869  value))
1870  goto failed;
1871  }
1872  else if (type == DBUS_TYPE_ARRAY)
1873  {
1874  int element_type;
1875  DBusMessageIter array;
1876  char buf[2];
1877 
1878  element_type = va_arg (var_args, int);
1879 
1880  buf[0] = element_type;
1881  buf[1] = '\0';
1884  buf,
1885  &array))
1886  goto failed;
1887 
1888  if (dbus_type_is_fixed (element_type) &&
1889  element_type != DBUS_TYPE_UNIX_FD)
1890  {
1891  const DBusBasicValue **value;
1892  int n_elements;
1893 
1894  value = va_arg (var_args, const DBusBasicValue**);
1895  n_elements = va_arg (var_args, int);
1896 
1898  element_type,
1899  value,
1900  n_elements)) {
1901  dbus_message_iter_abandon_container (&iter, &array);
1902  goto failed;
1903  }
1904  }
1905  else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
1906  {
1907  const char ***value_p;
1908  const char **value;
1909  int n_elements;
1910  int i;
1911 
1912  value_p = va_arg (var_args, const char***);
1913  n_elements = va_arg (var_args, int);
1914 
1915  value = *value_p;
1916 
1917  i = 0;
1918  while (i < n_elements)
1919  {
1920  if (!dbus_message_iter_append_basic (&array,
1921  element_type,
1922  &value[i])) {
1923  dbus_message_iter_abandon_container (&iter, &array);
1924  goto failed;
1925  }
1926  ++i;
1927  }
1928  }
1929  else
1930  {
1931  _dbus_warn ("arrays of %s can't be appended with %s for now\n",
1932  _dbus_type_to_string (element_type),
1933  _DBUS_FUNCTION_NAME);
1934  goto failed;
1935  }
1936 
1937  if (!dbus_message_iter_close_container (&iter, &array))
1938  goto failed;
1939  }
1940 #ifndef DBUS_DISABLE_CHECKS
1941  else
1942  {
1943  _dbus_warn ("type %s isn't supported yet in %s\n",
1944  _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
1945  goto failed;
1946  }
1947 #endif
1948 
1949  type = va_arg (var_args, int);
1950  }
1951 
1952  return TRUE;
1953 
1954  failed:
1955  return FALSE;
1956 }
1957 
2004  DBusError *error,
2005  int first_arg_type,
2006  ...)
2007 {
2008  dbus_bool_t retval;
2009  va_list var_args;
2010 
2011  _dbus_return_val_if_fail (message != NULL, FALSE);
2012  _dbus_return_val_if_error_is_set (error, FALSE);
2013 
2014  va_start (var_args, first_arg_type);
2015  retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
2016  va_end (var_args);
2017 
2018  return retval;
2019 }
2020 
2033  DBusError *error,
2034  int first_arg_type,
2035  va_list var_args)
2036 {
2037  DBusMessageIter iter;
2038 
2039  _dbus_return_val_if_fail (message != NULL, FALSE);
2040  _dbus_return_val_if_error_is_set (error, FALSE);
2041 
2042  dbus_message_iter_init (message, &iter);
2043  return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
2044 }
2045 
2046 static void
2047 _dbus_message_iter_init_common (DBusMessage *message,
2048  DBusMessageRealIter *real,
2049  int iter_type)
2050 {
2051  /* If these static assertions fail on your platform, report it as a bug. */
2052  _DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
2053  _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <=
2054  _DBUS_ALIGNOF (DBusMessageIter));
2055  /* A failure of these two assertions would indicate that we've broken
2056  * ABI on this platform since 1.10.0. */
2057  _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) ==
2058  sizeof (DBusMessageIter));
2059  _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) ==
2060  _DBUS_ALIGNOF (DBusMessageIter));
2061  /* If this static assertion fails, it means the DBusMessageIter struct
2062  * is not "packed", which might result in "iter = other_iter" not copying
2063  * every byte. */
2064  _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) ==
2065  4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int));
2066 
2067  /* Since the iterator will read or write who-knows-what from the
2068  * message, we need to get in the right byte order
2069  */
2070  ensure_byte_order (message);
2071 
2072  real->message = message;
2073  real->changed_stamp = message->changed_stamp;
2074  real->iter_type = iter_type;
2075  real->sig_refcount = 0;
2076 }
2077 
2102  DBusMessageIter *iter)
2103 {
2104  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2105  const DBusString *type_str;
2106  int type_pos;
2107 
2108  _dbus_return_val_if_fail (message != NULL, FALSE);
2109  _dbus_return_val_if_fail (iter != NULL, FALSE);
2110 
2111  get_const_signature (&message->header, &type_str, &type_pos);
2112 
2113  _dbus_message_iter_init_common (message, real,
2114  DBUS_MESSAGE_ITER_TYPE_READER);
2115 
2117  _dbus_header_get_byte_order (&message->header),
2118  type_str, type_pos,
2119  &message->body,
2120  0);
2121 
2123 }
2124 
2133 {
2134  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2135 
2136  _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2137  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2138 
2139  return _dbus_type_reader_has_next (&real->u.reader);
2140 }
2141 
2152 {
2153  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2154 
2155  _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2156  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2157 
2158  return _dbus_type_reader_next (&real->u.reader);
2159 }
2160 
2175 int
2177 {
2178  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2179 
2180  _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2181  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2182 
2184 }
2185 
2194 int
2196 {
2197  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2198 
2199  _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2200  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
2201  _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
2202 
2204 }
2205 
2231 void
2233  DBusMessageIter *sub)
2234 {
2235  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2236  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2237 
2238  _dbus_return_if_fail (_dbus_message_iter_check (real));
2239  _dbus_return_if_fail (sub != NULL);
2240 
2241  *real_sub = *real;
2242  _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
2243 }
2244 
2256 char *
2258 {
2259  const DBusString *sig;
2260  DBusString retstr;
2261  char *ret;
2262  int start, len;
2263  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2264 
2265  _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
2266 
2267  if (!_dbus_string_init (&retstr))
2268  return NULL;
2269 
2271  &start, &len);
2272  if (!_dbus_string_append_len (&retstr,
2273  _dbus_string_get_const_data (sig) + start,
2274  len))
2275  return NULL;
2276  if (!_dbus_string_steal_data (&retstr, &ret))
2277  return NULL;
2278  _dbus_string_free (&retstr);
2279  return ret;
2280 }
2281 
2329 void
2331  void *value)
2332 {
2333  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2334 
2335  _dbus_return_if_fail (_dbus_message_iter_check (real));
2336  _dbus_return_if_fail (value != NULL);
2337 
2339  {
2340 #ifdef HAVE_UNIX_FD_PASSING
2341  DBusBasicValue idx;
2342 
2343  _dbus_type_reader_read_basic(&real->u.reader, &idx);
2344 
2345  if (idx.u32 >= real->message->n_unix_fds) {
2346  /* Hmm, we cannot really signal an error here, so let's make
2347  sure to return an invalid fd. */
2348  *((int*) value) = -1;
2349  return;
2350  }
2351 
2352  *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
2353 #else
2354  *((int*) value) = -1;
2355 #endif
2356  }
2357  else
2358  {
2360  value);
2361  }
2362 }
2363 
2374 int
2376 {
2377  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2378  DBusTypeReader array;
2379  int element_type;
2380  int n_elements = 0;
2381 
2382  _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2383  _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
2384  == DBUS_TYPE_ARRAY, 0);
2385 
2386  element_type = _dbus_type_reader_get_element_type (&real->u.reader);
2387  _dbus_type_reader_recurse (&real->u.reader, &array);
2388  if (dbus_type_is_fixed (element_type))
2389  {
2390  int alignment = _dbus_type_get_alignment (element_type);
2391  int total_len = _dbus_type_reader_get_array_length (&array);
2392  n_elements = total_len / alignment;
2393  }
2394  else
2395  {
2397  {
2398  ++n_elements;
2399  _dbus_type_reader_next (&array);
2400  }
2401  }
2402 
2403  return n_elements;
2404 }
2405 
2418 int
2420 {
2421  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2422 
2423  _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2424 
2426 }
2427 
2463 void
2465  void *value,
2466  int *n_elements)
2467 {
2468  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2469 #ifndef DBUS_DISABLE_CHECKS
2470  int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
2471 
2472  _dbus_return_if_fail (_dbus_message_iter_check (real));
2473  _dbus_return_if_fail (value != NULL);
2474  _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
2475  (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
2476 #endif
2477 
2479  value, n_elements);
2480 }
2481 
2493 void
2495  DBusMessageIter *iter)
2496 {
2497  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2498 
2499  _dbus_return_if_fail (message != NULL);
2500  _dbus_return_if_fail (iter != NULL);
2501 
2502  _dbus_message_iter_init_common (message, real,
2503  DBUS_MESSAGE_ITER_TYPE_WRITER);
2504 
2505  /* We create the signature string and point iterators at it "on demand"
2506  * when a value is actually appended. That means that init() never fails
2507  * due to OOM.
2508  */
2510  _dbus_header_get_byte_order (&message->header),
2511  &message->body,
2512  _dbus_string_get_length (&message->body));
2513 }
2514 
2523 static dbus_bool_t
2524 _dbus_message_iter_open_signature (DBusMessageRealIter *real)
2525 {
2526  DBusString *str;
2527  const DBusString *current_sig;
2528  int current_sig_pos;
2529 
2530  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2531 
2532  if (real->u.writer.type_str != NULL)
2533  {
2534  _dbus_assert (real->sig_refcount > 0);
2535  real->sig_refcount += 1;
2536  return TRUE;
2537  }
2538 
2539  str = dbus_new (DBusString, 1);
2540  if (str == NULL)
2541  return FALSE;
2542 
2545  &current_sig, &current_sig_pos))
2546  current_sig = NULL;
2547 
2548  if (current_sig)
2549  {
2550  int current_len;
2551 
2552  current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
2553  current_sig_pos += 1; /* move on to sig data */
2554 
2555  if (!_dbus_string_init_preallocated (str, current_len + 4))
2556  {
2557  dbus_free (str);
2558  return FALSE;
2559  }
2560 
2561  if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
2562  str, 0))
2563  {
2564  _dbus_string_free (str);
2565  dbus_free (str);
2566  return FALSE;
2567  }
2568  }
2569  else
2570  {
2571  if (!_dbus_string_init_preallocated (str, 4))
2572  {
2573  dbus_free (str);
2574  return FALSE;
2575  }
2576  }
2577 
2578  real->sig_refcount = 1;
2579 
2581  str, _dbus_string_get_length (str));
2582  return TRUE;
2583 }
2584 
2594 static dbus_bool_t
2595 _dbus_message_iter_close_signature (DBusMessageRealIter *real)
2596 {
2597  DBusString *str;
2598  const char *v_STRING;
2599  dbus_bool_t retval;
2600 
2601  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2602  _dbus_assert (real->u.writer.type_str != NULL);
2603  _dbus_assert (real->sig_refcount > 0);
2604 
2605  real->sig_refcount -= 1;
2606 
2607  if (real->sig_refcount > 0)
2608  return TRUE;
2609  _dbus_assert (real->sig_refcount == 0);
2610 
2611  retval = TRUE;
2612 
2613  str = real->u.writer.type_str;
2614 
2615  v_STRING = _dbus_string_get_const_data (str);
2619  &v_STRING))
2620  retval = FALSE;
2621 
2623  _dbus_string_free (str);
2624  dbus_free (str);
2625 
2626  return retval;
2627 }
2628 
2636 static void
2637 _dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
2638 {
2639  DBusString *str;
2640 
2641  _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2642  _dbus_assert (real->u.writer.type_str != NULL);
2643  _dbus_assert (real->sig_refcount > 0);
2644 
2645  real->sig_refcount -= 1;
2646 
2647  if (real->sig_refcount > 0)
2648  return;
2649  _dbus_assert (real->sig_refcount == 0);
2650 
2651  str = real->u.writer.type_str;
2652 
2654  _dbus_string_free (str);
2655  dbus_free (str);
2656 }
2657 
2658 #ifndef DBUS_DISABLE_CHECKS
2659 static dbus_bool_t
2660 _dbus_message_iter_append_check (DBusMessageRealIter *iter)
2661 {
2662  if (!_dbus_message_iter_check (iter))
2663  return FALSE;
2664 
2665  if (iter->message->locked)
2666  {
2667  _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)\n");
2668  return FALSE;
2669  }
2670 
2671  return TRUE;
2672 }
2673 #endif /* DBUS_DISABLE_CHECKS */
2674 
2675 #ifdef HAVE_UNIX_FD_PASSING
2676 static int *
2677 expand_fd_array(DBusMessage *m,
2678  unsigned n)
2679 {
2680  _dbus_assert(m);
2681 
2682  /* This makes space for adding n new fds to the array and returns a
2683  pointer to the place were the first fd should be put. */
2684 
2685  if (m->n_unix_fds + n > m->n_unix_fds_allocated)
2686  {
2687  unsigned k;
2688  int *p;
2689 
2690  /* Make twice as much space as necessary */
2691  k = (m->n_unix_fds + n) * 2;
2692 
2693  /* Allocate at least four */
2694  if (k < 4)
2695  k = 4;
2696 
2697  p = dbus_realloc(m->unix_fds, k * sizeof(int));
2698  if (p == NULL)
2699  return NULL;
2700 
2701  m->unix_fds = p;
2702  m->n_unix_fds_allocated = k;
2703  }
2704 
2705  return m->unix_fds + m->n_unix_fds;
2706 }
2707 #endif
2708 
2730  int type,
2731  const void *value)
2732 {
2733  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2734  dbus_bool_t ret;
2735 
2736  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2737  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2738  _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
2739  _dbus_return_val_if_fail (value != NULL, FALSE);
2740 
2741 #ifndef DBUS_DISABLE_CHECKS
2742  switch (type)
2743  {
2744  const char * const *string_p;
2745  const dbus_bool_t *bool_p;
2746 
2747  case DBUS_TYPE_STRING:
2748  string_p = value;
2749  _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
2750  break;
2751 
2752  case DBUS_TYPE_OBJECT_PATH:
2753  string_p = value;
2754  _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
2755  break;
2756 
2757  case DBUS_TYPE_SIGNATURE:
2758  string_p = value;
2759  _dbus_return_val_if_fail (_dbus_check_is_valid_signature (*string_p), FALSE);
2760  break;
2761 
2762  case DBUS_TYPE_BOOLEAN:
2763  bool_p = value;
2764  _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
2765  break;
2766 
2767  default:
2768  {
2769  /* nothing to check, all possible values are allowed */
2770  }
2771  }
2772 #endif
2773 
2774  if (!_dbus_message_iter_open_signature (real))
2775  return FALSE;
2776 
2777  if (type == DBUS_TYPE_UNIX_FD)
2778  {
2779 #ifdef HAVE_UNIX_FD_PASSING
2780  int *fds;
2781  dbus_uint32_t u;
2782 
2783  /* First step, include the fd in the fd list of this message */
2784  if (!(fds = expand_fd_array(real->message, 1)))
2785  return FALSE;
2786 
2787  *fds = _dbus_dup(*(int*) value, NULL);
2788  if (*fds < 0)
2789  return FALSE;
2790 
2791  u = real->message->n_unix_fds;
2792 
2793  /* Second step, write the index to the fd */
2794  if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
2795  _dbus_close(*fds, NULL);
2796  return FALSE;
2797  }
2798 
2799  real->message->n_unix_fds += 1;
2800  u += 1;
2801 
2802  /* Final step, update the header accordingly */
2806  &u);
2807 
2808  /* If any of these operations fail the message is
2809  hosed. However, no memory or fds should be leaked since what
2810  has been added to message has been added to the message, and
2811  can hence be accounted for when the message is being
2812  freed. */
2813 #else
2814  ret = FALSE;
2815 #endif
2816  }
2817  else
2818  {
2819  ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
2820  }
2821 
2822  if (!_dbus_message_iter_close_signature (real))
2823  ret = FALSE;
2824 
2825  return ret;
2826 }
2827 
2865  int element_type,
2866  const void *value,
2867  int n_elements)
2868 {
2869  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2870  dbus_bool_t ret;
2871 
2872  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2873  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2874  _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
2875  _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
2876  _dbus_return_val_if_fail (value != NULL, FALSE);
2877  _dbus_return_val_if_fail (n_elements >= 0, FALSE);
2878  _dbus_return_val_if_fail (n_elements <=
2880  FALSE);
2881 
2882 #ifndef DBUS_DISABLE_CHECKS
2883  if (element_type == DBUS_TYPE_BOOLEAN)
2884  {
2885  const dbus_bool_t * const *bools = value;
2886  int i;
2887 
2888  for (i = 0; i < n_elements; i++)
2889  {
2890  _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
2891  }
2892  }
2893 #endif
2894 
2895  ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
2896 
2897  return ret;
2898 }
2899 
2923  int type,
2924  const char *contained_signature,
2925  DBusMessageIter *sub)
2926 {
2927  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2928  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2929  DBusString contained_str;
2930 
2931  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2932  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2933  _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
2934  _dbus_return_val_if_fail (sub != NULL, FALSE);
2935  _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
2936  contained_signature == NULL) ||
2937  (type == DBUS_TYPE_DICT_ENTRY &&
2938  contained_signature == NULL) ||
2939  (type == DBUS_TYPE_VARIANT &&
2940  contained_signature != NULL) ||
2941  (type == DBUS_TYPE_ARRAY &&
2942  contained_signature != NULL), FALSE);
2943 
2944  /* this would fail if the contained_signature is a dict entry, since
2945  * dict entries are invalid signatures standalone (they must be in
2946  * an array)
2947  */
2948  _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
2949  (contained_signature == NULL ||
2950  _dbus_check_is_valid_signature (contained_signature)),
2951  FALSE);
2952 
2953  if (!_dbus_message_iter_open_signature (real))
2954  return FALSE;
2955 
2956  *real_sub = *real;
2957 
2958  if (contained_signature != NULL)
2959  {
2960  _dbus_string_init_const (&contained_str, contained_signature);
2961 
2962  return _dbus_type_writer_recurse (&real->u.writer,
2963  type,
2964  &contained_str, 0,
2965  &real_sub->u.writer);
2966  }
2967  else
2968  {
2969  return _dbus_type_writer_recurse (&real->u.writer,
2970  type,
2971  NULL, 0,
2972  &real_sub->u.writer);
2973  }
2974 }
2975 
2976 
2992  DBusMessageIter *sub)
2993 {
2994  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
2995  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2996  dbus_bool_t ret;
2997 
2998  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2999  _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3000  _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
3001  _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3002 
3003  ret = _dbus_type_writer_unrecurse (&real->u.writer,
3004  &real_sub->u.writer);
3005 
3006  if (!_dbus_message_iter_close_signature (real))
3007  ret = FALSE;
3008 
3009  return ret;
3010 }
3011 
3023 void
3025  DBusMessageIter *sub)
3026 {
3027  DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
3028 #ifndef DBUS_DISABLE_CHECKS
3029  DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3030 
3031  _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3032  _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3033  _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3034  _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3035 #endif
3036 
3037  _dbus_message_iter_abandon_signature (real);
3038 }
3039 
3056 void
3058  dbus_bool_t no_reply)
3059 {
3060  _dbus_return_if_fail (message != NULL);
3061  _dbus_return_if_fail (!message->locked);
3062 
3063  _dbus_header_toggle_flag (&message->header,
3065  no_reply);
3066 }
3067 
3077 {
3078  _dbus_return_val_if_fail (message != NULL, FALSE);
3079 
3080  return _dbus_header_get_flag (&message->header,
3082 }
3083 
3098 void
3100  dbus_bool_t auto_start)
3101 {
3102  _dbus_return_if_fail (message != NULL);
3103  _dbus_return_if_fail (!message->locked);
3104 
3105  _dbus_header_toggle_flag (&message->header,
3107  !auto_start);
3108 }
3109 
3119 {
3120  _dbus_return_val_if_fail (message != NULL, FALSE);
3121 
3122  return !_dbus_header_get_flag (&message->header,
3124 }
3125 
3126 
3141  const char *object_path)
3142 {
3143  _dbus_return_val_if_fail (message != NULL, FALSE);
3144  _dbus_return_val_if_fail (!message->locked, FALSE);
3145  _dbus_return_val_if_fail (object_path == NULL ||
3146  _dbus_check_is_valid_path (object_path),
3147  FALSE);
3148 
3149  return set_or_delete_string_field (message,
3152  object_path);
3153 }
3154 
3168 const char*
3170 {
3171  const char *v;
3172 
3173  _dbus_return_val_if_fail (message != NULL, NULL);
3174 
3175  v = NULL; /* in case field doesn't exist */
3179  (void *) &v);
3180  return v;
3181 }
3182 
3194  const char *path)
3195 {
3196  const char *msg_path;
3197  msg_path = dbus_message_get_path (message);
3198 
3199  if (msg_path == NULL)
3200  {
3201  if (path == NULL)
3202  return TRUE;
3203  else
3204  return FALSE;
3205  }
3206 
3207  if (path == NULL)
3208  return FALSE;
3209 
3210  if (strcmp (msg_path, path) == 0)
3211  return TRUE;
3212 
3213  return FALSE;
3214 }
3215 
3238  char ***path)
3239 {
3240  const char *v;
3241 
3242  _dbus_return_val_if_fail (message != NULL, FALSE);
3243  _dbus_return_val_if_fail (path != NULL, FALSE);
3244 
3245  *path = NULL;
3246 
3247  v = dbus_message_get_path (message);
3248  if (v != NULL)
3249  {
3250  if (!_dbus_decompose_path (v, strlen (v),
3251  path, NULL))
3252  return FALSE;
3253  }
3254  return TRUE;
3255 }
3256 
3272  const char *iface)
3273 {
3274  _dbus_return_val_if_fail (message != NULL, FALSE);
3275  _dbus_return_val_if_fail (!message->locked, FALSE);
3276  _dbus_return_val_if_fail (iface == NULL ||
3277  _dbus_check_is_valid_interface (iface),
3278  FALSE);
3279 
3280  return set_or_delete_string_field (message,
3283  iface);
3284 }
3285 
3299 const char*
3301 {
3302  const char *v;
3303 
3304  _dbus_return_val_if_fail (message != NULL, NULL);
3305 
3306  v = NULL; /* in case field doesn't exist */
3310  (void *) &v);
3311  return v;
3312 }
3313 
3323  const char *iface)
3324 {
3325  const char *msg_interface;
3326  msg_interface = dbus_message_get_interface (message);
3327 
3328  if (msg_interface == NULL)
3329  {
3330  if (iface == NULL)
3331  return TRUE;
3332  else
3333  return FALSE;
3334  }
3335 
3336  if (iface == NULL)
3337  return FALSE;
3338 
3339  if (strcmp (msg_interface, iface) == 0)
3340  return TRUE;
3341 
3342  return FALSE;
3343 
3344 }
3345 
3360  const char *member)
3361 {
3362  _dbus_return_val_if_fail (message != NULL, FALSE);
3363  _dbus_return_val_if_fail (!message->locked, FALSE);
3364  _dbus_return_val_if_fail (member == NULL ||
3365  _dbus_check_is_valid_member (member),
3366  FALSE);
3367 
3368  return set_or_delete_string_field (message,
3371  member);
3372 }
3373 
3385 const char*
3387 {
3388  const char *v;
3389 
3390  _dbus_return_val_if_fail (message != NULL, NULL);
3391 
3392  v = NULL; /* in case field doesn't exist */
3396  (void *) &v);
3397  return v;
3398 }
3399 
3409  const char *member)
3410 {
3411  const char *msg_member;
3412  msg_member = dbus_message_get_member (message);
3413 
3414  if (msg_member == NULL)
3415  {
3416  if (member == NULL)
3417  return TRUE;
3418  else
3419  return FALSE;
3420  }
3421 
3422  if (member == NULL)
3423  return FALSE;
3424 
3425  if (strcmp (msg_member, member) == 0)
3426  return TRUE;
3427 
3428  return FALSE;
3429 
3430 }
3431 
3445  const char *error_name)
3446 {
3447  _dbus_return_val_if_fail (message != NULL, FALSE);
3448  _dbus_return_val_if_fail (!message->locked, FALSE);
3449  _dbus_return_val_if_fail (error_name == NULL ||
3450  _dbus_check_is_valid_error_name (error_name),
3451  FALSE);
3452 
3453  return set_or_delete_string_field (message,
3456  error_name);
3457 }
3458 
3469 const char*
3471 {
3472  const char *v;
3473 
3474  _dbus_return_val_if_fail (message != NULL, NULL);
3475 
3476  v = NULL; /* in case field doesn't exist */
3480  (void *) &v);
3481  return v;
3482 }
3483 
3499  const char *destination)
3500 {
3501  _dbus_return_val_if_fail (message != NULL, FALSE);
3502  _dbus_return_val_if_fail (!message->locked, FALSE);
3503  _dbus_return_val_if_fail (destination == NULL ||
3504  _dbus_check_is_valid_bus_name (destination),
3505  FALSE);
3506 
3507  return set_or_delete_string_field (message,
3510  destination);
3511 }
3512 
3522 const char*
3524 {
3525  const char *v;
3526 
3527  _dbus_return_val_if_fail (message != NULL, NULL);
3528 
3529  v = NULL; /* in case field doesn't exist */
3533  (void *) &v);
3534  return v;
3535 }
3536 
3553  const char *sender)
3554 {
3555  _dbus_return_val_if_fail (message != NULL, FALSE);
3556  _dbus_return_val_if_fail (!message->locked, FALSE);
3557  _dbus_return_val_if_fail (sender == NULL ||
3558  _dbus_check_is_valid_bus_name (sender),
3559  FALSE);
3560 
3561  return set_or_delete_string_field (message,
3564  sender);
3565 }
3566 
3582 const char*
3584 {
3585  const char *v;
3586 
3587  _dbus_return_val_if_fail (message != NULL, NULL);
3588 
3589  v = NULL; /* in case field doesn't exist */
3593  (void *) &v);
3594  return v;
3595 }
3596 
3615 const char*
3617 {
3618  const DBusString *type_str;
3619  int type_pos;
3620 
3621  _dbus_return_val_if_fail (message != NULL, NULL);
3622 
3623  get_const_signature (&message->header, &type_str, &type_pos);
3624 
3625  return _dbus_string_get_const_data_len (type_str, type_pos, 0);
3626 }
3627 
3628 static dbus_bool_t
3629 _dbus_message_has_type_interface_member (DBusMessage *message,
3630  int type,
3631  const char *iface,
3632  const char *member)
3633 {
3634  const char *n;
3635 
3636  _dbus_assert (message != NULL);
3637  _dbus_assert (iface != NULL);
3638  _dbus_assert (member != NULL);
3639 
3640  if (dbus_message_get_type (message) != type)
3641  return FALSE;
3642 
3643  /* Optimize by checking the short member name first
3644  * instead of the longer interface name
3645  */
3646 
3647  n = dbus_message_get_member (message);
3648 
3649  if (n && strcmp (n, member) == 0)
3650  {
3651  n = dbus_message_get_interface (message);
3652 
3653  if (n == NULL || strcmp (n, iface) == 0)
3654  return TRUE;
3655  }
3656 
3657  return FALSE;
3658 }
3659 
3676  const char *iface,
3677  const char *method)
3678 {
3679  _dbus_return_val_if_fail (message != NULL, FALSE);
3680  _dbus_return_val_if_fail (iface != NULL, FALSE);
3681  _dbus_return_val_if_fail (method != NULL, FALSE);
3682  /* don't check that interface/method are valid since it would be
3683  * expensive, and not catch many common errors
3684  */
3685 
3686  return _dbus_message_has_type_interface_member (message,
3688  iface, method);
3689 }
3690 
3704  const char *iface,
3705  const char *signal_name)
3706 {
3707  _dbus_return_val_if_fail (message != NULL, FALSE);
3708  _dbus_return_val_if_fail (iface != NULL, FALSE);
3709  _dbus_return_val_if_fail (signal_name != NULL, FALSE);
3710  /* don't check that interface/name are valid since it would be
3711  * expensive, and not catch many common errors
3712  */
3713 
3714  return _dbus_message_has_type_interface_member (message,
3716  iface, signal_name);
3717 }
3718 
3731  const char *error_name)
3732 {
3733  const char *n;
3734 
3735  _dbus_return_val_if_fail (message != NULL, FALSE);
3736  _dbus_return_val_if_fail (error_name != NULL, FALSE);
3737  /* don't check that error_name is valid since it would be expensive,
3738  * and not catch many common errors
3739  */
3740 
3742  return FALSE;
3743 
3744  n = dbus_message_get_error_name (message);
3745 
3746  if (n && strcmp (n, error_name) == 0)
3747  return TRUE;
3748  else
3749  return FALSE;
3750 }
3751 
3764  const char *name)
3765 {
3766  const char *s;
3767 
3768  _dbus_return_val_if_fail (message != NULL, FALSE);
3769  _dbus_return_val_if_fail (name != NULL, FALSE);
3770  /* don't check that name is valid since it would be expensive, and
3771  * not catch many common errors
3772  */
3773 
3774  s = dbus_message_get_destination (message);
3775 
3776  if (s && strcmp (s, name) == 0)
3777  return TRUE;
3778  else
3779  return FALSE;
3780 }
3781 
3799  const char *name)
3800 {
3801  const char *s;
3802 
3803  _dbus_return_val_if_fail (message != NULL, FALSE);
3804  _dbus_return_val_if_fail (name != NULL, FALSE);
3805  /* don't check that name is valid since it would be expensive, and
3806  * not catch many common errors
3807  */
3808 
3809  s = dbus_message_get_sender (message);
3810 
3811  if (s && strcmp (s, name) == 0)
3812  return TRUE;
3813  else
3814  return FALSE;
3815 }
3816 
3828  const char *signature)
3829 {
3830  const char *s;
3831 
3832  _dbus_return_val_if_fail (message != NULL, FALSE);
3833  _dbus_return_val_if_fail (signature != NULL, FALSE);
3834  /* don't check that signature is valid since it would be expensive,
3835  * and not catch many common errors
3836  */
3837 
3838  s = dbus_message_get_signature (message);
3839 
3840  if (s && strcmp (s, signature) == 0)
3841  return TRUE;
3842  else
3843  return FALSE;
3844 }
3845 
3870  DBusMessage *message)
3871 {
3872  const char *str;
3873 
3874  _dbus_return_val_if_fail (message != NULL, FALSE);
3875  _dbus_return_val_if_error_is_set (error, FALSE);
3876 
3878  return FALSE;
3879 
3880  str = NULL;
3881  dbus_message_get_args (message, NULL,
3882  DBUS_TYPE_STRING, &str,
3884 
3885  dbus_set_error (error, dbus_message_get_error_name (message),
3886  str ? "%s" : NULL, str);
3887 
3888  return TRUE;
3889 }
3890 
3899 {
3900 #ifdef HAVE_UNIX_FD_PASSING
3901  _dbus_assert(message);
3902 
3903  return message->n_unix_fds > 0;
3904 #else
3905  return FALSE;
3906 #endif
3907 }
3908 
3927 #define INITIAL_LOADER_DATA_LEN 32
3928 
3937 {
3938  DBusMessageLoader *loader;
3939 
3940  loader = dbus_new0 (DBusMessageLoader, 1);
3941  if (loader == NULL)
3942  return NULL;
3943 
3944  loader->refcount = 1;
3945 
3946  loader->corrupted = FALSE;
3947  loader->corruption_reason = DBUS_VALID;
3948 
3949  /* this can be configured by the app, but defaults to the protocol max */
3951 
3952  /* We set a very relatively conservative default here since due to how
3953  SCM_RIGHTS works we need to preallocate an fd array of the maximum
3954  number of unix fds we want to receive in advance. A
3955  try-and-reallocate loop is not possible. */
3956  loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
3957 
3958  if (!_dbus_string_init (&loader->data))
3959  {
3960  dbus_free (loader);
3961  return NULL;
3962  }
3963 
3964  /* preallocate the buffer for speed, ignore failure */
3966  _dbus_string_set_length (&loader->data, 0);
3967 
3968 #ifdef HAVE_UNIX_FD_PASSING
3969  loader->unix_fds = NULL;
3970  loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
3971  loader->unix_fds_outstanding = FALSE;
3972 #endif
3973 
3974  return loader;
3975 }
3976 
3985 {
3986  loader->refcount += 1;
3987 
3988  return loader;
3989 }
3990 
3997 void
3999 {
4000  loader->refcount -= 1;
4001  if (loader->refcount == 0)
4002  {
4003 #ifdef HAVE_UNIX_FD_PASSING
4004  close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
4005  dbus_free(loader->unix_fds);
4006 #endif
4007  _dbus_list_foreach (&loader->messages,
4009  NULL);
4010  _dbus_list_clear (&loader->messages);
4011  _dbus_string_free (&loader->data);
4012  dbus_free (loader);
4013  }
4014 }
4015 
4034 void
4036  DBusString **buffer)
4037 {
4038  _dbus_assert (!loader->buffer_outstanding);
4039 
4040  *buffer = &loader->data;
4041 
4042  loader->buffer_outstanding = TRUE;
4043 }
4044 
4054 void
4056  DBusString *buffer)
4057 {
4058  _dbus_assert (loader->buffer_outstanding);
4059  _dbus_assert (buffer == &loader->data);
4060 
4061  loader->buffer_outstanding = FALSE;
4062 }
4063 
4076  int **fds,
4077  unsigned *max_n_fds)
4078 {
4079 #ifdef HAVE_UNIX_FD_PASSING
4080  _dbus_assert (!loader->unix_fds_outstanding);
4081 
4082  /* Allocate space where we can put the fds we read. We allocate
4083  space for max_message_unix_fds since this is an
4084  upper limit how many fds can be received within a single
4085  message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
4086  we are allocating the maximum possible array size right from the
4087  beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
4088  there is no better way. */
4089 
4090  if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
4091  {
4092  int *a = dbus_realloc(loader->unix_fds,
4093  loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
4094 
4095  if (!a)
4096  return FALSE;
4097 
4098  loader->unix_fds = a;
4099  loader->n_unix_fds_allocated = loader->max_message_unix_fds;
4100  }
4101 
4102  *fds = loader->unix_fds + loader->n_unix_fds;
4103  *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
4104 
4105  loader->unix_fds_outstanding = TRUE;
4106  return TRUE;
4107 #else
4108  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
4109  return FALSE;
4110 #endif
4111 }
4112 
4123 void
4125  int *fds,
4126  unsigned n_fds)
4127 {
4128 #ifdef HAVE_UNIX_FD_PASSING
4129  _dbus_assert(loader->unix_fds_outstanding);
4130  _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
4131  _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
4132 
4133  loader->n_unix_fds += n_fds;
4134  loader->unix_fds_outstanding = FALSE;
4135 
4136  if (n_fds && loader->unix_fds_change)
4137  loader->unix_fds_change (loader->unix_fds_change_data);
4138 #else
4139  _dbus_assert_not_reached("Platform doesn't support unix fd passing");
4140 #endif
4141 }
4142 
4143 /*
4144  * FIXME when we move the header out of the buffer, that memmoves all
4145  * buffered messages. Kind of crappy.
4146  *
4147  * Also we copy the header and body, which is kind of crappy. To
4148  * avoid this, we have to allow header and body to be in a single
4149  * memory block, which is good for messages we read and bad for
4150  * messages we are creating. But we could move_len() the buffer into
4151  * this single memory block, and move_len() will just swap the buffers
4152  * if you're moving the entire buffer replacing the dest string.
4153  *
4154  * We could also have the message loader tell the transport how many
4155  * bytes to read; so it would first ask for some arbitrary number like
4156  * 256, then if the message was incomplete it would use the
4157  * header/body len to ask for exactly the size of the message (or
4158  * blocks the size of a typical kernel buffer for the socket). That
4159  * way we don't get trailing bytes in the buffer that have to be
4160  * memmoved. Though I suppose we also don't have a chance of reading a
4161  * bunch of small messages at once, so the optimization may be stupid.
4162  *
4163  * Another approach would be to keep a "start" index into
4164  * loader->data and only delete it occasionally, instead of after
4165  * each message is loaded.
4166  *
4167  * load_message() returns FALSE if not enough memory OR the loader was corrupted
4168  */
4169 static dbus_bool_t
4170 load_message (DBusMessageLoader *loader,
4171  DBusMessage *message,
4172  int byte_order,
4173  int fields_array_len,
4174  int header_len,
4175  int body_len)
4176 {
4177  dbus_bool_t oom;
4178  DBusValidity validity;
4179  const DBusString *type_str;
4180  int type_pos;
4181  DBusValidationMode mode;
4182  dbus_uint32_t n_unix_fds = 0;
4183 
4184  mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
4185 
4186  oom = FALSE;
4187 
4188 #if 0
4189  _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
4190 #endif
4191 
4192  /* 1. VALIDATE AND COPY OVER HEADER */
4193  _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
4194  _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
4195 
4196  if (!_dbus_header_load (&message->header,
4197  mode,
4198  &validity,
4199  byte_order,
4200  fields_array_len,
4201  header_len,
4202  body_len,
4203  &loader->data, 0,
4204  _dbus_string_get_length (&loader->data)))
4205  {
4206  _dbus_verbose ("Failed to load header for new message code %d\n", validity);
4207 
4208  /* assert here so we can catch any code that still uses DBUS_VALID to indicate
4209  oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
4210  _dbus_assert (validity != DBUS_VALID);
4211 
4212  if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
4213  oom = TRUE;
4214  else
4215  {
4216  loader->corrupted = TRUE;
4217  loader->corruption_reason = validity;
4218  }
4219  goto failed;
4220  }
4221 
4222  _dbus_assert (validity == DBUS_VALID);
4223 
4224  /* 2. VALIDATE BODY */
4225  if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
4226  {
4227  get_const_signature (&message->header, &type_str, &type_pos);
4228 
4229  /* Because the bytes_remaining arg is NULL, this validates that the
4230  * body is the right length
4231  */
4232  validity = _dbus_validate_body_with_reason (type_str,
4233  type_pos,
4234  byte_order,
4235  NULL,
4236  &loader->data,
4237  header_len,
4238  body_len);
4239  if (validity != DBUS_VALID)
4240  {
4241  _dbus_verbose ("Failed to validate message body code %d\n", validity);
4242 
4243  loader->corrupted = TRUE;
4244  loader->corruption_reason = validity;
4245 
4246  goto failed;
4247  }
4248  }
4249 
4250  /* 3. COPY OVER UNIX FDS */
4254  &n_unix_fds);
4255 
4256 #ifdef HAVE_UNIX_FD_PASSING
4257 
4258  if (n_unix_fds > loader->n_unix_fds)
4259  {
4260  _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
4261  n_unix_fds, loader->n_unix_fds);
4262 
4263  loader->corrupted = TRUE;
4264  loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4265  goto failed;
4266  }
4267 
4268  /* If this was a recycled message there might still be
4269  some memory allocated for the fds */
4270  dbus_free(message->unix_fds);
4271 
4272  if (n_unix_fds > 0)
4273  {
4274  message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
4275  if (message->unix_fds == NULL)
4276  {
4277  _dbus_verbose ("Failed to allocate file descriptor array\n");
4278  oom = TRUE;
4279  goto failed;
4280  }
4281 
4282  message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
4283  loader->n_unix_fds -= n_unix_fds;
4284  memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
4285 
4286  if (loader->unix_fds_change)
4287  loader->unix_fds_change (loader->unix_fds_change_data);
4288  }
4289  else
4290  message->unix_fds = NULL;
4291 
4292 #else
4293 
4294  if (n_unix_fds > 0)
4295  {
4296  _dbus_verbose ("Hmm, message claims to come with file descriptors "
4297  "but that's not supported on our platform, disconnecting.\n");
4298 
4299  loader->corrupted = TRUE;
4300  loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4301  goto failed;
4302  }
4303 
4304 #endif
4305 
4306  /* 3. COPY OVER BODY AND QUEUE MESSAGE */
4307 
4308  if (!_dbus_list_append (&loader->messages, message))
4309  {
4310  _dbus_verbose ("Failed to append new message to loader queue\n");
4311  oom = TRUE;
4312  goto failed;
4313  }
4314 
4315  _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4316  _dbus_assert (_dbus_string_get_length (&loader->data) >=
4317  (header_len + body_len));
4318 
4319  if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
4320  {
4321  _dbus_verbose ("Failed to move body into new message\n");
4322  oom = TRUE;
4323  goto failed;
4324  }
4325 
4326  _dbus_string_delete (&loader->data, 0, header_len + body_len);
4327 
4328  /* don't waste more than 2k of memory */
4329  _dbus_string_compact (&loader->data, 2048);
4330 
4331  _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
4332  _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4333 
4334  _dbus_verbose ("Loaded message %p\n", message);
4335 
4336  _dbus_assert (!oom);
4337  _dbus_assert (!loader->corrupted);
4338  _dbus_assert (loader->messages != NULL);
4339  _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4340 
4341  return TRUE;
4342 
4343  failed:
4344 
4345  /* Clean up */
4346 
4347  /* does nothing if the message isn't in the list */
4348  _dbus_list_remove_last (&loader->messages, message);
4349 
4350  if (oom)
4351  _dbus_assert (!loader->corrupted);
4352  else
4353  _dbus_assert (loader->corrupted);
4354 
4355  _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
4356 
4357  return FALSE;
4358 }
4359 
4376 {
4377  while (!loader->corrupted &&
4378  _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
4379  {
4380  DBusValidity validity;
4381  int byte_order, fields_array_len, header_len, body_len;
4382 
4384  &validity,
4385  &byte_order,
4386  &fields_array_len,
4387  &header_len,
4388  &body_len,
4389  &loader->data, 0,
4390  _dbus_string_get_length (&loader->data)))
4391  {
4393 
4394  _dbus_assert (validity == DBUS_VALID);
4395 
4396  message = dbus_message_new_empty_header ();
4397  if (message == NULL)
4398  return FALSE;
4399 
4400  if (!load_message (loader, message,
4401  byte_order, fields_array_len,
4402  header_len, body_len))
4403  {
4404  dbus_message_unref (message);
4405  /* load_message() returns false if corrupted or OOM; if
4406  * corrupted then return TRUE for not OOM
4407  */
4408  return loader->corrupted;
4409  }
4410 
4411  _dbus_assert (loader->messages != NULL);
4412  _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4413  }
4414  else
4415  {
4416  _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
4417  validity);
4418  if (validity != DBUS_VALID)
4419  {
4420  loader->corrupted = TRUE;
4421  loader->corruption_reason = validity;
4422  }
4423  return TRUE;
4424  }
4425  }
4426 
4427  return TRUE;
4428 }
4429 
4437 DBusMessage*
4439 {
4440  if (loader->messages)
4441  return loader->messages->data;
4442  else
4443  return NULL;
4444 }
4445 
4454 DBusMessage*
4456 {
4457  return _dbus_list_pop_first (&loader->messages);
4458 }
4459 
4468 DBusList*
4470 {
4471  return _dbus_list_pop_first_link (&loader->messages);
4472 }
4473 
4480 void
4482  DBusList *link)
4483 {
4484  _dbus_list_prepend_link (&loader->messages, link);
4485 }
4486 
4498 {
4499  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4500  (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4501  return loader->corrupted;
4502 }
4503 
4512 {
4513  _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4514  (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4515 
4516  return loader->corruption_reason;
4517 }
4518 
4525 void
4527  long size)
4528 {
4529  if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
4530  {
4531  _dbus_verbose ("clamping requested max message size %ld to %d\n",
4534  }
4535  loader->max_message_size = size;
4536 }
4537 
4544 long
4546 {
4547  return loader->max_message_size;
4548 }
4549 
4556 void
4558  long n)
4559 {
4561  {
4562  _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
4565  }
4566  loader->max_message_unix_fds = n;
4567 }
4568 
4575 long
4577 {
4578  return loader->max_message_unix_fds;
4579 }
4580 
4586 int
4588 {
4589 #ifdef HAVE_UNIX_FD_PASSING
4590  return loader->n_unix_fds;
4591 #else
4592  return 0;
4593 #endif
4594 }
4595 
4604 void
4606  void (* callback) (void *),
4607  void *data)
4608 {
4609 #ifdef HAVE_UNIX_FD_PASSING
4610  loader->unix_fds_change = callback;
4611  loader->unix_fds_change_data = data;
4612 #endif
4613 }
4614 
4615 static DBusDataSlotAllocator slot_allocator =
4616  _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
4617 
4633 dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
4634 {
4635  return _dbus_data_slot_allocator_alloc (&slot_allocator,
4636  slot_p);
4637 }
4638 
4650 void
4651 dbus_message_free_data_slot (dbus_int32_t *slot_p)
4652 {
4653  _dbus_return_if_fail (*slot_p >= 0);
4654 
4655  _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
4656 }
4657 
4673  dbus_int32_t slot,
4674  void *data,
4675  DBusFreeFunction free_data_func)
4676 {
4677  DBusFreeFunction old_free_func;
4678  void *old_data;
4679  dbus_bool_t retval;
4680 
4681  _dbus_return_val_if_fail (message != NULL, FALSE);
4682  _dbus_return_val_if_fail (slot >= 0, FALSE);
4683 
4684  retval = _dbus_data_slot_list_set (&slot_allocator,
4685  &message->slot_list,
4686  slot, data, free_data_func,
4687  &old_free_func, &old_data);
4688 
4689  if (retval)
4690  {
4691  /* Do the actual free outside the message lock */
4692  if (old_free_func)
4693  (* old_free_func) (old_data);
4694  }
4695 
4696  return retval;
4697 }
4698 
4707 void*
4709  dbus_int32_t slot)
4710 {
4711  void *res;
4712 
4713  _dbus_return_val_if_fail (message != NULL, NULL);
4714 
4715  res = _dbus_data_slot_list_get (&slot_allocator,
4716  &message->slot_list,
4717  slot);
4718 
4719  return res;
4720 }
4721 
4735 int
4736 dbus_message_type_from_string (const char *type_str)
4737 {
4738  if (strcmp (type_str, "method_call") == 0)
4740  if (strcmp (type_str, "method_return") == 0)
4742  else if (strcmp (type_str, "signal") == 0)
4743  return DBUS_MESSAGE_TYPE_SIGNAL;
4744  else if (strcmp (type_str, "error") == 0)
4745  return DBUS_MESSAGE_TYPE_ERROR;
4746  else
4748 }
4749 
4763 const char *
4765 {
4766  switch (type)
4767  {
4769  return "method_call";
4771  return "method_return";
4773  return "signal";
4775  return "error";
4776  default:
4777  return "invalid";
4778  }
4779 }
4780 
4795  char **marshalled_data_p,
4796  int *len_p)
4797 {
4798  DBusString tmp;
4799  dbus_bool_t was_locked;
4800 
4801  _dbus_return_val_if_fail (msg != NULL, FALSE);
4802  _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
4803  _dbus_return_val_if_fail (len_p != NULL, FALSE);
4804 
4805  if (!_dbus_string_init (&tmp))
4806  return FALSE;
4807 
4808  /* Ensure the message is locked, to ensure the length header is filled in. */
4809  was_locked = msg->locked;
4810 
4811  if (!was_locked)
4812  dbus_message_lock (msg);
4813 
4814  if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
4815  goto fail;
4816 
4817  *len_p = _dbus_string_get_length (&tmp);
4818 
4819  if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
4820  goto fail;
4821 
4822  *len_p = _dbus_string_get_length (&tmp);
4823 
4824  if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
4825  goto fail;
4826 
4827  _dbus_string_free (&tmp);
4828 
4829  if (!was_locked)
4830  msg->locked = FALSE;
4831 
4832  return TRUE;
4833 
4834  fail:
4835  _dbus_string_free (&tmp);
4836 
4837  if (!was_locked)
4838  msg->locked = FALSE;
4839 
4840  return FALSE;
4841 }
4842 
4855 DBusMessage *
4856 dbus_message_demarshal (const char *str,
4857  int len,
4858  DBusError *error)
4859 {
4860  DBusMessageLoader *loader;
4861  DBusString *buffer;
4862  DBusMessage *msg;
4863 
4864  _dbus_return_val_if_fail (str != NULL, NULL);
4865 
4866  loader = _dbus_message_loader_new ();
4867 
4868  if (loader == NULL)
4869  return NULL;
4870 
4871  _dbus_message_loader_get_buffer (loader, &buffer);
4872 
4873  if (!_dbus_string_append_len (buffer, str, len))
4874  goto fail_oom;
4875 
4876  _dbus_message_loader_return_buffer (loader, buffer);
4877 
4879  goto fail_oom;
4880 
4882  goto fail_corrupt;
4883 
4884  msg = _dbus_message_loader_pop_message (loader);
4885 
4886  if (!msg)
4887  goto fail_oom;
4888 
4889  _dbus_message_loader_unref (loader);
4890  return msg;
4891 
4892  fail_corrupt:
4893  dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
4894  _dbus_validity_to_error_message (loader->corruption_reason));
4895  _dbus_message_loader_unref (loader);
4896  return NULL;
4897 
4898  fail_oom:
4899  _DBUS_SET_OOM (error);
4900  _dbus_message_loader_unref (loader);
4901  return NULL;
4902 }
4903 
4916 int
4918  int len)
4919 {
4920  DBusString str;
4921  int byte_order, fields_array_len, header_len, body_len;
4922  DBusValidity validity = DBUS_VALID;
4923  int have_message;
4924 
4925  if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
4926  return 0;
4927 
4928  if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
4930  _dbus_string_init_const_len (&str, buf, len);
4931 
4932  validity = DBUS_VALID;
4933  have_message
4935  &validity, &byte_order,
4936  &fields_array_len,
4937  &header_len,
4938  &body_len,
4939  &str, 0,
4940  len);
4941  _dbus_string_free (&str);
4942 
4943  if (validity == DBUS_VALID)
4944  {
4945  _dbus_assert (have_message || (header_len + body_len) > len);
4946  (void) have_message; /* unused unless asserting */
4947  return header_len + body_len;
4948  }
4949  else
4950  {
4951  return -1; /* broken! */
4952  }
4953 }
4954 
4976 void
4978  dbus_bool_t allow)
4979 {
4980  _dbus_return_if_fail (message != NULL);
4981  _dbus_return_if_fail (!message->locked);
4982 
4983  _dbus_header_toggle_flag (&message->header,
4985  allow);
4986 }
4987 
4996 {
4997  _dbus_return_val_if_fail (message != NULL, FALSE);
4998 
4999  return _dbus_header_get_flag (&message->header,
5001 }
5002 
5005 /* 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...