D-Bus 1.13.18
dbus-message.c
1/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2/* dbus-message.c DBusMessage object
3 *
4 * Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
5 * Copyright (C) 2002, 2003 CodeFactory AB
6 *
7 * Licensed under the Academic Free License version 2.1
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 *
23 */
24
25#include <config.h>
26#include "dbus-internals.h"
27#include "dbus-marshal-recursive.h"
28#include "dbus-marshal-validate.h"
29#include "dbus-marshal-byteswap.h"
30#include "dbus-marshal-header.h"
31#include "dbus-signature.h"
32#include "dbus-message-private.h"
33#include "dbus-object-tree.h"
34#include "dbus-memory.h"
35#include "dbus-list.h"
36#include "dbus-threads-internal.h"
37#ifdef HAVE_UNIX_FD_PASSING
38#include "dbus-sysdeps.h"
39#include "dbus-sysdeps-unix.h"
40#endif
41
42#include <string.h>
43
44#define _DBUS_TYPE_IS_STRINGLIKE(type) \
45 (type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \
46 type == DBUS_TYPE_OBJECT_PATH)
47
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;
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 return NULL;
2293 if (!_dbus_string_steal_data (&retstr, &ret))
2294 return NULL;
2295 _dbus_string_free (&retstr);
2296 return ret;
2297}
2298
2346void
2348 void *value)
2349{
2351
2352 _dbus_return_if_fail (_dbus_message_iter_check (real));
2353 _dbus_return_if_fail (value != NULL);
2354
2356 {
2357#ifdef HAVE_UNIX_FD_PASSING
2358 DBusBasicValue idx;
2359
2361
2362 if (idx.u32 >= real->message->n_unix_fds) {
2363 /* Hmm, we cannot really signal an error here, so let's make
2364 sure to return an invalid fd. */
2365 *((int*) value) = -1;
2366 return;
2367 }
2368
2369 *((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
2370#else
2371 *((int*) value) = -1;
2372#endif
2373 }
2374 else
2375 {
2377 value);
2378 }
2379}
2380
2391int
2393{
2395 DBusTypeReader array;
2396 int element_type;
2397 int n_elements = 0;
2398
2399 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2400 _dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
2401 == DBUS_TYPE_ARRAY, 0);
2402
2403 element_type = _dbus_type_reader_get_element_type (&real->u.reader);
2404 _dbus_type_reader_recurse (&real->u.reader, &array);
2405 if (dbus_type_is_fixed (element_type))
2406 {
2407 int alignment = _dbus_type_get_alignment (element_type);
2408 int total_len = _dbus_type_reader_get_array_length (&array);
2409 n_elements = total_len / alignment;
2410 }
2411 else
2412 {
2414 {
2415 ++n_elements;
2416 _dbus_type_reader_next (&array);
2417 }
2418 }
2419
2420 return n_elements;
2421}
2422
2435int
2437{
2439
2440 _dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
2441
2443}
2444
2480void
2482 void *value,
2483 int *n_elements)
2484{
2486#ifndef DBUS_DISABLE_CHECKS
2487 int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
2488
2489 _dbus_return_if_fail (_dbus_message_iter_check (real));
2490 _dbus_return_if_fail (value != NULL);
2491 _dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
2492 (dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
2493#endif
2494
2496 value, n_elements);
2497}
2498
2510void
2512 DBusMessageIter *iter)
2513{
2515
2516 _dbus_return_if_fail (message != NULL);
2517 _dbus_return_if_fail (iter != NULL);
2518
2519 _dbus_message_iter_init_common (message, real,
2520 DBUS_MESSAGE_ITER_TYPE_WRITER);
2521
2522 /* We create the signature string and point iterators at it "on demand"
2523 * when a value is actually appended. That means that init() never fails
2524 * due to OOM.
2525 */
2528 &message->body,
2529 _dbus_string_get_length (&message->body));
2530}
2531
2540static dbus_bool_t
2541_dbus_message_iter_open_signature (DBusMessageRealIter *real)
2542{
2543 DBusString *str;
2544 const DBusString *current_sig;
2545 int current_sig_pos;
2546
2547 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2548
2549 if (real->u.writer.type_str != NULL)
2550 {
2551 _dbus_assert (real->sig_refcount > 0);
2552 real->sig_refcount += 1;
2553 return TRUE;
2554 }
2555
2556 str = dbus_new (DBusString, 1);
2557 if (str == NULL)
2558 return FALSE;
2559
2562 &current_sig, &current_sig_pos))
2563 current_sig = NULL;
2564
2565 if (current_sig)
2566 {
2567 int current_len;
2568
2569 current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
2570 current_sig_pos += 1; /* move on to sig data */
2571
2572 if (!_dbus_string_init_preallocated (str, current_len + 4))
2573 {
2574 dbus_free (str);
2575 return FALSE;
2576 }
2577
2578 if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
2579 str, 0))
2580 {
2581 _dbus_string_free (str);
2582 dbus_free (str);
2583 return FALSE;
2584 }
2585 }
2586 else
2587 {
2588 if (!_dbus_string_init_preallocated (str, 4))
2589 {
2590 dbus_free (str);
2591 return FALSE;
2592 }
2593 }
2594
2595 real->sig_refcount = 1;
2596
2597 /* If this assertion failed, then str would be neither stored in u.writer
2598 * nor freed by this function, resulting in a memory leak. */
2599 _dbus_assert (real->u.writer.type_str == NULL);
2601 str, _dbus_string_get_length (str));
2602 return TRUE;
2603}
2604
2614static dbus_bool_t
2615_dbus_message_iter_close_signature (DBusMessageRealIter *real)
2616{
2617 DBusString *str;
2618 const char *v_STRING;
2619 dbus_bool_t retval;
2620
2621 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2622 _dbus_assert (real->u.writer.type_str != NULL);
2623 _dbus_assert (real->sig_refcount > 0);
2624
2625 real->sig_refcount -= 1;
2626
2627 if (real->sig_refcount > 0)
2628 return TRUE;
2629 _dbus_assert (real->sig_refcount == 0);
2630
2631 retval = TRUE;
2632
2633 str = real->u.writer.type_str;
2634
2635 v_STRING = _dbus_string_get_const_data (str);
2639 &v_STRING))
2640 retval = FALSE;
2641
2643 _dbus_string_free (str);
2644 dbus_free (str);
2645
2646 return retval;
2647}
2648
2656static void
2657_dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
2658{
2659 DBusString *str;
2660
2661 _dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
2662 _dbus_assert (real->u.writer.type_str != NULL);
2663 _dbus_assert (real->sig_refcount > 0);
2664
2665 real->sig_refcount -= 1;
2666
2667 if (real->sig_refcount > 0)
2668 return;
2669 _dbus_assert (real->sig_refcount == 0);
2670
2671 str = real->u.writer.type_str;
2672
2674 _dbus_string_free (str);
2675 dbus_free (str);
2676}
2677
2678#ifndef DBUS_DISABLE_CHECKS
2679static dbus_bool_t
2680_dbus_message_iter_append_check (DBusMessageRealIter *iter)
2681{
2682 if (!_dbus_message_iter_check (iter))
2683 return FALSE;
2684
2685 if (iter->message->locked)
2686 {
2687 _dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)");
2688 return FALSE;
2689 }
2690
2691 return TRUE;
2692}
2693#endif /* DBUS_DISABLE_CHECKS */
2694
2695#ifdef HAVE_UNIX_FD_PASSING
2696static int *
2697expand_fd_array(DBusMessage *m,
2698 unsigned n)
2699{
2700 _dbus_assert(m);
2701
2702 /* This makes space for adding n new fds to the array and returns a
2703 pointer to the place were the first fd should be put. */
2704
2705 if (m->n_unix_fds + n > m->n_unix_fds_allocated)
2706 {
2707 unsigned k;
2708 int *p;
2709
2710 /* Make twice as much space as necessary */
2711 k = (m->n_unix_fds + n) * 2;
2712
2713 /* Allocate at least four */
2714 if (k < 4)
2715 k = 4;
2716
2717 p = dbus_realloc(m->unix_fds, k * sizeof(int));
2718 if (p == NULL)
2719 return NULL;
2720
2721 m->unix_fds = p;
2722 m->n_unix_fds_allocated = k;
2723 }
2724
2725 return m->unix_fds + m->n_unix_fds;
2726}
2727#endif
2728
2750 int type,
2751 const void *value)
2752{
2754 dbus_bool_t ret;
2755
2756 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2757 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2758 _dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
2759 _dbus_return_val_if_fail (value != NULL, FALSE);
2760
2761#ifndef DBUS_DISABLE_CHECKS
2762 switch (type)
2763 {
2764 DBusString str;
2765 DBusValidity signature_validity;
2766 const char * const *string_p;
2767 const dbus_bool_t *bool_p;
2768
2769 case DBUS_TYPE_STRING:
2770 string_p = value;
2771 _dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
2772 break;
2773
2775 string_p = value;
2776 _dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
2777 break;
2778
2780 string_p = value;
2781 _dbus_string_init_const (&str, *string_p);
2782 signature_validity = _dbus_validate_signature_with_reason (&str,
2783 0,
2784 _dbus_string_get_length (&str));
2785
2786 if (signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
2787 return FALSE;
2788
2789 _dbus_return_val_if_fail (signature_validity == DBUS_VALID, FALSE);
2790 break;
2791
2792 case DBUS_TYPE_BOOLEAN:
2793 bool_p = value;
2794 _dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
2795 break;
2796
2797 default:
2798 {
2799 /* nothing to check, all possible values are allowed */
2800 }
2801 }
2802#endif
2803
2804 if (!_dbus_message_iter_open_signature (real))
2805 return FALSE;
2806
2807 if (type == DBUS_TYPE_UNIX_FD)
2808 {
2809#ifdef HAVE_UNIX_FD_PASSING
2810 int *fds;
2811 dbus_uint32_t u;
2812
2813 ret = FALSE;
2814
2815 /* First step, include the fd in the fd list of this message */
2816 if (!(fds = expand_fd_array(real->message, 1)))
2817 goto out;
2818
2819 *fds = _dbus_dup(*(int*) value, NULL);
2820 if (*fds < 0)
2821 goto out;
2822
2823 u = real->message->n_unix_fds;
2824
2825 /* Second step, write the index to the fd */
2826 if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
2827 _dbus_close(*fds, NULL);
2828 goto out;
2829 }
2830
2831 real->message->n_unix_fds += 1;
2832 u += 1;
2833
2834 /* Final step, update the header accordingly */
2838 &u);
2839
2840 /* If any of these operations fail the message is
2841 hosed. However, no memory or fds should be leaked since what
2842 has been added to message has been added to the message, and
2843 can hence be accounted for when the message is being
2844 freed. */
2845#else
2846 ret = FALSE;
2847 /* This is redundant (we could just fall through), but it avoids
2848 * -Wunused-label in builds that don't HAVE_UNIX_FD_PASSING */
2849 goto out;
2850#endif
2851 }
2852 else
2853 {
2854 ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
2855 }
2856
2857out:
2858 if (!_dbus_message_iter_close_signature (real))
2859 ret = FALSE;
2860
2861 return ret;
2862}
2863
2901 int element_type,
2902 const void *value,
2903 int n_elements)
2904{
2906 dbus_bool_t ret;
2907
2908 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2909 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2910 _dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
2911 _dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
2912 _dbus_return_val_if_fail (value != NULL, FALSE);
2913 _dbus_return_val_if_fail (n_elements >= 0, FALSE);
2914 _dbus_return_val_if_fail (n_elements <=
2916 FALSE);
2917
2918#ifndef DBUS_DISABLE_CHECKS
2919 if (element_type == DBUS_TYPE_BOOLEAN)
2920 {
2921 const dbus_bool_t * const *bools = value;
2922 int i;
2923
2924 for (i = 0; i < n_elements; i++)
2925 {
2926 _dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
2927 }
2928 }
2929#endif
2930
2931 ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
2932
2933 return ret;
2934}
2935
2965 int type,
2966 const char *contained_signature,
2967 DBusMessageIter *sub)
2968{
2970 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
2971 DBusString contained_str;
2972 DBusValidity contained_signature_validity;
2973 dbus_bool_t ret;
2974
2975 _dbus_return_val_if_fail (sub != NULL, FALSE);
2976 /* Do our best to make sure the sub-iterator doesn't contain something
2977 * valid-looking on failure */
2978 _dbus_message_real_iter_zero (real_sub);
2979
2980 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
2981 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
2982 _dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
2983 _dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
2984 contained_signature == NULL) ||
2985 (type == DBUS_TYPE_DICT_ENTRY &&
2986 contained_signature == NULL) ||
2987 (type == DBUS_TYPE_VARIANT &&
2988 contained_signature != NULL) ||
2989 (type == DBUS_TYPE_ARRAY &&
2990 contained_signature != NULL), FALSE);
2991
2992 /* this would fail if the contained_signature is a dict entry, since
2993 * dict entries are invalid signatures standalone (they must be in
2994 * an array)
2995 */
2996 if (contained_signature != NULL)
2997 {
2998 _dbus_string_init_const (&contained_str, contained_signature);
2999 contained_signature_validity = _dbus_validate_signature_with_reason (&contained_str,
3000 0,
3001 _dbus_string_get_length (&contained_str));
3002
3003 if (contained_signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
3004 return FALSE;
3005 }
3006 else
3007 {
3008 /* just some placeholder value */
3009 contained_signature_validity = DBUS_VALID_BUT_INCOMPLETE;
3010 }
3011
3012 _dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
3013 contained_signature == NULL ||
3014 contained_signature_validity == DBUS_VALID,
3015 FALSE);
3016
3017 if (!_dbus_message_iter_open_signature (real))
3018 return FALSE;
3019
3020 ret = FALSE;
3021 *real_sub = *real;
3022
3023 if (contained_signature != NULL)
3024 {
3025 _dbus_string_init_const (&contained_str, contained_signature);
3026
3027 ret = _dbus_type_writer_recurse (&real->u.writer,
3028 type,
3029 &contained_str, 0,
3030 &real_sub->u.writer);
3031 }
3032 else
3033 {
3034 ret = _dbus_type_writer_recurse (&real->u.writer,
3035 type,
3036 NULL, 0,
3037 &real_sub->u.writer);
3038 }
3039
3040 if (!ret)
3041 _dbus_message_iter_abandon_signature (real);
3042
3043 return ret;
3044}
3045
3046
3068 DBusMessageIter *sub)
3069{
3071 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3072 dbus_bool_t ret;
3073
3074 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
3075 _dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3076 _dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
3077 _dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
3078
3079 ret = _dbus_type_writer_unrecurse (&real->u.writer,
3080 &real_sub->u.writer);
3081 _dbus_message_real_iter_zero (real_sub);
3082
3083 if (!_dbus_message_iter_close_signature (real))
3084 ret = FALSE;
3085
3086 return ret;
3087}
3088
3100void
3102 DBusMessageIter *sub)
3103{
3105 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3106
3107#ifndef DBUS_DISABLE_CHECKS
3108 _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3109 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3110 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3111 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3112#endif
3113
3114 _dbus_message_iter_abandon_signature (real);
3115 _dbus_message_real_iter_zero (real_sub);
3116}
3117
3159void
3161 DBusMessageIter *sub)
3162{
3164 DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
3165
3166 /* If both the parent and the child are zeroed out, then either we didn't
3167 * even get as far as successfully recursing into the parent, or we already
3168 * closed both the child and the parent. For example, in the code sample
3169 * in the doc-comment above, this happens for
3170 * abandon_container_if_open (&outer, &inner) if the first open_container
3171 * call failed, or if we reached result = TRUE and fell through. */
3172 if (_dbus_message_real_iter_is_zeroed (real) &&
3173 _dbus_message_real_iter_is_zeroed (real_sub))
3174 return;
3175
3176#ifndef DBUS_DISABLE_CHECKS
3177 /* If the child is not zeroed out, but the parent is, then something has
3178 * gone horribly wrong (in practice that would probably mean both are
3179 * uninitialized or corrupt, and the parent happens to have ended up
3180 * all-bytes-zero). */
3181 _dbus_return_if_fail (_dbus_message_iter_append_check (real));
3182 _dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3183#endif
3184
3185 /* If the parent is not zeroed out, but the child is, then either we did
3186 * not successfully open the child, or we already closed the child. This
3187 * means we do not own a reference to the parent's signature, so it would
3188 * be wrong to release it; so we must not call abandon_signature() here.
3189 * In the code sample in the doc-comment above, this happens for
3190 * abandon_container_if_open (&outer, &inner) if the second open_container
3191 * call failed, or if the second close_container call failed. */
3192 if (_dbus_message_real_iter_is_zeroed (real_sub))
3193 return;
3194
3195#ifndef DBUS_DISABLE_CHECKS
3196 _dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
3197 _dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
3198#endif
3199
3200 /* If neither the parent nor the child is zeroed out, then we genuinely
3201 * have an open container; close it. In the code sample in the doc-comment,
3202 * this happens for abandon_container_if_open (&outer, &inner) if the
3203 * append_basic call failed. */
3204 _dbus_message_iter_abandon_signature (real);
3205 _dbus_message_real_iter_zero (real_sub);
3206}
3207
3224void
3226 dbus_bool_t no_reply)
3227{
3228 _dbus_return_if_fail (message != NULL);
3229 _dbus_return_if_fail (!message->locked);
3230
3233 no_reply);
3234}
3235
3245{
3246 _dbus_return_val_if_fail (message != NULL, FALSE);
3247
3248 return _dbus_header_get_flag (&message->header,
3250}
3251
3266void
3268 dbus_bool_t auto_start)
3269{
3270 _dbus_return_if_fail (message != NULL);
3271 _dbus_return_if_fail (!message->locked);
3272
3275 !auto_start);
3276}
3277
3287{
3288 _dbus_return_val_if_fail (message != NULL, FALSE);
3289
3290 return !_dbus_header_get_flag (&message->header,
3292}
3293
3294
3309 const char *object_path)
3310{
3311 _dbus_return_val_if_fail (message != NULL, FALSE);
3312 _dbus_return_val_if_fail (!message->locked, FALSE);
3313 _dbus_return_val_if_fail (object_path == NULL ||
3314 _dbus_check_is_valid_path (object_path),
3315 FALSE);
3316
3317 return set_or_delete_string_field (message,
3320 object_path);
3321}
3322
3336const char*
3338{
3339 const char *v;
3340
3341 _dbus_return_val_if_fail (message != NULL, NULL);
3342
3343 v = NULL; /* in case field doesn't exist */
3347 (void *) &v);
3348 return v;
3349}
3350
3362 const char *path)
3363{
3364 const char *msg_path;
3365 msg_path = dbus_message_get_path (message);
3366
3367 if (msg_path == NULL)
3368 {
3369 if (path == NULL)
3370 return TRUE;
3371 else
3372 return FALSE;
3373 }
3374
3375 if (path == NULL)
3376 return FALSE;
3377
3378 if (strcmp (msg_path, path) == 0)
3379 return TRUE;
3380
3381 return FALSE;
3382}
3383
3406 char ***path)
3407{
3408 const char *v;
3409
3410 _dbus_return_val_if_fail (message != NULL, FALSE);
3411 _dbus_return_val_if_fail (path != NULL, FALSE);
3412
3413 *path = NULL;
3414
3415 v = dbus_message_get_path (message);
3416 if (v != NULL)
3417 {
3418 if (!_dbus_decompose_path (v, strlen (v),
3419 path, NULL))
3420 return FALSE;
3421 }
3422 return TRUE;
3423}
3424
3440 const char *iface)
3441{
3442 _dbus_return_val_if_fail (message != NULL, FALSE);
3443 _dbus_return_val_if_fail (!message->locked, FALSE);
3444 _dbus_return_val_if_fail (iface == NULL ||
3445 _dbus_check_is_valid_interface (iface),
3446 FALSE);
3447
3448 return set_or_delete_string_field (message,
3451 iface);
3452}
3453
3467const char*
3469{
3470 const char *v;
3471
3472 _dbus_return_val_if_fail (message != NULL, NULL);
3473
3474 v = NULL; /* in case field doesn't exist */
3478 (void *) &v);
3479 return v;
3480}
3481
3491 const char *iface)
3492{
3493 const char *msg_interface;
3494 msg_interface = dbus_message_get_interface (message);
3495
3496 if (msg_interface == NULL)
3497 {
3498 if (iface == NULL)
3499 return TRUE;
3500 else
3501 return FALSE;
3502 }
3503
3504 if (iface == NULL)
3505 return FALSE;
3506
3507 if (strcmp (msg_interface, iface) == 0)
3508 return TRUE;
3509
3510 return FALSE;
3511
3512}
3513
3528 const char *member)
3529{
3530 _dbus_return_val_if_fail (message != NULL, FALSE);
3531 _dbus_return_val_if_fail (!message->locked, FALSE);
3532 _dbus_return_val_if_fail (member == NULL ||
3533 _dbus_check_is_valid_member (member),
3534 FALSE);
3535
3536 return set_or_delete_string_field (message,
3539 member);
3540}
3541
3553const char*
3555{
3556 const char *v;
3557
3558 _dbus_return_val_if_fail (message != NULL, NULL);
3559
3560 v = NULL; /* in case field doesn't exist */
3564 (void *) &v);
3565 return v;
3566}
3567
3577 const char *member)
3578{
3579 const char *msg_member;
3580 msg_member = dbus_message_get_member (message);
3581
3582 if (msg_member == NULL)
3583 {
3584 if (member == NULL)
3585 return TRUE;
3586 else
3587 return FALSE;
3588 }
3589
3590 if (member == NULL)
3591 return FALSE;
3592
3593 if (strcmp (msg_member, member) == 0)
3594 return TRUE;
3595
3596 return FALSE;
3597
3598}
3599
3613 const char *error_name)
3614{
3615 _dbus_return_val_if_fail (message != NULL, FALSE);
3616 _dbus_return_val_if_fail (!message->locked, FALSE);
3617 _dbus_return_val_if_fail (error_name == NULL ||
3618 _dbus_check_is_valid_error_name (error_name),
3619 FALSE);
3620
3621 return set_or_delete_string_field (message,
3624 error_name);
3625}
3626
3637const char*
3639{
3640 const char *v;
3641
3642 _dbus_return_val_if_fail (message != NULL, NULL);
3643
3644 v = NULL; /* in case field doesn't exist */
3648 (void *) &v);
3649 return v;
3650}
3651
3667 const char *destination)
3668{
3669 _dbus_return_val_if_fail (message != NULL, FALSE);
3670 _dbus_return_val_if_fail (!message->locked, FALSE);
3671 _dbus_return_val_if_fail (destination == NULL ||
3672 _dbus_check_is_valid_bus_name (destination),
3673 FALSE);
3674
3675 return set_or_delete_string_field (message,
3678 destination);
3679}
3680
3690const char*
3692{
3693 const char *v;
3694
3695 _dbus_return_val_if_fail (message != NULL, NULL);
3696
3697 v = NULL; /* in case field doesn't exist */
3701 (void *) &v);
3702 return v;
3703}
3704
3721 const char *sender)
3722{
3723 _dbus_return_val_if_fail (message != NULL, FALSE);
3724 _dbus_return_val_if_fail (!message->locked, FALSE);
3725 _dbus_return_val_if_fail (sender == NULL ||
3726 _dbus_check_is_valid_bus_name (sender),
3727 FALSE);
3728
3729 return set_or_delete_string_field (message,
3732 sender);
3733}
3734
3750const char*
3752{
3753 const char *v;
3754
3755 _dbus_return_val_if_fail (message != NULL, NULL);
3756
3757 v = NULL; /* in case field doesn't exist */
3761 (void *) &v);
3762 return v;
3763}
3764
3783const char*
3785{
3786 const DBusString *type_str;
3787 int type_pos;
3788
3789 _dbus_return_val_if_fail (message != NULL, NULL);
3790
3791 get_const_signature (&message->header, &type_str, &type_pos);
3792
3793 return _dbus_string_get_const_data_len (type_str, type_pos, 0);
3794}
3795
3796static dbus_bool_t
3797_dbus_message_has_type_interface_member (DBusMessage *message,
3798 int type,
3799 const char *iface,
3800 const char *member)
3801{
3802 const char *n;
3803
3804 _dbus_assert (message != NULL);
3805 _dbus_assert (iface != NULL);
3806 _dbus_assert (member != NULL);
3807
3808 if (dbus_message_get_type (message) != type)
3809 return FALSE;
3810
3811 /* Optimize by checking the short member name first
3812 * instead of the longer interface name
3813 */
3814
3815 n = dbus_message_get_member (message);
3816
3817 if (n && strcmp (n, member) == 0)
3818 {
3819 n = dbus_message_get_interface (message);
3820
3821 if (n == NULL || strcmp (n, iface) == 0)
3822 return TRUE;
3823 }
3824
3825 return FALSE;
3826}
3827
3844 const char *iface,
3845 const char *method)
3846{
3847 _dbus_return_val_if_fail (message != NULL, FALSE);
3848 _dbus_return_val_if_fail (iface != NULL, FALSE);
3849 _dbus_return_val_if_fail (method != NULL, FALSE);
3850 /* don't check that interface/method are valid since it would be
3851 * expensive, and not catch many common errors
3852 */
3853
3854 return _dbus_message_has_type_interface_member (message,
3856 iface, method);
3857}
3858
3872 const char *iface,
3873 const char *signal_name)
3874{
3875 _dbus_return_val_if_fail (message != NULL, FALSE);
3876 _dbus_return_val_if_fail (iface != NULL, FALSE);
3877 _dbus_return_val_if_fail (signal_name != NULL, FALSE);
3878 /* don't check that interface/name are valid since it would be
3879 * expensive, and not catch many common errors
3880 */
3881
3882 return _dbus_message_has_type_interface_member (message,
3884 iface, signal_name);
3885}
3886
3899 const char *error_name)
3900{
3901 const char *n;
3902
3903 _dbus_return_val_if_fail (message != NULL, FALSE);
3904 _dbus_return_val_if_fail (error_name != NULL, FALSE);
3905 /* don't check that error_name is valid since it would be expensive,
3906 * and not catch many common errors
3907 */
3908
3910 return FALSE;
3911
3912 n = dbus_message_get_error_name (message);
3913
3914 if (n && strcmp (n, error_name) == 0)
3915 return TRUE;
3916 else
3917 return FALSE;
3918}
3919
3932 const char *name)
3933{
3934 const char *s;
3935
3936 _dbus_return_val_if_fail (message != NULL, FALSE);
3937 _dbus_return_val_if_fail (name != NULL, FALSE);
3938 /* don't check that name is valid since it would be expensive, and
3939 * not catch many common errors
3940 */
3941
3942 s = dbus_message_get_destination (message);
3943
3944 if (s && strcmp (s, name) == 0)
3945 return TRUE;
3946 else
3947 return FALSE;
3948}
3949
3967 const char *name)
3968{
3969 const char *s;
3970
3971 _dbus_return_val_if_fail (message != NULL, FALSE);
3972 _dbus_return_val_if_fail (name != NULL, FALSE);
3973 /* don't check that name is valid since it would be expensive, and
3974 * not catch many common errors
3975 */
3976
3977 s = dbus_message_get_sender (message);
3978
3979 if (s && strcmp (s, name) == 0)
3980 return TRUE;
3981 else
3982 return FALSE;
3983}
3984
3996 const char *signature)
3997{
3998 const char *s;
3999
4000 _dbus_return_val_if_fail (message != NULL, FALSE);
4001 _dbus_return_val_if_fail (signature != NULL, FALSE);
4002 /* don't check that signature is valid since it would be expensive,
4003 * and not catch many common errors
4004 */
4005
4006 s = dbus_message_get_signature (message);
4007
4008 if (s && strcmp (s, signature) == 0)
4009 return TRUE;
4010 else
4011 return FALSE;
4012}
4013
4038 DBusMessage *message)
4039{
4040 const char *str;
4041
4042 _dbus_return_val_if_fail (message != NULL, FALSE);
4043 _dbus_return_val_if_error_is_set (error, FALSE);
4044
4046 return FALSE;
4047
4048 str = NULL;
4049 dbus_message_get_args (message, NULL,
4050 DBUS_TYPE_STRING, &str,
4052
4054 str ? "%s" : NULL, str);
4055
4056 return TRUE;
4057}
4058
4067{
4068#ifdef HAVE_UNIX_FD_PASSING
4069 _dbus_assert(message);
4070
4071 return message->n_unix_fds > 0;
4072#else
4073 return FALSE;
4074#endif
4075}
4076
4089 const char *object_path)
4090{
4091 _dbus_return_val_if_fail (message != NULL, FALSE);
4092 _dbus_return_val_if_fail (!message->locked, FALSE);
4093 _dbus_return_val_if_fail (object_path == NULL ||
4094 _dbus_check_is_valid_path (object_path),
4095 FALSE);
4096
4097 return set_or_delete_string_field (message,
4100 object_path);
4101}
4102
4113const char *
4115{
4116 const char *v;
4117
4118 _dbus_return_val_if_fail (message != NULL, NULL);
4119
4120 v = NULL; /* in case field doesn't exist */
4124 (void *) &v);
4125 return v;
4126}
4127
4146#define INITIAL_LOADER_DATA_LEN 32
4147
4156{
4157 DBusMessageLoader *loader;
4158
4159 loader = dbus_new0 (DBusMessageLoader, 1);
4160 if (loader == NULL)
4161 return NULL;
4162
4163 loader->refcount = 1;
4164
4165 loader->corrupted = FALSE;
4166 loader->corruption_reason = DBUS_VALID;
4167
4168 /* this can be configured by the app, but defaults to the protocol max */
4170
4171 /* We set a very relatively conservative default here since due to how
4172 SCM_RIGHTS works we need to preallocate an fd array of the maximum
4173 number of unix fds we want to receive in advance. A
4174 try-and-reallocate loop is not possible. */
4175 loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
4176
4177 if (!_dbus_string_init (&loader->data))
4178 {
4179 dbus_free (loader);
4180 return NULL;
4181 }
4182
4183 /* preallocate the buffer for speed, ignore failure */
4185 _dbus_string_set_length (&loader->data, 0);
4186
4187#ifdef HAVE_UNIX_FD_PASSING
4188 loader->unix_fds = NULL;
4189 loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
4190 loader->unix_fds_outstanding = FALSE;
4191#endif
4192
4193 return loader;
4194}
4195
4204{
4205 loader->refcount += 1;
4206
4207 return loader;
4208}
4209
4216void
4218{
4219 loader->refcount -= 1;
4220 if (loader->refcount == 0)
4221 {
4222#ifdef HAVE_UNIX_FD_PASSING
4223 close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
4224 dbus_free(loader->unix_fds);
4225#endif
4228 _dbus_string_free (&loader->data);
4229 dbus_free (loader);
4230 }
4231}
4232
4251void
4253 DBusString **buffer,
4254 int *max_to_read,
4255 dbus_bool_t *may_read_fds)
4256{
4258
4259 *buffer = &loader->data;
4260
4261 loader->buffer_outstanding = TRUE;
4262
4263 if (max_to_read != NULL)
4264 {
4265#ifdef HAVE_UNIX_FD_PASSING
4266 int offset = 0;
4267 int remain;
4268 int byte_order;
4269 int fields_array_len;
4270 int header_len;
4271 int body_len;
4272#endif
4273
4274 *max_to_read = DBUS_MAXIMUM_MESSAGE_LENGTH;
4275 *may_read_fds = TRUE;
4276
4277#ifdef HAVE_UNIX_FD_PASSING
4278 /* If we aren't holding onto any fds, we can read as much as we want
4279 * (fast path). */
4280 if (loader->n_unix_fds == 0)
4281 return;
4282
4283 /* Slow path: we have a message with some fds in it. We don't want
4284 * to start on the next message until this one is out of the way;
4285 * otherwise a legitimate sender can keep us processing messages
4286 * containing fds, until we disconnect it for having had fds pending
4287 * for too long, a limit that is in place to stop malicious senders
4288 * from setting up recursive fd-passing that takes up our quota and
4289 * will never go away. */
4290
4291 remain = _dbus_string_get_length (&loader->data);
4292
4293 while (remain > 0)
4294 {
4295 DBusValidity validity = DBUS_VALIDITY_UNKNOWN;
4296 int needed;
4297
4298 /* If 0 < remain < DBUS_MINIMUM_HEADER_SIZE, then we've had at
4299 * least the first byte of a message, but we don't know how
4300 * much more to read. Only read the rest of the
4301 * DBUS_MINIMUM_HEADER_SIZE for now; then we'll know. */
4302 if (remain < DBUS_MINIMUM_HEADER_SIZE)
4303 {
4304 *max_to_read = DBUS_MINIMUM_HEADER_SIZE - remain;
4305 *may_read_fds = FALSE;
4306 return;
4307 }
4308
4310 &validity,
4311 &byte_order,
4312 &fields_array_len,
4313 &header_len,
4314 &body_len,
4315 &loader->data,
4316 offset,
4317 remain))
4318 {
4319 /* If a message in the buffer is invalid, we're going to
4320 * disconnect the sender anyway, so reading an arbitrary amount
4321 * is fine. */
4322 if (validity != DBUS_VALID)
4323 return;
4324
4325 /* We have a partial message, with the
4326 * DBUS_MINIMUM_HEADER_SIZE-byte fixed part of the header (which
4327 * lets us work out how much more we need), but no more. Read
4328 * the rest of the message. */
4329 needed = header_len + body_len;
4330 _dbus_assert (needed > remain);
4331 *max_to_read = needed - remain;
4332 *may_read_fds = FALSE;
4333 return;
4334 }
4335
4336 /* Skip over entire messages until we have less than a message
4337 * remaining. */
4338 needed = header_len + body_len;
4340 _dbus_assert (remain >= needed);
4341 remain -= needed;
4342 offset += needed;
4343 }
4344#endif
4345 }
4346}
4347
4357void
4359 DBusString *buffer)
4360{
4362 _dbus_assert (buffer == &loader->data);
4363
4364 loader->buffer_outstanding = FALSE;
4365}
4366
4367#ifdef HAVE_UNIX_FD_PASSING
4379_dbus_message_loader_get_unix_fds(DBusMessageLoader *loader,
4380 int **fds,
4381 unsigned *max_n_fds)
4382{
4383 _dbus_assert (!loader->unix_fds_outstanding);
4384
4385 /* Allocate space where we can put the fds we read. We allocate
4386 space for max_message_unix_fds since this is an
4387 upper limit how many fds can be received within a single
4388 message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
4389 we are allocating the maximum possible array size right from the
4390 beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
4391 there is no better way. */
4392
4393 if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
4394 {
4395 int *a = dbus_realloc(loader->unix_fds,
4396 loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
4397
4398 if (!a)
4399 return FALSE;
4400
4401 loader->unix_fds = a;
4402 loader->n_unix_fds_allocated = loader->max_message_unix_fds;
4403 }
4404
4405 *fds = loader->unix_fds + loader->n_unix_fds;
4406 *max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
4407
4408 loader->unix_fds_outstanding = TRUE;
4409 return TRUE;
4410}
4411
4422void
4423_dbus_message_loader_return_unix_fds(DBusMessageLoader *loader,
4424 int *fds,
4425 unsigned n_fds)
4426{
4427 _dbus_assert(loader->unix_fds_outstanding);
4428 _dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
4429 _dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
4430
4431 loader->n_unix_fds += n_fds;
4432 loader->unix_fds_outstanding = FALSE;
4433
4434 if (n_fds && loader->unix_fds_change)
4435 loader->unix_fds_change (loader->unix_fds_change_data);
4436}
4437#endif
4438
4439/*
4440 * FIXME when we move the header out of the buffer, that memmoves all
4441 * buffered messages. Kind of crappy.
4442 *
4443 * Also we copy the header and body, which is kind of crappy. To
4444 * avoid this, we have to allow header and body to be in a single
4445 * memory block, which is good for messages we read and bad for
4446 * messages we are creating. But we could move_len() the buffer into
4447 * this single memory block, and move_len() will just swap the buffers
4448 * if you're moving the entire buffer replacing the dest string.
4449 *
4450 * We could also have the message loader tell the transport how many
4451 * bytes to read; so it would first ask for some arbitrary number like
4452 * 256, then if the message was incomplete it would use the
4453 * header/body len to ask for exactly the size of the message (or
4454 * blocks the size of a typical kernel buffer for the socket). That
4455 * way we don't get trailing bytes in the buffer that have to be
4456 * memmoved. Though I suppose we also don't have a chance of reading a
4457 * bunch of small messages at once, so the optimization may be stupid.
4458 *
4459 * Another approach would be to keep a "start" index into
4460 * loader->data and only delete it occasionally, instead of after
4461 * each message is loaded.
4462 *
4463 * load_message() returns FALSE if not enough memory OR the loader was corrupted
4464 */
4465static dbus_bool_t
4466load_message (DBusMessageLoader *loader,
4467 DBusMessage *message,
4468 int byte_order,
4469 int fields_array_len,
4470 int header_len,
4471 int body_len)
4472{
4473 dbus_bool_t oom;
4474 DBusValidity validity;
4475 const DBusString *type_str;
4476 int type_pos;
4477 DBusValidationMode mode;
4478 dbus_uint32_t n_unix_fds = 0;
4479
4480 mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
4481
4482 oom = FALSE;
4483
4484#if 0
4485 _dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
4486#endif
4487
4488 /* 1. VALIDATE AND COPY OVER HEADER */
4489 _dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
4490 _dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
4491
4492 if (!_dbus_header_load (&message->header,
4493 mode,
4494 &validity,
4495 byte_order,
4496 fields_array_len,
4497 header_len,
4498 body_len,
4499 &loader->data))
4500 {
4501 _dbus_verbose ("Failed to load header for new message code %d\n", validity);
4502
4503 /* assert here so we can catch any code that still uses DBUS_VALID to indicate
4504 oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
4505 _dbus_assert (validity != DBUS_VALID);
4506
4507 if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
4508 oom = TRUE;
4509 else
4510 {
4511 loader->corrupted = TRUE;
4512 loader->corruption_reason = validity;
4513 }
4514 goto failed;
4515 }
4516
4517 _dbus_assert (validity == DBUS_VALID);
4518
4519 /* 2. VALIDATE BODY */
4520 if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
4521 {
4522 get_const_signature (&message->header, &type_str, &type_pos);
4523
4524 /* Because the bytes_remaining arg is NULL, this validates that the
4525 * body is the right length
4526 */
4527 validity = _dbus_validate_body_with_reason (type_str,
4528 type_pos,
4529 byte_order,
4530 NULL,
4531 &loader->data,
4532 header_len,
4533 body_len);
4534 if (validity != DBUS_VALID)
4535 {
4536 _dbus_verbose ("Failed to validate message body code %d\n", validity);
4537
4538 loader->corrupted = TRUE;
4539 loader->corruption_reason = validity;
4540
4541 goto failed;
4542 }
4543 }
4544
4545 /* 3. COPY OVER UNIX FDS */
4549 &n_unix_fds);
4550
4551#ifdef HAVE_UNIX_FD_PASSING
4552
4553 if (n_unix_fds > loader->n_unix_fds)
4554 {
4555 _dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
4556 n_unix_fds, loader->n_unix_fds);
4557
4558 loader->corrupted = TRUE;
4559 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4560 goto failed;
4561 }
4562
4563 /* If this was a recycled message there might still be
4564 some memory allocated for the fds */
4565 dbus_free(message->unix_fds);
4566
4567 if (n_unix_fds > 0)
4568 {
4569 message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
4570 if (message->unix_fds == NULL)
4571 {
4572 _dbus_verbose ("Failed to allocate file descriptor array\n");
4573 oom = TRUE;
4574 goto failed;
4575 }
4576
4577 message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
4578 loader->n_unix_fds -= n_unix_fds;
4579 memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
4580
4581 if (loader->unix_fds_change)
4582 loader->unix_fds_change (loader->unix_fds_change_data);
4583 }
4584 else
4585 message->unix_fds = NULL;
4586
4587#else
4588
4589 if (n_unix_fds > 0)
4590 {
4591 _dbus_verbose ("Hmm, message claims to come with file descriptors "
4592 "but that's not supported on our platform, disconnecting.\n");
4593
4594 loader->corrupted = TRUE;
4595 loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
4596 goto failed;
4597 }
4598
4599#endif
4600
4601 /* 3. COPY OVER BODY AND QUEUE MESSAGE */
4602
4603 if (!_dbus_list_append (&loader->messages, message))
4604 {
4605 _dbus_verbose ("Failed to append new message to loader queue\n");
4606 oom = TRUE;
4607 goto failed;
4608 }
4609
4610 _dbus_assert (_dbus_string_get_length (&message->body) == 0);
4611 _dbus_assert (_dbus_string_get_length (&loader->data) >=
4612 (header_len + body_len));
4613
4614 if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
4615 {
4616 _dbus_verbose ("Failed to move body into new message\n");
4617 oom = TRUE;
4618 goto failed;
4619 }
4620
4621 _dbus_string_delete (&loader->data, 0, header_len + body_len);
4622
4623 /* don't waste more than 2k of memory */
4624 _dbus_string_compact (&loader->data, 2048);
4625
4626 _dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
4627 _dbus_assert (_dbus_string_get_length (&message->body) == body_len);
4628
4629 _dbus_verbose ("Loaded message %p\n", message);
4630
4631 _dbus_assert (!oom);
4632 _dbus_assert (!loader->corrupted);
4633 _dbus_assert (loader->messages != NULL);
4634 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4635
4636 return TRUE;
4637
4638 failed:
4639
4640 /* Clean up */
4641
4642 /* does nothing if the message isn't in the list */
4643 _dbus_list_remove_last (&loader->messages, message);
4644
4645 if (oom)
4646 _dbus_assert (!loader->corrupted);
4647 else
4648 _dbus_assert (loader->corrupted);
4649
4650 _dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
4651
4652 return FALSE;
4653}
4654
4671{
4672 while (!loader->corrupted &&
4673 _dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
4674 {
4675 DBusValidity validity;
4676 int byte_order, fields_array_len, header_len, body_len;
4677
4679 &validity,
4680 &byte_order,
4681 &fields_array_len,
4682 &header_len,
4683 &body_len,
4684 &loader->data, 0,
4685 _dbus_string_get_length (&loader->data)))
4686 {
4687 DBusMessage *message;
4688
4689 _dbus_assert (validity == DBUS_VALID);
4690
4691 message = dbus_message_new_empty_header ();
4692 if (message == NULL)
4693 return FALSE;
4694
4695 if (!load_message (loader, message,
4696 byte_order, fields_array_len,
4697 header_len, body_len))
4698 {
4699 dbus_message_unref (message);
4700 /* load_message() returns false if corrupted or OOM; if
4701 * corrupted then return TRUE for not OOM
4702 */
4703 return loader->corrupted;
4704 }
4705
4706 _dbus_assert (loader->messages != NULL);
4707 _dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
4708 }
4709 else
4710 {
4711 _dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
4712 validity);
4713 if (validity != DBUS_VALID)
4714 {
4715 loader->corrupted = TRUE;
4716 loader->corruption_reason = validity;
4717 }
4718 return TRUE;
4719 }
4720 }
4721
4722 return TRUE;
4723}
4724
4734{
4735 if (loader->messages)
4736 return loader->messages->data;
4737 else
4738 return NULL;
4739}
4740
4751{
4752 return _dbus_list_pop_first (&loader->messages);
4753}
4754
4763DBusList*
4765{
4766 return _dbus_list_pop_first_link (&loader->messages);
4767}
4768
4775void
4777 DBusList *link)
4778{
4779 _dbus_list_prepend_link (&loader->messages, link);
4780}
4781
4793{
4794 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4795 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4796 return loader->corrupted;
4797}
4798
4807{
4808 _dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
4809 (!loader->corrupted && loader->corruption_reason == DBUS_VALID));
4810
4811 return loader->corruption_reason;
4812}
4813
4820void
4822 long size)
4823{
4824 if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
4825 {
4826 _dbus_verbose ("clamping requested max message size %ld to %d\n",
4829 }
4830 loader->max_message_size = size;
4831}
4832
4839long
4841{
4842 return loader->max_message_size;
4843}
4844
4851void
4853 long n)
4854{
4856 {
4857 _dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
4860 }
4861 loader->max_message_unix_fds = n;
4862}
4863
4870long
4872{
4873 return loader->max_message_unix_fds;
4874}
4875
4881int
4883{
4884#ifdef HAVE_UNIX_FD_PASSING
4885 return loader->n_unix_fds;
4886#else
4887 return 0;
4888#endif
4889}
4890
4899void
4901 void (* callback) (void *),
4902 void *data)
4903{
4904#ifdef HAVE_UNIX_FD_PASSING
4905 loader->unix_fds_change = callback;
4906 loader->unix_fds_change_data = data;
4907#endif
4908}
4909
4910static DBusDataSlotAllocator slot_allocator =
4911 _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
4912
4929{
4930 return _dbus_data_slot_allocator_alloc (&slot_allocator,
4931 slot_p);
4932}
4933
4945void
4946dbus_message_free_data_slot (dbus_int32_t *slot_p)
4947{
4948 _dbus_return_if_fail (*slot_p >= 0);
4949
4950 _dbus_data_slot_allocator_free (&slot_allocator, slot_p);
4951}
4952
4968 dbus_int32_t slot,
4969 void *data,
4970 DBusFreeFunction free_data_func)
4971{
4972 DBusFreeFunction old_free_func;
4973 void *old_data;
4974 dbus_bool_t retval;
4975
4976 _dbus_return_val_if_fail (message != NULL, FALSE);
4977 _dbus_return_val_if_fail (slot >= 0, FALSE);
4978
4979 retval = _dbus_data_slot_list_set (&slot_allocator,
4980 &message->slot_list,
4981 slot, data, free_data_func,
4982 &old_free_func, &old_data);
4983
4984 if (retval)
4985 {
4986 /* Do the actual free outside the message lock */
4987 if (old_free_func)
4988 (* old_free_func) (old_data);
4989 }
4990
4991 return retval;
4992}
4993
5002void*
5004 dbus_int32_t slot)
5005{
5006 void *res;
5007
5008 _dbus_return_val_if_fail (message != NULL, NULL);
5009
5010 res = _dbus_data_slot_list_get (&slot_allocator,
5011 &message->slot_list,
5012 slot);
5013
5014 return res;
5015}
5016
5030int
5031dbus_message_type_from_string (const char *type_str)
5032{
5033 if (strcmp (type_str, "method_call") == 0)
5035 if (strcmp (type_str, "method_return") == 0)
5037 else if (strcmp (type_str, "signal") == 0)
5039 else if (strcmp (type_str, "error") == 0)
5041 else
5043}
5044
5058const char *
5060{
5061 switch (type)
5062 {
5064 return "method_call";
5066 return "method_return";
5068 return "signal";
5070 return "error";
5071 default:
5072 return "invalid";
5073 }
5074}
5075
5090 char **marshalled_data_p,
5091 int *len_p)
5092{
5093 DBusString tmp;
5094 dbus_bool_t was_locked;
5095
5096 _dbus_return_val_if_fail (msg != NULL, FALSE);
5097 _dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
5098 _dbus_return_val_if_fail (len_p != NULL, FALSE);
5099
5100 if (!_dbus_string_init (&tmp))
5101 return FALSE;
5102
5103 /* Ensure the message is locked, to ensure the length header is filled in. */
5104 was_locked = msg->locked;
5105
5106 if (!was_locked)
5107 dbus_message_lock (msg);
5108
5109 if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
5110 goto fail;
5111
5112 *len_p = _dbus_string_get_length (&tmp);
5113
5114 if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
5115 goto fail;
5116
5117 *len_p = _dbus_string_get_length (&tmp);
5118
5119 if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
5120 goto fail;
5121
5122 _dbus_string_free (&tmp);
5123
5124 if (!was_locked)
5125 msg->locked = FALSE;
5126
5127 return TRUE;
5128
5129 fail:
5130 _dbus_string_free (&tmp);
5131
5132 if (!was_locked)
5133 msg->locked = FALSE;
5134
5135 return FALSE;
5136}
5137
5151dbus_message_demarshal (const char *str,
5152 int len,
5153 DBusError *error)
5154{
5155 DBusMessageLoader *loader = NULL;
5156 DBusString *buffer;
5157 DBusMessage *msg;
5158
5159 _dbus_return_val_if_fail (str != NULL, NULL);
5160
5161 loader = _dbus_message_loader_new ();
5162
5163 if (loader == NULL)
5164 goto fail_oom;
5165
5166 _dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
5167
5168 if (!_dbus_string_append_len (buffer, str, len))
5169 goto fail_oom;
5170
5171 _dbus_message_loader_return_buffer (loader, buffer);
5172
5174 goto fail_oom;
5175
5177 goto fail_corrupt;
5178
5179 msg = _dbus_message_loader_pop_message (loader);
5180
5181 if (!msg)
5182 goto fail_oom;
5183
5185 return msg;
5186
5187 fail_corrupt:
5188 dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
5189 _dbus_validity_to_error_message (loader->corruption_reason));
5191 return NULL;
5192
5193 fail_oom:
5194 _DBUS_SET_OOM (error);
5195
5196 if (loader != NULL)
5198
5199 return NULL;
5200}
5201
5214int
5216 int len)
5217{
5218 DBusString str;
5219 int byte_order, fields_array_len, header_len, body_len;
5220 DBusValidity validity = DBUS_VALID;
5221 int have_message;
5222
5223 if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
5224 return 0;
5225
5228 _dbus_string_init_const_len (&str, buf, len);
5229
5230 validity = DBUS_VALID;
5231 have_message
5233 &validity, &byte_order,
5234 &fields_array_len,
5235 &header_len,
5236 &body_len,
5237 &str, 0,
5238 len);
5239 _dbus_string_free (&str);
5240
5241 if (validity == DBUS_VALID)
5242 {
5243 _dbus_assert (have_message || (header_len + body_len) > len);
5244 (void) have_message; /* unused unless asserting */
5245 return header_len + body_len;
5246 }
5247 else
5248 {
5249 return -1; /* broken! */
5250 }
5251}
5252
5274void
5276 dbus_bool_t allow)
5277{
5278 _dbus_return_if_fail (message != NULL);
5279 _dbus_return_if_fail (!message->locked);
5280
5283 allow);
5284}
5285
5294{
5295 _dbus_return_val_if_fail (message != NULL, FALSE);
5296
5297 return _dbus_header_get_flag (&message->header,
5299}
5300
5308{
5309 DBusString data;
5310};
5311
5325{
5326 DBusVariant *self = NULL;
5327 /* Points to the single item we will read from the reader */
5328 DBusMessageRealIter *real_reader = (DBusMessageRealIter *) reader;
5329 /* The position in self at which we will write a single variant
5330 * (it is position 0) */
5331 DBusTypeWriter items_writer;
5332 /* The position in self at which we will write a copy of reader
5333 * (it is inside the variant) */
5334 DBusTypeWriter variant_writer;
5335 /* 'v' */
5336 DBusString variant_signature;
5337 /* Whatever is the signature of the item we will copy from the reader */
5338 DBusString contained_signature;
5339 /* TRUE if self->data needs to be freed */
5340 dbus_bool_t data_inited = FALSE;
5341 /* The type of the item we will read from the reader */
5342 int type;
5343 /* The string, start position within that string, and length of the signature
5344 * of the single complete type of the item reader points to */
5345 const DBusString *sig;
5346 int start, len;
5347
5348 _dbus_assert (_dbus_message_iter_check (real_reader));
5349 _dbus_assert (real_reader->iter_type == DBUS_MESSAGE_ITER_TYPE_READER);
5351 type = dbus_message_iter_get_arg_type (reader);
5352 _dbus_type_reader_get_signature (&real_reader->u.reader, &sig, &start, &len);
5353
5354 if (!_dbus_string_init (&contained_signature))
5355 return NULL;
5356
5357 if (!_dbus_string_copy_len (sig, start, len, &contained_signature, 0))
5358 goto oom;
5359
5360 self = dbus_new0 (DBusVariant, 1);
5361
5362 if (self == NULL)
5363 goto oom;
5364
5365 if (!_dbus_string_init (&self->data))
5366 goto oom;
5367
5368 data_inited = TRUE;
5369
5370 _dbus_type_writer_init_values_only (&items_writer, DBUS_COMPILER_BYTE_ORDER,
5371 &variant_signature, 0, &self->data, 0);
5372
5373 if (!_dbus_type_writer_recurse (&items_writer, DBUS_TYPE_VARIANT,
5374 &contained_signature, 0, &variant_writer))
5375 goto oom;
5376
5377 if (type == DBUS_TYPE_ARRAY)
5378 {
5379 /* Points to each item in turn inside the array we are copying */
5380 DBusMessageIter array_reader;
5381 /* Same as array_reader */
5382 DBusMessageRealIter *real_array_reader = (DBusMessageRealIter *) &array_reader;
5383 /* The position inside the copied array at which we will write
5384 * the copy of array_reader */
5385 DBusTypeWriter array_writer;
5386
5387 dbus_message_iter_recurse (reader, &array_reader);
5388
5389 if (!_dbus_type_writer_recurse (&variant_writer, type,
5390 &contained_signature, 1, &array_writer))
5391 goto oom;
5392
5393 if (!_dbus_type_writer_write_reader (&array_writer,
5394 &real_array_reader->u.reader))
5395 goto oom;
5396
5397 if (!_dbus_type_writer_unrecurse (&variant_writer, &array_writer))
5398 goto oom;
5399 }
5400 else if (type == DBUS_TYPE_DICT_ENTRY || type == DBUS_TYPE_VARIANT ||
5401 type == DBUS_TYPE_STRUCT)
5402 {
5403 /* Points to each item in turn inside the container we are copying */
5404 DBusMessageIter inner_reader;
5405 /* Same as inner_reader */
5406 DBusMessageRealIter *real_inner_reader = (DBusMessageRealIter *) &inner_reader;
5407 /* The position inside the copied container at which we will write the
5408 * copy of inner_reader */
5409 DBusTypeWriter inner_writer;
5410
5411 dbus_message_iter_recurse (reader, &inner_reader);
5412
5413 if (!_dbus_type_writer_recurse (&variant_writer, type, NULL, 0,
5414 &inner_writer))
5415 goto oom;
5416
5417 if (!_dbus_type_writer_write_reader (&inner_writer,
5418 &real_inner_reader->u.reader))
5419 goto oom;
5420
5421 if (!_dbus_type_writer_unrecurse (&variant_writer, &inner_writer))
5422 goto oom;
5423 }
5424 else
5425 {
5426 DBusBasicValue value;
5427
5428 /* We eliminated all the container types above */
5430
5431 dbus_message_iter_get_basic (reader, &value);
5432
5433 if (!_dbus_type_writer_write_basic (&variant_writer, type, &value))
5434 goto oom;
5435 }
5436
5437 _dbus_string_free (&contained_signature);
5438 return self;
5439
5440oom:
5441 if (self != NULL)
5442 {
5443 if (data_inited)
5444 _dbus_string_free (&self->data);
5445
5446 dbus_free (self);
5447 }
5448
5449 _dbus_string_free (&contained_signature);
5450 return NULL;
5451}
5452
5459const char *
5461{
5462 unsigned char len;
5463 const char *ret;
5464
5465 _dbus_assert (self != NULL);
5466
5467 /* Here we make use of the fact that the serialization of a variant starts
5468 * with the 1-byte length, then that many bytes of signature, then \0. */
5469 len = _dbus_string_get_byte (&self->data, 0);
5470 ret = _dbus_string_get_const_data_len (&self->data, 1, len);
5471 _dbus_assert (strlen (ret) == len);
5472 return ret;
5473}
5474
5488 DBusMessageIter *writer)
5489{
5490 /* 'v' */
5491 DBusString variant_signature;
5492 /* Points to the single item in self */
5493 DBusTypeReader variant_reader;
5494 /* Points to the single item (of whatever type) inside the variant */
5495 DBusTypeReader reader;
5496 /* The position at which we will copy reader */
5497 DBusMessageRealIter *real_writer = (DBusMessageRealIter *) writer;
5498 dbus_bool_t ret;
5499
5500 _dbus_assert (self != NULL);
5501 _dbus_assert (_dbus_message_iter_append_check (real_writer));
5502 _dbus_assert (real_writer->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
5503
5505 _dbus_type_reader_init (&reader, DBUS_COMPILER_BYTE_ORDER,
5506 &variant_signature, 0, &self->data, 0);
5507 _dbus_type_reader_recurse (&reader, &variant_reader);
5508
5509 if (!_dbus_message_iter_open_signature (real_writer))
5510 return FALSE;
5511
5512 ret = _dbus_type_writer_write_reader (&real_writer->u.writer,
5513 &variant_reader);
5514
5515 if (!_dbus_message_iter_close_signature (real_writer))
5516 return FALSE;
5517
5518 return ret;
5519}
5520
5521int
5522_dbus_variant_get_length (DBusVariant *self)
5523{
5524 _dbus_assert (self != NULL);
5525 return _dbus_string_get_length (&self->data);
5526}
5527
5528const DBusString *
5529_dbus_variant_peek (DBusVariant *self)
5530{
5531 _dbus_assert (self != NULL);
5532 return &self->data;
5533}
5534
5535void
5536_dbus_variant_free (DBusVariant *self)
5537{
5538 _dbus_assert (self != NULL);
5539 _dbus_string_free (&self->data);
5540 dbus_free (self);
5541}
5542
5545/* 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:784
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:813
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:704
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:604
#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:752
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:826
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:1307
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:665
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:1161
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:271
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:1217
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:1096
dbus_bool_t _dbus_string_compact(DBusString *str, int max_waste)
Compacts the string to avoid wasted memory.
Definition: dbus-string.c:413
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:1399
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