dbus-message.c
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* dbus-message.c DBusMessage object
*
* Copyright (C) 2002, 2003, 2004, 2005 Red Hat Inc.
* Copyright (C) 2002, 2003 CodeFactory AB
*
* SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
*
* Licensed under the Academic Free License version 2.1
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <config.h>
#include "dbus-internals.h"
#include "dbus-marshal-recursive.h"
#include "dbus-marshal-validate.h"
#include "dbus-marshal-byteswap.h"
#include "dbus-marshal-header.h"
#include "dbus-signature.h"
#include "dbus-message-private.h"
#include "dbus-object-tree.h"
#include "dbus-memory.h"
#include "dbus-list.h"
#include "dbus-threads-internal.h"
#ifdef HAVE_UNIX_FD_PASSING
#include "dbus-sysdeps.h"
#include "dbus-sysdeps-unix.h"
#endif
#include <string.h>
#define _DBUS_TYPE_IS_STRINGLIKE(type) \
(type == DBUS_TYPE_STRING || type == DBUS_TYPE_SIGNATURE || \
type == DBUS_TYPE_OBJECT_PATH)
static void dbus_message_finalize (DBusMessage *message);
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
static dbus_bool_t
_dbus_enable_message_cache (void)
{
static int enabled = -1;
if (enabled < 0)
{
const char *s = _dbus_getenv ("DBUS_MESSAGE_CACHE");
enabled = TRUE;
if (s && *s)
{
if (*s == '0')
enabled = FALSE;
else if (*s == '1')
enabled = TRUE;
else
_dbus_warn ("DBUS_MESSAGE_CACHE should be 0 or 1 if set, not '%s'",
s);
}
}
return enabled;
}
#else
/* constant expression, should be optimized away */
# define _dbus_enable_message_cache() (TRUE)
#endif
#ifndef _dbus_message_trace_ref
void
_dbus_message_trace_ref (DBusMessage *message,
int old_refcount,
int new_refcount,
const char *why)
{
static int enabled = -1;
_dbus_trace_ref ("DBusMessage", message, old_refcount, new_refcount, why,
"DBUS_MESSAGE_TRACE", &enabled);
}
#endif
/* Not thread locked, but strictly const/read-only so should be OK
*/
_DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, "");
/* these have wacky values to help trap uninitialized iterators;
* but has to fit in 3 bits
*/
enum {
DBUS_MESSAGE_ITER_TYPE_READER = 3,
DBUS_MESSAGE_ITER_TYPE_WRITER = 7
};
typedef struct DBusMessageRealIter DBusMessageRealIter;
struct DBusMessageRealIter
{
DBusMessage *message;
dbus_uint32_t changed_stamp : CHANGED_STAMP_BITS;
dbus_uint32_t iter_type : 3;
dbus_uint32_t sig_refcount : 8;
union
{
DBusTypeWriter writer;
DBusTypeReader reader;
} u;
};
#if DBUS_SIZEOF_VOID_P > 8
/*
* Architectures with 128-bit pointers were not supported in DBus 1.10, so we
* do no check for DBus 1.10 structure layout compatibility for such
* architectures (e.g. Arm Morello).
*/
#define CHECK_DBUS_1_10_BINARY_COMPATIBILITY 0
#else
#define CHECK_DBUS_1_10_BINARY_COMPATIBILITY 1
typedef struct
{
void *dummy1;
void *dummy2;
dbus_uint32_t dummy3;
int dummy4;
int dummy5;
int dummy6;
int dummy7;
int dummy8;
int dummy9;
int dummy10;
int dummy11;
int pad1;
int pad2;
void *pad3;
} DBusMessageIter_1_10_0;
#endif
static void
get_const_signature (DBusHeader *header,
const DBusString **type_str_p,
int *type_pos_p)
{
if (_dbus_header_get_field_raw (header,
DBUS_HEADER_FIELD_SIGNATURE,
type_str_p,
type_pos_p))
{
*type_pos_p += 1; /* skip the signature length which is 1 byte */
}
else
{
*type_str_p = &_dbus_empty_signature_str;
*type_pos_p = 0;
}
}
static void
_dbus_message_byteswap (DBusMessage *message)
{
const DBusString *type_str;
int type_pos;
char byte_order;
byte_order = _dbus_header_get_byte_order (&message->header);
if (byte_order == DBUS_COMPILER_BYTE_ORDER)
return;
_dbus_verbose ("Swapping message into compiler byte order\n");
get_const_signature (&message->header, &type_str, &type_pos);
_dbus_marshal_byteswap (type_str, type_pos,
byte_order,
DBUS_COMPILER_BYTE_ORDER,
&message->body, 0);
_dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
_dbus_assert (_dbus_header_get_byte_order (&message->header) ==
DBUS_COMPILER_BYTE_ORDER);
}
#define ensure_byte_order(message) _dbus_message_byteswap (message)
void
_dbus_message_get_network_data (DBusMessage *message,
const DBusString **header,
const DBusString **body)
{
_dbus_assert (message->locked);
*header = &message->header.data;
*body = &message->body;
}
void _dbus_message_get_unix_fds(DBusMessage *message,
const int **fds,
unsigned *n_fds)
{
_dbus_assert (message->locked);
#ifdef HAVE_UNIX_FD_PASSING
*fds = message->unix_fds;
*n_fds = message->n_unix_fds;
#else
*fds = NULL;
*n_fds = 0;
#endif
}
dbus_bool_t
_dbus_message_remove_unknown_fields (DBusMessage *message)
{
return _dbus_header_remove_unknown_fields (&message->header);
}
void
dbus_message_set_serial (DBusMessage *message,
dbus_uint32_t serial)
{
_dbus_return_if_fail (message != NULL);
_dbus_return_if_fail (!message->locked);
_dbus_header_set_serial (&message->header, serial);
}
void
_dbus_message_add_counter_link (DBusMessage *message,
DBusList *link)
{
/* right now we don't recompute the delta when message
* size changes, and that's OK for current purposes
* I think, but could be important to change later.
* Do recompute it whenever there are no outstanding counters,
* since it's basically free.
*/
if (message->counters == NULL)
{
message->size_counter_delta =
_dbus_string_get_length (&message->header.data) +
_dbus_string_get_length (&message->body);
#ifdef HAVE_UNIX_FD_PASSING
message->unix_fd_counter_delta = message->n_unix_fds;
#endif
#if 0
_dbus_verbose ("message has size %ld\n",
message->size_counter_delta);
#endif
}
_dbus_list_append_link (&message->counters, link);
_dbus_counter_adjust_size (link->data, message->size_counter_delta);
#ifdef HAVE_UNIX_FD_PASSING
_dbus_counter_adjust_unix_fd (link->data, message->unix_fd_counter_delta);
#endif
}
dbus_bool_t
_dbus_message_add_counter (DBusMessage *message,
DBusCounter *counter)
{
DBusList *link;
link = _dbus_list_alloc_link (counter);
if (link == NULL)
return FALSE;
_dbus_counter_ref (counter);
_dbus_message_add_counter_link (message, link);
return TRUE;
}
void
_dbus_message_remove_counter (DBusMessage *message,
DBusCounter *counter)
{
DBusList *link;
link = _dbus_list_find_last (&message->counters,
counter);
_dbus_assert (link != NULL);
_dbus_list_remove_link (&message->counters, link);
_dbus_counter_adjust_size (counter, - message->size_counter_delta);
#ifdef HAVE_UNIX_FD_PASSING
_dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
#endif
_dbus_counter_notify (counter);
_dbus_counter_unref (counter);
}
void
dbus_message_lock (DBusMessage *message)
{
if (!message->locked)
{
_dbus_header_update_lengths (&message->header,
_dbus_string_get_length (&message->body));
/* must have a signature if you have a body */
_dbus_assert (_dbus_string_get_length (&message->body) == 0 ||
dbus_message_get_signature (message) != NULL);
message->locked = TRUE;
}
}
static dbus_bool_t
set_or_delete_string_field (DBusMessage *message,
int field,
int typecode,
const char *value)
{
if (value == NULL)
return _dbus_header_delete_field (&message->header, field);
else
return _dbus_header_set_field_basic (&message->header,
field,
typecode,
&value);
}
/* Message Cache
*
* We cache some DBusMessage to reduce the overhead of allocating
* them. In my profiling this consistently made about an 8%
* difference. It avoids the malloc for the message, the malloc for
* the slot list, the malloc for the header string and body string,
* and the associated free() calls. It does introduce another global
* lock which could be a performance issue in certain cases.
*
* For the echo client/server the round trip time goes from around
* .000077 to .000069 with the message cache on my laptop. The sysprof
* change is as follows (numbers are cumulative percentage):
*
* with message cache implemented as array as it is now (0.000069 per):
* new_empty_header 1.46
* mutex_lock 0.56 # i.e. _DBUS_LOCK(message_cache)
* mutex_unlock 0.25
* self 0.41
* unref 2.24
* self 0.68
* list_clear 0.43
* mutex_lock 0.33 # i.e. _DBUS_LOCK(message_cache)
* mutex_unlock 0.25
*
* with message cache implemented as list (0.000070 per roundtrip):
* new_empty_header 2.72
* list_pop_first 1.88
* unref 3.3
* list_prepend 1.63
*
* without cache (0.000077 per roundtrip):
* new_empty_header 6.7
* string_init_preallocated 3.43
* dbus_malloc 2.43
* dbus_malloc0 2.59
*
* unref 4.02
* string_free 1.82
* dbus_free 1.63
* dbus_free 0.71
*
* If you implement the message_cache with a list, the primary reason
* it's slower is that you add another thread lock (on the DBusList
* mempool).
*/
#define MAX_MESSAGE_SIZE_TO_CACHE 10 * _DBUS_ONE_KILOBYTE
#define MAX_MESSAGE_CACHE_SIZE 5
/* Protected by _DBUS_LOCK (message_cache) */
static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE];
static int message_cache_count = 0;
static dbus_bool_t message_cache_shutdown_registered = FALSE;
static void
dbus_message_cache_shutdown (void *data)
{
int i;
if (!_DBUS_LOCK (message_cache))
_dbus_assert_not_reached ("we would have initialized global locks "
"before registering a shutdown function");
i = 0;
while (i < MAX_MESSAGE_CACHE_SIZE)
{
if (message_cache[i])
dbus_message_finalize (message_cache[i]);
++i;
}
message_cache_count = 0;
message_cache_shutdown_registered = FALSE;
_DBUS_UNLOCK (message_cache);
}
static DBusMessage*
dbus_message_get_cached (void)
{
DBusMessage *message;
int i;
message = NULL;
if (!_DBUS_LOCK (message_cache))
{
/* we'd have initialized global locks before caching anything,
* so there can't be anything in the cache */
return NULL;
}
_dbus_assert (message_cache_count >= 0);
if (message_cache_count == 0)
{
_DBUS_UNLOCK (message_cache);
return NULL;
}
/* This is not necessarily true unless count > 0, and
* message_cache is uninitialized until the shutdown is
* registered
*/
_dbus_assert (message_cache_shutdown_registered);
i = 0;
while (i < MAX_MESSAGE_CACHE_SIZE)
{
if (message_cache[i])
{
message = message_cache[i];
message_cache[i] = NULL;
message_cache_count -= 1;
break;
}
++i;
}
_dbus_assert (message_cache_count >= 0);
_dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
_dbus_assert (message != NULL);
_dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
_dbus_assert (message->counters == NULL);
_DBUS_UNLOCK (message_cache);
return message;
}
#ifdef HAVE_UNIX_FD_PASSING
static void
close_unix_fds(int *fds, unsigned *n_fds)
{
DBusError e;
unsigned int i;
if (*n_fds <= 0)
return;
dbus_error_init(&e);
for (i = 0; i < *n_fds; i++)
{
if (!_dbus_close(fds[i], &e))
{
_dbus_warn("Failed to close file descriptor: %s", e.message);
dbus_error_free(&e);
}
}
*n_fds = 0;
/* We don't free the array here, in case we can recycle it later */
}
#endif
static void
free_counter (void *element,
void *data)
{
DBusCounter *counter = element;
DBusMessage *message = data;
_dbus_counter_adjust_size (counter, - message->size_counter_delta);
#ifdef HAVE_UNIX_FD_PASSING
_dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
#endif
_dbus_counter_notify (counter);
_dbus_counter_unref (counter);
}
static void
dbus_message_cache_or_finalize (DBusMessage *message)
{
dbus_bool_t was_cached;
int i;
_dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
/* This calls application code and has to be done first thing
* without holding the lock
*/
_dbus_data_slot_list_clear (&message->slot_list);
_dbus_list_foreach (&message->counters,
free_counter, message);
_dbus_list_clear (&message->counters);
#ifdef HAVE_UNIX_FD_PASSING
close_unix_fds(message->unix_fds, &message->n_unix_fds);
#endif
was_cached = FALSE;
if (!_DBUS_LOCK (message_cache))
{
/* The only way to get a non-null message goes through
* dbus_message_get_cached() which takes the lock. */
_dbus_assert_not_reached ("we would have initialized global locks "
"the first time we constructed a message");
}
if (!message_cache_shutdown_registered)
{
_dbus_assert (message_cache_count == 0);
if (!_dbus_register_shutdown_func (dbus_message_cache_shutdown, NULL))
goto out;
i = 0;
while (i < MAX_MESSAGE_CACHE_SIZE)
{
message_cache[i] = NULL;
++i;
}
message_cache_shutdown_registered = TRUE;
}
_dbus_assert (message_cache_count >= 0);
if (!_dbus_enable_message_cache ())
goto out;
if ((_dbus_string_get_length (&message->header.data) +
_dbus_string_get_length (&message->body)) >
MAX_MESSAGE_SIZE_TO_CACHE)
goto out;
if (message_cache_count >= MAX_MESSAGE_CACHE_SIZE)
goto out;
/* Find empty slot */
i = 0;
while (message_cache[i] != NULL)
++i;
_dbus_assert (i < MAX_MESSAGE_CACHE_SIZE);
_dbus_assert (message_cache[i] == NULL);
message_cache[i] = message;
message_cache_count += 1;
was_cached = TRUE;
#ifndef DBUS_DISABLE_CHECKS
message->in_cache = TRUE;
#endif
out:
_dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
_DBUS_UNLOCK (message_cache);
if (!was_cached)
dbus_message_finalize (message);
}
/*
* Arrange for iter to be something that _dbus_message_iter_check() would
* reject as not a valid iterator.
*/
static void
_dbus_message_real_iter_zero (DBusMessageRealIter *iter)
{
_dbus_assert (iter != NULL);
_DBUS_ZERO (*iter);
/* NULL is not, strictly speaking, guaranteed to be all-bits-zero */
iter->message = NULL;
}
void
dbus_message_iter_init_closed (DBusMessageIter *iter)
{
_dbus_return_if_fail (iter != NULL);
_dbus_message_real_iter_zero ((DBusMessageRealIter *) iter);
}
static dbus_bool_t
_dbus_message_real_iter_is_zeroed (DBusMessageRealIter *iter)
{
return (iter != NULL && iter->message == NULL && iter->changed_stamp == 0 &&
iter->iter_type == 0 && iter->sig_refcount == 0);
}
#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
static dbus_bool_t
_dbus_message_iter_check (DBusMessageRealIter *iter)
{
char byte_order;
if (iter == NULL)
{
_dbus_warn_check_failed ("dbus message iterator is NULL");
return FALSE;
}
if (iter->message == NULL || iter->iter_type == 0)
{
_dbus_warn_check_failed ("dbus message iterator has already been "
"closed, or is uninitialized or corrupt");
return FALSE;
}
byte_order = _dbus_header_get_byte_order (&iter->message->header);
if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_READER)
{
if (iter->u.reader.byte_order != byte_order)
{
_dbus_warn_check_failed ("dbus message changed byte order since iterator was created");
return FALSE;
}
/* because we swap the message into compiler order when you init an iter */
_dbus_assert (iter->u.reader.byte_order == DBUS_COMPILER_BYTE_ORDER);
}
else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
{
if (iter->u.writer.byte_order != byte_order)
{
_dbus_warn_check_failed ("dbus message changed byte order since append iterator was created");
return FALSE;
}
/* because we swap the message into compiler order when you init an iter */
_dbus_assert (iter->u.writer.byte_order == DBUS_COMPILER_BYTE_ORDER);
}
else
{
_dbus_warn_check_failed ("dbus message iterator looks uninitialized or corrupted");
return FALSE;
}
if (iter->changed_stamp != iter->message->changed_stamp)
{
_dbus_warn_check_failed ("dbus message iterator invalid because the message has been modified (or perhaps the iterator is just uninitialized)");
return FALSE;
}
return TRUE;
}
#endif /* DBUS_ENABLE_CHECKS || DBUS_ENABLE_ASSERT */
dbus_bool_t
_dbus_message_iter_get_args_valist (DBusMessageIter *iter,
DBusError *error,
int first_arg_type,
va_list var_args)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
int spec_type, msg_type, i, j;
dbus_bool_t retval;
va_list copy_args;
_dbus_assert (_dbus_message_iter_check (real));
retval = FALSE;
spec_type = first_arg_type;
i = 0;
/* copy var_args first, then we can do another iteration over it to
* free memory and close unix fds if parse failed at some point.
*/
va_copy (copy_args, var_args);
while (spec_type != DBUS_TYPE_INVALID)
{
msg_type = dbus_message_iter_get_arg_type (iter);
if (msg_type != spec_type)
{
dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
"Argument %d is specified to be of type \"%s\", but "
"is actually of type \"%s\"\n", i,
_dbus_type_to_string (spec_type),
_dbus_type_to_string (msg_type));
goto out;
}
if (spec_type == DBUS_TYPE_UNIX_FD)
{
#ifdef HAVE_UNIX_FD_PASSING
DBusBasicValue idx;
int *pfd, nfd;
pfd = va_arg (var_args, int*);
_dbus_assert(pfd);
_dbus_type_reader_read_basic(&real->u.reader, &idx);
if (idx.u32 >= real->message->n_unix_fds)
{
dbus_set_error (error, DBUS_ERROR_INCONSISTENT_MESSAGE,
"Message refers to file descriptor at index %i,"
"but has only %i descriptors attached.\n",
idx.u32,
real->message->n_unix_fds);
goto out;
}
if ((nfd = _dbus_dup(real->message->unix_fds[idx.u32], error)) < 0)
goto out;
*pfd = nfd;
#else
dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
"Platform does not support file desciptor passing.\n");
goto out;
#endif
}
else if (dbus_type_is_basic (spec_type))
{
void *ptr;
ptr = va_arg (var_args, void *);
_dbus_assert (ptr != NULL);
_dbus_type_reader_read_basic (&real->u.reader,
ptr);
}
else if (spec_type == DBUS_TYPE_ARRAY)
{
int element_type;
int spec_element_type;
const void **ptr;
int *n_elements_p;
DBusTypeReader array;
spec_element_type = va_arg (var_args, int);
element_type = _dbus_type_reader_get_element_type (&real->u.reader);
if (spec_element_type != element_type)
{
dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
"Argument %d is specified to be an array of \"%s\", but "
"is actually an array of \"%s\"\n",
i,
_dbus_type_to_string (spec_element_type),
_dbus_type_to_string (element_type));
goto out;
}
if (dbus_type_is_fixed (spec_element_type) &&
element_type != DBUS_TYPE_UNIX_FD)
{
ptr = va_arg (var_args, const void **);
n_elements_p = va_arg (var_args, int*);
_dbus_assert (ptr != NULL);
_dbus_assert (n_elements_p != NULL);
_dbus_type_reader_recurse (&real->u.reader, &array);
_dbus_type_reader_read_fixed_multi (&array, ptr, n_elements_p);
}
else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
{
char ***str_array_p;
int n_elements;
char **str_array;
str_array_p = va_arg (var_args, char***);
n_elements_p = va_arg (var_args, int*);
_dbus_assert (str_array_p != NULL);
_dbus_assert (n_elements_p != NULL);
/* Count elements in the array */
_dbus_type_reader_recurse (&real->u.reader, &array);
n_elements = 0;
while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
{
++n_elements;
_dbus_type_reader_next (&array);
}
str_array = dbus_new0 (char*, n_elements + 1);
if (str_array == NULL)
{
_DBUS_SET_OOM (error);
goto out;
}
/* Now go through and dup each string */
_dbus_type_reader_recurse (&real->u.reader, &array);
j = 0;
while (j < n_elements)
{
const char *s;
_dbus_type_reader_read_basic (&array,
(void *) &s);
str_array[j] = _dbus_strdup (s);
if (str_array[j] == NULL)
{
dbus_free_string_array (str_array);
_DBUS_SET_OOM (error);
goto out;
}
++j;
if (!_dbus_type_reader_next (&array))
_dbus_assert (j == n_elements);
}
_dbus_assert (_dbus_type_reader_get_current_type (&array) == DBUS_TYPE_INVALID);
_dbus_assert (j == n_elements);
_dbus_assert (str_array[j] == NULL);
*str_array_p = str_array;
*n_elements_p = n_elements;
}
#ifndef DBUS_DISABLE_CHECKS
else
{
_dbus_warn ("you can't read arrays of container types (struct, variant, array) with %s for now",
_DBUS_FUNCTION_NAME);
goto out;
}
#endif
}
#ifndef DBUS_DISABLE_CHECKS
else
{
_dbus_warn ("you can only read arrays and basic types with %s for now",
_DBUS_FUNCTION_NAME);
goto out;
}
#endif
/* how many arguments already handled */
i++;
spec_type = va_arg (var_args, int);
if (!_dbus_type_reader_next (&real->u.reader) && spec_type != DBUS_TYPE_INVALID)
{
dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
"Message has only %d arguments, but more were expected", i);
goto out;
}
}
retval = TRUE;
out:
/* there may memory or unix fd leak in the above iteration if parse failed.
* so we have another iteration over copy_args to free memory and close
* unix fds.
*/
if (!retval)
{
spec_type = first_arg_type;
j = 0;
while (j < i)
{
if (spec_type == DBUS_TYPE_UNIX_FD)
{
#ifdef HAVE_UNIX_FD_PASSING
int *pfd;
pfd = va_arg (copy_args, int *);
_dbus_assert(pfd);
if (*pfd >= 0)
{
_dbus_close (*pfd, NULL);
*pfd = -1;
}
#endif
}
else if (dbus_type_is_basic (spec_type))
{
/* move the index forward */
va_arg (copy_args, const void *);
}
else if (spec_type == DBUS_TYPE_ARRAY)
{
int spec_element_type;
spec_element_type = va_arg (copy_args, int);
if (dbus_type_is_fixed (spec_element_type))
{
/* move the index forward */
va_arg (copy_args, const void **);
va_arg (copy_args, int *);
}
else if (_DBUS_TYPE_IS_STRINGLIKE (spec_element_type))
{
char ***str_array_p;
str_array_p = va_arg (copy_args, char ***);
/* move the index forward */
va_arg (copy_args, int *);
_dbus_assert (str_array_p != NULL);
dbus_free_string_array (*str_array_p);
*str_array_p = NULL;
}
}
spec_type = va_arg (copy_args, int);
j++;
}
}
va_end (copy_args);
return retval;
}
dbus_uint32_t
dbus_message_get_serial (DBusMessage *message)
{
_dbus_return_val_if_fail (message != NULL, 0);
return _dbus_header_get_serial (&message->header);
}
dbus_bool_t
dbus_message_set_reply_serial (DBusMessage *message,
dbus_uint32_t reply_serial)
{
DBusBasicValue value;
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (!message->locked, FALSE);
_dbus_return_val_if_fail (reply_serial != 0, FALSE); /* 0 is invalid */
value.u32 = reply_serial;
return _dbus_header_set_field_basic (&message->header,
DBUS_HEADER_FIELD_REPLY_SERIAL,
DBUS_TYPE_UINT32,
&value);
}
dbus_uint32_t
dbus_message_get_reply_serial (DBusMessage *message)
{
dbus_uint32_t v_UINT32;
_dbus_return_val_if_fail (message != NULL, 0);
if (_dbus_header_get_field_basic (&message->header,
DBUS_HEADER_FIELD_REPLY_SERIAL,
DBUS_TYPE_UINT32,
&v_UINT32))
return v_UINT32;
else
return 0;
}
static void
dbus_message_finalize (DBusMessage *message)
{
_dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
/* This calls application callbacks! */
_dbus_data_slot_list_free (&message->slot_list);
_dbus_list_foreach (&message->counters,
free_counter, message);
_dbus_list_clear (&message->counters);
_dbus_header_free (&message->header);
_dbus_string_free (&message->body);
#ifdef HAVE_UNIX_FD_PASSING
close_unix_fds(message->unix_fds, &message->n_unix_fds);
dbus_free(message->unix_fds);
#endif
_dbus_assert (_dbus_atomic_get (&message->refcount) == 0);
dbus_free (message);
}
static DBusMessage*
dbus_message_new_empty_header (void)
{
DBusMessage *message;
dbus_bool_t from_cache;
message = dbus_message_get_cached ();
if (message != NULL)
{
from_cache = TRUE;
}
else
{
from_cache = FALSE;
message = dbus_new0 (DBusMessage, 1);
if (message == NULL)
return NULL;
#ifndef DBUS_DISABLE_CHECKS
message->generation = _dbus_current_generation;
#endif
#ifdef HAVE_UNIX_FD_PASSING
message->unix_fds = NULL;
message->n_unix_fds_allocated = 0;
#endif
}
_dbus_atomic_inc (&message->refcount);
_dbus_message_trace_ref (message, 0, 1, "new_empty_header");
message->locked = FALSE;
#ifndef DBUS_DISABLE_CHECKS
message->in_cache = FALSE;
#endif
message->counters = NULL;
message->size_counter_delta = 0;
message->changed_stamp = 0;
#ifdef HAVE_UNIX_FD_PASSING
message->n_unix_fds = 0;
message->n_unix_fds_allocated = 0;
message->unix_fd_counter_delta = 0;
#endif
if (!from_cache)
_dbus_data_slot_list_init (&message->slot_list);
if (from_cache)
{
_dbus_header_reinit (&message->header);
_dbus_string_set_length (&message->body, 0);
}
else
{
if (!_dbus_header_init (&message->header))
{
dbus_free (message);
return NULL;
}
if (!_dbus_string_init_preallocated (&message->body, 32))
{
_dbus_header_free (&message->header);
dbus_free (message);
return NULL;
}
}
return message;
}
DBusMessage*
dbus_message_new (int message_type)
{
DBusMessage *message;
_dbus_return_val_if_fail (message_type != DBUS_MESSAGE_TYPE_INVALID, NULL);
message = dbus_message_new_empty_header ();
if (message == NULL)
return NULL;
if (!_dbus_header_create (&message->header,
DBUS_COMPILER_BYTE_ORDER,
message_type,
NULL, NULL, NULL, NULL, NULL))
{
dbus_message_unref (message);
return NULL;
}
return message;
}
DBusMessage*
dbus_message_new_method_call (const char *destination,
const char *path,
const char *iface,
const char *method)
{
DBusMessage *message;
_dbus_return_val_if_fail (path != NULL, NULL);
_dbus_return_val_if_fail (method != NULL, NULL);
_dbus_return_val_if_fail (destination == NULL ||
_dbus_check_is_valid_bus_name (destination), NULL);
_dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
_dbus_return_val_if_fail (iface == NULL ||
_dbus_check_is_valid_interface (iface), NULL);
_dbus_return_val_if_fail (_dbus_check_is_valid_member (method), NULL);
message = dbus_message_new_empty_header ();
if (message == NULL)
return NULL;
if (!_dbus_header_create (&message->header,
DBUS_COMPILER_BYTE_ORDER,
DBUS_MESSAGE_TYPE_METHOD_CALL,
destination, path, iface, method, NULL))
{
dbus_message_unref (message);
return NULL;
}
return message;
}
DBusMessage*
dbus_message_new_method_return (DBusMessage *method_call)
{
DBusMessage *message;
const char *sender;
_dbus_return_val_if_fail (method_call != NULL, NULL);
sender = dbus_message_get_sender (method_call);
/* sender is allowed to be null here in peer-to-peer case */
message = dbus_message_new_empty_header ();
if (message == NULL)
return NULL;
if (!_dbus_header_create (&message->header,
DBUS_COMPILER_BYTE_ORDER,
DBUS_MESSAGE_TYPE_METHOD_RETURN,
sender, NULL, NULL, NULL, NULL))
{
dbus_message_unref (message);
return NULL;
}
dbus_message_set_no_reply (message, TRUE);
if (!dbus_message_set_reply_serial (message,
dbus_message_get_serial (method_call)))
{
dbus_message_unref (message);
return NULL;
}
return message;
}
DBusMessage*
dbus_message_new_signal (const char *path,
const char *iface,
const char *name)
{
DBusMessage *message;
_dbus_return_val_if_fail (path != NULL, NULL);
_dbus_return_val_if_fail (iface != NULL, NULL);
_dbus_return_val_if_fail (name != NULL, NULL);
_dbus_return_val_if_fail (_dbus_check_is_valid_path (path), NULL);
_dbus_return_val_if_fail (_dbus_check_is_valid_interface (iface), NULL);
_dbus_return_val_if_fail (_dbus_check_is_valid_member (name), NULL);
message = dbus_message_new_empty_header ();
if (message == NULL)
return NULL;
if (!_dbus_header_create (&message->header,
DBUS_COMPILER_BYTE_ORDER,
DBUS_MESSAGE_TYPE_SIGNAL,
NULL, path, iface, name, NULL))
{
dbus_message_unref (message);
return NULL;
}
dbus_message_set_no_reply (message, TRUE);
return message;
}
DBusMessage*
dbus_message_new_error (DBusMessage *reply_to,
const char *error_name,
const char *error_message)
{
DBusMessage *message;
const char *sender;
DBusMessageIter iter;
_dbus_return_val_if_fail (reply_to != NULL, NULL);
_dbus_return_val_if_fail (error_name != NULL, NULL);
_dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
sender = dbus_message_get_sender (reply_to);
/* sender may be NULL for non-message-bus case or
* when the message bus is dealing with an unregistered
* connection.
*/
message = dbus_message_new_empty_header ();
if (message == NULL)
return NULL;
if (!_dbus_header_create (&message->header,
DBUS_COMPILER_BYTE_ORDER,
DBUS_MESSAGE_TYPE_ERROR,
sender, NULL, NULL, NULL, error_name))
{
dbus_message_unref (message);
return NULL;
}
dbus_message_set_no_reply (message, TRUE);
if (!dbus_message_set_reply_serial (message,
dbus_message_get_serial (reply_to)))
{
dbus_message_unref (message);
return NULL;
}
if (error_message != NULL)
{
dbus_message_iter_init_append (message, &iter);
if (!dbus_message_iter_append_basic (&iter,
DBUS_TYPE_STRING,
&error_message))
{
dbus_message_unref (message);
return NULL;
}
}
return message;
}
DBusMessage*
dbus_message_new_error_printf (DBusMessage *reply_to,
const char *error_name,
const char *error_format,
...)
{
va_list args;
DBusString str;
DBusMessage *message;
_dbus_return_val_if_fail (reply_to != NULL, NULL);
_dbus_return_val_if_fail (error_name != NULL, NULL);
_dbus_return_val_if_fail (_dbus_check_is_valid_error_name (error_name), NULL);
if (!_dbus_string_init (&str))
return NULL;
va_start (args, error_format);
if (_dbus_string_append_printf_valist (&str, error_format, args))
message = dbus_message_new_error (reply_to, error_name,
_dbus_string_get_const_data (&str));
else
message = NULL;
_dbus_string_free (&str);
va_end (args);
return message;
}
DBusMessage *
dbus_message_copy (const DBusMessage *message)
{
DBusMessage *retval;
_dbus_return_val_if_fail (message != NULL, NULL);
retval = dbus_new0 (DBusMessage, 1);
if (retval == NULL)
return NULL;
_dbus_atomic_inc (&retval->refcount);
retval->locked = FALSE;
#ifndef DBUS_DISABLE_CHECKS
retval->generation = message->generation;
#endif
if (!_dbus_header_copy (&message->header, &retval->header))
{
dbus_free (retval);
return NULL;
}
if (!_dbus_string_init_preallocated (&retval->body,
_dbus_string_get_length (&message->body)))
{
_dbus_header_free (&retval->header);
dbus_free (retval);
return NULL;
}
if (!_dbus_string_copy (&message->body, 0,
&retval->body, 0))
goto failed_copy;
#ifdef HAVE_UNIX_FD_PASSING
retval->unix_fds = dbus_new(int, message->n_unix_fds);
if (retval->unix_fds == NULL && message->n_unix_fds > 0)
goto failed_copy;
retval->n_unix_fds_allocated = message->n_unix_fds;
for (retval->n_unix_fds = 0;
retval->n_unix_fds < message->n_unix_fds;
retval->n_unix_fds++)
{
retval->unix_fds[retval->n_unix_fds] = _dbus_dup(message->unix_fds[retval->n_unix_fds], NULL);
if (retval->unix_fds[retval->n_unix_fds] < 0)
goto failed_copy;
}
#endif
_dbus_message_trace_ref (retval, 0, 1, "copy");
return retval;
failed_copy:
_dbus_header_free (&retval->header);
_dbus_string_free (&retval->body);
#ifdef HAVE_UNIX_FD_PASSING
close_unix_fds(retval->unix_fds, &retval->n_unix_fds);
dbus_free(retval->unix_fds);
#endif
dbus_free (retval);
return NULL;
}
DBusMessage *
dbus_message_ref (DBusMessage *message)
{
dbus_int32_t old_refcount;
_dbus_return_val_if_fail (message != NULL, NULL);
_dbus_return_val_if_fail (message->generation == _dbus_current_generation, NULL);
_dbus_return_val_if_fail (!message->in_cache, NULL);
old_refcount = _dbus_atomic_inc (&message->refcount);
_dbus_assert (old_refcount >= 1);
_dbus_message_trace_ref (message, old_refcount, old_refcount + 1, "ref");
return message;
}
void
dbus_message_unref (DBusMessage *message)
{
dbus_int32_t old_refcount;
_dbus_return_if_fail (message != NULL);
_dbus_return_if_fail (message->generation == _dbus_current_generation);
_dbus_return_if_fail (!message->in_cache);
old_refcount = _dbus_atomic_dec (&message->refcount);
_dbus_assert (old_refcount >= 1);
_dbus_message_trace_ref (message, old_refcount, old_refcount - 1, "unref");
if (old_refcount == 1)
{
/* Calls application callbacks! */
dbus_message_cache_or_finalize (message);
}
}
int
dbus_message_get_type (DBusMessage *message)
{
_dbus_return_val_if_fail (message != NULL, DBUS_MESSAGE_TYPE_INVALID);
return _dbus_header_get_message_type (&message->header);
}
dbus_bool_t
dbus_message_append_args (DBusMessage *message,
int first_arg_type,
...)
{
dbus_bool_t retval;
va_list var_args;
_dbus_return_val_if_fail (message != NULL, FALSE);
va_start (var_args, first_arg_type);
retval = dbus_message_append_args_valist (message,
first_arg_type,
var_args);
va_end (var_args);
return retval;
}
dbus_bool_t
dbus_message_append_args_valist (DBusMessage *message,
int first_arg_type,
va_list var_args)
{
int type;
DBusMessageIter iter;
_dbus_return_val_if_fail (message != NULL, FALSE);
type = first_arg_type;
dbus_message_iter_init_append (message, &iter);
while (type != DBUS_TYPE_INVALID)
{
if (dbus_type_is_basic (type))
{
const void *value;
value = va_arg (var_args, const void *);
if (!dbus_message_iter_append_basic (&iter,
type,
value))
goto failed;
}
else if (type == DBUS_TYPE_ARRAY)
{
int element_type;
DBusMessageIter array;
char buf[2];
element_type = va_arg (var_args, int);
buf[0] = element_type;
buf[1] = '\0';
if (!dbus_message_iter_open_container (&iter,
DBUS_TYPE_ARRAY,
buf,
&array))
goto failed;
if (dbus_type_is_fixed (element_type) &&
element_type != DBUS_TYPE_UNIX_FD)
{
const void **value;
int n_elements;
value = va_arg (var_args, const void **);
n_elements = va_arg (var_args, int);
if (!dbus_message_iter_append_fixed_array (&array,
element_type,
value,
n_elements)) {
dbus_message_iter_abandon_container (&iter, &array);
goto failed;
}
}
else if (_DBUS_TYPE_IS_STRINGLIKE (element_type))
{
const char ***value_p;
const char **value;
int n_elements;
int i;
value_p = va_arg (var_args, const char***);
n_elements = va_arg (var_args, int);
value = *value_p;
i = 0;
while (i < n_elements)
{
if (!dbus_message_iter_append_basic (&array,
element_type,
&value[i])) {
dbus_message_iter_abandon_container (&iter, &array);
goto failed;
}
++i;
}
}
else
{
_dbus_warn ("arrays of %s can't be appended with %s for now",
_dbus_type_to_string (element_type),
_DBUS_FUNCTION_NAME);
dbus_message_iter_abandon_container (&iter, &array);
goto failed;
}
if (!dbus_message_iter_close_container (&iter, &array))
goto failed;
}
#ifndef DBUS_DISABLE_CHECKS
else
{
_dbus_warn ("type %s isn't supported yet in %s",
_dbus_type_to_string (type), _DBUS_FUNCTION_NAME);
goto failed;
}
#endif
type = va_arg (var_args, int);
}
return TRUE;
failed:
return FALSE;
}
dbus_bool_t
dbus_message_get_args (DBusMessage *message,
DBusError *error,
int first_arg_type,
...)
{
dbus_bool_t retval;
va_list var_args;
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_error_is_set (error, FALSE);
va_start (var_args, first_arg_type);
retval = dbus_message_get_args_valist (message, error, first_arg_type, var_args);
va_end (var_args);
return retval;
}
dbus_bool_t
dbus_message_get_args_valist (DBusMessage *message,
DBusError *error,
int first_arg_type,
va_list var_args)
{
DBusMessageIter iter;
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_error_is_set (error, FALSE);
dbus_message_iter_init (message, &iter);
return _dbus_message_iter_get_args_valist (&iter, error, first_arg_type, var_args);
}
static void
_dbus_message_iter_init_common (DBusMessage *message,
DBusMessageRealIter *real,
int iter_type)
{
/* If these static assertions fail on your platform, report it as a bug. */
_DBUS_STATIC_ASSERT (sizeof (DBusMessageRealIter) <= sizeof (DBusMessageIter));
_DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageRealIter) <=
_DBUS_ALIGNOF (DBusMessageIter));
#if CHECK_DBUS_1_10_BINARY_COMPATIBILITY
/* A failure of these two assertions would indicate that we've broken
* ABI on this platform since 1.10.0. */
_DBUS_STATIC_ASSERT (sizeof (DBusMessageIter_1_10_0) ==
sizeof (DBusMessageIter));
_DBUS_STATIC_ASSERT (_DBUS_ALIGNOF (DBusMessageIter_1_10_0) ==
_DBUS_ALIGNOF (DBusMessageIter));
#endif
/* If this static assertion fails, it means the DBusMessageIter struct
* is not "packed", which might result in "iter = other_iter" not copying
* every byte. */
#if DBUS_SIZEOF_VOID_P > 8
_DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) == 16 * sizeof (void *));
#else
_DBUS_STATIC_ASSERT (sizeof (DBusMessageIter) ==
4 * sizeof (void *) + sizeof (dbus_uint32_t) + 9 * sizeof (int));
#endif
/* Since the iterator will read or write who-knows-what from the
* message, we need to get in the right byte order
*/
ensure_byte_order (message);
real->message = message;
real->changed_stamp = message->changed_stamp;
real->iter_type = iter_type;
real->sig_refcount = 0;
}
dbus_bool_t
dbus_message_iter_init (DBusMessage *message,
DBusMessageIter *iter)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
const DBusString *type_str;
int type_pos;
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (iter != NULL, FALSE);
get_const_signature (&message->header, &type_str, &type_pos);
_dbus_message_iter_init_common (message, real,
DBUS_MESSAGE_ITER_TYPE_READER);
_dbus_type_reader_init (&real->u.reader,
_dbus_header_get_byte_order (&message->header),
type_str, type_pos,
&message->body,
0);
return _dbus_type_reader_get_current_type (&real->u.reader) != DBUS_TYPE_INVALID;
}
dbus_bool_t
dbus_message_iter_has_next (DBusMessageIter *iter)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
_dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
_dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
return _dbus_type_reader_has_next (&real->u.reader);
}
dbus_bool_t
dbus_message_iter_next (DBusMessageIter *iter)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
_dbus_return_val_if_fail (_dbus_message_iter_check (real), FALSE);
_dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
return _dbus_type_reader_next (&real->u.reader);
}
int
dbus_message_iter_get_arg_type (DBusMessageIter *iter)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
_dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
_dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, FALSE);
return _dbus_type_reader_get_current_type (&real->u.reader);
}
int
dbus_message_iter_get_element_type (DBusMessageIter *iter)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
_dbus_return_val_if_fail (_dbus_message_iter_check (real), DBUS_TYPE_INVALID);
_dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_READER, DBUS_TYPE_INVALID);
_dbus_return_val_if_fail (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_ARRAY, DBUS_TYPE_INVALID);
return _dbus_type_reader_get_element_type (&real->u.reader);
}
void
dbus_message_iter_recurse (DBusMessageIter *iter,
DBusMessageIter *sub)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
_dbus_return_if_fail (_dbus_message_iter_check (real));
_dbus_return_if_fail (sub != NULL);
*real_sub = *real;
_dbus_type_reader_recurse (&real->u.reader, &real_sub->u.reader);
}
char *
dbus_message_iter_get_signature (DBusMessageIter *iter)
{
const DBusString *sig;
DBusString retstr;
char *ret = NULL;
int start, len;
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
_dbus_return_val_if_fail (_dbus_message_iter_check (real), NULL);
if (!_dbus_string_init (&retstr))
return NULL;
_dbus_type_reader_get_signature (&real->u.reader, &sig,
&start, &len);
if (!_dbus_string_append_len (&retstr,
_dbus_string_get_const_data (sig) + start,
len))
goto oom;
/* This is correct whether it succeeds or fails: on success it sets `ret`,
* and on failure it leaves `ret` set to NULL. */
_dbus_string_steal_data (&retstr, &ret);
oom:
_dbus_string_free (&retstr);
return ret;
}
void
dbus_message_iter_get_basic (DBusMessageIter *iter,
void *value)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
_dbus_return_if_fail (_dbus_message_iter_check (real));
_dbus_return_if_fail (value != NULL);
if (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_UNIX_FD)
{
#ifdef HAVE_UNIX_FD_PASSING
DBusBasicValue idx;
_dbus_type_reader_read_basic(&real->u.reader, &idx);
if (idx.u32 >= real->message->n_unix_fds) {
/* Hmm, we cannot really signal an error here, so let's make
sure to return an invalid fd. */
*((int*) value) = -1;
return;
}
*((int*) value) = _dbus_dup(real->message->unix_fds[idx.u32], NULL);
#else
*((int*) value) = -1;
#endif
}
else
{
_dbus_type_reader_read_basic (&real->u.reader,
value);
}
}
int
dbus_message_iter_get_element_count (DBusMessageIter *iter)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
DBusTypeReader array;
int element_type;
int n_elements = 0;
_dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
_dbus_return_val_if_fail (_dbus_type_reader_get_current_type (&real->u.reader)
== DBUS_TYPE_ARRAY, 0);
element_type = _dbus_type_reader_get_element_type (&real->u.reader);
_dbus_type_reader_recurse (&real->u.reader, &array);
if (dbus_type_is_fixed (element_type))
{
int alignment = _dbus_type_get_alignment (element_type);
int total_len = _dbus_type_reader_get_array_length (&array);
n_elements = total_len / alignment;
}
else
{
while (_dbus_type_reader_get_current_type (&array) != DBUS_TYPE_INVALID)
{
++n_elements;
_dbus_type_reader_next (&array);
}
}
return n_elements;
}
int
dbus_message_iter_get_array_len (DBusMessageIter *iter)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
_dbus_return_val_if_fail (_dbus_message_iter_check (real), 0);
return _dbus_type_reader_get_array_length (&real->u.reader);
}
void
dbus_message_iter_get_fixed_array (DBusMessageIter *iter,
void *value,
int *n_elements)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
#ifndef DBUS_DISABLE_CHECKS
int subtype = _dbus_type_reader_get_current_type(&real->u.reader);
_dbus_return_if_fail (_dbus_message_iter_check (real));
_dbus_return_if_fail (value != NULL);
_dbus_return_if_fail ((subtype == DBUS_TYPE_INVALID) ||
(dbus_type_is_fixed (subtype) && subtype != DBUS_TYPE_UNIX_FD));
#endif
_dbus_type_reader_read_fixed_multi (&real->u.reader,
value, n_elements);
}
void
dbus_message_iter_init_append (DBusMessage *message,
DBusMessageIter *iter)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
_dbus_return_if_fail (message != NULL);
_dbus_return_if_fail (iter != NULL);
_dbus_message_iter_init_common (message, real,
DBUS_MESSAGE_ITER_TYPE_WRITER);
/* We create the signature string and point iterators at it "on demand"
* when a value is actually appended. That means that init() never fails
* due to OOM.
*/
_dbus_type_writer_init_types_delayed (&real->u.writer,
_dbus_header_get_byte_order (&message->header),
&message->body,
_dbus_string_get_length (&message->body));
}
static dbus_bool_t
_dbus_message_iter_open_signature (DBusMessageRealIter *real)
{
DBusString *str;
const DBusString *current_sig;
int current_sig_pos;
_dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
if (real->u.writer.type_str != NULL)
{
_dbus_assert (real->sig_refcount > 0);
real->sig_refcount += 1;
return TRUE;
}
str = dbus_new (DBusString, 1);
if (str == NULL)
return FALSE;
if (!_dbus_header_get_field_raw (&real->message->header,
DBUS_HEADER_FIELD_SIGNATURE,
&current_sig, &current_sig_pos))
current_sig = NULL;
if (current_sig)
{
int current_len;
current_len = _dbus_string_get_byte (current_sig, current_sig_pos);
current_sig_pos += 1; /* move on to sig data */
if (!_dbus_string_init_preallocated (str, current_len + 4))
{
dbus_free (str);
return FALSE;
}
if (!_dbus_string_copy_len (current_sig, current_sig_pos, current_len,
str, 0))
{
_dbus_string_free (str);
dbus_free (str);
return FALSE;
}
}
else
{
if (!_dbus_string_init_preallocated (str, 4))
{
dbus_free (str);
return FALSE;
}
}
real->sig_refcount = 1;
/* If this assertion failed, then str would be neither stored in u.writer
* nor freed by this function, resulting in a memory leak. */
_dbus_assert (real->u.writer.type_str == NULL);
_dbus_type_writer_add_types (&real->u.writer,
str, _dbus_string_get_length (str));
return TRUE;
}
static dbus_bool_t
_dbus_message_iter_close_signature (DBusMessageRealIter *real)
{
DBusString *str;
const char *v_STRING;
dbus_bool_t retval;
_dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
_dbus_assert (real->u.writer.type_str != NULL);
_dbus_assert (real->sig_refcount > 0);
real->sig_refcount -= 1;
if (real->sig_refcount > 0)
return TRUE;
_dbus_assert (real->sig_refcount == 0);
retval = TRUE;
str = real->u.writer.type_str;
v_STRING = _dbus_string_get_const_data (str);
if (!_dbus_header_set_field_basic (&real->message->header,
DBUS_HEADER_FIELD_SIGNATURE,
DBUS_TYPE_SIGNATURE,
&v_STRING))
retval = FALSE;
_dbus_type_writer_remove_types (&real->u.writer);
_dbus_string_free (str);
dbus_free (str);
return retval;
}
static void
_dbus_message_iter_abandon_signature (DBusMessageRealIter *real)
{
DBusString *str;
_dbus_assert (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
_dbus_assert (real->u.writer.type_str != NULL);
_dbus_assert (real->sig_refcount > 0);
real->sig_refcount -= 1;
if (real->sig_refcount > 0)
return;
_dbus_assert (real->sig_refcount == 0);
str = real->u.writer.type_str;
_dbus_type_writer_remove_types (&real->u.writer);
_dbus_string_free (str);
dbus_free (str);
}
#if defined(DBUS_ENABLE_CHECKS) || defined(DBUS_ENABLE_ASSERT)
static dbus_bool_t
_dbus_message_iter_append_check (DBusMessageRealIter *iter)
{
if (!_dbus_message_iter_check (iter))
return FALSE;
if (iter->message->locked)
{
_dbus_warn_check_failed ("dbus append iterator can't be used: message is locked (has already been sent)");
return FALSE;
}
return TRUE;
}
#endif
#ifdef HAVE_UNIX_FD_PASSING
static int *
expand_fd_array(DBusMessage *m,
unsigned n)
{
_dbus_assert(m);
/* This makes space for adding n new fds to the array and returns a
pointer to the place were the first fd should be put. */
if (m->n_unix_fds + n > m->n_unix_fds_allocated)
{
unsigned k;
int *p;
/* Make twice as much space as necessary */
k = (m->n_unix_fds + n) * 2;
/* Allocate at least four */
if (k < 4)
k = 4;
p = dbus_realloc(m->unix_fds, k * sizeof(int));
if (p == NULL)
return NULL;
m->unix_fds = p;
m->n_unix_fds_allocated = k;
}
return m->unix_fds + m->n_unix_fds;
}
#endif
dbus_bool_t
dbus_message_iter_append_basic (DBusMessageIter *iter,
int type,
const void *value)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
dbus_bool_t ret;
_dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
_dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
_dbus_return_val_if_fail (dbus_type_is_basic (type), FALSE);
_dbus_return_val_if_fail (value != NULL, FALSE);
#ifndef DBUS_DISABLE_CHECKS
switch (type)
{
DBusString str;
DBusValidity signature_validity;
const char * const *string_p;
const dbus_bool_t *bool_p;
case DBUS_TYPE_STRING:
string_p = value;
_dbus_return_val_if_fail (_dbus_check_is_valid_utf8 (*string_p), FALSE);
break;
case DBUS_TYPE_OBJECT_PATH:
string_p = value;
_dbus_return_val_if_fail (_dbus_check_is_valid_path (*string_p), FALSE);
break;
case DBUS_TYPE_SIGNATURE:
string_p = value;
_dbus_string_init_const (&str, *string_p);
signature_validity = _dbus_validate_signature_with_reason (&str,
0,
_dbus_string_get_length (&str));
if (signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
return FALSE;
_dbus_return_val_if_fail (signature_validity == DBUS_VALID, FALSE);
break;
case DBUS_TYPE_BOOLEAN:
bool_p = value;
_dbus_return_val_if_fail (*bool_p == 0 || *bool_p == 1, FALSE);
break;
default:
{
/* nothing to check, all possible values are allowed */
}
}
#endif
if (!_dbus_message_iter_open_signature (real))
return FALSE;
if (type == DBUS_TYPE_UNIX_FD)
{
#ifdef HAVE_UNIX_FD_PASSING
int *fds;
dbus_uint32_t u;
ret = FALSE;
/* First step, include the fd in the fd list of this message */
if (!(fds = expand_fd_array(real->message, 1)))
goto out;
*fds = _dbus_dup(*(int*) value, NULL);
if (*fds < 0)
goto out;
u = real->message->n_unix_fds;
/* Second step, write the index to the fd */
if (!(ret = _dbus_type_writer_write_basic (&real->u.writer, DBUS_TYPE_UNIX_FD, &u))) {
_dbus_close(*fds, NULL);
goto out;
}
real->message->n_unix_fds += 1;
u += 1;
/* Final step, update the header accordingly */
ret = _dbus_header_set_field_basic (&real->message->header,
DBUS_HEADER_FIELD_UNIX_FDS,
DBUS_TYPE_UINT32,
&u);
/* If any of these operations fail the message is
hosed. However, no memory or fds should be leaked since what
has been added to message has been added to the message, and
can hence be accounted for when the message is being
freed. */
#else
ret = FALSE;
/* This is redundant (we could just fall through), but it avoids
* -Wunused-label in builds that don't HAVE_UNIX_FD_PASSING */
goto out;
#endif
}
else
{
ret = _dbus_type_writer_write_basic (&real->u.writer, type, value);
}
out:
if (!_dbus_message_iter_close_signature (real))
ret = FALSE;
return ret;
}
dbus_bool_t
dbus_message_iter_append_fixed_array (DBusMessageIter *iter,
int element_type,
const void *value,
int n_elements)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
dbus_bool_t ret;
_dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
_dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
_dbus_return_val_if_fail (dbus_type_is_fixed (element_type) && element_type != DBUS_TYPE_UNIX_FD, FALSE);
_dbus_return_val_if_fail (real->u.writer.container_type == DBUS_TYPE_ARRAY, FALSE);
_dbus_return_val_if_fail (value != NULL, FALSE);
_dbus_return_val_if_fail (n_elements >= 0, FALSE);
_dbus_return_val_if_fail (n_elements <=
DBUS_MAXIMUM_ARRAY_LENGTH / _dbus_type_get_alignment (element_type),
FALSE);
#ifndef DBUS_DISABLE_CHECKS
if (element_type == DBUS_TYPE_BOOLEAN)
{
const dbus_bool_t * const *bools = value;
int i;
for (i = 0; i < n_elements; i++)
{
_dbus_return_val_if_fail ((*bools)[i] == 0 || (*bools)[i] == 1, FALSE);
}
}
#endif
ret = _dbus_type_writer_write_fixed_multi (&real->u.writer, element_type, value, n_elements);
return ret;
}
dbus_bool_t
dbus_message_iter_open_container (DBusMessageIter *iter,
int type,
const char *contained_signature,
DBusMessageIter *sub)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
DBusString contained_str;
DBusValidity contained_signature_validity;
dbus_bool_t ret;
_dbus_return_val_if_fail (sub != NULL, FALSE);
/* Do our best to make sure the sub-iterator doesn't contain something
* valid-looking on failure */
_dbus_message_real_iter_zero (real_sub);
_dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
_dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
_dbus_return_val_if_fail (dbus_type_is_container (type), FALSE);
_dbus_return_val_if_fail ((type == DBUS_TYPE_STRUCT &&
contained_signature == NULL) ||
(type == DBUS_TYPE_DICT_ENTRY &&
contained_signature == NULL) ||
(type == DBUS_TYPE_VARIANT &&
contained_signature != NULL) ||
(type == DBUS_TYPE_ARRAY &&
contained_signature != NULL), FALSE);
/* this would fail if the contained_signature is a dict entry, since
* dict entries are invalid signatures standalone (they must be in
* an array)
*/
if (contained_signature != NULL)
{
_dbus_string_init_const (&contained_str, contained_signature);
contained_signature_validity = _dbus_validate_signature_with_reason (&contained_str,
0,
_dbus_string_get_length (&contained_str));
if (contained_signature_validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
return FALSE;
}
else
{
/* just some placeholder value */
contained_signature_validity = DBUS_VALID_BUT_INCOMPLETE;
}
_dbus_return_val_if_fail ((type == DBUS_TYPE_ARRAY && contained_signature && *contained_signature == DBUS_DICT_ENTRY_BEGIN_CHAR) ||
contained_signature == NULL ||
contained_signature_validity == DBUS_VALID,
FALSE);
if (!_dbus_message_iter_open_signature (real))
return FALSE;
ret = FALSE;
*real_sub = *real;
if (contained_signature != NULL)
{
_dbus_string_init_const (&contained_str, contained_signature);
ret = _dbus_type_writer_recurse (&real->u.writer,
type,
&contained_str, 0,
&real_sub->u.writer);
}
else
{
ret = _dbus_type_writer_recurse (&real->u.writer,
type,
NULL, 0,
&real_sub->u.writer);
}
if (!ret)
_dbus_message_iter_abandon_signature (real);
return ret;
}
dbus_bool_t
dbus_message_iter_close_container (DBusMessageIter *iter,
DBusMessageIter *sub)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
dbus_bool_t ret;
_dbus_return_val_if_fail (_dbus_message_iter_append_check (real), FALSE);
_dbus_return_val_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
_dbus_return_val_if_fail (_dbus_message_iter_append_check (real_sub), FALSE);
_dbus_return_val_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER, FALSE);
ret = _dbus_type_writer_unrecurse (&real->u.writer,
&real_sub->u.writer);
_dbus_message_real_iter_zero (real_sub);
if (!_dbus_message_iter_close_signature (real))
ret = FALSE;
return ret;
}
void
dbus_message_iter_abandon_container (DBusMessageIter *iter,
DBusMessageIter *sub)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
#ifndef DBUS_DISABLE_CHECKS
_dbus_return_if_fail (_dbus_message_iter_append_check (real));
_dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
_dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
_dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
#endif
_dbus_message_iter_abandon_signature (real);
_dbus_message_real_iter_zero (real_sub);
}
void
dbus_message_iter_abandon_container_if_open (DBusMessageIter *iter,
DBusMessageIter *sub)
{
DBusMessageRealIter *real = (DBusMessageRealIter *)iter;
DBusMessageRealIter *real_sub = (DBusMessageRealIter *)sub;
/* If both the parent and the child are zeroed out, then either we didn't
* even get as far as successfully recursing into the parent, or we already
* closed both the child and the parent. For example, in the code sample
* in the doc-comment above, this happens for
* abandon_container_if_open (&outer, &inner) if the first open_container
* call failed, or if we reached result = TRUE and fell through. */
if (_dbus_message_real_iter_is_zeroed (real) &&
_dbus_message_real_iter_is_zeroed (real_sub))
return;
#ifndef DBUS_DISABLE_CHECKS
/* If the child is not zeroed out, but the parent is, then something has
* gone horribly wrong (in practice that would probably mean both are
* uninitialized or corrupt, and the parent happens to have ended up
* all-bytes-zero). */
_dbus_return_if_fail (_dbus_message_iter_append_check (real));
_dbus_return_if_fail (real->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
#endif
/* If the parent is not zeroed out, but the child is, then either we did
* not successfully open the child, or we already closed the child. This
* means we do not own a reference to the parent's signature, so it would
* be wrong to release it; so we must not call abandon_signature() here.
* In the code sample in the doc-comment above, this happens for
* abandon_container_if_open (&outer, &inner) if the second open_container
* call failed, or if the second close_container call failed. */
if (_dbus_message_real_iter_is_zeroed (real_sub))
return;
#ifndef DBUS_DISABLE_CHECKS
_dbus_return_if_fail (_dbus_message_iter_append_check (real_sub));
_dbus_return_if_fail (real_sub->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
#endif
/* If neither the parent nor the child is zeroed out, then we genuinely
* have an open container; close it. In the code sample in the doc-comment,
* this happens for abandon_container_if_open (&outer, &inner) if the
* append_basic call failed. */
_dbus_message_iter_abandon_signature (real);
_dbus_message_real_iter_zero (real_sub);
}
void
dbus_message_set_no_reply (DBusMessage *message,
dbus_bool_t no_reply)
{
_dbus_return_if_fail (message != NULL);
_dbus_return_if_fail (!message->locked);
_dbus_header_toggle_flag (&message->header,
DBUS_HEADER_FLAG_NO_REPLY_EXPECTED,
no_reply);
}
dbus_bool_t
dbus_message_get_no_reply (DBusMessage *message)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
return _dbus_header_get_flag (&message->header,
DBUS_HEADER_FLAG_NO_REPLY_EXPECTED);
}
void
dbus_message_set_auto_start (DBusMessage *message,
dbus_bool_t auto_start)
{
_dbus_return_if_fail (message != NULL);
_dbus_return_if_fail (!message->locked);
_dbus_header_toggle_flag (&message->header,
DBUS_HEADER_FLAG_NO_AUTO_START,
!auto_start);
}
dbus_bool_t
dbus_message_get_auto_start (DBusMessage *message)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
return !_dbus_header_get_flag (&message->header,
DBUS_HEADER_FLAG_NO_AUTO_START);
}
dbus_bool_t
dbus_message_set_path (DBusMessage *message,
const char *object_path)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (!message->locked, FALSE);
_dbus_return_val_if_fail (object_path == NULL ||
_dbus_check_is_valid_path (object_path),
FALSE);
return set_or_delete_string_field (message,
DBUS_HEADER_FIELD_PATH,
DBUS_TYPE_OBJECT_PATH,
object_path);
}
const char*
dbus_message_get_path (DBusMessage *message)
{
const char *v;
_dbus_return_val_if_fail (message != NULL, NULL);
v = NULL; /* in case field doesn't exist */
_dbus_header_get_field_basic (&message->header,
DBUS_HEADER_FIELD_PATH,
DBUS_TYPE_OBJECT_PATH,
(void *) &v);
return v;
}
dbus_bool_t
dbus_message_has_path (DBusMessage *message,
const char *path)
{
const char *msg_path;
msg_path = dbus_message_get_path (message);
if (msg_path == NULL)
{
if (path == NULL)
return TRUE;
else
return FALSE;
}
if (path == NULL)
return FALSE;
if (strcmp (msg_path, path) == 0)
return TRUE;
return FALSE;
}
dbus_bool_t
dbus_message_get_path_decomposed (DBusMessage *message,
char ***path)
{
const char *v;
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (path != NULL, FALSE);
*path = NULL;
v = dbus_message_get_path (message);
if (v != NULL)
{
if (!_dbus_decompose_path (v, strlen (v),
path, NULL))
return FALSE;
}
return TRUE;
}
dbus_bool_t
dbus_message_set_interface (DBusMessage *message,
const char *iface)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (!message->locked, FALSE);
_dbus_return_val_if_fail (iface == NULL ||
_dbus_check_is_valid_interface (iface),
FALSE);
return set_or_delete_string_field (message,
DBUS_HEADER_FIELD_INTERFACE,
DBUS_TYPE_STRING,
iface);
}
const char*
dbus_message_get_interface (DBusMessage *message)
{
const char *v;
_dbus_return_val_if_fail (message != NULL, NULL);
v = NULL; /* in case field doesn't exist */
_dbus_header_get_field_basic (&message->header,
DBUS_HEADER_FIELD_INTERFACE,
DBUS_TYPE_STRING,
(void *) &v);
return v;
}
dbus_bool_t
dbus_message_has_interface (DBusMessage *message,
const char *iface)
{
const char *msg_interface;
msg_interface = dbus_message_get_interface (message);
if (msg_interface == NULL)
{
if (iface == NULL)
return TRUE;
else
return FALSE;
}
if (iface == NULL)
return FALSE;
if (strcmp (msg_interface, iface) == 0)
return TRUE;
return FALSE;
}
dbus_bool_t
dbus_message_set_member (DBusMessage *message,
const char *member)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (!message->locked, FALSE);
_dbus_return_val_if_fail (member == NULL ||
_dbus_check_is_valid_member (member),
FALSE);
return set_or_delete_string_field (message,
DBUS_HEADER_FIELD_MEMBER,
DBUS_TYPE_STRING,
member);
}
const char*
dbus_message_get_member (DBusMessage *message)
{
const char *v;
_dbus_return_val_if_fail (message != NULL, NULL);
v = NULL; /* in case field doesn't exist */
_dbus_header_get_field_basic (&message->header,
DBUS_HEADER_FIELD_MEMBER,
DBUS_TYPE_STRING,
(void *) &v);
return v;
}
dbus_bool_t
dbus_message_has_member (DBusMessage *message,
const char *member)
{
const char *msg_member;
msg_member = dbus_message_get_member (message);
if (msg_member == NULL)
{
if (member == NULL)
return TRUE;
else
return FALSE;
}
if (member == NULL)
return FALSE;
if (strcmp (msg_member, member) == 0)
return TRUE;
return FALSE;
}
dbus_bool_t
dbus_message_set_error_name (DBusMessage *message,
const char *error_name)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (!message->locked, FALSE);
_dbus_return_val_if_fail (error_name == NULL ||
_dbus_check_is_valid_error_name (error_name),
FALSE);
return set_or_delete_string_field (message,
DBUS_HEADER_FIELD_ERROR_NAME,
DBUS_TYPE_STRING,
error_name);
}
const char*
dbus_message_get_error_name (DBusMessage *message)
{
const char *v;
_dbus_return_val_if_fail (message != NULL, NULL);
v = NULL; /* in case field doesn't exist */
_dbus_header_get_field_basic (&message->header,
DBUS_HEADER_FIELD_ERROR_NAME,
DBUS_TYPE_STRING,
(void *) &v);
return v;
}
dbus_bool_t
dbus_message_set_destination (DBusMessage *message,
const char *destination)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (!message->locked, FALSE);
_dbus_return_val_if_fail (destination == NULL ||
_dbus_check_is_valid_bus_name (destination),
FALSE);
return set_or_delete_string_field (message,
DBUS_HEADER_FIELD_DESTINATION,
DBUS_TYPE_STRING,
destination);
}
const char*
dbus_message_get_destination (DBusMessage *message)
{
const char *v;
_dbus_return_val_if_fail (message != NULL, NULL);
v = NULL; /* in case field doesn't exist */
_dbus_header_get_field_basic (&message->header,
DBUS_HEADER_FIELD_DESTINATION,
DBUS_TYPE_STRING,
(void *) &v);
return v;
}
dbus_bool_t
dbus_message_set_sender (DBusMessage *message,
const char *sender)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (!message->locked, FALSE);
_dbus_return_val_if_fail (sender == NULL ||
_dbus_check_is_valid_bus_name (sender),
FALSE);
return set_or_delete_string_field (message,
DBUS_HEADER_FIELD_SENDER,
DBUS_TYPE_STRING,
sender);
}
const char*
dbus_message_get_sender (DBusMessage *message)
{
const char *v;
_dbus_return_val_if_fail (message != NULL, NULL);
v = NULL; /* in case field doesn't exist */
_dbus_header_get_field_basic (&message->header,
DBUS_HEADER_FIELD_SENDER,
DBUS_TYPE_STRING,
(void *) &v);
return v;
}
const char*
dbus_message_get_signature (DBusMessage *message)
{
const DBusString *type_str;
int type_pos;
_dbus_return_val_if_fail (message != NULL, NULL);
get_const_signature (&message->header, &type_str, &type_pos);
return _dbus_string_get_const_data_len (type_str, type_pos, 0);
}
static dbus_bool_t
_dbus_message_has_type_interface_member (DBusMessage *message,
int type,
const char *iface,
const char *member)
{
const char *n;
_dbus_assert (message != NULL);
_dbus_assert (iface != NULL);
_dbus_assert (member != NULL);
if (dbus_message_get_type (message) != type)
return FALSE;
/* Optimize by checking the short member name first
* instead of the longer interface name
*/
n = dbus_message_get_member (message);
if (n && strcmp (n, member) == 0)
{
n = dbus_message_get_interface (message);
if (n == NULL || strcmp (n, iface) == 0)
return TRUE;
}
return FALSE;
}
dbus_bool_t
dbus_message_is_method_call (DBusMessage *message,
const char *iface,
const char *method)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (iface != NULL, FALSE);
_dbus_return_val_if_fail (method != NULL, FALSE);
/* don't check that interface/method are valid since it would be
* expensive, and not catch many common errors
*/
return _dbus_message_has_type_interface_member (message,
DBUS_MESSAGE_TYPE_METHOD_CALL,
iface, method);
}
dbus_bool_t
dbus_message_is_signal (DBusMessage *message,
const char *iface,
const char *signal_name)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (iface != NULL, FALSE);
_dbus_return_val_if_fail (signal_name != NULL, FALSE);
/* don't check that interface/name are valid since it would be
* expensive, and not catch many common errors
*/
return _dbus_message_has_type_interface_member (message,
DBUS_MESSAGE_TYPE_SIGNAL,
iface, signal_name);
}
dbus_bool_t
dbus_message_is_error (DBusMessage *message,
const char *error_name)
{
const char *n;
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (error_name != NULL, FALSE);
/* don't check that error_name is valid since it would be expensive,
* and not catch many common errors
*/
if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
return FALSE;
n = dbus_message_get_error_name (message);
if (n && strcmp (n, error_name) == 0)
return TRUE;
else
return FALSE;
}
dbus_bool_t
dbus_message_has_destination (DBusMessage *message,
const char *name)
{
const char *s;
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (name != NULL, FALSE);
/* don't check that name is valid since it would be expensive, and
* not catch many common errors
*/
s = dbus_message_get_destination (message);
if (s && strcmp (s, name) == 0)
return TRUE;
else
return FALSE;
}
dbus_bool_t
dbus_message_has_sender (DBusMessage *message,
const char *name)
{
const char *s;
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (name != NULL, FALSE);
/* don't check that name is valid since it would be expensive, and
* not catch many common errors
*/
s = dbus_message_get_sender (message);
if (s && strcmp (s, name) == 0)
return TRUE;
else
return FALSE;
}
dbus_bool_t
dbus_message_has_signature (DBusMessage *message,
const char *signature)
{
const char *s;
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (signature != NULL, FALSE);
/* don't check that signature is valid since it would be expensive,
* and not catch many common errors
*/
s = dbus_message_get_signature (message);
if (s && strcmp (s, signature) == 0)
return TRUE;
else
return FALSE;
}
dbus_bool_t
dbus_set_error_from_message (DBusError *error,
DBusMessage *message)
{
const char *str;
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_error_is_set (error, FALSE);
if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_ERROR)
return FALSE;
str = NULL;
dbus_message_get_args (message, NULL,
DBUS_TYPE_STRING, &str,
DBUS_TYPE_INVALID);
dbus_set_error (error, dbus_message_get_error_name (message),
str ? "%s" : NULL, str);
return TRUE;
}
dbus_bool_t
dbus_message_contains_unix_fds(DBusMessage *message)
{
#ifdef HAVE_UNIX_FD_PASSING
_dbus_assert(message);
return message->n_unix_fds > 0;
#else
return FALSE;
#endif
}
dbus_bool_t
dbus_message_set_container_instance (DBusMessage *message,
const char *object_path)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (!message->locked, FALSE);
_dbus_return_val_if_fail (object_path == NULL ||
_dbus_check_is_valid_path (object_path),
FALSE);
return set_or_delete_string_field (message,
DBUS_HEADER_FIELD_CONTAINER_INSTANCE,
DBUS_TYPE_OBJECT_PATH,
object_path);
}
const char *
dbus_message_get_container_instance (DBusMessage *message)
{
const char *v;
_dbus_return_val_if_fail (message != NULL, NULL);
v = NULL; /* in case field doesn't exist */
_dbus_header_get_field_basic (&message->header,
DBUS_HEADER_FIELD_CONTAINER_INSTANCE,
DBUS_TYPE_OBJECT_PATH,
(void *) &v);
return v;
}
#define INITIAL_LOADER_DATA_LEN 32
DBusMessageLoader*
_dbus_message_loader_new (void)
{
DBusMessageLoader *loader;
loader = dbus_new0 (DBusMessageLoader, 1);
if (loader == NULL)
return NULL;
loader->refcount = 1;
loader->corrupted = FALSE;
loader->corruption_reason = DBUS_VALID;
/* this can be configured by the app, but defaults to the protocol max */
loader->max_message_size = DBUS_MAXIMUM_MESSAGE_LENGTH;
/* We set a very relatively conservative default here since due to how
SCM_RIGHTS works we need to preallocate an fd array of the maximum
number of unix fds we want to receive in advance. A
try-and-reallocate loop is not possible. */
loader->max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
if (!_dbus_string_init (&loader->data))
{
dbus_free (loader);
return NULL;
}
/* preallocate the buffer for speed, ignore failure */
_dbus_string_set_length (&loader->data, INITIAL_LOADER_DATA_LEN);
_dbus_string_set_length (&loader->data, 0);
#ifdef HAVE_UNIX_FD_PASSING
loader->unix_fds = NULL;
loader->n_unix_fds = loader->n_unix_fds_allocated = 0;
loader->unix_fds_outstanding = FALSE;
#endif
return loader;
}
DBusMessageLoader *
_dbus_message_loader_ref (DBusMessageLoader *loader)
{
loader->refcount += 1;
return loader;
}
void
_dbus_message_loader_unref (DBusMessageLoader *loader)
{
loader->refcount -= 1;
if (loader->refcount == 0)
{
#ifdef HAVE_UNIX_FD_PASSING
close_unix_fds(loader->unix_fds, &loader->n_unix_fds);
dbus_free(loader->unix_fds);
#endif
_dbus_list_clear_full (&loader->messages,
(DBusFreeFunction) dbus_message_unref);
_dbus_string_free (&loader->data);
dbus_free (loader);
}
}
void
_dbus_message_loader_get_buffer (DBusMessageLoader *loader,
DBusString **buffer,
int *max_to_read,
dbus_bool_t *may_read_fds)
{
_dbus_assert (!loader->buffer_outstanding);
*buffer = &loader->data;
loader->buffer_outstanding = TRUE;
if (max_to_read != NULL)
{
#ifdef HAVE_UNIX_FD_PASSING
int offset = 0;
int remain;
int byte_order;
int fields_array_len;
int header_len;
int body_len;
#endif
*max_to_read = DBUS_MAXIMUM_MESSAGE_LENGTH;
*may_read_fds = TRUE;
#ifdef HAVE_UNIX_FD_PASSING
/* If we aren't holding onto any fds, we can read as much as we want
* (fast path). */
if (loader->n_unix_fds == 0)
return;
/* Slow path: we have a message with some fds in it. We don't want
* to start on the next message until this one is out of the way;
* otherwise a legitimate sender can keep us processing messages
* containing fds, until we disconnect it for having had fds pending
* for too long, a limit that is in place to stop malicious senders
* from setting up recursive fd-passing that takes up our quota and
* will never go away. */
remain = _dbus_string_get_length (&loader->data);
while (remain > 0)
{
DBusValidity validity = DBUS_VALIDITY_UNKNOWN;
int needed;
/* If 0 < remain < DBUS_MINIMUM_HEADER_SIZE, then we've had at
* least the first byte of a message, but we don't know how
* much more to read. Only read the rest of the
* DBUS_MINIMUM_HEADER_SIZE for now; then we'll know. */
if (remain < DBUS_MINIMUM_HEADER_SIZE)
{
*max_to_read = DBUS_MINIMUM_HEADER_SIZE - remain;
*may_read_fds = FALSE;
return;
}
if (!_dbus_header_have_message_untrusted (loader->max_message_size,
&validity,
&byte_order,
&fields_array_len,
&header_len,
&body_len,
&loader->data,
offset,
remain))
{
/* If a message in the buffer is invalid, we're going to
* disconnect the sender anyway, so reading an arbitrary amount
* is fine. */
if (validity != DBUS_VALID)
return;
/* We have a partial message, with the
* DBUS_MINIMUM_HEADER_SIZE-byte fixed part of the header (which
* lets us work out how much more we need), but no more. Read
* the rest of the message. */
needed = header_len + body_len;
_dbus_assert (needed > remain);
*max_to_read = needed - remain;
*may_read_fds = FALSE;
return;
}
/* Skip over entire messages until we have less than a message
* remaining. */
needed = header_len + body_len;
_dbus_assert (needed > DBUS_MINIMUM_HEADER_SIZE);
_dbus_assert (remain >= needed);
remain -= needed;
offset += needed;
}
#endif
}
}
void
_dbus_message_loader_return_buffer (DBusMessageLoader *loader,
DBusString *buffer)
{
_dbus_assert (loader->buffer_outstanding);
_dbus_assert (buffer == &loader->data);
loader->buffer_outstanding = FALSE;
}
#ifdef HAVE_UNIX_FD_PASSING
dbus_bool_t
_dbus_message_loader_get_unix_fds(DBusMessageLoader *loader,
int **fds,
unsigned *max_n_fds)
{
_dbus_assert (!loader->unix_fds_outstanding);
/* Allocate space where we can put the fds we read. We allocate
space for max_message_unix_fds since this is an
upper limit how many fds can be received within a single
message. Since SCM_RIGHTS doesn't allow a reallocate+retry logic
we are allocating the maximum possible array size right from the
beginning. This sucks a bit, however unless SCM_RIGHTS is fixed
there is no better way. */
if (loader->n_unix_fds_allocated < loader->max_message_unix_fds)
{
int *a = dbus_realloc(loader->unix_fds,
loader->max_message_unix_fds * sizeof(loader->unix_fds[0]));
if (!a)
return FALSE;
loader->unix_fds = a;
loader->n_unix_fds_allocated = loader->max_message_unix_fds;
}
*fds = loader->unix_fds + loader->n_unix_fds;
*max_n_fds = loader->n_unix_fds_allocated - loader->n_unix_fds;
loader->unix_fds_outstanding = TRUE;
return TRUE;
}
void
_dbus_message_loader_return_unix_fds(DBusMessageLoader *loader,
int *fds,
unsigned n_fds)
{
_dbus_assert(loader->unix_fds_outstanding);
_dbus_assert(loader->unix_fds + loader->n_unix_fds == fds);
_dbus_assert(loader->n_unix_fds + n_fds <= loader->n_unix_fds_allocated);
loader->n_unix_fds += n_fds;
loader->unix_fds_outstanding = FALSE;
if (n_fds && loader->unix_fds_change)
loader->unix_fds_change (loader->unix_fds_change_data);
}
#endif
/*
* FIXME when we move the header out of the buffer, that memmoves all
* buffered messages. Kind of crappy.
*
* Also we copy the header and body, which is kind of crappy. To
* avoid this, we have to allow header and body to be in a single
* memory block, which is good for messages we read and bad for
* messages we are creating. But we could move_len() the buffer into
* this single memory block, and move_len() will just swap the buffers
* if you're moving the entire buffer replacing the dest string.
*
* We could also have the message loader tell the transport how many
* bytes to read; so it would first ask for some arbitrary number like
* 256, then if the message was incomplete it would use the
* header/body len to ask for exactly the size of the message (or
* blocks the size of a typical kernel buffer for the socket). That
* way we don't get trailing bytes in the buffer that have to be
* memmoved. Though I suppose we also don't have a chance of reading a
* bunch of small messages at once, so the optimization may be stupid.
*
* Another approach would be to keep a "start" index into
* loader->data and only delete it occasionally, instead of after
* each message is loaded.
*
* load_message() returns FALSE if not enough memory OR the loader was corrupted
*/
static dbus_bool_t
load_message (DBusMessageLoader *loader,
DBusMessage *message,
int byte_order,
int fields_array_len,
int header_len,
int body_len)
{
dbus_bool_t oom;
DBusValidity validity;
const DBusString *type_str;
int type_pos;
DBusValidationMode mode;
dbus_uint32_t n_unix_fds = 0;
mode = DBUS_VALIDATION_MODE_DATA_IS_UNTRUSTED;
oom = FALSE;
#if 0
_dbus_verbose_bytes_of_string (&loader->data, 0, header_len /* + body_len */);
#endif
/* 1. VALIDATE AND COPY OVER HEADER */
_dbus_assert (_dbus_string_get_length (&message->header.data) == 0);
_dbus_assert ((header_len + body_len) <= _dbus_string_get_length (&loader->data));
if (!_dbus_header_load (&message->header,
mode,
&validity,
byte_order,
fields_array_len,
header_len,
body_len,
&loader->data))
{
_dbus_verbose ("Failed to load header for new message code %d\n", validity);
/* assert here so we can catch any code that still uses DBUS_VALID to indicate
oom errors. They should use DBUS_VALIDITY_UNKNOWN_OOM_ERROR instead */
_dbus_assert (validity != DBUS_VALID);
if (validity == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
oom = TRUE;
else
{
loader->corrupted = TRUE;
loader->corruption_reason = validity;
}
goto failed;
}
_dbus_assert (validity == DBUS_VALID);
/* 2. VALIDATE BODY */
if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
{
get_const_signature (&message->header, &type_str, &type_pos);
/* Because the bytes_remaining arg is NULL, this validates that the
* body is the right length
*/
validity = _dbus_validate_body_with_reason (type_str,
type_pos,
byte_order,
NULL,
&loader->data,
header_len,
body_len);
if (validity != DBUS_VALID)
{
_dbus_verbose ("Failed to validate message body code %d\n", validity);
loader->corrupted = TRUE;
loader->corruption_reason = validity;
goto failed;
}
}
/* 3. COPY OVER UNIX FDS */
_dbus_header_get_field_basic(&message->header,
DBUS_HEADER_FIELD_UNIX_FDS,
DBUS_TYPE_UINT32,
&n_unix_fds);
#ifdef HAVE_UNIX_FD_PASSING
if (n_unix_fds > loader->n_unix_fds)
{
_dbus_verbose("Message contains references to more unix fds than were sent %u != %u\n",
n_unix_fds, loader->n_unix_fds);
loader->corrupted = TRUE;
loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
goto failed;
}
/* If this was a recycled message there might still be
some memory allocated for the fds */
dbus_free(message->unix_fds);
if (n_unix_fds > 0)
{
message->unix_fds = _dbus_memdup(loader->unix_fds, n_unix_fds * sizeof(message->unix_fds[0]));
if (message->unix_fds == NULL)
{
_dbus_verbose ("Failed to allocate file descriptor array\n");
oom = TRUE;
goto failed;
}
message->n_unix_fds_allocated = message->n_unix_fds = n_unix_fds;
loader->n_unix_fds -= n_unix_fds;
memmove (loader->unix_fds, loader->unix_fds + n_unix_fds, loader->n_unix_fds * sizeof (loader->unix_fds[0]));
if (loader->unix_fds_change)
loader->unix_fds_change (loader->unix_fds_change_data);
}
else
message->unix_fds = NULL;
#else
if (n_unix_fds > 0)
{
_dbus_verbose ("Hmm, message claims to come with file descriptors "
"but that's not supported on our platform, disconnecting.\n");
loader->corrupted = TRUE;
loader->corruption_reason = DBUS_INVALID_MISSING_UNIX_FDS;
goto failed;
}
#endif
/* 3. COPY OVER BODY AND QUEUE MESSAGE */
if (!_dbus_list_append (&loader->messages, message))
{
_dbus_verbose ("Failed to append new message to loader queue\n");
oom = TRUE;
goto failed;
}
_dbus_assert (_dbus_string_get_length (&message->body) == 0);
_dbus_assert (_dbus_string_get_length (&loader->data) >=
(header_len + body_len));
if (!_dbus_string_copy_len (&loader->data, header_len, body_len, &message->body, 0))
{
_dbus_verbose ("Failed to move body into new message\n");
oom = TRUE;
goto failed;
}
_dbus_string_delete (&loader->data, 0, header_len + body_len);
/* don't waste more than 2k of memory */
_dbus_string_compact (&loader->data, 2048);
_dbus_assert (_dbus_string_get_length (&message->header.data) == header_len);
_dbus_assert (_dbus_string_get_length (&message->body) == body_len);
_dbus_verbose ("Loaded message %p\n", message);
_dbus_assert (!oom);
_dbus_assert (!loader->corrupted);
_dbus_assert (loader->messages != NULL);
_dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
return TRUE;
failed:
/* Clean up */
/* does nothing if the message isn't in the list */
_dbus_list_remove_last (&loader->messages, message);
if (oom)
_dbus_assert (!loader->corrupted);
else
_dbus_assert (loader->corrupted);
_dbus_verbose_bytes_of_string (&loader->data, 0, _dbus_string_get_length (&loader->data));
return FALSE;
}
dbus_bool_t
_dbus_message_loader_queue_messages (DBusMessageLoader *loader)
{
while (!loader->corrupted &&
_dbus_string_get_length (&loader->data) >= DBUS_MINIMUM_HEADER_SIZE)
{
DBusValidity validity;
int byte_order, fields_array_len, header_len, body_len;
if (_dbus_header_have_message_untrusted (loader->max_message_size,
&validity,
&byte_order,
&fields_array_len,
&header_len,
&body_len,
&loader->data, 0,
_dbus_string_get_length (&loader->data)))
{
DBusMessage *message;
_dbus_assert (validity == DBUS_VALID);
message = dbus_message_new_empty_header ();
if (message == NULL)
return FALSE;
if (!load_message (loader, message,
byte_order, fields_array_len,
header_len, body_len))
{
dbus_message_unref (message);
/* load_message() returns false if corrupted or OOM; if
* corrupted then return TRUE for not OOM
*/
return loader->corrupted;
}
_dbus_assert (loader->messages != NULL);
_dbus_assert (_dbus_list_find_last (&loader->messages, message) != NULL);
}
else
{
_dbus_verbose ("Initial peek at header says we don't have a whole message yet, or data broken with invalid code %d\n",
validity);
if (validity != DBUS_VALID)
{
loader->corrupted = TRUE;
loader->corruption_reason = validity;
}
return TRUE;
}
}
return TRUE;
}
DBusMessage*
_dbus_message_loader_peek_message (DBusMessageLoader *loader)
{
if (loader->messages)
return loader->messages->data;
else
return NULL;
}
DBusMessage*
_dbus_message_loader_pop_message (DBusMessageLoader *loader)
{
return _dbus_list_pop_first (&loader->messages);
}
DBusList*
_dbus_message_loader_pop_message_link (DBusMessageLoader *loader)
{
return _dbus_list_pop_first_link (&loader->messages);
}
void
_dbus_message_loader_putback_message_link (DBusMessageLoader *loader,
DBusList *link)
{
_dbus_list_prepend_link (&loader->messages, link);
}
dbus_bool_t
_dbus_message_loader_get_is_corrupted (DBusMessageLoader *loader)
{
_dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
(!loader->corrupted && loader->corruption_reason == DBUS_VALID));
return loader->corrupted;
}
DBusValidity
_dbus_message_loader_get_corruption_reason (DBusMessageLoader *loader)
{
_dbus_assert ((loader->corrupted && loader->corruption_reason != DBUS_VALID) ||
(!loader->corrupted && loader->corruption_reason == DBUS_VALID));
return loader->corruption_reason;
}
void
_dbus_message_loader_set_max_message_size (DBusMessageLoader *loader,
long size)
{
if (size > DBUS_MAXIMUM_MESSAGE_LENGTH)
{
_dbus_verbose ("clamping requested max message size %ld to %d\n",
size, DBUS_MAXIMUM_MESSAGE_LENGTH);
size = DBUS_MAXIMUM_MESSAGE_LENGTH;
}
loader->max_message_size = size;
}
long
_dbus_message_loader_get_max_message_size (DBusMessageLoader *loader)
{
return loader->max_message_size;
}
void
_dbus_message_loader_set_max_message_unix_fds (DBusMessageLoader *loader,
long n)
{
if (n > DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
{
_dbus_verbose ("clamping requested max message unix_fds %ld to %d\n",
n, DBUS_MAXIMUM_MESSAGE_UNIX_FDS);
n = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
}
loader->max_message_unix_fds = n;
}
long
_dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader)
{
return loader->max_message_unix_fds;
}
int
_dbus_message_loader_get_pending_fds_count (DBusMessageLoader *loader)
{
#ifdef HAVE_UNIX_FD_PASSING
return loader->n_unix_fds;
#else
return 0;
#endif
}
void
_dbus_message_loader_set_pending_fds_function (DBusMessageLoader *loader,
void (* callback) (void *),
void *data)
{
#ifdef HAVE_UNIX_FD_PASSING
loader->unix_fds_change = callback;
loader->unix_fds_change_data = data;
#endif
}
static DBusDataSlotAllocator slot_allocator =
_DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots));
dbus_bool_t
dbus_message_allocate_data_slot (dbus_int32_t *slot_p)
{
return _dbus_data_slot_allocator_alloc (&slot_allocator,
slot_p);
}
void
dbus_message_free_data_slot (dbus_int32_t *slot_p)
{
_dbus_return_if_fail (*slot_p >= 0);
_dbus_data_slot_allocator_free (&slot_allocator, slot_p);
}
dbus_bool_t
dbus_message_set_data (DBusMessage *message,
dbus_int32_t slot,
void *data,
DBusFreeFunction free_data_func)
{
DBusFreeFunction old_free_func;
void *old_data;
dbus_bool_t retval;
_dbus_return_val_if_fail (message != NULL, FALSE);
_dbus_return_val_if_fail (slot >= 0, FALSE);
retval = _dbus_data_slot_list_set (&slot_allocator,
&message->slot_list,
slot, data, free_data_func,
&old_free_func, &old_data);
if (retval)
{
/* Do the actual free outside the message lock */
if (old_free_func)
(* old_free_func) (old_data);
}
return retval;
}
void*
dbus_message_get_data (DBusMessage *message,
dbus_int32_t slot)
{
void *res;
_dbus_return_val_if_fail (message != NULL, NULL);
res = _dbus_data_slot_list_get (&slot_allocator,
&message->slot_list,
slot);
return res;
}
int
dbus_message_type_from_string (const char *type_str)
{
if (strcmp (type_str, "method_call") == 0)
return DBUS_MESSAGE_TYPE_METHOD_CALL;
if (strcmp (type_str, "method_return") == 0)
return DBUS_MESSAGE_TYPE_METHOD_RETURN;
else if (strcmp (type_str, "signal") == 0)
return DBUS_MESSAGE_TYPE_SIGNAL;
else if (strcmp (type_str, "error") == 0)
return DBUS_MESSAGE_TYPE_ERROR;
else
return DBUS_MESSAGE_TYPE_INVALID;
}
const char *
dbus_message_type_to_string (int type)
{
switch (type)
{
case DBUS_MESSAGE_TYPE_METHOD_CALL:
return "method_call";
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
return "method_return";
case DBUS_MESSAGE_TYPE_SIGNAL:
return "signal";
case DBUS_MESSAGE_TYPE_ERROR:
return "error";
default:
return "invalid";
}
}
dbus_bool_t
dbus_message_marshal (DBusMessage *msg,
char **marshalled_data_p,
int *len_p)
{
DBusString tmp;
dbus_bool_t was_locked;
_dbus_return_val_if_fail (msg != NULL, FALSE);
_dbus_return_val_if_fail (marshalled_data_p != NULL, FALSE);
_dbus_return_val_if_fail (len_p != NULL, FALSE);
if (!_dbus_string_init (&tmp))
return FALSE;
/* Ensure the message is locked, to ensure the length header is filled in. */
was_locked = msg->locked;
if (!was_locked)
dbus_message_lock (msg);
if (!_dbus_string_copy (&(msg->header.data), 0, &tmp, 0))
goto fail;
*len_p = _dbus_string_get_length (&tmp);
if (!_dbus_string_copy (&(msg->body), 0, &tmp, *len_p))
goto fail;
*len_p = _dbus_string_get_length (&tmp);
if (!_dbus_string_steal_data (&tmp, marshalled_data_p))
goto fail;
_dbus_string_free (&tmp);
if (!was_locked)
msg->locked = FALSE;
return TRUE;
fail:
_dbus_string_free (&tmp);
if (!was_locked)
msg->locked = FALSE;
return FALSE;
}
DBusMessage *
dbus_message_demarshal (const char *str,
int len,
DBusError *error)
{
DBusMessageLoader *loader = NULL;
DBusString *buffer;
DBusMessage *msg;
_dbus_return_val_if_fail (str != NULL, NULL);
loader = _dbus_message_loader_new ();
if (loader == NULL)
goto fail_oom;
_dbus_message_loader_get_buffer (loader, &buffer, NULL, NULL);
if (!_dbus_string_append_len (buffer, str, len))
goto fail_oom;
_dbus_message_loader_return_buffer (loader, buffer);
if (!_dbus_message_loader_queue_messages (loader))
goto fail_oom;
if (_dbus_message_loader_get_is_corrupted (loader))
goto fail_corrupt;
msg = _dbus_message_loader_pop_message (loader);
if (!msg)
goto fail_oom;
_dbus_message_loader_unref (loader);
return msg;
fail_corrupt:
if (loader->corruption_reason == DBUS_VALIDITY_UNKNOWN_OOM_ERROR)
goto fail_oom;
dbus_set_error (error, DBUS_ERROR_INVALID_ARGS, "Message is corrupted (%s)",
_dbus_validity_to_error_message (loader->corruption_reason));
_dbus_message_loader_unref (loader);
return NULL;
fail_oom:
_DBUS_SET_OOM (error);
if (loader != NULL)
_dbus_message_loader_unref (loader);
return NULL;
}
int
dbus_message_demarshal_bytes_needed(const char *buf,
int len)
{
DBusString str;
int byte_order, fields_array_len, header_len, body_len;
DBusValidity validity = DBUS_VALID;
int have_message;
if (!buf || len < DBUS_MINIMUM_HEADER_SIZE)
return 0;
if (len > DBUS_MAXIMUM_MESSAGE_LENGTH)
len = DBUS_MAXIMUM_MESSAGE_LENGTH;
_dbus_string_init_const_len (&str, buf, len);
validity = DBUS_VALID;
have_message
= _dbus_header_have_message_untrusted(DBUS_MAXIMUM_MESSAGE_LENGTH,
&validity, &byte_order,
&fields_array_len,
&header_len,
&body_len,
&str, 0,
len);
_dbus_string_free (&str);
if (validity == DBUS_VALID)
{
_dbus_assert (have_message || (header_len + body_len) > len);
(void) have_message; /* unused unless asserting */
return header_len + body_len;
}
else
{
return -1; /* broken! */
}
}
void
dbus_message_set_allow_interactive_authorization (DBusMessage *message,
dbus_bool_t allow)
{
_dbus_return_if_fail (message != NULL);
_dbus_return_if_fail (!message->locked);
_dbus_header_toggle_flag (&message->header,
DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION,
allow);
}
dbus_bool_t
dbus_message_get_allow_interactive_authorization (DBusMessage *message)
{
_dbus_return_val_if_fail (message != NULL, FALSE);
return _dbus_header_get_flag (&message->header,
DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION);
}
struct DBusVariant
{
DBusString data;
};
DBusVariant *
_dbus_variant_read (DBusMessageIter *reader)
{
DBusVariant *self = NULL;
/* Points to the single item we will read from the reader */
DBusMessageRealIter *real_reader = (DBusMessageRealIter *) reader;
/* The position in self at which we will write a single variant
* (it is position 0) */
DBusTypeWriter items_writer;
/* The position in self at which we will write a copy of reader
* (it is inside the variant) */
DBusTypeWriter variant_writer;
/* 'v' */
DBusString variant_signature;
/* Whatever is the signature of the item we will copy from the reader */
DBusString contained_signature;
/* TRUE if self->data needs to be freed */
dbus_bool_t data_inited = FALSE;
/* The type of the item we will read from the reader */
int type;
/* The string, start position within that string, and length of the signature
* of the single complete type of the item reader points to */
const DBusString *sig;
int start, len;
_dbus_assert (_dbus_message_iter_check (real_reader));
_dbus_assert (real_reader->iter_type == DBUS_MESSAGE_ITER_TYPE_READER);
_dbus_string_init_const (&variant_signature, DBUS_TYPE_VARIANT_AS_STRING);
type = dbus_message_iter_get_arg_type (reader);
_dbus_type_reader_get_signature (&real_reader->u.reader, &sig, &start, &len);
if (!_dbus_string_init (&contained_signature))
return NULL;
if (!_dbus_string_copy_len (sig, start, len, &contained_signature, 0))
goto oom;
self = dbus_new0 (DBusVariant, 1);
if (self == NULL)
goto oom;
if (!_dbus_string_init (&self->data))
goto oom;
data_inited = TRUE;
_dbus_type_writer_init_values_only (&items_writer, DBUS_COMPILER_BYTE_ORDER,
&variant_signature, 0, &self->data, 0);
if (!_dbus_type_writer_recurse (&items_writer, DBUS_TYPE_VARIANT,
&contained_signature, 0, &variant_writer))
goto oom;
if (type == DBUS_TYPE_ARRAY)
{
/* Points to each item in turn inside the array we are copying */
DBusMessageIter array_reader;
/* Same as array_reader */
DBusMessageRealIter *real_array_reader = (DBusMessageRealIter *) &array_reader;
/* The position inside the copied array at which we will write
* the copy of array_reader */
DBusTypeWriter array_writer;
dbus_message_iter_recurse (reader, &array_reader);
if (!_dbus_type_writer_recurse (&variant_writer, type,
&contained_signature, 1, &array_writer))
goto oom;
if (!_dbus_type_writer_write_reader (&array_writer,
&real_array_reader->u.reader))
goto oom;
if (!_dbus_type_writer_unrecurse (&variant_writer, &array_writer))
goto oom;
}
else if (type == DBUS_TYPE_DICT_ENTRY || type == DBUS_TYPE_VARIANT ||
type == DBUS_TYPE_STRUCT)
{
/* Points to each item in turn inside the container we are copying */
DBusMessageIter inner_reader;
/* Same as inner_reader */
DBusMessageRealIter *real_inner_reader = (DBusMessageRealIter *) &inner_reader;
/* The position inside the copied container at which we will write the
* copy of inner_reader */
DBusTypeWriter inner_writer;
dbus_message_iter_recurse (reader, &inner_reader);
if (!_dbus_type_writer_recurse (&variant_writer, type, NULL, 0,
&inner_writer))
goto oom;
if (!_dbus_type_writer_write_reader (&inner_writer,
&real_inner_reader->u.reader))
goto oom;
if (!_dbus_type_writer_unrecurse (&variant_writer, &inner_writer))
goto oom;
}
else
{
DBusBasicValue value;
/* We eliminated all the container types above */
_dbus_assert (dbus_type_is_basic (type));
dbus_message_iter_get_basic (reader, &value);
if (!_dbus_type_writer_write_basic (&variant_writer, type, &value))
goto oom;
}
_dbus_string_free (&contained_signature);
return self;
oom:
if (self != NULL)
{
if (data_inited)
_dbus_string_free (&self->data);
dbus_free (self);
}
_dbus_string_free (&contained_signature);
return NULL;
}
const char *
_dbus_variant_get_signature (DBusVariant *self)
{
const char *ret;
#ifndef DBUS_DISABLE_ASSERT
unsigned char len;
#endif
_dbus_assert (self != NULL);
#ifndef DBUS_DISABLE_ASSERT
/* Here we make use of the fact that the serialization of a variant starts
* with the 1-byte length, then that many bytes of signature, then \0. */
len = _dbus_string_get_byte (&self->data, 0);
#endif
ret = _dbus_string_get_const_data_len (&self->data, 1, len);
_dbus_assert (strlen (ret) == len);
return ret;
}
dbus_bool_t
_dbus_variant_write (DBusVariant *self,
DBusMessageIter *writer)
{
/* 'v' */
DBusString variant_signature;
/* Points to the single item in self */
DBusTypeReader variant_reader;
/* Points to the single item (of whatever type) inside the variant */
DBusTypeReader reader;
/* The position at which we will copy reader */
DBusMessageRealIter *real_writer = (DBusMessageRealIter *) writer;
dbus_bool_t ret;
_dbus_assert (self != NULL);
_dbus_assert (_dbus_message_iter_append_check (real_writer));
_dbus_assert (real_writer->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER);
_dbus_string_init_const (&variant_signature, DBUS_TYPE_VARIANT_AS_STRING);
_dbus_type_reader_init (&reader, DBUS_COMPILER_BYTE_ORDER,
&variant_signature, 0, &self->data, 0);
_dbus_type_reader_recurse (&reader, &variant_reader);
if (!_dbus_message_iter_open_signature (real_writer))
return FALSE;
ret = _dbus_type_writer_write_reader (&real_writer->u.writer,
&variant_reader);
if (!_dbus_message_iter_close_signature (real_writer))
return FALSE;
return ret;
}
int
_dbus_variant_get_length (DBusVariant *self)
{
_dbus_assert (self != NULL);
return _dbus_string_get_length (&self->data);
}
const DBusString *
_dbus_variant_peek (DBusVariant *self)
{
_dbus_assert (self != NULL);
return &self->data;
}
void
_dbus_variant_free (DBusVariant *self)
{
_dbus_assert (self != NULL);
_dbus_string_free (&self->data);
dbus_free (self);
}
/* tests in dbus-message-util.c */
_dbus_data_slot_allocator_free
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().
Definition dbus-dataslot.c:157
_dbus_data_slot_list_clear
void _dbus_data_slot_list_clear(DBusDataSlotList *list)
Frees all data slots contained in the list, calling application-provided free functions if they exist...
Definition dbus-dataslot.c:320
_dbus_data_slot_list_init
void _dbus_data_slot_list_init(DBusDataSlotList *list)
Initializes a slot list.
Definition dbus-dataslot.c:200
_dbus_data_slot_list_free
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...
Definition dbus-dataslot.c:343
_dbus_data_slot_list_get
void * _dbus_data_slot_list_get(DBusDataSlotAllocator *allocator, DBusDataSlotList *list, int slot)
Retrieves data previously set with _dbus_data_slot_list_set_data().
Definition dbus-dataslot.c:288
_dbus_data_slot_list_set
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...
Definition dbus-dataslot.c:224
_dbus_data_slot_allocator_alloc
dbus_bool_t _dbus_data_slot_allocator_alloc(DBusDataSlotAllocator *allocator, dbus_int32_t *slot_id_p)
Allocates an integer ID to be used for storing data in a DBusDataSlotList.
Definition dbus-dataslot.c:72
dbus_error_init
void dbus_error_init(DBusError *error)
Initializes a DBusError structure.
Definition dbus-errors.c:190
dbus_set_error
void dbus_set_error(DBusError *error, const char *name, const char *format,...)
Assigns an error name and message to a DBusError.
Definition dbus-errors.c:356
dbus_error_free
void dbus_error_free(DBusError *error)
Frees an error that's been set (or just initialized), then reinitializes the error as in dbus_error_i...
Definition dbus-errors.c:213
_dbus_assert_not_reached
#define _dbus_assert_not_reached(explanation)
Aborts with an error message if called.
Definition dbus-internals.h:164
_dbus_assert
#define _dbus_assert(condition)
Aborts with an error message if the condition is false.
Definition dbus-internals.h:153
_DBUS_UNLOCK
#define _DBUS_UNLOCK(name)
Unlocks a global lock.
Definition dbus-internals.h:438
_DBUS_LOCK
#define _DBUS_LOCK(name)
Locks a global lock, initializing it first if necessary.
Definition dbus-internals.h:437
_dbus_warn_check_failed
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...
Definition dbus-internals.c:310
_dbus_strdup
char * _dbus_strdup(const char *str)
Duplicates a string.
Definition dbus-internals.c:621
_dbus_warn
void _dbus_warn(const char *format,...)
Prints a warning message to stderr.
Definition dbus-internals.c:278
_DBUS_LOCK_NAME
#define _DBUS_LOCK_NAME(name)
Expands to name of a global lock variable.
Definition dbus-internals.h:436
_DBUS_ZERO
#define _DBUS_ZERO(object)
Sets all bits in an object to zero.
Definition dbus-internals.h:194
_dbus_memdup
void * _dbus_memdup(const void *mem, size_t n_bytes)
Duplicates a block of memory.
Definition dbus-internals.c:649
_dbus_list_pop_first_link
DBusList * _dbus_list_pop_first_link(DBusList **list)
Removes the first link in the list and returns it.
Definition dbus-list.c:658
_dbus_list_append_link
void _dbus_list_append_link(DBusList **list, DBusList *link)
Appends a link to the list.
Definition dbus-list.c:318
_dbus_list_clear_full
void _dbus_list_clear_full(DBusList **list, DBusFreeFunction function)
Free every link and every element in the list.
Definition dbus-list.c:570
_dbus_list_remove_link
void _dbus_list_remove_link(DBusList **list, DBusList *link)
Removes a link from the list.
Definition dbus-list.c:530
_dbus_list_find_last
DBusList * _dbus_list_find_last(DBusList **list, void *data)
Finds a value in the list.
Definition dbus-list.c:475
_dbus_list_pop_first
void * _dbus_list_pop_first(DBusList **list)
Removes the first value in the list and returns it.
Definition dbus-list.c:679
_dbus_list_foreach
void _dbus_list_foreach(DBusList **list, DBusForeachFunction function, void *data)
Calls the given function for each element in the list.
Definition dbus-list.c:789
_dbus_list_clear
void _dbus_list_clear(DBusList **list)
Frees all links in the list and sets the list head to NULL.
Definition dbus-list.c:545
_dbus_list_prepend_link
void _dbus_list_prepend_link(DBusList **list, DBusList *link)
Prepends a link to the list.
Definition dbus-list.c:336
_dbus_list_alloc_link
DBusList * _dbus_list_alloc_link(void *data)
Allocates a linked list node.
Definition dbus-list.c:245
_dbus_list_remove_last
dbus_bool_t _dbus_list_remove_last(DBusList **list, void *data)
Removes a value from the list.
Definition dbus-list.c:449
_dbus_list_append
dbus_bool_t _dbus_list_append(DBusList **list, void *data)
Appends a value to the list.
Definition dbus-list.c:273
NULL
#define NULL
A null pointer, defined appropriately for C or C++.
Definition dbus-macros.h:51
TRUE
#define TRUE
Expands to "1".
Definition dbus-macros.h:41
FALSE
#define FALSE
Expands to "0".
Definition dbus-macros.h:44
_dbus_type_writer_write_basic
dbus_bool_t _dbus_type_writer_write_basic(DBusTypeWriter *writer, int type, const void *value)
Writes out a basic type.
Definition dbus-marshal-recursive.c:2310
_dbus_type_reader_recurse
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...
Definition dbus-marshal-recursive.c:987
DBusValidity
DBusValidity
This is primarily used in unit testing, so we can verify that each invalid message is invalid for the...
Definition dbus-marshal-validate.h:54
_dbus_header_update_lengths
void _dbus_header_update_lengths(DBusHeader *header, int body_len)
Fills in the correct body length.
Definition dbus-marshal-header.c:1207
_dbus_header_copy
dbus_bool_t _dbus_header_copy(const DBusHeader *header, DBusHeader *dest)
Initializes dest with a copy of the given header.
Definition dbus-marshal-header.c:495
_dbus_validate_signature_with_reason
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.
Definition dbus-marshal-validate.c:53
_dbus_type_writer_init_values_only
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...
Definition dbus-marshal-recursive.c:1583
_dbus_type_get_alignment
int _dbus_type_get_alignment(int typecode)
Gets the alignment requirement for the given type; will be 1, 2, 4, or 8.
Definition dbus-marshal-basic.c:1244
_dbus_type_writer_remove_types
void _dbus_type_writer_remove_types(DBusTypeWriter *writer)
Removes type string from the writer.
Definition dbus-marshal-recursive.c:1562
_dbus_type_reader_init
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.
Definition dbus-marshal-recursive.c:732
_dbus_verbose_bytes_of_string
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.
Definition dbus-marshal-basic.c:1428
_dbus_header_set_field_basic
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.
Definition dbus-marshal-header.c:1284
_dbus_header_get_message_type
int _dbus_header_get_message_type(DBusHeader *header)
Gets the type of the message.
Definition dbus-marshal-header.c:391
_dbus_type_reader_get_signature
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.
Definition dbus-marshal-recursive.c:1124
_dbus_type_writer_write_reader
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.
Definition dbus-marshal-recursive.c:2730
_dbus_header_get_field_basic
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.
Definition dbus-marshal-header.c:1362
_dbus_type_writer_recurse
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.
Definition dbus-marshal-recursive.c:2108
_dbus_header_get_flag
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.
Definition dbus-marshal-header.c:1490
_dbus_marshal_byteswap
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.
Definition dbus-marshal-byteswap.c:224
_dbus_type_reader_read_fixed_multi
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...
Definition dbus-marshal-recursive.c:923
_dbus_header_get_byte_order
char _dbus_header_get_byte_order(const DBusHeader *header)
Returns the header's byte order.
Definition dbus-marshal-header.c:179
_dbus_header_have_message_untrusted
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,...
Definition dbus-marshal-header.c:681
_dbus_header_reinit
void _dbus_header_reinit(DBusHeader *header)
Re-initializes a header that was previously initialized and never freed.
Definition dbus-marshal-header.c:448
_dbus_type_reader_get_element_type
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.
Definition dbus-marshal-recursive.c:820
_dbus_type_reader_next
dbus_bool_t _dbus_type_reader_next(DBusTypeReader *reader)
Skip to the next value on this "level".
Definition dbus-marshal-recursive.c:1053
_dbus_header_delete_field
dbus_bool_t _dbus_header_delete_field(DBusHeader *header, int field)
Deletes a field, if it exists.
Definition dbus-marshal-header.c:1427
_dbus_type_reader_get_array_length
int _dbus_type_reader_get_array_length(const DBusTypeReader *reader)
Returns the number of bytes in the array.
Definition dbus-marshal-recursive.c:899
_dbus_header_remove_unknown_fields
dbus_bool_t _dbus_header_remove_unknown_fields(DBusHeader *header)
Remove every header field not known to this version of dbus.
Definition dbus-marshal-header.c:1532
_dbus_header_get_serial
dbus_uint32_t _dbus_header_get_serial(DBusHeader *header)
See dbus_message_get_serial().
Definition dbus-marshal-header.c:432
_dbus_type_writer_add_types
void _dbus_type_writer_add_types(DBusTypeWriter *writer, DBusString *type_str, int type_pos)
Adds type string to the writer, if it had none.
Definition dbus-marshal-recursive.c:1545
_dbus_type_reader_has_next
dbus_bool_t _dbus_type_reader_has_next(const DBusTypeReader *reader)
Check whether there's another value on this "level".
Definition dbus-marshal-recursive.c:1093
_dbus_type_reader_read_basic
void _dbus_type_reader_read_basic(const DBusTypeReader *reader, void *value)
Reads a basic-typed value, as with _dbus_marshal_read_basic().
Definition dbus-marshal-recursive.c:869
_dbus_type_writer_init_types_delayed
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.
Definition dbus-marshal-recursive.c:1527
_dbus_type_to_string
const char * _dbus_type_to_string(int typecode)
Returns a string describing the given type.
Definition dbus-marshal-basic.c:1290
_dbus_validate_body_with_reason
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...
Definition dbus-marshal-validate.c:767
_dbus_type_reader_get_current_type
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...
Definition dbus-marshal-recursive.c:785
_dbus_header_free
void _dbus_header_free(DBusHeader *header)
Frees a header.
Definition dbus-marshal-header.c:481
_dbus_header_init
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...
Definition dbus-marshal-header.c:465
_dbus_header_create
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.
Definition dbus-marshal-header.c:533
_dbus_type_writer_unrecurse
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...
Definition dbus-marshal-recursive.c:2178
_dbus_type_writer_write_fixed_multi
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.
Definition dbus-marshal-recursive.c:2358
_dbus_header_toggle_flag
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.
Definition dbus-marshal-header.c:1468
_dbus_header_set_serial
void _dbus_header_set_serial(DBusHeader *header, dbus_uint32_t serial)
Sets the serial number of a header.
Definition dbus-marshal-header.c:409
_dbus_header_load
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.
Definition dbus-marshal-header.c:981
_dbus_header_byteswap
void _dbus_header_byteswap(DBusHeader *header, int new_order)
Swaps the header into the given order if required.
Definition dbus-marshal-header.c:1507
_dbus_header_get_field_raw
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.
Definition dbus-marshal-header.c:1403
DBusValidationMode
DBusValidationMode
This is used rather than a bool for high visibility.
Definition dbus-marshal-validate.h:41
DBUS_VALIDITY_UNKNOWN_OOM_ERROR
@ DBUS_VALIDITY_UNKNOWN_OOM_ERROR
can't determine validity due to OOM
Definition dbus-marshal-validate.h:56
DBUS_VALID
@ DBUS_VALID
the data is valid
Definition dbus-marshal-validate.h:60
_dbus_current_generation
int _dbus_current_generation
_dbus_current_generation is used to track each time that dbus_shutdown() is called,...
Definition dbus-memory.c:790
_dbus_register_shutdown_func
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:819
dbus_free
void dbus_free(void *memory)
Frees a block of memory previously allocated by dbus_malloc() or dbus_malloc0().
Definition dbus-memory.c:710
dbus_realloc
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:610
dbus_new
#define dbus_new(type, count)
Safe macro for using dbus_malloc().
Definition dbus-memory.h:59
DBusFreeFunction
void(* DBusFreeFunction)(void *memory)
The type of a function which frees a block of memory.
Definition dbus-memory.h:65
dbus_new0
#define dbus_new0(type, count)
Safe macro for using dbus_malloc0().
Definition dbus-memory.h:60
dbus_free_string_array
void dbus_free_string_array(char **str_array)
Frees a NULL-terminated array of strings.
Definition dbus-memory.c:758
_dbus_message_loader_set_max_message_size
void _dbus_message_loader_set_max_message_size(DBusMessageLoader *loader, long size)
Sets the maximum size message we allow.
Definition dbus-message.c:4843
_dbus_message_remove_unknown_fields
dbus_bool_t _dbus_message_remove_unknown_fields(DBusMessage *message)
Remove every header field not known to this version of dbus.
Definition dbus-message.c:284
_dbus_message_iter_get_args_valist
DBUS_PRIVATE_EXPORT dbus_bool_t _dbus_message_iter_get_args_valist(DBusMessageIter *iter, DBusError *error, int first_arg_type, va_list var_args)
Implementation of the varargs arg-getting functions.
Definition dbus-message.c:838
_dbus_variant_read
DBusVariant * _dbus_variant_read(DBusMessageIter *reader)
Copy a single D-Bus message item from reader into a newly-allocated DBusVariant.
Definition dbus-message.c:5349
ensure_byte_order
#define ensure_byte_order(message)
byte-swap the message if it doesn't match our byte order.
Definition dbus-message.c:230
MAX_MESSAGE_SIZE_TO_CACHE
#define MAX_MESSAGE_SIZE_TO_CACHE
Avoid caching huge messages.
Definition dbus-message.c:508
_dbus_variant_write
dbus_bool_t _dbus_variant_write(DBusVariant *self, DBusMessageIter *writer)
Copy the single D-Bus message item from self into writer.
Definition dbus-message.c:5516
dbus_message_iter_init_closed
void dbus_message_iter_init_closed(DBusMessageIter *iter)
Initialize iter as if with DBUS_MESSAGE_ITER_INIT_CLOSED.
Definition dbus-message.c:755
_dbus_message_loader_get_is_corrupted
dbus_bool_t _dbus_message_loader_get_is_corrupted(DBusMessageLoader *loader)
Checks whether the loader is confused due to bad data.
Definition dbus-message.c:4814
dbus_message_set_serial
void dbus_message_set_serial(DBusMessage *message, dbus_uint32_t serial)
Sets the serial number of a message.
Definition dbus-message.c:301
dbus_message_lock
void dbus_message_lock(DBusMessage *message)
Locks a message.
Definition dbus-message.c:431
dbus_message_type_from_string
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.
Definition dbus-message.c:5053
_dbus_message_loader_unref
void _dbus_message_loader_unref(DBusMessageLoader *loader)
Decrements the reference count of the loader and finalizes the loader when the count reaches zero.
Definition dbus-message.c:4239
dbus_message_allocate_data_slot
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.
Definition dbus-message.c:4950
_dbus_message_get_unix_fds
void _dbus_message_get_unix_fds(DBusMessage *message, const int **fds, unsigned *n_fds)
Gets the unix fds to be sent over the network for this message.
Definition dbus-message.c:262
dbus_message_demarshal
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.
Definition dbus-message.c:5173
_dbus_message_loader_pop_message
DBusMessage * _dbus_message_loader_pop_message(DBusMessageLoader *loader)
Pops a loaded message (passing ownership of the message to the caller).
Definition dbus-message.c:4772
_dbus_message_get_network_data
void _dbus_message_get_network_data(DBusMessage *message, const DBusString **header, const DBusString **body)
Gets the data to be sent over the network for this message.
Definition dbus-message.c:243
_dbus_message_loader_set_pending_fds_function
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...
Definition dbus-message.c:4922
CHANGED_STAMP_BITS
#define CHANGED_STAMP_BITS
How many bits are in the changed_stamp used to validate iterators.
Definition dbus-message-private.h:92
dbus_message_set_data
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...
Definition dbus-message.c:4989
_dbus_message_loader_putback_message_link
void _dbus_message_loader_putback_message_link(DBusMessageLoader *loader, DBusList *link)
Returns a popped message link, used to undo a pop.
Definition dbus-message.c:4798
dbus_message_get_data
void * dbus_message_get_data(DBusMessage *message, dbus_int32_t slot)
Retrieves data previously set with dbus_message_set_data().
Definition dbus-message.c:5025
dbus_message_type_to_string
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).
Definition dbus-message.c:5081
dbus_message_set_allow_interactive_authorization
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...
Definition dbus-message.c:5300
_dbus_message_loader_get_pending_fds_count
int _dbus_message_loader_get_pending_fds_count(DBusMessageLoader *loader)
Return how many file descriptors are pending in the loader.
Definition dbus-message.c:4904
_dbus_variant_get_signature
const char * _dbus_variant_get_signature(DBusVariant *self)
Return the signature of the item stored in self.
Definition dbus-message.c:5485
dbus_message_demarshal_bytes_needed
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.
Definition dbus-message.c:5240
_DBUS_STRING_DEFINE_STATIC
_DBUS_STRING_DEFINE_STATIC(_dbus_empty_signature_str, "")
An static string representing an empty signature.
_dbus_message_loader_get_buffer
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.
Definition dbus-message.c:4274
dbus_message_free_data_slot
void dbus_message_free_data_slot(dbus_int32_t *slot_p)
Deallocates a global ID for message data slots.
Definition dbus-message.c:4968
_dbus_message_remove_counter
void _dbus_message_remove_counter(DBusMessage *message, DBusCounter *counter)
Removes a counter tracking the size/unix fds of this message, and decrements the counter by the size/...
Definition dbus-message.c:399
INITIAL_LOADER_DATA_LEN
#define INITIAL_LOADER_DATA_LEN
The initial buffer size of the message loader.
Definition dbus-message.c:4168
_dbus_message_add_counter
dbus_bool_t _dbus_message_add_counter(DBusMessage *message, DBusCounter *counter)
Adds a counter to be incremented immediately with the size/unix fds of this message,...
Definition dbus-message.c:376
_dbus_message_loader_peek_message
DBusMessage * _dbus_message_loader_peek_message(DBusMessageLoader *loader)
Peeks at first loaded message, returns NULL if no messages have been queued.
Definition dbus-message.c:4755
dbus_message_marshal
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.
Definition dbus-message.c:5111
_dbus_message_loader_set_max_message_unix_fds
void _dbus_message_loader_set_max_message_unix_fds(DBusMessageLoader *loader, long n)
Sets the maximum unix fds per message we allow.
Definition dbus-message.c:4874
_dbus_message_loader_get_max_message_size
long _dbus_message_loader_get_max_message_size(DBusMessageLoader *loader)
Gets the maximum allowed message size in bytes.
Definition dbus-message.c:4862
_dbus_message_loader_new
DBusMessageLoader * _dbus_message_loader_new(void)
Creates a new message loader.
Definition dbus-message.c:4177
MAX_MESSAGE_CACHE_SIZE
#define MAX_MESSAGE_CACHE_SIZE
Avoid caching too many messages.
Definition dbus-message.c:511
_dbus_message_loader_pop_message_link
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).
Definition dbus-message.c:4786
_dbus_message_loader_queue_messages
dbus_bool_t _dbus_message_loader_queue_messages(DBusMessageLoader *loader)
Converts buffered data into messages, if we have enough data.
Definition dbus-message.c:4692
_dbus_message_loader_return_buffer
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...
Definition dbus-message.c:4380
_dbus_message_loader_ref
DBusMessageLoader * _dbus_message_loader_ref(DBusMessageLoader *loader)
Increments the reference count of the loader.
Definition dbus-message.c:4225
_dbus_message_loader_get_max_message_unix_fds
long _dbus_message_loader_get_max_message_unix_fds(DBusMessageLoader *loader)
Gets the maximum allowed number of unix fds per message.
Definition dbus-message.c:4893
_dbus_message_add_counter_link
void _dbus_message_add_counter_link(DBusMessage *message, DBusList *link)
Adds a counter to be incremented immediately with the size/unix fds of this message,...
Definition dbus-message.c:327
_dbus_message_loader_get_corruption_reason
DBusValidity _dbus_message_loader_get_corruption_reason(DBusMessageLoader *loader)
Checks what kind of bad data confused the loader.
Definition dbus-message.c:4828
dbus_message_get_allow_interactive_authorization
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...
Definition dbus-message.c:5318
dbus_message_has_destination
dbus_bool_t dbus_message_has_destination(DBusMessage *message, const char *name)
Checks whether the message was sent to the given name.
Definition dbus-message.c:3953
dbus_message_set_interface
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...
Definition dbus-message.c:3461
dbus_message_has_interface
dbus_bool_t dbus_message_has_interface(DBusMessage *message, const char *iface)
Checks if the message has an interface.
Definition dbus-message.c:3512
dbus_message_set_no_reply
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,...
Definition dbus-message.c:3247
dbus_message_append_args_valist
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.
Definition dbus-message.c:1875
dbus_message_get_sender
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...
Definition dbus-message.c:3773
dbus_message_set_auto_start
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...
Definition dbus-message.c:3289
dbus_message_iter_append_basic
dbus_bool_t dbus_message_iter_append_basic(DBusMessageIter *iter, int type, const void *value)
Appends a basic-typed value to the message.
Definition dbus-message.c:2771
dbus_message_get_path
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...
Definition dbus-message.c:3359
dbus_message_get_interface
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...
Definition dbus-message.c:3490
dbus_message_new_error
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.
Definition dbus-message.c:1515
dbus_message_has_sender
dbus_bool_t dbus_message_has_sender(DBusMessage *message, const char *name)
Checks whether the message has the given unique name as its sender.
Definition dbus-message.c:3988
dbus_message_get_serial
dbus_uint32_t dbus_message_get_serial(DBusMessage *message)
Returns the serial of a message or 0 if none has been specified.
Definition dbus-message.c:1168
dbus_message_set_member
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...
Definition dbus-message.c:3549
dbus_message_iter_get_basic
void dbus_message_iter_get_basic(DBusMessageIter *iter, void *value)
Reads a basic-typed value from the message iterator.
Definition dbus-message.c:2369
dbus_message_get_type
int dbus_message_get_type(DBusMessage *message)
Gets the type of a message.
Definition dbus-message.c:1767
dbus_message_copy
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 ...
Definition dbus-message.c:1632
dbus_message_get_error_name
const char * dbus_message_get_error_name(DBusMessage *message)
Gets the error name (DBUS_MESSAGE_TYPE_ERROR only) or NULL if none.
Definition dbus-message.c:3660
dbus_message_iter_next
dbus_bool_t dbus_message_iter_next(DBusMessageIter *iter)
Moves the iterator to the next field, if any.
Definition dbus-message.c:2186
dbus_message_append_args
dbus_bool_t dbus_message_append_args(DBusMessage *message, int first_arg_type,...)
Appends fields to a message given a variable argument list.
Definition dbus-message.c:1843
dbus_message_iter_get_arg_type
int dbus_message_iter_get_arg_type(DBusMessageIter *iter)
Returns the argument type of the argument that the message iterator points to.
Definition dbus-message.c:2211
dbus_message_get_no_reply
dbus_bool_t dbus_message_get_no_reply(DBusMessage *message)
Returns TRUE if the message does not expect a reply.
Definition dbus-message.c:3266
dbus_message_new_signal
DBusMessage * dbus_message_new_signal(const char *path, const char *iface, const char *name)
Constructs a new message representing a signal emission.
Definition dbus-message.c:1469
dbus_message_iter_append_fixed_array
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.
Definition dbus-message.c:2922
dbus_message_iter_abandon_container
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...
Definition dbus-message.c:3123
dbus_message_new_error_printf
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...
Definition dbus-message.c:1587
dbus_message_is_error
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.
Definition dbus-message.c:3920
dbus_message_contains_unix_fds
dbus_bool_t dbus_message_contains_unix_fds(DBusMessage *message)
Checks whether a message contains unix fds.
Definition dbus-message.c:4088
dbus_message_iter_recurse
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...
Definition dbus-message.c:2267
dbus_message_ref
DBusMessage * dbus_message_ref(DBusMessage *message)
Increments the reference count of a DBusMessage.
Definition dbus-message.c:1712
dbus_message_get_auto_start
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.
Definition dbus-message.c:3308
dbus_message_iter_get_element_type
int dbus_message_iter_get_element_type(DBusMessageIter *iter)
Returns the element type of the array that the message iterator points to.
Definition dbus-message.c:2230
dbus_message_set_error_name
dbus_bool_t dbus_message_set_error_name(DBusMessage *message, const char *error_name)
Sets the name of the error (DBUS_MESSAGE_TYPE_ERROR).
Definition dbus-message.c:3634
dbus_message_has_signature
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...
Definition dbus-message.c:4017
dbus_message_iter_open_container
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.
Definition dbus-message.c:2986
dbus_message_get_reply_serial
dbus_uint32_t dbus_message_get_reply_serial(DBusMessage *message)
Returns the serial that the message is a reply to or 0 if none.
Definition dbus-message.c:1208
dbus_message_new_method_return
DBusMessage * dbus_message_new_method_return(DBusMessage *method_call)
Constructs a message that is a reply to a method call.
Definition dbus-message.c:1418
dbus_message_new_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.
Definition dbus-message.c:1378
dbus_message_iter_init
dbus_bool_t dbus_message_iter_init(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for reading the arguments of the message passed in.
Definition dbus-message.c:2136
dbus_message_set_sender
dbus_bool_t dbus_message_set_sender(DBusMessage *message, const char *sender)
Sets the message sender.
Definition dbus-message.c:3742
dbus_message_iter_abandon_container_if_open
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...
Definition dbus-message.c:3182
dbus_message_get_destination
const char * dbus_message_get_destination(DBusMessage *message)
Gets the destination of a message or NULL if there is none set.
Definition dbus-message.c:3713
dbus_message_set_path
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...
Definition dbus-message.c:3330
dbus_message_iter_has_next
dbus_bool_t dbus_message_iter_has_next(DBusMessageIter *iter)
Checks if an iterator has any more fields.
Definition dbus-message.c:2167
dbus_message_get_args_valist
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.
Definition dbus-message.c:2061
dbus_message_iter_get_signature
char * dbus_message_iter_get_signature(DBusMessageIter *iter)
Returns the current signature of a message iterator.
Definition dbus-message.c:2292
dbus_message_unref
void dbus_message_unref(DBusMessage *message)
Decrements the reference count of a DBusMessage, freeing the message if the count reaches 0.
Definition dbus-message.c:1735
dbus_message_iter_get_array_len
int dbus_message_iter_get_array_len(DBusMessageIter *iter)
Returns the number of bytes in the array as marshaled in the wire protocol.
Definition dbus-message.c:2458
dbus_message_new
DBusMessage * dbus_message_new(int message_type)
Constructs a new message of the given message type.
Definition dbus-message.c:1334
dbus_set_error_from_message
dbus_bool_t dbus_set_error_from_message(DBusError *error, DBusMessage *message)
Sets a DBusError based on the contents of the given message.
Definition dbus-message.c:4059
dbus_message_iter_get_element_count
int dbus_message_iter_get_element_count(DBusMessageIter *iter)
Returns the number of elements in the array-typed value pointed to by the iterator.
Definition dbus-message.c:2414
dbus_message_set_destination
dbus_bool_t dbus_message_set_destination(DBusMessage *message, const char *destination)
Sets the message's destination.
Definition dbus-message.c:3688
dbus_message_has_path
dbus_bool_t dbus_message_has_path(DBusMessage *message, const char *path)
Checks if the message has a particular object path.
Definition dbus-message.c:3383
dbus_message_has_member
dbus_bool_t dbus_message_has_member(DBusMessage *message, const char *member)
Checks if the message has an interface member.
Definition dbus-message.c:3598
dbus_message_get_args
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.
Definition dbus-message.c:2032
dbus_message_is_method_call
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.
Definition dbus-message.c:3865
dbus_message_iter_get_fixed_array
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.
Definition dbus-message.c:2503
dbus_message_set_reply_serial
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).
Definition dbus-message.c:1184
dbus_message_is_signal
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.
Definition dbus-message.c:3893
dbus_message_get_signature
const char * dbus_message_get_signature(DBusMessage *message)
Gets the type signature of the message, i.e.
Definition dbus-message.c:3806
dbus_message_set_container_instance
dbus_bool_t dbus_message_set_container_instance(DBusMessage *message, const char *object_path)
Sets the container instance this message was sent from.
Definition dbus-message.c:4110
dbus_message_iter_close_container
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...
Definition dbus-message.c:3089
dbus_message_get_path_decomposed
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...
Definition dbus-message.c:3427
dbus_message_get_member
const char * dbus_message_get_member(DBusMessage *message)
Gets the interface member being invoked (DBUS_MESSAGE_TYPE_METHOD_CALL) or emitted (DBUS_MESSAGE_TYPE...
Definition dbus-message.c:3576
dbus_message_iter_init_append
void dbus_message_iter_init_append(DBusMessage *message, DBusMessageIter *iter)
Initializes a DBusMessageIter for appending arguments to the end of a message.
Definition dbus-message.c:2533
dbus_message_get_container_instance
const char * dbus_message_get_container_instance(DBusMessage *message)
Gets the container instance this message was sent from, or NULL if none.
Definition dbus-message.c:4136
_dbus_decompose_path
dbus_bool_t _dbus_decompose_path(const char *data, int len, char ***path, int *path_len)
Decompose an object path.
Definition dbus-object-tree.c:1247
DBUS_HEADER_FIELD_UNIX_FDS
#define DBUS_HEADER_FIELD_UNIX_FDS
Header field code for the number of unix file descriptors associated with this message.
Definition dbus-protocol.h:304
DBUS_MESSAGE_TYPE_METHOD_CALL
#define DBUS_MESSAGE_TYPE_METHOD_CALL
Message type of a method call message, see dbus_message_get_type().
Definition dbus-protocol.h:236
DBUS_HEADER_FIELD_PATH
#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...
Definition dbus-protocol.h:272
DBUS_HEADER_FLAG_NO_REPLY_EXPECTED
#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,...
Definition dbus-protocol.h:251
DBUS_HEADER_FIELD_REPLY_SERIAL
#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...
Definition dbus-protocol.h:286
DBUS_HEADER_FIELD_CONTAINER_INSTANCE
#define DBUS_HEADER_FIELD_CONTAINER_INSTANCE
Header field code for the container instance that sent this message.
Definition dbus-protocol.h:308
DBUS_TYPE_SIGNATURE
#define DBUS_TYPE_SIGNATURE
Type code marking a D-Bus type signature.
Definition dbus-protocol.h:112
DBUS_MAXIMUM_MESSAGE_UNIX_FDS
#define DBUS_MAXIMUM_MESSAGE_UNIX_FDS
The maximum total number of unix fds in a message.
Definition dbus-protocol.h:220
DBUS_MAXIMUM_MESSAGE_LENGTH
#define DBUS_MAXIMUM_MESSAGE_LENGTH
The maximum total message size including header and body; similar rationale to max array size.
Definition dbus-protocol.h:212
DBUS_HEADER_FIELD_INTERFACE
#define DBUS_HEADER_FIELD_INTERFACE
Header field code for the interface containing a member (method or signal).
Definition dbus-protocol.h:276
DBUS_ERROR_INCONSISTENT_MESSAGE
#define DBUS_ERROR_INCONSISTENT_MESSAGE
The message meta data does not match the payload.
Definition dbus-protocol.h:459
DBUS_HEADER_FIELD_MEMBER
#define DBUS_HEADER_FIELD_MEMBER
Header field code for a member (method or signal).
Definition dbus-protocol.h:278
DBUS_MESSAGE_TYPE_ERROR
#define DBUS_MESSAGE_TYPE_ERROR
Message type of an error reply message, see dbus_message_get_type().
Definition dbus-protocol.h:240
DBUS_TYPE_OBJECT_PATH
#define DBUS_TYPE_OBJECT_PATH
Type code marking a D-Bus object path.
Definition dbus-protocol.h:108
DBUS_ERROR_NOT_SUPPORTED
#define DBUS_ERROR_NOT_SUPPORTED
Requested operation isn't supported (like ENOSYS on UNIX).
Definition dbus-protocol.h:375
DBUS_HEADER_FIELD_SENDER
#define DBUS_HEADER_FIELD_SENDER
Header field code for the sender of a message; usually initialized by the message bus.
Definition dbus-protocol.h:295
DBUS_HEADER_FIELD_SIGNATURE
#define DBUS_HEADER_FIELD_SIGNATURE
Header field code for the type signature of a message.
Definition dbus-protocol.h:299
DBUS_MESSAGE_TYPE_METHOD_RETURN
#define DBUS_MESSAGE_TYPE_METHOD_RETURN
Message type of a method return message, see dbus_message_get_type().
Definition dbus-protocol.h:238
DBUS_TYPE_VARIANT
#define DBUS_TYPE_VARIANT
Type code marking a D-Bus variant type.
Definition dbus-protocol.h:126
DBUS_MAXIMUM_ARRAY_LENGTH
#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...
Definition dbus-protocol.h:205
DBUS_TYPE_UNIX_FD
#define DBUS_TYPE_UNIX_FD
Type code marking a unix file descriptor.
Definition dbus-protocol.h:116
DBUS_TYPE_BOOLEAN
#define DBUS_TYPE_BOOLEAN
Type code marking a boolean.
Definition dbus-protocol.h:72
DBUS_MESSAGE_TYPE_SIGNAL
#define DBUS_MESSAGE_TYPE_SIGNAL
Message type of a signal message, see dbus_message_get_type().
Definition dbus-protocol.h:242
DBUS_TYPE_STRING
#define DBUS_TYPE_STRING
Type code marking a UTF-8 encoded, nul-terminated Unicode string.
Definition dbus-protocol.h:104
DBUS_HEADER_FLAG_NO_AUTO_START
#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 ...
Definition dbus-protocol.h:258
DBUS_TYPE_ARRAY
#define DBUS_TYPE_ARRAY
Type code marking a D-Bus array type.
Definition dbus-protocol.h:122
DBUS_HEADER_FLAG_ALLOW_INTERACTIVE_AUTHORIZATION
#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...
Definition dbus-protocol.h:263
DBUS_TYPE_INVALID
#define DBUS_TYPE_INVALID
Type code that is never equal to a legitimate type code.
Definition dbus-protocol.h:62
DBUS_HEADER_FIELD_ERROR_NAME
#define DBUS_HEADER_FIELD_ERROR_NAME
Header field code for an error name (found in DBUS_MESSAGE_TYPE_ERROR messages).
Definition dbus-protocol.h:282
DBUS_TYPE_VARIANT_AS_STRING
#define DBUS_TYPE_VARIANT_AS_STRING
DBUS_TYPE_VARIANT as a string literal instead of a int literal
Definition dbus-protocol.h:128
DBUS_MESSAGE_TYPE_INVALID
#define DBUS_MESSAGE_TYPE_INVALID
This value is never a valid message type, see dbus_message_get_type().
Definition dbus-protocol.h:234
DBUS_ERROR_INVALID_ARGS
#define DBUS_ERROR_INVALID_ARGS
Invalid arguments passed to a method call.
Definition dbus-protocol.h:397
DBUS_TYPE_DICT_ENTRY
#define DBUS_TYPE_DICT_ENTRY
Type code used to represent a dict entry; however, this type code does not appear in type signatures,...
Definition dbus-protocol.h:145
DBUS_DICT_ENTRY_BEGIN_CHAR
#define DBUS_DICT_ENTRY_BEGIN_CHAR
Code marking the start of a dict entry type in a type signature.
Definition dbus-protocol.h:166
DBUS_HEADER_FIELD_DESTINATION
#define DBUS_HEADER_FIELD_DESTINATION
Header field code for the destination bus name of a message.
Definition dbus-protocol.h:290
DBUS_TYPE_STRUCT
#define DBUS_TYPE_STRUCT
STRUCT and DICT_ENTRY are sort of special since their codes can't appear in a type string,...
Definition dbus-protocol.h:138
DBUS_TYPE_UINT32
#define DBUS_TYPE_UINT32
Type code marking a 32-bit unsigned integer.
Definition dbus-protocol.h:88
DBUS_MINIMUM_HEADER_SIZE
#define DBUS_MINIMUM_HEADER_SIZE
The smallest header size that can occur.
Definition dbus-protocol.h:352
_dbus_counter_unref
void _dbus_counter_unref(DBusCounter *counter)
Decrements refcount of the counter and possibly finalizes the counter.
Definition dbus-resources.c:138
_dbus_counter_adjust_unix_fd
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.
Definition dbus-resources.c:238
_dbus_counter_notify
void _dbus_counter_notify(DBusCounter *counter)
Calls the notify function from _dbus_counter_set_notify(), if that function has been specified and th...
Definition dbus-resources.c:209
_dbus_counter_ref
DBusCounter * _dbus_counter_ref(DBusCounter *counter)
Increments refcount of the counter.
Definition dbus-resources.c:118
_dbus_counter_adjust_size
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.
Definition dbus-resources.c:169
dbus_type_is_basic
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...
Definition dbus-signature.c:324
dbus_type_is_fixed
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.
Definition dbus-signature.c:355
dbus_type_is_container
dbus_bool_t dbus_type_is_container(int typecode)
A "container type" can contain basic types, or nested container types.
Definition dbus-signature.c:300
_dbus_string_set_length
dbus_bool_t _dbus_string_set_length(DBusString *str, int length)
Sets the length of a string.
Definition dbus-string.c:847
_dbus_string_init
dbus_bool_t _dbus_string_init(DBusString *str)
Initializes a string.
Definition dbus-string.c:182
_dbus_string_init_const
void _dbus_string_init_const(DBusString *str, const char *value)
Initializes a constant string.
Definition dbus-string.c:197
_dbus_string_copy
dbus_bool_t _dbus_string_copy(const DBusString *source, int start, DBusString *dest, int insert_at)
Like _dbus_string_move(), but does not delete the section of the source string that's copied to the d...
Definition dbus-string.c:1345
_dbus_string_steal_data
dbus_bool_t _dbus_string_steal_data(DBusString *str, char **data_return)
Like _dbus_string_get_data(), but removes the gotten data from the original string.
Definition dbus-string.c:686
_dbus_string_init_preallocated
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
_dbus_string_init_const_len
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_string_append_len
dbus_bool_t _dbus_string_append_len(DBusString *str, const char *buffer, int len)
Appends block of bytes with the given length to a DBusString.
Definition dbus-string.c:1170
_dbus_string_free
void _dbus_string_free(DBusString *str)
Frees a string created by _dbus_string_init(), and fills it with the same contents as _DBUS_STRING_IN...
Definition dbus-string.c:278
_dbus_string_delete
void _dbus_string_delete(DBusString *str, int start, int len)
Deletes a segment of a DBusString with length len starting at start.
Definition dbus-string.c:1255
_dbus_string_append_printf_valist
dbus_bool_t _dbus_string_append_printf_valist(DBusString *str, const char *format, va_list args)
Appends a printf-style formatted string to the DBusString.
Definition dbus-string.c:1105
_dbus_string_compact
dbus_bool_t _dbus_string_compact(DBusString *str, int max_waste)
Compacts the string to avoid wasted memory.
Definition dbus-string.c:420
_dbus_string_copy_len
dbus_bool_t _dbus_string_copy_len(const DBusString *source, int start, int len, DBusString *dest, int insert_at)
Like _dbus_string_copy(), but can copy a segment from the middle of the source string.
Definition dbus-string.c:1437
_dbus_close
dbus_bool_t _dbus_close(int fd, DBusError *error)
Closes a file descriptor.
Definition dbus-sysdeps-unix.c:3727
_dbus_dup
int _dbus_dup(int fd, DBusError *error)
Duplicates a file descriptor.
Definition dbus-sysdeps-unix.c:3755
_dbus_atomic_dec
dbus_int32_t _dbus_atomic_dec(DBusAtomic *atomic)
Atomically decrement an integer.
Definition dbus-sysdeps-unix.c:3205
_dbus_getenv
const char * _dbus_getenv(const char *varname)
Wrapper for getenv().
Definition dbus-sysdeps.c:197
_dbus_atomic_get
dbus_int32_t _dbus_atomic_get(DBusAtomic *atomic)
Atomically get the value of an integer.
Definition dbus-sysdeps-unix.c:3233
_dbus_atomic_inc
dbus_int32_t _dbus_atomic_inc(DBusAtomic *atomic)
Atomically increments an integer.
Definition dbus-sysdeps-unix.c:3178
dbus_uint32_t
unsigned int dbus_uint32_t
A 32-bit unsigned integer on all platforms.
Definition dbus-arch-deps.h:45
dbus_int32_t
int dbus_int32_t
A 32-bit signed integer on all platforms.
Definition dbus-arch-deps.h:44
dbus_bool_t
dbus_uint32_t dbus_bool_t
A boolean, valid values are TRUE and FALSE.
Definition dbus-types.h:37
DBusCounter
Internals of DBusCounter.
Definition dbus-resources.c:57
DBusDataSlotAllocator
An allocator that tracks a set of slot IDs.
Definition dbus-dataslot.h:58
DBusError
Object representing an exception.
Definition dbus-errors.h:51
DBusError::message
const char * message
public error message field
Definition dbus-errors.h:53
DBusHeader
Message header data and some cached details of it.
Definition dbus-marshal-header.h:90
DBusHeader::data
DBusString data
Header network data, stored separately from body so we can independently realloc it.
Definition dbus-marshal-header.h:91
DBusList
A node in a linked list.
Definition dbus-list.h:37
DBusList::data
void * data
Data stored at this element.
Definition dbus-list.h:40
DBusMessageIter_1_10_0
Layout of a DBusMessageIter on the stack in dbus 1.10.0.
Definition dbus-message.c:156
DBusMessageIter
DBusMessageIter struct; contains no public fields.
Definition dbus-message.h:64
DBusMessageLoader
Implementation details of DBusMessageLoader.
Definition dbus-message-private.h:63
DBusMessageLoader::max_message_size
long max_message_size
Maximum size of a message.
Definition dbus-message-private.h:70
DBusMessageLoader::max_message_unix_fds
long max_message_unix_fds
Maximum unix fds in a message.
Definition dbus-message-private.h:71
DBusMessageLoader::data
DBusString data
Buffered data.
Definition dbus-message-private.h:66
DBusMessageLoader::messages
DBusList * messages
Complete messages.
Definition dbus-message-private.h:68
DBusMessageLoader::corrupted
unsigned int corrupted
We got broken data, and are no longer working.
Definition dbus-message-private.h:75
DBusMessageLoader::buffer_outstanding
unsigned int buffer_outstanding
Someone is using the buffer to read.
Definition dbus-message-private.h:77
DBusMessageLoader::corruption_reason
DBusValidity corruption_reason
why we were corrupted
Definition dbus-message-private.h:73
DBusMessageLoader::refcount
int refcount
Reference count.
Definition dbus-message-private.h:64
DBusMessageRealIter
Internals of DBusMessageIter.
Definition dbus-message.c:129
DBusMessageRealIter::message
DBusMessage * message
Message used.
Definition dbus-message.c:130
DBusMessageRealIter::iter_type
dbus_uint32_t iter_type
whether this is a reader or writer iter
Definition dbus-message.c:132
DBusMessageRealIter::u
union DBusMessageRealIter::@074337266072331130372054317224250203251245140017 u
the type writer or reader that does all the work
DBusMessageRealIter::sig_refcount
dbus_uint32_t sig_refcount
depth of open_signature()
Definition dbus-message.c:133
DBusMessageRealIter::writer
DBusTypeWriter writer
writer
Definition dbus-message.c:136
DBusMessageRealIter::changed_stamp
dbus_uint32_t changed_stamp
stamp to detect invalid iters
Definition dbus-message.c:131
DBusMessageRealIter::reader
DBusTypeReader reader
reader
Definition dbus-message.c:137
DBusMessage
Internals of DBusMessage.
Definition dbus-message-private.h:102
DBusMessage::header
DBusHeader header
Header network data and associated cache.
Definition dbus-message-private.h:105
DBusMessage::body
DBusString body
Body network data.
Definition dbus-message-private.h:107
DBusMessage::slot_list
DBusDataSlotList slot_list
Data stored by allocated integer ID.
Definition dbus-message-private.h:120
DBusMessage::refcount
DBusAtomic refcount
Reference count.
Definition dbus-message-private.h:103
DBusMessage::changed_stamp
dbus_uint32_t changed_stamp
Incremented when iterators are invalidated.
Definition dbus-message-private.h:118
DBusMessage::generation
int generation
_dbus_current_generation when message was created
Definition dbus-message-private.h:123
DBusMessage::size_counter_delta
long size_counter_delta
Size we incremented the size counters by.
Definition dbus-message-private.h:116
DBusMessage::counters
DBusList * counters
0-N DBusCounter used to track message size/unix fds.
Definition dbus-message-private.h:115
DBusMessage::in_cache
unsigned int in_cache
Has been "freed" since it's in the cache (this is a debug feature).
Definition dbus-message-private.h:112
DBusMessage::locked
unsigned int locked
Message being sent, no modifications allowed.
Definition dbus-message-private.h:109
DBusString
Definition dbus-string.h:47
DBusTypeReader
The type reader is an iterator for reading values from a block of values.
Definition dbus-marshal-recursive.h:42
DBusTypeReader::byte_order
dbus_uint32_t byte_order
byte order of the block
Definition dbus-marshal-recursive.h:47
DBusTypeWriter
The type writer is an iterator for writing to a block of values.
Definition dbus-marshal-recursive.h:68
DBusTypeWriter::byte_order
dbus_uint32_t byte_order
byte order to write values with
Definition dbus-marshal-recursive.h:71
DBusTypeWriter::type_str
DBusString * type_str
where to write typecodes (or read type expectations)
Definition dbus-marshal-recursive.h:69
DBusTypeWriter::container_type
dbus_uint32_t container_type
what are we inside?
Definition dbus-marshal-recursive.h:73
DBusVariant
An opaque data structure containing the serialized form of any single D-Bus message item,...
Definition dbus-message.c:5333
DBusBasicValue
A simple value union that lets you access bytes as if they were various types; useful when dealing wi...
Definition dbus-types.h:161
DBusBasicValue::u32
dbus_uint32_t u32
as int32
Definition dbus-types.h:166