D-Bus 1.15.2
dbus-message.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-message.c DBusMessage object
3 *
4 * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
5 * Copyright (C) 2002, 2003 CodeFactory AB
6 *
7 * Licensed under the Academic Free License version 2.1
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25#include <config.h>
26#include "dbus-internals.h"
27#include "dbus-marshal-recursive.h"
28#include "dbus-marshal-validate.h"
29#include "dbus-marshal-byteswap.h"
30#include "dbus-marshal-header.h"
31#include "dbus-signature.h"
32#include "dbus-message-private.h"
33#include "dbus-object-tree.h"
34#include "dbus-memory.h"
35#include "dbus-list.h"
36#include "dbus-threads-internal.h"
37#ifdef HAVE_UNIX_FD_PASSING
38#include "dbus-sysdeps.h"
39#include "dbus-sysdeps-unix.h"
40#endif
41
42#include <string.h>
43
44#define _DBUS_TYPE_IS_STRINGLIKE(type) \
45 (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \
46 type == DBUS_TYPE_OBJECT_PATH)
47
48static void dbus_message_finalize (DBusMessage *message);
49
60#ifdef DBUS_ENABLE_EMBEDDED_TESTS
61static dbus_bool_t
62_dbus_enable_message_cache (void)
63{
64 static int enabled = -1;
65
66 if (enabled < 0)
67 {
68 const char *s = _dbus_getenv ("DBUS_MESSAGE_CACHE");
69
70 enabled = TRUE;
71
72 if (s && *s)
73 {
74 if (*s == '0')
75 enabled = FALSE;
76 else if (*s == '1')
77 enabled = TRUE;
78 else
79 _dbus_warn ("DBUS_MESSAGE_CACHE should be 0 or 1 if set, not '%s'",
80 s);
81 }
82 }
83
84 return enabled;
85}
86#else
87 /* constant expression, should be optimized away */
88# define _dbus_enable_message_cache() (TRUE)
89#endif
90
91#ifndef _dbus_message_trace_ref
92void
93_dbus_message_trace_ref (DBusMessage *message,
94 int old_refcount,
95 int new_refcount,
96 const char *why)
97{
98 static int enabled = -1;
99
100 _dbus_trace_ref ("DBusMessage", message, old_refcount, new_refcount, why,
101 "DBUS_MESSAGE_TRACE", &enabled);
102}
103#endif
104
105/* Not thread locked, but strictly const/read-only so should be OK
106 */
108_DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, "");
109
110/* these have wacky values to help trap uninitialized iterators;
111 * but has to fit in 3 bits
112 */
113enum {
114 DBUS_MESSAGE_ITER_TYPE_READER = 3,
115 DBUS_MESSAGE_ITER_TYPE_WRITER = 7
116};
117
120
127{
132 union
133 {
136 } u;
137};
138
139#if DBUS_SIZEOF_VOID_P > 8
140/*
141 * Architectures with 128-bit pointers were not supported in DBus 1.10, so we
142 * do no check for DBus 1.10 structure layout compatibility for such
143 * architectures (e.g. Arm Morello).
144 */
145#define CHECK_DBUS_1_10_BINARY_COMPATIBILITY 0
146#else
147#define CHECK_DBUS_1_10_BINARY_COMPATIBILITY 1
153typedef struct
154{
155 void *dummy1;
156 void *dummy2;
157 dbus_uint32_t dummy3;
158 int dummy4;
159 int dummy5;
160 int dummy6;
161 int dummy7;
162 int dummy8;
163 int dummy9;
164 int dummy10;
165 int dummy11;
166 int pad1;
167 int pad2;
168 void *pad3;
170#endif
171
172static void
173get_const_signature (DBusHeader *header,
174 const DBusString **type_str_p,
175 int *type_pos_p)
176{
177 if (_dbus_header_get_field_raw (header,
179 type_str_p,
180 type_pos_p))
181 {
182 *type_pos_p += 1; /* skip the signature length which is 1 byte */
183 }
184 else
185 {
186 *type_str_p = &_dbus_empty_signature_str;
187 *type_pos_p = 0;
188 }
189}
190
196static void
197_dbus_message_byteswap (DBusMessage *message)
198{
199 const DBusString *type_str;
200 int type_pos;
201 char byte_order;
202
203 byte_order = _dbus_header_get_byte_order (&message->header);
204
205 if (byte_order == DBUS_COMPILER_BYTE_ORDER)
206 return;
207
208 _dbus_verbose ("Swapping message into compiler byte order\n");
209
210 get_const_signature (&message->header, &type_str, &type_pos);
211
212 _dbus_marshal_byteswap (type_str, type_pos,
213 byte_order,
214 DBUS_COMPILER_BYTE_ORDER,
215 &message->body, 0);
216
217 _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
219 DBUS_COMPILER_BYTE_ORDER);
220}
221
228#define ensure_byte_order(message) _dbus_message_byteswap (message)
229
240void
242 const DBusString **header,
243 const DBusString **body)
244{
245 _dbus_assert (message->locked);
246
247 *header = &message->header.data;
248 *body = &message->body;
249}
250
261 const int **fds,
262 unsigned *n_fds)
263{
264 _dbus_assert (message->locked);
265
266#ifdef HAVE_UNIX_FD_PASSING
267 *fds = message->unix_fds;
268 *n_fds = message->n_unix_fds;
269#else
270 *fds = NULL;
271 *n_fds = 0;
272#endif
273}
274
283{
285}
286
298void
300 dbus_uint32_t serial)
301{
302 _dbus_return_if_fail (message != NULL);
303 _dbus_return_if_fail (!message->locked);
304
305 _dbus_header_set_serial (&message->header, serial);
306}
307
324void
326 DBusList *link)
327{
328 /* right now we don't recompute the delta when message
329 * size changes, and that's OK for current purposes
330 * I think, but could be important to change later.
331 * Do recompute it whenever there are no outstanding counters,
332 * since it's basically free.
333 */
334 if (message->counters == NULL)
335 {
336 message->size_counter_delta =
338 _dbus_string_get_length (&message->body);
339
340#ifdef HAVE_UNIX_FD_PASSING
341 message->unix_fd_counter_delta = message->n_unix_fds;
342#endif
343
344#if 0
345 _dbus_verbose ("message has size %ld\n",
346 message->size_counter_delta);
347#endif
348 }
349
350 _dbus_list_append_link (&message->counters, link);
351
353
354#ifdef HAVE_UNIX_FD_PASSING
355 _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
356#endif
357}
358
375 DBusCounter *counter)
376{
377 DBusList *link;
378
379 link = _dbus_list_alloc_link (counter);
380 if (link == NULL)
381 return FALSE;
382
383 _dbus_counter_ref (counter);
384 _dbus_message_add_counter_link (message, link);
385
386 return TRUE;
387}
388
396void
398 DBusCounter *counter)
399{
400 DBusList *link;
401
402 link = _dbus_list_find_last (&message->counters,
403 counter);
404 _dbus_assert (link != NULL);
405
406 _dbus_list_remove_link (&message->counters, link);
407
408 _dbus_counter_adjust_size (counter, - message->size_counter_delta);
409
410#ifdef HAVE_UNIX_FD_PASSING
411 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
412#endif
413
414 _dbus_counter_notify (counter);
415 _dbus_counter_unref (counter);
416}
417
428void
430{
431 if (!message->locked)
432 {
434 _dbus_string_get_length (&message->body));
435
436 /* must have a signature if you have a body */
437 _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
438 dbus_message_get_signature (message) != NULL);
439
440 message->locked = TRUE;
441 }
442}
443
444static dbus_bool_t
445set_or_delete_string_field (DBusMessage *message,
446 int field,
447 int typecode,
448 const char *value)
449{
450 if (value == NULL)
451 return _dbus_header_delete_field (&message->header, field);
452 else
453 return _dbus_header_set_field_basic (&message->header,
454 field,
455 typecode,
456 &value);
457}
458
459/* Message Cache
460 *
461 * We cache some DBusMessage to reduce the overhead of allocating
462 * them. In my profiling this consistently made about an 8%
463 * difference. It avoids the malloc for the message, the malloc for
464 * the slot list, the malloc for the header string and body string,
465 * and the associated free() calls. It does introduce another global
466 * lock which could be a performance issue in certain cases.
467 *
468 * For the echo client/server the round trip time goes from around
469 * .000077 to .000069 with the message cache on my laptop. The sysprof
470 * change is as follows (numbers are cumulative percentage):
471 *
472 * with message cache implemented as array as it is now (0.000069 per):
473 * new_empty_header 1.46
474 * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache)
475 * mutex_unlock 0.25
476 * self 0.41
477 * unref 2.24
478 * self 0.68
479 * list_clear 0.43
480 * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache)
481 * mutex_unlock 0.25
482 *
483 * with message cache implemented as list (0.000070 per roundtrip):
484 * new_empty_header 2.72
485 * list_pop_first 1.88
486 * unref 3.3
487 * list_prepend 1.63
488 *
489 * without cache (0.000077 per roundtrip):
490 * new_empty_header 6.7
491 * string_init_preallocated 3.43
492 * dbus_malloc 2.43
493 * dbus_malloc0 2.59
494 *
495 * unref 4.02
496 * string_free 1.82
497 * dbus_free 1.63
498 * dbus_free 0.71
499 *
500 * If you implement the message_cache with a list, the primary reason
501 * it's slower is that you add another thread lock (on the DBusList
502 * mempool).
503 */
504
506#define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
507
509#define MAX_MESSAGE_CACHE_SIZE 5
510
511/* Protected by _DBUS_LOCK (message_cache) */
512static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
513static int message_cache_count = 0;
514static dbus_bool_t message_cache_shutdown_registered = FALSE;
515
516static void
517dbus_message_cache_shutdown (void *data)
518{
519 int i;
520
521 if (!_DBUS_LOCK (message_cache))
522 _dbus_assert_not_reached ("we would have initialized global locks "
523 "before registering a shutdown function");
524
525 i = 0;
526 while (i < MAX_MESSAGE_CACHE_SIZE)
527 {
528 if (message_cache[i])
529 dbus_message_finalize (message_cache[i]);
530
531 ++i;
532 }
533
534 message_cache_count = 0;
535 message_cache_shutdown_registered = FALSE;
536
537 _DBUS_UNLOCK (message_cache);
538}
539
547static DBusMessage*
548dbus_message_get_cached (void)
549{
550 DBusMessage *message;
551 int i;
552
553 message = NULL;
554
555 if (!_DBUS_LOCK (message_cache))
556 {
557 /* we'd have initialized global locks before caching anything,
558 * so there can't be anything in the cache */
559 return NULL;
560 }
561
562 _dbus_assert (message_cache_count >= 0);
563
564 if (message_cache_count == 0)
565 {
566 _DBUS_UNLOCK (message_cache);
567 return NULL;
568 }
569
570 /* This is not necessarily true unless count > 0, and
571 * message_cache is uninitialized until the shutdown is
572 * registered
573 */
574 _dbus_assert (message_cache_shutdown_registered);
575
576 i = 0;
577 while (i < MAX_MESSAGE_CACHE_SIZE)
578 {
579 if (message_cache[i])
580 {
581 message = message_cache[i];
582 message_cache[i] = NULL;
583 message_cache_count -= 1;
584 break;
585 }
586 ++i;
587 }
588 _dbus_assert (message_cache_count >= 0);
590 _dbus_assert (message != NULL);
591
592 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
593
594 _dbus_assert (message->counters == NULL);
595
596 _DBUS_UNLOCK (message_cache);
597
598 return message;
599}
600
601#ifdef HAVE_UNIX_FD_PASSING
602static void
603close_unix_fds(int *fds, unsigned *n_fds)
604{
605 DBusError e;
606 unsigned int i;
607
608 if (*n_fds <= 0)
609 return;
610
611 dbus_error_init(&e);
612
613 for (i = 0; i < *n_fds; i++)
614 {
615 if (!_dbus_close(fds[i], &e))
616 {
617 _dbus_warn("Failed to close file descriptor: %s", e.message);
618 dbus_error_free(&e);
619 }
620 }
621
622 *n_fds = 0;
623
624 /* We don't free the array here, in case we can recycle it later */
625}
626#endif
627
628static void
629free_counter (void *element,
630 void *data)
631{
632 DBusCounter *counter = element;
633 DBusMessage *message = data;
634
635 _dbus_counter_adjust_size (counter, - message->size_counter_delta);
636#ifdef HAVE_UNIX_FD_PASSING
637 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
638#endif
639
640 _dbus_counter_notify (counter);
641 _dbus_counter_unref (counter);
642}
643
649static void
650dbus_message_cache_or_finalize (DBusMessage *message)
651{
652 dbus_bool_t was_cached;
653 int i;
654
655 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
656
657 /* This calls application code and has to be done first thing
658 * without holding the lock
659 */
661
662 _dbus_list_foreach (&message->counters,
663 free_counter, message);
664 _dbus_list_clear (&message->counters);
665
666#ifdef HAVE_UNIX_FD_PASSING
667 close_unix_fds(message->unix_fds, &message->n_unix_fds);
668#endif
669
670 was_cached = FALSE;
671
672 if (!_DBUS_LOCK (message_cache))
673 {
674 /* The only way to get a non-null message goes through
675 * dbus_message_get_cached() which takes the lock. */
676 _dbus_assert_not_reached ("we would have initialized global locks "
677 "the first time we constructed a message");
678 }
679
680 if (!message_cache_shutdown_registered)
681 {
682 _dbus_assert (message_cache_count == 0);
683
684 if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
685 goto out;
686
687 i = 0;
688 while (i < MAX_MESSAGE_CACHE_SIZE)
689 {
690 message_cache[i] = NULL;
691 ++i;
692 }
693
694 message_cache_shutdown_registered = TRUE;
695 }
696
697 _dbus_assert (message_cache_count >= 0);
698
699 if (!_dbus_enable_message_cache ())
700 goto out;
701
702 if ((_dbus_string_get_length (&message->header.data) +
703 _dbus_string_get_length (&message->body)) >
705 goto out;
706
707 if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
708 goto out;
709
710 /* Find empty slot */
711 i = 0;
712 while (message_cache[i] != NULL)
713 ++i;
714
716
717 _dbus_assert (message_cache[i] == NULL);
718 message_cache[i] = message;
719 message_cache_count += 1;
720 was_cached = TRUE;
721#ifndef DBUS_DISABLE_CHECKS
722 message->in_cache = TRUE;
723#endif
724
725 out:
726 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
727
728 _DBUS_UNLOCK (message_cache);
729
730 if (!was_cached)
731 dbus_message_finalize (message);
732}
733
734/*
735 * Arrange for iter to be something that _dbus_message_iter_check() would
736 * reject as not a valid iterator.
737 */
738static void
739_dbus_message_real_iter_zero (DBusMessageRealIter *iter)
740{
741 _dbus_assert (iter != NULL);
742 _DBUS_ZERO (*iter);
743 /* NULL is not, strictly speaking, guaranteed to be all-bits-zero */
744 iter->message = NULL;
745}
746
752void
754{
755 _dbus_return_if_fail (iter != NULL);
756 _dbus_message_real_iter_zero ((DBusMessageRealIter *) iter);
757}
758
759static dbus_bool_t
760_dbus_message_real_iter_is_zeroed (DBusMessageRealIter *iter)
761{
762 return (iter != NULL && iter->message == NULL && iter->changed_stamp == 0 &&
763 iter->iter_type == 0 && iter->sig_refcount == 0);
764}
765
766#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
767static dbus_bool_t
768_dbus_message_iter_check (DBusMessageRealIter *iter)
769{
770 char byte_order;
771
772 if (iter == NULL)
773 {
774 _dbus_warn_check_failed ("dbus message iterator is NULL");
775 return FALSE;
776 }
777
778 if (iter->message == NULL || iter->iter_type == 0)
779 {
780 _dbus_warn_check_failed ("dbus message iterator has already been "
781 "closed, or is uninitialized or corrupt");
782 return FALSE;
783 }
784
785 byte_order = _dbus_header_get_byte_order (&iter->message->header);
786
787 if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
788 {
789 if (iter->u.reader.byte_order != byte_order)
790 {
791 _dbus_warn_check_failed ("dbus message changed byte order since iterator was created");
792 return FALSE;
793 }
794 /* because we swap the message into compiler order when you init an iter */
795 _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
796 }
797 else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
798 {
799 if (iter->u.writer.byte_order != byte_order)
800 {
801 _dbus_warn_check_failed ("dbus message changed byte order since append iterator was created");
802 return FALSE;
803 }
804 /* because we swap the message into compiler order when you init an iter */
805 _dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
806 }
807 else
808 {
809 _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted");
810 return FALSE;
811 }
812
813 if (iter->changed_stamp != iter->message->changed_stamp)
814 {
815 _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)");
816 return FALSE;
817 }
818
819 return TRUE;
820}
821#endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */
822
837 DBusError *error,
838 int first_arg_type,
839 va_list var_args)
840{
842 int spec_type, msg_type, i, j;
843 dbus_bool_t retval;
844 va_list copy_args;
845
846 _dbus_assert (_dbus_message_iter_check (real));
847
848 retval = FALSE;
849
850 spec_type = first_arg_type;
851 i = 0;
852
853 /* copy var_args first, then we can do another iteration over it to
854 * free memory and close unix fds if parse failed at some point.
855 */
856 va_copy (copy_args, var_args);
857
858 while (spec_type != DBUS_TYPE_INVALID)
859 {
860 msg_type = dbus_message_iter_get_arg_type (iter);
861
862 if (msg_type != spec_type)
863 {
865 "Argument %d is specified to be of type \"%s\", but "
866 "is actually of type \"%s\"\n", i,
867 _dbus_type_to_string (spec_type),
868 _dbus_type_to_string (msg_type));
869
870 goto out;
871 }
872
873 if (spec_type == DBUS_TYPE_UNIX_FD)
874 {
875#ifdef HAVE_UNIX_FD_PASSING
876 DBusBasicValue idx;
877 int *pfd, nfd;
878
879 pfd = va_arg (var_args, int*);
880 _dbus_assert(pfd);
881
883
884 if (idx.u32 >= real->message->n_unix_fds)
885 {
887 "Message refers to file descriptor at index %i,"
888 "but has only %i descriptors attached.\n",
889 idx.u32,
890 real->message->n_unix_fds);
891 goto out;
892 }
893
894 if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
895 goto out;
896
897 *pfd = nfd;
898#else
900 "Platform does not support file desciptor passing.\n");
901 goto out;
902#endif
903 }
904 else if (dbus_type_is_basic (spec_type))
905 {
906 void *ptr;
907
908 ptr = va_arg (var_args, void *);
909
910 _dbus_assert (ptr != NULL);
911
913 ptr);
914 }
915 else if (spec_type == DBUS_TYPE_ARRAY)
916 {
917 int element_type;
918 int spec_element_type;
919 const void **ptr;
920 int *n_elements_p;
921 DBusTypeReader array;
922
923 spec_element_type = va_arg (var_args, int);
924 element_type = _dbus_type_reader_get_element_type (&real->u.reader);
925
926 if (spec_element_type != element_type)
927 {
929 "Argument %d is specified to be an array of \"%s\", but "
930 "is actually an array of \"%s\"\n",
931 i,
932 _dbus_type_to_string (spec_element_type),
933 _dbus_type_to_string (element_type));
934
935 goto out;
936 }
937
938 if (dbus_type_is_fixed (spec_element_type) &&
939 element_type != DBUS_TYPE_UNIX_FD)
940 {
941 ptr = va_arg (var_args, const void **);
942 n_elements_p = va_arg (var_args, int*);
943
944 _dbus_assert (ptr != NULL);
945 _dbus_assert (n_elements_p != NULL);
946
947 _dbus_type_reader_recurse (&real->u.reader, &array);
948
949 _dbus_type_reader_read_fixed_multi (&array, ptr, n_elements_p);
950 }
951 else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
952 {
953 char ***str_array_p;
954 int n_elements;
955 char **str_array;
956
957 str_array_p = va_arg (var_args, char***);
958 n_elements_p = va_arg (var_args, int*);
959
960 _dbus_assert (str_array_p != NULL);
961 _dbus_assert (n_elements_p != NULL);
962
963 /* Count elements in the array */
964 _dbus_type_reader_recurse (&real->u.reader, &array);
965
966 n_elements = 0;
968 {
969 ++n_elements;
970 _dbus_type_reader_next (&array);
971 }
972
973 str_array = dbus_new0 (char*, n_elements + 1);
974 if (str_array == NULL)
975 {
976 _DBUS_SET_OOM (error);
977 goto out;
978 }
979
980 /* Now go through and dup each string */
981 _dbus_type_reader_recurse (&real->u.reader, &array);
982
983 j = 0;
984 while (j < n_elements)
985 {
986 const char *s;
988 (void *) &s);
989
990 str_array[j] = _dbus_strdup (s);
991 if (str_array[j] == NULL)
992 {
993 dbus_free_string_array (str_array);
994 _DBUS_SET_OOM (error);
995 goto out;
996 }
997
998 ++j;
999
1000 if (!_dbus_type_reader_next (&array))
1001 _dbus_assert (j == n_elements);
1002 }
1003
1005 _dbus_assert (j == n_elements);
1006 _dbus_assert (str_array[j] == NULL);
1007
1008 *str_array_p = str_array;
1009 *n_elements_p = n_elements;
1010 }
1011#ifndef DBUS_DISABLE_CHECKS
1012 else
1013 {
1014 _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now",
1015 _DBUS_FUNCTION_NAME);
1016 goto out;
1017 }
1018#endif
1019 }
1020#ifndef DBUS_DISABLE_CHECKS
1021 else
1022 {
1023 _dbus_warn ("you can only read arrays and basic types with %s for now",
1024 _DBUS_FUNCTION_NAME);
1025 goto out;
1026 }
1027#endif
1028
1029 /* how many arguments already handled */
1030 i++;
1031
1032 spec_type = va_arg (var_args, int);
1033 if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
1034 {
1036 "Message has only %d arguments, but more were expected", i);
1037 goto out;
1038 }
1039 }
1040
1041 retval = TRUE;
1042
1043 out:
1044 /* there may memory or unix fd leak in the above iteration if parse failed.
1045 * so we have another iteration over copy_args to free memory and close
1046 * unix fds.
1047 */
1048 if (!retval)
1049 {
1050 spec_type = first_arg_type;
1051 j = 0;
1052
1053 while (j < i)
1054 {
1055 if (spec_type == DBUS_TYPE_UNIX_FD)
1056 {
1057#ifdef HAVE_UNIX_FD_PASSING
1058 int *pfd;
1059
1060 pfd = va_arg (copy_args, int *);
1061 _dbus_assert(pfd);
1062 if (*pfd >= 0)
1063 {
1064 _dbus_close (*pfd, NULL);
1065 *pfd = -1;
1066 }
1067#endif
1068 }
1069 else if (dbus_type_is_basic (spec_type))
1070 {
1071 /* move the index forward */
1072 va_arg (copy_args, const void *);
1073 }
1074 else if (spec_type == DBUS_TYPE_ARRAY)
1075 {
1076 int spec_element_type;
1077
1078 spec_element_type = va_arg (copy_args, int);
1079 if (dbus_type_is_fixed (spec_element_type))
1080 {
1081 /* move the index forward */
1082 va_arg (copy_args, const void **);
1083 va_arg (copy_args, int *);
1084 }
1085 else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
1086 {
1087 char ***str_array_p;
1088
1089 str_array_p = va_arg (copy_args, char ***);
1090 /* move the index forward */
1091 va_arg (copy_args, int *);
1092 _dbus_assert (str_array_p != NULL);
1093 dbus_free_string_array (*str_array_p);
1094 *str_array_p = NULL;
1095 }
1096 }
1097
1098 spec_type = va_arg (copy_args, int);
1099 j++;
1100 }
1101 }
1102
1103 va_end (copy_args);
1104 return retval;
1105}
1106
1167{
1168 _dbus_return_val_if_fail (message != NULL, 0);
1169
1170 return _dbus_header_get_serial (&message->header);
1171}
1172
1183 dbus_uint32_t reply_serial)
1184{
1185 DBusBasicValue value;
1186
1187 _dbus_return_val_if_fail (message != NULL, FALSE);
1188 _dbus_return_val_if_fail (!message->locked, FALSE);
1189 _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
1190
1191 value.u32 = reply_serial;
1192
1193 return _dbus_header_set_field_basic (&message->header,
1196 &value);
1197}
1198
1207{
1208 dbus_uint32_t v_UINT32;
1209
1210 _dbus_return_val_if_fail (message != NULL, 0);
1211
1212 if (_dbus_header_get_field_basic (&message->header,
1215 &v_UINT32))
1216 return v_UINT32;
1217 else
1218 return 0;
1219}
1220
1221static void
1222dbus_message_finalize (DBusMessage *message)
1223{
1224 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1225
1226 /* This calls application callbacks! */
1228
1229 _dbus_list_foreach (&message->counters,
1230 free_counter, message);
1231 _dbus_list_clear (&message->counters);
1232
1233 _dbus_header_free (&message->header);
1234 _dbus_string_free (&message->body);
1235
1236#ifdef HAVE_UNIX_FD_PASSING
1237 close_unix_fds(message->unix_fds, &message->n_unix_fds);
1238 dbus_free(message->unix_fds);
1239#endif
1240
1241 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1242
1243 dbus_free (message);
1244}
1245
1246static DBusMessage*
1247dbus_message_new_empty_header (void)
1248{
1249 DBusMessage *message;
1250 dbus_bool_t from_cache;
1251
1252 message = dbus_message_get_cached ();
1253
1254 if (message != NULL)
1255 {
1256 from_cache = TRUE;
1257 }
1258 else
1259 {
1260 from_cache = FALSE;
1261 message = dbus_new0 (DBusMessage, 1);
1262 if (message == NULL)
1263 return NULL;
1264#ifndef DBUS_DISABLE_CHECKS
1266#endif
1267
1268#ifdef HAVE_UNIX_FD_PASSING
1269 message->unix_fds = NULL;
1270 message->n_unix_fds_allocated = 0;
1271#endif
1272 }
1273
1274 _dbus_atomic_inc (&message->refcount);
1275
1276 _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
1277
1278 message->locked = FALSE;
1279#ifndef DBUS_DISABLE_CHECKS
1280 message->in_cache = FALSE;
1281#endif
1282 message->counters = NULL;
1283 message->size_counter_delta = 0;
1284 message->changed_stamp = 0;
1285
1286#ifdef HAVE_UNIX_FD_PASSING
1287 message->n_unix_fds = 0;
1288 message->n_unix_fds_allocated = 0;
1289 message->unix_fd_counter_delta = 0;
1290#endif
1291
1292 if (!from_cache)
1294
1295 if (from_cache)
1296 {
1297 _dbus_header_reinit (&message->header);
1298 _dbus_string_set_length (&message->body, 0);
1299 }
1300 else
1301 {
1302 if (!_dbus_header_init (&message->header))
1303 {
1304 dbus_free (message);
1305 return NULL;
1306 }
1307
1308 if (!_dbus_string_init_preallocated (&message->body, 32))
1309 {
1310 _dbus_header_free (&message->header);
1311 dbus_free (message);
1312 return NULL;
1313 }
1314 }
1315
1316 return message;
1317}
1318
1332dbus_message_new (int message_type)
1333{
1334 DBusMessage *message;
1335
1336 _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
1337
1338 message = dbus_message_new_empty_header ();
1339 if (message == NULL)
1340 return NULL;
1341
1342 if (!_dbus_header_create (&message->header,
1343 DBUS_COMPILER_BYTE_ORDER,
1344 message_type,
1345 NULL, NULL, NULL, NULL, NULL))
1346 {
1347 dbus_message_unref (message);
1348 return NULL;
1349 }
1350
1351 return message;
1352}
1353
1376dbus_message_new_method_call (const char *destination,
1377 const char *path,
1378 const char *iface,
1379 const char *method)
1380{
1381 DBusMessage *message;
1382
1383 _dbus_return_val_if_fail (path != NULL, NULL);
1384 _dbus_return_val_if_fail (method != NULL, NULL);
1385 _dbus_return_val_if_fail (destination == NULL ||
1386 _dbus_check_is_valid_bus_name (destination), NULL);
1387 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1388 _dbus_return_val_if_fail (iface == NULL ||
1389 _dbus_check_is_valid_interface (iface), NULL);
1390 _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
1391
1392 message = dbus_message_new_empty_header ();
1393 if (message == NULL)
1394 return NULL;
1395
1396 if (!_dbus_header_create (&message->header,
1397 DBUS_COMPILER_BYTE_ORDER,
1399 destination, path, iface, method, NULL))
1400 {
1401 dbus_message_unref (message);
1402 return NULL;
1403 }
1404
1405 return message;
1406}
1407
1417{
1418 DBusMessage *message;
1419 const char *sender;
1420
1421 _dbus_return_val_if_fail (method_call != NULL, NULL);
1422
1423 sender = dbus_message_get_sender (method_call);
1424
1425 /* sender is allowed to be null here in peer-to-peer case */
1426
1427 message = dbus_message_new_empty_header ();
1428 if (message == NULL)
1429 return NULL;
1430
1431 if (!_dbus_header_create (&message->header,
1432 DBUS_COMPILER_BYTE_ORDER,
1434 sender, NULL, NULL, NULL, NULL))
1435 {
1436 dbus_message_unref (message);
1437 return NULL;
1438 }
1439
1441
1442 if (!dbus_message_set_reply_serial (message,
1443 dbus_message_get_serial (method_call)))
1444 {
1445 dbus_message_unref (message);
1446 return NULL;
1447 }
1448
1449 return message;
1450}
1451
1467dbus_message_new_signal (const char *path,
1468 const char *iface,
1469 const char *name)
1470{
1471 DBusMessage *message;
1472
1473 _dbus_return_val_if_fail (path != NULL, NULL);
1474 _dbus_return_val_if_fail (iface != NULL, NULL);
1475 _dbus_return_val_if_fail (name != NULL, NULL);
1476 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1477 _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
1478 _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
1479
1480 message = dbus_message_new_empty_header ();
1481 if (message == NULL)
1482 return NULL;
1483
1484 if (!_dbus_header_create (&message->header,
1485 DBUS_COMPILER_BYTE_ORDER,
1487 NULL, path, iface, name, NULL))
1488 {
1489 dbus_message_unref (message);
1490 return NULL;
1491 }
1492
1494
1495 return message;
1496}
1497
1514 const char *error_name,
1515 const char *error_message)
1516{
1517 DBusMessage *message;
1518 const char *sender;
1519 DBusMessageIter iter;
1520
1521 _dbus_return_val_if_fail (reply_to != NULL, NULL);
1522 _dbus_return_val_if_fail (error_name != NULL, NULL);
1523 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1524
1525 sender = dbus_message_get_sender (reply_to);
1526
1527 /* sender may be NULL for non-message-bus case or
1528 * when the message bus is dealing with an unregistered
1529 * connection.
1530 */
1531 message = dbus_message_new_empty_header ();
1532 if (message == NULL)
1533 return NULL;
1534
1535 if (!_dbus_header_create (&message->header,
1536 DBUS_COMPILER_BYTE_ORDER,
1538 sender, NULL, NULL, NULL, error_name))
1539 {
1540 dbus_message_unref (message);
1541 return NULL;
1542 }
1543
1545
1546 if (!dbus_message_set_reply_serial (message,
1547 dbus_message_get_serial (reply_to)))
1548 {
1549 dbus_message_unref (message);
1550 return NULL;
1551 }
1552
1553 if (error_message != NULL)
1554 {
1555 dbus_message_iter_init_append (message, &iter);
1558 &error_message))
1559 {
1560 dbus_message_unref (message);
1561 return NULL;
1562 }
1563 }
1564
1565 return message;
1566}
1567
1586 const char *error_name,
1587 const char *error_format,
1588 ...)
1589{
1590 va_list args;
1591 DBusString str;
1592 DBusMessage *message;
1593
1594 _dbus_return_val_if_fail (reply_to != NULL, NULL);
1595 _dbus_return_val_if_fail (error_name != NULL, NULL);
1596 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1597
1598 if (!_dbus_string_init (&str))
1599 return NULL;
1600
1601 va_start (args, error_format);
1602
1603 if (_dbus_string_append_printf_valist (&str, error_format, args))
1604 message = dbus_message_new_error (reply_to, error_name,
1606 else
1607 message = NULL;
1608
1609 _dbus_string_free (&str);
1610
1611 va_end (args);
1612
1613 return message;
1614}
1615
1616
1631{
1632 DBusMessage *retval;
1633
1634 _dbus_return_val_if_fail (message != NULL, NULL);
1635
1636 retval = dbus_new0 (DBusMessage, 1);
1637 if (retval == NULL)
1638 return NULL;
1639
1640 _dbus_atomic_inc (&retval->refcount);
1641
1642 retval->locked = FALSE;
1643#ifndef DBUS_DISABLE_CHECKS
1644 retval->generation = message->generation;
1645#endif
1646
1647 if (!_dbus_header_copy (&message->header, &retval->header))
1648 {
1649 dbus_free (retval);
1650 return NULL;
1651 }
1652
1653 if (!_dbus_string_init_preallocated (&retval->body,
1654 _dbus_string_get_length (&message->body)))
1655 {
1656 _dbus_header_free (&retval->header);
1657 dbus_free (retval);
1658 return NULL;
1659 }
1660
1661 if (!_dbus_string_copy (&message->body, 0,
1662 &retval->body, 0))
1663 goto failed_copy;
1664
1665#ifdef HAVE_UNIX_FD_PASSING
1666 retval->unix_fds = dbus_new(int, message->n_unix_fds);
1667 if (retval->unix_fds == NULL && message->n_unix_fds > 0)
1668 goto failed_copy;
1669
1670 retval->n_unix_fds_allocated = message->n_unix_fds;
1671
1672 for (retval->n_unix_fds = 0;
1673 retval->n_unix_fds < message->n_unix_fds;
1674 retval->n_unix_fds++)
1675 {
1676 retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
1677
1678 if (retval->unix_fds[retval->n_unix_fds] < 0)
1679 goto failed_copy;
1680 }
1681
1682#endif
1683
1684 _dbus_message_trace_ref (retval, 0, 1, "copy");
1685 return retval;
1686
1687 failed_copy:
1688 _dbus_header_free (&retval->header);
1689 _dbus_string_free (&retval->body);
1690
1691#ifdef HAVE_UNIX_FD_PASSING
1692 close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
1693 dbus_free(retval->unix_fds);
1694#endif
1695
1696 dbus_free (retval);
1697
1698 return NULL;
1699}
1700
1701
1711{
1712 dbus_int32_t old_refcount;
1713
1714 _dbus_return_val_if_fail (message != NULL, NULL);
1715 _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
1716 _dbus_return_val_if_fail (!message->in_cache, NULL);
1717
1718 old_refcount = _dbus_atomic_inc (&message->refcount);
1719 _dbus_assert (old_refcount >= 1);
1720 _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
1721
1722 return message;
1723}
1724
1732void
1734{
1735 dbus_int32_t old_refcount;
1736
1737 _dbus_return_if_fail (message != NULL);
1738 _dbus_return_if_fail (message->generation == _dbus_current_generation);
1739 _dbus_return_if_fail (!message->in_cache);
1740
1741 old_refcount = _dbus_atomic_dec (&message->refcount);
1742
1743 _dbus_assert (old_refcount >= 1);
1744
1745 _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
1746
1747 if (old_refcount == 1)
1748 {
1749 /* Calls application callbacks! */
1750 dbus_message_cache_or_finalize (message);
1751 }
1752}
1753
1764int
1766{
1767 _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
1768
1769 return _dbus_header_get_message_type (&message->header);
1770}
1771
1842 int first_arg_type,
1843 ...)
1844{
1845 dbus_bool_t retval;
1846 va_list var_args;
1847
1848 _dbus_return_val_if_fail (message != NULL, FALSE);
1849
1850 va_start (var_args, first_arg_type);
1851 retval = dbus_message_append_args_valist (message,
1852 first_arg_type,
1853 var_args);
1854 va_end (var_args);
1855
1856 return retval;
1857}
1858
1874 int first_arg_type,
1875 va_list var_args)
1876{
1877 int type;
1878 DBusMessageIter iter;
1879
1880 _dbus_return_val_if_fail (message != NULL, FALSE);
1881
1882 type = first_arg_type;
1883
1884 dbus_message_iter_init_append (message, &iter);
1885
1886 while (type != DBUS_TYPE_INVALID)
1887 {
1888 if (dbus_type_is_basic (type))
1889 {
1890 const void *value;
1891 value = va_arg (var_args, const void *);
1892
1894 type,
1895 value))
1896 goto failed;
1897 }
1898 else if (type == DBUS_TYPE_ARRAY)
1899 {
1900 int element_type;
1901 DBusMessageIter array;
1902 char buf[2];
1903
1904 element_type = va_arg (var_args, int);
1905
1906 buf[0] = element_type;
1907 buf[1] = '\0';
1910 buf,
1911 &array))
1912 goto failed;
1913
1914 if (dbus_type_is_fixed (element_type) &&
1915 element_type != DBUS_TYPE_UNIX_FD)
1916 {
1917 const void **value;
1918 int n_elements;
1919
1920 value = va_arg (var_args, const void **);
1921 n_elements = va_arg (var_args, int);
1922
1924 element_type,
1925 value,
1926 n_elements)) {
1928 goto failed;
1929 }
1930 }
1931 else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
1932 {
1933 const char ***value_p;
1934 const char **value;
1935 int n_elements;
1936 int i;
1937
1938 value_p = va_arg (var_args, const char***);
1939 n_elements = va_arg (var_args, int);
1940
1941 value = *value_p;
1942
1943 i = 0;
1944 while (i < n_elements)
1945 {
1946 if (!dbus_message_iter_append_basic (&array,
1947 element_type,
1948 &value[i])) {
1950 goto failed;
1951 }
1952 ++i;
1953 }
1954 }
1955 else
1956 {
1957 _dbus_warn ("arrays of %s can't be appended with %s for now",
1958 _dbus_type_to_string (element_type),
1959 _DBUS_FUNCTION_NAME);
1961 goto failed;
1962 }
1963
1964 if (!dbus_message_iter_close_container (&iter, &array))
1965 goto failed;
1966 }
1967#ifndef DBUS_DISABLE_CHECKS
1968 else
1969 {
1970 _dbus_warn ("type %s isn't supported yet in %s",
1971 _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
1972 goto failed;
1973 }
1974#endif
1975
1976 type = va_arg (var_args, int);
1977 }
1978
1979 return TRUE;
1980
1981 failed:
1982 return FALSE;
1983}
1984
2031 DBusError *error,
2032 int first_arg_type,
2033 ...)
2034{
2035 dbus_bool_t retval;
2036 va_list var_args;
2037
2038 _dbus_return_val_if_fail (message != NULL, FALSE);
2039 _dbus_return_val_if_error_is_set (error, FALSE);
2040
2041 va_start (var_args, first_arg_type);
2042 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
2043 va_end (var_args);
2044
2045 return retval;
2046}
2047
2060 DBusError *error,
2061 int first_arg_type,
2062 va_list var_args)
2063{
2064 DBusMessageIter iter;
2065
2066 _dbus_return_val_if_fail (message != NULL, FALSE);
2067 _dbus_return_val_if_error_is_set (error, FALSE);
2068
2069 dbus_message_iter_init (message, &iter);
2070 return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
2071}
2072
2073static void
2074_dbus_message_iter_init_common (DBusMessage *message,
2075 DBusMessageRealIter *real,
2076 int iter_type)
2077{
2078 /* If these static assertions fail on your platform, report it as a bug. */
2079 _DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
2080 _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <=
2081 _DBUS_ALIGNOF (DBusMessageIter));
2082#if CHECK_DBUS_1_10_BINARY_COMPATIBILITY
2083 /* A failure of these two assertions would indicate that we've broken
2084 * ABI on this platform since 1.10.0. */
2085 _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) ==
2086 sizeof (DBusMessageIter));
2087 _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) ==
2088 _DBUS_ALIGNOF (DBusMessageIter));
2089#endif
2090 /* If this static assertion fails, it means the DBusMessageIter struct
2091 * is not "packed", which might result in "iter = other_iter" not copying
2092 * every byte. */
2093#if DBUS_SIZEOF_VOID_P > 8
2094 _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) == 16 * sizeof (void *));
2095#else
2096 _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) ==
2097 4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int));
2098#endif
2099
2100 /* Since the iterator will read or write who-knows-what from the
2101 * message, we need to get in the right byte order
2102 */
2103 ensure_byte_order (message);
2104
2105 real->message = message;
2106 real->changed_stamp = message->changed_stamp;
2107 real->iter_type = iter_type;
2108 real->sig_refcount = 0;
2109}
2110
2135 DBusMessageIter *iter)
2136{
2138 const DBusString *type_str;
2139 int type_pos;
2140
2141 _dbus_return_val_if_fail (message != NULL, FALSE);
2142 _dbus_return_val_if_fail (iter != NULL, FALSE);
2143
2144 get_const_signature (&message->header, &type_str, &type_pos);
2145
2146 _dbus_message_iter_init_common (message, real,
2147 DBUS_MESSAGE_ITER_TYPE_READER);
2148
2151 type_str, type_pos,
2152 &message->body,
2153 0);
2154
2156}
2157
2166{
2168
2169 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2170 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2171
2172 return _dbus_type_reader_has_next (&real->u.reader);
2173}
2174
2185{
2187
2188 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2189 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2190
2191 return _dbus_type_reader_next (&real->u.reader);
2192}
2193
2208int
2210{
2212
2213 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2214 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2215
2217}
2218
2227int
2229{
2231
2232 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2233 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
2234 _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
2235
2237}
2238
2264void
2266 DBusMessageIter *sub)
2267{
2269 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2270
2271 _dbus_return_if_fail (_dbus_message_iter_check (real));
2272 _dbus_return_if_fail (sub != NULL);
2273
2274 *real_sub = *real;
2275 _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
2276}
2277
2289char *
2291{
2292 const DBusString *sig;
2293 DBusString retstr;
2294 char *ret;
2295 int start, len;
2297
2298 _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
2299
2300 if (!_dbus_string_init (&retstr))
2301 return NULL;
2302
2304 &start, &len);
2305 if (!_dbus_string_append_len (&retstr,
2306 _dbus_string_get_const_data (sig) + start,
2307 len))
2308 return NULL;
2309 if (!_dbus_string_steal_data (&retstr, &ret))
2310 return NULL;
2311 _dbus_string_free (&retstr);
2312 return ret;
2313}
2314
2362void
2364 void *value)
2365{
2367
2368 _dbus_return_if_fail (_dbus_message_iter_check (real));
2369 _dbus_return_if_fail (value != NULL);
2370
2372 {
2373#ifdef HAVE_UNIX_FD_PASSING
2374 DBusBasicValue idx;
2375
2377
2378 if (idx.u32 >= real->message->n_unix_fds) {
2379 /* Hmm, we cannot really signal an error here, so let's make
2380 sure to return an invalid fd. */
2381 *((int*) value) = -1;
2382 return;
2383 }
2384
2385 *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
2386#else
2387 *((int*) value) = -1;
2388#endif
2389 }
2390 else
2391 {
2393 value);
2394 }
2395}
2396
2407int
2409{
2411 DBusTypeReader array;
2412 int element_type;
2413 int n_elements = 0;
2414
2415 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2416 _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
2417 == DBUS_TYPE_ARRAY, 0);
2418
2419 element_type = _dbus_type_reader_get_element_type (&real->u.reader);
2420 _dbus_type_reader_recurse (&real->u.reader, &array);
2421 if (dbus_type_is_fixed (element_type))
2422 {
2423 int alignment = _dbus_type_get_alignment (element_type);
2424 int total_len = _dbus_type_reader_get_array_length (&array);
2425 n_elements = total_len / alignment;
2426 }
2427 else
2428 {
2430 {
2431 ++n_elements;
2432 _dbus_type_reader_next (&array);
2433 }
2434 }
2435
2436 return n_elements;
2437}
2438
2451int
2453{
2455
2456 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2457
2459}
2460
2496void
2498 void *value,
2499 int *n_elements)
2500{
2502#ifndef DBUS_DISABLE_CHECKS
2503 int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
2504
2505 _dbus_return_if_fail (_dbus_message_iter_check (real));
2506 _dbus_return_if_fail (value != NULL);
2507 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
2508 (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
2509#endif
2510
2512 value, n_elements);
2513}
2514
2526void
2528 DBusMessageIter *iter)
2529{
2531
2532 _dbus_return_if_fail (message != NULL);
2533 _dbus_return_if_fail (iter != NULL);
2534
2535 _dbus_message_iter_init_common (message, real,
2536 DBUS_MESSAGE_ITER_TYPE_WRITER);
2537
2538 /* We create the signature string and point iterators at it "on demand"
2539 * when a value is actually appended. That means that init() never fails
2540 * due to OOM.
2541 */
2544 &message->body,
2545 _dbus_string_get_length (&message->body));
2546}
2547
2556static dbus_bool_t
2557_dbus_message_iter_open_signature (DBusMessageRealIter *real)
2558{
2559 DBusString *str;
2560 const DBusString *current_sig;
2561 int current_sig_pos;
2562
2563 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2564
2565 if (real->u.writer.type_str != NULL)
2566 {
2567 _dbus_assert (real->sig_refcount > 0);
2568 real->sig_refcount += 1;
2569 return TRUE;
2570 }
2571
2572 str = dbus_new (DBusString, 1);
2573 if (str == NULL)
2574 return FALSE;
2575
2578 &current_sig, &current_sig_pos))
2579 current_sig = NULL;
2580
2581 if (current_sig)
2582 {
2583 int current_len;
2584
2585 current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
2586 current_sig_pos += 1; /* move on to sig data */
2587
2588 if (!_dbus_string_init_preallocated (str, current_len + 4))
2589 {
2590 dbus_free (str);
2591 return FALSE;
2592 }
2593
2594 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
2595 str, 0))
2596 {
2597 _dbus_string_free (str);
2598 dbus_free (str);
2599 return FALSE;
2600 }
2601 }
2602 else
2603 {
2604 if (!_dbus_string_init_preallocated (str, 4))
2605 {
2606 dbus_free (str);
2607 return FALSE;
2608 }
2609 }
2610
2611 real->sig_refcount = 1;
2612
2613 /* If this assertion failed, then str would be neither stored in u.writer
2614 * nor freed by this function, resulting in a memory leak. */
2615 _dbus_assert (real->u.writer.type_str == NULL);
2617 str, _dbus_string_get_length (str));
2618 return TRUE;
2619}
2620
2630static dbus_bool_t
2631_dbus_message_iter_close_signature (DBusMessageRealIter *real)
2632{
2633 DBusString *str;
2634 const char *v_STRING;
2635 dbus_bool_t retval;
2636
2637 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2638 _dbus_assert (real->u.writer.type_str != NULL);
2639 _dbus_assert (real->sig_refcount > 0);
2640
2641 real->sig_refcount -= 1;
2642
2643 if (real->sig_refcount > 0)
2644 return TRUE;
2645 _dbus_assert (real->sig_refcount == 0);
2646
2647 retval = TRUE;
2648
2649 str = real->u.writer.type_str;
2650
2651 v_STRING = _dbus_string_get_const_data (str);
2655 &v_STRING))
2656 retval = FALSE;
2657
2659 _dbus_string_free (str);
2660 dbus_free (str);
2661
2662 return retval;
2663}
2664
2672static void
2673_dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
2674{
2675 DBusString *str;
2676
2677 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2678 _dbus_assert (real->u.writer.type_str != NULL);
2679 _dbus_assert (real->sig_refcount > 0);
2680
2681 real->sig_refcount -= 1;
2682
2683 if (real->sig_refcount > 0)
2684 return;
2685 _dbus_assert (real->sig_refcount == 0);
2686
2687 str = real->u.writer.type_str;
2688
2690 _dbus_string_free (str);
2691 dbus_free (str);
2692}
2693
2694#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
2695static dbus_bool_t
2696_dbus_message_iter_append_check (DBusMessageRealIter *iter)
2697{
2698 if (!_dbus_message_iter_check (iter))
2699 return FALSE;
2700
2701 if (iter->message->locked)
2702 {
2703 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)");
2704 return FALSE;
2705 }
2706
2707 return TRUE;
2708}
2709#endif
2710
2711#ifdef HAVE_UNIX_FD_PASSING
2712static int *
2713expand_fd_array(DBusMessage *m,
2714 unsigned n)
2715{
2716 _dbus_assert(m);
2717
2718 /* This makes space for adding n new fds to the array and returns a
2719 pointer to the place were the first fd should be put. */
2720
2721 if (m->n_unix_fds + n > m->n_unix_fds_allocated)
2722 {
2723 unsigned k;
2724 int *p;
2725
2726 /* Make twice as much space as necessary */
2727 k = (m->n_unix_fds + n) * 2;
2728
2729 /* Allocate at least four */
2730 if (k < 4)
2731 k = 4;
2732
2733 p = dbus_realloc(m->unix_fds, k * sizeof(int));
2734 if (p == NULL)
2735 return NULL;
2736
2737 m->unix_fds = p;
2738 m->n_unix_fds_allocated = k;
2739 }
2740
2741 return m->unix_fds + m->n_unix_fds;
2742}
2743#endif
2744
2766 int type,
2767 const void *value)
2768{
2770 dbus_bool_t ret;
2771
2772 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2773 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2774 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
2775 _dbus_return_val_if_fail (value != NULL, FALSE);
2776
2777#ifndef DBUS_DISABLE_CHECKS
2778 switch (type)
2779 {
2780 DBusString str;
2781 DBusValidity signature_validity;
2782 const char * const *string_p;
2783 const dbus_bool_t *bool_p;
2784
2785 case DBUS_TYPE_STRING:
2786 string_p = value;
2787 _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
2788 break;
2789
2791 string_p = value;
2792 _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
2793 break;
2794
2796 string_p = value;
2797 _dbus_string_init_const (&str, *string_p);
2798 signature_validity = _dbus_validate_signature_with_reason (&str,
2799 0,
2801
2802 if (signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
2803 return FALSE;
2804
2805 _dbus_return_val_if_fail (signature_validity == DBUS_VALID, FALSE);
2806 break;
2807
2808 case DBUS_TYPE_BOOLEAN:
2809 bool_p = value;
2810 _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
2811 break;
2812
2813 default:
2814 {
2815 /* nothing to check, all possible values are allowed */
2816 }
2817 }
2818#endif
2819
2820 if (!_dbus_message_iter_open_signature (real))
2821 return FALSE;
2822
2823 if (type == DBUS_TYPE_UNIX_FD)
2824 {
2825#ifdef HAVE_UNIX_FD_PASSING
2826 int *fds;
2827 dbus_uint32_t u;
2828
2829 ret = FALSE;
2830
2831 /* First step, include the fd in the fd list of this message */
2832 if (!(fds = expand_fd_array(real->message, 1)))
2833 goto out;
2834
2835 *fds = _dbus_dup(*(int*) value, NULL);
2836 if (*fds < 0)
2837 goto out;
2838
2839 u = real->message->n_unix_fds;
2840
2841 /* Second step, write the index to the fd */
2842 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
2843 _dbus_close(*fds, NULL);
2844 goto out;
2845 }
2846
2847 real->message->n_unix_fds += 1;
2848 u += 1;
2849
2850 /* Final step, update the header accordingly */
2854 &u);
2855
2856 /* If any of these operations fail the message is
2857 hosed. However, no memory or fds should be leaked since what
2858 has been added to message has been added to the message, and
2859 can hence be accounted for when the message is being
2860 freed. */
2861#else
2862 ret = FALSE;
2863 /* This is redundant (we could just fall through), but it avoids
2864 * -Wunused-label in builds that don't HAVE_UNIX_FD_PASSING */
2865 goto out;
2866#endif
2867 }
2868 else
2869 {
2870 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
2871 }
2872
2873out:
2874 if (!_dbus_message_iter_close_signature (real))
2875 ret = FALSE;
2876
2877 return ret;
2878}
2879
2917 int element_type,
2918 const void *value,
2919 int n_elements)
2920{
2922 dbus_bool_t ret;
2923
2924 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2925 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2926 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
2927 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
2928 _dbus_return_val_if_fail (value != NULL, FALSE);
2929 _dbus_return_val_if_fail (n_elements >= 0, FALSE);
2930 _dbus_return_val_if_fail (n_elements <=
2932 FALSE);
2933
2934#ifndef DBUS_DISABLE_CHECKS
2935 if (element_type == DBUS_TYPE_BOOLEAN)
2936 {
2937 const dbus_bool_t * const *bools = value;
2938 int i;
2939
2940 for (i = 0; i < n_elements; i++)
2941 {
2942 _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
2943 }
2944 }
2945#endif
2946
2947 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
2948
2949 return ret;
2950}
2951
2981 int type,
2982 const char *contained_signature,
2983 DBusMessageIter *sub)
2984{
2986 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2987 DBusString contained_str;
2988 DBusValidity contained_signature_validity;
2989 dbus_bool_t ret;
2990
2991 _dbus_return_val_if_fail (sub != NULL, FALSE);
2992 /* Do our best to make sure the sub-iterator doesn't contain something
2993 * valid-looking on failure */
2994 _dbus_message_real_iter_zero (real_sub);
2995
2996 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2997 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2998 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
2999 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
3000 contained_signature == NULL) ||
3001 (type == DBUS_TYPE_DICT_ENTRY &&
3002 contained_signature == NULL) ||
3003 (type == DBUS_TYPE_VARIANT &&
3004 contained_signature != NULL) ||
3005 (type == DBUS_TYPE_ARRAY &&
3006 contained_signature != NULL), FALSE);
3007
3008 /* this would fail if the contained_signature is a dict entry, since
3009 * dict entries are invalid signatures standalone (they must be in
3010 * an array)
3011 */
3012 if (contained_signature != NULL)
3013 {
3014 _dbus_string_init_const (&contained_str, contained_signature);
3015 contained_signature_validity = _dbus_validate_signature_with_reason (&contained_str,
3016 0,
3017 _dbus_string_get_length (&contained_str));
3018
3019 if (contained_signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
3020 return FALSE;
3021 }
3022 else
3023 {
3024 /* just some placeholder value */
3025 contained_signature_validity = DBUS_VALID_BUT_INCOMPLETE;
3026 }
3027
3028 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
3029 contained_signature == NULL ||
3030 contained_signature_validity == DBUS_VALID,
3031 FALSE);
3032
3033 if (!_dbus_message_iter_open_signature (real))
3034 return FALSE;
3035
3036 ret = FALSE;
3037 *real_sub = *real;
3038
3039 if (contained_signature != NULL)
3040 {
3041 _dbus_string_init_const (&contained_str, contained_signature);
3042
3043 ret = _dbus_type_writer_recurse (&real->u.writer,
3044 type,
3045 &contained_str, 0,
3046 &real_sub->u.writer);
3047 }
3048 else
3049 {
3050 ret = _dbus_type_writer_recurse (&real->u.writer,
3051 type,
3052 NULL, 0,
3053 &real_sub->u.writer);
3054 }
3055
3056 if (!ret)
3057 _dbus_message_iter_abandon_signature (real);
3058
3059 return ret;
3060}
3061
3062
3084 DBusMessageIter *sub)
3085{
3087 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3088 dbus_bool_t ret;
3089
3090 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
3091 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3092 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
3093 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3094
3095 ret = _dbus_type_writer_unrecurse (&real->u.writer,
3096 &real_sub->u.writer);
3097 _dbus_message_real_iter_zero (real_sub);
3098
3099 if (!_dbus_message_iter_close_signature (real))
3100 ret = FALSE;
3101
3102 return ret;
3103}
3104
3116void
3118 DBusMessageIter *sub)
3119{
3121 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3122
3123#ifndef DBUS_DISABLE_CHECKS
3124 _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3125 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3126 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3127 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3128#endif
3129
3130 _dbus_message_iter_abandon_signature (real);
3131 _dbus_message_real_iter_zero (real_sub);
3132}
3133
3175void
3177 DBusMessageIter *sub)
3178{
3180 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3181
3182 /* If both the parent and the child are zeroed out, then either we didn't
3183 * even get as far as successfully recursing into the parent, or we already
3184 * closed both the child and the parent. For example, in the code sample
3185 * in the doc-comment above, this happens for
3186 * abandon_container_if_open (&outer, &inner) if the first open_container
3187 * call failed, or if we reached result = TRUE and fell through. */
3188 if (_dbus_message_real_iter_is_zeroed (real) &&
3189 _dbus_message_real_iter_is_zeroed (real_sub))
3190 return;
3191
3192#ifndef DBUS_DISABLE_CHECKS
3193 /* If the child is not zeroed out, but the parent is, then something has
3194 * gone horribly wrong (in practice that would probably mean both are
3195 * uninitialized or corrupt, and the parent happens to have ended up
3196 * all-bytes-zero). */
3197 _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3198 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3199#endif
3200
3201 /* If the parent is not zeroed out, but the child is, then either we did
3202 * not successfully open the child, or we already closed the child. This
3203 * means we do not own a reference to the parent's signature, so it would
3204 * be wrong to release it; so we must not call abandon_signature() here.
3205 * In the code sample in the doc-comment above, this happens for
3206 * abandon_container_if_open (&outer, &inner) if the second open_container
3207 * call failed, or if the second close_container call failed. */
3208 if (_dbus_message_real_iter_is_zeroed (real_sub))
3209 return;
3210
3211#ifndef DBUS_DISABLE_CHECKS
3212 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3213 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3214#endif
3215
3216 /* If neither the parent nor the child is zeroed out, then we genuinely
3217 * have an open container; close it. In the code sample in the doc-comment,
3218 * this happens for abandon_container_if_open (&outer, &inner) if the
3219 * append_basic call failed. */
3220 _dbus_message_iter_abandon_signature (real);
3221 _dbus_message_real_iter_zero (real_sub);
3222}
3223
3240void
3242 dbus_bool_t no_reply)
3243{
3244 _dbus_return_if_fail (message != NULL);
3245 _dbus_return_if_fail (!message->locked);
3246
3249 no_reply);
3250}
3251
3261{
3262 _dbus_return_val_if_fail (message != NULL, FALSE);
3263
3264 return _dbus_header_get_flag (&message->header,
3266}
3267
3282void
3284 dbus_bool_t auto_start)
3285{
3286 _dbus_return_if_fail (message != NULL);
3287 _dbus_return_if_fail (!message->locked);
3288
3291 !auto_start);
3292}
3293
3303{
3304 _dbus_return_val_if_fail (message != NULL, FALSE);
3305
3306 return !_dbus_header_get_flag (&message->header,
3308}
3309
3310
3325 const char *object_path)
3326{
3327 _dbus_return_val_if_fail (message != NULL, FALSE);
3328 _dbus_return_val_if_fail (!message->locked, FALSE);
3329 _dbus_return_val_if_fail (object_path == NULL ||
3330 _dbus_check_is_valid_path (object_path),
3331 FALSE);
3332
3333 return set_or_delete_string_field (message,
3336 object_path);
3337}
3338
3352const char*
3354{
3355 const char *v;
3356
3357 _dbus_return_val_if_fail (message != NULL, NULL);
3358
3359 v = NULL; /* in case field doesn't exist */
3363 (void *) &v);
3364 return v;
3365}
3366
3378 const char *path)
3379{
3380 const char *msg_path;
3381 msg_path = dbus_message_get_path (message);
3382
3383 if (msg_path == NULL)
3384 {
3385 if (path == NULL)
3386 return TRUE;
3387 else
3388 return FALSE;
3389 }
3390
3391 if (path == NULL)
3392 return FALSE;
3393
3394 if (strcmp (msg_path, path) == 0)
3395 return TRUE;
3396
3397 return FALSE;
3398}
3399
3422 char ***path)
3423{
3424 const char *v;
3425
3426 _dbus_return_val_if_fail (message != NULL, FALSE);
3427 _dbus_return_val_if_fail (path != NULL, FALSE);
3428
3429 *path = NULL;
3430
3431 v = dbus_message_get_path (message);
3432 if (v != NULL)
3433 {
3434 if (!_dbus_decompose_path (v, strlen (v),
3435 path, NULL))
3436 return FALSE;
3437 }
3438 return TRUE;
3439}
3440
3456 const char *iface)
3457{
3458 _dbus_return_val_if_fail (message != NULL, FALSE);
3459 _dbus_return_val_if_fail (!message->locked, FALSE);
3460 _dbus_return_val_if_fail (iface == NULL ||
3461 _dbus_check_is_valid_interface (iface),
3462 FALSE);
3463
3464 return set_or_delete_string_field (message,
3467 iface);
3468}
3469
3483const char*
3485{
3486 const char *v;
3487
3488 _dbus_return_val_if_fail (message != NULL, NULL);
3489
3490 v = NULL; /* in case field doesn't exist */
3494 (void *) &v);
3495 return v;
3496}
3497
3507 const char *iface)
3508{
3509 const char *msg_interface;
3510 msg_interface = dbus_message_get_interface (message);
3511
3512 if (msg_interface == NULL)
3513 {
3514 if (iface == NULL)
3515 return TRUE;
3516 else
3517 return FALSE;
3518 }
3519
3520 if (iface == NULL)
3521 return FALSE;
3522
3523 if (strcmp (msg_interface, iface) == 0)
3524 return TRUE;
3525
3526 return FALSE;
3527
3528}
3529
3544 const char *member)
3545{
3546 _dbus_return_val_if_fail (message != NULL, FALSE);
3547 _dbus_return_val_if_fail (!message->locked, FALSE);
3548 _dbus_return_val_if_fail (member == NULL ||
3549 _dbus_check_is_valid_member (member),
3550 FALSE);
3551
3552 return set_or_delete_string_field (message,
3555 member);
3556}
3557
3569const char*
3571{
3572 const char *v;
3573
3574 _dbus_return_val_if_fail (message != NULL, NULL);
3575
3576 v = NULL; /* in case field doesn't exist */
3580 (void *) &v);
3581 return v;
3582}
3583
3593 const char *member)
3594{
3595 const char *msg_member;
3596 msg_member = dbus_message_get_member (message);
3597
3598 if (msg_member == NULL)
3599 {
3600 if (member == NULL)
3601 return TRUE;
3602 else
3603 return FALSE;
3604 }
3605
3606 if (member == NULL)
3607 return FALSE;
3608
3609 if (strcmp (msg_member, member) == 0)
3610 return TRUE;
3611
3612 return FALSE;
3613
3614}
3615
3629 const char *error_name)
3630{
3631 _dbus_return_val_if_fail (message != NULL, FALSE);
3632 _dbus_return_val_if_fail (!message->locked, FALSE);
3633 _dbus_return_val_if_fail (error_name == NULL ||
3634 _dbus_check_is_valid_error_name (error_name),
3635 FALSE);
3636
3637 return set_or_delete_string_field (message,
3640 error_name);
3641}
3642
3653const char*
3655{
3656 const char *v;
3657
3658 _dbus_return_val_if_fail (message != NULL, NULL);
3659
3660 v = NULL; /* in case field doesn't exist */
3664 (void *) &v);
3665 return v;
3666}
3667
3683 const char *destination)
3684{
3685 _dbus_return_val_if_fail (message != NULL, FALSE);
3686 _dbus_return_val_if_fail (!message->locked, FALSE);
3687 _dbus_return_val_if_fail (destination == NULL ||
3688 _dbus_check_is_valid_bus_name (destination),
3689 FALSE);
3690
3691 return set_or_delete_string_field (message,
3694 destination);
3695}
3696
3706const char*
3708{
3709 const char *v;
3710
3711 _dbus_return_val_if_fail (message != NULL, NULL);
3712
3713 v = NULL; /* in case field doesn't exist */
3717 (void *) &v);
3718 return v;
3719}
3720
3737 const char *sender)
3738{
3739 _dbus_return_val_if_fail (message != NULL, FALSE);
3740 _dbus_return_val_if_fail (!message->locked, FALSE);
3741 _dbus_return_val_if_fail (sender == NULL ||
3742 _dbus_check_is_valid_bus_name (sender),
3743 FALSE);
3744
3745 return set_or_delete_string_field (message,
3748 sender);
3749}
3750
3766const char*
3768{
3769 const char *v;
3770
3771 _dbus_return_val_if_fail (message != NULL, NULL);
3772
3773 v = NULL; /* in case field doesn't exist */
3777 (void *) &v);
3778 return v;
3779}
3780
3799const char*
3801{
3802 const DBusString *type_str;
3803 int type_pos;
3804
3805 _dbus_return_val_if_fail (message != NULL, NULL);
3806
3807 get_const_signature (&message->header, &type_str, &type_pos);
3808
3809 return _dbus_string_get_const_data_len (type_str, type_pos, 0);
3810}
3811
3812static dbus_bool_t
3813_dbus_message_has_type_interface_member (DBusMessage *message,
3814 int type,
3815 const char *iface,
3816 const char *member)
3817{
3818 const char *n;
3819
3820 _dbus_assert (message != NULL);
3821 _dbus_assert (iface != NULL);
3822 _dbus_assert (member != NULL);
3823
3824 if (dbus_message_get_type (message) != type)
3825 return FALSE;
3826
3827 /* Optimize by checking the short member name first
3828 * instead of the longer interface name
3829 */
3830
3831 n = dbus_message_get_member (message);
3832
3833 if (n && strcmp (n, member) == 0)
3834 {
3835 n = dbus_message_get_interface (message);
3836
3837 if (n == NULL || strcmp (n, iface) == 0)
3838 return TRUE;
3839 }
3840
3841 return FALSE;
3842}
3843
3860 const char *iface,
3861 const char *method)
3862{
3863 _dbus_return_val_if_fail (message != NULL, FALSE);
3864 _dbus_return_val_if_fail (iface != NULL, FALSE);
3865 _dbus_return_val_if_fail (method != NULL, FALSE);
3866 /* don't check that interface/method are valid since it would be
3867 * expensive, and not catch many common errors
3868 */
3869
3870 return _dbus_message_has_type_interface_member (message,
3872 iface, method);
3873}
3874
3888 const char *iface,
3889 const char *signal_name)
3890{
3891 _dbus_return_val_if_fail (message != NULL, FALSE);
3892 _dbus_return_val_if_fail (iface != NULL, FALSE);
3893 _dbus_return_val_if_fail (signal_name != NULL, FALSE);
3894 /* don't check that interface/name are valid since it would be
3895 * expensive, and not catch many common errors
3896 */
3897
3898 return _dbus_message_has_type_interface_member (message,
3900 iface, signal_name);
3901}
3902
3915 const char *error_name)
3916{
3917 const char *n;
3918
3919 _dbus_return_val_if_fail (message != NULL, FALSE);
3920 _dbus_return_val_if_fail (error_name != NULL, FALSE);
3921 /* don't check that error_name is valid since it would be expensive,
3922 * and not catch many common errors
3923 */
3924
3926 return FALSE;
3927
3928 n = dbus_message_get_error_name (message);
3929
3930 if (n && strcmp (n, error_name) == 0)
3931 return TRUE;
3932 else
3933 return FALSE;
3934}
3935
3948 const char *name)
3949{
3950 const char *s;
3951
3952 _dbus_return_val_if_fail (message != NULL, FALSE);
3953 _dbus_return_val_if_fail (name != NULL, FALSE);
3954 /* don't check that name is valid since it would be expensive, and
3955 * not catch many common errors
3956 */
3957
3958 s = dbus_message_get_destination (message);
3959
3960 if (s && strcmp (s, name) == 0)
3961 return TRUE;
3962 else
3963 return FALSE;
3964}
3965
3983 const char *name)
3984{
3985 const char *s;
3986
3987 _dbus_return_val_if_fail (message != NULL, FALSE);
3988 _dbus_return_val_if_fail (name != NULL, FALSE);
3989 /* don't check that name is valid since it would be expensive, and
3990 * not catch many common errors
3991 */
3992
3993 s = dbus_message_get_sender (message);
3994
3995 if (s && strcmp (s, name) == 0)
3996 return TRUE;
3997 else
3998 return FALSE;
3999}
4000
4012 const char *signature)
4013{
4014 const char *s;
4015
4016 _dbus_return_val_if_fail (message != NULL, FALSE);
4017 _dbus_return_val_if_fail (signature != NULL, FALSE);
4018 /* don't check that signature is valid since it would be expensive,
4019 * and not catch many common errors
4020 */
4021
4022 s = dbus_message_get_signature (message);
4023
4024 if (s && strcmp (s, signature) == 0)
4025 return TRUE;
4026 else
4027 return FALSE;
4028}
4029
4054 DBusMessage *message)
4055{
4056 const char *str;
4057
4058 _dbus_return_val_if_fail (message != NULL, FALSE);
4059 _dbus_return_val_if_error_is_set (error, FALSE);
4060
4062 return FALSE;
4063
4064 str = NULL;
4065 dbus_message_get_args (message, NULL,
4066 DBUS_TYPE_STRING, &str,
4068
4070 str ? "%s" : NULL, str);
4071
4072 return TRUE;
4073}
4074
4083{
4084#ifdef HAVE_UNIX_FD_PASSING
4085 _dbus_assert(message);
4086
4087 return message->n_unix_fds > 0;
4088#else
4089 return FALSE;
4090#endif
4091}
4092
4105 const char *object_path)
4106{
4107 _dbus_return_val_if_fail (message != NULL, FALSE);
4108 _dbus_return_val_if_fail (!message->locked, FALSE);
4109 _dbus_return_val_if_fail (object_path == NULL ||
4110 _dbus_check_is_valid_path (object_path),
4111 FALSE);
4112
4113 return set_or_delete_string_field (message,
4116 object_path);
4117}
4118
4129const char *
4131{
4132 const char *v;
4133
4134 _dbus_return_val_if_fail (message != NULL, NULL);
4135
4136 v = NULL; /* in case field doesn't exist */
4140 (void *) &v);
4141 return v;
4142}
4143
4162#define INITIAL_LOADER_DATA_LEN 32
4163
4172{
4173 DBusMessageLoader *loader;
4174
4175 loader = dbus_new0 (DBusMessageLoader, 1);
4176 if (loader == NULL)
4177 return NULL;
4178
4179 loader->refcount = 1;
4180
4181 loader->corrupted = FALSE;
4182 loader->corruption_reason = DBUS_VALID;
4183
4184 /* this can be configured by the app, but defaults to the protocol max */
4186
4187 /* We set a very relatively conservative default here since due to how
4188 SCM_RIGHTS works we need to preallocate an fd array of the maximum
4189 number of unix fds we want to receive in advance. A
4190 try-and-reallocate loop is not possible. */
4191 loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
4192
4193 if (!_dbus_string_init (&loader->data))
4194 {
4195 dbus_free (loader);
4196 return NULL;
4197 }
4198
4199 /* preallocate the buffer for speed, ignore failure */
4201 _dbus_string_set_length (&loader->data, 0);
4202
4203#ifdef HAVE_UNIX_FD_PASSING
4204 loader->unix_fds = NULL;
4205 loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
4206 loader->unix_fds_outstanding = FALSE;
4207#endif
4208
4209 return loader;
4210}
4211
4220{
4221 loader->refcount += 1;
4222
4223 return loader;
4224}
4225
4232void
4234{
4235 loader->refcount -= 1;
4236 if (loader->refcount == 0)
4237 {
4238#ifdef HAVE_UNIX_FD_PASSING
4239 close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
4240 dbus_free(loader->unix_fds);
4241#endif
4244 _dbus_string_free (&loader->data);
4245 dbus_free (loader);
4246 }
4247}
4248
4267void
4269 DBusString **buffer,
4270 int *max_to_read,
4271 dbus_bool_t *may_read_fds)
4272{
4274
4275 *buffer = &loader->data;
4276
4277 loader->buffer_outstanding = TRUE;
4278
4279 if (max_to_read != NULL)
4280 {
4281#ifdef HAVE_UNIX_FD_PASSING
4282 int offset = 0;
4283 int remain;
4284 int byte_order;
4285 int fields_array_len;
4286 int header_len;
4287 int body_len;
4288#endif
4289
4290 *max_to_read = DBUS_MAXIMUM_MESSAGE_LENGTH;
4291 *may_read_fds = TRUE;
4292
4293#ifdef HAVE_UNIX_FD_PASSING
4294 /* If we aren't holding onto any fds, we can read as much as we want
4295 * (fast path). */
4296 if (loader->n_unix_fds == 0)
4297 return;
4298
4299 /* Slow path: we have a message with some fds in it. We don't want
4300 * to start on the next message until this one is out of the way;
4301 * otherwise a legitimate sender can keep us processing messages
4302 * containing fds, until we disconnect it for having had fds pending
4303 * for too long, a limit that is in place to stop malicious senders
4304 * from setting up recursive fd-passing that takes up our quota and
4305 * will never go away. */
4306
4307 remain = _dbus_string_get_length (&loader->data);
4308
4309 while (remain > 0)
4310 {
4311 DBusValidity validity = DBUS_VALIDITY_UNKNOWN;
4312 int needed;
4313
4314 /* If 0 < remain < DBUS_MINIMUM_HEADER_SIZE, then we've had at
4315 * least the first byte of a message, but we don't know how
4316 * much more to read. Only read the rest of the
4317 * DBUS_MINIMUM_HEADER_SIZE for now; then we'll know. */
4318 if (remain < DBUS_MINIMUM_HEADER_SIZE)
4319 {
4320 *max_to_read = DBUS_MINIMUM_HEADER_SIZE - remain;
4321 *may_read_fds = FALSE;
4322 return;
4323 }
4324
4326 &validity,
4327 &byte_order,
4328 &fields_array_len,
4329 &header_len,
4330 &body_len,
4331 &loader->data,
4332 offset,
4333 remain))
4334 {
4335 /* If a message in the buffer is invalid, we're going to
4336 * disconnect the sender anyway, so reading an arbitrary amount
4337 * is fine. */
4338 if (validity != DBUS_VALID)
4339 return;
4340
4341 /* We have a partial message, with the
4342 * DBUS_MINIMUM_HEADER_SIZE-byte fixed part of the header (which
4343 * lets us work out how much more we need), but no more. Read
4344 * the rest of the message. */
4345 needed = header_len + body_len;
4346 _dbus_assert (needed > remain);
4347 *max_to_read = needed - remain;
4348 *may_read_fds = FALSE;
4349 return;
4350 }
4351
4352 /* Skip over entire messages until we have less than a message
4353 * remaining. */
4354 needed = header_len + body_len;
4356 _dbus_assert (remain >= needed);
4357 remain -= needed;
4358 offset += needed;
4359 }
4360#endif
4361 }
4362}
4363
4373void
4375 DBusString *buffer)
4376{
4378 _dbus_assert (buffer == &loader->data);
4379
4380 loader->buffer_outstanding = FALSE;
4381}
4382
4383#ifdef HAVE_UNIX_FD_PASSING
4395_dbus_message_loader_get_unix_fds(DBusMessageLoader *loader,
4396 int **fds,
4397 unsigned *max_n_fds)
4398{
4399 _dbus_assert (!loader->unix_fds_outstanding);
4400
4401 /* Allocate space where we can put the fds we read. We allocate
4402 space for max_message_unix_fds since this is an
4403 upper limit how many fds can be received within a single
4404 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
4405 we are allocating the maximum possible array size right from the
4406 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
4407 there is no better way. */
4408
4409 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
4410 {
4411 int *a = dbus_realloc(loader->unix_fds,
4412 loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
4413
4414 if (!a)
4415 return FALSE;
4416
4417 loader->unix_fds = a;
4418 loader->n_unix_fds_allocated = loader->max_message_unix_fds;
4419 }
4420
4421 *fds = loader->unix_fds + loader->n_unix_fds;
4422 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
4423
4424 loader->unix_fds_outstanding = TRUE;
4425 return TRUE;
4426}
4427
4438void
4439_dbus_message_loader_return_unix_fds(DBusMessageLoader *loader,
4440 int *fds,
4441 unsigned n_fds)
4442{
4443 _dbus_assert(loader->unix_fds_outstanding);
4444 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
4445 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
4446
4447 loader->n_unix_fds += n_fds;
4448 loader->unix_fds_outstanding = FALSE;
4449
4450 if (n_fds && loader->unix_fds_change)
4451 loader->unix_fds_change (loader->unix_fds_change_data);
4452}
4453#endif
4454
4455/*
4456 * FIXME when we move the header out of the buffer, that memmoves all
4457 * buffered messages. Kind of crappy.
4458 *
4459 * Also we copy the header and body, which is kind of crappy. To
4460 * avoid this, we have to allow header and body to be in a single
4461 * memory block, which is good for messages we read and bad for
4462 * messages we are creating. But we could move_len() the buffer into
4463 * this single memory block, and move_len() will just swap the buffers
4464 * if you're moving the entire buffer replacing the dest string.
4465 *
4466 * We could also have the message loader tell the transport how many
4467 * bytes to read; so it would first ask for some arbitrary number like
4468 * 256, then if the message was incomplete it would use the
4469 * header/body len to ask for exactly the size of the message (or
4470 * blocks the size of a typical kernel buffer for the socket). That
4471 * way we don't get trailing bytes in the buffer that have to be
4472 * memmoved. Though I suppose we also don't have a chance of reading a
4473 * bunch of small messages at once, so the optimization may be stupid.
4474 *
4475 * Another approach would be to keep a "start" index into
4476 * loader->data and only delete it occasionally, instead of after
4477 * each message is loaded.
4478 *
4479 * load_message() returns FALSE if not enough memory OR the loader was corrupted
4480 */
4481static dbus_bool_t
4482load_message (DBusMessageLoader *loader,
4483 DBusMessage *message,
4484 int byte_order,
4485 int fields_array_len,
4486 int header_len,
4487 int body_len)
4488{
4489 dbus_bool_t oom;
4490 DBusValidity validity;
4491 const DBusString *type_str;
4492 int type_pos;
4493 DBusValidationMode mode;
4494 dbus_uint32_t n_unix_fds = 0;
4495
4496 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
4497
4498 oom = FALSE;
4499
4500#if 0
4501 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
4502#endif
4503
4504 /* 1. VALIDATE AND COPY OVER HEADER */
4506 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
4507
4508 if (!_dbus_header_load (&message->header,
4509 mode,
4510 &validity,
4511 byte_order,
4512 fields_array_len,
4513 header_len,
4514 body_len,
4515 &loader->data))
4516 {
4517 _dbus_verbose ("Failed to load header for new message code %d\n", validity);
4518
4519 /* assert here so we can catch any code that still uses DBUS_VALID to indicate
4520 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
4521 _dbus_assert (validity != DBUS_VALID);
4522
4523 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
4524 oom = TRUE;
4525 else
4526 {
4527 loader->corrupted = TRUE;
4528 loader->corruption_reason = validity;
4529 }
4530 goto failed;
4531 }
4532
4533 _dbus_assert (validity == DBUS_VALID);
4534
4535 /* 2. VALIDATE BODY */
4536 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
4537 {
4538 get_const_signature (&message->header, &type_str, &type_pos);
4539
4540 /* Because the bytes_remaining arg is NULL, this validates that the
4541 * body is the right length
4542 */
4543 validity = _dbus_validate_body_with_reason (type_str,
4544 type_pos,
4545 byte_order,
4546 NULL,
4547 &loader->data,
4548 header_len,
4549 body_len);
4550 if (validity != DBUS_VALID)
4551 {
4552 _dbus_verbose ("Failed to validate message body code %d\n", validity);
4553
4554 loader->corrupted = TRUE;
4555 loader->corruption_reason = validity;
4556
4557 goto failed;
4558 }
4559 }
4560
4561 /* 3. COPY OVER UNIX FDS */
4565 &n_unix_fds);
4566
4567#ifdef HAVE_UNIX_FD_PASSING
4568
4569 if (n_unix_fds > loader->n_unix_fds)
4570 {
4571 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
4572 n_unix_fds, loader->n_unix_fds);
4573
4574 loader->corrupted = TRUE;
4575 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4576 goto failed;
4577 }
4578
4579 /* If this was a recycled message there might still be
4580 some memory allocated for the fds */
4581 dbus_free(message->unix_fds);
4582
4583 if (n_unix_fds > 0)
4584 {
4585 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
4586 if (message->unix_fds == NULL)
4587 {
4588 _dbus_verbose ("Failed to allocate file descriptor array\n");
4589 oom = TRUE;
4590 goto failed;
4591 }
4592
4593 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
4594 loader->n_unix_fds -= n_unix_fds;
4595 memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
4596
4597 if (loader->unix_fds_change)
4598 loader->unix_fds_change (loader->unix_fds_change_data);
4599 }
4600 else
4601 message->unix_fds = NULL;
4602
4603#else
4604
4605 if (n_unix_fds > 0)
4606 {
4607 _dbus_verbose ("Hmm, message claims to come with file descriptors "
4608 "but that's not supported on our platform, disconnecting.\n");
4609
4610 loader->corrupted = TRUE;
4611 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4612 goto failed;
4613 }
4614
4615#endif
4616
4617 /* 3. COPY OVER BODY AND QUEUE MESSAGE */
4618
4619 if (!_dbus_list_append (&loader->messages, message))
4620 {
4621 _dbus_verbose ("Failed to append new message to loader queue\n");
4622 oom = TRUE;
4623 goto failed;
4624 }
4625
4626 _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4628 (header_len + body_len));
4629
4630 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
4631 {
4632 _dbus_verbose ("Failed to move body into new message\n");
4633 oom = TRUE;
4634 goto failed;
4635 }
4636
4637 _dbus_string_delete (&loader->data, 0, header_len + body_len);
4638
4639 /* don't waste more than 2k of memory */
4640 _dbus_string_compact (&loader->data, 2048);
4641
4642 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
4643 _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4644
4645 _dbus_verbose ("Loaded message %p\n", message);
4646
4647 _dbus_assert (!oom);
4648 _dbus_assert (!loader->corrupted);
4649 _dbus_assert (loader->messages != NULL);
4650 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4651
4652 return TRUE;
4653
4654 failed:
4655
4656 /* Clean up */
4657
4658 /* does nothing if the message isn't in the list */
4659 _dbus_list_remove_last (&loader->messages, message);
4660
4661 if (oom)
4662 _dbus_assert (!loader->corrupted);
4663 else
4664 _dbus_assert (loader->corrupted);
4665
4667
4668 return FALSE;
4669}
4670
4687{
4688 while (!loader->corrupted &&
4690 {
4691 DBusValidity validity;
4692 int byte_order, fields_array_len, header_len, body_len;
4693
4695 &validity,
4696 &byte_order,
4697 &fields_array_len,
4698 &header_len,
4699 &body_len,
4700 &loader->data, 0,
4701 _dbus_string_get_length (&loader->data)))
4702 {
4703 DBusMessage *message;
4704
4705 _dbus_assert (validity == DBUS_VALID);
4706
4707 message = dbus_message_new_empty_header ();
4708 if (message == NULL)
4709 return FALSE;
4710
4711 if (!load_message (loader, message,
4712 byte_order, fields_array_len,
4713 header_len, body_len))
4714 {
4715 dbus_message_unref (message);
4716 /* load_message() returns false if corrupted or OOM; if
4717 * corrupted then return TRUE for not OOM
4718 */
4719 return loader->corrupted;
4720 }
4721
4722 _dbus_assert (loader->messages != NULL);
4723 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4724 }
4725 else
4726 {
4727 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
4728 validity);
4729 if (validity != DBUS_VALID)
4730 {
4731 loader->corrupted = TRUE;
4732 loader->corruption_reason = validity;
4733 }
4734 return TRUE;
4735 }
4736 }
4737
4738 return TRUE;
4739}
4740
4750{
4751 if (loader->messages)
4752 return loader->messages->data;
4753 else
4754 return NULL;
4755}
4756
4767{
4768 return _dbus_list_pop_first (&loader->messages);
4769}
4770
4779DBusList*
4781{
4782 return _dbus_list_pop_first_link (&loader->messages);
4783}
4784
4791void
4793 DBusList *link)
4794{
4795 _dbus_list_prepend_link (&loader->messages, link);
4796}
4797
4809{
4810 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4811 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4812 return loader->corrupted;
4813}
4814
4823{
4824 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4825 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4826
4827 return loader->corruption_reason;
4828}
4829
4836void
4838 long size)
4839{
4840 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
4841 {
4842 _dbus_verbose ("clamping requested max message size %ld to %d\n",
4845 }
4846 loader->max_message_size = size;
4847}
4848
4855long
4857{
4858 return loader->max_message_size;
4859}
4860
4867void
4869 long n)
4870{
4872 {
4873 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
4876 }
4877 loader->max_message_unix_fds = n;
4878}
4879
4886long
4888{
4889 return loader->max_message_unix_fds;
4890}
4891
4897int
4899{
4900#ifdef HAVE_UNIX_FD_PASSING
4901 return loader->n_unix_fds;
4902#else
4903 return 0;
4904#endif
4905}
4906
4915void
4917 void (* callback) (void *),
4918 void *data)
4919{
4920#ifdef HAVE_UNIX_FD_PASSING
4921 loader->unix_fds_change = callback;
4922 loader->unix_fds_change_data = data;
4923#endif
4924}
4925
4926static DBusDataSlotAllocator slot_allocator =
4927 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
4928
4945{
4946 return _dbus_data_slot_allocator_alloc (&slot_allocator,
4947 slot_p);
4948}
4949
4961void
4963{
4964 _dbus_return_if_fail (*slot_p >= 0);
4965
4966 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
4967}
4968
4984 dbus_int32_t slot,
4985 void *data,
4986 DBusFreeFunction free_data_func)
4987{
4988 DBusFreeFunction old_free_func;
4989 void *old_data;
4990 dbus_bool_t retval;
4991
4992 _dbus_return_val_if_fail (message != NULL, FALSE);
4993 _dbus_return_val_if_fail (slot >= 0, FALSE);
4994
4995 retval = _dbus_data_slot_list_set (&slot_allocator,
4996 &message->slot_list,
4997 slot, data, free_data_func,
4998 &old_free_func, &old_data);
4999
5000 if (retval)
5001 {
5002 /* Do the actual free outside the message lock */
5003 if (old_free_func)
5004 (* old_free_func) (old_data);
5005 }
5006
5007 return retval;
5008}
5009
5018void*
5020 dbus_int32_t slot)
5021{
5022 void *res;
5023
5024 _dbus_return_val_if_fail (message != NULL, NULL);
5025
5026 res = _dbus_data_slot_list_get (&slot_allocator,
5027 &message->slot_list,
5028 slot);
5029
5030 return res;
5031}
5032
5046int
5047dbus_message_type_from_string (const char *type_str)
5048{
5049 if (strcmp (type_str, "method_call") == 0)
5051 if (strcmp (type_str, "method_return") == 0)
5053 else if (strcmp (type_str, "signal") == 0)
5055 else if (strcmp (type_str, "error") == 0)
5057 else
5059}
5060
5074const char *
5076{
5077 switch (type)
5078 {
5080 return "method_call";
5082 return "method_return";
5084 return "signal";
5086 return "error";
5087 default:
5088 return "invalid";
5089 }
5090}
5091
5106 char **marshalled_data_p,
5107 int *len_p)
5108{
5109 DBusString tmp;
5110 dbus_bool_t was_locked;
5111
5112 _dbus_return_val_if_fail (msg != NULL, FALSE);
5113 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
5114 _dbus_return_val_if_fail (len_p != NULL, FALSE);
5115
5116 if (!_dbus_string_init (&tmp))
5117 return FALSE;
5118
5119 /* Ensure the message is locked, to ensure the length header is filled in. */
5120 was_locked = msg->locked;
5121
5122 if (!was_locked)
5123 dbus_message_lock (msg);
5124
5125 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
5126 goto fail;
5127
5128 *len_p = _dbus_string_get_length (&tmp);
5129
5130 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
5131 goto fail;
5132
5133 *len_p = _dbus_string_get_length (&tmp);
5134
5135 if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
5136 goto fail;
5137
5138 _dbus_string_free (&tmp);
5139
5140 if (!was_locked)
5141 msg->locked = FALSE;
5142
5143 return TRUE;
5144
5145 fail:
5146 _dbus_string_free (&tmp);
5147
5148 if (!was_locked)
5149 msg->locked = FALSE;
5150
5151 return FALSE;
5152}
5153
5167dbus_message_demarshal (const char *str,
5168 int len,
5169 DBusError *error)
5170{
5171 DBusMessageLoader *loader = NULL;
5172 DBusString *buffer;
5173 DBusMessage *msg;
5174
5175 _dbus_return_val_if_fail (str != NULL, NULL);
5176
5177 loader = _dbus_message_loader_new ();
5178
5179 if (loader == NULL)
5180 goto fail_oom;
5181
5182 _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
5183
5184 if (!_dbus_string_append_len (buffer, str, len))
5185 goto fail_oom;
5186
5187 _dbus_message_loader_return_buffer (loader, buffer);
5188
5190 goto fail_oom;
5191
5193 goto fail_corrupt;
5194
5195 msg = _dbus_message_loader_pop_message (loader);
5196
5197 if (!msg)
5198 goto fail_oom;
5199
5201 return msg;
5202
5203 fail_corrupt:
5204 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
5205 _dbus_validity_to_error_message (loader->corruption_reason));
5207 return NULL;
5208
5209 fail_oom:
5210 _DBUS_SET_OOM (error);
5211
5212 if (loader != NULL)
5214
5215 return NULL;
5216}
5217
5230int
5232 int len)
5233{
5234 DBusString str;
5235 int byte_order, fields_array_len, header_len, body_len;
5236 DBusValidity validity = DBUS_VALID;
5237 int have_message;
5238
5239 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
5240 return 0;
5241
5244 _dbus_string_init_const_len (&str, buf, len);
5245
5246 validity = DBUS_VALID;
5247 have_message
5249 &validity, &byte_order,
5250 &fields_array_len,
5251 &header_len,
5252 &body_len,
5253 &str, 0,
5254 len);
5255 _dbus_string_free (&str);
5256
5257 if (validity == DBUS_VALID)
5258 {
5259 _dbus_assert (have_message || (header_len + body_len) > len);
5260 (void) have_message; /* unused unless asserting */
5261 return header_len + body_len;
5262 }
5263 else
5264 {
5265 return -1; /* broken! */
5266 }
5267}
5268
5290void
5292 dbus_bool_t allow)
5293{
5294 _dbus_return_if_fail (message != NULL);
5295 _dbus_return_if_fail (!message->locked);
5296
5299 allow);
5300}
5301
5310{
5311 _dbus_return_val_if_fail (message != NULL, FALSE);
5312
5313 return _dbus_header_get_flag (&message->header,
5315}
5316
5324{
5325 DBusString data;
5326};
5327
5341{
5342 DBusVariant *self = NULL;
5343 /* Points to the single item we will read from the reader */
5344 DBusMessageRealIter *real_reader = (DBusMessageRealIter *) reader;
5345 /* The position in self at which we will write a single variant
5346 * (it is position 0) */
5347 DBusTypeWriter items_writer;
5348 /* The position in self at which we will write a copy of reader
5349 * (it is inside the variant) */
5350 DBusTypeWriter variant_writer;
5351 /* 'v' */
5352 DBusString variant_signature;
5353 /* Whatever is the signature of the item we will copy from the reader */
5354 DBusString contained_signature;
5355 /* TRUE if self->data needs to be freed */
5356 dbus_bool_t data_inited = FALSE;
5357 /* The type of the item we will read from the reader */
5358 int type;
5359 /* The string, start position within that string, and length of the signature
5360 * of the single complete type of the item reader points to */
5361 const DBusString *sig;
5362 int start, len;
5363
5364 _dbus_assert (_dbus_message_iter_check (real_reader));
5365 _dbus_assert (real_reader->iter_type == DBUS_MESSAGE_ITER_TYPE_READER);
5367 type = dbus_message_iter_get_arg_type (reader);
5368 _dbus_type_reader_get_signature (&real_reader->u.reader, &sig, &start, &len);
5369
5370 if (!_dbus_string_init (&contained_signature))
5371 return NULL;
5372
5373 if (!_dbus_string_copy_len (sig, start, len, &contained_signature, 0))
5374 goto oom;
5375
5376 self = dbus_new0 (DBusVariant, 1);
5377
5378 if (self == NULL)
5379 goto oom;
5380
5381 if (!_dbus_string_init (&self->data))
5382 goto oom;
5383
5384 data_inited = TRUE;
5385
5386 _dbus_type_writer_init_values_only (&items_writer, DBUS_COMPILER_BYTE_ORDER,
5387 &variant_signature, 0, &self->data, 0);
5388
5389 if (!_dbus_type_writer_recurse (&items_writer, DBUS_TYPE_VARIANT,
5390 &contained_signature, 0, &variant_writer))
5391 goto oom;
5392
5393 if (type == DBUS_TYPE_ARRAY)
5394 {
5395 /* Points to each item in turn inside the array we are copying */
5396 DBusMessageIter array_reader;
5397 /* Same as array_reader */
5398 DBusMessageRealIter *real_array_reader = (DBusMessageRealIter *) &array_reader;
5399 /* The position inside the copied array at which we will write
5400 * the copy of array_reader */
5401 DBusTypeWriter array_writer;
5402
5403 dbus_message_iter_recurse (reader, &array_reader);
5404
5405 if (!_dbus_type_writer_recurse (&variant_writer, type,
5406 &contained_signature, 1, &array_writer))
5407 goto oom;
5408
5409 if (!_dbus_type_writer_write_reader (&array_writer,
5410 &real_array_reader->u.reader))
5411 goto oom;
5412
5413 if (!_dbus_type_writer_unrecurse (&variant_writer, &array_writer))
5414 goto oom;
5415 }
5416 else if (type == DBUS_TYPE_DICT_ENTRY || type == DBUS_TYPE_VARIANT ||
5417 type == DBUS_TYPE_STRUCT)
5418 {
5419 /* Points to each item in turn inside the container we are copying */
5420 DBusMessageIter inner_reader;
5421 /* Same as inner_reader */
5422 DBusMessageRealIter *real_inner_reader = (DBusMessageRealIter *) &inner_reader;
5423 /* The position inside the copied container at which we will write the
5424 * copy of inner_reader */
5425 DBusTypeWriter inner_writer;
5426
5427 dbus_message_iter_recurse (reader, &inner_reader);
5428
5429 if (!_dbus_type_writer_recurse (&variant_writer, type, NULL, 0,
5430 &inner_writer))
5431 goto oom;
5432
5433 if (!_dbus_type_writer_write_reader (&inner_writer,
5434 &real_inner_reader->u.reader))
5435 goto oom;
5436
5437 if (!_dbus_type_writer_unrecurse (&variant_writer, &inner_writer))
5438 goto oom;
5439 }
5440 else
5441 {
5442 DBusBasicValue value;
5443
5444 /* We eliminated all the container types above */
5446
5447 dbus_message_iter_get_basic (reader, &value);
5448
5449 if (!_dbus_type_writer_write_basic (&variant_writer, type, &value))
5450 goto oom;
5451 }
5452
5453 _dbus_string_free (&contained_signature);
5454 return self;
5455
5456oom:
5457 if (self != NULL)
5458 {
5459 if (data_inited)
5460 _dbus_string_free (&self->data);
5461
5462 dbus_free (self);
5463 }
5464
5465 _dbus_string_free (&contained_signature);
5466 return NULL;
5467}
5468
5475const char *
5477{
5478 const char *ret;
5479#ifndef DBUS_DISABLE_ASSERT
5480 unsigned char len;
5481#endif
5482
5483 _dbus_assert (self != NULL);
5484
5485#ifndef DBUS_DISABLE_ASSERT
5486 /* Here we make use of the fact that the serialization of a variant starts
5487 * with the 1-byte length, then that many bytes of signature, then \0. */
5488 len = _dbus_string_get_byte (&self->data, 0);
5489#endif
5490 ret = _dbus_string_get_const_data_len (&self->data, 1, len);
5491 _dbus_assert (strlen (ret) == len);
5492 return ret;
5493}
5494
5508 DBusMessageIter *writer)
5509{
5510 /* 'v' */
5511 DBusString variant_signature;
5512 /* Points to the single item in self */
5513 DBusTypeReader variant_reader;
5514 /* Points to the single item (of whatever type) inside the variant */
5515 DBusTypeReader reader;
5516 /* The position at which we will copy reader */
5517 DBusMessageRealIter *real_writer = (DBusMessageRealIter *) writer;
5518 dbus_bool_t ret;
5519
5520 _dbus_assert (self != NULL);
5521 _dbus_assert (_dbus_message_iter_append_check (real_writer));
5522 _dbus_assert (real_writer->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
5523
5525 _dbus_type_reader_init (&reader, DBUS_COMPILER_BYTE_ORDER,
5526 &variant_signature, 0, &self->data, 0);
5527 _dbus_type_reader_recurse (&reader, &variant_reader);
5528
5529 if (!_dbus_message_iter_open_signature (real_writer))
5530 return FALSE;
5531
5532 ret = _dbus_type_writer_write_reader (&real_writer->u.writer,
5533 &variant_reader);
5534
5535 if (!_dbus_message_iter_close_signature (real_writer))
5536 return FALSE;
5537
5538 return ret;
5539}
5540
5541int
5542_dbus_variant_get_length (DBusVariant *self)
5543{
5544 _dbus_assert (self != NULL);
5545 return _dbus_string_get_length (&self->data);
5546}
5547
5548const DBusString *
5549_dbus_variant_peek (DBusVariant *self)
5550{
5551 _dbus_assert (self != NULL);
5552 return &self->data;
5553}
5554
5555void
5556_dbus_variant_free (DBusVariant *self)
5557{
5558 _dbus_assert (self != NULL);
5559 _dbus_string_free (&self->data);
5560 dbus_free (self);
5561}
5562
5565/* 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:70
void dbus_error_init(DBusError *error)
Initializes a DBusError structure.
Definition: dbus-errors.c:188
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition: dbus-errors.c:354
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:211
#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:656
void _dbus_list_append_link(DBusList **list, DBusList *link)
Appends a link to the list.
Definition: dbus-list.c:316
void _dbus_list_clear_full(DBusList **list, DBusFreeFunction function)
Free every link and every element in the list.
Definition: dbus-list.c:568
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition: dbus-list.c:528
DBusList * _dbus_list_find_last(DBusList **list, void *data)
Finds a value in the list.
Definition: dbus-list.c:473
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition: dbus-list.c:677
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition: dbus-list.c:787
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition: dbus-list.c:543
void _dbus_list_prepend_link(DBusList **list, DBusList *link)
Prepends a link to the list.
Definition: dbus-list.c:334
DBusList * _dbus_list_alloc_link(void *data)
Allocates a linked list node.
Definition: dbus-list.c:243
dbus_bool_t _dbus_list_remove_last(DBusList **list, void *data)
Removes a value from the list.
Definition: dbus-list.c:447
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition: dbus-list.c:271
#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, 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:772
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:801
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition: dbus-memory.h:63
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition: dbus-memory.c:692
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:592
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition: dbus-memory.h:57
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition: dbus-memory.h:58
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition: dbus-memory.c:740
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:282
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:836
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:228
#define MAX_MESSAGE_SIZE_TO_CACHE
Avoid caching huge messages.
Definition: dbus-message.c:506
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:753
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:299
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition: dbus-message.c:429
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:260
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:241
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:397
#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:374
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:509
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:325
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:70
#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:60
#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:86
#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:845
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:180
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:195
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:1343
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:684
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:137
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:215
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:1168
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:276
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:1253
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:1103
int _dbus_string_get_length(const DBusString *str)
Gets the length of a string (not including nul termination).
Definition: dbus-string.c:782
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:557
const char * _dbus_string_get_const_data(const DBusString *str)
Gets the raw character buffer from a const string.
Definition: dbus-string.c:511
unsigned char _dbus_string_get_byte(const DBusString *str, int start)
Gets the byte at the given position.
Definition: dbus-string.c:605
dbus_bool_t _dbus_string_compact(DBusString *str, int max_waste)
Compacts the string to avoid wasted memory.
Definition: dbus-string.c:418
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:1435
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:195
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:35
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:56
Object representing an exception.
Definition: dbus-errors.h:49
const char * message
public error message field
Definition: dbus-errors.h:51
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:35
void * data
Data stored at this element.
Definition: dbus-list.h:38
Layout of a DBusMessageIter on the stack in dbus 1.10.0.
Definition: dbus-message.c:154
DBusMessageIter struct; contains no public fields.
Definition: dbus-message.h:62
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:127
union DBusMessageRealIter::@6 u
the type writer or reader that does all the work
DBusMessage * message
Message used.
Definition: dbus-message.c:128
dbus_uint32_t iter_type
whether this is a reader or writer iter
Definition: dbus-message.c:130
dbus_uint32_t sig_refcount
depth of open_signature()
Definition: dbus-message.c:131
DBusTypeWriter writer
writer
Definition: dbus-message.c:134
dbus_uint32_t changed_stamp
stamp to detect invalid iters
Definition: dbus-message.c:129
DBusTypeReader reader
reader
Definition: dbus-message.c:135
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:159
dbus_uint32_t u32
as int32
Definition: dbus-types.h:164