D-Bus 1.14.10
dbus-message.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-message.c DBusMessage object
3 *
4 * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
5 * Copyright (C) 2002, 2003 CodeFactory AB
6 *
7 * Licensed under the Academic Free License version 2.1
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25#include <config.h>
26#include "dbus-internals.h"
27#include "dbus-marshal-recursive.h"
28#include "dbus-marshal-validate.h"
29#include "dbus-marshal-byteswap.h"
30#include "dbus-marshal-header.h"
31#include "dbus-signature.h"
32#include "dbus-message-private.h"
33#include "dbus-object-tree.h"
34#include "dbus-memory.h"
35#include "dbus-list.h"
36#include "dbus-threads-internal.h"
37#ifdef HAVE_UNIX_FD_PASSING
38#include "dbus-sysdeps.h"
39#include "dbus-sysdeps-unix.h"
40#endif
41
42#include <string.h>
43
44#define _DBUS_TYPE_IS_STRINGLIKE(type) \
45 (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \
46 type == DBUS_TYPE_OBJECT_PATH)
47
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{
130 dbus_uint32_t iter_type : 3;
131 dbus_uint32_t sig_refcount : 8;
132 union
133 {
136 } u;
137};
138
144typedef struct
145{
146 void *dummy1;
147 void *dummy2;
148 dbus_uint32_t dummy3;
149 int dummy4;
150 int dummy5;
151 int dummy6;
152 int dummy7;
153 int dummy8;
154 int dummy9;
155 int dummy10;
156 int dummy11;
157 int pad1;
158 int pad2;
159 void *pad3;
161
162static void
163get_const_signature (DBusHeader *header,
164 const DBusString **type_str_p,
165 int *type_pos_p)
166{
167 if (_dbus_header_get_field_raw (header,
169 type_str_p,
170 type_pos_p))
171 {
172 *type_pos_p += 1; /* skip the signature length which is 1 byte */
173 }
174 else
175 {
176 *type_str_p = &_dbus_empty_signature_str;
177 *type_pos_p = 0;
178 }
179}
180
186static void
187_dbus_message_byteswap (DBusMessage *message)
188{
189 const DBusString *type_str;
190 int type_pos;
191 char byte_order;
192
193 byte_order = _dbus_header_get_byte_order (&message->header);
194
195 if (byte_order == DBUS_COMPILER_BYTE_ORDER)
196 return;
197
198 _dbus_verbose ("Swapping message into compiler byte order\n");
199
200 get_const_signature (&message->header, &type_str, &type_pos);
201
202 _dbus_marshal_byteswap (type_str, type_pos,
203 byte_order,
204 DBUS_COMPILER_BYTE_ORDER,
205 &message->body, 0);
206
207 _dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
209 DBUS_COMPILER_BYTE_ORDER);
210}
211
218#define ensure_byte_order(message) _dbus_message_byteswap (message)
219
230void
232 const DBusString **header,
233 const DBusString **body)
234{
235 _dbus_assert (message->locked);
236
237 *header = &message->header.data;
238 *body = &message->body;
239}
240
251 const int **fds,
252 unsigned *n_fds)
253{
254 _dbus_assert (message->locked);
255
256#ifdef HAVE_UNIX_FD_PASSING
257 *fds = message->unix_fds;
258 *n_fds = message->n_unix_fds;
259#else
260 *fds = NULL;
261 *n_fds = 0;
262#endif
263}
264
273{
275}
276
288void
290 dbus_uint32_t serial)
291{
292 _dbus_return_if_fail (message != NULL);
293 _dbus_return_if_fail (!message->locked);
294
295 _dbus_header_set_serial (&message->header, serial);
296}
297
314void
316 DBusList *link)
317{
318 /* right now we don't recompute the delta when message
319 * size changes, and that's OK for current purposes
320 * I think, but could be important to change later.
321 * Do recompute it whenever there are no outstanding counters,
322 * since it's basically free.
323 */
324 if (message->counters == NULL)
325 {
326 message->size_counter_delta =
327 _dbus_string_get_length (&message->header.data) +
328 _dbus_string_get_length (&message->body);
329
330#ifdef HAVE_UNIX_FD_PASSING
331 message->unix_fd_counter_delta = message->n_unix_fds;
332#endif
333
334#if 0
335 _dbus_verbose ("message has size %ld\n",
336 message->size_counter_delta);
337#endif
338 }
339
340 _dbus_list_append_link (&message->counters, link);
341
343
344#ifdef HAVE_UNIX_FD_PASSING
345 _dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
346#endif
347}
348
365 DBusCounter *counter)
366{
367 DBusList *link;
368
369 link = _dbus_list_alloc_link (counter);
370 if (link == NULL)
371 return FALSE;
372
373 _dbus_counter_ref (counter);
374 _dbus_message_add_counter_link (message, link);
375
376 return TRUE;
377}
378
386void
388 DBusCounter *counter)
389{
390 DBusList *link;
391
392 link = _dbus_list_find_last (&message->counters,
393 counter);
394 _dbus_assert (link != NULL);
395
396 _dbus_list_remove_link (&message->counters, link);
397
398 _dbus_counter_adjust_size (counter, - message->size_counter_delta);
399
400#ifdef HAVE_UNIX_FD_PASSING
401 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
402#endif
403
404 _dbus_counter_notify (counter);
405 _dbus_counter_unref (counter);
406}
407
418void
420{
421 if (!message->locked)
422 {
424 _dbus_string_get_length (&message->body));
425
426 /* must have a signature if you have a body */
427 _dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
428 dbus_message_get_signature (message) != NULL);
429
430 message->locked = TRUE;
431 }
432}
433
434static dbus_bool_t
435set_or_delete_string_field (DBusMessage *message,
436 int field,
437 int typecode,
438 const char *value)
439{
440 if (value == NULL)
441 return _dbus_header_delete_field (&message->header, field);
442 else
443 return _dbus_header_set_field_basic (&message->header,
444 field,
445 typecode,
446 &value);
447}
448
449/* Message Cache
450 *
451 * We cache some DBusMessage to reduce the overhead of allocating
452 * them. In my profiling this consistently made about an 8%
453 * difference. It avoids the malloc for the message, the malloc for
454 * the slot list, the malloc for the header string and body string,
455 * and the associated free() calls. It does introduce another global
456 * lock which could be a performance issue in certain cases.
457 *
458 * For the echo client/server the round trip time goes from around
459 * .000077 to .000069 with the message cache on my laptop. The sysprof
460 * change is as follows (numbers are cumulative percentage):
461 *
462 * with message cache implemented as array as it is now (0.000069 per):
463 * new_empty_header 1.46
464 * mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache)
465 * mutex_unlock 0.25
466 * self 0.41
467 * unref 2.24
468 * self 0.68
469 * list_clear 0.43
470 * mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache)
471 * mutex_unlock 0.25
472 *
473 * with message cache implemented as list (0.000070 per roundtrip):
474 * new_empty_header 2.72
475 * list_pop_first 1.88
476 * unref 3.3
477 * list_prepend 1.63
478 *
479 * without cache (0.000077 per roundtrip):
480 * new_empty_header 6.7
481 * string_init_preallocated 3.43
482 * dbus_malloc 2.43
483 * dbus_malloc0 2.59
484 *
485 * unref 4.02
486 * string_free 1.82
487 * dbus_free 1.63
488 * dbus_free 0.71
489 *
490 * If you implement the message_cache with a list, the primary reason
491 * it's slower is that you add another thread lock (on the DBusList
492 * mempool).
493 */
494
496#define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
497
499#define MAX_MESSAGE_CACHE_SIZE 5
500
501/* Protected by _DBUS_LOCK (message_cache) */
502static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
503static int message_cache_count = 0;
504static dbus_bool_t message_cache_shutdown_registered = FALSE;
505
506static void
507dbus_message_cache_shutdown (void *data)
508{
509 int i;
510
511 if (!_DBUS_LOCK (message_cache))
512 _dbus_assert_not_reached ("we would have initialized global locks "
513 "before registering a shutdown function");
514
515 i = 0;
516 while (i < MAX_MESSAGE_CACHE_SIZE)
517 {
518 if (message_cache[i])
519 dbus_message_finalize (message_cache[i]);
520
521 ++i;
522 }
523
524 message_cache_count = 0;
525 message_cache_shutdown_registered = FALSE;
526
527 _DBUS_UNLOCK (message_cache);
528}
529
537static DBusMessage*
538dbus_message_get_cached (void)
539{
540 DBusMessage *message;
541 int i;
542
543 message = NULL;
544
545 if (!_DBUS_LOCK (message_cache))
546 {
547 /* we'd have initialized global locks before caching anything,
548 * so there can't be anything in the cache */
549 return NULL;
550 }
551
552 _dbus_assert (message_cache_count >= 0);
553
554 if (message_cache_count == 0)
555 {
556 _DBUS_UNLOCK (message_cache);
557 return NULL;
558 }
559
560 /* This is not necessarily true unless count > 0, and
561 * message_cache is uninitialized until the shutdown is
562 * registered
563 */
564 _dbus_assert (message_cache_shutdown_registered);
565
566 i = 0;
567 while (i < MAX_MESSAGE_CACHE_SIZE)
568 {
569 if (message_cache[i])
570 {
571 message = message_cache[i];
572 message_cache[i] = NULL;
573 message_cache_count -= 1;
574 break;
575 }
576 ++i;
577 }
578 _dbus_assert (message_cache_count >= 0);
580 _dbus_assert (message != NULL);
581
582 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
583
584 _dbus_assert (message->counters == NULL);
585
586 _DBUS_UNLOCK (message_cache);
587
588 return message;
589}
590
591#ifdef HAVE_UNIX_FD_PASSING
592static void
593close_unix_fds(int *fds, unsigned *n_fds)
594{
595 DBusError e;
596 unsigned int i;
597
598 if (*n_fds <= 0)
599 return;
600
601 dbus_error_init(&e);
602
603 for (i = 0; i < *n_fds; i++)
604 {
605 if (!_dbus_close(fds[i], &e))
606 {
607 _dbus_warn("Failed to close file descriptor: %s", e.message);
608 dbus_error_free(&e);
609 }
610 }
611
612 *n_fds = 0;
613
614 /* We don't free the array here, in case we can recycle it later */
615}
616#endif
617
618static void
619free_counter (void *element,
620 void *data)
621{
622 DBusCounter *counter = element;
623 DBusMessage *message = data;
624
625 _dbus_counter_adjust_size (counter, - message->size_counter_delta);
626#ifdef HAVE_UNIX_FD_PASSING
627 _dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
628#endif
629
630 _dbus_counter_notify (counter);
631 _dbus_counter_unref (counter);
632}
633
639static void
640dbus_message_cache_or_finalize (DBusMessage *message)
641{
642 dbus_bool_t was_cached;
643 int i;
644
645 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
646
647 /* This calls application code and has to be done first thing
648 * without holding the lock
649 */
651
652 _dbus_list_foreach (&message->counters,
653 free_counter, message);
654 _dbus_list_clear (&message->counters);
655
656#ifdef HAVE_UNIX_FD_PASSING
657 close_unix_fds(message->unix_fds, &message->n_unix_fds);
658#endif
659
660 was_cached = FALSE;
661
662 if (!_DBUS_LOCK (message_cache))
663 {
664 /* The only way to get a non-null message goes through
665 * dbus_message_get_cached() which takes the lock. */
666 _dbus_assert_not_reached ("we would have initialized global locks "
667 "the first time we constructed a message");
668 }
669
670 if (!message_cache_shutdown_registered)
671 {
672 _dbus_assert (message_cache_count == 0);
673
674 if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
675 goto out;
676
677 i = 0;
678 while (i < MAX_MESSAGE_CACHE_SIZE)
679 {
680 message_cache[i] = NULL;
681 ++i;
682 }
683
684 message_cache_shutdown_registered = TRUE;
685 }
686
687 _dbus_assert (message_cache_count >= 0);
688
689 if (!_dbus_enable_message_cache ())
690 goto out;
691
692 if ((_dbus_string_get_length (&message->header.data) +
693 _dbus_string_get_length (&message->body)) >
695 goto out;
696
697 if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
698 goto out;
699
700 /* Find empty slot */
701 i = 0;
702 while (message_cache[i] != NULL)
703 ++i;
704
706
707 _dbus_assert (message_cache[i] == NULL);
708 message_cache[i] = message;
709 message_cache_count += 1;
710 was_cached = TRUE;
711#ifndef DBUS_DISABLE_CHECKS
712 message->in_cache = TRUE;
713#endif
714
715 out:
716 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
717
718 _DBUS_UNLOCK (message_cache);
719
720 if (!was_cached)
721 dbus_message_finalize (message);
722}
723
724/*
725 * Arrange for iter to be something that _dbus_message_iter_check() would
726 * reject as not a valid iterator.
727 */
728static void
729_dbus_message_real_iter_zero (DBusMessageRealIter *iter)
730{
731 _dbus_assert (iter != NULL);
732 _DBUS_ZERO (*iter);
733 /* NULL is not, strictly speaking, guaranteed to be all-bits-zero */
734 iter->message = NULL;
735}
736
742void
744{
745 _dbus_return_if_fail (iter != NULL);
746 _dbus_message_real_iter_zero ((DBusMessageRealIter *) iter);
747}
748
749static dbus_bool_t
750_dbus_message_real_iter_is_zeroed (DBusMessageRealIter *iter)
751{
752 return (iter != NULL && iter->message == NULL && iter->changed_stamp == 0 &&
753 iter->iter_type == 0 && iter->sig_refcount == 0);
754}
755
756#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
757static dbus_bool_t
758_dbus_message_iter_check (DBusMessageRealIter *iter)
759{
760 char byte_order;
761
762 if (iter == NULL)
763 {
764 _dbus_warn_check_failed ("dbus message iterator is NULL");
765 return FALSE;
766 }
767
768 if (iter->message == NULL || iter->iter_type == 0)
769 {
770 _dbus_warn_check_failed ("dbus message iterator has already been "
771 "closed, or is uninitialized or corrupt");
772 return FALSE;
773 }
774
775 byte_order = _dbus_header_get_byte_order (&iter->message->header);
776
777 if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
778 {
779 if (iter->u.reader.byte_order != byte_order)
780 {
781 _dbus_warn_check_failed ("dbus message changed byte order since iterator was created");
782 return FALSE;
783 }
784 /* because we swap the message into compiler order when you init an iter */
785 _dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
786 }
787 else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
788 {
789 if (iter->u.writer.byte_order != byte_order)
790 {
791 _dbus_warn_check_failed ("dbus message changed byte order since append 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.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
796 }
797 else
798 {
799 _dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted");
800 return FALSE;
801 }
802
803 if (iter->changed_stamp != iter->message->changed_stamp)
804 {
805 _dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)");
806 return FALSE;
807 }
808
809 return TRUE;
810}
811#endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */
812
827 DBusError *error,
828 int first_arg_type,
829 va_list var_args)
830{
832 int spec_type, msg_type, i, j;
833 dbus_bool_t retval;
834 va_list copy_args;
835
836 _dbus_assert (_dbus_message_iter_check (real));
837
838 retval = FALSE;
839
840 spec_type = first_arg_type;
841 i = 0;
842
843 /* copy var_args first, then we can do another iteration over it to
844 * free memory and close unix fds if parse failed at some point.
845 */
846 DBUS_VA_COPY (copy_args, var_args);
847
848 while (spec_type != DBUS_TYPE_INVALID)
849 {
850 msg_type = dbus_message_iter_get_arg_type (iter);
851
852 if (msg_type != spec_type)
853 {
855 "Argument %d is specified to be of type \"%s\", but "
856 "is actually of type \"%s\"\n", i,
857 _dbus_type_to_string (spec_type),
858 _dbus_type_to_string (msg_type));
859
860 goto out;
861 }
862
863 if (spec_type == DBUS_TYPE_UNIX_FD)
864 {
865#ifdef HAVE_UNIX_FD_PASSING
866 DBusBasicValue idx;
867 int *pfd, nfd;
868
869 pfd = va_arg (var_args, int*);
870 _dbus_assert(pfd);
871
873
874 if (idx.u32 >= real->message->n_unix_fds)
875 {
877 "Message refers to file descriptor at index %i,"
878 "but has only %i descriptors attached.\n",
879 idx.u32,
880 real->message->n_unix_fds);
881 goto out;
882 }
883
884 if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
885 goto out;
886
887 *pfd = nfd;
888#else
890 "Platform does not support file desciptor passing.\n");
891 goto out;
892#endif
893 }
894 else if (dbus_type_is_basic (spec_type))
895 {
896 void *ptr;
897
898 ptr = va_arg (var_args, void *);
899
900 _dbus_assert (ptr != NULL);
901
903 ptr);
904 }
905 else if (spec_type == DBUS_TYPE_ARRAY)
906 {
907 int element_type;
908 int spec_element_type;
909 const void **ptr;
910 int *n_elements_p;
911 DBusTypeReader array;
912
913 spec_element_type = va_arg (var_args, int);
914 element_type = _dbus_type_reader_get_element_type (&real->u.reader);
915
916 if (spec_element_type != element_type)
917 {
919 "Argument %d is specified to be an array of \"%s\", but "
920 "is actually an array of \"%s\"\n",
921 i,
922 _dbus_type_to_string (spec_element_type),
923 _dbus_type_to_string (element_type));
924
925 goto out;
926 }
927
928 if (dbus_type_is_fixed (spec_element_type) &&
929 element_type != DBUS_TYPE_UNIX_FD)
930 {
931 ptr = va_arg (var_args, const void **);
932 n_elements_p = va_arg (var_args, int*);
933
934 _dbus_assert (ptr != NULL);
935 _dbus_assert (n_elements_p != NULL);
936
937 _dbus_type_reader_recurse (&real->u.reader, &array);
938
939 _dbus_type_reader_read_fixed_multi (&array, ptr, n_elements_p);
940 }
941 else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
942 {
943 char ***str_array_p;
944 int n_elements;
945 char **str_array;
946
947 str_array_p = va_arg (var_args, char***);
948 n_elements_p = va_arg (var_args, int*);
949
950 _dbus_assert (str_array_p != NULL);
951 _dbus_assert (n_elements_p != NULL);
952
953 /* Count elements in the array */
954 _dbus_type_reader_recurse (&real->u.reader, &array);
955
956 n_elements = 0;
958 {
959 ++n_elements;
960 _dbus_type_reader_next (&array);
961 }
962
963 str_array = dbus_new0 (char*, n_elements + 1);
964 if (str_array == NULL)
965 {
966 _DBUS_SET_OOM (error);
967 goto out;
968 }
969
970 /* Now go through and dup each string */
971 _dbus_type_reader_recurse (&real->u.reader, &array);
972
973 j = 0;
974 while (j < n_elements)
975 {
976 const char *s;
978 (void *) &s);
979
980 str_array[j] = _dbus_strdup (s);
981 if (str_array[j] == NULL)
982 {
983 dbus_free_string_array (str_array);
984 _DBUS_SET_OOM (error);
985 goto out;
986 }
987
988 ++j;
989
990 if (!_dbus_type_reader_next (&array))
991 _dbus_assert (j == n_elements);
992 }
993
995 _dbus_assert (j == n_elements);
996 _dbus_assert (str_array[j] == NULL);
997
998 *str_array_p = str_array;
999 *n_elements_p = n_elements;
1000 }
1001#ifndef DBUS_DISABLE_CHECKS
1002 else
1003 {
1004 _dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now",
1005 _DBUS_FUNCTION_NAME);
1006 goto out;
1007 }
1008#endif
1009 }
1010#ifndef DBUS_DISABLE_CHECKS
1011 else
1012 {
1013 _dbus_warn ("you can only read arrays and basic types with %s for now",
1014 _DBUS_FUNCTION_NAME);
1015 goto out;
1016 }
1017#endif
1018
1019 /* how many arguments already handled */
1020 i++;
1021
1022 spec_type = va_arg (var_args, int);
1023 if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
1024 {
1026 "Message has only %d arguments, but more were expected", i);
1027 goto out;
1028 }
1029 }
1030
1031 retval = TRUE;
1032
1033 out:
1034 /* there may memory or unix fd leak in the above iteration if parse failed.
1035 * so we have another iteration over copy_args to free memory and close
1036 * unix fds.
1037 */
1038 if (!retval)
1039 {
1040 spec_type = first_arg_type;
1041 j = 0;
1042
1043 while (j < i)
1044 {
1045 if (spec_type == DBUS_TYPE_UNIX_FD)
1046 {
1047#ifdef HAVE_UNIX_FD_PASSING
1048 int *pfd;
1049
1050 pfd = va_arg (copy_args, int *);
1051 _dbus_assert(pfd);
1052 if (*pfd >= 0)
1053 {
1054 _dbus_close (*pfd, NULL);
1055 *pfd = -1;
1056 }
1057#endif
1058 }
1059 else if (dbus_type_is_basic (spec_type))
1060 {
1061 /* move the index forward */
1062 va_arg (copy_args, const void *);
1063 }
1064 else if (spec_type == DBUS_TYPE_ARRAY)
1065 {
1066 int spec_element_type;
1067
1068 spec_element_type = va_arg (copy_args, int);
1069 if (dbus_type_is_fixed (spec_element_type))
1070 {
1071 /* move the index forward */
1072 va_arg (copy_args, const void **);
1073 va_arg (copy_args, int *);
1074 }
1075 else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
1076 {
1077 char ***str_array_p;
1078
1079 str_array_p = va_arg (copy_args, char ***);
1080 /* move the index forward */
1081 va_arg (copy_args, int *);
1082 _dbus_assert (str_array_p != NULL);
1083 dbus_free_string_array (*str_array_p);
1084 *str_array_p = NULL;
1085 }
1086 }
1087
1088 spec_type = va_arg (copy_args, int);
1089 j++;
1090 }
1091 }
1092
1093 va_end (copy_args);
1094 return retval;
1095}
1096
1155dbus_uint32_t
1157{
1158 _dbus_return_val_if_fail (message != NULL, 0);
1159
1160 return _dbus_header_get_serial (&message->header);
1161}
1162
1173 dbus_uint32_t reply_serial)
1174{
1175 DBusBasicValue value;
1176
1177 _dbus_return_val_if_fail (message != NULL, FALSE);
1178 _dbus_return_val_if_fail (!message->locked, FALSE);
1179 _dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
1180
1181 value.u32 = reply_serial;
1182
1183 return _dbus_header_set_field_basic (&message->header,
1186 &value);
1187}
1188
1195dbus_uint32_t
1197{
1198 dbus_uint32_t v_UINT32;
1199
1200 _dbus_return_val_if_fail (message != NULL, 0);
1201
1202 if (_dbus_header_get_field_basic (&message->header,
1205 &v_UINT32))
1206 return v_UINT32;
1207 else
1208 return 0;
1209}
1210
1211static void
1212dbus_message_finalize (DBusMessage *message)
1213{
1214 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1215
1216 /* This calls application callbacks! */
1218
1219 _dbus_list_foreach (&message->counters,
1220 free_counter, message);
1221 _dbus_list_clear (&message->counters);
1222
1223 _dbus_header_free (&message->header);
1224 _dbus_string_free (&message->body);
1225
1226#ifdef HAVE_UNIX_FD_PASSING
1227 close_unix_fds(message->unix_fds, &message->n_unix_fds);
1228 dbus_free(message->unix_fds);
1229#endif
1230
1231 _dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
1232
1233 dbus_free (message);
1234}
1235
1236static DBusMessage*
1237dbus_message_new_empty_header (void)
1238{
1239 DBusMessage *message;
1240 dbus_bool_t from_cache;
1241
1242 message = dbus_message_get_cached ();
1243
1244 if (message != NULL)
1245 {
1246 from_cache = TRUE;
1247 }
1248 else
1249 {
1250 from_cache = FALSE;
1251 message = dbus_new0 (DBusMessage, 1);
1252 if (message == NULL)
1253 return NULL;
1254#ifndef DBUS_DISABLE_CHECKS
1256#endif
1257
1258#ifdef HAVE_UNIX_FD_PASSING
1259 message->unix_fds = NULL;
1260 message->n_unix_fds_allocated = 0;
1261#endif
1262 }
1263
1264 _dbus_atomic_inc (&message->refcount);
1265
1266 _dbus_message_trace_ref (message, 0, 1, "new_empty_header");
1267
1268 message->locked = FALSE;
1269#ifndef DBUS_DISABLE_CHECKS
1270 message->in_cache = FALSE;
1271#endif
1272 message->counters = NULL;
1273 message->size_counter_delta = 0;
1274 message->changed_stamp = 0;
1275
1276#ifdef HAVE_UNIX_FD_PASSING
1277 message->n_unix_fds = 0;
1278 message->n_unix_fds_allocated = 0;
1279 message->unix_fd_counter_delta = 0;
1280#endif
1281
1282 if (!from_cache)
1284
1285 if (from_cache)
1286 {
1287 _dbus_header_reinit (&message->header);
1288 _dbus_string_set_length (&message->body, 0);
1289 }
1290 else
1291 {
1292 if (!_dbus_header_init (&message->header))
1293 {
1294 dbus_free (message);
1295 return NULL;
1296 }
1297
1298 if (!_dbus_string_init_preallocated (&message->body, 32))
1299 {
1300 _dbus_header_free (&message->header);
1301 dbus_free (message);
1302 return NULL;
1303 }
1304 }
1305
1306 return message;
1307}
1308
1322dbus_message_new (int message_type)
1323{
1324 DBusMessage *message;
1325
1326 _dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
1327
1328 message = dbus_message_new_empty_header ();
1329 if (message == NULL)
1330 return NULL;
1331
1332 if (!_dbus_header_create (&message->header,
1333 DBUS_COMPILER_BYTE_ORDER,
1334 message_type,
1335 NULL, NULL, NULL, NULL, NULL))
1336 {
1337 dbus_message_unref (message);
1338 return NULL;
1339 }
1340
1341 return message;
1342}
1343
1366dbus_message_new_method_call (const char *destination,
1367 const char *path,
1368 const char *iface,
1369 const char *method)
1370{
1371 DBusMessage *message;
1372
1373 _dbus_return_val_if_fail (path != NULL, NULL);
1374 _dbus_return_val_if_fail (method != NULL, NULL);
1375 _dbus_return_val_if_fail (destination == NULL ||
1376 _dbus_check_is_valid_bus_name (destination), NULL);
1377 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1378 _dbus_return_val_if_fail (iface == NULL ||
1379 _dbus_check_is_valid_interface (iface), NULL);
1380 _dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
1381
1382 message = dbus_message_new_empty_header ();
1383 if (message == NULL)
1384 return NULL;
1385
1386 if (!_dbus_header_create (&message->header,
1387 DBUS_COMPILER_BYTE_ORDER,
1389 destination, path, iface, method, NULL))
1390 {
1391 dbus_message_unref (message);
1392 return NULL;
1393 }
1394
1395 return message;
1396}
1397
1407{
1408 DBusMessage *message;
1409 const char *sender;
1410
1411 _dbus_return_val_if_fail (method_call != NULL, NULL);
1412
1413 sender = dbus_message_get_sender (method_call);
1414
1415 /* sender is allowed to be null here in peer-to-peer case */
1416
1417 message = dbus_message_new_empty_header ();
1418 if (message == NULL)
1419 return NULL;
1420
1421 if (!_dbus_header_create (&message->header,
1422 DBUS_COMPILER_BYTE_ORDER,
1424 sender, NULL, NULL, NULL, NULL))
1425 {
1426 dbus_message_unref (message);
1427 return NULL;
1428 }
1429
1431
1432 if (!dbus_message_set_reply_serial (message,
1433 dbus_message_get_serial (method_call)))
1434 {
1435 dbus_message_unref (message);
1436 return NULL;
1437 }
1438
1439 return message;
1440}
1441
1457dbus_message_new_signal (const char *path,
1458 const char *iface,
1459 const char *name)
1460{
1461 DBusMessage *message;
1462
1463 _dbus_return_val_if_fail (path != NULL, NULL);
1464 _dbus_return_val_if_fail (iface != NULL, NULL);
1465 _dbus_return_val_if_fail (name != NULL, NULL);
1466 _dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
1467 _dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
1468 _dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
1469
1470 message = dbus_message_new_empty_header ();
1471 if (message == NULL)
1472 return NULL;
1473
1474 if (!_dbus_header_create (&message->header,
1475 DBUS_COMPILER_BYTE_ORDER,
1477 NULL, path, iface, name, NULL))
1478 {
1479 dbus_message_unref (message);
1480 return NULL;
1481 }
1482
1484
1485 return message;
1486}
1487
1504 const char *error_name,
1505 const char *error_message)
1506{
1507 DBusMessage *message;
1508 const char *sender;
1509 DBusMessageIter iter;
1510
1511 _dbus_return_val_if_fail (reply_to != NULL, NULL);
1512 _dbus_return_val_if_fail (error_name != NULL, NULL);
1513 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1514
1515 sender = dbus_message_get_sender (reply_to);
1516
1517 /* sender may be NULL for non-message-bus case or
1518 * when the message bus is dealing with an unregistered
1519 * connection.
1520 */
1521 message = dbus_message_new_empty_header ();
1522 if (message == NULL)
1523 return NULL;
1524
1525 if (!_dbus_header_create (&message->header,
1526 DBUS_COMPILER_BYTE_ORDER,
1528 sender, NULL, NULL, NULL, error_name))
1529 {
1530 dbus_message_unref (message);
1531 return NULL;
1532 }
1533
1535
1536 if (!dbus_message_set_reply_serial (message,
1537 dbus_message_get_serial (reply_to)))
1538 {
1539 dbus_message_unref (message);
1540 return NULL;
1541 }
1542
1543 if (error_message != NULL)
1544 {
1545 dbus_message_iter_init_append (message, &iter);
1548 &error_message))
1549 {
1550 dbus_message_unref (message);
1551 return NULL;
1552 }
1553 }
1554
1555 return message;
1556}
1557
1576 const char *error_name,
1577 const char *error_format,
1578 ...)
1579{
1580 va_list args;
1581 DBusString str;
1582 DBusMessage *message;
1583
1584 _dbus_return_val_if_fail (reply_to != NULL, NULL);
1585 _dbus_return_val_if_fail (error_name != NULL, NULL);
1586 _dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
1587
1588 if (!_dbus_string_init (&str))
1589 return NULL;
1590
1591 va_start (args, error_format);
1592
1593 if (_dbus_string_append_printf_valist (&str, error_format, args))
1594 message = dbus_message_new_error (reply_to, error_name,
1595 _dbus_string_get_const_data (&str));
1596 else
1597 message = NULL;
1598
1599 _dbus_string_free (&str);
1600
1601 va_end (args);
1602
1603 return message;
1604}
1605
1606
1621{
1622 DBusMessage *retval;
1623
1624 _dbus_return_val_if_fail (message != NULL, NULL);
1625
1626 retval = dbus_new0 (DBusMessage, 1);
1627 if (retval == NULL)
1628 return NULL;
1629
1630 _dbus_atomic_inc (&retval->refcount);
1631
1632 retval->locked = FALSE;
1633#ifndef DBUS_DISABLE_CHECKS
1634 retval->generation = message->generation;
1635#endif
1636
1637 if (!_dbus_header_copy (&message->header, &retval->header))
1638 {
1639 dbus_free (retval);
1640 return NULL;
1641 }
1642
1643 if (!_dbus_string_init_preallocated (&retval->body,
1644 _dbus_string_get_length (&message->body)))
1645 {
1646 _dbus_header_free (&retval->header);
1647 dbus_free (retval);
1648 return NULL;
1649 }
1650
1651 if (!_dbus_string_copy (&message->body, 0,
1652 &retval->body, 0))
1653 goto failed_copy;
1654
1655#ifdef HAVE_UNIX_FD_PASSING
1656 retval->unix_fds = dbus_new(int, message->n_unix_fds);
1657 if (retval->unix_fds == NULL && message->n_unix_fds > 0)
1658 goto failed_copy;
1659
1660 retval->n_unix_fds_allocated = message->n_unix_fds;
1661
1662 for (retval->n_unix_fds = 0;
1663 retval->n_unix_fds < message->n_unix_fds;
1664 retval->n_unix_fds++)
1665 {
1666 retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
1667
1668 if (retval->unix_fds[retval->n_unix_fds] < 0)
1669 goto failed_copy;
1670 }
1671
1672#endif
1673
1674 _dbus_message_trace_ref (retval, 0, 1, "copy");
1675 return retval;
1676
1677 failed_copy:
1678 _dbus_header_free (&retval->header);
1679 _dbus_string_free (&retval->body);
1680
1681#ifdef HAVE_UNIX_FD_PASSING
1682 close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
1683 dbus_free(retval->unix_fds);
1684#endif
1685
1686 dbus_free (retval);
1687
1688 return NULL;
1689}
1690
1691
1701{
1702 dbus_int32_t old_refcount;
1703
1704 _dbus_return_val_if_fail (message != NULL, NULL);
1705 _dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
1706 _dbus_return_val_if_fail (!message->in_cache, NULL);
1707
1708 old_refcount = _dbus_atomic_inc (&message->refcount);
1709 _dbus_assert (old_refcount >= 1);
1710 _dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
1711
1712 return message;
1713}
1714
1722void
1724{
1725 dbus_int32_t old_refcount;
1726
1727 _dbus_return_if_fail (message != NULL);
1728 _dbus_return_if_fail (message->generation == _dbus_current_generation);
1729 _dbus_return_if_fail (!message->in_cache);
1730
1731 old_refcount = _dbus_atomic_dec (&message->refcount);
1732
1733 _dbus_assert (old_refcount >= 1);
1734
1735 _dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
1736
1737 if (old_refcount == 1)
1738 {
1739 /* Calls application callbacks! */
1740 dbus_message_cache_or_finalize (message);
1741 }
1742}
1743
1754int
1756{
1757 _dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
1758
1759 return _dbus_header_get_message_type (&message->header);
1760}
1761
1832 int first_arg_type,
1833 ...)
1834{
1835 dbus_bool_t retval;
1836 va_list var_args;
1837
1838 _dbus_return_val_if_fail (message != NULL, FALSE);
1839
1840 va_start (var_args, first_arg_type);
1841 retval = dbus_message_append_args_valist (message,
1842 first_arg_type,
1843 var_args);
1844 va_end (var_args);
1845
1846 return retval;
1847}
1848
1864 int first_arg_type,
1865 va_list var_args)
1866{
1867 int type;
1868 DBusMessageIter iter;
1869
1870 _dbus_return_val_if_fail (message != NULL, FALSE);
1871
1872 type = first_arg_type;
1873
1874 dbus_message_iter_init_append (message, &iter);
1875
1876 while (type != DBUS_TYPE_INVALID)
1877 {
1878 if (dbus_type_is_basic (type))
1879 {
1880 const void *value;
1881 value = va_arg (var_args, const void *);
1882
1884 type,
1885 value))
1886 goto failed;
1887 }
1888 else if (type == DBUS_TYPE_ARRAY)
1889 {
1890 int element_type;
1891 DBusMessageIter array;
1892 char buf[2];
1893
1894 element_type = va_arg (var_args, int);
1895
1896 buf[0] = element_type;
1897 buf[1] = '\0';
1900 buf,
1901 &array))
1902 goto failed;
1903
1904 if (dbus_type_is_fixed (element_type) &&
1905 element_type != DBUS_TYPE_UNIX_FD)
1906 {
1907 const void **value;
1908 int n_elements;
1909
1910 value = va_arg (var_args, const void **);
1911 n_elements = va_arg (var_args, int);
1912
1914 element_type,
1915 value,
1916 n_elements)) {
1918 goto failed;
1919 }
1920 }
1921 else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
1922 {
1923 const char ***value_p;
1924 const char **value;
1925 int n_elements;
1926 int i;
1927
1928 value_p = va_arg (var_args, const char***);
1929 n_elements = va_arg (var_args, int);
1930
1931 value = *value_p;
1932
1933 i = 0;
1934 while (i < n_elements)
1935 {
1936 if (!dbus_message_iter_append_basic (&array,
1937 element_type,
1938 &value[i])) {
1940 goto failed;
1941 }
1942 ++i;
1943 }
1944 }
1945 else
1946 {
1947 _dbus_warn ("arrays of %s can't be appended with %s for now",
1948 _dbus_type_to_string (element_type),
1949 _DBUS_FUNCTION_NAME);
1951 goto failed;
1952 }
1953
1954 if (!dbus_message_iter_close_container (&iter, &array))
1955 goto failed;
1956 }
1957#ifndef DBUS_DISABLE_CHECKS
1958 else
1959 {
1960 _dbus_warn ("type %s isn't supported yet in %s",
1961 _dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
1962 goto failed;
1963 }
1964#endif
1965
1966 type = va_arg (var_args, int);
1967 }
1968
1969 return TRUE;
1970
1971 failed:
1972 return FALSE;
1973}
1974
2021 DBusError *error,
2022 int first_arg_type,
2023 ...)
2024{
2025 dbus_bool_t retval;
2026 va_list var_args;
2027
2028 _dbus_return_val_if_fail (message != NULL, FALSE);
2029 _dbus_return_val_if_error_is_set (error, FALSE);
2030
2031 va_start (var_args, first_arg_type);
2032 retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
2033 va_end (var_args);
2034
2035 return retval;
2036}
2037
2050 DBusError *error,
2051 int first_arg_type,
2052 va_list var_args)
2053{
2054 DBusMessageIter iter;
2055
2056 _dbus_return_val_if_fail (message != NULL, FALSE);
2057 _dbus_return_val_if_error_is_set (error, FALSE);
2058
2059 dbus_message_iter_init (message, &iter);
2060 return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
2061}
2062
2063static void
2064_dbus_message_iter_init_common (DBusMessage *message,
2065 DBusMessageRealIter *real,
2066 int iter_type)
2067{
2068 /* If these static assertions fail on your platform, report it as a bug. */
2069 _DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
2070 _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <=
2071 _DBUS_ALIGNOF (DBusMessageIter));
2072 /* A failure of these two assertions would indicate that we've broken
2073 * ABI on this platform since 1.10.0. */
2074 _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) ==
2075 sizeof (DBusMessageIter));
2076 _DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) ==
2077 _DBUS_ALIGNOF (DBusMessageIter));
2078 /* If this static assertion fails, it means the DBusMessageIter struct
2079 * is not "packed", which might result in "iter = other_iter" not copying
2080 * every byte. */
2081 _DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) ==
2082 4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int));
2083
2084 /* Since the iterator will read or write who-knows-what from the
2085 * message, we need to get in the right byte order
2086 */
2087 ensure_byte_order (message);
2088
2089 real->message = message;
2090 real->changed_stamp = message->changed_stamp;
2091 real->iter_type = iter_type;
2092 real->sig_refcount = 0;
2093}
2094
2119 DBusMessageIter *iter)
2120{
2122 const DBusString *type_str;
2123 int type_pos;
2124
2125 _dbus_return_val_if_fail (message != NULL, FALSE);
2126 _dbus_return_val_if_fail (iter != NULL, FALSE);
2127
2128 get_const_signature (&message->header, &type_str, &type_pos);
2129
2130 _dbus_message_iter_init_common (message, real,
2131 DBUS_MESSAGE_ITER_TYPE_READER);
2132
2135 type_str, type_pos,
2136 &message->body,
2137 0);
2138
2140}
2141
2150{
2152
2153 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2154 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2155
2156 return _dbus_type_reader_has_next (&real->u.reader);
2157}
2158
2169{
2171
2172 _dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
2173 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2174
2175 return _dbus_type_reader_next (&real->u.reader);
2176}
2177
2192int
2194{
2196
2197 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2198 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
2199
2201}
2202
2211int
2213{
2215
2216 _dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
2217 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
2218 _dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
2219
2221}
2222
2248void
2250 DBusMessageIter *sub)
2251{
2253 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2254
2255 _dbus_return_if_fail (_dbus_message_iter_check (real));
2256 _dbus_return_if_fail (sub != NULL);
2257
2258 *real_sub = *real;
2259 _dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
2260}
2261
2273char *
2275{
2276 const DBusString *sig;
2277 DBusString retstr;
2278 char *ret = NULL;
2279 int start, len;
2281
2282 _dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
2283
2284 if (!_dbus_string_init (&retstr))
2285 return NULL;
2286
2288 &start, &len);
2289 if (!_dbus_string_append_len (&retstr,
2290 _dbus_string_get_const_data (sig) + start,
2291 len))
2292 goto oom;
2293
2294 /* This is correct whether it succeeds or fails: on success it sets `ret`,
2295 * and on failure it leaves `ret` set to NULL. */
2296 _dbus_string_steal_data (&retstr, &ret);
2297
2298oom:
2299 _dbus_string_free (&retstr);
2300 return ret;
2301}
2302
2350void
2352 void *value)
2353{
2355
2356 _dbus_return_if_fail (_dbus_message_iter_check (real));
2357 _dbus_return_if_fail (value != NULL);
2358
2360 {
2361#ifdef HAVE_UNIX_FD_PASSING
2362 DBusBasicValue idx;
2363
2365
2366 if (idx.u32 >= real->message->n_unix_fds) {
2367 /* Hmm, we cannot really signal an error here, so let's make
2368 sure to return an invalid fd. */
2369 *((int*) value) = -1;
2370 return;
2371 }
2372
2373 *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
2374#else
2375 *((int*) value) = -1;
2376#endif
2377 }
2378 else
2379 {
2381 value);
2382 }
2383}
2384
2395int
2397{
2399 DBusTypeReader array;
2400 int element_type;
2401 int n_elements = 0;
2402
2403 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2404 _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
2405 == DBUS_TYPE_ARRAY, 0);
2406
2407 element_type = _dbus_type_reader_get_element_type (&real->u.reader);
2408 _dbus_type_reader_recurse (&real->u.reader, &array);
2409 if (dbus_type_is_fixed (element_type))
2410 {
2411 int alignment = _dbus_type_get_alignment (element_type);
2412 int total_len = _dbus_type_reader_get_array_length (&array);
2413 n_elements = total_len / alignment;
2414 }
2415 else
2416 {
2418 {
2419 ++n_elements;
2420 _dbus_type_reader_next (&array);
2421 }
2422 }
2423
2424 return n_elements;
2425}
2426
2439int
2441{
2443
2444 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2445
2447}
2448
2484void
2486 void *value,
2487 int *n_elements)
2488{
2490#ifndef DBUS_DISABLE_CHECKS
2491 int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
2492
2493 _dbus_return_if_fail (_dbus_message_iter_check (real));
2494 _dbus_return_if_fail (value != NULL);
2495 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
2496 (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
2497#endif
2498
2500 value, n_elements);
2501}
2502
2514void
2516 DBusMessageIter *iter)
2517{
2519
2520 _dbus_return_if_fail (message != NULL);
2521 _dbus_return_if_fail (iter != NULL);
2522
2523 _dbus_message_iter_init_common (message, real,
2524 DBUS_MESSAGE_ITER_TYPE_WRITER);
2525
2526 /* We create the signature string and point iterators at it "on demand"
2527 * when a value is actually appended. That means that init() never fails
2528 * due to OOM.
2529 */
2532 &message->body,
2533 _dbus_string_get_length (&message->body));
2534}
2535
2544static dbus_bool_t
2545_dbus_message_iter_open_signature (DBusMessageRealIter *real)
2546{
2547 DBusString *str;
2548 const DBusString *current_sig;
2549 int current_sig_pos;
2550
2551 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2552
2553 if (real->u.writer.type_str != NULL)
2554 {
2555 _dbus_assert (real->sig_refcount > 0);
2556 real->sig_refcount += 1;
2557 return TRUE;
2558 }
2559
2560 str = dbus_new (DBusString, 1);
2561 if (str == NULL)
2562 return FALSE;
2563
2566 &current_sig, &current_sig_pos))
2567 current_sig = NULL;
2568
2569 if (current_sig)
2570 {
2571 int current_len;
2572
2573 current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
2574 current_sig_pos += 1; /* move on to sig data */
2575
2576 if (!_dbus_string_init_preallocated (str, current_len + 4))
2577 {
2578 dbus_free (str);
2579 return FALSE;
2580 }
2581
2582 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
2583 str, 0))
2584 {
2585 _dbus_string_free (str);
2586 dbus_free (str);
2587 return FALSE;
2588 }
2589 }
2590 else
2591 {
2592 if (!_dbus_string_init_preallocated (str, 4))
2593 {
2594 dbus_free (str);
2595 return FALSE;
2596 }
2597 }
2598
2599 real->sig_refcount = 1;
2600
2601 /* If this assertion failed, then str would be neither stored in u.writer
2602 * nor freed by this function, resulting in a memory leak. */
2603 _dbus_assert (real->u.writer.type_str == NULL);
2605 str, _dbus_string_get_length (str));
2606 return TRUE;
2607}
2608
2618static dbus_bool_t
2619_dbus_message_iter_close_signature (DBusMessageRealIter *real)
2620{
2621 DBusString *str;
2622 const char *v_STRING;
2623 dbus_bool_t retval;
2624
2625 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2626 _dbus_assert (real->u.writer.type_str != NULL);
2627 _dbus_assert (real->sig_refcount > 0);
2628
2629 real->sig_refcount -= 1;
2630
2631 if (real->sig_refcount > 0)
2632 return TRUE;
2633 _dbus_assert (real->sig_refcount == 0);
2634
2635 retval = TRUE;
2636
2637 str = real->u.writer.type_str;
2638
2639 v_STRING = _dbus_string_get_const_data (str);
2643 &v_STRING))
2644 retval = FALSE;
2645
2647 _dbus_string_free (str);
2648 dbus_free (str);
2649
2650 return retval;
2651}
2652
2660static void
2661_dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
2662{
2663 DBusString *str;
2664
2665 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2666 _dbus_assert (real->u.writer.type_str != NULL);
2667 _dbus_assert (real->sig_refcount > 0);
2668
2669 real->sig_refcount -= 1;
2670
2671 if (real->sig_refcount > 0)
2672 return;
2673 _dbus_assert (real->sig_refcount == 0);
2674
2675 str = real->u.writer.type_str;
2676
2678 _dbus_string_free (str);
2679 dbus_free (str);
2680}
2681
2682#ifndef DBUS_DISABLE_CHECKS
2683static dbus_bool_t
2684_dbus_message_iter_append_check (DBusMessageRealIter *iter)
2685{
2686 if (!_dbus_message_iter_check (iter))
2687 return FALSE;
2688
2689 if (iter->message->locked)
2690 {
2691 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)");
2692 return FALSE;
2693 }
2694
2695 return TRUE;
2696}
2697#endif /* DBUS_DISABLE_CHECKS */
2698
2699#ifdef HAVE_UNIX_FD_PASSING
2700static int *
2701expand_fd_array(DBusMessage *m,
2702 unsigned n)
2703{
2704 _dbus_assert(m);
2705
2706 /* This makes space for adding n new fds to the array and returns a
2707 pointer to the place were the first fd should be put. */
2708
2709 if (m->n_unix_fds + n > m->n_unix_fds_allocated)
2710 {
2711 unsigned k;
2712 int *p;
2713
2714 /* Make twice as much space as necessary */
2715 k = (m->n_unix_fds + n) * 2;
2716
2717 /* Allocate at least four */
2718 if (k < 4)
2719 k = 4;
2720
2721 p = dbus_realloc(m->unix_fds, k * sizeof(int));
2722 if (p == NULL)
2723 return NULL;
2724
2725 m->unix_fds = p;
2726 m->n_unix_fds_allocated = k;
2727 }
2728
2729 return m->unix_fds + m->n_unix_fds;
2730}
2731#endif
2732
2754 int type,
2755 const void *value)
2756{
2758 dbus_bool_t ret;
2759
2760 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2761 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2762 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
2763 _dbus_return_val_if_fail (value != NULL, FALSE);
2764
2765#ifndef DBUS_DISABLE_CHECKS
2766 switch (type)
2767 {
2768 DBusString str;
2769 DBusValidity signature_validity;
2770 const char * const *string_p;
2771 const dbus_bool_t *bool_p;
2772
2773 case DBUS_TYPE_STRING:
2774 string_p = value;
2775 _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
2776 break;
2777
2779 string_p = value;
2780 _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
2781 break;
2782
2784 string_p = value;
2785 _dbus_string_init_const (&str, *string_p);
2786 signature_validity = _dbus_validate_signature_with_reason (&str,
2787 0,
2788 _dbus_string_get_length (&str));
2789
2790 if (signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
2791 return FALSE;
2792
2793 _dbus_return_val_if_fail (signature_validity == DBUS_VALID, FALSE);
2794 break;
2795
2796 case DBUS_TYPE_BOOLEAN:
2797 bool_p = value;
2798 _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
2799 break;
2800
2801 default:
2802 {
2803 /* nothing to check, all possible values are allowed */
2804 }
2805 }
2806#endif
2807
2808 if (!_dbus_message_iter_open_signature (real))
2809 return FALSE;
2810
2811 if (type == DBUS_TYPE_UNIX_FD)
2812 {
2813#ifdef HAVE_UNIX_FD_PASSING
2814 int *fds;
2815 dbus_uint32_t u;
2816
2817 ret = FALSE;
2818
2819 /* First step, include the fd in the fd list of this message */
2820 if (!(fds = expand_fd_array(real->message, 1)))
2821 goto out;
2822
2823 *fds = _dbus_dup(*(int*) value, NULL);
2824 if (*fds < 0)
2825 goto out;
2826
2827 u = real->message->n_unix_fds;
2828
2829 /* Second step, write the index to the fd */
2830 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
2831 _dbus_close(*fds, NULL);
2832 goto out;
2833 }
2834
2835 real->message->n_unix_fds += 1;
2836 u += 1;
2837
2838 /* Final step, update the header accordingly */
2842 &u);
2843
2844 /* If any of these operations fail the message is
2845 hosed. However, no memory or fds should be leaked since what
2846 has been added to message has been added to the message, and
2847 can hence be accounted for when the message is being
2848 freed. */
2849#else
2850 ret = FALSE;
2851 /* This is redundant (we could just fall through), but it avoids
2852 * -Wunused-label in builds that don't HAVE_UNIX_FD_PASSING */
2853 goto out;
2854#endif
2855 }
2856 else
2857 {
2858 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
2859 }
2860
2861out:
2862 if (!_dbus_message_iter_close_signature (real))
2863 ret = FALSE;
2864
2865 return ret;
2866}
2867
2905 int element_type,
2906 const void *value,
2907 int n_elements)
2908{
2910 dbus_bool_t ret;
2911
2912 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2913 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2914 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
2915 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
2916 _dbus_return_val_if_fail (value != NULL, FALSE);
2917 _dbus_return_val_if_fail (n_elements >= 0, FALSE);
2918 _dbus_return_val_if_fail (n_elements <=
2920 FALSE);
2921
2922#ifndef DBUS_DISABLE_CHECKS
2923 if (element_type == DBUS_TYPE_BOOLEAN)
2924 {
2925 const dbus_bool_t * const *bools = value;
2926 int i;
2927
2928 for (i = 0; i < n_elements; i++)
2929 {
2930 _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
2931 }
2932 }
2933#endif
2934
2935 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
2936
2937 return ret;
2938}
2939
2969 int type,
2970 const char *contained_signature,
2971 DBusMessageIter *sub)
2972{
2974 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2975 DBusString contained_str;
2976 DBusValidity contained_signature_validity;
2977 dbus_bool_t ret;
2978
2979 _dbus_return_val_if_fail (sub != NULL, FALSE);
2980 /* Do our best to make sure the sub-iterator doesn't contain something
2981 * valid-looking on failure */
2982 _dbus_message_real_iter_zero (real_sub);
2983
2984 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2985 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2986 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
2987 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
2988 contained_signature == NULL) ||
2989 (type == DBUS_TYPE_DICT_ENTRY &&
2990 contained_signature == NULL) ||
2991 (type == DBUS_TYPE_VARIANT &&
2992 contained_signature != NULL) ||
2993 (type == DBUS_TYPE_ARRAY &&
2994 contained_signature != NULL), FALSE);
2995
2996 /* this would fail if the contained_signature is a dict entry, since
2997 * dict entries are invalid signatures standalone (they must be in
2998 * an array)
2999 */
3000 if (contained_signature != NULL)
3001 {
3002 _dbus_string_init_const (&contained_str, contained_signature);
3003 contained_signature_validity = _dbus_validate_signature_with_reason (&contained_str,
3004 0,
3005 _dbus_string_get_length (&contained_str));
3006
3007 if (contained_signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
3008 return FALSE;
3009 }
3010 else
3011 {
3012 /* just some placeholder value */
3013 contained_signature_validity = DBUS_VALID_BUT_INCOMPLETE;
3014 }
3015
3016 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
3017 contained_signature == NULL ||
3018 contained_signature_validity == DBUS_VALID,
3019 FALSE);
3020
3021 if (!_dbus_message_iter_open_signature (real))
3022 return FALSE;
3023
3024 ret = FALSE;
3025 *real_sub = *real;
3026
3027 if (contained_signature != NULL)
3028 {
3029 _dbus_string_init_const (&contained_str, contained_signature);
3030
3031 ret = _dbus_type_writer_recurse (&real->u.writer,
3032 type,
3033 &contained_str, 0,
3034 &real_sub->u.writer);
3035 }
3036 else
3037 {
3038 ret = _dbus_type_writer_recurse (&real->u.writer,
3039 type,
3040 NULL, 0,
3041 &real_sub->u.writer);
3042 }
3043
3044 if (!ret)
3045 _dbus_message_iter_abandon_signature (real);
3046
3047 return ret;
3048}
3049
3050
3072 DBusMessageIter *sub)
3073{
3075 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3076 dbus_bool_t ret;
3077
3078 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
3079 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3080 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
3081 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3082
3083 ret = _dbus_type_writer_unrecurse (&real->u.writer,
3084 &real_sub->u.writer);
3085 _dbus_message_real_iter_zero (real_sub);
3086
3087 if (!_dbus_message_iter_close_signature (real))
3088 ret = FALSE;
3089
3090 return ret;
3091}
3092
3104void
3106 DBusMessageIter *sub)
3107{
3109 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3110
3111#ifndef DBUS_DISABLE_CHECKS
3112 _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3113 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3114 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3115 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3116#endif
3117
3118 _dbus_message_iter_abandon_signature (real);
3119 _dbus_message_real_iter_zero (real_sub);
3120}
3121
3163void
3165 DBusMessageIter *sub)
3166{
3168 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3169
3170 /* If both the parent and the child are zeroed out, then either we didn't
3171 * even get as far as successfully recursing into the parent, or we already
3172 * closed both the child and the parent. For example, in the code sample
3173 * in the doc-comment above, this happens for
3174 * abandon_container_if_open (&outer, &inner) if the first open_container
3175 * call failed, or if we reached result = TRUE and fell through. */
3176 if (_dbus_message_real_iter_is_zeroed (real) &&
3177 _dbus_message_real_iter_is_zeroed (real_sub))
3178 return;
3179
3180#ifndef DBUS_DISABLE_CHECKS
3181 /* If the child is not zeroed out, but the parent is, then something has
3182 * gone horribly wrong (in practice that would probably mean both are
3183 * uninitialized or corrupt, and the parent happens to have ended up
3184 * all-bytes-zero). */
3185 _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3186 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3187#endif
3188
3189 /* If the parent is not zeroed out, but the child is, then either we did
3190 * not successfully open the child, or we already closed the child. This
3191 * means we do not own a reference to the parent's signature, so it would
3192 * be wrong to release it; so we must not call abandon_signature() here.
3193 * In the code sample in the doc-comment above, this happens for
3194 * abandon_container_if_open (&outer, &inner) if the second open_container
3195 * call failed, or if the second close_container call failed. */
3196 if (_dbus_message_real_iter_is_zeroed (real_sub))
3197 return;
3198
3199#ifndef DBUS_DISABLE_CHECKS
3200 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3201 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3202#endif
3203
3204 /* If neither the parent nor the child is zeroed out, then we genuinely
3205 * have an open container; close it. In the code sample in the doc-comment,
3206 * this happens for abandon_container_if_open (&outer, &inner) if the
3207 * append_basic call failed. */
3208 _dbus_message_iter_abandon_signature (real);
3209 _dbus_message_real_iter_zero (real_sub);
3210}
3211
3228void
3230 dbus_bool_t no_reply)
3231{
3232 _dbus_return_if_fail (message != NULL);
3233 _dbus_return_if_fail (!message->locked);
3234
3237 no_reply);
3238}
3239
3249{
3250 _dbus_return_val_if_fail (message != NULL, FALSE);
3251
3252 return _dbus_header_get_flag (&message->header,
3254}
3255
3270void
3272 dbus_bool_t auto_start)
3273{
3274 _dbus_return_if_fail (message != NULL);
3275 _dbus_return_if_fail (!message->locked);
3276
3279 !auto_start);
3280}
3281
3291{
3292 _dbus_return_val_if_fail (message != NULL, FALSE);
3293
3294 return !_dbus_header_get_flag (&message->header,
3296}
3297
3298
3313 const char *object_path)
3314{
3315 _dbus_return_val_if_fail (message != NULL, FALSE);
3316 _dbus_return_val_if_fail (!message->locked, FALSE);
3317 _dbus_return_val_if_fail (object_path == NULL ||
3318 _dbus_check_is_valid_path (object_path),
3319 FALSE);
3320
3321 return set_or_delete_string_field (message,
3324 object_path);
3325}
3326
3340const char*
3342{
3343 const char *v;
3344
3345 _dbus_return_val_if_fail (message != NULL, NULL);
3346
3347 v = NULL; /* in case field doesn't exist */
3351 (void *) &v);
3352 return v;
3353}
3354
3366 const char *path)
3367{
3368 const char *msg_path;
3369 msg_path = dbus_message_get_path (message);
3370
3371 if (msg_path == NULL)
3372 {
3373 if (path == NULL)
3374 return TRUE;
3375 else
3376 return FALSE;
3377 }
3378
3379 if (path == NULL)
3380 return FALSE;
3381
3382 if (strcmp (msg_path, path) == 0)
3383 return TRUE;
3384
3385 return FALSE;
3386}
3387
3410 char ***path)
3411{
3412 const char *v;
3413
3414 _dbus_return_val_if_fail (message != NULL, FALSE);
3415 _dbus_return_val_if_fail (path != NULL, FALSE);
3416
3417 *path = NULL;
3418
3419 v = dbus_message_get_path (message);
3420 if (v != NULL)
3421 {
3422 if (!_dbus_decompose_path (v, strlen (v),
3423 path, NULL))
3424 return FALSE;
3425 }
3426 return TRUE;
3427}
3428
3444 const char *iface)
3445{
3446 _dbus_return_val_if_fail (message != NULL, FALSE);
3447 _dbus_return_val_if_fail (!message->locked, FALSE);
3448 _dbus_return_val_if_fail (iface == NULL ||
3449 _dbus_check_is_valid_interface (iface),
3450 FALSE);
3451
3452 return set_or_delete_string_field (message,
3455 iface);
3456}
3457
3471const char*
3473{
3474 const char *v;
3475
3476 _dbus_return_val_if_fail (message != NULL, NULL);
3477
3478 v = NULL; /* in case field doesn't exist */
3482 (void *) &v);
3483 return v;
3484}
3485
3495 const char *iface)
3496{
3497 const char *msg_interface;
3498 msg_interface = dbus_message_get_interface (message);
3499
3500 if (msg_interface == NULL)
3501 {
3502 if (iface == NULL)
3503 return TRUE;
3504 else
3505 return FALSE;
3506 }
3507
3508 if (iface == NULL)
3509 return FALSE;
3510
3511 if (strcmp (msg_interface, iface) == 0)
3512 return TRUE;
3513
3514 return FALSE;
3515
3516}
3517
3532 const char *member)
3533{
3534 _dbus_return_val_if_fail (message != NULL, FALSE);
3535 _dbus_return_val_if_fail (!message->locked, FALSE);
3536 _dbus_return_val_if_fail (member == NULL ||
3537 _dbus_check_is_valid_member (member),
3538 FALSE);
3539
3540 return set_or_delete_string_field (message,
3543 member);
3544}
3545
3557const char*
3559{
3560 const char *v;
3561
3562 _dbus_return_val_if_fail (message != NULL, NULL);
3563
3564 v = NULL; /* in case field doesn't exist */
3568 (void *) &v);
3569 return v;
3570}
3571
3581 const char *member)
3582{
3583 const char *msg_member;
3584 msg_member = dbus_message_get_member (message);
3585
3586 if (msg_member == NULL)
3587 {
3588 if (member == NULL)
3589 return TRUE;
3590 else
3591 return FALSE;
3592 }
3593
3594 if (member == NULL)
3595 return FALSE;
3596
3597 if (strcmp (msg_member, member) == 0)
3598 return TRUE;
3599
3600 return FALSE;
3601
3602}
3603
3617 const char *error_name)
3618{
3619 _dbus_return_val_if_fail (message != NULL, FALSE);
3620 _dbus_return_val_if_fail (!message->locked, FALSE);
3621 _dbus_return_val_if_fail (error_name == NULL ||
3622 _dbus_check_is_valid_error_name (error_name),
3623 FALSE);
3624
3625 return set_or_delete_string_field (message,
3628 error_name);
3629}
3630
3641const char*
3643{
3644 const char *v;
3645
3646 _dbus_return_val_if_fail (message != NULL, NULL);
3647
3648 v = NULL; /* in case field doesn't exist */
3652 (void *) &v);
3653 return v;
3654}
3655
3671 const char *destination)
3672{
3673 _dbus_return_val_if_fail (message != NULL, FALSE);
3674 _dbus_return_val_if_fail (!message->locked, FALSE);
3675 _dbus_return_val_if_fail (destination == NULL ||
3676 _dbus_check_is_valid_bus_name (destination),
3677 FALSE);
3678
3679 return set_or_delete_string_field (message,
3682 destination);
3683}
3684
3694const char*
3696{
3697 const char *v;
3698
3699 _dbus_return_val_if_fail (message != NULL, NULL);
3700
3701 v = NULL; /* in case field doesn't exist */
3705 (void *) &v);
3706 return v;
3707}
3708
3725 const char *sender)
3726{
3727 _dbus_return_val_if_fail (message != NULL, FALSE);
3728 _dbus_return_val_if_fail (!message->locked, FALSE);
3729 _dbus_return_val_if_fail (sender == NULL ||
3730 _dbus_check_is_valid_bus_name (sender),
3731 FALSE);
3732
3733 return set_or_delete_string_field (message,
3736 sender);
3737}
3738
3754const char*
3756{
3757 const char *v;
3758
3759 _dbus_return_val_if_fail (message != NULL, NULL);
3760
3761 v = NULL; /* in case field doesn't exist */
3765 (void *) &v);
3766 return v;
3767}
3768
3787const char*
3789{
3790 const DBusString *type_str;
3791 int type_pos;
3792
3793 _dbus_return_val_if_fail (message != NULL, NULL);
3794
3795 get_const_signature (&message->header, &type_str, &type_pos);
3796
3797 return _dbus_string_get_const_data_len (type_str, type_pos, 0);
3798}
3799
3800static dbus_bool_t
3801_dbus_message_has_type_interface_member (DBusMessage *message,
3802 int type,
3803 const char *iface,
3804 const char *member)
3805{
3806 const char *n;
3807
3808 _dbus_assert (message != NULL);
3809 _dbus_assert (iface != NULL);
3810 _dbus_assert (member != NULL);
3811
3812 if (dbus_message_get_type (message) != type)
3813 return FALSE;
3814
3815 /* Optimize by checking the short member name first
3816 * instead of the longer interface name
3817 */
3818
3819 n = dbus_message_get_member (message);
3820
3821 if (n && strcmp (n, member) == 0)
3822 {
3823 n = dbus_message_get_interface (message);
3824
3825 if (n == NULL || strcmp (n, iface) == 0)
3826 return TRUE;
3827 }
3828
3829 return FALSE;
3830}
3831
3848 const char *iface,
3849 const char *method)
3850{
3851 _dbus_return_val_if_fail (message != NULL, FALSE);
3852 _dbus_return_val_if_fail (iface != NULL, FALSE);
3853 _dbus_return_val_if_fail (method != NULL, FALSE);
3854 /* don't check that interface/method are valid since it would be
3855 * expensive, and not catch many common errors
3856 */
3857
3858 return _dbus_message_has_type_interface_member (message,
3860 iface, method);
3861}
3862
3876 const char *iface,
3877 const char *signal_name)
3878{
3879 _dbus_return_val_if_fail (message != NULL, FALSE);
3880 _dbus_return_val_if_fail (iface != NULL, FALSE);
3881 _dbus_return_val_if_fail (signal_name != NULL, FALSE);
3882 /* don't check that interface/name are valid since it would be
3883 * expensive, and not catch many common errors
3884 */
3885
3886 return _dbus_message_has_type_interface_member (message,
3888 iface, signal_name);
3889}
3890
3903 const char *error_name)
3904{
3905 const char *n;
3906
3907 _dbus_return_val_if_fail (message != NULL, FALSE);
3908 _dbus_return_val_if_fail (error_name != NULL, FALSE);
3909 /* don't check that error_name is valid since it would be expensive,
3910 * and not catch many common errors
3911 */
3912
3914 return FALSE;
3915
3916 n = dbus_message_get_error_name (message);
3917
3918 if (n && strcmp (n, error_name) == 0)
3919 return TRUE;
3920 else
3921 return FALSE;
3922}
3923
3936 const char *name)
3937{
3938 const char *s;
3939
3940 _dbus_return_val_if_fail (message != NULL, FALSE);
3941 _dbus_return_val_if_fail (name != NULL, FALSE);
3942 /* don't check that name is valid since it would be expensive, and
3943 * not catch many common errors
3944 */
3945
3946 s = dbus_message_get_destination (message);
3947
3948 if (s && strcmp (s, name) == 0)
3949 return TRUE;
3950 else
3951 return FALSE;
3952}
3953
3971 const char *name)
3972{
3973 const char *s;
3974
3975 _dbus_return_val_if_fail (message != NULL, FALSE);
3976 _dbus_return_val_if_fail (name != NULL, FALSE);
3977 /* don't check that name is valid since it would be expensive, and
3978 * not catch many common errors
3979 */
3980
3981 s = dbus_message_get_sender (message);
3982
3983 if (s && strcmp (s, name) == 0)
3984 return TRUE;
3985 else
3986 return FALSE;
3987}
3988
4000 const char *signature)
4001{
4002 const char *s;
4003
4004 _dbus_return_val_if_fail (message != NULL, FALSE);
4005 _dbus_return_val_if_fail (signature != NULL, FALSE);
4006 /* don't check that signature is valid since it would be expensive,
4007 * and not catch many common errors
4008 */
4009
4010 s = dbus_message_get_signature (message);
4011
4012 if (s && strcmp (s, signature) == 0)
4013 return TRUE;
4014 else
4015 return FALSE;
4016}
4017
4042 DBusMessage *message)
4043{
4044 const char *str;
4045
4046 _dbus_return_val_if_fail (message != NULL, FALSE);
4047 _dbus_return_val_if_error_is_set (error, FALSE);
4048
4050 return FALSE;
4051
4052 str = NULL;
4053 dbus_message_get_args (message, NULL,
4054 DBUS_TYPE_STRING, &str,
4056
4058 str ? "%s" : NULL, str);
4059
4060 return TRUE;
4061}
4062
4071{
4072#ifdef HAVE_UNIX_FD_PASSING
4073 _dbus_assert(message);
4074
4075 return message->n_unix_fds > 0;
4076#else
4077 return FALSE;
4078#endif
4079}
4080
4093 const char *object_path)
4094{
4095 _dbus_return_val_if_fail (message != NULL, FALSE);
4096 _dbus_return_val_if_fail (!message->locked, FALSE);
4097 _dbus_return_val_if_fail (object_path == NULL ||
4098 _dbus_check_is_valid_path (object_path),
4099 FALSE);
4100
4101 return set_or_delete_string_field (message,
4104 object_path);
4105}
4106
4117const char *
4119{
4120 const char *v;
4121
4122 _dbus_return_val_if_fail (message != NULL, NULL);
4123
4124 v = NULL; /* in case field doesn't exist */
4128 (void *) &v);
4129 return v;
4130}
4131
4150#define INITIAL_LOADER_DATA_LEN 32
4151
4160{
4161 DBusMessageLoader *loader;
4162
4163 loader = dbus_new0 (DBusMessageLoader, 1);
4164 if (loader == NULL)
4165 return NULL;
4166
4167 loader->refcount = 1;
4168
4169 loader->corrupted = FALSE;
4170 loader->corruption_reason = DBUS_VALID;
4171
4172 /* this can be configured by the app, but defaults to the protocol max */
4174
4175 /* We set a very relatively conservative default here since due to how
4176 SCM_RIGHTS works we need to preallocate an fd array of the maximum
4177 number of unix fds we want to receive in advance. A
4178 try-and-reallocate loop is not possible. */
4179 loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
4180
4181 if (!_dbus_string_init (&loader->data))
4182 {
4183 dbus_free (loader);
4184 return NULL;
4185 }
4186
4187 /* preallocate the buffer for speed, ignore failure */
4189 _dbus_string_set_length (&loader->data, 0);
4190
4191#ifdef HAVE_UNIX_FD_PASSING
4192 loader->unix_fds = NULL;
4193 loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
4194 loader->unix_fds_outstanding = FALSE;
4195#endif
4196
4197 return loader;
4198}
4199
4208{
4209 loader->refcount += 1;
4210
4211 return loader;
4212}
4213
4220void
4222{
4223 loader->refcount -= 1;
4224 if (loader->refcount == 0)
4225 {
4226#ifdef HAVE_UNIX_FD_PASSING
4227 close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
4228 dbus_free(loader->unix_fds);
4229#endif
4232 _dbus_string_free (&loader->data);
4233 dbus_free (loader);
4234 }
4235}
4236
4255void
4257 DBusString **buffer,
4258 int *max_to_read,
4259 dbus_bool_t *may_read_fds)
4260{
4262
4263 *buffer = &loader->data;
4264
4265 loader->buffer_outstanding = TRUE;
4266
4267 if (max_to_read != NULL)
4268 {
4269#ifdef HAVE_UNIX_FD_PASSING
4270 int offset = 0;
4271 int remain;
4272 int byte_order;
4273 int fields_array_len;
4274 int header_len;
4275 int body_len;
4276#endif
4277
4278 *max_to_read = DBUS_MAXIMUM_MESSAGE_LENGTH;
4279 *may_read_fds = TRUE;
4280
4281#ifdef HAVE_UNIX_FD_PASSING
4282 /* If we aren't holding onto any fds, we can read as much as we want
4283 * (fast path). */
4284 if (loader->n_unix_fds == 0)
4285 return;
4286
4287 /* Slow path: we have a message with some fds in it. We don't want
4288 * to start on the next message until this one is out of the way;
4289 * otherwise a legitimate sender can keep us processing messages
4290 * containing fds, until we disconnect it for having had fds pending
4291 * for too long, a limit that is in place to stop malicious senders
4292 * from setting up recursive fd-passing that takes up our quota and
4293 * will never go away. */
4294
4295 remain = _dbus_string_get_length (&loader->data);
4296
4297 while (remain > 0)
4298 {
4299 DBusValidity validity = DBUS_VALIDITY_UNKNOWN;
4300 int needed;
4301
4302 /* If 0 < remain < DBUS_MINIMUM_HEADER_SIZE, then we've had at
4303 * least the first byte of a message, but we don't know how
4304 * much more to read. Only read the rest of the
4305 * DBUS_MINIMUM_HEADER_SIZE for now; then we'll know. */
4306 if (remain < DBUS_MINIMUM_HEADER_SIZE)
4307 {
4308 *max_to_read = DBUS_MINIMUM_HEADER_SIZE - remain;
4309 *may_read_fds = FALSE;
4310 return;
4311 }
4312
4314 &validity,
4315 &byte_order,
4316 &fields_array_len,
4317 &header_len,
4318 &body_len,
4319 &loader->data,
4320 offset,
4321 remain))
4322 {
4323 /* If a message in the buffer is invalid, we're going to
4324 * disconnect the sender anyway, so reading an arbitrary amount
4325 * is fine. */
4326 if (validity != DBUS_VALID)
4327 return;
4328
4329 /* We have a partial message, with the
4330 * DBUS_MINIMUM_HEADER_SIZE-byte fixed part of the header (which
4331 * lets us work out how much more we need), but no more. Read
4332 * the rest of the message. */
4333 needed = header_len + body_len;
4334 _dbus_assert (needed > remain);
4335 *max_to_read = needed - remain;
4336 *may_read_fds = FALSE;
4337 return;
4338 }
4339
4340 /* Skip over entire messages until we have less than a message
4341 * remaining. */
4342 needed = header_len + body_len;
4344 _dbus_assert (remain >= needed);
4345 remain -= needed;
4346 offset += needed;
4347 }
4348#endif
4349 }
4350}
4351
4361void
4363 DBusString *buffer)
4364{
4366 _dbus_assert (buffer == &loader->data);
4367
4368 loader->buffer_outstanding = FALSE;
4369}
4370
4371#ifdef HAVE_UNIX_FD_PASSING
4383_dbus_message_loader_get_unix_fds(DBusMessageLoader *loader,
4384 int **fds,
4385 unsigned *max_n_fds)
4386{
4387 _dbus_assert (!loader->unix_fds_outstanding);
4388
4389 /* Allocate space where we can put the fds we read. We allocate
4390 space for max_message_unix_fds since this is an
4391 upper limit how many fds can be received within a single
4392 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
4393 we are allocating the maximum possible array size right from the
4394 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
4395 there is no better way. */
4396
4397 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
4398 {
4399 int *a = dbus_realloc(loader->unix_fds,
4400 loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
4401
4402 if (!a)
4403 return FALSE;
4404
4405 loader->unix_fds = a;
4406 loader->n_unix_fds_allocated = loader->max_message_unix_fds;
4407 }
4408
4409 *fds = loader->unix_fds + loader->n_unix_fds;
4410 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
4411
4412 loader->unix_fds_outstanding = TRUE;
4413 return TRUE;
4414}
4415
4426void
4427_dbus_message_loader_return_unix_fds(DBusMessageLoader *loader,
4428 int *fds,
4429 unsigned n_fds)
4430{
4431 _dbus_assert(loader->unix_fds_outstanding);
4432 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
4433 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
4434
4435 loader->n_unix_fds += n_fds;
4436 loader->unix_fds_outstanding = FALSE;
4437
4438 if (n_fds && loader->unix_fds_change)
4439 loader->unix_fds_change (loader->unix_fds_change_data);
4440}
4441#endif
4442
4443/*
4444 * FIXME when we move the header out of the buffer, that memmoves all
4445 * buffered messages. Kind of crappy.
4446 *
4447 * Also we copy the header and body, which is kind of crappy. To
4448 * avoid this, we have to allow header and body to be in a single
4449 * memory block, which is good for messages we read and bad for
4450 * messages we are creating. But we could move_len() the buffer into
4451 * this single memory block, and move_len() will just swap the buffers
4452 * if you're moving the entire buffer replacing the dest string.
4453 *
4454 * We could also have the message loader tell the transport how many
4455 * bytes to read; so it would first ask for some arbitrary number like
4456 * 256, then if the message was incomplete it would use the
4457 * header/body len to ask for exactly the size of the message (or
4458 * blocks the size of a typical kernel buffer for the socket). That
4459 * way we don't get trailing bytes in the buffer that have to be
4460 * memmoved. Though I suppose we also don't have a chance of reading a
4461 * bunch of small messages at once, so the optimization may be stupid.
4462 *
4463 * Another approach would be to keep a "start" index into
4464 * loader->data and only delete it occasionally, instead of after
4465 * each message is loaded.
4466 *
4467 * load_message() returns FALSE if not enough memory OR the loader was corrupted
4468 */
4469static dbus_bool_t
4470load_message (DBusMessageLoader *loader,
4471 DBusMessage *message,
4472 int byte_order,
4473 int fields_array_len,
4474 int header_len,
4475 int body_len)
4476{
4477 dbus_bool_t oom;
4478 DBusValidity validity;
4479 const DBusString *type_str;
4480 int type_pos;
4481 DBusValidationMode mode;
4482 dbus_uint32_t n_unix_fds = 0;
4483
4484 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
4485
4486 oom = FALSE;
4487
4488#if 0
4489 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
4490#endif
4491
4492 /* 1. VALIDATE AND COPY OVER HEADER */
4493 _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
4494 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
4495
4496 if (!_dbus_header_load (&message->header,
4497 mode,
4498 &validity,
4499 byte_order,
4500 fields_array_len,
4501 header_len,
4502 body_len,
4503 &loader->data))
4504 {
4505 _dbus_verbose ("Failed to load header for new message code %d\n", validity);
4506
4507 /* assert here so we can catch any code that still uses DBUS_VALID to indicate
4508 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
4509 _dbus_assert (validity != DBUS_VALID);
4510
4511 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
4512 oom = TRUE;
4513 else
4514 {
4515 loader->corrupted = TRUE;
4516 loader->corruption_reason = validity;
4517 }
4518 goto failed;
4519 }
4520
4521 _dbus_assert (validity == DBUS_VALID);
4522
4523 /* 2. VALIDATE BODY */
4524 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
4525 {
4526 get_const_signature (&message->header, &type_str, &type_pos);
4527
4528 /* Because the bytes_remaining arg is NULL, this validates that the
4529 * body is the right length
4530 */
4531 validity = _dbus_validate_body_with_reason (type_str,
4532 type_pos,
4533 byte_order,
4534 NULL,
4535 &loader->data,
4536 header_len,
4537 body_len);
4538 if (validity != DBUS_VALID)
4539 {
4540 _dbus_verbose ("Failed to validate message body code %d\n", validity);
4541
4542 loader->corrupted = TRUE;
4543 loader->corruption_reason = validity;
4544
4545 goto failed;
4546 }
4547 }
4548
4549 /* 3. COPY OVER UNIX FDS */
4553 &n_unix_fds);
4554
4555#ifdef HAVE_UNIX_FD_PASSING
4556
4557 if (n_unix_fds > loader->n_unix_fds)
4558 {
4559 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
4560 n_unix_fds, loader->n_unix_fds);
4561
4562 loader->corrupted = TRUE;
4563 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4564 goto failed;
4565 }
4566
4567 /* If this was a recycled message there might still be
4568 some memory allocated for the fds */
4569 dbus_free(message->unix_fds);
4570
4571 if (n_unix_fds > 0)
4572 {
4573 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
4574 if (message->unix_fds == NULL)
4575 {
4576 _dbus_verbose ("Failed to allocate file descriptor array\n");
4577 oom = TRUE;
4578 goto failed;
4579 }
4580
4581 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
4582 loader->n_unix_fds -= n_unix_fds;
4583 memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
4584
4585 if (loader->unix_fds_change)
4586 loader->unix_fds_change (loader->unix_fds_change_data);
4587 }
4588 else
4589 message->unix_fds = NULL;
4590
4591#else
4592
4593 if (n_unix_fds > 0)
4594 {
4595 _dbus_verbose ("Hmm, message claims to come with file descriptors "
4596 "but that's not supported on our platform, disconnecting.\n");
4597
4598 loader->corrupted = TRUE;
4599 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4600 goto failed;
4601 }
4602
4603#endif
4604
4605 /* 3. COPY OVER BODY AND QUEUE MESSAGE */
4606
4607 if (!_dbus_list_append (&loader->messages, message))
4608 {
4609 _dbus_verbose ("Failed to append new message to loader queue\n");
4610 oom = TRUE;
4611 goto failed;
4612 }
4613
4614 _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4615 _dbus_assert (_dbus_string_get_length (&loader->data) >=
4616 (header_len + body_len));
4617
4618 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
4619 {
4620 _dbus_verbose ("Failed to move body into new message\n");
4621 oom = TRUE;
4622 goto failed;
4623 }
4624
4625 _dbus_string_delete (&loader->data, 0, header_len + body_len);
4626
4627 /* don't waste more than 2k of memory */
4628 _dbus_string_compact (&loader->data, 2048);
4629
4630 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
4631 _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4632
4633 _dbus_verbose ("Loaded message %p\n", message);
4634
4635 _dbus_assert (!oom);
4636 _dbus_assert (!loader->corrupted);
4637 _dbus_assert (loader->messages != NULL);
4638 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4639
4640 return TRUE;
4641
4642 failed:
4643
4644 /* Clean up */
4645
4646 /* does nothing if the message isn't in the list */
4647 _dbus_list_remove_last (&loader->messages, message);
4648
4649 if (oom)
4650 _dbus_assert (!loader->corrupted);
4651 else
4652 _dbus_assert (loader->corrupted);
4653
4654 _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
4655
4656 return FALSE;
4657}
4658
4675{
4676 while (!loader->corrupted &&
4677 _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
4678 {
4679 DBusValidity validity;
4680 int byte_order, fields_array_len, header_len, body_len;
4681
4683 &validity,
4684 &byte_order,
4685 &fields_array_len,
4686 &header_len,
4687 &body_len,
4688 &loader->data, 0,
4689 _dbus_string_get_length (&loader->data)))
4690 {
4691 DBusMessage *message;
4692
4693 _dbus_assert (validity == DBUS_VALID);
4694
4695 message = dbus_message_new_empty_header ();
4696 if (message == NULL)
4697 return FALSE;
4698
4699 if (!load_message (loader, message,
4700 byte_order, fields_array_len,
4701 header_len, body_len))
4702 {
4703 dbus_message_unref (message);
4704 /* load_message() returns false if corrupted or OOM; if
4705 * corrupted then return TRUE for not OOM
4706 */
4707 return loader->corrupted;
4708 }
4709
4710 _dbus_assert (loader->messages != NULL);
4711 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4712 }
4713 else
4714 {
4715 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
4716 validity);
4717 if (validity != DBUS_VALID)
4718 {
4719 loader->corrupted = TRUE;
4720 loader->corruption_reason = validity;
4721 }
4722 return TRUE;
4723 }
4724 }
4725
4726 return TRUE;
4727}
4728
4738{
4739 if (loader->messages)
4740 return loader->messages->data;
4741 else
4742 return NULL;
4743}
4744
4755{
4756 return _dbus_list_pop_first (&loader->messages);
4757}
4758
4767DBusList*
4769{
4770 return _dbus_list_pop_first_link (&loader->messages);
4771}
4772
4779void
4781 DBusList *link)
4782{
4783 _dbus_list_prepend_link (&loader->messages, link);
4784}
4785
4797{
4798 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4799 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4800 return loader->corrupted;
4801}
4802
4811{
4812 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4813 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4814
4815 return loader->corruption_reason;
4816}
4817
4824void
4826 long size)
4827{
4828 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
4829 {
4830 _dbus_verbose ("clamping requested max message size %ld to %d\n",
4833 }
4834 loader->max_message_size = size;
4835}
4836
4843long
4845{
4846 return loader->max_message_size;
4847}
4848
4855void
4857 long n)
4858{
4860 {
4861 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
4864 }
4865 loader->max_message_unix_fds = n;
4866}
4867
4874long
4876{
4877 return loader->max_message_unix_fds;
4878}
4879
4885int
4887{
4888#ifdef HAVE_UNIX_FD_PASSING
4889 return loader->n_unix_fds;
4890#else
4891 return 0;
4892#endif
4893}
4894
4903void
4905 void (* callback) (void *),
4906 void *data)
4907{
4908#ifdef HAVE_UNIX_FD_PASSING
4909 loader->unix_fds_change = callback;
4910 loader->unix_fds_change_data = data;
4911#endif
4912}
4913
4914static DBusDataSlotAllocator slot_allocator =
4915 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
4916
4933{
4934 return _dbus_data_slot_allocator_alloc (&slot_allocator,
4935 slot_p);
4936}
4937
4949void
4950dbus_message_free_data_slot (dbus_int32_t *slot_p)
4951{
4952 _dbus_return_if_fail (*slot_p >= 0);
4953
4954 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
4955}
4956
4972 dbus_int32_t slot,
4973 void *data,
4974 DBusFreeFunction free_data_func)
4975{
4976 DBusFreeFunction old_free_func;
4977 void *old_data;
4978 dbus_bool_t retval;
4979
4980 _dbus_return_val_if_fail (message != NULL, FALSE);
4981 _dbus_return_val_if_fail (slot >= 0, FALSE);
4982
4983 retval = _dbus_data_slot_list_set (&slot_allocator,
4984 &message->slot_list,
4985 slot, data, free_data_func,
4986 &old_free_func, &old_data);
4987
4988 if (retval)
4989 {
4990 /* Do the actual free outside the message lock */
4991 if (old_free_func)
4992 (* old_free_func) (old_data);
4993 }
4994
4995 return retval;
4996}
4997
5006void*
5008 dbus_int32_t slot)
5009{
5010 void *res;
5011
5012 _dbus_return_val_if_fail (message != NULL, NULL);
5013
5014 res = _dbus_data_slot_list_get (&slot_allocator,
5015 &message->slot_list,
5016 slot);
5017
5018 return res;
5019}
5020
5034int
5035dbus_message_type_from_string (const char *type_str)
5036{
5037 if (strcmp (type_str, "method_call") == 0)
5039 if (strcmp (type_str, "method_return") == 0)
5041 else if (strcmp (type_str, "signal") == 0)
5043 else if (strcmp (type_str, "error") == 0)
5045 else
5047}
5048
5062const char *
5064{
5065 switch (type)
5066 {
5068 return "method_call";
5070 return "method_return";
5072 return "signal";
5074 return "error";
5075 default:
5076 return "invalid";
5077 }
5078}
5079
5094 char **marshalled_data_p,
5095 int *len_p)
5096{
5097 DBusString tmp;
5098 dbus_bool_t was_locked;
5099
5100 _dbus_return_val_if_fail (msg != NULL, FALSE);
5101 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
5102 _dbus_return_val_if_fail (len_p != NULL, FALSE);
5103
5104 if (!_dbus_string_init (&tmp))
5105 return FALSE;
5106
5107 /* Ensure the message is locked, to ensure the length header is filled in. */
5108 was_locked = msg->locked;
5109
5110 if (!was_locked)
5111 dbus_message_lock (msg);
5112
5113 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
5114 goto fail;
5115
5116 *len_p = _dbus_string_get_length (&tmp);
5117
5118 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
5119 goto fail;
5120
5121 *len_p = _dbus_string_get_length (&tmp);
5122
5123 if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
5124 goto fail;
5125
5126 _dbus_string_free (&tmp);
5127
5128 if (!was_locked)
5129 msg->locked = FALSE;
5130
5131 return TRUE;
5132
5133 fail:
5134 _dbus_string_free (&tmp);
5135
5136 if (!was_locked)
5137 msg->locked = FALSE;
5138
5139 return FALSE;
5140}
5141
5155dbus_message_demarshal (const char *str,
5156 int len,
5157 DBusError *error)
5158{
5159 DBusMessageLoader *loader = NULL;
5160 DBusString *buffer;
5161 DBusMessage *msg;
5162
5163 _dbus_return_val_if_fail (str != NULL, NULL);
5164
5165 loader = _dbus_message_loader_new ();
5166
5167 if (loader == NULL)
5168 goto fail_oom;
5169
5170 _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
5171
5172 if (!_dbus_string_append_len (buffer, str, len))
5173 goto fail_oom;
5174
5175 _dbus_message_loader_return_buffer (loader, buffer);
5176
5178 goto fail_oom;
5179
5181 goto fail_corrupt;
5182
5183 msg = _dbus_message_loader_pop_message (loader);
5184
5185 if (!msg)
5186 goto fail_oom;
5187
5189 return msg;
5190
5191 fail_corrupt:
5193 goto fail_oom;
5194
5195 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
5196 _dbus_validity_to_error_message (loader->corruption_reason));
5198 return NULL;
5199
5200 fail_oom:
5201 _DBUS_SET_OOM (error);
5202
5203 if (loader != NULL)
5205
5206 return NULL;
5207}
5208
5221int
5223 int len)
5224{
5225 DBusString str;
5226 int byte_order, fields_array_len, header_len, body_len;
5227 DBusValidity validity = DBUS_VALID;
5228 int have_message;
5229
5230 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
5231 return 0;
5232
5235 _dbus_string_init_const_len (&str, buf, len);
5236
5237 validity = DBUS_VALID;
5238 have_message
5240 &validity, &byte_order,
5241 &fields_array_len,
5242 &header_len,
5243 &body_len,
5244 &str, 0,
5245 len);
5246 _dbus_string_free (&str);
5247
5248 if (validity == DBUS_VALID)
5249 {
5250 _dbus_assert (have_message || (header_len + body_len) > len);
5251 (void) have_message; /* unused unless asserting */
5252 return header_len + body_len;
5253 }
5254 else
5255 {
5256 return -1; /* broken! */
5257 }
5258}
5259
5281void
5283 dbus_bool_t allow)
5284{
5285 _dbus_return_if_fail (message != NULL);
5286 _dbus_return_if_fail (!message->locked);
5287
5290 allow);
5291}
5292
5301{
5302 _dbus_return_val_if_fail (message != NULL, FALSE);
5303
5304 return _dbus_header_get_flag (&message->header,
5306}
5307
5315{
5316 DBusString data;
5317};
5318
5332{
5333 DBusVariant *self = NULL;
5334 /* Points to the single item we will read from the reader */
5335 DBusMessageRealIter *real_reader = (DBusMessageRealIter *) reader;
5336 /* The position in self at which we will write a single variant
5337 * (it is position 0) */
5338 DBusTypeWriter items_writer;
5339 /* The position in self at which we will write a copy of reader
5340 * (it is inside the variant) */
5341 DBusTypeWriter variant_writer;
5342 /* 'v' */
5343 DBusString variant_signature;
5344 /* Whatever is the signature of the item we will copy from the reader */
5345 DBusString contained_signature;
5346 /* TRUE if self->data needs to be freed */
5347 dbus_bool_t data_inited = FALSE;
5348 /* The type of the item we will read from the reader */
5349 int type;
5350 /* The string, start position within that string, and length of the signature
5351 * of the single complete type of the item reader points to */
5352 const DBusString *sig;
5353 int start, len;
5354
5355 _dbus_assert (_dbus_message_iter_check (real_reader));
5356 _dbus_assert (real_reader->iter_type == DBUS_MESSAGE_ITER_TYPE_READER);
5358 type = dbus_message_iter_get_arg_type (reader);
5359 _dbus_type_reader_get_signature (&real_reader->u.reader, &sig, &start, &len);
5360
5361 if (!_dbus_string_init (&contained_signature))
5362 return NULL;
5363
5364 if (!_dbus_string_copy_len (sig, start, len, &contained_signature, 0))
5365 goto oom;
5366
5367 self = dbus_new0 (DBusVariant, 1);
5368
5369 if (self == NULL)
5370 goto oom;
5371
5372 if (!_dbus_string_init (&self->data))
5373 goto oom;
5374
5375 data_inited = TRUE;
5376
5377 _dbus_type_writer_init_values_only (&items_writer, DBUS_COMPILER_BYTE_ORDER,
5378 &variant_signature, 0, &self->data, 0);
5379
5380 if (!_dbus_type_writer_recurse (&items_writer, DBUS_TYPE_VARIANT,
5381 &contained_signature, 0, &variant_writer))
5382 goto oom;
5383
5384 if (type == DBUS_TYPE_ARRAY)
5385 {
5386 /* Points to each item in turn inside the array we are copying */
5387 DBusMessageIter array_reader;
5388 /* Same as array_reader */
5389 DBusMessageRealIter *real_array_reader = (DBusMessageRealIter *) &array_reader;
5390 /* The position inside the copied array at which we will write
5391 * the copy of array_reader */
5392 DBusTypeWriter array_writer;
5393
5394 dbus_message_iter_recurse (reader, &array_reader);
5395
5396 if (!_dbus_type_writer_recurse (&variant_writer, type,
5397 &contained_signature, 1, &array_writer))
5398 goto oom;
5399
5400 if (!_dbus_type_writer_write_reader (&array_writer,
5401 &real_array_reader->u.reader))
5402 goto oom;
5403
5404 if (!_dbus_type_writer_unrecurse (&variant_writer, &array_writer))
5405 goto oom;
5406 }
5407 else if (type == DBUS_TYPE_DICT_ENTRY || type == DBUS_TYPE_VARIANT ||
5408 type == DBUS_TYPE_STRUCT)
5409 {
5410 /* Points to each item in turn inside the container we are copying */
5411 DBusMessageIter inner_reader;
5412 /* Same as inner_reader */
5413 DBusMessageRealIter *real_inner_reader = (DBusMessageRealIter *) &inner_reader;
5414 /* The position inside the copied container at which we will write the
5415 * copy of inner_reader */
5416 DBusTypeWriter inner_writer;
5417
5418 dbus_message_iter_recurse (reader, &inner_reader);
5419
5420 if (!_dbus_type_writer_recurse (&variant_writer, type, NULL, 0,
5421 &inner_writer))
5422 goto oom;
5423
5424 if (!_dbus_type_writer_write_reader (&inner_writer,
5425 &real_inner_reader->u.reader))
5426 goto oom;
5427
5428 if (!_dbus_type_writer_unrecurse (&variant_writer, &inner_writer))
5429 goto oom;
5430 }
5431 else
5432 {
5433 DBusBasicValue value;
5434
5435 /* We eliminated all the container types above */
5437
5438 dbus_message_iter_get_basic (reader, &value);
5439
5440 if (!_dbus_type_writer_write_basic (&variant_writer, type, &value))
5441 goto oom;
5442 }
5443
5444 _dbus_string_free (&contained_signature);
5445 return self;
5446
5447oom:
5448 if (self != NULL)
5449 {
5450 if (data_inited)
5451 _dbus_string_free (&self->data);
5452
5453 dbus_free (self);
5454 }
5455
5456 _dbus_string_free (&contained_signature);
5457 return NULL;
5458}
5459
5466const char *
5468{
5469 unsigned char len;
5470 const char *ret;
5471
5472 _dbus_assert (self != NULL);
5473
5474 /* Here we make use of the fact that the serialization of a variant starts
5475 * with the 1-byte length, then that many bytes of signature, then \0. */
5476 len = _dbus_string_get_byte (&self->data, 0);
5477 ret = _dbus_string_get_const_data_len (&self->data, 1, len);
5478 _dbus_assert (strlen (ret) == len);
5479 return ret;
5480}
5481
5495 DBusMessageIter *writer)
5496{
5497 /* 'v' */
5498 DBusString variant_signature;
5499 /* Points to the single item in self */
5500 DBusTypeReader variant_reader;
5501 /* Points to the single item (of whatever type) inside the variant */
5502 DBusTypeReader reader;
5503 /* The position at which we will copy reader */
5504 DBusMessageRealIter *real_writer = (DBusMessageRealIter *) writer;
5505 dbus_bool_t ret;
5506
5507 _dbus_assert (self != NULL);
5508 _dbus_assert (_dbus_message_iter_append_check (real_writer));
5509 _dbus_assert (real_writer->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
5510
5512 _dbus_type_reader_init (&reader, DBUS_COMPILER_BYTE_ORDER,
5513 &variant_signature, 0, &self->data, 0);
5514 _dbus_type_reader_recurse (&reader, &variant_reader);
5515
5516 if (!_dbus_message_iter_open_signature (real_writer))
5517 return FALSE;
5518
5519 ret = _dbus_type_writer_write_reader (&real_writer->u.writer,
5520 &variant_reader);
5521
5522 if (!_dbus_message_iter_close_signature (real_writer))
5523 return FALSE;
5524
5525 return ret;
5526}
5527
5528int
5529_dbus_variant_get_length (DBusVariant *self)
5530{
5531 _dbus_assert (self != NULL);
5532 return _dbus_string_get_length (&self->data);
5533}
5534
5535const DBusString *
5536_dbus_variant_peek (DBusVariant *self)
5537{
5538 _dbus_assert (self != NULL);
5539 return &self->data;
5540}
5541
5542void
5543_dbus_variant_free (DBusVariant *self)
5544{
5545 _dbus_assert (self != NULL);
5546 _dbus_string_free (&self->data);
5547 dbus_free (self);
5548}
5549
5552/* 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:272
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:826
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:218
#define MAX_MESSAGE_SIZE_TO_CACHE
Avoid caching huge messages.
Definition: dbus-message.c:496
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:743
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:289
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition: dbus-message.c:419
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:250
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:231
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:387
#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:364
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:499
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:315
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:833
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition: dbus-string.c:182
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition: dbus-string.c:197
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition: dbus-string.c: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:672
dbus_bool_t _dbus_string_init_preallocated(DBusString *str, int allocate_size)
Initializes a string that can be up to the given allocation size before it has to realloc.
Definition: dbus-string.c:139
void _dbus_string_init_const_len(DBusString *str, const char *value, int len)
Initializes a constant string with a length.
Definition: dbus-string.c:217
dbus_bool_t _dbus_string_append_len(DBusString *str, const char *buffer, int len)
Appends block of bytes with the given length to a DBusString.
Definition: dbus-string.c: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:278
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
Definition: dbus-string.c: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
dbus_bool_t _dbus_string_compact(DBusString *str, int max_waste)
Compacts the string to avoid wasted memory.
Definition: dbus-string.c:420
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition: dbus-string.c: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
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:145
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:138
dbus_uint32_t u32
as int32
Definition: dbus-types.h:143