D-Bus 1.15.4
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 * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
8 *
9 * Licensed under the Academic Free License version 2.1
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 */
26
27#include <config.h>
28#include "dbus-internals.h"
29#include "dbus-marshal-recursive.h"
30#include "dbus-marshal-validate.h"
31#include "dbus-marshal-byteswap.h"
32#include "dbus-marshal-header.h"
33#include "dbus-signature.h"
34#include "dbus-message-private.h"
35#include "dbus-object-tree.h"
36#include "dbus-memory.h"
37#include "dbus-list.h"
38#include "dbus-threads-internal.h"
39#ifdef HAVE_UNIX_FD_PASSING
40#include "dbus-sysdeps.h"
41#include "dbus-sysdeps-unix.h"
42#endif
43
44#include <string.h>
45
46#define _DBUS_TYPE_IS_STRINGLIKE(type) \
47 (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \
48 type == DBUS_TYPE_OBJECT_PATH)
49
50static void dbus_message_finalize (DBusMessage *message);
51
62#ifdef DBUS_ENABLE_EMBEDDED_TESTS
63static dbus_bool_t
64_dbus_enable_message_cache (void)
65{
66 static int enabled = -1;
67
68 if (enabled < 0)
69 {
70 const char *s = _dbus_getenv ("DBUS_MESSAGE_CACHE");
71
72 enabled = TRUE;
73
74 if (s && *s)
75 {
76 if (*s == '0')
77 enabled = FALSE;
78 else if (*s == '1')
79 enabled = TRUE;
80 else
81 _dbus_warn ("DBUS_MESSAGE_CACHE should be 0 or 1 if set, not '%s'",
82 s);
83 }
84 }
85
86 return enabled;
87}
88#else
89 /* constant expression, should be optimized away */
90# define _dbus_enable_message_cache() (TRUE)
91#endif
92
93#ifndef _dbus_message_trace_ref
94void
95_dbus_message_trace_ref (DBusMessage *message,
96 int old_refcount,
97 int new_refcount,
98 const char *why)
99{
100 static int enabled = -1;
101
102 _dbus_trace_ref ("DBusMessage", message, old_refcount, new_refcount, why,
103 "DBUS_MESSAGE_TRACE", &enabled);
104}
105#endif
106
107/* Not thread locked, but strictly const/read-only so should be OK
108 */
110_DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, "");
111
112/* these have wacky values to help trap uninitialized iterators;
113 * but has to fit in 3 bits
114 */
115enum {
116 DBUS_MESSAGE_ITER_TYPE_READER = 3,
117 DBUS_MESSAGE_ITER_TYPE_WRITER = 7
118};
119
122
129{
134 union
135 {
138 } u;
139};
140
141#if DBUS_SIZEOF_VOID_P > 8
142/*
143 * Architectures with 128-bit pointers were not supported in DBus 1.10, so we
144 * do no check for DBus 1.10 structure layout compatibility for such
145 * architectures (e.g. Arm Morello).
146 */
147#define CHECK_DBUS_1_10_BINARY_COMPATIBILITY 0
148#else
149#define CHECK_DBUS_1_10_BINARY_COMPATIBILITY 1
155typedef struct
156{
157 void *dummy1;
158 void *dummy2;
159 dbus_uint32_t dummy3;
160 int dummy4;
161 int dummy5;
162 int dummy6;
163 int dummy7;
164 int dummy8;
165 int dummy9;
166 int dummy10;
167 int dummy11;
168 int pad1;
169 int pad2;
170 void *pad3;
172#endif
173
174static void
175get_const_signature (DBusHeader *header,
176 const DBusString **type_str_p,
177 int *type_pos_p)
178{
179 if (_dbus_header_get_field_raw (header,
181 type_str_p,
182 type_pos_p))
183 {
184 *type_pos_p += 1; /* skip the signature length which is 1 byte */
185 }
186 else
187 {
188 *type_str_p = &_dbus_empty_signature_str;
189 *type_pos_p = 0;
190 }
191}
192
198static void
199_dbus_message_byteswap (DBusMessage *message)
200{
201 const DBusString *type_str;
202 int type_pos;
203 char byte_order;
204
205 byte_order = _dbus_header_get_byte_order (&message->header);
206
207 if (byte_order == DBUS_COMPILER_BYTE_ORDER)
208 return;
209
210 _dbus_verbose ("Swapping message into compiler byte order\n");
211
212 get_const_signature (&message->header, &type_str, &type_pos);
213
214 _dbus_marshal_byteswap (type_str, type_pos,
215 byte_order,
216 DBUS_COMPILER_BYTE_ORDER,
217 &message->body, 0);
218
219 _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
221 DBUS_COMPILER_BYTE_ORDER);
222}
223
230#define ensure_byte_order(message) _dbus_message_byteswap (message)
231
242void
244 const DBusString **header,
245 const DBusString **body)
246{
247 _dbus_assert (message->locked);
248
249 *header = &message->header.data;
250 *body = &message->body;
251}
252
263 const int **fds,
264 unsigned *n_fds)
265{
266 _dbus_assert (message->locked);
267
268#ifdef HAVE_UNIX_FD_PASSING
269 *fds = message->unix_fds;
270 *n_fds = message->n_unix_fds;
271#else
272 *fds = NULL;
273 *n_fds = 0;
274#endif
275}
276
285{
287}
288
300void
302 dbus_uint32_t serial)
303{
304 _dbus_return_if_fail (message != NULL);
305 _dbus_return_if_fail (!message->locked);
306
307 _dbus_header_set_serial (&message->header, serial);
308}
309
326void
328 DBusList *link)
329{
330 /* right now we don't recompute the delta when message
331 * size changes, and that's OK for current purposes
332 * I think, but could be important to change later.
333 * Do recompute it whenever there are no outstanding counters,
334 * since it's basically free.
335 */
336 if (message->counters == NULL)
337 {
338 message->size_counter_delta =
340 _dbus_string_get_length (&message->body);
341
342#ifdef HAVE_UNIX_FD_PASSING
343 message->unix_fd_counter_delta = message->n_unix_fds;
344#endif
345
346#if 0
347 _dbus_verbose ("message has size %ld\n",
348 message->size_counter_delta);
349#endif
350 }
351
352 _dbus_list_append_link (&message->counters, link);
353
355
356#ifdef HAVE_UNIX_FD_PASSING
357 _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
358#endif
359}
360
377 DBusCounter *counter)
378{
379 DBusList *link;
380
381 link = _dbus_list_alloc_link (counter);
382 if (link == NULL)
383 return FALSE;
384
385 _dbus_counter_ref (counter);
386 _dbus_message_add_counter_link (message, link);
387
388 return TRUE;
389}
390
398void
400 DBusCounter *counter)
401{
402 DBusList *link;
403
404 link = _dbus_list_find_last (&message->counters,
405 counter);
406 _dbus_assert (link != NULL);
407
408 _dbus_list_remove_link (&message->counters, link);
409
410 _dbus_counter_adjust_size (counter, - message->size_counter_delta);
411
412#ifdef HAVE_UNIX_FD_PASSING
413 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
414#endif
415
416 _dbus_counter_notify (counter);
417 _dbus_counter_unref (counter);
418}
419
430void
432{
433 if (!message->locked)
434 {
436 _dbus_string_get_length (&message->body));
437
438 /* must have a signature if you have a body */
439 _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
440 dbus_message_get_signature (message) != NULL);
441
442 message->locked = TRUE;
443 }
444}
445
446static dbus_bool_t
447set_or_delete_string_field (DBusMessage *message,
448 int field,
449 int typecode,
450 const char *value)
451{
452 if (value == NULL)
453 return _dbus_header_delete_field (&message->header, field);
454 else
455 return _dbus_header_set_field_basic (&message->header,
456 field,
457 typecode,
458 &value);
459}
460
461/* Message Cache
462 *
463 * We cache some DBusMessage to reduce the overhead of allocating
464 * them. In my profiling this consistently made about an 8%
465 * difference. It avoids the malloc for the message, the malloc for
466 * the slot list, the malloc for the header string and body string,
467 * and the associated free() calls. It does introduce another global
468 * lock which could be a performance issue in certain cases.
469 *
470 * For the echo client/server the round trip time goes from around
471 * .000077 to .000069 with the message cache on my laptop. The sysprof
472 * change is as follows (numbers are cumulative percentage):
473 *
474 * with message cache implemented as array as it is now (0.000069 per):
475 * new_empty_header 1.46
476 * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache)
477 * mutex_unlock 0.25
478 * self 0.41
479 * unref 2.24
480 * self 0.68
481 * list_clear 0.43
482 * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache)
483 * mutex_unlock 0.25
484 *
485 * with message cache implemented as list (0.000070 per roundtrip):
486 * new_empty_header 2.72
487 * list_pop_first 1.88
488 * unref 3.3
489 * list_prepend 1.63
490 *
491 * without cache (0.000077 per roundtrip):
492 * new_empty_header 6.7
493 * string_init_preallocated 3.43
494 * dbus_malloc 2.43
495 * dbus_malloc0 2.59
496 *
497 * unref 4.02
498 * string_free 1.82
499 * dbus_free 1.63
500 * dbus_free 0.71
501 *
502 * If you implement the message_cache with a list, the primary reason
503 * it's slower is that you add another thread lock (on the DBusList
504 * mempool).
505 */
506
508#define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
509
511#define MAX_MESSAGE_CACHE_SIZE 5
512
513/* Protected by _DBUS_LOCK (message_cache) */
514static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
515static int message_cache_count = 0;
516static dbus_bool_t message_cache_shutdown_registered = FALSE;
517
518static void
519dbus_message_cache_shutdown (void *data)
520{
521 int i;
522
523 if (!_DBUS_LOCK (message_cache))
524 _dbus_assert_not_reached ("we would have initialized global locks "
525 "before registering a shutdown function");
526
527 i = 0;
528 while (i < MAX_MESSAGE_CACHE_SIZE)
529 {
530 if (message_cache[i])
531 dbus_message_finalize (message_cache[i]);
532
533 ++i;
534 }
535
536 message_cache_count = 0;
537 message_cache_shutdown_registered = FALSE;
538
539 _DBUS_UNLOCK (message_cache);
540}
541
549static DBusMessage*
550dbus_message_get_cached (void)
551{
552 DBusMessage *message;
553 int i;
554
555 message = NULL;
556
557 if (!_DBUS_LOCK (message_cache))
558 {
559 /* we'd have initialized global locks before caching anything,
560 * so there can't be anything in the cache */
561 return NULL;
562 }
563
564 _dbus_assert (message_cache_count >= 0);
565
566 if (message_cache_count == 0)
567 {
568 _DBUS_UNLOCK (message_cache);
569 return NULL;
570 }
571
572 /* This is not necessarily true unless count > 0, and
573 * message_cache is uninitialized until the shutdown is
574 * registered
575 */
576 _dbus_assert (message_cache_shutdown_registered);
577
578 i = 0;
579 while (i < MAX_MESSAGE_CACHE_SIZE)
580 {
581 if (message_cache[i])
582 {
583 message = message_cache[i];
584 message_cache[i] = NULL;
585 message_cache_count -= 1;
586 break;
587 }
588 ++i;
589 }
590 _dbus_assert (message_cache_count >= 0);
592 _dbus_assert (message != NULL);
593
594 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
595
596 _dbus_assert (message->counters == NULL);
597
598 _DBUS_UNLOCK (message_cache);
599
600 return message;
601}
602
603#ifdef HAVE_UNIX_FD_PASSING
604static void
605close_unix_fds(int *fds, unsigned *n_fds)
606{
607 DBusError e;
608 unsigned int i;
609
610 if (*n_fds <= 0)
611 return;
612
613 dbus_error_init(&e);
614
615 for (i = 0; i < *n_fds; i++)
616 {
617 if (!_dbus_close(fds[i], &e))
618 {
619 _dbus_warn("Failed to close file descriptor: %s", e.message);
620 dbus_error_free(&e);
621 }
622 }
623
624 *n_fds = 0;
625
626 /* We don't free the array here, in case we can recycle it later */
627}
628#endif
629
630static void
631free_counter (void *element,
632 void *data)
633{
634 DBusCounter *counter = element;
635 DBusMessage *message = data;
636
637 _dbus_counter_adjust_size (counter, - message->size_counter_delta);
638#ifdef HAVE_UNIX_FD_PASSING
639 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
640#endif
641
642 _dbus_counter_notify (counter);
643 _dbus_counter_unref (counter);
644}
645
651static void
652dbus_message_cache_or_finalize (DBusMessage *message)
653{
654 dbus_bool_t was_cached;
655 int i;
656
657 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
658
659 /* This calls application code and has to be done first thing
660 * without holding the lock
661 */
663
664 _dbus_list_foreach (&message->counters,
665 free_counter, message);
666 _dbus_list_clear (&message->counters);
667
668#ifdef HAVE_UNIX_FD_PASSING
669 close_unix_fds(message->unix_fds, &message->n_unix_fds);
670#endif
671
672 was_cached = FALSE;
673
674 if (!_DBUS_LOCK (message_cache))
675 {
676 /* The only way to get a non-null message goes through
677 * dbus_message_get_cached() which takes the lock. */
678 _dbus_assert_not_reached ("we would have initialized global locks "
679 "the first time we constructed a message");
680 }
681
682 if (!message_cache_shutdown_registered)
683 {
684 _dbus_assert (message_cache_count == 0);
685
686 if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
687 goto out;
688
689 i = 0;
690 while (i < MAX_MESSAGE_CACHE_SIZE)
691 {
692 message_cache[i] = NULL;
693 ++i;
694 }
695
696 message_cache_shutdown_registered = TRUE;
697 }
698
699 _dbus_assert (message_cache_count >= 0);
700
701 if (!_dbus_enable_message_cache ())
702 goto out;
703
704 if ((_dbus_string_get_length (&message->header.data) +
705 _dbus_string_get_length (&message->body)) >
707 goto out;
708
709 if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
710 goto out;
711
712 /* Find empty slot */
713 i = 0;
714 while (message_cache[i] != NULL)
715 ++i;
716
718
719 _dbus_assert (message_cache[i] == NULL);
720 message_cache[i] = message;
721 message_cache_count += 1;
722 was_cached = TRUE;
723#ifndef DBUS_DISABLE_CHECKS
724 message->in_cache = TRUE;
725#endif
726
727 out:
728 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
729
730 _DBUS_UNLOCK (message_cache);
731
732 if (!was_cached)
733 dbus_message_finalize (message);
734}
735
736/*
737 * Arrange for iter to be something that _dbus_message_iter_check() would
738 * reject as not a valid iterator.
739 */
740static void
741_dbus_message_real_iter_zero (DBusMessageRealIter *iter)
742{
743 _dbus_assert (iter != NULL);
744 _DBUS_ZERO (*iter);
745 /* NULL is not, strictly speaking, guaranteed to be all-bits-zero */
746 iter->message = NULL;
747}
748
754void
756{
757 _dbus_return_if_fail (iter != NULL);
758 _dbus_message_real_iter_zero ((DBusMessageRealIter *) iter);
759}
760
761static dbus_bool_t
762_dbus_message_real_iter_is_zeroed (DBusMessageRealIter *iter)
763{
764 return (iter != NULL && iter->message == NULL && iter->changed_stamp == 0 &&
765 iter->iter_type == 0 && iter->sig_refcount == 0);
766}
767
768#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
769static dbus_bool_t
770_dbus_message_iter_check (DBusMessageRealIter *iter)
771{
772 char byte_order;
773
774 if (iter == NULL)
775 {
776 _dbus_warn_check_failed ("dbus message iterator is NULL");
777 return FALSE;
778 }
779
780 if (iter->message == NULL || iter->iter_type == 0)
781 {
782 _dbus_warn_check_failed ("dbus message iterator has already been "
783 "closed, or is uninitialized or corrupt");
784 return FALSE;
785 }
786
787 byte_order = _dbus_header_get_byte_order (&iter->message->header);
788
789 if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
790 {
791 if (iter->u.reader.byte_order != byte_order)
792 {
793 _dbus_warn_check_failed ("dbus message changed byte order since iterator was created");
794 return FALSE;
795 }
796 /* because we swap the message into compiler order when you init an iter */
797 _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
798 }
799 else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
800 {
801 if (iter->u.writer.byte_order != byte_order)
802 {
803 _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created");
804 return FALSE;
805 }
806 /* because we swap the message into compiler order when you init an iter */
807 _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
808 }
809 else
810 {
811 _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted");
812 return FALSE;
813 }
814
815 if (iter->changed_stamp != iter->message->changed_stamp)
816 {
817 _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)");
818 return FALSE;
819 }
820
821 return TRUE;
822}
823#endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */
824
839 DBusError *error,
840 int first_arg_type,
841 va_list var_args)
842{
844 int spec_type, msg_type, i, j;
845 dbus_bool_t retval;
846 va_list copy_args;
847
848 _dbus_assert (_dbus_message_iter_check (real));
849
850 retval = FALSE;
851
852 spec_type = first_arg_type;
853 i = 0;
854
855 /* copy var_args first, then we can do another iteration over it to
856 * free memory and close unix fds if parse failed at some point.
857 */
858 va_copy (copy_args, var_args);
859
860 while (spec_type != DBUS_TYPE_INVALID)
861 {
862 msg_type = dbus_message_iter_get_arg_type (iter);
863
864 if (msg_type != spec_type)
865 {
867 "Argument %d is specified to be of type \"%s\", but "
868 "is actually of type \"%s\"\n", i,
869 _dbus_type_to_string (spec_type),
870 _dbus_type_to_string (msg_type));
871
872 goto out;
873 }
874
875 if (spec_type == DBUS_TYPE_UNIX_FD)
876 {
877#ifdef HAVE_UNIX_FD_PASSING
878 DBusBasicValue idx;
879 int *pfd, nfd;
880
881 pfd = va_arg (var_args, int*);
882 _dbus_assert(pfd);
883
885
886 if (idx.u32 >= real->message->n_unix_fds)
887 {
889 "Message refers to file descriptor at index %i,"
890 "but has only %i descriptors attached.\n",
891 idx.u32,
892 real->message->n_unix_fds);
893 goto out;
894 }
895
896 if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
897 goto out;
898
899 *pfd = nfd;
900#else
902 "Platform does not support file desciptor passing.\n");
903 goto out;
904#endif
905 }
906 else if (dbus_type_is_basic (spec_type))
907 {
908 void *ptr;
909
910 ptr = va_arg (var_args, void *);
911
912 _dbus_assert (ptr != NULL);
913
915 ptr);
916 }
917 else if (spec_type == DBUS_TYPE_ARRAY)
918 {
919 int element_type;
920 int spec_element_type;
921 const void **ptr;
922 int *n_elements_p;
923 DBusTypeReader array;
924
925 spec_element_type = va_arg (var_args, int);
926 element_type = _dbus_type_reader_get_element_type (&real->u.reader);
927
928 if (spec_element_type != element_type)
929 {
931 "Argument %d is specified to be an array of \"%s\", but "
932 "is actually an array of \"%s\"\n",
933 i,
934 _dbus_type_to_string (spec_element_type),
935 _dbus_type_to_string (element_type));
936
937 goto out;
938 }
939
940 if (dbus_type_is_fixed (spec_element_type) &&
941 element_type != DBUS_TYPE_UNIX_FD)
942 {
943 ptr = va_arg (var_args, const void **);
944 n_elements_p = va_arg (var_args, int*);
945
946 _dbus_assert (ptr != NULL);
947 _dbus_assert (n_elements_p != NULL);
948
949 _dbus_type_reader_recurse (&real->u.reader, &array);
950
951 _dbus_type_reader_read_fixed_multi (&array, ptr, n_elements_p);
952 }
953 else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
954 {
955 char ***str_array_p;
956 int n_elements;
957 char **str_array;
958
959 str_array_p = va_arg (var_args, char***);
960 n_elements_p = va_arg (var_args, int*);
961
962 _dbus_assert (str_array_p != NULL);
963 _dbus_assert (n_elements_p != NULL);
964
965 /* Count elements in the array */
966 _dbus_type_reader_recurse (&real->u.reader, &array);
967
968 n_elements = 0;
970 {
971 ++n_elements;
972 _dbus_type_reader_next (&array);
973 }
974
975 str_array = dbus_new0 (char*, n_elements + 1);
976 if (str_array == NULL)
977 {
978 _DBUS_SET_OOM (error);
979 goto out;
980 }
981
982 /* Now go through and dup each string */
983 _dbus_type_reader_recurse (&real->u.reader, &array);
984
985 j = 0;
986 while (j < n_elements)
987 {
988 const char *s;
990 (void *) &s);
991
992 str_array[j] = _dbus_strdup (s);
993 if (str_array[j] == NULL)
994 {
995 dbus_free_string_array (str_array);
996 _DBUS_SET_OOM (error);
997 goto out;
998 }
999
1000 ++j;
1001
1002 if (!_dbus_type_reader_next (&array))
1003 _dbus_assert (j == n_elements);
1004 }
1005
1007 _dbus_assert (j == n_elements);
1008 _dbus_assert (str_array[j] == NULL);
1009
1010 *str_array_p = str_array;
1011 *n_elements_p = n_elements;
1012 }
1013#ifndef DBUS_DISABLE_CHECKS
1014 else
1015 {
1016 _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now",
1017 _DBUS_FUNCTION_NAME);
1018 goto out;
1019 }
1020#endif
1021 }
1022#ifndef DBUS_DISABLE_CHECKS
1023 else
1024 {
1025 _dbus_warn ("you can only read arrays and basic types with %s for now",
1026 _DBUS_FUNCTION_NAME);
1027 goto out;
1028 }
1029#endif
1030
1031 /* how many arguments already handled */
1032 i++;
1033
1034 spec_type = va_arg (var_args, int);
1035 if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
1036 {
1038 "Message has only %d arguments, but more were expected", i);
1039 goto out;
1040 }
1041 }
1042
1043 retval = TRUE;
1044
1045 out:
1046 /* there may memory or unix fd leak in the above iteration if parse failed.
1047 * so we have another iteration over copy_args to free memory and close
1048 * unix fds.
1049 */
1050 if (!retval)
1051 {
1052 spec_type = first_arg_type;
1053 j = 0;
1054
1055 while (j < i)
1056 {
1057 if (spec_type == DBUS_TYPE_UNIX_FD)
1058 {
1059#ifdef HAVE_UNIX_FD_PASSING
1060 int *pfd;
1061
1062 pfd = va_arg (copy_args, int *);
1063 _dbus_assert(pfd);
1064 if (*pfd >= 0)
1065 {
1066 _dbus_close (*pfd, NULL);
1067 *pfd = -1;
1068 }
1069#endif
1070 }
1071 else if (dbus_type_is_basic (spec_type))
1072 {
1073 /* move the index forward */
1074 va_arg (copy_args, const void *);
1075 }
1076 else if (spec_type == DBUS_TYPE_ARRAY)
1077 {
1078 int spec_element_type;
1079
1080 spec_element_type = va_arg (copy_args, int);
1081 if (dbus_type_is_fixed (spec_element_type))
1082 {
1083 /* move the index forward */
1084 va_arg (copy_args, const void **);
1085 va_arg (copy_args, int *);
1086 }
1087 else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
1088 {
1089 char ***str_array_p;
1090
1091 str_array_p = va_arg (copy_args, char ***);
1092 /* move the index forward */
1093 va_arg (copy_args, int *);
1094 _dbus_assert (str_array_p != NULL);
1095 dbus_free_string_array (*str_array_p);
1096 *str_array_p = NULL;
1097 }
1098 }
1099
1100 spec_type = va_arg (copy_args, int);
1101 j++;
1102 }
1103 }
1104
1105 va_end (copy_args);
1106 return retval;
1107}
1108
1169{
1170 _dbus_return_val_if_fail (message != NULL, 0);
1171
1172 return _dbus_header_get_serial (&message->header);
1173}
1174
1185 dbus_uint32_t reply_serial)
1186{
1187 DBusBasicValue value;
1188
1189 _dbus_return_val_if_fail (message != NULL, FALSE);
1190 _dbus_return_val_if_fail (!message->locked, FALSE);
1191 _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
1192
1193 value.u32 = reply_serial;
1194
1195 return _dbus_header_set_field_basic (&message->header,
1198 &value);
1199}
1200
1209{
1210 dbus_uint32_t v_UINT32;
1211
1212 _dbus_return_val_if_fail (message != NULL, 0);
1213
1214 if (_dbus_header_get_field_basic (&message->header,
1217 &v_UINT32))
1218 return v_UINT32;
1219 else
1220 return 0;
1221}
1222
1223static void
1224dbus_message_finalize (DBusMessage *message)
1225{
1226 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1227
1228 /* This calls application callbacks! */
1230
1231 _dbus_list_foreach (&message->counters,
1232 free_counter, message);
1233 _dbus_list_clear (&message->counters);
1234
1235 _dbus_header_free (&message->header);
1236 _dbus_string_free (&message->body);
1237
1238#ifdef HAVE_UNIX_FD_PASSING
1239 close_unix_fds(message->unix_fds, &message->n_unix_fds);
1240 dbus_free(message->unix_fds);
1241#endif
1242
1243 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1244
1245 dbus_free (message);
1246}
1247
1248static DBusMessage*
1249dbus_message_new_empty_header (void)
1250{
1251 DBusMessage *message;
1252 dbus_bool_t from_cache;
1253
1254 message = dbus_message_get_cached ();
1255
1256 if (message != NULL)
1257 {
1258 from_cache = TRUE;
1259 }
1260 else
1261 {
1262 from_cache = FALSE;
1263 message = dbus_new0 (DBusMessage, 1);
1264 if (message == NULL)
1265 return NULL;
1266#ifndef DBUS_DISABLE_CHECKS
1268#endif
1269
1270#ifdef HAVE_UNIX_FD_PASSING
1271 message->unix_fds = NULL;
1272 message->n_unix_fds_allocated = 0;
1273#endif
1274 }
1275
1276 _dbus_atomic_inc (&message->refcount);
1277
1278 _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
1279
1280 message->locked = FALSE;
1281#ifndef DBUS_DISABLE_CHECKS
1282 message->in_cache = FALSE;
1283#endif
1284 message->counters = NULL;
1285 message->size_counter_delta = 0;
1286 message->changed_stamp = 0;
1287
1288#ifdef HAVE_UNIX_FD_PASSING
1289 message->n_unix_fds = 0;
1290 message->n_unix_fds_allocated = 0;
1291 message->unix_fd_counter_delta = 0;
1292#endif
1293
1294 if (!from_cache)
1296
1297 if (from_cache)
1298 {
1299 _dbus_header_reinit (&message->header);
1300 _dbus_string_set_length (&message->body, 0);
1301 }
1302 else
1303 {
1304 if (!_dbus_header_init (&message->header))
1305 {
1306 dbus_free (message);
1307 return NULL;
1308 }
1309
1310 if (!_dbus_string_init_preallocated (&message->body, 32))
1311 {
1312 _dbus_header_free (&message->header);
1313 dbus_free (message);
1314 return NULL;
1315 }
1316 }
1317
1318 return message;
1319}
1320
1334dbus_message_new (int message_type)
1335{
1336 DBusMessage *message;
1337
1338 _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
1339
1340 message = dbus_message_new_empty_header ();
1341 if (message == NULL)
1342 return NULL;
1343
1344 if (!_dbus_header_create (&message->header,
1345 DBUS_COMPILER_BYTE_ORDER,
1346 message_type,
1347 NULL, NULL, NULL, NULL, NULL))
1348 {
1349 dbus_message_unref (message);
1350 return NULL;
1351 }
1352
1353 return message;
1354}
1355
1378dbus_message_new_method_call (const char *destination,
1379 const char *path,
1380 const char *iface,
1381 const char *method)
1382{
1383 DBusMessage *message;
1384
1385 _dbus_return_val_if_fail (path != NULL, NULL);
1386 _dbus_return_val_if_fail (method != NULL, NULL);
1387 _dbus_return_val_if_fail (destination == NULL ||
1388 _dbus_check_is_valid_bus_name (destination), NULL);
1389 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1390 _dbus_return_val_if_fail (iface == NULL ||
1391 _dbus_check_is_valid_interface (iface), NULL);
1392 _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
1393
1394 message = dbus_message_new_empty_header ();
1395 if (message == NULL)
1396 return NULL;
1397
1398 if (!_dbus_header_create (&message->header,
1399 DBUS_COMPILER_BYTE_ORDER,
1401 destination, path, iface, method, NULL))
1402 {
1403 dbus_message_unref (message);
1404 return NULL;
1405 }
1406
1407 return message;
1408}
1409
1419{
1420 DBusMessage *message;
1421 const char *sender;
1422
1423 _dbus_return_val_if_fail (method_call != NULL, NULL);
1424
1425 sender = dbus_message_get_sender (method_call);
1426
1427 /* sender is allowed to be null here in peer-to-peer case */
1428
1429 message = dbus_message_new_empty_header ();
1430 if (message == NULL)
1431 return NULL;
1432
1433 if (!_dbus_header_create (&message->header,
1434 DBUS_COMPILER_BYTE_ORDER,
1436 sender, NULL, NULL, NULL, NULL))
1437 {
1438 dbus_message_unref (message);
1439 return NULL;
1440 }
1441
1443
1444 if (!dbus_message_set_reply_serial (message,
1445 dbus_message_get_serial (method_call)))
1446 {
1447 dbus_message_unref (message);
1448 return NULL;
1449 }
1450
1451 return message;
1452}
1453
1469dbus_message_new_signal (const char *path,
1470 const char *iface,
1471 const char *name)
1472{
1473 DBusMessage *message;
1474
1475 _dbus_return_val_if_fail (path != NULL, NULL);
1476 _dbus_return_val_if_fail (iface != NULL, NULL);
1477 _dbus_return_val_if_fail (name != NULL, NULL);
1478 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1479 _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
1480 _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
1481
1482 message = dbus_message_new_empty_header ();
1483 if (message == NULL)
1484 return NULL;
1485
1486 if (!_dbus_header_create (&message->header,
1487 DBUS_COMPILER_BYTE_ORDER,
1489 NULL, path, iface, name, NULL))
1490 {
1491 dbus_message_unref (message);
1492 return NULL;
1493 }
1494
1496
1497 return message;
1498}
1499
1516 const char *error_name,
1517 const char *error_message)
1518{
1519 DBusMessage *message;
1520 const char *sender;
1521 DBusMessageIter iter;
1522
1523 _dbus_return_val_if_fail (reply_to != NULL, NULL);
1524 _dbus_return_val_if_fail (error_name != NULL, NULL);
1525 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1526
1527 sender = dbus_message_get_sender (reply_to);
1528
1529 /* sender may be NULL for non-message-bus case or
1530 * when the message bus is dealing with an unregistered
1531 * connection.
1532 */
1533 message = dbus_message_new_empty_header ();
1534 if (message == NULL)
1535 return NULL;
1536
1537 if (!_dbus_header_create (&message->header,
1538 DBUS_COMPILER_BYTE_ORDER,
1540 sender, NULL, NULL, NULL, error_name))
1541 {
1542 dbus_message_unref (message);
1543 return NULL;
1544 }
1545
1547
1548 if (!dbus_message_set_reply_serial (message,
1549 dbus_message_get_serial (reply_to)))
1550 {
1551 dbus_message_unref (message);
1552 return NULL;
1553 }
1554
1555 if (error_message != NULL)
1556 {
1557 dbus_message_iter_init_append (message, &iter);
1560 &error_message))
1561 {
1562 dbus_message_unref (message);
1563 return NULL;
1564 }
1565 }
1566
1567 return message;
1568}
1569
1588 const char *error_name,
1589 const char *error_format,
1590 ...)
1591{
1592 va_list args;
1593 DBusString str;
1594 DBusMessage *message;
1595
1596 _dbus_return_val_if_fail (reply_to != NULL, NULL);
1597 _dbus_return_val_if_fail (error_name != NULL, NULL);
1598 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1599
1600 if (!_dbus_string_init (&str))
1601 return NULL;
1602
1603 va_start (args, error_format);
1604
1605 if (_dbus_string_append_printf_valist (&str, error_format, args))
1606 message = dbus_message_new_error (reply_to, error_name,
1608 else
1609 message = NULL;
1610
1611 _dbus_string_free (&str);
1612
1613 va_end (args);
1614
1615 return message;
1616}
1617
1618
1633{
1634 DBusMessage *retval;
1635
1636 _dbus_return_val_if_fail (message != NULL, NULL);
1637
1638 retval = dbus_new0 (DBusMessage, 1);
1639 if (retval == NULL)
1640 return NULL;
1641
1642 _dbus_atomic_inc (&retval->refcount);
1643
1644 retval->locked = FALSE;
1645#ifndef DBUS_DISABLE_CHECKS
1646 retval->generation = message->generation;
1647#endif
1648
1649 if (!_dbus_header_copy (&message->header, &retval->header))
1650 {
1651 dbus_free (retval);
1652 return NULL;
1653 }
1654
1655 if (!_dbus_string_init_preallocated (&retval->body,
1656 _dbus_string_get_length (&message->body)))
1657 {
1658 _dbus_header_free (&retval->header);
1659 dbus_free (retval);
1660 return NULL;
1661 }
1662
1663 if (!_dbus_string_copy (&message->body, 0,
1664 &retval->body, 0))
1665 goto failed_copy;
1666
1667#ifdef HAVE_UNIX_FD_PASSING
1668 retval->unix_fds = dbus_new(int, message->n_unix_fds);
1669 if (retval->unix_fds == NULL && message->n_unix_fds > 0)
1670 goto failed_copy;
1671
1672 retval->n_unix_fds_allocated = message->n_unix_fds;
1673
1674 for (retval->n_unix_fds = 0;
1675 retval->n_unix_fds < message->n_unix_fds;
1676 retval->n_unix_fds++)
1677 {
1678 retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
1679
1680 if (retval->unix_fds[retval->n_unix_fds] < 0)
1681 goto failed_copy;
1682 }
1683
1684#endif
1685
1686 _dbus_message_trace_ref (retval, 0, 1, "copy");
1687 return retval;
1688
1689 failed_copy:
1690 _dbus_header_free (&retval->header);
1691 _dbus_string_free (&retval->body);
1692
1693#ifdef HAVE_UNIX_FD_PASSING
1694 close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
1695 dbus_free(retval->unix_fds);
1696#endif
1697
1698 dbus_free (retval);
1699
1700 return NULL;
1701}
1702
1703
1713{
1714 dbus_int32_t old_refcount;
1715
1716 _dbus_return_val_if_fail (message != NULL, NULL);
1717 _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
1718 _dbus_return_val_if_fail (!message->in_cache, NULL);
1719
1720 old_refcount = _dbus_atomic_inc (&message->refcount);
1721 _dbus_assert (old_refcount >= 1);
1722 _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
1723
1724 return message;
1725}
1726
1734void
1736{
1737 dbus_int32_t old_refcount;
1738
1739 _dbus_return_if_fail (message != NULL);
1740 _dbus_return_if_fail (message->generation == _dbus_current_generation);
1741 _dbus_return_if_fail (!message->in_cache);
1742
1743 old_refcount = _dbus_atomic_dec (&message->refcount);
1744
1745 _dbus_assert (old_refcount >= 1);
1746
1747 _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
1748
1749 if (old_refcount == 1)
1750 {
1751 /* Calls application callbacks! */
1752 dbus_message_cache_or_finalize (message);
1753 }
1754}
1755
1766int
1768{
1769 _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
1770
1771 return _dbus_header_get_message_type (&message->header);
1772}
1773
1844 int first_arg_type,
1845 ...)
1846{
1847 dbus_bool_t retval;
1848 va_list var_args;
1849
1850 _dbus_return_val_if_fail (message != NULL, FALSE);
1851
1852 va_start (var_args, first_arg_type);
1853 retval = dbus_message_append_args_valist (message,
1854 first_arg_type,
1855 var_args);
1856 va_end (var_args);
1857
1858 return retval;
1859}
1860
1876 int first_arg_type,
1877 va_list var_args)
1878{
1879 int type;
1880 DBusMessageIter iter;
1881
1882 _dbus_return_val_if_fail (message != NULL, FALSE);
1883
1884 type = first_arg_type;
1885
1886 dbus_message_iter_init_append (message, &iter);
1887
1888 while (type != DBUS_TYPE_INVALID)
1889 {
1890 if (dbus_type_is_basic (type))
1891 {
1892 const void *value;
1893 value = va_arg (var_args, const void *);
1894
1896 type,
1897 value))
1898 goto failed;
1899 }
1900 else if (type == DBUS_TYPE_ARRAY)
1901 {
1902 int element_type;
1903 DBusMessageIter array;
1904 char buf[2];
1905
1906 element_type = va_arg (var_args, int);
1907
1908 buf[0] = element_type;
1909 buf[1] = '\0';
1912 buf,
1913 &array))
1914 goto failed;
1915
1916 if (dbus_type_is_fixed (element_type) &&
1917 element_type != DBUS_TYPE_UNIX_FD)
1918 {
1919 const void **value;
1920 int n_elements;
1921
1922 value = va_arg (var_args, const void **);
1923 n_elements = va_arg (var_args, int);
1924
1926 element_type,
1927 value,
1928 n_elements)) {
1930 goto failed;
1931 }
1932 }
1933 else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
1934 {
1935 const char ***value_p;
1936 const char **value;
1937 int n_elements;
1938 int i;
1939
1940 value_p = va_arg (var_args, const char***);
1941 n_elements = va_arg (var_args, int);
1942
1943 value = *value_p;
1944
1945 i = 0;
1946 while (i < n_elements)
1947 {
1948 if (!dbus_message_iter_append_basic (&array,
1949 element_type,
1950 &value[i])) {
1952 goto failed;
1953 }
1954 ++i;
1955 }
1956 }
1957 else
1958 {
1959 _dbus_warn ("arrays of %s can't be appended with %s for now",
1960 _dbus_type_to_string (element_type),
1961 _DBUS_FUNCTION_NAME);
1963 goto failed;
1964 }
1965
1966 if (!dbus_message_iter_close_container (&iter, &array))
1967 goto failed;
1968 }
1969#ifndef DBUS_DISABLE_CHECKS
1970 else
1971 {
1972 _dbus_warn ("type %s isn't supported yet in %s",
1973 _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
1974 goto failed;
1975 }
1976#endif
1977
1978 type = va_arg (var_args, int);
1979 }
1980
1981 return TRUE;
1982
1983 failed:
1984 return FALSE;
1985}
1986
2033 DBusError *error,
2034 int first_arg_type,
2035 ...)
2036{
2037 dbus_bool_t retval;
2038 va_list var_args;
2039
2040 _dbus_return_val_if_fail (message != NULL, FALSE);
2041 _dbus_return_val_if_error_is_set (error, FALSE);
2042
2043 va_start (var_args, first_arg_type);
2044 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
2045 va_end (var_args);
2046
2047 return retval;
2048}
2049
2062 DBusError *error,
2063 int first_arg_type,
2064 va_list var_args)
2065{
2066 DBusMessageIter iter;
2067
2068 _dbus_return_val_if_fail (message != NULL, FALSE);
2069 _dbus_return_val_if_error_is_set (error, FALSE);
2070
2071 dbus_message_iter_init (message, &iter);
2072 return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
2073}
2074
2075static void
2076_dbus_message_iter_init_common (DBusMessage *message,
2077 DBusMessageRealIter *real,
2078 int iter_type)
2079{
2080 /* If these static assertions fail on your platform, report it as a bug. */
2081 _DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
2082 _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <=
2083 _DBUS_ALIGNOF (DBusMessageIter));
2084#if CHECK_DBUS_1_10_BINARY_COMPATIBILITY
2085 /* A failure of these two assertions would indicate that we've broken
2086 * ABI on this platform since 1.10.0. */
2087 _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) ==
2088 sizeof (DBusMessageIter));
2089 _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) ==
2090 _DBUS_ALIGNOF (DBusMessageIter));
2091#endif
2092 /* If this static assertion fails, it means the DBusMessageIter struct
2093 * is not "packed", which might result in "iter = other_iter" not copying
2094 * every byte. */
2095#if DBUS_SIZEOF_VOID_P > 8
2096 _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) == 16 * sizeof (void *));
2097#else
2098 _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) ==
2099 4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int));
2100#endif
2101
2102 /* Since the iterator will read or write who-knows-what from the
2103 * message, we need to get in the right byte order
2104 */
2105 ensure_byte_order (message);
2106
2107 real->message = message;
2108 real->changed_stamp = message->changed_stamp;
2109 real->iter_type = iter_type;
2110 real->sig_refcount = 0;
2111}
2112
2137 DBusMessageIter *iter)
2138{
2140 const DBusString *type_str;
2141 int type_pos;
2142
2143 _dbus_return_val_if_fail (message != NULL, FALSE);
2144 _dbus_return_val_if_fail (iter != NULL, FALSE);
2145
2146 get_const_signature (&message->header, &type_str, &type_pos);
2147
2148 _dbus_message_iter_init_common (message, real,
2149 DBUS_MESSAGE_ITER_TYPE_READER);
2150
2153 type_str, type_pos,
2154 &message->body,
2155 0);
2156
2158}
2159
2168{
2170
2171 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2172 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2173
2174 return _dbus_type_reader_has_next (&real->u.reader);
2175}
2176
2187{
2189
2190 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2191 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2192
2193 return _dbus_type_reader_next (&real->u.reader);
2194}
2195
2210int
2212{
2214
2215 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2216 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2217
2219}
2220
2229int
2231{
2233
2234 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2235 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
2236 _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
2237
2239}
2240
2266void
2268 DBusMessageIter *sub)
2269{
2271 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2272
2273 _dbus_return_if_fail (_dbus_message_iter_check (real));
2274 _dbus_return_if_fail (sub != NULL);
2275
2276 *real_sub = *real;
2277 _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
2278}
2279
2291char *
2293{
2294 const DBusString *sig;
2295 DBusString retstr;
2296 char *ret;
2297 int start, len;
2299
2300 _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
2301
2302 if (!_dbus_string_init (&retstr))
2303 return NULL;
2304
2306 &start, &len);
2307 if (!_dbus_string_append_len (&retstr,
2308 _dbus_string_get_const_data (sig) + start,
2309 len))
2310 return NULL;
2311 if (!_dbus_string_steal_data (&retstr, &ret))
2312 return NULL;
2313 _dbus_string_free (&retstr);
2314 return ret;
2315}
2316
2364void
2366 void *value)
2367{
2369
2370 _dbus_return_if_fail (_dbus_message_iter_check (real));
2371 _dbus_return_if_fail (value != NULL);
2372
2374 {
2375#ifdef HAVE_UNIX_FD_PASSING
2376 DBusBasicValue idx;
2377
2379
2380 if (idx.u32 >= real->message->n_unix_fds) {
2381 /* Hmm, we cannot really signal an error here, so let's make
2382 sure to return an invalid fd. */
2383 *((int*) value) = -1;
2384 return;
2385 }
2386
2387 *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
2388#else
2389 *((int*) value) = -1;
2390#endif
2391 }
2392 else
2393 {
2395 value);
2396 }
2397}
2398
2409int
2411{
2413 DBusTypeReader array;
2414 int element_type;
2415 int n_elements = 0;
2416
2417 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2418 _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
2419 == DBUS_TYPE_ARRAY, 0);
2420
2421 element_type = _dbus_type_reader_get_element_type (&real->u.reader);
2422 _dbus_type_reader_recurse (&real->u.reader, &array);
2423 if (dbus_type_is_fixed (element_type))
2424 {
2425 int alignment = _dbus_type_get_alignment (element_type);
2426 int total_len = _dbus_type_reader_get_array_length (&array);
2427 n_elements = total_len / alignment;
2428 }
2429 else
2430 {
2432 {
2433 ++n_elements;
2434 _dbus_type_reader_next (&array);
2435 }
2436 }
2437
2438 return n_elements;
2439}
2440
2453int
2455{
2457
2458 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2459
2461}
2462
2498void
2500 void *value,
2501 int *n_elements)
2502{
2504#ifndef DBUS_DISABLE_CHECKS
2505 int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
2506
2507 _dbus_return_if_fail (_dbus_message_iter_check (real));
2508 _dbus_return_if_fail (value != NULL);
2509 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
2510 (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
2511#endif
2512
2514 value, n_elements);
2515}
2516
2528void
2530 DBusMessageIter *iter)
2531{
2533
2534 _dbus_return_if_fail (message != NULL);
2535 _dbus_return_if_fail (iter != NULL);
2536
2537 _dbus_message_iter_init_common (message, real,
2538 DBUS_MESSAGE_ITER_TYPE_WRITER);
2539
2540 /* We create the signature string and point iterators at it "on demand"
2541 * when a value is actually appended. That means that init() never fails
2542 * due to OOM.
2543 */
2546 &message->body,
2547 _dbus_string_get_length (&message->body));
2548}
2549
2558static dbus_bool_t
2559_dbus_message_iter_open_signature (DBusMessageRealIter *real)
2560{
2561 DBusString *str;
2562 const DBusString *current_sig;
2563 int current_sig_pos;
2564
2565 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2566
2567 if (real->u.writer.type_str != NULL)
2568 {
2569 _dbus_assert (real->sig_refcount > 0);
2570 real->sig_refcount += 1;
2571 return TRUE;
2572 }
2573
2574 str = dbus_new (DBusString, 1);
2575 if (str == NULL)
2576 return FALSE;
2577
2580 &current_sig, &current_sig_pos))
2581 current_sig = NULL;
2582
2583 if (current_sig)
2584 {
2585 int current_len;
2586
2587 current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
2588 current_sig_pos += 1; /* move on to sig data */
2589
2590 if (!_dbus_string_init_preallocated (str, current_len + 4))
2591 {
2592 dbus_free (str);
2593 return FALSE;
2594 }
2595
2596 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
2597 str, 0))
2598 {
2599 _dbus_string_free (str);
2600 dbus_free (str);
2601 return FALSE;
2602 }
2603 }
2604 else
2605 {
2606 if (!_dbus_string_init_preallocated (str, 4))
2607 {
2608 dbus_free (str);
2609 return FALSE;
2610 }
2611 }
2612
2613 real->sig_refcount = 1;
2614
2615 /* If this assertion failed, then str would be neither stored in u.writer
2616 * nor freed by this function, resulting in a memory leak. */
2617 _dbus_assert (real->u.writer.type_str == NULL);
2619 str, _dbus_string_get_length (str));
2620 return TRUE;
2621}
2622
2632static dbus_bool_t
2633_dbus_message_iter_close_signature (DBusMessageRealIter *real)
2634{
2635 DBusString *str;
2636 const char *v_STRING;
2637 dbus_bool_t retval;
2638
2639 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2640 _dbus_assert (real->u.writer.type_str != NULL);
2641 _dbus_assert (real->sig_refcount > 0);
2642
2643 real->sig_refcount -= 1;
2644
2645 if (real->sig_refcount > 0)
2646 return TRUE;
2647 _dbus_assert (real->sig_refcount == 0);
2648
2649 retval = TRUE;
2650
2651 str = real->u.writer.type_str;
2652
2653 v_STRING = _dbus_string_get_const_data (str);
2657 &v_STRING))
2658 retval = FALSE;
2659
2661 _dbus_string_free (str);
2662 dbus_free (str);
2663
2664 return retval;
2665}
2666
2674static void
2675_dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
2676{
2677 DBusString *str;
2678
2679 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2680 _dbus_assert (real->u.writer.type_str != NULL);
2681 _dbus_assert (real->sig_refcount > 0);
2682
2683 real->sig_refcount -= 1;
2684
2685 if (real->sig_refcount > 0)
2686 return;
2687 _dbus_assert (real->sig_refcount == 0);
2688
2689 str = real->u.writer.type_str;
2690
2692 _dbus_string_free (str);
2693 dbus_free (str);
2694}
2695
2696#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
2697static dbus_bool_t
2698_dbus_message_iter_append_check (DBusMessageRealIter *iter)
2699{
2700 if (!_dbus_message_iter_check (iter))
2701 return FALSE;
2702
2703 if (iter->message->locked)
2704 {
2705 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)");
2706 return FALSE;
2707 }
2708
2709 return TRUE;
2710}
2711#endif
2712
2713#ifdef HAVE_UNIX_FD_PASSING
2714static int *
2715expand_fd_array(DBusMessage *m,
2716 unsigned n)
2717{
2718 _dbus_assert(m);
2719
2720 /* This makes space for adding n new fds to the array and returns a
2721 pointer to the place were the first fd should be put. */
2722
2723 if (m->n_unix_fds + n > m->n_unix_fds_allocated)
2724 {
2725 unsigned k;
2726 int *p;
2727
2728 /* Make twice as much space as necessary */
2729 k = (m->n_unix_fds + n) * 2;
2730
2731 /* Allocate at least four */
2732 if (k < 4)
2733 k = 4;
2734
2735 p = dbus_realloc(m->unix_fds, k * sizeof(int));
2736 if (p == NULL)
2737 return NULL;
2738
2739 m->unix_fds = p;
2740 m->n_unix_fds_allocated = k;
2741 }
2742
2743 return m->unix_fds + m->n_unix_fds;
2744}
2745#endif
2746
2768 int type,
2769 const void *value)
2770{
2772 dbus_bool_t ret;
2773
2774 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2775 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2776 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
2777 _dbus_return_val_if_fail (value != NULL, FALSE);
2778
2779#ifndef DBUS_DISABLE_CHECKS
2780 switch (type)
2781 {
2782 DBusString str;
2783 DBusValidity signature_validity;
2784 const char * const *string_p;
2785 const dbus_bool_t *bool_p;
2786
2787 case DBUS_TYPE_STRING:
2788 string_p = value;
2789 _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
2790 break;
2791
2793 string_p = value;
2794 _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
2795 break;
2796
2798 string_p = value;
2799 _dbus_string_init_const (&str, *string_p);
2800 signature_validity = _dbus_validate_signature_with_reason (&str,
2801 0,
2803
2804 if (signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
2805 return FALSE;
2806
2807 _dbus_return_val_if_fail (signature_validity == DBUS_VALID, FALSE);
2808 break;
2809
2810 case DBUS_TYPE_BOOLEAN:
2811 bool_p = value;
2812 _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
2813 break;
2814
2815 default:
2816 {
2817 /* nothing to check, all possible values are allowed */
2818 }
2819 }
2820#endif
2821
2822 if (!_dbus_message_iter_open_signature (real))
2823 return FALSE;
2824
2825 if (type == DBUS_TYPE_UNIX_FD)
2826 {
2827#ifdef HAVE_UNIX_FD_PASSING
2828 int *fds;
2829 dbus_uint32_t u;
2830
2831 ret = FALSE;
2832
2833 /* First step, include the fd in the fd list of this message */
2834 if (!(fds = expand_fd_array(real->message, 1)))
2835 goto out;
2836
2837 *fds = _dbus_dup(*(int*) value, NULL);
2838 if (*fds < 0)
2839 goto out;
2840
2841 u = real->message->n_unix_fds;
2842
2843 /* Second step, write the index to the fd */
2844 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
2845 _dbus_close(*fds, NULL);
2846 goto out;
2847 }
2848
2849 real->message->n_unix_fds += 1;
2850 u += 1;
2851
2852 /* Final step, update the header accordingly */
2856 &u);
2857
2858 /* If any of these operations fail the message is
2859 hosed. However, no memory or fds should be leaked since what
2860 has been added to message has been added to the message, and
2861 can hence be accounted for when the message is being
2862 freed. */
2863#else
2864 ret = FALSE;
2865 /* This is redundant (we could just fall through), but it avoids
2866 * -Wunused-label in builds that don't HAVE_UNIX_FD_PASSING */
2867 goto out;
2868#endif
2869 }
2870 else
2871 {
2872 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
2873 }
2874
2875out:
2876 if (!_dbus_message_iter_close_signature (real))
2877 ret = FALSE;
2878
2879 return ret;
2880}
2881
2919 int element_type,
2920 const void *value,
2921 int n_elements)
2922{
2924 dbus_bool_t ret;
2925
2926 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2927 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2928 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
2929 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
2930 _dbus_return_val_if_fail (value != NULL, FALSE);
2931 _dbus_return_val_if_fail (n_elements >= 0, FALSE);
2932 _dbus_return_val_if_fail (n_elements <=
2934 FALSE);
2935
2936#ifndef DBUS_DISABLE_CHECKS
2937 if (element_type == DBUS_TYPE_BOOLEAN)
2938 {
2939 const dbus_bool_t * const *bools = value;
2940 int i;
2941
2942 for (i = 0; i < n_elements; i++)
2943 {
2944 _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
2945 }
2946 }
2947#endif
2948
2949 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
2950
2951 return ret;
2952}
2953
2983 int type,
2984 const char *contained_signature,
2985 DBusMessageIter *sub)
2986{
2988 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2989 DBusString contained_str;
2990 DBusValidity contained_signature_validity;
2991 dbus_bool_t ret;
2992
2993 _dbus_return_val_if_fail (sub != NULL, FALSE);
2994 /* Do our best to make sure the sub-iterator doesn't contain something
2995 * valid-looking on failure */
2996 _dbus_message_real_iter_zero (real_sub);
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_type_is_container (type), FALSE);
3001 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
3002 contained_signature == NULL) ||
3003 (type == DBUS_TYPE_DICT_ENTRY &&
3004 contained_signature == NULL) ||
3005 (type == DBUS_TYPE_VARIANT &&
3006 contained_signature != NULL) ||
3007 (type == DBUS_TYPE_ARRAY &&
3008 contained_signature != NULL), FALSE);
3009
3010 /* this would fail if the contained_signature is a dict entry, since
3011 * dict entries are invalid signatures standalone (they must be in
3012 * an array)
3013 */
3014 if (contained_signature != NULL)
3015 {
3016 _dbus_string_init_const (&contained_str, contained_signature);
3017 contained_signature_validity = _dbus_validate_signature_with_reason (&contained_str,
3018 0,
3019 _dbus_string_get_length (&contained_str));
3020
3021 if (contained_signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
3022 return FALSE;
3023 }
3024 else
3025 {
3026 /* just some placeholder value */
3027 contained_signature_validity = DBUS_VALID_BUT_INCOMPLETE;
3028 }
3029
3030 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
3031 contained_signature == NULL ||
3032 contained_signature_validity == DBUS_VALID,
3033 FALSE);
3034
3035 if (!_dbus_message_iter_open_signature (real))
3036 return FALSE;
3037
3038 ret = FALSE;
3039 *real_sub = *real;
3040
3041 if (contained_signature != NULL)
3042 {
3043 _dbus_string_init_const (&contained_str, contained_signature);
3044
3045 ret = _dbus_type_writer_recurse (&real->u.writer,
3046 type,
3047 &contained_str, 0,
3048 &real_sub->u.writer);
3049 }
3050 else
3051 {
3052 ret = _dbus_type_writer_recurse (&real->u.writer,
3053 type,
3054 NULL, 0,
3055 &real_sub->u.writer);
3056 }
3057
3058 if (!ret)
3059 _dbus_message_iter_abandon_signature (real);
3060
3061 return ret;
3062}
3063
3064
3086 DBusMessageIter *sub)
3087{
3089 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3090 dbus_bool_t ret;
3091
3092 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
3093 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3094 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
3095 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3096
3097 ret = _dbus_type_writer_unrecurse (&real->u.writer,
3098 &real_sub->u.writer);
3099 _dbus_message_real_iter_zero (real_sub);
3100
3101 if (!_dbus_message_iter_close_signature (real))
3102 ret = FALSE;
3103
3104 return ret;
3105}
3106
3118void
3120 DBusMessageIter *sub)
3121{
3123 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3124
3125#ifndef DBUS_DISABLE_CHECKS
3126 _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3127 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3128 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3129 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3130#endif
3131
3132 _dbus_message_iter_abandon_signature (real);
3133 _dbus_message_real_iter_zero (real_sub);
3134}
3135
3177void
3179 DBusMessageIter *sub)
3180{
3182 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3183
3184 /* If both the parent and the child are zeroed out, then either we didn't
3185 * even get as far as successfully recursing into the parent, or we already
3186 * closed both the child and the parent. For example, in the code sample
3187 * in the doc-comment above, this happens for
3188 * abandon_container_if_open (&outer, &inner) if the first open_container
3189 * call failed, or if we reached result = TRUE and fell through. */
3190 if (_dbus_message_real_iter_is_zeroed (real) &&
3191 _dbus_message_real_iter_is_zeroed (real_sub))
3192 return;
3193
3194#ifndef DBUS_DISABLE_CHECKS
3195 /* If the child is not zeroed out, but the parent is, then something has
3196 * gone horribly wrong (in practice that would probably mean both are
3197 * uninitialized or corrupt, and the parent happens to have ended up
3198 * all-bytes-zero). */
3199 _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3200 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3201#endif
3202
3203 /* If the parent is not zeroed out, but the child is, then either we did
3204 * not successfully open the child, or we already closed the child. This
3205 * means we do not own a reference to the parent's signature, so it would
3206 * be wrong to release it; so we must not call abandon_signature() here.
3207 * In the code sample in the doc-comment above, this happens for
3208 * abandon_container_if_open (&outer, &inner) if the second open_container
3209 * call failed, or if the second close_container call failed. */
3210 if (_dbus_message_real_iter_is_zeroed (real_sub))
3211 return;
3212
3213#ifndef DBUS_DISABLE_CHECKS
3214 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3215 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3216#endif
3217
3218 /* If neither the parent nor the child is zeroed out, then we genuinely
3219 * have an open container; close it. In the code sample in the doc-comment,
3220 * this happens for abandon_container_if_open (&outer, &inner) if the
3221 * append_basic call failed. */
3222 _dbus_message_iter_abandon_signature (real);
3223 _dbus_message_real_iter_zero (real_sub);
3224}
3225
3242void
3244 dbus_bool_t no_reply)
3245{
3246 _dbus_return_if_fail (message != NULL);
3247 _dbus_return_if_fail (!message->locked);
3248
3251 no_reply);
3252}
3253
3263{
3264 _dbus_return_val_if_fail (message != NULL, FALSE);
3265
3266 return _dbus_header_get_flag (&message->header,
3268}
3269
3284void
3286 dbus_bool_t auto_start)
3287{
3288 _dbus_return_if_fail (message != NULL);
3289 _dbus_return_if_fail (!message->locked);
3290
3293 !auto_start);
3294}
3295
3305{
3306 _dbus_return_val_if_fail (message != NULL, FALSE);
3307
3308 return !_dbus_header_get_flag (&message->header,
3310}
3311
3312
3327 const char *object_path)
3328{
3329 _dbus_return_val_if_fail (message != NULL, FALSE);
3330 _dbus_return_val_if_fail (!message->locked, FALSE);
3331 _dbus_return_val_if_fail (object_path == NULL ||
3332 _dbus_check_is_valid_path (object_path),
3333 FALSE);
3334
3335 return set_or_delete_string_field (message,
3338 object_path);
3339}
3340
3354const char*
3356{
3357 const char *v;
3358
3359 _dbus_return_val_if_fail (message != NULL, NULL);
3360
3361 v = NULL; /* in case field doesn't exist */
3365 (void *) &v);
3366 return v;
3367}
3368
3380 const char *path)
3381{
3382 const char *msg_path;
3383 msg_path = dbus_message_get_path (message);
3384
3385 if (msg_path == NULL)
3386 {
3387 if (path == NULL)
3388 return TRUE;
3389 else
3390 return FALSE;
3391 }
3392
3393 if (path == NULL)
3394 return FALSE;
3395
3396 if (strcmp (msg_path, path) == 0)
3397 return TRUE;
3398
3399 return FALSE;
3400}
3401
3424 char ***path)
3425{
3426 const char *v;
3427
3428 _dbus_return_val_if_fail (message != NULL, FALSE);
3429 _dbus_return_val_if_fail (path != NULL, FALSE);
3430
3431 *path = NULL;
3432
3433 v = dbus_message_get_path (message);
3434 if (v != NULL)
3435 {
3436 if (!_dbus_decompose_path (v, strlen (v),
3437 path, NULL))
3438 return FALSE;
3439 }
3440 return TRUE;
3441}
3442
3458 const char *iface)
3459{
3460 _dbus_return_val_if_fail (message != NULL, FALSE);
3461 _dbus_return_val_if_fail (!message->locked, FALSE);
3462 _dbus_return_val_if_fail (iface == NULL ||
3463 _dbus_check_is_valid_interface (iface),
3464 FALSE);
3465
3466 return set_or_delete_string_field (message,
3469 iface);
3470}
3471
3485const char*
3487{
3488 const char *v;
3489
3490 _dbus_return_val_if_fail (message != NULL, NULL);
3491
3492 v = NULL; /* in case field doesn't exist */
3496 (void *) &v);
3497 return v;
3498}
3499
3509 const char *iface)
3510{
3511 const char *msg_interface;
3512 msg_interface = dbus_message_get_interface (message);
3513
3514 if (msg_interface == NULL)
3515 {
3516 if (iface == NULL)
3517 return TRUE;
3518 else
3519 return FALSE;
3520 }
3521
3522 if (iface == NULL)
3523 return FALSE;
3524
3525 if (strcmp (msg_interface, iface) == 0)
3526 return TRUE;
3527
3528 return FALSE;
3529
3530}
3531
3546 const char *member)
3547{
3548 _dbus_return_val_if_fail (message != NULL, FALSE);
3549 _dbus_return_val_if_fail (!message->locked, FALSE);
3550 _dbus_return_val_if_fail (member == NULL ||
3551 _dbus_check_is_valid_member (member),
3552 FALSE);
3553
3554 return set_or_delete_string_field (message,
3557 member);
3558}
3559
3571const char*
3573{
3574 const char *v;
3575
3576 _dbus_return_val_if_fail (message != NULL, NULL);
3577
3578 v = NULL; /* in case field doesn't exist */
3582 (void *) &v);
3583 return v;
3584}
3585
3595 const char *member)
3596{
3597 const char *msg_member;
3598 msg_member = dbus_message_get_member (message);
3599
3600 if (msg_member == NULL)
3601 {
3602 if (member == NULL)
3603 return TRUE;
3604 else
3605 return FALSE;
3606 }
3607
3608 if (member == NULL)
3609 return FALSE;
3610
3611 if (strcmp (msg_member, member) == 0)
3612 return TRUE;
3613
3614 return FALSE;
3615
3616}
3617
3631 const char *error_name)
3632{
3633 _dbus_return_val_if_fail (message != NULL, FALSE);
3634 _dbus_return_val_if_fail (!message->locked, FALSE);
3635 _dbus_return_val_if_fail (error_name == NULL ||
3636 _dbus_check_is_valid_error_name (error_name),
3637 FALSE);
3638
3639 return set_or_delete_string_field (message,
3642 error_name);
3643}
3644
3655const char*
3657{
3658 const char *v;
3659
3660 _dbus_return_val_if_fail (message != NULL, NULL);
3661
3662 v = NULL; /* in case field doesn't exist */
3666 (void *) &v);
3667 return v;
3668}
3669
3685 const char *destination)
3686{
3687 _dbus_return_val_if_fail (message != NULL, FALSE);
3688 _dbus_return_val_if_fail (!message->locked, FALSE);
3689 _dbus_return_val_if_fail (destination == NULL ||
3690 _dbus_check_is_valid_bus_name (destination),
3691 FALSE);
3692
3693 return set_or_delete_string_field (message,
3696 destination);
3697}
3698
3708const char*
3710{
3711 const char *v;
3712
3713 _dbus_return_val_if_fail (message != NULL, NULL);
3714
3715 v = NULL; /* in case field doesn't exist */
3719 (void *) &v);
3720 return v;
3721}
3722
3739 const char *sender)
3740{
3741 _dbus_return_val_if_fail (message != NULL, FALSE);
3742 _dbus_return_val_if_fail (!message->locked, FALSE);
3743 _dbus_return_val_if_fail (sender == NULL ||
3744 _dbus_check_is_valid_bus_name (sender),
3745 FALSE);
3746
3747 return set_or_delete_string_field (message,
3750 sender);
3751}
3752
3768const char*
3770{
3771 const char *v;
3772
3773 _dbus_return_val_if_fail (message != NULL, NULL);
3774
3775 v = NULL; /* in case field doesn't exist */
3779 (void *) &v);
3780 return v;
3781}
3782
3801const char*
3803{
3804 const DBusString *type_str;
3805 int type_pos;
3806
3807 _dbus_return_val_if_fail (message != NULL, NULL);
3808
3809 get_const_signature (&message->header, &type_str, &type_pos);
3810
3811 return _dbus_string_get_const_data_len (type_str, type_pos, 0);
3812}
3813
3814static dbus_bool_t
3815_dbus_message_has_type_interface_member (DBusMessage *message,
3816 int type,
3817 const char *iface,
3818 const char *member)
3819{
3820 const char *n;
3821
3822 _dbus_assert (message != NULL);
3823 _dbus_assert (iface != NULL);
3824 _dbus_assert (member != NULL);
3825
3826 if (dbus_message_get_type (message) != type)
3827 return FALSE;
3828
3829 /* Optimize by checking the short member name first
3830 * instead of the longer interface name
3831 */
3832
3833 n = dbus_message_get_member (message);
3834
3835 if (n && strcmp (n, member) == 0)
3836 {
3837 n = dbus_message_get_interface (message);
3838
3839 if (n == NULL || strcmp (n, iface) == 0)
3840 return TRUE;
3841 }
3842
3843 return FALSE;
3844}
3845
3862 const char *iface,
3863 const char *method)
3864{
3865 _dbus_return_val_if_fail (message != NULL, FALSE);
3866 _dbus_return_val_if_fail (iface != NULL, FALSE);
3867 _dbus_return_val_if_fail (method != NULL, FALSE);
3868 /* don't check that interface/method are valid since it would be
3869 * expensive, and not catch many common errors
3870 */
3871
3872 return _dbus_message_has_type_interface_member (message,
3874 iface, method);
3875}
3876
3890 const char *iface,
3891 const char *signal_name)
3892{
3893 _dbus_return_val_if_fail (message != NULL, FALSE);
3894 _dbus_return_val_if_fail (iface != NULL, FALSE);
3895 _dbus_return_val_if_fail (signal_name != NULL, FALSE);
3896 /* don't check that interface/name are valid since it would be
3897 * expensive, and not catch many common errors
3898 */
3899
3900 return _dbus_message_has_type_interface_member (message,
3902 iface, signal_name);
3903}
3904
3917 const char *error_name)
3918{
3919 const char *n;
3920
3921 _dbus_return_val_if_fail (message != NULL, FALSE);
3922 _dbus_return_val_if_fail (error_name != NULL, FALSE);
3923 /* don't check that error_name is valid since it would be expensive,
3924 * and not catch many common errors
3925 */
3926
3928 return FALSE;
3929
3930 n = dbus_message_get_error_name (message);
3931
3932 if (n && strcmp (n, error_name) == 0)
3933 return TRUE;
3934 else
3935 return FALSE;
3936}
3937
3950 const char *name)
3951{
3952 const char *s;
3953
3954 _dbus_return_val_if_fail (message != NULL, FALSE);
3955 _dbus_return_val_if_fail (name != NULL, FALSE);
3956 /* don't check that name is valid since it would be expensive, and
3957 * not catch many common errors
3958 */
3959
3960 s = dbus_message_get_destination (message);
3961
3962 if (s && strcmp (s, name) == 0)
3963 return TRUE;
3964 else
3965 return FALSE;
3966}
3967
3985 const char *name)
3986{
3987 const char *s;
3988
3989 _dbus_return_val_if_fail (message != NULL, FALSE);
3990 _dbus_return_val_if_fail (name != NULL, FALSE);
3991 /* don't check that name is valid since it would be expensive, and
3992 * not catch many common errors
3993 */
3994
3995 s = dbus_message_get_sender (message);
3996
3997 if (s && strcmp (s, name) == 0)
3998 return TRUE;
3999 else
4000 return FALSE;
4001}
4002
4014 const char *signature)
4015{
4016 const char *s;
4017
4018 _dbus_return_val_if_fail (message != NULL, FALSE);
4019 _dbus_return_val_if_fail (signature != NULL, FALSE);
4020 /* don't check that signature is valid since it would be expensive,
4021 * and not catch many common errors
4022 */
4023
4024 s = dbus_message_get_signature (message);
4025
4026 if (s && strcmp (s, signature) == 0)
4027 return TRUE;
4028 else
4029 return FALSE;
4030}
4031
4056 DBusMessage *message)
4057{
4058 const char *str;
4059
4060 _dbus_return_val_if_fail (message != NULL, FALSE);
4061 _dbus_return_val_if_error_is_set (error, FALSE);
4062
4064 return FALSE;
4065
4066 str = NULL;
4067 dbus_message_get_args (message, NULL,
4068 DBUS_TYPE_STRING, &str,
4070
4072 str ? "%s" : NULL, str);
4073
4074 return TRUE;
4075}
4076
4085{
4086#ifdef HAVE_UNIX_FD_PASSING
4087 _dbus_assert(message);
4088
4089 return message->n_unix_fds > 0;
4090#else
4091 return FALSE;
4092#endif
4093}
4094
4107 const char *object_path)
4108{
4109 _dbus_return_val_if_fail (message != NULL, FALSE);
4110 _dbus_return_val_if_fail (!message->locked, FALSE);
4111 _dbus_return_val_if_fail (object_path == NULL ||
4112 _dbus_check_is_valid_path (object_path),
4113 FALSE);
4114
4115 return set_or_delete_string_field (message,
4118 object_path);
4119}
4120
4131const char *
4133{
4134 const char *v;
4135
4136 _dbus_return_val_if_fail (message != NULL, NULL);
4137
4138 v = NULL; /* in case field doesn't exist */
4142 (void *) &v);
4143 return v;
4144}
4145
4164#define INITIAL_LOADER_DATA_LEN 32
4165
4174{
4175 DBusMessageLoader *loader;
4176
4177 loader = dbus_new0 (DBusMessageLoader, 1);
4178 if (loader == NULL)
4179 return NULL;
4180
4181 loader->refcount = 1;
4182
4183 loader->corrupted = FALSE;
4184 loader->corruption_reason = DBUS_VALID;
4185
4186 /* this can be configured by the app, but defaults to the protocol max */
4188
4189 /* We set a very relatively conservative default here since due to how
4190 SCM_RIGHTS works we need to preallocate an fd array of the maximum
4191 number of unix fds we want to receive in advance. A
4192 try-and-reallocate loop is not possible. */
4193 loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
4194
4195 if (!_dbus_string_init (&loader->data))
4196 {
4197 dbus_free (loader);
4198 return NULL;
4199 }
4200
4201 /* preallocate the buffer for speed, ignore failure */
4203 _dbus_string_set_length (&loader->data, 0);
4204
4205#ifdef HAVE_UNIX_FD_PASSING
4206 loader->unix_fds = NULL;
4207 loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
4208 loader->unix_fds_outstanding = FALSE;
4209#endif
4210
4211 return loader;
4212}
4213
4222{
4223 loader->refcount += 1;
4224
4225 return loader;
4226}
4227
4234void
4236{
4237 loader->refcount -= 1;
4238 if (loader->refcount == 0)
4239 {
4240#ifdef HAVE_UNIX_FD_PASSING
4241 close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
4242 dbus_free(loader->unix_fds);
4243#endif
4246 _dbus_string_free (&loader->data);
4247 dbus_free (loader);
4248 }
4249}
4250
4269void
4271 DBusString **buffer,
4272 int *max_to_read,
4273 dbus_bool_t *may_read_fds)
4274{
4276
4277 *buffer = &loader->data;
4278
4279 loader->buffer_outstanding = TRUE;
4280
4281 if (max_to_read != NULL)
4282 {
4283#ifdef HAVE_UNIX_FD_PASSING
4284 int offset = 0;
4285 int remain;
4286 int byte_order;
4287 int fields_array_len;
4288 int header_len;
4289 int body_len;
4290#endif
4291
4292 *max_to_read = DBUS_MAXIMUM_MESSAGE_LENGTH;
4293 *may_read_fds = TRUE;
4294
4295#ifdef HAVE_UNIX_FD_PASSING
4296 /* If we aren't holding onto any fds, we can read as much as we want
4297 * (fast path). */
4298 if (loader->n_unix_fds == 0)
4299 return;
4300
4301 /* Slow path: we have a message with some fds in it. We don't want
4302 * to start on the next message until this one is out of the way;
4303 * otherwise a legitimate sender can keep us processing messages
4304 * containing fds, until we disconnect it for having had fds pending
4305 * for too long, a limit that is in place to stop malicious senders
4306 * from setting up recursive fd-passing that takes up our quota and
4307 * will never go away. */
4308
4309 remain = _dbus_string_get_length (&loader->data);
4310
4311 while (remain > 0)
4312 {
4313 DBusValidity validity = DBUS_VALIDITY_UNKNOWN;
4314 int needed;
4315
4316 /* If 0 < remain < DBUS_MINIMUM_HEADER_SIZE, then we've had at
4317 * least the first byte of a message, but we don't know how
4318 * much more to read. Only read the rest of the
4319 * DBUS_MINIMUM_HEADER_SIZE for now; then we'll know. */
4320 if (remain < DBUS_MINIMUM_HEADER_SIZE)
4321 {
4322 *max_to_read = DBUS_MINIMUM_HEADER_SIZE - remain;
4323 *may_read_fds = FALSE;
4324 return;
4325 }
4326
4328 &validity,
4329 &byte_order,
4330 &fields_array_len,
4331 &header_len,
4332 &body_len,
4333 &loader->data,
4334 offset,
4335 remain))
4336 {
4337 /* If a message in the buffer is invalid, we're going to
4338 * disconnect the sender anyway, so reading an arbitrary amount
4339 * is fine. */
4340 if (validity != DBUS_VALID)
4341 return;
4342
4343 /* We have a partial message, with the
4344 * DBUS_MINIMUM_HEADER_SIZE-byte fixed part of the header (which
4345 * lets us work out how much more we need), but no more. Read
4346 * the rest of the message. */
4347 needed = header_len + body_len;
4348 _dbus_assert (needed > remain);
4349 *max_to_read = needed - remain;
4350 *may_read_fds = FALSE;
4351 return;
4352 }
4353
4354 /* Skip over entire messages until we have less than a message
4355 * remaining. */
4356 needed = header_len + body_len;
4358 _dbus_assert (remain >= needed);
4359 remain -= needed;
4360 offset += needed;
4361 }
4362#endif
4363 }
4364}
4365
4375void
4377 DBusString *buffer)
4378{
4380 _dbus_assert (buffer == &loader->data);
4381
4382 loader->buffer_outstanding = FALSE;
4383}
4384
4385#ifdef HAVE_UNIX_FD_PASSING
4397_dbus_message_loader_get_unix_fds(DBusMessageLoader *loader,
4398 int **fds,
4399 unsigned *max_n_fds)
4400{
4401 _dbus_assert (!loader->unix_fds_outstanding);
4402
4403 /* Allocate space where we can put the fds we read. We allocate
4404 space for max_message_unix_fds since this is an
4405 upper limit how many fds can be received within a single
4406 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
4407 we are allocating the maximum possible array size right from the
4408 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
4409 there is no better way. */
4410
4411 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
4412 {
4413 int *a = dbus_realloc(loader->unix_fds,
4414 loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
4415
4416 if (!a)
4417 return FALSE;
4418
4419 loader->unix_fds = a;
4420 loader->n_unix_fds_allocated = loader->max_message_unix_fds;
4421 }
4422
4423 *fds = loader->unix_fds + loader->n_unix_fds;
4424 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
4425
4426 loader->unix_fds_outstanding = TRUE;
4427 return TRUE;
4428}
4429
4440void
4441_dbus_message_loader_return_unix_fds(DBusMessageLoader *loader,
4442 int *fds,
4443 unsigned n_fds)
4444{
4445 _dbus_assert(loader->unix_fds_outstanding);
4446 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
4447 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
4448
4449 loader->n_unix_fds += n_fds;
4450 loader->unix_fds_outstanding = FALSE;
4451
4452 if (n_fds && loader->unix_fds_change)
4453 loader->unix_fds_change (loader->unix_fds_change_data);
4454}
4455#endif
4456
4457/*
4458 * FIXME when we move the header out of the buffer, that memmoves all
4459 * buffered messages. Kind of crappy.
4460 *
4461 * Also we copy the header and body, which is kind of crappy. To
4462 * avoid this, we have to allow header and body to be in a single
4463 * memory block, which is good for messages we read and bad for
4464 * messages we are creating. But we could move_len() the buffer into
4465 * this single memory block, and move_len() will just swap the buffers
4466 * if you're moving the entire buffer replacing the dest string.
4467 *
4468 * We could also have the message loader tell the transport how many
4469 * bytes to read; so it would first ask for some arbitrary number like
4470 * 256, then if the message was incomplete it would use the
4471 * header/body len to ask for exactly the size of the message (or
4472 * blocks the size of a typical kernel buffer for the socket). That
4473 * way we don't get trailing bytes in the buffer that have to be
4474 * memmoved. Though I suppose we also don't have a chance of reading a
4475 * bunch of small messages at once, so the optimization may be stupid.
4476 *
4477 * Another approach would be to keep a "start" index into
4478 * loader->data and only delete it occasionally, instead of after
4479 * each message is loaded.
4480 *
4481 * load_message() returns FALSE if not enough memory OR the loader was corrupted
4482 */
4483static dbus_bool_t
4484load_message (DBusMessageLoader *loader,
4485 DBusMessage *message,
4486 int byte_order,
4487 int fields_array_len,
4488 int header_len,
4489 int body_len)
4490{
4491 dbus_bool_t oom;
4492 DBusValidity validity;
4493 const DBusString *type_str;
4494 int type_pos;
4495 DBusValidationMode mode;
4496 dbus_uint32_t n_unix_fds = 0;
4497
4498 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
4499
4500 oom = FALSE;
4501
4502#if 0
4503 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
4504#endif
4505
4506 /* 1. VALIDATE AND COPY OVER HEADER */
4508 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
4509
4510 if (!_dbus_header_load (&message->header,
4511 mode,
4512 &validity,
4513 byte_order,
4514 fields_array_len,
4515 header_len,
4516 body_len,
4517 &loader->data))
4518 {
4519 _dbus_verbose ("Failed to load header for new message code %d\n", validity);
4520
4521 /* assert here so we can catch any code that still uses DBUS_VALID to indicate
4522 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
4523 _dbus_assert (validity != DBUS_VALID);
4524
4525 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
4526 oom = TRUE;
4527 else
4528 {
4529 loader->corrupted = TRUE;
4530 loader->corruption_reason = validity;
4531 }
4532 goto failed;
4533 }
4534
4535 _dbus_assert (validity == DBUS_VALID);
4536
4537 /* 2. VALIDATE BODY */
4538 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
4539 {
4540 get_const_signature (&message->header, &type_str, &type_pos);
4541
4542 /* Because the bytes_remaining arg is NULL, this validates that the
4543 * body is the right length
4544 */
4545 validity = _dbus_validate_body_with_reason (type_str,
4546 type_pos,
4547 byte_order,
4548 NULL,
4549 &loader->data,
4550 header_len,
4551 body_len);
4552 if (validity != DBUS_VALID)
4553 {
4554 _dbus_verbose ("Failed to validate message body code %d\n", validity);
4555
4556 loader->corrupted = TRUE;
4557 loader->corruption_reason = validity;
4558
4559 goto failed;
4560 }
4561 }
4562
4563 /* 3. COPY OVER UNIX FDS */
4567 &n_unix_fds);
4568
4569#ifdef HAVE_UNIX_FD_PASSING
4570
4571 if (n_unix_fds > loader->n_unix_fds)
4572 {
4573 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
4574 n_unix_fds, loader->n_unix_fds);
4575
4576 loader->corrupted = TRUE;
4577 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4578 goto failed;
4579 }
4580
4581 /* If this was a recycled message there might still be
4582 some memory allocated for the fds */
4583 dbus_free(message->unix_fds);
4584
4585 if (n_unix_fds > 0)
4586 {
4587 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
4588 if (message->unix_fds == NULL)
4589 {
4590 _dbus_verbose ("Failed to allocate file descriptor array\n");
4591 oom = TRUE;
4592 goto failed;
4593 }
4594
4595 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
4596 loader->n_unix_fds -= n_unix_fds;
4597 memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
4598
4599 if (loader->unix_fds_change)
4600 loader->unix_fds_change (loader->unix_fds_change_data);
4601 }
4602 else
4603 message->unix_fds = NULL;
4604
4605#else
4606
4607 if (n_unix_fds > 0)
4608 {
4609 _dbus_verbose ("Hmm, message claims to come with file descriptors "
4610 "but that's not supported on our platform, disconnecting.\n");
4611
4612 loader->corrupted = TRUE;
4613 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4614 goto failed;
4615 }
4616
4617#endif
4618
4619 /* 3. COPY OVER BODY AND QUEUE MESSAGE */
4620
4621 if (!_dbus_list_append (&loader->messages, message))
4622 {
4623 _dbus_verbose ("Failed to append new message to loader queue\n");
4624 oom = TRUE;
4625 goto failed;
4626 }
4627
4628 _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4630 (header_len + body_len));
4631
4632 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
4633 {
4634 _dbus_verbose ("Failed to move body into new message\n");
4635 oom = TRUE;
4636 goto failed;
4637 }
4638
4639 _dbus_string_delete (&loader->data, 0, header_len + body_len);
4640
4641 /* don't waste more than 2k of memory */
4642 _dbus_string_compact (&loader->data, 2048);
4643
4644 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
4645 _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4646
4647 _dbus_verbose ("Loaded message %p\n", message);
4648
4649 _dbus_assert (!oom);
4650 _dbus_assert (!loader->corrupted);
4651 _dbus_assert (loader->messages != NULL);
4652 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4653
4654 return TRUE;
4655
4656 failed:
4657
4658 /* Clean up */
4659
4660 /* does nothing if the message isn't in the list */
4661 _dbus_list_remove_last (&loader->messages, message);
4662
4663 if (oom)
4664 _dbus_assert (!loader->corrupted);
4665 else
4666 _dbus_assert (loader->corrupted);
4667
4669
4670 return FALSE;
4671}
4672
4689{
4690 while (!loader->corrupted &&
4692 {
4693 DBusValidity validity;
4694 int byte_order, fields_array_len, header_len, body_len;
4695
4697 &validity,
4698 &byte_order,
4699 &fields_array_len,
4700 &header_len,
4701 &body_len,
4702 &loader->data, 0,
4703 _dbus_string_get_length (&loader->data)))
4704 {
4705 DBusMessage *message;
4706
4707 _dbus_assert (validity == DBUS_VALID);
4708
4709 message = dbus_message_new_empty_header ();
4710 if (message == NULL)
4711 return FALSE;
4712
4713 if (!load_message (loader, message,
4714 byte_order, fields_array_len,
4715 header_len, body_len))
4716 {
4717 dbus_message_unref (message);
4718 /* load_message() returns false if corrupted or OOM; if
4719 * corrupted then return TRUE for not OOM
4720 */
4721 return loader->corrupted;
4722 }
4723
4724 _dbus_assert (loader->messages != NULL);
4725 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4726 }
4727 else
4728 {
4729 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
4730 validity);
4731 if (validity != DBUS_VALID)
4732 {
4733 loader->corrupted = TRUE;
4734 loader->corruption_reason = validity;
4735 }
4736 return TRUE;
4737 }
4738 }
4739
4740 return TRUE;
4741}
4742
4752{
4753 if (loader->messages)
4754 return loader->messages->data;
4755 else
4756 return NULL;
4757}
4758
4769{
4770 return _dbus_list_pop_first (&loader->messages);
4771}
4772
4781DBusList*
4783{
4784 return _dbus_list_pop_first_link (&loader->messages);
4785}
4786
4793void
4795 DBusList *link)
4796{
4797 _dbus_list_prepend_link (&loader->messages, link);
4798}
4799
4811{
4812 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4813 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4814 return loader->corrupted;
4815}
4816
4825{
4826 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4827 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4828
4829 return loader->corruption_reason;
4830}
4831
4838void
4840 long size)
4841{
4842 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
4843 {
4844 _dbus_verbose ("clamping requested max message size %ld to %d\n",
4847 }
4848 loader->max_message_size = size;
4849}
4850
4857long
4859{
4860 return loader->max_message_size;
4861}
4862
4869void
4871 long n)
4872{
4874 {
4875 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
4878 }
4879 loader->max_message_unix_fds = n;
4880}
4881
4888long
4890{
4891 return loader->max_message_unix_fds;
4892}
4893
4899int
4901{
4902#ifdef HAVE_UNIX_FD_PASSING
4903 return loader->n_unix_fds;
4904#else
4905 return 0;
4906#endif
4907}
4908
4917void
4919 void (* callback) (void *),
4920 void *data)
4921{
4922#ifdef HAVE_UNIX_FD_PASSING
4923 loader->unix_fds_change = callback;
4924 loader->unix_fds_change_data = data;
4925#endif
4926}
4927
4928static DBusDataSlotAllocator slot_allocator =
4929 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
4930
4947{
4948 return _dbus_data_slot_allocator_alloc (&slot_allocator,
4949 slot_p);
4950}
4951
4963void
4965{
4966 _dbus_return_if_fail (*slot_p >= 0);
4967
4968 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
4969}
4970
4986 dbus_int32_t slot,
4987 void *data,
4988 DBusFreeFunction free_data_func)
4989{
4990 DBusFreeFunction old_free_func;
4991 void *old_data;
4992 dbus_bool_t retval;
4993
4994 _dbus_return_val_if_fail (message != NULL, FALSE);
4995 _dbus_return_val_if_fail (slot >= 0, FALSE);
4996
4997 retval = _dbus_data_slot_list_set (&slot_allocator,
4998 &message->slot_list,
4999 slot, data, free_data_func,
5000 &old_free_func, &old_data);
5001
5002 if (retval)
5003 {
5004 /* Do the actual free outside the message lock */
5005 if (old_free_func)
5006 (* old_free_func) (old_data);
5007 }
5008
5009 return retval;
5010}
5011
5020void*
5022 dbus_int32_t slot)
5023{
5024 void *res;
5025
5026 _dbus_return_val_if_fail (message != NULL, NULL);
5027
5028 res = _dbus_data_slot_list_get (&slot_allocator,
5029 &message->slot_list,
5030 slot);
5031
5032 return res;
5033}
5034
5048int
5049dbus_message_type_from_string (const char *type_str)
5050{
5051 if (strcmp (type_str, "method_call") == 0)
5053 if (strcmp (type_str, "method_return") == 0)
5055 else if (strcmp (type_str, "signal") == 0)
5057 else if (strcmp (type_str, "error") == 0)
5059 else
5061}
5062
5076const char *
5078{
5079 switch (type)
5080 {
5082 return "method_call";
5084 return "method_return";
5086 return "signal";
5088 return "error";
5089 default:
5090 return "invalid";
5091 }
5092}
5093
5108 char **marshalled_data_p,
5109 int *len_p)
5110{
5111 DBusString tmp;
5112 dbus_bool_t was_locked;
5113
5114 _dbus_return_val_if_fail (msg != NULL, FALSE);
5115 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
5116 _dbus_return_val_if_fail (len_p != NULL, FALSE);
5117
5118 if (!_dbus_string_init (&tmp))
5119 return FALSE;
5120
5121 /* Ensure the message is locked, to ensure the length header is filled in. */
5122 was_locked = msg->locked;
5123
5124 if (!was_locked)
5125 dbus_message_lock (msg);
5126
5127 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
5128 goto fail;
5129
5130 *len_p = _dbus_string_get_length (&tmp);
5131
5132 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
5133 goto fail;
5134
5135 *len_p = _dbus_string_get_length (&tmp);
5136
5137 if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
5138 goto fail;
5139
5140 _dbus_string_free (&tmp);
5141
5142 if (!was_locked)
5143 msg->locked = FALSE;
5144
5145 return TRUE;
5146
5147 fail:
5148 _dbus_string_free (&tmp);
5149
5150 if (!was_locked)
5151 msg->locked = FALSE;
5152
5153 return FALSE;
5154}
5155
5169dbus_message_demarshal (const char *str,
5170 int len,
5171 DBusError *error)
5172{
5173 DBusMessageLoader *loader = NULL;
5174 DBusString *buffer;
5175 DBusMessage *msg;
5176
5177 _dbus_return_val_if_fail (str != NULL, NULL);
5178
5179 loader = _dbus_message_loader_new ();
5180
5181 if (loader == NULL)
5182 goto fail_oom;
5183
5184 _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
5185
5186 if (!_dbus_string_append_len (buffer, str, len))
5187 goto fail_oom;
5188
5189 _dbus_message_loader_return_buffer (loader, buffer);
5190
5192 goto fail_oom;
5193
5195 goto fail_corrupt;
5196
5197 msg = _dbus_message_loader_pop_message (loader);
5198
5199 if (!msg)
5200 goto fail_oom;
5201
5203 return msg;
5204
5205 fail_corrupt:
5207 goto fail_oom;
5208
5209 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
5210 _dbus_validity_to_error_message (loader->corruption_reason));
5212 return NULL;
5213
5214 fail_oom:
5215 _DBUS_SET_OOM (error);
5216
5217 if (loader != NULL)
5219
5220 return NULL;
5221}
5222
5235int
5237 int len)
5238{
5239 DBusString str;
5240 int byte_order, fields_array_len, header_len, body_len;
5241 DBusValidity validity = DBUS_VALID;
5242 int have_message;
5243
5244 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
5245 return 0;
5246
5249 _dbus_string_init_const_len (&str, buf, len);
5250
5251 validity = DBUS_VALID;
5252 have_message
5254 &validity, &byte_order,
5255 &fields_array_len,
5256 &header_len,
5257 &body_len,
5258 &str, 0,
5259 len);
5260 _dbus_string_free (&str);
5261
5262 if (validity == DBUS_VALID)
5263 {
5264 _dbus_assert (have_message || (header_len + body_len) > len);
5265 (void) have_message; /* unused unless asserting */
5266 return header_len + body_len;
5267 }
5268 else
5269 {
5270 return -1; /* broken! */
5271 }
5272}
5273
5295void
5297 dbus_bool_t allow)
5298{
5299 _dbus_return_if_fail (message != NULL);
5300 _dbus_return_if_fail (!message->locked);
5301
5304 allow);
5305}
5306
5315{
5316 _dbus_return_val_if_fail (message != NULL, FALSE);
5317
5318 return _dbus_header_get_flag (&message->header,
5320}
5321
5329{
5330 DBusString data;
5331};
5332
5346{
5347 DBusVariant *self = NULL;
5348 /* Points to the single item we will read from the reader */
5349 DBusMessageRealIter *real_reader = (DBusMessageRealIter *) reader;
5350 /* The position in self at which we will write a single variant
5351 * (it is position 0) */
5352 DBusTypeWriter items_writer;
5353 /* The position in self at which we will write a copy of reader
5354 * (it is inside the variant) */
5355 DBusTypeWriter variant_writer;
5356 /* 'v' */
5357 DBusString variant_signature;
5358 /* Whatever is the signature of the item we will copy from the reader */
5359 DBusString contained_signature;
5360 /* TRUE if self->data needs to be freed */
5361 dbus_bool_t data_inited = FALSE;
5362 /* The type of the item we will read from the reader */
5363 int type;
5364 /* The string, start position within that string, and length of the signature
5365 * of the single complete type of the item reader points to */
5366 const DBusString *sig;
5367 int start, len;
5368
5369 _dbus_assert (_dbus_message_iter_check (real_reader));
5370 _dbus_assert (real_reader->iter_type == DBUS_MESSAGE_ITER_TYPE_READER);
5372 type = dbus_message_iter_get_arg_type (reader);
5373 _dbus_type_reader_get_signature (&real_reader->u.reader, &sig, &start, &len);
5374
5375 if (!_dbus_string_init (&contained_signature))
5376 return NULL;
5377
5378 if (!_dbus_string_copy_len (sig, start, len, &contained_signature, 0))
5379 goto oom;
5380
5381 self = dbus_new0 (DBusVariant, 1);
5382
5383 if (self == NULL)
5384 goto oom;
5385
5386 if (!_dbus_string_init (&self->data))
5387 goto oom;
5388
5389 data_inited = TRUE;
5390
5391 _dbus_type_writer_init_values_only (&items_writer, DBUS_COMPILER_BYTE_ORDER,
5392 &variant_signature, 0, &self->data, 0);
5393
5394 if (!_dbus_type_writer_recurse (&items_writer, DBUS_TYPE_VARIANT,
5395 &contained_signature, 0, &variant_writer))
5396 goto oom;
5397
5398 if (type == DBUS_TYPE_ARRAY)
5399 {
5400 /* Points to each item in turn inside the array we are copying */
5401 DBusMessageIter array_reader;
5402 /* Same as array_reader */
5403 DBusMessageRealIter *real_array_reader = (DBusMessageRealIter *) &array_reader;
5404 /* The position inside the copied array at which we will write
5405 * the copy of array_reader */
5406 DBusTypeWriter array_writer;
5407
5408 dbus_message_iter_recurse (reader, &array_reader);
5409
5410 if (!_dbus_type_writer_recurse (&variant_writer, type,
5411 &contained_signature, 1, &array_writer))
5412 goto oom;
5413
5414 if (!_dbus_type_writer_write_reader (&array_writer,
5415 &real_array_reader->u.reader))
5416 goto oom;
5417
5418 if (!_dbus_type_writer_unrecurse (&variant_writer, &array_writer))
5419 goto oom;
5420 }
5421 else if (type == DBUS_TYPE_DICT_ENTRY || type == DBUS_TYPE_VARIANT ||
5422 type == DBUS_TYPE_STRUCT)
5423 {
5424 /* Points to each item in turn inside the container we are copying */
5425 DBusMessageIter inner_reader;
5426 /* Same as inner_reader */
5427 DBusMessageRealIter *real_inner_reader = (DBusMessageRealIter *) &inner_reader;
5428 /* The position inside the copied container at which we will write the
5429 * copy of inner_reader */
5430 DBusTypeWriter inner_writer;
5431
5432 dbus_message_iter_recurse (reader, &inner_reader);
5433
5434 if (!_dbus_type_writer_recurse (&variant_writer, type, NULL, 0,
5435 &inner_writer))
5436 goto oom;
5437
5438 if (!_dbus_type_writer_write_reader (&inner_writer,
5439 &real_inner_reader->u.reader))
5440 goto oom;
5441
5442 if (!_dbus_type_writer_unrecurse (&variant_writer, &inner_writer))
5443 goto oom;
5444 }
5445 else
5446 {
5447 DBusBasicValue value;
5448
5449 /* We eliminated all the container types above */
5451
5452 dbus_message_iter_get_basic (reader, &value);
5453
5454 if (!_dbus_type_writer_write_basic (&variant_writer, type, &value))
5455 goto oom;
5456 }
5457
5458 _dbus_string_free (&contained_signature);
5459 return self;
5460
5461oom:
5462 if (self != NULL)
5463 {
5464 if (data_inited)
5465 _dbus_string_free (&self->data);
5466
5467 dbus_free (self);
5468 }
5469
5470 _dbus_string_free (&contained_signature);
5471 return NULL;
5472}
5473
5480const char *
5482{
5483 const char *ret;
5484#ifndef DBUS_DISABLE_ASSERT
5485 unsigned char len;
5486#endif
5487
5488 _dbus_assert (self != NULL);
5489
5490#ifndef DBUS_DISABLE_ASSERT
5491 /* Here we make use of the fact that the serialization of a variant starts
5492 * with the 1-byte length, then that many bytes of signature, then \0. */
5493 len = _dbus_string_get_byte (&self->data, 0);
5494#endif
5495 ret = _dbus_string_get_const_data_len (&self->data, 1, len);
5496 _dbus_assert (strlen (ret) == len);
5497 return ret;
5498}
5499
5513 DBusMessageIter *writer)
5514{
5515 /* 'v' */
5516 DBusString variant_signature;
5517 /* Points to the single item in self */
5518 DBusTypeReader variant_reader;
5519 /* Points to the single item (of whatever type) inside the variant */
5520 DBusTypeReader reader;
5521 /* The position at which we will copy reader */
5522 DBusMessageRealIter *real_writer = (DBusMessageRealIter *) writer;
5523 dbus_bool_t ret;
5524
5525 _dbus_assert (self != NULL);
5526 _dbus_assert (_dbus_message_iter_append_check (real_writer));
5527 _dbus_assert (real_writer->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
5528
5530 _dbus_type_reader_init (&reader, DBUS_COMPILER_BYTE_ORDER,
5531 &variant_signature, 0, &self->data, 0);
5532 _dbus_type_reader_recurse (&reader, &variant_reader);
5533
5534 if (!_dbus_message_iter_open_signature (real_writer))
5535 return FALSE;
5536
5537 ret = _dbus_type_writer_write_reader (&real_writer->u.writer,
5538 &variant_reader);
5539
5540 if (!_dbus_message_iter_close_signature (real_writer))
5541 return FALSE;
5542
5543 return ret;
5544}
5545
5546int
5547_dbus_variant_get_length (DBusVariant *self)
5548{
5549 _dbus_assert (self != NULL);
5550 return _dbus_string_get_length (&self->data);
5551}
5552
5553const DBusString *
5554_dbus_variant_peek (DBusVariant *self)
5555{
5556 _dbus_assert (self != NULL);
5557 return &self->data;
5558}
5559
5560void
5561_dbus_variant_free (DBusVariant *self)
5562{
5563 _dbus_assert (self != NULL);
5564 _dbus_string_free (&self->data);
5565 dbus_free (self);
5566}
5567
5570/* tests in dbus-message-util.c */
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().
void _dbus_data_slot_list_clear(DBusDataSlotList *list)
Frees all data slots contained in the list, calling application-provided free functions if they exist...
void _dbus_data_slot_list_init(DBusDataSlotList *list)
Initializes a slot list.
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...
void * _dbus_data_slot_list_get(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot)
Retrieves data previously set with _dbus_data_slot_list_set_data().
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_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:72
void dbus_error_init(DBusError *error)
Initializes a DBusError structure.
Definition: dbus-errors.c:190
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:356
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition: dbus-errors.c:213
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
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...
char * _dbus_strdup(const char *str)
Duplicates a string.
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
#define _DBUS_LOCK_NAME(name)
Expands to name of a global lock variable.
#define _DBUS_ZERO(object)
Sets all bits in an object to zero.
void * _dbus_memdup(const void *mem, size_t n_bytes)
Duplicates a block of memory.
DBusList * _dbus_list_pop_first_link(DBusList **list)
Removes the first link in the list and returns it.
Definition: dbus-list.c:658
void _dbus_list_append_link(DBusList **list, DBusList *link)
Appends a link to the list.
Definition: dbus-list.c:318
void _dbus_list_clear_full(DBusList **list, DBusFreeFunction function)
Free every link and every element in the list.
Definition: dbus-list.c:570
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition: dbus-list.c:530
DBusList * _dbus_list_find_last(DBusList **list, void *data)
Finds a value in the list.
Definition: dbus-list.c:475
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:679
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition: dbus-list.c:789
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:545
void _dbus_list_prepend_link(DBusList **list, DBusList *link)
Prepends a link to the list.
Definition: dbus-list.c:336
DBusList * _dbus_list_alloc_link(void *data)
Allocates a linked list node.
Definition: dbus-list.c:245
dbus_bool_t _dbus_list_remove_last(DBusList **list, void *data)
Removes a value from the list.
Definition: dbus-list.c:449
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:273
#define NULL
A null pointer, defined appropriately for C or C++.
#define TRUE
Expands to "1".
#define FALSE
Expands to "0".
dbus_bool_t _dbus_type_writer_write_basic(DBusTypeWriter *writer, int type, const void *value)
Writes out a basic type.
void _dbus_type_reader_recurse(DBusTypeReader *reader, DBusTypeReader *sub)
Initialize a new reader pointing to the first type and corresponding value that's a child of the curr...
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
void _dbus_header_update_lengths(DBusHeader *header, int body_len)
Fills in the correct body length.
dbus_bool_t _dbus_header_copy(const DBusHeader *header, DBusHeader *dest)
Initializes dest with a copy of the given header.
DBusValidity _dbus_validate_signature_with_reason(const DBusString *type_str, int type_pos, int len)
Verifies that the range of type_str from type_pos to type_end is a valid signature.
void _dbus_type_writer_init_values_only(DBusTypeWriter *writer, int byte_order, const DBusString *type_str, int type_pos, DBusString *value_str, int value_pos)
Like _dbus_type_writer_init(), except the type string passed in should correspond to an existing sign...
int _dbus_type_get_alignment(int typecode)
Gets the alignment requirement for the given type; will be 1, 2, 4, or 8.
void _dbus_type_writer_remove_types(DBusTypeWriter *writer)
Removes type string from the writer.
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.
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_header_set_field_basic(DBusHeader *header, int field, int type, const void *value)
Sets the value of a field with basic type.
int _dbus_header_get_message_type(DBusHeader *header)
Gets the type of the message.
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_type_writer_write_reader(DBusTypeWriter *writer, DBusTypeReader *reader)
Iterate through all values in the given reader, writing a copy of each value to the writer.
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_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_bool_t _dbus_header_get_flag(DBusHeader *header, dbus_uint32_t flag)
Gets a message flag bit, returning TRUE if the bit is set.
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.
void _dbus_type_reader_read_fixed_multi(const DBusTypeReader *reader, const 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...
char _dbus_header_get_byte_order(const DBusHeader *header)
Returns the header's byte order.
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,...
void _dbus_header_reinit(DBusHeader *header)
Re-initializes a header that was previously initialized and never freed.
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.
dbus_bool_t _dbus_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
dbus_bool_t _dbus_header_delete_field(DBusHeader *header, int field)
Deletes a field, if it exists.
int _dbus_type_reader_get_array_length(const DBusTypeReader *reader)
Returns the number of bytes in the array.
dbus_bool_t _dbus_header_remove_unknown_fields(DBusHeader *header)
Remove every header field not known to this version of dbus.
dbus_uint32_t _dbus_header_get_serial(DBusHeader *header)
See dbus_message_get_serial()
void _dbus_type_writer_add_types(DBusTypeWriter *writer, DBusString *type_str, int type_pos)
Adds type string to the writer, if it had none.
dbus_bool_t _dbus_type_reader_has_next(const DBusTypeReader *reader)
Check whether there's another value on this "level".
void _dbus_type_reader_read_basic(const DBusTypeReader *reader, void *value)
Reads a basic-typed value, as with _dbus_marshal_read_basic().
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.
const char * _dbus_type_to_string(int typecode)
Returns a string describing the given type.
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_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...
void _dbus_header_free(DBusHeader *header)
Frees a header.
dbus_bool_t _dbus_header_init(DBusHeader *header)
Initializes a header, but doesn't prepare it for use; to make the header valid, you have to call _dbu...
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.
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_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_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_set_serial(DBusHeader *header, dbus_uint32_t serial)
Sets the serial number of a header.
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)
Creates a message header from potentially-untrusted data.
void _dbus_header_byteswap(DBusHeader *header, int new_order)
Swaps the header into the given order if required.
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.
DBusValidationMode
This is used rather than a bool for high visibility.
@ DBUS_VALIDITY_UNKNOWN_OOM_ERROR
can't determine validity due to OOM
@ DBUS_VALID
the data is valid
int _dbus_current_generation
_dbus_current_generation is used to track each time that dbus_shutdown() is called,...
Definition: dbus-memory.c:774
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:803
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition: dbus-memory.h:65
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:694
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:594
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:59
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:60
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:742
void _dbus_message_loader_set_max_message_size(DBusMessageLoader *loader, long size)
Sets the maximum size message we allow.
dbus_bool_t _dbus_message_remove_unknown_fields(DBusMessage *message)
Remove every header field not known to this version of dbus.
Definition: dbus-message.c:284
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:838
DBusVariant * _dbus_variant_read(DBusMessageIter *reader)
Copy a single D-Bus message item from reader into a newly-allocated DBusVariant.
#define ensure_byte_order(message)
byte-swap the message if it doesn't match our byte order.
Definition: dbus-message.c:230
#define MAX_MESSAGE_SIZE_TO_CACHE
Avoid caching huge messages.
Definition: dbus-message.c:508
dbus_bool_t _dbus_variant_write(DBusVariant *self, DBusMessageIter *writer)
Copy the single D-Bus message item from self into writer.
void dbus_message_iter_init_closed(DBusMessageIter *iter)
Initialize iter as if with DBUS_MESSAGE_ITER_INIT_CLOSED.
Definition: dbus-message.c:755
dbus_bool_t _dbus_message_loader_get_is_corrupted(DBusMessageLoader *loader)
Checks whether the loader is confused due to bad data.
void dbus_message_set_serial(DBusMessage *message, dbus_uint32_t serial)
Sets the serial number of a message.
Definition: dbus-message.c:301
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition: dbus-message.c:431
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.
void _dbus_message_loader_unref(DBusMessageLoader *loader)
Decrements the reference count of the loader and finalizes the loader when the count reaches zero.
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 _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:262
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.
DBusMessage * _dbus_message_loader_pop_message(DBusMessageLoader *loader)
Pops a loaded message (passing ownership of the message to the caller).
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:243
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...
#define CHANGED_STAMP_BITS
How many bits are in the changed_stamp used to validate iterators.
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_loader_putback_message_link(DBusMessageLoader *loader, DBusList *link)
Returns a popped message link, used to undo a pop.
void * dbus_message_get_data(DBusMessage *message, dbus_int32_t slot)
Retrieves data previously set with dbus_message_set_data().
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_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...
int _dbus_message_loader_get_pending_fds_count(DBusMessageLoader *loader)
Return how many file descriptors are pending in the loader.
const char * _dbus_variant_get_signature(DBusVariant *self)
Return the signature of the item stored in self.
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_STRING_DEFINE_STATIC(_dbus_empty_signature_str, "")
An static string representing an empty signature.
void _dbus_message_loader_get_buffer(DBusMessageLoader *loader, DBusString **buffer, int *max_to_read, dbus_bool_t *may_read_fds)
Gets the buffer to use for reading data from the network.
void dbus_message_free_data_slot(dbus_int32_t *slot_p)
Deallocates a global ID for message data slots.
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:399
#define INITIAL_LOADER_DATA_LEN
The initial buffer size of the message loader.
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,...
Definition: dbus-message.c:376
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_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.
void _dbus_message_loader_set_max_message_unix_fds(DBusMessageLoader *loader, long n)
Sets the maximum unix fds per message we allow.
long _dbus_message_loader_get_max_message_size(DBusMessageLoader *loader)
Gets the maximum allowed message size in bytes.
DBusMessageLoader * _dbus_message_loader_new(void)
Creates a new message loader.
#define MAX_MESSAGE_CACHE_SIZE
Avoid caching too many messages.
Definition: dbus-message.c:511
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).
dbus_bool_t _dbus_message_loader_queue_messages(DBusMessageLoader *loader)
Converts buffered data into messages, if we have enough data.
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...
DBusMessageLoader * _dbus_message_loader_ref(DBusMessageLoader *loader)
Increments the reference count of the loader.
long _dbus_message_loader_get_max_message_unix_fds(DBusMessageLoader *loader)
Gets the maximum allowed number of unix fds per message.
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,...
Definition: dbus-message.c:327
DBusValidity _dbus_message_loader_get_corruption_reason(DBusMessageLoader *loader)
Checks what kind of bad data confused the loader.
dbus_bool_t dbus_message_get_allow_interactive_authorization(DBusMessage *message)
Returns whether the flag controlled by dbus_message_set_allow_interactive_authorization() has been se...
dbus_bool_t dbus_message_has_destination(DBusMessage *message, const char *name)
Checks whether the message was sent to the given name.
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...
dbus_bool_t dbus_message_has_interface(DBusMessage *message, const char *iface)
Checks if the message has an interface.
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,...
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.
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...
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...
dbus_bool_t dbus_message_iter_append_basic(DBusMessageIter *iter, int type, const void *value)
Appends a basic-typed value to the 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...
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...
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.
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_uint32_t dbus_message_get_serial(DBusMessage *message)
Returns the serial of a message or 0 if none has been specified.
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...
void dbus_message_iter_get_basic(DBusMessageIter *iter, void *value)
Reads a basic-typed value from the message iterator.
int dbus_message_get_type(DBusMessage *message)
Gets the type of a message.
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 ...
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_next(DBusMessageIter *iter)
Moves the iterator to the next field, if any.
dbus_bool_t dbus_message_append_args(DBusMessage *message, int first_arg_type,...)
Appends fields to a message given a variable argument list.
int dbus_message_iter_get_arg_type(DBusMessageIter *iter)
Returns the argument type of the argument that the message iterator points to.
dbus_bool_t dbus_message_get_no_reply(DBusMessage *message)
Returns TRUE if the message does not expect a reply.
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_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.
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...
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_is_error(DBusMessage *message, const char *error_name)
Checks whether the message is an error reply with the given error name.
dbus_bool_t dbus_message_contains_unix_fds(DBusMessage *message)
Checks whether a message contains unix fds.
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...
DBusMessage * dbus_message_ref(DBusMessage *message)
Increments the reference count of a DBusMessage.
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.
int dbus_message_iter_get_element_type(DBusMessageIter *iter)
Returns the element type of the array that the message iterator points to.
dbus_bool_t dbus_message_set_error_name(DBusMessage *message, const char *error_name)
Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
dbus_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...
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.
dbus_uint32_t dbus_message_get_reply_serial(DBusMessage *message)
Returns the serial that the message is a reply to or 0 if none.
DBusMessage * dbus_message_new_method_return(DBusMessage *method_call)
Constructs a message that is a reply to a method call.
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.
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_set_sender(DBusMessage *message, const char *sender)
Sets the message sender.
void dbus_message_iter_abandon_container_if_open(DBusMessageIter *iter, DBusMessageIter *sub)
Abandons creation of a contained-typed value and frees resources created by dbus_message_iter_open_co...
const char * dbus_message_get_destination(DBusMessage *message)
Gets the destination of a message or NULL if there is none set.
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...
dbus_bool_t dbus_message_iter_has_next(DBusMessageIter *iter)
Checks if an iterator has any more fields.
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.
char * dbus_message_iter_get_signature(DBusMessageIter *iter)
Returns the current signature of a message iterator.
void dbus_message_unref(DBusMessage *message)
Decrements the reference count of a DBusMessage, freeing the message if the count reaches 0.
int dbus_message_iter_get_array_len(DBusMessageIter *iter)
Returns the number of bytes in the array as marshaled in the wire protocol.
DBusMessage * dbus_message_new(int message_type)
Constructs a new message of the given message type.
dbus_bool_t dbus_set_error_from_message(DBusError *error, DBusMessage *message)
Sets a DBusError based on the contents of the given message.
int dbus_message_iter_get_element_count(DBusMessageIter *iter)
Returns the number of elements in the array-typed value pointed to by the iterator.
dbus_bool_t dbus_message_set_destination(DBusMessage *message, const char *destination)
Sets the message's destination.
dbus_bool_t dbus_message_has_path(DBusMessage *message, const char *path)
Checks if the message has a particular object path.
dbus_bool_t dbus_message_has_member(DBusMessage *message, const char *member)
Checks if the message has an interface member.
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.
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.
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.
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).
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.
const char * dbus_message_get_signature(DBusMessage *message)
Gets the type signature of the message, i.e.
dbus_bool_t dbus_message_set_container_instance(DBusMessage *message, const char *object_path)
Sets the container instance this message was sent from.
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_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...
const char * dbus_message_get_member(DBusMessage *message)
Gets the interface member being invoked (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted (DBUS_MESSAGE_TYPE...
void dbus_message_iter_init_append(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for appending arguments to the end of a message.
const char * dbus_message_get_container_instance(DBusMessage *message)
Gets the container instance this message was sent from, or NULL if none.
dbus_bool_t _dbus_decompose_path(const char *data, int len, char ***path, int *path_len)
Decompose an object path.
#define DBUS_HEADER_FIELD_UNIX_FDS
Header field code for the number of unix file descriptors associated with this message.
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type()
#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...
#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,...
#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...
#define DBUS_HEADER_FIELD_CONTAINER_INSTANCE
Header field code for the container instance that sent this message.
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS
The maximum total number of unix fds in a message.
#define DBUS_MAXIMUM_MESSAGE_LENGTH
The maximum total message size including header and body; similar rationale to max array size.
#define DBUS_HEADER_FIELD_INTERFACE
Header field code for the interface containing a member (method or signal).
#define DBUS_ERROR_INCONSISTENT_MESSAGE
The message meta data does not match the payload.
#define DBUS_HEADER_FIELD_MEMBER
Header field code for a member (method or signal).
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type()
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn't supported (like ENOSYS on UNIX).
#define DBUS_HEADER_FIELD_SENDER
Header field code for the sender of a message; usually initialized by the message bus.
#define DBUS_HEADER_FIELD_SIGNATURE
Header field code for the type signature of a message.
#define DBUS_MESSAGE_TYPE_METHOD_RETURN
Message type of a method return message, see dbus_message_get_type()
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
#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...
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
#define DBUS_TYPE_BOOLEAN
Type code marking a boolean.
Definition: dbus-protocol.h:72
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type()
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
#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 ...
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array 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...
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition: dbus-protocol.h:62
#define DBUS_HEADER_FIELD_ERROR_NAME
Header field code for an error name (found in DBUS_MESSAGE_TYPE_ERROR messages).
#define DBUS_TYPE_VARIANT_AS_STRING
DBUS_TYPE_VARIANT as a string literal instead of a int literal
#define DBUS_MESSAGE_TYPE_INVALID
This value is never a valid message type, see dbus_message_get_type()
#define DBUS_ERROR_INVALID_ARGS
Invalid arguments passed to a method call.
#define DBUS_TYPE_DICT_ENTRY
Type code used to represent a dict entry; however, this type code does not appear in type signatures,...
#define DBUS_DICT_ENTRY_BEGIN_CHAR
Code marking the start of a dict entry type in a type signature.
#define DBUS_HEADER_FIELD_DESTINATION
Header field code for the destination bus name of a message.
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string,...
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition: dbus-protocol.h:88
#define DBUS_MINIMUM_HEADER_SIZE
The smallest header size that can occur.
void _dbus_counter_unref(DBusCounter *counter)
Decrements refcount of the counter and possibly finalizes the counter.
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.
void _dbus_counter_notify(DBusCounter *counter)
Calls the notify function from _dbus_counter_set_notify(), if that function has been specified and th...
DBusCounter * _dbus_counter_ref(DBusCounter *counter)
Increments refcount of the counter.
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.
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...
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.
dbus_bool_t dbus_type_is_container(int typecode)
A "container type" can contain basic types, or nested container types.
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition: dbus-string.c:847
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:182
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:197
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c:1345
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:686
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:139
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:217
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:1170
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as #_DBUS_STRING_I...
Definition: dbus-string.c:278
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:1255
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:1105
int _dbus_string_get_length(const DBusString *str)
Gets the length of a string (not including nul termination).
Definition: dbus-string.c:784
const char * _dbus_string_get_const_data_len(const DBusString *str, int start, int len)
const version of _dbus_string_get_data_len().
Definition: dbus-string.c:559
const char * _dbus_string_get_const_data(const DBusString *str)
Gets the raw character buffer from a const string.
Definition: dbus-string.c:513
unsigned char _dbus_string_get_byte(const DBusString *str, int start)
Gets the byte at the given position.
Definition: dbus-string.c:607
dbus_bool_t _dbus_string_compact(DBusString *str, int max_waste)
Compacts the string to avoid wasted memory.
Definition: dbus-string.c:420
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:1437
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
int _dbus_dup(int fd, DBusError *error)
Duplicates a file descriptor.
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition: dbus-sysdeps.c:197
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition: dbus-types.h:37
int dbus_int32_t
A 32-bit signed integer on all platforms.
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
Internals of DBusCounter.
An allocator that tracks a set of slot IDs.
Definition: dbus-dataslot.h:58
Object representing an exception.
Definition: dbus-errors.h:51
const char * message
public error message field
Definition: dbus-errors.h:53
Message header data and some cached details of it.
DBusString data
Header network data, stored separately from body so we can independently realloc it.
A node in a linked list.
Definition: dbus-list.h:37
void * data
Data stored at this element.
Definition: dbus-list.h:40
Layout of a DBusMessageIter on the stack in dbus 1.10.0.
Definition: dbus-message.c:156
DBusMessageIter struct; contains no public fields.
Definition: dbus-message.h:64
Implementation details of DBusMessageLoader.
long max_message_size
Maximum size of a message.
long max_message_unix_fds
Maximum unix fds in a message.
DBusString data
Buffered data.
DBusList * messages
Complete messages.
unsigned int corrupted
We got broken data, and are no longer working.
unsigned int buffer_outstanding
Someone is using the buffer to read.
DBusValidity corruption_reason
why we were corrupted
int refcount
Reference count.
Internals of DBusMessageIter.
Definition: dbus-message.c:129
union DBusMessageRealIter::@6 u
the type writer or reader that does all the work
DBusMessage * message
Message used.
Definition: dbus-message.c:130
dbus_uint32_t iter_type
whether this is a reader or writer iter
Definition: dbus-message.c:132
dbus_uint32_t sig_refcount
depth of open_signature()
Definition: dbus-message.c:133
DBusTypeWriter writer
writer
Definition: dbus-message.c:136
dbus_uint32_t changed_stamp
stamp to detect invalid iters
Definition: dbus-message.c:131
DBusTypeReader reader
reader
Definition: dbus-message.c:137
Internals of DBusMessage.
DBusHeader header
Header network data and associated cache.
DBusString body
Body network data.
DBusDataSlotList slot_list
Data stored by allocated integer ID.
DBusAtomic refcount
Reference count.
dbus_uint32_t changed_stamp
Incremented when iterators are invalidated.
int generation
_dbus_current_generation when message was created
long size_counter_delta
Size we incremented the size counters by.
DBusList * counters
0-N DBusCounter used to track message size/unix fds.
unsigned int in_cache
Has been "freed" since it's in the cache (this is a debug feature)
unsigned int locked
Message being sent, no modifications allowed.
The type reader is an iterator for reading values from a block of values.
dbus_uint32_t byte_order
byte order of the block
The type writer is an iterator for writing to a block of values.
dbus_uint32_t byte_order
byte order to write values with
DBusString * type_str
where to write typecodes (or read type expectations)
dbus_uint32_t container_type
what are we inside? (e.g.
An opaque data structure containing the serialized form of any single D-Bus message item,...
A simple value union that lets you access bytes as if they were various types; useful when dealing wi...
Definition: dbus-types.h:161
dbus_uint32_t u32
as int32
Definition: dbus-types.h:166