summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HACKING7
-rw-r--r--NEWS87
-rw-r--r--bus/Makefile.am46
-rw-r--r--bus/activation-helper.c7
-rw-r--r--bus/activation.c59
-rw-r--r--bus/bus.c50
-rw-r--r--bus/config-parser.c11
-rw-r--r--bus/connection.c165
-rw-r--r--bus/connection.h13
-rw-r--r--bus/dir-watch-inotify.c17
-rw-r--r--bus/dir-watch-kqueue.c17
-rw-r--r--bus/dispatch.c1
-rw-r--r--bus/driver.c196
-rw-r--r--bus/expirelist.c15
-rw-r--r--bus/main.c30
-rw-r--r--bus/signals.c609
-rw-r--r--bus/signals.h30
-rw-r--r--bus/stats.c352
-rw-r--r--bus/stats.h38
-rw-r--r--bus/test.c38
-rw-r--r--cmake/CMakeLists.txt67
-rw-r--r--cmake/config.h.cmake6
-rw-r--r--cmake/test/CMakeLists.txt16
-rw-r--r--cmake/test/name-test/CMakeLists.txt8
-rw-r--r--cmake/tools/CMakeLists.txt8
-rw-r--r--configure.ac98
-rw-r--r--dbus-1-uninstalled.pc.in2
-rw-r--r--dbus-1.pc.in3
-rw-r--r--dbus/Makefile.am43
-rw-r--r--dbus/dbus-bus.c35
-rw-r--r--dbus/dbus-connection-internal.h15
-rw-r--r--dbus/dbus-connection.c383
-rw-r--r--dbus/dbus-internals.c4
-rw-r--r--dbus/dbus-list.c12
-rw-r--r--dbus/dbus-list.h7
-rw-r--r--dbus/dbus-mainloop.c603
-rw-r--r--dbus/dbus-mainloop.h20
-rw-r--r--dbus/dbus-marshal-basic.c38
-rw-r--r--dbus/dbus-marshal-basic.h1
-rw-r--r--dbus/dbus-marshal-header.c61
-rw-r--r--dbus/dbus-marshal-header.h8
-rw-r--r--dbus/dbus-marshal-recursive-util.c5
-rw-r--r--dbus/dbus-marshal-validate.c70
-rw-r--r--dbus/dbus-marshal-validate.h3
-rw-r--r--dbus/dbus-memory.c3
-rw-r--r--dbus/dbus-mempool.c42
-rw-r--r--dbus/dbus-mempool.h6
-rw-r--r--dbus/dbus-message-factory.c23
-rw-r--r--dbus/dbus-message-internal.h3
-rw-r--r--dbus/dbus-message-private.h2
-rw-r--r--dbus/dbus-message.c66
-rw-r--r--dbus/dbus-nonce.c2
-rw-r--r--dbus/dbus-object-tree.c8
-rw-r--r--dbus/dbus-object-tree.h3
-rw-r--r--dbus/dbus-pending-call.c2
-rw-r--r--dbus/dbus-resources.c69
-rw-r--r--dbus/dbus-resources.h4
-rw-r--r--dbus/dbus-server-socket.c3
-rw-r--r--dbus/dbus-signature.c53
-rw-r--r--dbus/dbus-signature.h3
-rw-r--r--dbus/dbus-spawn-win.c54
-rw-r--r--dbus/dbus-spawn.c135
-rw-r--r--dbus/dbus-spawn.h6
-rw-r--r--dbus/dbus-string-private.h16
-rw-r--r--dbus/dbus-string-util.c143
-rw-r--r--dbus/dbus-string.c190
-rw-r--r--dbus/dbus-string.h10
-rw-r--r--dbus/dbus-sysdeps-unix.c21
-rw-r--r--dbus/dbus-sysdeps-unix.h2
-rw-r--r--dbus/dbus-sysdeps-util-unix.c1
-rw-r--r--dbus/dbus-sysdeps.h2
-rw-r--r--dbus/dbus-test.h2
-rw-r--r--dbus/dbus-transport-socket.c6
-rw-r--r--dbus/dbus-transport.c37
-rw-r--r--dbus/dbus-transport.h6
-rw-r--r--dbus/dbus-watch.c17
-rw-r--r--dbus/dbus-watch.h4
-rw-r--r--doc/dbus-specification.xml538
-rw-r--r--test/Makefile.am98
-rw-r--r--test/break-loader.c2
-rw-r--r--test/data/valid-config-files/incoming-limit.conf18
-rw-r--r--test/dbus-daemon-eavesdrop.c558
-rw-r--r--test/dbus-daemon.c77
-rw-r--r--test/marshal.c1
-rw-r--r--test/name-test/Makefile.am69
-rw-r--r--test/name-test/test-privserver-client.c1
-rw-r--r--test/test-service.c9
-rw-r--r--test/test-shell-service.c7
-rw-r--r--test/test-utils.c64
-rw-r--r--tools/Makefile.am45
-rw-r--r--tools/dbus-monitor.c45
-rw-r--r--tools/dbus-viewer.c617
92 files changed, 4017 insertions, 2380 deletions
diff --git a/HACKING b/HACKING
index bebf7ac1..e776fd6d 100644
--- a/HACKING
+++ b/HACKING
@@ -154,6 +154,10 @@ To make a release of D-Bus, do the following:
- update the file NEWS based on the git history
+ - verify that the version number of dbus-specification.xml is
+ changed if it needs to be; if changes have been made, update the
+ release date in that file
+
- update the AUTHORS file with "make update-authors" if necessary
- the version number should have major.minor.micro, even
@@ -175,7 +179,8 @@ To make a release of D-Bus, do the following:
- bump the version number up in configure.ac (so the micro version is odd),
and commit it. Make sure you do this *after* tagging the previous
release! The idea is that git has a newer version number
- than anything released.
+ than anything released. Similarly, bump the version number of
+ dbus-specification.xml and set the release date to "(not finalized)".
- merge the branch you've released to the chronologically-later
branch (usually "master"). You'll probably have to fix a merge
diff --git a/NEWS b/NEWS
index ac7096e2..30435c53 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,8 @@
-D-Bus 1.4.16 (UNRELEASED)
+D-Bus 1.5.8 (UNRELEASED)
==
+• Clean up dead code (fd.o #39231, Simon McVittie)
+
• Add a regression test for fd.o #38005 (fd.o #39836, Simon McVittie)
• Make "NOCONFIGURE=1 ./autogen.sh" not run configure (Colin Walters)
@@ -23,16 +25,35 @@ D-Bus 1.4.16 (UNRELEASED)
C99 meaning (Ralf Habacker)
· Fix misuse of GPid in test/dbus-daemon.c (fd.o #40003, Simon McVittie)
-D-Bus 1.4.14 (2011-07-29)
+D-Bus 1.5.6 (2011-07-29)
==
-The "Puny receptacle!" release.
+The "weird, gravy-like aftertaste" release.
-Changes:
+In addition to new features and refactoring, this release contains all of the
+bugfixes from 1.4.14.
+
+Potentially incompatible (Bustle and similar debugging tools will need
+changes to work as intended):
+
+• Do not allow match rules to "eavesdrop" (receive messages intended for a
+ different recipient) by mistake: eavesdroppers must now opt-in to this
+ behaviour by putting "eavesdrop='true'" in the match rule, which will
+ not have any practical effect on buses where eavesdropping is not allowed
+ (fd.o #37890, Cosimo Alfarano)
+
+Other changes:
+
+• D-Bus Specification version 0.18 (fd.o #37890, fd.o #39450, fd.o #38252;
+ Cosimo Alfarano, Simon McVittie)
+ · add the "eavesdrop" keyword to match rules
+ · define eavesdropping, unicast messages and broadcast messages
+ · stop claiming that match rules are needed to match unicast messages to you
+ · promote the type system to be a top-level section
• Use DBUS_ERROR_OBJECT_PATH_IN_USE if dbus_connection_try_register_object_path
- or dbus_connection_try_register_fallback fails, not ...ADDRESS_IN_USE
- (fd.o #38874, Jiří Klimeš)
+ or dbus_connection_try_register_fallback fails, not ...ADDRESS_IN_USE,
+ and simplify object-path registration (fd.o #38874, Jiří Klimeš)
• Consistently use atomic operations on everything that is ever manipulated
via atomic ops, as was done for changes to DBusConnection's refcount in
@@ -44,6 +65,26 @@ Changes:
• Make "make check" in a clean tree work, by not running tests until
test data has been set up (fd.o #34405, Simon McVittie)
+• The dbus-daemon no longer busy-loops if it has a very large number of file
+ descriptors (fd.o #23194, Simon McVittie)
+
+• Refactor message flow through dispatching to avoid locking violations if
+ the bus daemon's message limit is hit; remove the per-connection link cache,
+ which was meant to improve performance, but now reduces it (fd.o #34393,
+ Simon McVittie)
+
+• Some cmake fixes (Ralf Habacker)
+
+• Remove dead code, mainly from DBusString (fd.o #38570, fd.o #39610;
+ Simon McVittie, Lennart Poettering)
+
+• Stop storing two extra byte order indicators in each D-Bus message
+ (fd.o #38287, Simon McVittie)
+
+• Add an optional Stats interface which can be used to get statistics from
+ a running dbus-daemon if enabled at configure time with --enable-stats
+ (fd.o #34040, Simon McVittie)
+
• Fix various typos (fd.o #27227, fd.o #38284; Sascha Silbe, Simon McVittie)
• Documentation (fd.o #36156, Simon McVittie):
@@ -62,7 +103,7 @@ Changes:
· fix use of a mutex for autolaunch server detection
· don't crash on malloc failure in _dbus_printf_string_upper_bound
-D-Bus 1.4.12 (2011-06-10)
+D-Bus 1.5.4 (2011-06-10)
==
Security (local denial of service):
@@ -103,10 +144,10 @@ Changes:
• Windows-specific changes:
· don't try to build dbus-daemon-launch-helper (fd.o #37838, Mark Brand)
-D-Bus 1.4.10 (2011-06-01)
+D-Bus 1.5.2 (2011-06-01)
==
-The "Ape Ale" release.
+The "Boar Hunter" release.
Notes for distributors:
@@ -120,6 +161,10 @@ Notes for distributors:
Changes:
+ • D-Bus Specification v0.17
+ · Reserve the extra characters used in signatures by GVariant
+ (fd.o #34529, Simon McVittie)
+ · Define the ObjectManager interface (fd.o #34869, David Zeuthen)
• Don't force -fPIE: distributions and libtool know better than we do whether
it's desirable (fd.o #16621, fd.o #27215; Simon McVittie)
• Allow --disable-gc-sections, in case your toolchain offers the
@@ -129,6 +174,8 @@ Changes:
(fd.o #14512; Simon McVittie, loosely based on a patch from Luca Barbato)
• Ensure that maintainers upload documentation with the right permissions
(fd.o #36130, Simon McVittie)
+ • Don't force users of libdbus to be linked against -lpthread, -lrt
+ (fd.o #32827, Simon McVittie)
• Log system-bus activation information to syslog (fd.o #35705,
Colin Walters)
• Log messages dropped due to quotas to syslog (fd.o #35358,
@@ -148,6 +195,28 @@ Changes:
• Windows:
• Remove obsolete workaround for winioctl.h (fd.o #35083, Ralf Habacker)
+D-Bus 1.5.0 (2011-04-11)
+==
+
+The "you never know when you need to tow something from your giant
+flying shark" release.
+
+ • D-Bus Specification v0.16
+ · Add support for path_namespace and arg0namespace in match rules
+ (fd.o #24317, #34870; Will Thompson, David Zeuthen, Simon McVittie)
+ · Make argNpath support object paths, not just object-path-like strings,
+ and document it better (fd.o #31818, Will Thompson)
+ • Let the bus daemon implement more than one interface (fd.o #33757,
+ Simon McVittie)
+ • Optimize _dbus_string_replace_len to reduce waste (fd.o #21261,
+ Roberto Guido)
+ • Require user intervention to compile with missing 64-bit support
+ (fd.o #35114, Simon McVittie)
+ • Add dbus_type_is_valid as public API (fd.o #20496, Simon McVittie)
+ • Raise UnknownObject instead of UnknownMethod for calls to methods on
+ paths that are not part of the object tree, and UnknownInterface for calls
+ to unknown interfaces in the bus daemon (fd.o #34527, Lennart Poettering)
+
D-Bus 1.4.8 (2011-04-08)
==
diff --git a/bus/Makefile.am b/bus/Makefile.am
index a3ddb6cf..6cbc09a6 100644
--- a/bus/Makefile.am
+++ b/bus/Makefile.am
@@ -1,10 +1,30 @@
configdir=$(sysconfdir)/dbus-1
dbus_daemon_execdir = $(DBUS_DAEMONDIR)
-INCLUDES = -I$(top_srcdir) \
- $(DBUS_BUS_CFLAGS) \
+DBUS_BUS_LIBS = \
+ $(XML_LIBS) \
+ $(SELINUX_LIBS) \
+ $(THREAD_LIBS) \
+ $(ADT_LIBS) \
+ $(NETWORK_libs) \
+ $(NULL)
+
+DBUS_LAUNCHER_LIBS = \
+ $(XML_LIBS) \
+ $(THREAD_LIBS) \
+ $(NETWORK_libs) \
+ $(NULL)
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ $(XML_CFLAGS) \
-DDBUS_SYSTEM_CONFIG_FILE=\""$(configdir)/system.conf"\" \
- -DDBUS_COMPILATION
+ -DDBUS_COMPILATION \
+ -DDBUS_STATIC_BUILD \
+ $(NULL)
+
+# if assertions are enabled, improve backtraces
+AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
EFENCE=
@@ -73,6 +93,8 @@ BUS_SOURCES= \
services.h \
signals.c \
signals.h \
+ stats.c \
+ stats.h \
test.c \
test.h \
utils.c \
@@ -83,14 +105,11 @@ dbus_daemon_SOURCES= \
$(BUS_SOURCES) \
main.c
-dbus_daemon_CPPFLAGS = -DDBUS_STATIC_BUILD
dbus_daemon_LDADD= \
$(top_builddir)/dbus/libdbus-internal.la \
$(EFENCE) \
$(DBUS_BUS_LIBS)
-dbus_daemon_LDFLAGS=@R_DYNAMIC_LDFLAG@
-
LAUNCH_HELPER_SOURCES= \
$(XML_SOURCES) \
config-parser-common.c \
@@ -110,13 +129,10 @@ dbus_daemon_launch_helper_SOURCES= \
activation-helper-bin.c \
$(LAUNCH_HELPER_SOURCES)
-dbus_daemon_launch_helper_CPPFLAGS = -DDBUS_STATIC_BUILD
dbus_daemon_launch_helper_LDADD= \
$(top_builddir)/dbus/libdbus-internal.la \
$(DBUS_LAUNCHER_LIBS)
-dbus_daemon_launch_helper_LDFLAGS=@R_DYNAMIC_LDFLAG@
-
## we build another binary so we can do the launch testing without root privs.
## DO NOT INSTALL THIS FILE
dbus_daemon_launch_helper_test_SOURCES= \
@@ -127,8 +143,8 @@ dbus_daemon_launch_helper_test_LDADD= \
$(top_builddir)/dbus/libdbus-internal.la \
$(DBUS_LAUNCHER_LIBS)
-dbus_daemon_launch_helper_test_LDFLAGS=@R_DYNAMIC_LDFLAG@
-dbus_daemon_launch_helper_test_CPPFLAGS= -DDBUS_STATIC_BUILD \
+dbus_daemon_launch_helper_test_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
-DACTIVATION_LAUNCHER_TEST
## we build yet another binary so we can do the OOM tests
@@ -141,8 +157,8 @@ bus_test_launch_helper_LDADD= \
$(top_builddir)/dbus/libdbus-internal.la \
$(DBUS_LAUNCHER_LIBS)
-bus_test_launch_helper_LDFLAGS=@R_DYNAMIC_LDFLAG@
-bus_test_launch_helper_CPPFLAGS= -DDBUS_STATIC_BUILD \
+bus_test_launch_helper_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
-DACTIVATION_LAUNCHER_TEST \
-DACTIVATION_LAUNCHER_DO_OOM
@@ -183,17 +199,13 @@ bus_test_system_SOURCES= \
utils.h \
test-system.c
-bus_test_system_CPPFLAGS = -DDBUS_STATIC_BUILD
bus_test_system_LDADD=$(top_builddir)/dbus/libdbus-internal.la $(DBUS_BUS_LIBS)
-bus_test_system_LDFLAGS=@R_DYNAMIC_LDFLAG@
bus_test_SOURCES= \
$(BUS_SOURCES) \
test-main.c
-bus_test_CPPFLAGS = -DDBUS_STATIC_BUILD
bus_test_LDADD=$(top_builddir)/dbus/libdbus-internal.la $(DBUS_BUS_LIBS)
-bus_test_LDFLAGS=@R_DYNAMIC_LDFLAG@
## mop up the gcov files
clean-local:
diff --git a/bus/activation-helper.c b/bus/activation-helper.c
index baba8f04..7012227e 100644
--- a/bus/activation-helper.c
+++ b/bus/activation-helper.c
@@ -184,6 +184,7 @@ clear_environment (DBusError *error)
static dbus_bool_t
check_permissions (const char *dbus_user, DBusError *error)
{
+#ifndef ACTIVATION_LAUNCHER_TEST
uid_t uid, euid;
struct passwd *pw;
@@ -191,7 +192,6 @@ check_permissions (const char *dbus_user, DBusError *error)
uid = 0;
euid = 0;
-#ifndef ACTIVATION_LAUNCHER_TEST
/* bail out unless the dbus user is invoking the helper */
pw = getpwnam(dbus_user);
if (!pw)
@@ -403,12 +403,15 @@ get_correct_parser (BusConfigParser **parser, DBusError *error)
{
DBusString config_file;
dbus_bool_t retval;
+#ifdef ACTIVATION_LAUNCHER_TEST
const char *test_config_file;
+#endif
retval = FALSE;
- test_config_file = NULL;
#ifdef ACTIVATION_LAUNCHER_TEST
+ test_config_file = NULL;
+
/* there is no _way_ we should be setuid if this define is set.
* but we should be doubly paranoid and check... */
if (getuid() != geteuid())
diff --git a/bus/activation.c b/bus/activation.c
index 3177d023..6101173f 100644
--- a/bus/activation.c
+++ b/bus/activation.c
@@ -143,16 +143,6 @@ bus_pending_activation_entry_free (BusPendingActivationEntry *entry)
dbus_free (entry);
}
-static void
-handle_timeout_callback (DBusTimeout *timeout,
- void *data)
-{
- BusPendingActivation *pending_activation = data;
-
- while (!dbus_timeout_handle (pending_activation->timeout))
- _dbus_wait_for_memory ();
-}
-
static BusPendingActivation *
bus_pending_activation_ref (BusPendingActivation *pending_activation)
{
@@ -179,8 +169,7 @@ bus_pending_activation_unref (BusPendingActivation *pending_activation)
if (pending_activation->timeout_added)
{
_dbus_loop_remove_timeout (bus_context_get_loop (pending_activation->activation->context),
- pending_activation->timeout,
- handle_timeout_callback, pending_activation);
+ pending_activation->timeout);
pending_activation->timeout_added = FALSE;
}
@@ -892,8 +881,6 @@ bus_activation_new (BusContext *context,
DBusError *error)
{
BusActivation *activation;
- DBusList *link;
- char *dir;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -1334,22 +1321,16 @@ handle_servicehelper_exit_error (int exit_code,
}
}
-static dbus_bool_t
-babysitter_watch_callback (DBusWatch *watch,
- unsigned int condition,
- void *data)
+static void
+pending_activation_finished_cb (DBusBabysitter *babysitter,
+ void *data)
{
BusPendingActivation *pending_activation = data;
- dbus_bool_t retval;
- DBusBabysitter *babysitter;
dbus_bool_t uses_servicehelper;
- babysitter = pending_activation->babysitter;
-
+ _dbus_assert (babysitter == pending_activation->babysitter);
_dbus_babysitter_ref (babysitter);
- retval = dbus_watch_handle (watch, condition);
-
/* There are two major cases here; are we the system bus or the session? Here this
* is distinguished by whether or not we use a setuid helper launcher. With the launch helper,
* some process exit codes are meaningful, processed by handle_servicehelper_exit_error.
@@ -1360,15 +1341,7 @@ babysitter_watch_callback (DBusWatch *watch,
*/
uses_servicehelper = bus_context_get_servicehelper (pending_activation->activation->context) != NULL;
- /* FIXME this is broken in the same way that
- * connection watches used to be; there should be
- * a separate callback for status change, instead
- * of doing "if we handled a watch status might
- * have changed"
- *
- * Fixing this lets us move dbus_watch_handle
- * calls into dbus-mainloop.c
- */
+ /* strictly speaking this is redundant with the check in dbus-spawn now */
if (_dbus_babysitter_get_child_exited (babysitter))
{
DBusError error;
@@ -1428,8 +1401,6 @@ babysitter_watch_callback (DBusWatch *watch,
}
_dbus_babysitter_unref (babysitter);
-
- return retval;
}
static dbus_bool_t
@@ -1438,9 +1409,9 @@ add_babysitter_watch (DBusWatch *watch,
{
BusPendingActivation *pending_activation = data;
- return _dbus_loop_add_watch (bus_context_get_loop (pending_activation->activation->context),
- watch, babysitter_watch_callback, pending_activation,
- NULL);
+ return _dbus_loop_add_watch (
+ bus_context_get_loop (pending_activation->activation->context),
+ watch);
}
static void
@@ -1450,7 +1421,7 @@ remove_babysitter_watch (DBusWatch *watch,
BusPendingActivation *pending_activation = data;
_dbus_loop_remove_watch (bus_context_get_loop (pending_activation->activation->context),
- watch, babysitter_watch_callback, pending_activation);
+ watch);
}
static dbus_bool_t
@@ -1698,7 +1669,6 @@ bus_activation_activate_service (BusActivation *activation,
char **envp = NULL;
int argc;
dbus_bool_t retval;
- DBusHashIter iter;
dbus_bool_t was_pending_activation;
DBusString command;
@@ -1860,10 +1830,7 @@ bus_activation_activate_service (BusActivation *activation,
}
if (!_dbus_loop_add_timeout (bus_context_get_loop (activation->context),
- pending_activation->timeout,
- handle_timeout_callback,
- pending_activation,
- NULL))
+ pending_activation->timeout))
{
_dbus_verbose ("Failed to add timeout for pending activation\n");
@@ -2133,6 +2100,10 @@ bus_activation_activate_service (BusActivation *activation,
_dbus_assert (pending_activation->babysitter != NULL);
+ _dbus_babysitter_set_result_function (pending_activation->babysitter,
+ pending_activation_finished_cb,
+ pending_activation);
+
if (!_dbus_babysitter_set_watch_functions (pending_activation->babysitter,
add_babysitter_watch,
remove_babysitter_watch,
diff --git a/bus/bus.c b/bus/bus.c
index f805e3fa..748ee90a 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -103,19 +103,6 @@ server_get_context (DBusServer *server)
}
static dbus_bool_t
-server_watch_callback (DBusWatch *watch,
- unsigned int condition,
- void *data)
-{
- /* FIXME this can be done in dbus-mainloop.c
- * if the code in activation.c for the babysitter
- * watch handler is fixed.
- */
-
- return dbus_watch_handle (watch, condition);
-}
-
-static dbus_bool_t
add_server_watch (DBusWatch *watch,
void *data)
{
@@ -124,9 +111,7 @@ add_server_watch (DBusWatch *watch,
context = server_get_context (server);
- return _dbus_loop_add_watch (context->loop,
- watch, server_watch_callback, server,
- NULL);
+ return _dbus_loop_add_watch (context->loop, watch);
}
static void
@@ -138,17 +123,7 @@ remove_server_watch (DBusWatch *watch,
context = server_get_context (server);
- _dbus_loop_remove_watch (context->loop,
- watch, server_watch_callback, server);
-}
-
-
-static void
-server_timeout_callback (DBusTimeout *timeout,
- void *data)
-{
- /* can return FALSE on OOM but we just let it fire again later */
- dbus_timeout_handle (timeout);
+ _dbus_loop_remove_watch (context->loop, watch);
}
static dbus_bool_t
@@ -160,8 +135,7 @@ add_server_timeout (DBusTimeout *timeout,
context = server_get_context (server);
- return _dbus_loop_add_timeout (context->loop,
- timeout, server_timeout_callback, server, NULL);
+ return _dbus_loop_add_timeout (context->loop, timeout);
}
static void
@@ -173,8 +147,7 @@ remove_server_timeout (DBusTimeout *timeout,
context = server_get_context (server);
- _dbus_loop_remove_timeout (context->loop,
- timeout, server_timeout_callback, server);
+ _dbus_loop_remove_timeout (context->loop, timeout);
}
static void
@@ -508,7 +481,6 @@ process_config_every_time (BusContext *context,
DBusString full_address;
DBusList *link;
DBusList **dirs;
- BusActivation *new_activation;
char *addr;
const char *servicehelper;
char *s;
@@ -715,7 +687,6 @@ bus_context_new (const DBusString *config_file,
dbus_bool_t systemd_activation,
DBusError *error)
{
- DBusString log_prefix;
BusContext *context;
BusConfigParser *parser;
@@ -1320,12 +1291,7 @@ out:
va_end (args);
}
-/* TODO: move to autotools generated config.h like done in cmake */
-#ifndef DBUS_INLINE
-#define DBUS_INLINE inline
-#endif
-
-static DBUS_INLINE const char *
+static inline const char *
nonnull (const char *maybe_null,
const char *if_null)
{
@@ -1425,9 +1391,6 @@ bus_context_check_security_policy (BusContext *context,
dbus_bool_t log;
int type;
dbus_bool_t requested_reply;
- const char *sender_name;
- const char *sender_loginfo;
- const char *proposed_recipient_loginfo;
type = dbus_message_get_type (message);
dest = dbus_message_get_destination (message);
@@ -1593,9 +1556,6 @@ bus_context_check_security_policy (BusContext *context,
proposed_recipient,
message, &toggles, &log))
{
- const char *msg = "Rejected send message, %d matched rules; "
- "type=\"%s\", sender=\"%s\" (%s) interface=\"%s\" member=\"%s\" error name=\"%s\" requested_reply=%d destination=\"%s\" (%s))";
-
complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
"Rejected send message", toggles,
message, sender, proposed_recipient, requested_reply,
diff --git a/bus/config-parser.c b/bus/config-parser.c
index f9432555..c636707f 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -3271,11 +3271,12 @@ test_default_session_servicedirs (void)
DBusList *dirs;
DBusList *link;
DBusString progs;
- const char *common_progs;
int i;
#ifdef DBUS_WIN
+ const char *common_progs;
char buffer[1024];
+
if (_dbus_get_install_root(buffer, sizeof(buffer)))
{
strcat(buffer,DBUS_DATADIR);
@@ -3289,8 +3290,9 @@ test_default_session_servicedirs (void)
if (!_dbus_string_init (&progs))
_dbus_assert_not_reached ("OOM allocating progs");
- common_progs = _dbus_getenv ("CommonProgramFiles");
#ifndef DBUS_UNIX
+ common_progs = _dbus_getenv ("CommonProgramFiles");
+
if (common_progs)
{
if (!_dbus_string_append (&progs, common_progs))
@@ -3411,7 +3413,9 @@ test_default_system_servicedirs (void)
DBusList *dirs;
DBusList *link;
DBusString progs;
+#ifndef DBUS_UNIX
const char *common_progs;
+#endif
int i;
/* On Unix we don't actually use this variable, but it's easier to handle the
@@ -3419,8 +3423,9 @@ test_default_system_servicedirs (void)
if (!_dbus_string_init (&progs))
_dbus_assert_not_reached ("OOM allocating progs");
- common_progs = _dbus_getenv ("CommonProgramFiles");
#ifndef DBUS_UNIX
+ common_progs = _dbus_getenv ("CommonProgramFiles");
+
if (common_progs)
{
if (!_dbus_string_append (&progs, common_progs))
diff --git a/bus/connection.c b/bus/connection.c
index 8e7d222a..81f595d2 100644
--- a/bus/connection.c
+++ b/bus/connection.c
@@ -62,6 +62,16 @@ struct BusConnections
DBusTimeout *expire_timeout; /**< Timeout for expiring incomplete connections. */
int stamp; /**< Incrementing number */
BusExpireList *pending_replies; /**< List of pending replies */
+
+#ifdef DBUS_ENABLE_STATS
+ int total_match_rules;
+ int peak_match_rules;
+ int peak_match_rules_per_conn;
+
+ int total_bus_names;
+ int peak_bus_names;
+ int peak_bus_names_per_conn;
+#endif
};
static dbus_int32_t connection_data_slot = -1;
@@ -87,6 +97,11 @@ typedef struct
long connection_tv_sec; /**< Time when we connected (seconds component) */
long connection_tv_usec; /**< Time when we connected (microsec component) */
int stamp; /**< connections->stamp last time we were traversed */
+
+#ifdef DBUS_ENABLE_STATS
+ int peak_match_rules;
+ int peak_bus_names;
+#endif
} BusConnectionData;
static dbus_bool_t bus_pending_reply_expired (BusExpireList *list,
@@ -295,30 +310,12 @@ bus_connection_disconnected (DBusConnection *connection)
}
static dbus_bool_t
-connection_watch_callback (DBusWatch *watch,
- unsigned int condition,
- void *data)
-{
- /* FIXME this can be done in dbus-mainloop.c
- * if the code in activation.c for the babysitter
- * watch handler is fixed.
- */
-
-#if 0
- _dbus_verbose ("Calling handle_watch\n");
-#endif
- return dbus_watch_handle (watch, condition);
-}
-
-static dbus_bool_t
add_connection_watch (DBusWatch *watch,
void *data)
{
DBusConnection *connection = data;
- return _dbus_loop_add_watch (connection_get_loop (connection),
- watch, connection_watch_callback, connection,
- NULL);
+ return _dbus_loop_add_watch (connection_get_loop (connection), watch);
}
static void
@@ -327,18 +324,7 @@ remove_connection_watch (DBusWatch *watch,
{
DBusConnection *connection = data;
- _dbus_loop_remove_watch (connection_get_loop (connection),
- watch, connection_watch_callback, connection);
-}
-
-static void
-connection_timeout_callback (DBusTimeout *timeout,
- void *data)
-{
- /* DBusConnection *connection = data; */
-
- /* can return FALSE on OOM but we just let it fire again later */
- dbus_timeout_handle (timeout);
+ _dbus_loop_remove_watch (connection_get_loop (connection), watch);
}
static dbus_bool_t
@@ -347,8 +333,7 @@ add_connection_timeout (DBusTimeout *timeout,
{
DBusConnection *connection = data;
- return _dbus_loop_add_timeout (connection_get_loop (connection),
- timeout, connection_timeout_callback, connection, NULL);
+ return _dbus_loop_add_timeout (connection_get_loop (connection), timeout);
}
static void
@@ -357,8 +342,7 @@ remove_connection_timeout (DBusTimeout *timeout,
{
DBusConnection *connection = data;
- _dbus_loop_remove_timeout (connection_get_loop (connection),
- timeout, connection_timeout_callback, connection);
+ _dbus_loop_remove_timeout (connection_get_loop (connection), timeout);
}
static void
@@ -460,8 +444,7 @@ bus_connections_new (BusContext *context)
goto failed_4;
if (!_dbus_loop_add_timeout (bus_context_get_loop (context),
- connections->expire_timeout,
- call_timeout_callback, NULL, NULL))
+ connections->expire_timeout))
goto failed_5;
connections->refcount = 1;
@@ -532,8 +515,7 @@ bus_connections_unref (BusConnections *connections)
bus_expire_list_free (connections->pending_replies);
_dbus_loop_remove_timeout (bus_context_get_loop (connections->context),
- connections->expire_timeout,
- call_timeout_callback, NULL);
+ connections->expire_timeout);
_dbus_timeout_unref (connections->expire_timeout);
@@ -1224,6 +1206,16 @@ bus_connection_send_oom_error (DBusConnection *connection,
d->oom_preallocated = NULL;
}
+#ifdef DBUS_ENABLE_STATS
+static void
+update_peak (int *peak,
+ int n)
+{
+ if (*peak < n)
+ *peak = n;
+}
+#endif
+
void
bus_connection_add_match_rule_link (DBusConnection *connection,
DBusList *link)
@@ -1236,6 +1228,15 @@ bus_connection_add_match_rule_link (DBusConnection *connection,
_dbus_list_append_link (&d->match_rules, link);
d->n_match_rules += 1;
+
+#ifdef DBUS_ENABLE_STATS
+ update_peak (&d->peak_match_rules, d->n_match_rules);
+ update_peak (&d->connections->peak_match_rules_per_conn, d->n_match_rules);
+
+ d->connections->total_match_rules += 1;
+ update_peak (&d->connections->peak_match_rules,
+ d->connections->total_match_rules);
+#endif
}
dbus_bool_t
@@ -1267,6 +1268,10 @@ bus_connection_remove_match_rule (DBusConnection *connection,
d->n_match_rules -= 1;
_dbus_assert (d->n_match_rules >= 0);
+
+#ifdef DBUS_ENABLE_STATS
+ d->connections->total_match_rules -= 1;
+#endif
}
int
@@ -1292,6 +1297,16 @@ bus_connection_add_owned_service_link (DBusConnection *connection,
_dbus_list_append_link (&d->services_owned, link);
d->n_services_owned += 1;
+
+#ifdef DBUS_ENABLE_STATS
+ update_peak (&d->peak_bus_names, d->n_services_owned);
+ update_peak (&d->connections->peak_bus_names_per_conn,
+ d->n_services_owned);
+
+ d->connections->total_bus_names += 1;
+ update_peak (&d->connections->peak_bus_names,
+ d->connections->total_bus_names);
+#endif
}
dbus_bool_t
@@ -1323,6 +1338,10 @@ bus_connection_remove_owned_service (DBusConnection *connection,
d->n_services_owned -= 1;
_dbus_assert (d->n_services_owned >= 0);
+
+#ifdef DBUS_ENABLE_STATS
+ d->connections->total_bus_names -= 1;
+#endif
}
int
@@ -2306,3 +2325,71 @@ bus_transaction_add_cancel_hook (BusTransaction *transaction,
return TRUE;
}
+
+#ifdef DBUS_ENABLE_STATS
+int
+bus_connections_get_n_active (BusConnections *connections)
+{
+ return connections->n_completed;
+}
+
+int
+bus_connections_get_n_incomplete (BusConnections *connections)
+{
+ return connections->n_incomplete;
+}
+
+int
+bus_connections_get_total_match_rules (BusConnections *connections)
+{
+ return connections->total_match_rules;
+}
+
+int
+bus_connections_get_peak_match_rules (BusConnections *connections)
+{
+ return connections->peak_match_rules;
+}
+
+int
+bus_connections_get_peak_match_rules_per_conn (BusConnections *connections)
+{
+ return connections->peak_match_rules_per_conn;
+}
+
+int
+bus_connections_get_total_bus_names (BusConnections *connections)
+{
+ return connections->total_bus_names;
+}
+
+int
+bus_connections_get_peak_bus_names (BusConnections *connections)
+{
+ return connections->peak_bus_names;
+}
+
+int
+bus_connections_get_peak_bus_names_per_conn (BusConnections *connections)
+{
+ return connections->peak_bus_names_per_conn;
+}
+
+int
+bus_connection_get_peak_match_rules (DBusConnection *connection)
+{
+ BusConnectionData *d;
+
+ d = BUS_CONNECTION_DATA (connection);
+ return d->peak_match_rules;
+}
+
+int
+bus_connection_get_peak_bus_names (DBusConnection *connection)
+{
+ BusConnectionData *d;
+
+ d = BUS_CONNECTION_DATA (connection);
+ return d->peak_bus_names;
+}
+#endif /* DBUS_ENABLE_STATS */
diff --git a/bus/connection.h b/bus/connection.h
index 4b9a754b..c9360212 100644
--- a/bus/connection.h
+++ b/bus/connection.h
@@ -138,4 +138,17 @@ dbus_bool_t bus_transaction_add_cancel_hook (BusTransaction *
void *data,
DBusFreeFunction free_data_function);
+/* called by stats.c, only present if DBUS_ENABLE_STATS */
+int bus_connections_get_n_active (BusConnections *connections);
+int bus_connections_get_n_incomplete (BusConnections *connections);
+int bus_connections_get_total_match_rules (BusConnections *connections);
+int bus_connections_get_peak_match_rules (BusConnections *connections);
+int bus_connections_get_peak_match_rules_per_conn (BusConnections *connections);
+int bus_connections_get_total_bus_names (BusConnections *connections);
+int bus_connections_get_peak_bus_names (BusConnections *connections);
+int bus_connections_get_peak_bus_names_per_conn (BusConnections *connections);
+
+int bus_connection_get_peak_match_rules (DBusConnection *connection);
+int bus_connection_get_peak_bus_names (DBusConnection *connection);
+
#endif /* BUS_CONNECTION_H */
diff --git a/bus/dir-watch-inotify.c b/bus/dir-watch-inotify.c
index 461b8ee3..2e9be988 100644
--- a/bus/dir-watch-inotify.c
+++ b/bus/dir-watch-inotify.c
@@ -50,12 +50,6 @@ static DBusWatch *watch = NULL;
static DBusLoop *loop = NULL;
static dbus_bool_t
-_inotify_watch_callback (DBusWatch *watch, unsigned int condition, void *data)
-{
- return dbus_watch_handle (watch, condition);
-}
-
-static dbus_bool_t
_handle_inotify_watch (DBusWatch *passed_watch, unsigned int flags, void *data)
{
char buffer[INOTIFY_BUF_LEN];
@@ -204,16 +198,18 @@ _shutdown_inotify (void *data)
_set_watched_dirs_internal (&empty);
- close (inotify_fd);
- inotify_fd = -1;
if (watch != NULL)
{
- _dbus_loop_remove_watch (loop, watch, _inotify_watch_callback, NULL);
+ _dbus_loop_remove_watch (loop, watch);
+ _dbus_watch_invalidate (watch);
_dbus_watch_unref (watch);
_dbus_loop_unref (loop);
}
watch = NULL;
loop = NULL;
+
+ close (inotify_fd);
+ inotify_fd = -1;
}
static int
@@ -250,8 +246,7 @@ _init_inotify (BusContext *context)
goto out;
}
- if (!_dbus_loop_add_watch (loop, watch, _inotify_watch_callback,
- NULL, NULL))
+ if (!_dbus_loop_add_watch (loop, watch))
{
_dbus_warn ("Unable to add reload watch to main loop");
_dbus_watch_unref (watch);
diff --git a/bus/dir-watch-kqueue.c b/bus/dir-watch-kqueue.c
index 4e436eb1..ac6290cc 100644
--- a/bus/dir-watch-kqueue.c
+++ b/bus/dir-watch-kqueue.c
@@ -50,12 +50,6 @@ static DBusWatch *watch = NULL;
static DBusLoop *loop = NULL;
static dbus_bool_t
-_kqueue_watch_callback (DBusWatch *watch, unsigned int condition, void *data)
-{
- return dbus_watch_handle (watch, condition);
-}
-
-static dbus_bool_t
_handle_kqueue_watch (DBusWatch *watch, unsigned int flags, void *data)
{
struct kevent ev;
@@ -80,7 +74,8 @@ _handle_kqueue_watch (DBusWatch *watch, unsigned int flags, void *data)
kq = -1;
if (watch != NULL)
{
- _dbus_loop_remove_watch (loop, watch, _kqueue_watch_callback, NULL);
+ _dbus_loop_remove_watch (loop, watch);
+ _dbus_watch_invalidate (watch);
_dbus_watch_unref (watch);
watch = NULL;
}
@@ -120,14 +115,14 @@ _init_kqueue (BusContext *context)
goto out;
}
- if (!_dbus_loop_add_watch (loop, watch, _kqueue_watch_callback,
- NULL, NULL))
+ if (!_dbus_loop_add_watch (loop, watch))
{
_dbus_warn ("Unable to add reload watch to main loop");
- close (kq);
- kq = -1;
+ _dbus_watch_invalidate (watch);
_dbus_watch_unref (watch);
watch = NULL;
+ close (kq);
+ kq = -1;
goto out;
}
}
diff --git a/bus/dispatch.c b/bus/dispatch.c
index a80476cd..dfe6f746 100644
--- a/bus/dispatch.c
+++ b/bus/dispatch.c
@@ -4773,7 +4773,6 @@ bus_unix_fds_passing_test(const DBusString *test_data_dir)
DBusConnection *foo, *bar;
DBusError error;
DBusMessage *m;
- dbus_bool_t b;
int one[2], two[2], x, y, z;
char r;
diff --git a/bus/driver.c b/bus/driver.c
index cc8d1f26..9ecfd55f 100644
--- a/bus/driver.c
+++ b/bus/driver.c
@@ -30,6 +30,7 @@
#include "services.h"
#include "selinux.h"
#include "signals.h"
+#include "stats.h"
#include "utils.h"
#include <dbus/dbus-string.h>
#include <dbus/dbus-internals.h>
@@ -1644,11 +1645,7 @@ bus_driver_handle_get_id (DBusConnection *connection,
return FALSE;
}
-/* For speed it might be useful to sort this in order of
- * frequency of use (but doesn't matter with only a few items
- * anyhow)
- */
-static struct
+typedef struct
{
const char *name;
const char *in_args;
@@ -1657,7 +1654,13 @@ static struct
BusTransaction *transaction,
DBusMessage *message,
DBusError *error);
-} message_handlers[] = {
+} MessageHandler;
+
+/* For speed it might be useful to sort this in order of
+ * frequency of use (but doesn't matter with only a few items
+ * anyhow)
+ */
+static const MessageHandler dbus_message_handlers[] = {
{ "Hello",
"",
DBUS_TYPE_STRING_AS_STRING,
@@ -1729,7 +1732,52 @@ static struct
{ "GetId",
"",
DBUS_TYPE_STRING_AS_STRING,
- bus_driver_handle_get_id }
+ bus_driver_handle_get_id },
+ { NULL, NULL, NULL, NULL }
+};
+
+static dbus_bool_t bus_driver_handle_introspect (DBusConnection *,
+ BusTransaction *, DBusMessage *, DBusError *);
+
+static const MessageHandler introspectable_message_handlers[] = {
+ { "Introspect", "", DBUS_TYPE_STRING_AS_STRING, bus_driver_handle_introspect },
+ { NULL, NULL, NULL, NULL }
+};
+
+#ifdef DBUS_ENABLE_STATS
+static const MessageHandler stats_message_handlers[] = {
+ { "GetStats", "", "a{sv}", bus_stats_handle_get_stats },
+ { "GetConnectionStats", "s", "a{sv}", bus_stats_handle_get_connection_stats },
+ { NULL, NULL, NULL, NULL }
+};
+#endif
+
+typedef struct {
+ const char *name;
+ const MessageHandler *message_handlers;
+ const char *extra_introspection;
+} InterfaceHandler;
+
+/* These should ideally be sorted by frequency of use, although it
+ * probably doesn't matter with this few items */
+static InterfaceHandler interface_handlers[] = {
+ { DBUS_INTERFACE_DBUS, dbus_message_handlers,
+ " <signal name=\"NameOwnerChanged\">\n"
+ " <arg type=\"s\"/>\n"
+ " <arg type=\"s\"/>\n"
+ " <arg type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NameLost\">\n"
+ " <arg type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NameAcquired\">\n"
+ " <arg type=\"s\"/>\n"
+ " </signal>\n" },
+ { DBUS_INTERFACE_INTROSPECTABLE, introspectable_message_handlers, NULL },
+#ifdef DBUS_ENABLE_STATS
+ { BUS_INTERFACE_STATS, stats_message_handlers, NULL },
+#endif
+ { NULL, NULL, NULL }
};
static dbus_bool_t
@@ -1770,86 +1818,43 @@ write_args_for_direction (DBusString *xml,
dbus_bool_t
bus_driver_generate_introspect_string (DBusString *xml)
{
- int i;
+ const InterfaceHandler *ih;
+ const MessageHandler *mh;
if (!_dbus_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
return FALSE;
if (!_dbus_string_append (xml, "<node>\n"))
return FALSE;
- if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE))
- return FALSE;
- if (!_dbus_string_append (xml, " <method name=\"Introspect\">\n"))
- return FALSE;
- if (!_dbus_string_append_printf (xml, " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING))
- return FALSE;
- if (!_dbus_string_append (xml, " </method>\n"))
- return FALSE;
- if (!_dbus_string_append (xml, " </interface>\n"))
- return FALSE;
- if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n",
- DBUS_INTERFACE_DBUS))
- return FALSE;
-
- i = 0;
- while (i < _DBUS_N_ELEMENTS (message_handlers))
+ for (ih = interface_handlers; ih->name != NULL; ih++)
{
-
- if (!_dbus_string_append_printf (xml, " <method name=\"%s\">\n",
- message_handlers[i].name))
+ if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n",
+ ih->name))
return FALSE;
- if (!write_args_for_direction (xml, message_handlers[i].in_args, TRUE))
- return FALSE;
-
- if (!write_args_for_direction (xml, message_handlers[i].out_args, FALSE))
- return FALSE;
-
- if (!_dbus_string_append (xml, " </method>\n"))
- return FALSE;
-
- ++i;
- }
-
- if (!_dbus_string_append_printf (xml, " <signal name=\"NameOwnerChanged\">\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " </signal>\n"))
- return FALSE;
-
-
-
- if (!_dbus_string_append_printf (xml, " <signal name=\"NameLost\">\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " </signal>\n"))
- return FALSE;
-
+ for (mh = ih->message_handlers; mh->name != NULL; mh++)
+ {
+ if (!_dbus_string_append_printf (xml, " <method name=\"%s\">\n",
+ mh->name))
+ return FALSE;
+ if (!write_args_for_direction (xml, mh->in_args, TRUE))
+ return FALSE;
- if (!_dbus_string_append_printf (xml, " <signal name=\"NameAcquired\">\n"))
- return FALSE;
+ if (!write_args_for_direction (xml, mh->out_args, FALSE))
+ return FALSE;
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
+ if (!_dbus_string_append (xml, " </method>\n"))
+ return FALSE;
+ }
- if (!_dbus_string_append_printf (xml, " </signal>\n"))
- return FALSE;
+ if (ih->extra_introspection != NULL &&
+ !_dbus_string_append (xml, ih->extra_introspection))
+ return FALSE;
- if (!_dbus_string_append (xml, " </interface>\n"))
- return FALSE;
+ if (!_dbus_string_append (xml, " </interface>\n"))
+ return FALSE;
+ }
if (!_dbus_string_append (xml, "</node>\n"))
return FALSE;
@@ -1926,7 +1931,9 @@ bus_driver_handle_message (DBusConnection *connection,
DBusError *error)
{
const char *name, *sender, *interface;
- int i;
+ const InterfaceHandler *ih;
+ const MessageHandler *mh;
+ dbus_bool_t found_interface = FALSE;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -1944,57 +1951,50 @@ bus_driver_handle_message (DBusConnection *connection,
return TRUE; /* we just ignore this */
}
- if (dbus_message_is_method_call (message,
- DBUS_INTERFACE_INTROSPECTABLE,
- "Introspect"))
- return bus_driver_handle_introspect (connection, transaction, message, error);
-
+ /* may be NULL, which means "any interface will do" */
interface = dbus_message_get_interface (message);
- if (interface == NULL)
- interface = DBUS_INTERFACE_DBUS;
_dbus_assert (dbus_message_get_member (message) != NULL);
name = dbus_message_get_member (message);
sender = dbus_message_get_sender (message);
- if (strcmp (interface,
- DBUS_INTERFACE_DBUS) != 0)
- {
- _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
- interface);
- goto unknown;
- }
-
_dbus_verbose ("Driver got a method call: %s\n",
dbus_message_get_member (message));
/* security checks should have kept this from getting here */
_dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
- i = 0;
- while (i < _DBUS_N_ELEMENTS (message_handlers))
+ for (ih = interface_handlers; ih->name != NULL; ih++)
{
- if (strcmp (message_handlers[i].name, name) == 0)
+ if (interface != NULL && strcmp (interface, ih->name) != 0)
+ continue;
+
+ found_interface = TRUE;
+
+ for (mh = ih->message_handlers; mh->name != NULL; mh++)
{
+ if (strcmp (mh->name, name) != 0)
+ continue;
+
_dbus_verbose ("Found driver handler for %s\n", name);
- if (!dbus_message_has_signature (message, message_handlers[i].in_args))
+ if (!dbus_message_has_signature (message, mh->in_args))
{
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
_dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
name, dbus_message_get_signature (message),
- message_handlers[i].in_args);
+ mh->in_args);
dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
"Call to %s has wrong args (%s, expected %s)\n",
name, dbus_message_get_signature (message),
- message_handlers[i].in_args);
+ mh->in_args);
_DBUS_ASSERT_ERROR_IS_SET (error);
return FALSE;
}
- if ((* message_handlers[i].handler) (connection, transaction, message, error))
+ if ((* mh->handler) (connection, transaction, message, error))
{
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
_dbus_verbose ("Driver handler succeeded\n");
@@ -2007,15 +2007,13 @@ bus_driver_handle_message (DBusConnection *connection,
return FALSE;
}
}
-
- ++i;
}
unknown:
_dbus_verbose ("No driver handler for message \"%s\"\n",
name);
- dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD,
+ dbus_set_error (error, found_interface ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_INTERFACE,
"%s does not understand message %s",
DBUS_SERVICE_DBUS, name);
diff --git a/bus/expirelist.c b/bus/expirelist.c
index 946a615c..3c87c119 100644
--- a/bus/expirelist.c
+++ b/bus/expirelist.c
@@ -40,14 +40,6 @@ struct BusExpireList
static dbus_bool_t expire_timeout_handler (void *data);
-static void
-call_timeout_callback (DBusTimeout *timeout,
- void *data)
-{
- /* can return FALSE on OOM but we just let it fire again later */
- dbus_timeout_handle (timeout);
-}
-
BusExpireList*
bus_expire_list_new (DBusLoop *loop,
int expire_after,
@@ -73,9 +65,7 @@ bus_expire_list_new (DBusLoop *loop,
_dbus_timeout_set_enabled (list->timeout, FALSE);
- if (!_dbus_loop_add_timeout (list->loop,
- list->timeout,
- call_timeout_callback, NULL, NULL))
+ if (!_dbus_loop_add_timeout (list->loop, list->timeout))
goto failed;
return list;
@@ -94,8 +84,7 @@ bus_expire_list_free (BusExpireList *list)
{
_dbus_assert (list->items == NULL);
- _dbus_loop_remove_timeout (list->loop, list->timeout,
- call_timeout_callback, NULL);
+ _dbus_loop_remove_timeout (list->loop, list->timeout);
_dbus_timeout_unref (list->timeout);
diff --git a/bus/main.c b/bus/main.c
index 47f38c8c..8a9ffdfe 100644
--- a/bus/main.c
+++ b/bus/main.c
@@ -32,12 +32,12 @@
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h> /* for write() and STDERR_FILENO */
+#endif
#include "selinux.h"
static BusContext *context;
@@ -46,7 +46,7 @@ static int reload_pipe[2];
#define RELOAD_READ_END 0
#define RELOAD_WRITE_END 1
-static void close_reload_pipe (void);
+static void close_reload_pipe (DBusWatch **);
typedef enum
{
@@ -229,7 +229,7 @@ handle_reload_watch (DBusWatch *watch,
_dbus_read_socket (reload_pipe[RELOAD_READ_END], &str, 1) != 1)
{
_dbus_warn ("Couldn't read from reload pipe.\n");
- close_reload_pipe ();
+ close_reload_pipe (&watch);
return TRUE;
}
@@ -284,14 +284,6 @@ handle_reload_watch (DBusWatch *watch,
return TRUE;
}
-static dbus_bool_t
-reload_watch_callback (DBusWatch *watch,
- unsigned int condition,
- void *data)
-{
- return dbus_watch_handle (watch, condition);
-}
-
static void
setup_reload_pipe (DBusLoop *loop)
{
@@ -321,8 +313,7 @@ setup_reload_pipe (DBusLoop *loop)
exit (1);
}
- if (!_dbus_loop_add_watch (loop, watch, reload_watch_callback,
- NULL, NULL))
+ if (!_dbus_loop_add_watch (loop, watch))
{
_dbus_warn ("Unable to add reload watch to main loop: %s\n",
error.message);
@@ -333,8 +324,13 @@ setup_reload_pipe (DBusLoop *loop)
}
static void
-close_reload_pipe (void)
+close_reload_pipe (DBusWatch **watch)
{
+ _dbus_loop_remove_watch (bus_context_get_loop (context), *watch);
+ _dbus_watch_invalidate (*watch);
+ _dbus_watch_unref (*watch);
+ *watch = NULL;
+
_dbus_close_socket (reload_pipe[RELOAD_READ_END], NULL);
reload_pipe[RELOAD_READ_END] = -1;
@@ -356,7 +352,6 @@ main (int argc, char **argv)
int i;
dbus_bool_t print_address;
dbus_bool_t print_pid;
- dbus_bool_t is_session_bus;
int force_fork;
dbus_bool_t systemd_activation;
@@ -374,7 +369,6 @@ main (int argc, char **argv)
print_address = FALSE;
print_pid = FALSE;
- is_session_bus = FALSE;
force_fork = FORK_FOLLOW_CONFIG_FILE;
systemd_activation = FALSE;
diff --git a/bus/signals.c b/bus/signals.c
index c85a88df..28506d3f 100644
--- a/bus/signals.c
+++ b/bus/signals.c
@@ -47,8 +47,11 @@ struct BusMatchRule
int args_len;
};
+#define BUS_MATCH_ARG_NAMESPACE 0x4000000u
#define BUS_MATCH_ARG_IS_PATH 0x8000000u
+#define BUS_MATCH_ARG_FLAGS (BUS_MATCH_ARG_NAMESPACE | BUS_MATCH_ARG_IS_PATH)
+
BusMatchRule*
bus_match_rule_new (DBusConnection *matches_go_to)
{
@@ -135,36 +138,9 @@ match_rule_to_string (BusMatchRule *rule)
if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
{
- if (rule->message_type == DBUS_MESSAGE_TYPE_INVALID)
- {
- if (!_dbus_string_append_printf (&str, "type='INVALID'"))
- goto nomem;
- }
- else if (rule->message_type == DBUS_MESSAGE_TYPE_METHOD_CALL)
- {
- if (!_dbus_string_append_printf (&str, "type='method_call'"))
- goto nomem;
- }
- else if (rule->message_type == DBUS_MESSAGE_TYPE_METHOD_RETURN)
- {
- if (!_dbus_string_append_printf (&str, "type='method_return'"))
- goto nomem;
- }
- else if (rule->message_type == DBUS_MESSAGE_TYPE_ERROR)
- {
- if (!_dbus_string_append_printf (&str, "type='error'"))
- goto nomem;
- }
- else if (rule->message_type == DBUS_MESSAGE_TYPE_SIGNAL)
- {
- if (!_dbus_string_append_printf (&str, "type='signal'"))
- goto nomem;
- }
- else
- {
- if (!_dbus_string_append_printf (&str, "type='%d'", rule->message_type))
- goto nomem;
- }
+ if (!_dbus_string_append_printf (&str, "type='%s'",
+ dbus_message_type_to_string (rule->message_type)))
+ goto nomem;
}
if (rule->flags & BUS_MATCH_INTERFACE)
@@ -203,6 +179,18 @@ match_rule_to_string (BusMatchRule *rule)
goto nomem;
}
+ if (rule->flags & BUS_MATCH_PATH_NAMESPACE)
+ {
+ if (_dbus_string_get_length (&str) > 0)
+ {
+ if (!_dbus_string_append (&str, ","))
+ goto nomem;
+ }
+
+ if (!_dbus_string_append_printf (&str, "path_namespace='%s'", rule->path))
+ goto nomem;
+ }
+
if (rule->flags & BUS_MATCH_SENDER)
{
if (_dbus_string_get_length (&str) > 0)
@@ -227,6 +215,20 @@ match_rule_to_string (BusMatchRule *rule)
goto nomem;
}
+ if (rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING)
+ {
+ if (_dbus_string_get_length (&str) > 0)
+ {
+ if (!_dbus_string_append (&str, ","))
+ goto nomem;
+ }
+
+ if (!_dbus_string_append_printf (&str, "eavesdrop='%s'",
+ (rule->flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING) ?
+ "true" : "false"))
+ goto nomem;
+ }
+
if (rule->flags & BUS_MATCH_ARGS)
{
int i;
@@ -238,7 +240,7 @@ match_rule_to_string (BusMatchRule *rule)
{
if (rule->args[i] != NULL)
{
- dbus_bool_t is_path;
+ dbus_bool_t is_path, is_namespace;
if (_dbus_string_get_length (&str) > 0)
{
@@ -247,10 +249,13 @@ match_rule_to_string (BusMatchRule *rule)
}
is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0;
+ is_namespace = (rule->arg_lens[i] & BUS_MATCH_ARG_NAMESPACE) != 0;
if (!_dbus_string_append_printf (&str,
"arg%d%s='%s'",
- i, is_path ? "path" : "",
+ i,
+ is_path ? "path" :
+ is_namespace ? "namespace" : "",
rule->args[i]))
goto nomem;
}
@@ -363,9 +368,20 @@ bus_match_rule_set_destination (BusMatchRule *rule,
return TRUE;
}
+void
+bus_match_rule_set_client_is_eavesdropping (BusMatchRule *rule,
+ dbus_bool_t is_eavesdropping)
+{
+ if (is_eavesdropping)
+ rule->flags |= BUS_MATCH_CLIENT_IS_EAVESDROPPING;
+ else
+ rule->flags &= ~(BUS_MATCH_CLIENT_IS_EAVESDROPPING);
+}
+
dbus_bool_t
bus_match_rule_set_path (BusMatchRule *rule,
- const char *path)
+ const char *path,
+ dbus_bool_t is_namespace)
{
char *new;
@@ -375,7 +391,13 @@ bus_match_rule_set_path (BusMatchRule *rule,
if (new == NULL)
return FALSE;
- rule->flags |= BUS_MATCH_PATH;
+ rule->flags &= ~(BUS_MATCH_PATH|BUS_MATCH_PATH_NAMESPACE);
+
+ if (is_namespace)
+ rule->flags |= BUS_MATCH_PATH_NAMESPACE;
+ else
+ rule->flags |= BUS_MATCH_PATH;
+
dbus_free (rule->path);
rule->path = new;
@@ -386,7 +408,8 @@ dbus_bool_t
bus_match_rule_set_arg (BusMatchRule *rule,
int arg,
const DBusString *value,
- dbus_bool_t is_path)
+ dbus_bool_t is_path,
+ dbus_bool_t is_namespace)
{
int length;
char *new;
@@ -453,6 +476,9 @@ bus_match_rule_set_arg (BusMatchRule *rule,
if (is_path)
rule->arg_lens[arg] |= BUS_MATCH_ARG_IS_PATH;
+ if (is_namespace)
+ rule->arg_lens[arg] |= BUS_MATCH_ARG_NAMESPACE;
+
/* NULL termination didn't get busted */
_dbus_assert (rule->args[rule->args_len] == NULL);
_dbus_assert (rule->arg_lens[rule->args_len] == 0);
@@ -747,7 +773,8 @@ bus_match_rule_parse_arg_match (BusMatchRule *rule,
const DBusString *value,
DBusError *error)
{
- dbus_bool_t is_path;
+ dbus_bool_t is_path = FALSE;
+ dbus_bool_t is_namespace = FALSE;
DBusString key_str;
unsigned long arg;
int length;
@@ -778,16 +805,34 @@ bus_match_rule_parse_arg_match (BusMatchRule *rule,
goto failed;
}
- if (end != length &&
- ((end + 4) != length ||
- !_dbus_string_ends_with_c_str (&key_str, "path")))
+ if (end != length)
{
- dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
- "Key '%s' in match rule contains junk after argument number. Only 'path' is optionally valid ('arg0path' for example).\n", key);
- goto failed;
- }
+ if ((end + strlen ("path")) == length &&
+ _dbus_string_ends_with_c_str (&key_str, "path"))
+ {
+ is_path = TRUE;
+ }
+ else if (_dbus_string_equal_c_str (&key_str, "arg0namespace"))
+ {
+ int value_len = _dbus_string_get_length (value);
- is_path = end != length;
+ is_namespace = TRUE;
+
+ if (!_dbus_validate_bus_namespace (value, 0, value_len))
+ {
+ dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+ "arg0namespace='%s' is not a valid prefix of a bus name",
+ _dbus_string_get_const_data (value));
+ goto failed;
+ }
+ }
+ else
+ {
+ dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+ "Key '%s' in match rule contains junk after argument number (%u). Only 'arg%upath' (for example) or 'arg0namespace' are valid", key, arg, arg);
+ goto failed;
+ }
+ }
/* If we didn't check this we could allocate a huge amount of RAM */
if (arg > DBUS_MAXIMUM_MATCH_RULE_ARG_NUMBER)
@@ -806,7 +851,7 @@ bus_match_rule_parse_arg_match (BusMatchRule *rule,
goto failed;
}
- if (!bus_match_rule_set_arg (rule, arg, value, is_path))
+ if (!bus_match_rule_set_arg (rule, arg, value, is_path, is_namespace))
{
BUS_SET_OOM (error);
goto failed;
@@ -962,12 +1007,15 @@ bus_match_rule_parse (DBusConnection *matches_go_to,
goto failed;
}
}
- else if (strcmp (key, "path") == 0)
+ else if (strcmp (key, "path") == 0 ||
+ strcmp (key, "path_namespace") == 0)
{
- if (rule->flags & BUS_MATCH_PATH)
+ dbus_bool_t is_namespace = (strcmp (key, "path_namespace") == 0);
+
+ if (rule->flags & (BUS_MATCH_PATH | BUS_MATCH_PATH_NAMESPACE))
{
dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
- "Key %s specified twice in match rule\n", key);
+ "path or path_namespace specified twice in match rule\n");
goto failed;
}
@@ -978,7 +1026,7 @@ bus_match_rule_parse (DBusConnection *matches_go_to,
goto failed;
}
- if (!bus_match_rule_set_path (rule, value))
+ if (!bus_match_rule_set_path (rule, value, is_namespace))
{
BUS_SET_OOM (error);
goto failed;
@@ -1006,6 +1054,31 @@ bus_match_rule_parse (DBusConnection *matches_go_to,
goto failed;
}
}
+ else if (strcmp (key, "eavesdrop") == 0)
+ {
+ /* do not detect "eavesdrop" being used more than once in rule:
+ * 1) it's not possible, it's only in the flags
+ * 2) it might be used twice to disable eavesdropping when it's
+ * automatically added (eg dbus-monitor/bustle) */
+
+ /* we accept only "true|false" as possible values */
+ if ((strcmp (value, "true") == 0))
+ {
+ bus_match_rule_set_client_is_eavesdropping (rule, TRUE);
+ }
+ else if (strcmp (value, "false") == 0)
+ {
+ bus_match_rule_set_client_is_eavesdropping (rule, FALSE);
+ }
+ else
+ {
+ dbus_set_error (error, DBUS_ERROR_MATCH_RULE_INVALID,
+ "eavesdrop='%s' is invalid, "
+ "it should be 'true' or 'false'\n",
+ value);
+ goto failed;
+ }
+ }
else if (strncmp (key, "arg", 3) == 0)
{
if (!bus_match_rule_parse_arg_match (rule, key, &tmp_str, error))
@@ -1315,7 +1388,7 @@ match_rule_equal (BusMatchRule *a,
if ((a->flags & BUS_MATCH_PATH) &&
strcmp (a->path, b->path) != 0)
return FALSE;
-
+
if ((a->flags & BUS_MATCH_INTERFACE) &&
strcmp (a->interface, b->interface) != 0)
return FALSE;
@@ -1328,6 +1401,9 @@ match_rule_equal (BusMatchRule *a,
strcmp (a->destination, b->destination) != 0)
return FALSE;
+ /* we already compared the value of flags, and
+ * BUS_MATCH_CLIENT_IS_EAVESDROPPING does not have another struct member */
+
if (a->flags & BUS_MATCH_ARGS)
{
int i;
@@ -1346,7 +1422,7 @@ match_rule_equal (BusMatchRule *a,
if (a->arg_lens[i] != b->arg_lens[i])
return FALSE;
- length = a->arg_lens[i] & ~BUS_MATCH_ARG_IS_PATH;
+ length = a->arg_lens[i] & ~BUS_MATCH_ARG_FLAGS;
if (a->args[i] != NULL)
{
@@ -1578,12 +1654,24 @@ connection_is_primary_owner (DBusConnection *connection,
}
static dbus_bool_t
+str_has_prefix (const char *str, const char *prefix)
+{
+ size_t prefix_len;
+ prefix_len = strlen (prefix);
+ if (strncmp (str, prefix, prefix_len) == 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static dbus_bool_t
match_rule_matches (BusMatchRule *rule,
DBusConnection *sender,
DBusConnection *addressed_recipient,
DBusMessage *message,
BusMatchFlags already_matched)
{
+ dbus_bool_t wants_to_eavesdrop = FALSE;
int flags;
/* All features of the match rule are AND'd together,
@@ -1598,6 +1686,9 @@ match_rule_matches (BusMatchRule *rule,
/* Don't bother re-matching features we've already checked implicitly. */
flags = rule->flags & (~already_matched);
+ if (flags & BUS_MATCH_CLIENT_IS_EAVESDROPPING)
+ wants_to_eavesdrop = TRUE;
+
if (flags & BUS_MATCH_MESSAGE_TYPE)
{
_dbus_assert (rule->message_type != DBUS_MESSAGE_TYPE_INVALID);
@@ -1651,6 +1742,24 @@ match_rule_matches (BusMatchRule *rule,
}
}
+ /* Note: this part is relevant for eavesdropper rules:
+ * Two cases:
+ * 1) rule has a destination to be matched
+ * (flag BUS_MATCH_DESTINATION present). Rule will match if:
+ * - rule->destination matches the addressed_recipient
+ * AND
+ * - wants_to_eavesdrop=TRUE
+ *
+ * Note: (the case in which addressed_recipient is the actual rule owner
+ * is handled elsewere in dispatch.c:bus_dispatch_matches().
+ *
+ * 2) rule has no destination. Rule will match if:
+ * - message has no specified destination (ie broadcasts)
+ * (Note: this will rule out unicast method calls and unicast signals,
+ * fixing FDO#269748)
+ * OR
+ * - wants_to_eavesdrop=TRUE (destination-catch-all situation)
+ */
if (flags & BUS_MATCH_DESTINATION)
{
const char *destination;
@@ -1659,6 +1768,12 @@ match_rule_matches (BusMatchRule *rule,
destination = dbus_message_get_destination (message);
if (destination == NULL)
+ /* broadcast, but this rule specified a destination: no match */
+ return FALSE;
+
+ /* rule owner does not intend to eavesdrop: we'll deliver only msgs
+ * directed to it, NOT MATCHING */
+ if (!wants_to_eavesdrop)
return FALSE;
if (addressed_recipient == NULL)
@@ -1672,6 +1787,19 @@ match_rule_matches (BusMatchRule *rule,
if (!connection_is_primary_owner (addressed_recipient, rule->destination))
return FALSE;
}
+ } else { /* no destination in rule */
+ dbus_bool_t msg_is_broadcast;
+
+ _dbus_assert (rule->destination == NULL);
+
+ msg_is_broadcast = (dbus_message_get_destination (message) == NULL);
+
+ if (!wants_to_eavesdrop && !msg_is_broadcast)
+ return FALSE;
+
+ /* if we are here rule owner intends to eavesdrop
+ * OR
+ * message is being broadcasted */
}
if (flags & BUS_MATCH_PATH)
@@ -1688,6 +1816,31 @@ match_rule_matches (BusMatchRule *rule,
return FALSE;
}
+ if (flags & BUS_MATCH_PATH_NAMESPACE)
+ {
+ const char *path;
+ int len;
+
+ _dbus_assert (rule->path != NULL);
+
+ path = dbus_message_get_path (message);
+ if (path == NULL)
+ return FALSE;
+
+ if (!str_has_prefix (path, rule->path))
+ return FALSE;
+
+ len = strlen (rule->path);
+
+ /* Check that the actual argument is within the expected
+ * namespace, rather than just starting with that string,
+ * by checking that the matched prefix is followed by a '/'
+ * or the end of the path.
+ */
+ if (path[len] != '\0' && path[len] != '/')
+ return FALSE;
+ }
+
if (flags & BUS_MATCH_ARGS)
{
int i;
@@ -1703,11 +1856,12 @@ match_rule_matches (BusMatchRule *rule,
int current_type;
const char *expected_arg;
int expected_length;
- dbus_bool_t is_path;
+ dbus_bool_t is_path, is_namespace;
expected_arg = rule->args[i];
- expected_length = rule->arg_lens[i] & ~BUS_MATCH_ARG_IS_PATH;
+ expected_length = rule->arg_lens[i] & ~BUS_MATCH_ARG_FLAGS;
is_path = (rule->arg_lens[i] & BUS_MATCH_ARG_IS_PATH) != 0;
+ is_namespace = (rule->arg_lens[i] & BUS_MATCH_ARG_NAMESPACE) != 0;
current_type = dbus_message_iter_get_arg_type (&iter);
@@ -1715,8 +1869,9 @@ match_rule_matches (BusMatchRule *rule,
{
const char *actual_arg;
int actual_length;
-
- if (current_type != DBUS_TYPE_STRING)
+
+ if (current_type != DBUS_TYPE_STRING &&
+ (!is_path || current_type != DBUS_TYPE_OBJECT_PATH))
return FALSE;
actual_arg = NULL;
@@ -1739,6 +1894,32 @@ match_rule_matches (BusMatchRule *rule,
MIN (actual_length, expected_length)) != 0)
return FALSE;
}
+ else if (is_namespace)
+ {
+ if (expected_length > actual_length)
+ return FALSE;
+
+ /* If the actual argument doesn't start with the expected
+ * namespace, then we don't match.
+ */
+ if (memcmp (expected_arg, actual_arg, expected_length) != 0)
+ return FALSE;
+
+ if (expected_length < actual_length)
+ {
+ /* Check that the actual argument is within the expected
+ * namespace, rather than just starting with that string,
+ * by checking that the matched prefix ends in a '.'.
+ *
+ * This doesn't stop "foo.bar." matching "foo.bar..baz"
+ * which is an invalid namespace, but at some point the
+ * daemon can't cover up for broken services.
+ */
+ if (actual_arg[expected_length] != '.')
+ return FALSE;
+ }
+ /* otherwise we had an exact match. */
+ }
else
{
if (expected_length != actual_length ||
@@ -2053,7 +2234,73 @@ test_parsing (void *data)
bus_match_rule_unref (rule);
}
-
+
+ rule = check_parse (TRUE, "arg7path='/foo'");
+ if (rule != NULL)
+ {
+ _dbus_assert (rule->flags = BUS_MATCH_ARGS);
+ _dbus_assert (rule->args != NULL);
+ _dbus_assert (rule->args_len == 8);
+ _dbus_assert (rule->args[7] != NULL);
+ _dbus_assert (rule->args[8] == NULL);
+ _dbus_assert (strcmp (rule->args[7], "/foo") == 0);
+ _dbus_assert ((rule->arg_lens[7] & BUS_MATCH_ARG_IS_PATH)
+ == BUS_MATCH_ARG_IS_PATH);
+
+ bus_match_rule_unref (rule);
+ }
+
+ /* Arg 0 namespace matches */
+ rule = check_parse (TRUE, "arg0namespace='foo'");
+ if (rule != NULL)
+ {
+ _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+ _dbus_assert (rule->args != NULL);
+ _dbus_assert (rule->args_len == 1);
+ _dbus_assert (strcmp (rule->args[0], "foo") == 0);
+ _dbus_assert ((rule->arg_lens[0] & BUS_MATCH_ARG_NAMESPACE)
+ == BUS_MATCH_ARG_NAMESPACE);
+
+ bus_match_rule_unref (rule);
+ }
+
+ rule = check_parse (TRUE, "arg0namespace='foo.bar'");
+ if (rule != NULL)
+ {
+ _dbus_assert (rule->flags == BUS_MATCH_ARGS);
+ _dbus_assert (rule->args != NULL);
+ _dbus_assert (rule->args_len == 1);
+ _dbus_assert (strcmp (rule->args[0], "foo.bar") == 0);
+ _dbus_assert ((rule->arg_lens[0] & BUS_MATCH_ARG_NAMESPACE)
+ == BUS_MATCH_ARG_NAMESPACE);
+
+ bus_match_rule_unref (rule);
+ }
+
+ /* Only arg0namespace is supported. */
+ rule = check_parse (FALSE, "arg1namespace='foo'");
+ _dbus_assert (rule == NULL);
+
+ /* An empty string isn't a valid namespace prefix (you should just not
+ * specify this key at all).
+ */
+ rule = check_parse (FALSE, "arg0namespace=''");
+ _dbus_assert (rule == NULL);
+
+ /* Trailing periods aren't allowed (earlier versions of the arg0namespace
+ * spec allowed a single trailing period, which altered the semantics) */
+ rule = check_parse (FALSE, "arg0namespace='foo.'");
+ _dbus_assert (rule == NULL);
+
+ rule = check_parse (FALSE, "arg0namespace='foo.bar.'");
+ _dbus_assert (rule == NULL);
+
+ rule = check_parse (FALSE, "arg0namespace='foo..'");
+ _dbus_assert (rule == NULL);
+
+ rule = check_parse (FALSE, "arg0namespace='foo.bar..'");
+ _dbus_assert (rule == NULL);
+
/* Too-large argN */
rule = check_parse (FALSE, "arg300='foo'");
_dbus_assert (rule == NULL);
@@ -2074,6 +2321,24 @@ test_parsing (void *data)
rule = check_parse (FALSE, "type='signal',type='method_call'");
_dbus_assert (rule == NULL);
+ rule = check_parse (TRUE, "path_namespace='/foo/bar'");
+ if (rule != NULL)
+ {
+ _dbus_assert (rule->flags == BUS_MATCH_PATH_NAMESPACE);
+ _dbus_assert (rule->path != NULL);
+ _dbus_assert (strcmp (rule->path, "/foo/bar") == 0);
+
+ bus_match_rule_unref (rule);
+ }
+
+ /* Almost a duplicate */
+ rule = check_parse (FALSE, "path='/foo',path_namespace='/foo'");
+ _dbus_assert (rule == NULL);
+
+ /* Trailing / was supported in the initial proposal, but now isn't */
+ rule = check_parse (FALSE, "path_namespace='/foo/'");
+ _dbus_assert (rule == NULL);
+
/* Duplicates with the argN code */
rule = check_parse (FALSE, "arg0='foo',arg0='bar'");
_dbus_assert (rule == NULL);
@@ -2134,6 +2399,7 @@ static struct {
{ "type='method_call',arg0='blah',arg1='baz'", "arg0='blah',arg1='baz',type='method_call'" },
{ "type='method_call',arg3='foosh'", "arg3='foosh',type='method_call'" },
{ "arg3='fool'", "arg3='fool'" },
+ { "arg0namespace='fool'", "arg0namespace='fool'" },
{ "member='food'", "member='food'" }
};
@@ -2203,6 +2469,13 @@ should_match_message_1[] = {
"type='signal',member='Frobated',arg0='foobar'",
"member='Frobated',arg0='foobar'",
"type='signal',arg0='foobar'",
+ /* The definition of argXpath matches says: "As with normal argument matches,
+ * if the argument is exactly equal to the string given in the match rule
+ * then the rule is satisfied." So this should match (even though the
+ * argument is not a valid path)!
+ */
+ "arg0path='foobar'",
+ "arg0namespace='foobar'",
NULL
};
@@ -2221,6 +2494,44 @@ should_not_match_message_1[] = {
"arg0='foobar',arg1='abcdef'",
"arg0='foobar',arg1='abcdef',arg2='abcdefghi',arg3='abcdefghi',arg4='abcdefghi'",
"arg0='foobar',arg1='abcdef',arg4='abcdefghi',arg3='abcdefghi',arg2='abcdefghi'",
+ "arg0path='foo'",
+ "arg0path='foobar/'",
+ "arg1path='3'",
+ "arg0namespace='foo'",
+ "arg0namespace='foo',arg1='abcdef'",
+ "arg0namespace='moo'",
+ NULL
+};
+
+#define EXAMPLE_NAME "com.example.backend.foo"
+
+static const char *
+should_match_message_2[] = {
+ /* EXAMPLE_NAME is in all of these namespaces */
+ "arg0namespace='com.example.backend'",
+ "arg0namespace='com.example'",
+ "arg0namespace='com'",
+
+ /* If the client specifies the name exactly, with no trailing period, then
+ * it should match.
+ */
+ "arg0namespace='com.example.backend.foo'",
+
+ NULL
+};
+
+static const char *
+should_not_match_message_2[] = {
+ /* These are not even prefixes */
+ "arg0namespace='com.example.backend.foo.bar'",
+ "arg0namespace='com.example.backend.foobar'",
+
+ /* These are prefixes, but they're not parent namespaces. */
+ "arg0namespace='com.example.backend.fo'",
+ "arg0namespace='com.example.backen'",
+ "arg0namespace='com.exampl'",
+ "arg0namespace='co'",
+
NULL
};
@@ -2276,7 +2587,7 @@ check_matching (DBusMessage *message,
static void
test_matching (void)
{
- DBusMessage *message1;
+ DBusMessage *message1, *message2;
const char *v_STRING;
dbus_int32_t v_INT32;
@@ -2298,6 +2609,185 @@ test_matching (void)
should_not_match_message_1);
dbus_message_unref (message1);
+
+ message2 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
+ _dbus_assert (message2 != NULL);
+ if (!dbus_message_set_member (message2, "NameOwnerChanged"))
+ _dbus_assert_not_reached ("oom");
+
+ /* Obviously this isn't really a NameOwnerChanged signal. */
+ v_STRING = EXAMPLE_NAME;
+ if (!dbus_message_append_args (message2,
+ DBUS_TYPE_STRING, &v_STRING,
+ NULL))
+ _dbus_assert_not_reached ("oom");
+
+ check_matching (message2, 2,
+ should_match_message_2,
+ should_not_match_message_2);
+
+ dbus_message_unref (message2);
+}
+
+#define PATH_MATCH_RULE "arg0path='/aa/bb/'"
+
+/* This is a list of paths that should be matched by PATH_MATCH_RULE, taken
+ * from the specification. Notice that not all of them are actually legal D-Bus
+ * paths.
+ *
+ * The author of this test takes no responsibility for the semantics of
+ * this match rule key.
+ */
+static const char *paths_that_should_be_matched[] = {
+ "/aa/",
+ "/aa/bb/",
+ "/aa/bb/cc/",
+#define FIRST_VALID_PATH_WHICH_SHOULD_MATCH 3
+ "/",
+ "/aa/bb/cc",
+ NULL
+};
+
+/* These paths should not be matched by PATH_MATCH_RULE. */
+static const char *paths_that_should_not_be_matched[] = {
+ "/aa/b",
+ "/aa",
+ /* or even... */
+ "/aa/bb",
+ NULL
+};
+
+static void
+test_path_match (int type,
+ const char *path,
+ const char *rule_text,
+ BusMatchRule *rule,
+ dbus_bool_t should_match)
+{
+ DBusMessage *message = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
+ dbus_bool_t matched;
+
+ _dbus_assert (message != NULL);
+ if (!dbus_message_set_member (message, "Foo"))
+ _dbus_assert_not_reached ("oom");
+
+ if (!dbus_message_append_args (message,
+ type, &path,
+ NULL))
+ _dbus_assert_not_reached ("oom");
+
+ matched = match_rule_matches (rule, NULL, NULL, message, 0);
+
+ if (matched != should_match)
+ {
+ _dbus_warn ("Expected rule %s to %s message "
+ "with first arg %s of type '%c', failed\n",
+ rule_text,
+ should_match ? "match" : "not match",
+ path,
+ (char) type);
+ exit (1);
+ }
+
+ dbus_message_unref (message);
+}
+
+static void
+test_path_matching (void)
+{
+ BusMatchRule *rule;
+ const char **s;
+
+ rule = check_parse (TRUE, PATH_MATCH_RULE);
+ _dbus_assert (rule != NULL);
+
+ for (s = paths_that_should_be_matched; *s != NULL; s++)
+ test_path_match (DBUS_TYPE_STRING, *s, PATH_MATCH_RULE, rule, TRUE);
+
+ for (s = paths_that_should_be_matched + FIRST_VALID_PATH_WHICH_SHOULD_MATCH;
+ *s != NULL; s++)
+ test_path_match (DBUS_TYPE_OBJECT_PATH, *s, PATH_MATCH_RULE, rule, TRUE);
+
+ for (s = paths_that_should_not_be_matched; *s != NULL; s++)
+ {
+ test_path_match (DBUS_TYPE_STRING, *s, PATH_MATCH_RULE, rule, FALSE);
+ test_path_match (DBUS_TYPE_OBJECT_PATH, *s, PATH_MATCH_RULE, rule, FALSE);
+ }
+
+ bus_match_rule_unref (rule);
+}
+
+static const char*
+path_namespace_should_match_message_1[] = {
+ "type='signal',path_namespace='/foo'",
+ "type='signal',path_namespace='/foo/TheObjectManager'",
+ NULL
+};
+
+static const char*
+path_namespace_should_not_match_message_1[] = {
+ "type='signal',path_namespace='/bar'",
+ "type='signal',path_namespace='/bar/TheObjectManager'",
+ NULL
+};
+
+static const char*
+path_namespace_should_match_message_2[] = {
+ "type='signal',path_namespace='/foo/TheObjectManager'",
+ NULL
+};
+
+static const char*
+path_namespace_should_not_match_message_2[] = {
+ NULL
+};
+
+static const char*
+path_namespace_should_match_message_3[] = {
+ NULL
+};
+
+static const char*
+path_namespace_should_not_match_message_3[] = {
+ "type='signal',path_namespace='/foo/TheObjectManager'",
+ NULL
+};
+
+static void
+test_matching_path_namespace (void)
+{
+ DBusMessage *message1;
+ DBusMessage *message2;
+ DBusMessage *message3;
+
+ message1 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
+ _dbus_assert (message1 != NULL);
+ if (!dbus_message_set_path (message1, "/foo/TheObjectManager"))
+ _dbus_assert_not_reached ("oom");
+
+ message2 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
+ _dbus_assert (message2 != NULL);
+ if (!dbus_message_set_path (message2, "/foo/TheObjectManager/child_object"))
+ _dbus_assert_not_reached ("oom");
+
+ message3 = dbus_message_new (DBUS_MESSAGE_TYPE_SIGNAL);
+ _dbus_assert (message3 != NULL);
+ if (!dbus_message_set_path (message3, "/foo/TheObjectManagerOther"))
+ _dbus_assert_not_reached ("oom");
+
+ check_matching (message1, 1,
+ path_namespace_should_match_message_1,
+ path_namespace_should_not_match_message_1);
+ check_matching (message2, 2,
+ path_namespace_should_match_message_2,
+ path_namespace_should_not_match_message_2);
+ check_matching (message3, 3,
+ path_namespace_should_match_message_3,
+ path_namespace_should_not_match_message_3);
+
+ dbus_message_unref (message3);
+ dbus_message_unref (message2);
+ dbus_message_unref (message1);
}
dbus_bool_t
@@ -2314,9 +2804,10 @@ bus_signals_test (const DBusString *test_data_dir)
_dbus_assert_not_reached ("Parsing match rules test failed");
test_equality ();
-
test_matching ();
-
+ test_path_matching ();
+ test_matching_path_namespace ();
+
return TRUE;
}
diff --git a/bus/signals.h b/bus/signals.h
index eeb1d2d0..a71d2e45 100644
--- a/bus/signals.h
+++ b/bus/signals.h
@@ -31,13 +31,15 @@
typedef enum
{
- BUS_MATCH_MESSAGE_TYPE = 1 << 0,
- BUS_MATCH_INTERFACE = 1 << 1,
- BUS_MATCH_MEMBER = 1 << 2,
- BUS_MATCH_SENDER = 1 << 3,
- BUS_MATCH_DESTINATION = 1 << 4,
- BUS_MATCH_PATH = 1 << 5,
- BUS_MATCH_ARGS = 1 << 6
+ BUS_MATCH_MESSAGE_TYPE = 1 << 0,
+ BUS_MATCH_INTERFACE = 1 << 1,
+ BUS_MATCH_MEMBER = 1 << 2,
+ BUS_MATCH_SENDER = 1 << 3,
+ BUS_MATCH_DESTINATION = 1 << 4,
+ BUS_MATCH_PATH = 1 << 5,
+ BUS_MATCH_ARGS = 1 << 6,
+ BUS_MATCH_PATH_NAMESPACE = 1 << 7,
+ BUS_MATCH_CLIENT_IS_EAVESDROPPING = 1 << 8
} BusMatchFlags;
BusMatchRule* bus_match_rule_new (DBusConnection *matches_go_to);
@@ -55,11 +57,21 @@ dbus_bool_t bus_match_rule_set_sender (BusMatchRule *rule,
dbus_bool_t bus_match_rule_set_destination (BusMatchRule *rule,
const char *destination);
dbus_bool_t bus_match_rule_set_path (BusMatchRule *rule,
- const char *path);
+ const char *path,
+ dbus_bool_t is_namespace);
dbus_bool_t bus_match_rule_set_arg (BusMatchRule *rule,
int arg,
const DBusString *value,
- dbus_bool_t is_path);
+ dbus_bool_t is_path,
+ dbus_bool_t is_namespace);
+
+/* Calling this methods a client declares that it is creating a rule which
+ * needs to eavesdrop (e.g., dbus-monitor), any other created rules not
+ * setting themselves as eavesdropping won't receive any message not addressed
+ * to them, when eavedrop is enabled in the policy. On the other hand, when
+ * eavedrop is not enabled in policy, this method won't have any effect */
+void bus_match_rule_set_client_is_eavesdropping (BusMatchRule *rule,
+ dbus_bool_t is_eavesdropping);
BusMatchRule* bus_match_rule_parse (DBusConnection *matches_go_to,
const DBusString *rule_text,
diff --git a/bus/stats.c b/bus/stats.c
new file mode 100644
index 00000000..28fd49ba
--- /dev/null
+++ b/bus/stats.c
@@ -0,0 +1,352 @@
+/* stats.c - statistics from the bus driver
+ *
+ * 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 "stats.h"
+
+#include <dbus/dbus-internals.h>
+#include <dbus/dbus-connection-internal.h>
+
+#include "connection.h"
+#include "services.h"
+#include "utils.h"
+
+#ifdef DBUS_ENABLE_STATS
+
+static DBusMessage *
+new_asv_reply (DBusMessage *message,
+ DBusMessageIter *iter,
+ DBusMessageIter *arr_iter)
+{
+ DBusMessage *reply = dbus_message_new_method_return (message);
+
+ if (reply == NULL)
+ return NULL;
+
+ dbus_message_iter_init_append (reply, iter);
+
+ if (!dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{sv}",
+ arr_iter))
+ {
+ dbus_message_unref (reply);
+ return NULL;
+ }
+
+ return reply;
+}
+
+static dbus_bool_t
+open_asv_entry (DBusMessageIter *arr_iter,
+ DBusMessageIter *entry_iter,
+ const char *key,
+ const char *type,
+ DBusMessageIter *var_iter)
+{
+ if (!dbus_message_iter_open_container (arr_iter, DBUS_TYPE_DICT_ENTRY,
+ NULL, entry_iter))
+ return FALSE;
+
+ if (!dbus_message_iter_append_basic (entry_iter, DBUS_TYPE_STRING, &key))
+ {
+ dbus_message_iter_abandon_container (arr_iter, entry_iter);
+ return FALSE;
+ }
+
+ if (!dbus_message_iter_open_container (entry_iter, DBUS_TYPE_VARIANT,
+ type, var_iter))
+ {
+ dbus_message_iter_abandon_container (arr_iter, entry_iter);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static dbus_bool_t
+close_asv_entry (DBusMessageIter *arr_iter,
+ DBusMessageIter *entry_iter,
+ DBusMessageIter *var_iter)
+{
+ if (!dbus_message_iter_close_container (entry_iter, var_iter))
+ {
+ dbus_message_iter_abandon_container (arr_iter, entry_iter);
+ return FALSE;
+ }
+
+ if (!dbus_message_iter_close_container (arr_iter, entry_iter))
+ return FALSE;
+
+ return TRUE;
+}
+
+static dbus_bool_t
+close_asv_reply (DBusMessageIter *iter,
+ DBusMessageIter *arr_iter)
+{
+ return dbus_message_iter_close_container (iter, arr_iter);
+}
+
+static void
+abandon_asv_entry (DBusMessageIter *arr_iter,
+ DBusMessageIter *entry_iter,
+ DBusMessageIter *var_iter)
+{
+ dbus_message_iter_abandon_container (entry_iter, var_iter);
+ dbus_message_iter_abandon_container (arr_iter, entry_iter);
+}
+
+static void
+abandon_asv_reply (DBusMessageIter *iter,
+ DBusMessageIter *arr_iter)
+{
+ dbus_message_iter_abandon_container (iter, arr_iter);
+}
+
+static dbus_bool_t
+asv_add_uint32 (DBusMessageIter *iter,
+ DBusMessageIter *arr_iter,
+ const char *key,
+ dbus_uint32_t value)
+{
+ DBusMessageIter entry_iter, var_iter;
+
+ if (!open_asv_entry (arr_iter, &entry_iter, key, DBUS_TYPE_UINT32_AS_STRING,
+ &var_iter))
+ goto oom;
+
+ if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_UINT32,
+ &value))
+ {
+ abandon_asv_entry (arr_iter, &entry_iter, &var_iter);
+ goto oom;
+ }
+
+ if (!close_asv_entry (arr_iter, &entry_iter, &var_iter))
+ goto oom;
+
+ return TRUE;
+
+oom:
+ abandon_asv_reply (iter, arr_iter);
+ return FALSE;
+}
+
+static dbus_bool_t
+asv_add_string (DBusMessageIter *iter,
+ DBusMessageIter *arr_iter,
+ const char *key,
+ const char *value)
+{
+ DBusMessageIter entry_iter, var_iter;
+
+ if (!open_asv_entry (arr_iter, &entry_iter, key, DBUS_TYPE_STRING_AS_STRING,
+ &var_iter))
+ goto oom;
+
+ if (!dbus_message_iter_append_basic (&var_iter, DBUS_TYPE_STRING,
+ &value))
+ {
+ abandon_asv_entry (arr_iter, &entry_iter, &var_iter);
+ goto oom;
+ }
+
+ if (!close_asv_entry (arr_iter, &entry_iter, &var_iter))
+ goto oom;
+
+ return TRUE;
+
+oom:
+ abandon_asv_reply (iter, arr_iter);
+ return FALSE;
+}
+
+dbus_bool_t
+bus_stats_handle_get_stats (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ BusConnections *connections;
+ DBusMessage *reply = NULL;
+ DBusMessageIter iter, arr_iter;
+ static dbus_uint32_t stats_serial = 0;
+ dbus_uint32_t in_use, in_free_list, allocated;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ connections = bus_transaction_get_connections (transaction);
+
+ reply = new_asv_reply (message, &iter, &arr_iter);
+
+ if (reply == NULL)
+ goto oom;
+
+ /* Globals */
+
+ if (!asv_add_uint32 (&iter, &arr_iter, "Serial", stats_serial++))
+ goto oom;
+
+ _dbus_list_get_stats (&in_use, &in_free_list, &allocated);
+ if (!asv_add_uint32 (&iter, &arr_iter, "ListMemPoolUsedBytes", in_use) ||
+ !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolCachedBytes",
+ in_free_list) ||
+ !asv_add_uint32 (&iter, &arr_iter, "ListMemPoolAllocatedBytes",
+ allocated))
+ goto oom;
+
+ /* Connections */
+
+ if (!asv_add_uint32 (&iter, &arr_iter, "ActiveConnections",
+ bus_connections_get_n_active (connections)) ||
+ !asv_add_uint32 (&iter, &arr_iter, "IncompleteConnections",
+ bus_connections_get_n_incomplete (connections)) ||
+ !asv_add_uint32 (&iter, &arr_iter, "MatchRules",
+ bus_connections_get_total_match_rules (connections)) ||
+ !asv_add_uint32 (&iter, &arr_iter, "PeakMatchRules",
+ bus_connections_get_peak_match_rules (connections)) ||
+ !asv_add_uint32 (&iter, &arr_iter, "PeakMatchRulesPerConnection",
+ bus_connections_get_peak_match_rules_per_conn (connections)) ||
+ !asv_add_uint32 (&iter, &arr_iter, "BusNames",
+ bus_connections_get_total_bus_names (connections)) ||
+ !asv_add_uint32 (&iter, &arr_iter, "PeakBusNames",
+ bus_connections_get_peak_bus_names (connections)) ||
+ !asv_add_uint32 (&iter, &arr_iter, "PeakBusNamesPerConnection",
+ bus_connections_get_peak_bus_names_per_conn (connections)))
+ goto oom;
+
+ /* end */
+
+ if (!close_asv_reply (&iter, &arr_iter))
+ goto oom;
+
+ if (!bus_transaction_send_from_driver (transaction, connection, reply))
+ goto oom;
+
+ dbus_message_unref (reply);
+ return TRUE;
+
+oom:
+ if (reply != NULL)
+ dbus_message_unref (reply);
+
+ BUS_SET_OOM (error);
+ return FALSE;
+}
+
+dbus_bool_t
+bus_stats_handle_get_connection_stats (DBusConnection *caller_connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error)
+{
+ const char *bus_name = NULL;
+ DBusString bus_name_str;
+ DBusMessage *reply = NULL;
+ DBusMessageIter iter, arr_iter;
+ static dbus_uint32_t stats_serial = 0;
+ dbus_uint32_t in_messages, in_bytes, in_fds, in_peak_bytes, in_peak_fds;
+ dbus_uint32_t out_messages, out_bytes, out_fds, out_peak_bytes, out_peak_fds;
+ BusRegistry *registry;
+ BusService *service;
+ DBusConnection *stats_connection;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+ registry = bus_connection_get_registry (caller_connection);
+
+ if (! dbus_message_get_args (message, error,
+ DBUS_TYPE_STRING, &bus_name,
+ DBUS_TYPE_INVALID))
+ return FALSE;
+
+ _dbus_string_init_const (&bus_name_str, bus_name);
+ service = bus_registry_lookup (registry, &bus_name_str);
+
+ if (service == NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
+ "Bus name '%s' has no owner", bus_name);
+ return FALSE;
+ }
+
+ stats_connection = bus_service_get_primary_owners_connection (service);
+ _dbus_assert (stats_connection != NULL);
+
+ reply = new_asv_reply (message, &iter, &arr_iter);
+
+ if (reply == NULL)
+ goto oom;
+
+ /* Bus daemon per-connection stats */
+
+ if (!asv_add_uint32 (&iter, &arr_iter, "Serial", stats_serial++) ||
+ !asv_add_uint32 (&iter, &arr_iter, "MatchRules",
+ bus_connection_get_n_match_rules (stats_connection)) ||
+ !asv_add_uint32 (&iter, &arr_iter, "PeakMatchRules",
+ bus_connection_get_peak_match_rules (stats_connection)) ||
+ !asv_add_uint32 (&iter, &arr_iter, "BusNames",
+ bus_connection_get_n_services_owned (stats_connection)) ||
+ !asv_add_uint32 (&iter, &arr_iter, "PeakBusNames",
+ bus_connection_get_peak_bus_names (stats_connection)) ||
+ !asv_add_string (&iter, &arr_iter, "UniqueName",
+ bus_connection_get_name (stats_connection)))
+ goto oom;
+
+ /* DBusConnection per-connection stats */
+
+ _dbus_connection_get_stats (stats_connection,
+ &in_messages, &in_bytes, &in_fds,
+ &in_peak_bytes, &in_peak_fds,
+ &out_messages, &out_bytes, &out_fds,
+ &out_peak_bytes, &out_peak_fds);
+
+ if (!asv_add_uint32 (&iter, &arr_iter, "IncomingMessages", in_messages) ||
+ !asv_add_uint32 (&iter, &arr_iter, "IncomingBytes", in_bytes) ||
+ !asv_add_uint32 (&iter, &arr_iter, "IncomingFDs", in_fds) ||
+ !asv_add_uint32 (&iter, &arr_iter, "PeakIncomingBytes", in_peak_bytes) ||
+ !asv_add_uint32 (&iter, &arr_iter, "PeakIncomingFDs", in_peak_fds) ||
+ !asv_add_uint32 (&iter, &arr_iter, "OutgoingMessages", out_messages) ||
+ !asv_add_uint32 (&iter, &arr_iter, "OutgoingBytes", out_bytes) ||
+ !asv_add_uint32 (&iter, &arr_iter, "OutgoingFDs", out_fds) ||
+ !asv_add_uint32 (&iter, &arr_iter, "PeakOutgoingBytes", out_peak_bytes) ||
+ !asv_add_uint32 (&iter, &arr_iter, "PeakOutgoingFDs", out_peak_fds))
+ goto oom;
+
+ /* end */
+
+ if (!close_asv_reply (&iter, &arr_iter))
+ goto oom;
+
+ if (!bus_transaction_send_from_driver (transaction, caller_connection,
+ reply))
+ goto oom;
+
+ dbus_message_unref (reply);
+ return TRUE;
+
+oom:
+ if (reply != NULL)
+ dbus_message_unref (reply);
+
+ BUS_SET_OOM (error);
+ return FALSE;
+}
+
+#endif
diff --git a/bus/stats.h b/bus/stats.h
new file mode 100644
index 00000000..0f843db5
--- /dev/null
+++ b/bus/stats.h
@@ -0,0 +1,38 @@
+/* stats.h - statistics from the bus driver
+ *
+ * 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
+ */
+
+#ifndef BUS_STATS_H
+#define BUS_STATS_H
+
+#include "bus.h"
+
+#define BUS_INTERFACE_STATS "org.freedesktop.DBus.Debug.Stats"
+
+dbus_bool_t bus_stats_handle_get_stats (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
+
+dbus_bool_t bus_stats_handle_get_connection_stats (DBusConnection *connection,
+ BusTransaction *transaction,
+ DBusMessage *message,
+ DBusError *error);
+
+#endif /* multiple-inclusion guard */
diff --git a/bus/test.c b/bus/test.c
index 6efad6e0..049fae6f 100644
--- a/bus/test.c
+++ b/bus/test.c
@@ -37,27 +37,12 @@ static DBusList *clients = NULL;
static DBusLoop *client_loop = NULL;
static dbus_bool_t
-client_watch_callback (DBusWatch *watch,
- unsigned int condition,
- void *data)
-{
- /* FIXME this can be done in dbus-mainloop.c
- * if the code in activation.c for the babysitter
- * watch handler is fixed.
- */
-
- return dbus_watch_handle (watch, condition);
-}
-
-static dbus_bool_t
add_client_watch (DBusWatch *watch,
void *data)
{
DBusConnection *connection = data;
- return _dbus_loop_add_watch (client_loop,
- watch, client_watch_callback, connection,
- NULL);
+ return _dbus_loop_add_watch (client_loop, watch);
}
static void
@@ -66,22 +51,7 @@ remove_client_watch (DBusWatch *watch,
{
DBusConnection *connection = data;
- _dbus_loop_remove_watch (client_loop,
- watch, client_watch_callback, connection);
-}
-
-static void
-client_timeout_callback (DBusTimeout *timeout,
- void *data)
-{
- DBusConnection *connection = data;
-
- dbus_connection_ref (connection);
-
- /* can return FALSE on OOM but we just let it fire again later */
- dbus_timeout_handle (timeout);
-
- dbus_connection_unref (connection);
+ _dbus_loop_remove_watch (client_loop, watch);
}
static dbus_bool_t
@@ -90,7 +60,7 @@ add_client_timeout (DBusTimeout *timeout,
{
DBusConnection *connection = data;
- return _dbus_loop_add_timeout (client_loop, timeout, client_timeout_callback, connection, NULL);
+ return _dbus_loop_add_timeout (client_loop, timeout);
}
static void
@@ -99,7 +69,7 @@ remove_client_timeout (DBusTimeout *timeout,
{
DBusConnection *connection = data;
- _dbus_loop_remove_timeout (client_loop, timeout, client_timeout_callback, connection);
+ _dbus_loop_remove_timeout (client_loop, timeout);
}
static DBusHandlerResult
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 750e3f1a..72c42318 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -38,7 +38,7 @@ if ($ENV{DBUSDIR})
endif ($ENV{DBUSDIR})
if (DBUS_INSTALL_DIR)
- set(CMAKE_INSTALL_PREFIX "${DBUS_INSTALL_DIR}" CACHE TYPE PATH FORCE)
+ set(CMAKE_INSTALL_PREFIX "${DBUS_INSTALL_DIR}" CACHE PATH "install prefix" FORCE)
else (DBUS_INSTALL_DIR)
set(DBUS_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}")
endif (DBUS_INSTALL_DIR)
@@ -92,11 +92,13 @@ find_package(LibExpat)
find_package(X11)
if(NOT WIN32)
- OPTION(DBUS_ENABLE_ABSTRACT_SOCKETS "enable support for abstract sockets" ON)
+ option (DBUS_ENABLE_ABSTRACT_SOCKETS "enable support for abstract sockets" ON)
endif(NOT WIN32)
#AC_ARG_ENABLE(asserts, AS_HELP_STRING([--enable-asserts],[include assertion checks]),enable_asserts=$enableval,enable_asserts=$USE_MAINTAINER_MODE)
-OPTION(DBUS_DISABLE_ASSERTS "Disable assertion checking" OFF)
+option (DBUS_DISABLE_ASSERTS "Disable assertion checking" OFF)
+
+option (DBUS_ENABLE_STATS "enable bus daemon usage statistics" OFF)
option (DBUS_ENABLE_STATS "enable bus daemon usage statistics" OFF)
@@ -113,7 +115,7 @@ SET(DBUS_SOURCE_DIR ${CMAKE_SOURCE_DIR}/..)
include (MacroLibrary)
if(VCS)
- set(DBUS_VERBOSE_C_S 1 CACHE TYPE STRING FORCE)
+ set(DBUS_VERBOSE_C_S 1 CACHE STRING "verbose mode" FORCE)
set(DBUS_VERBOSE_C_S 1)
endif(VCS)
@@ -131,8 +133,8 @@ if(WIN32)
# Use the highest warning level
if (WALL)
- set(WALL 1 CACHE TYPE STRING FORCE)
- set(CMAKE_CXX_WARNING_LEVEL 4 CACHE TYPE STRING FORCE)
+ set(WALL 1 CACHE STRING "all warnings" FORCE)
+ set(CMAKE_CXX_WARNING_LEVEL 4 CACHE STRING "warning level" FORCE)
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
STRING(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
@@ -146,7 +148,7 @@ if(WIN32)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W4")
endif(CMAKE_C_FLAGS MATCHES "/W[0-4]")
else (WALL)
- set(CMAKE_CXX_WARNING_LEVEL 3 CACHE TYPE STRING FORCE)
+ set(CMAKE_CXX_WARNING_LEVEL 3 CACHE STRING "warning level" FORCE)
endif (WALL)
SET(MSVC_W_ERROR " /we4028 /we4013 /we4133 /we4047 /we4031 /we4002 /we4003 /we4114")
@@ -228,24 +230,24 @@ ENABLE_TESTING()
# TODO: take check from configure.in
#AC_ARG_ENABLE(tests, AS_HELP_STRING([--enable-tests],[enable unit test code]),enable_tests=$enableval,enable_tests=$USE_MAINTAINER_MODE)
-OPTION(DBUS_BUILD_TESTS "enable unit test code" ON)
+option (DBUS_BUILD_TESTS "enable unit test code" ON)
if(DBUS_BUILD_TESTS)
add_definitions(-DDBUS_BUILD_TESTS -DDBUS_ENABLE_EMBEDDED_TESTS)
endif(DBUS_BUILD_TESTS)
-OPTION(DBUS_USE_OUTPUT_DEBUG_STRING "enable win32 debug port for message output" OFF)
+option (DBUS_USE_OUTPUT_DEBUG_STRING "enable win32 debug port for message output" OFF)
if(DBUS_USE_OUTPUT_DEBUG_STRING)
add_definitions(-DDBUS_USE_OUTPUT_DEBUG_STRING)
endif(DBUS_USE_OUTPUT_DEBUG_STRING)
if(WIN32)
# win32 dbus service support - this support is not complete
- OPTION(DBUS_SERVICE "enable dbus service installer" OFF)
+ option (DBUS_SERVICE "enable dbus service installer" OFF)
endif(WIN32)
#AC_ARG_ENABLE(ansi, AS_HELP_STRING([--enable-ansi],[enable -ansi -pedantic gcc flags]),enable_ansi=$enableval,enable_ansi=no)
-OPTION(DBUS_ENABLE_ANSI "enable -ansi -pedantic gcc flags" OFF)
+option (DBUS_ENABLE_ANSI "enable -ansi -pedantic gcc flags" OFF)
if(DBUS_ENABLE_ANSI)
if(NOT MSVC)
add_definitions(-ansi -D_POSIX_C_SOURCE=199309L -D_BSD_SOURCE -pedantic)
@@ -255,14 +257,14 @@ if(DBUS_ENABLE_ANSI)
endif(DBUS_ENABLE_ANSI)
#AC_ARG_ENABLE(verbose-mode, AS_HELP_STRING([--enable-verbose-mode],[support verbose debug mode]),enable_verbose_mode=$enableval,enable_verbose_mode=$USE_MAINTAINER_MODE)
-OPTION(DBUS_ENABLE_VERBOSE_MODE "support verbose debug mode" ON)
+option (DBUS_ENABLE_VERBOSE_MODE "support verbose debug mode" ON)
#AC_ARG_ENABLE(checks, AS_HELP_STRING([--enable-checks],[include sanity checks on public API]),enable_checks=$enableval,enable_checks=yes)
-OPTION(DBUS_DISABLE_CHECKS "Disable public API sanity checking" OFF)
+option (DBUS_DISABLE_CHECKS "Disable public API sanity checking" OFF)
if(NOT MSVC)
#AC_ARG_ENABLE(gcov, AS_HELP_STRING([--enable-gcov],[compile with coverage profiling instrumentation (gcc only)]),enable_gcov=$enableval,enable_gcov=no)
- OPTION(DBUS_GCOV_ENABLED "compile with coverage profiling instrumentation (gcc only)" OFF)
+ option (DBUS_GCOV_ENABLED "compile with coverage profiling instrumentation (gcc only)" OFF)
if(DBUS_GCOV_ENABLED)
add_definitions(-fprofile-arcs -ftest-coverage)
# FIXME!!!!
@@ -279,7 +281,7 @@ endif(NOT MSVC)
#AC_ARG_ENABLE(dnotify, AS_HELP_STRING([--enable-dnotify],[build with dnotify support (linux only)]),enable_dnotify=$enableval,enable_dnotify=auto)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
- OPTION(DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX "build with dnotify support (linux only)" ON) # add a check !
+ option (DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX "build with dnotify support (linux only)" ON) # add a check !
endif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
#AC_ARG_ENABLE(kqueue, AS_HELP_STRING([--enable-kqueue],[build with kqueue support (FreeBSD only)]),enable_kqueue=$enableval,enable_kqueue=auto)
@@ -288,9 +290,9 @@ endif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
#AC_ARG_ENABLE(console-owner-file, AS_HELP_STRING([--enable-console-owner-file],[enable console owner file]),enable_console_owner_file=$enableval,enable_console_owner_file=auto)
STRING(TOUPPER ${CMAKE_SYSTEM_NAME} sysname)
if("${sysname}" MATCHES ".*SOLARIS.*")
- OPTION(HAVE_CONSOLE_OWNER_FILE "enable console owner file (solaris only)" ON)
+ option (HAVE_CONSOLE_OWNER_FILE "enable console owner file (solaris only)" ON)
if(HAVE_CONSOLE_OWNER_FILE)
- SET(DBUS_CONSOLE_OWNER_FILE "/dev/console" CACHE STRING "Directory to check for console ownerhip")
+ set (DBUS_CONSOLE_OWNER_FILE "/dev/console" CACHE STRING "Directory to check for console ownerhip")
endif(HAVE_CONSOLE_OWNER_FILE)
endif("${sysname}" MATCHES ".*SOLARIS.*")
@@ -300,9 +302,9 @@ if(NOT LIBXML2_FOUND AND NOT LIBEXPAT_FOUND)
endif(NOT LIBXML2_FOUND AND NOT LIBEXPAT_FOUND)
if(LIBEXPAT_FOUND)
- OPTION(DBUS_USE_EXPAT "Use expat (== ON) or libxml2 (==OFF)" ON)
+ option (DBUS_USE_EXPAT "Use expat (== ON) or libxml2 (==OFF)" ON)
else(LIBEXPAT_FOUND)
- OPTION(DBUS_USE_EXPAT "Use expat (== ON) or libxml2 (==OFF)" OFF)
+ option (DBUS_USE_EXPAT "Use expat (== ON) or libxml2 (==OFF)" OFF)
endif(LIBEXPAT_FOUND)
if(DBUS_USE_EXPAT)
@@ -350,11 +352,11 @@ if(CMAKE_COMPILER_IS_GNUCC AND NOT DBUS_ENABLE_ANSI)
endif(UNAME_EXECUTABLE)
endif(CMAKE_COMPILER_IS_GNUCC AND NOT DBUS_ENABLE_ANSI)
-OPTION(DBUS_HAVE_ATOMIC_INT "Some atomic integer implementation present" ${atomic_int})
-OPTION(DBUS_USE_ATOMIC_INT_486 "Use atomic integer implementation for 486" ${atomic_int_486})
+set (DBUS_HAVE_ATOMIC_INT ${atomic_int} CACHE STRING "Some atomic integer implementation present")
+set (DBUS_USE_ATOMIC_INT_486 ${atomic_int_486} CACHE STRING "Use atomic integer implementation for 486")
if(X11_FOUND)
- OPTION(DBUS_BUILD_X11 "Build with X11 autolaunch support " ON)
+ option (DBUS_BUILD_X11 "Build with X11 autolaunch support " ON)
endif(X11_FOUND)
# test binary names
@@ -444,16 +446,16 @@ set (DBUS_USER )
if (WIN32)
- set (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "nonce-tcp:" CACHE STRING "system bus default address" )
- set (DBUS_SESSION_BUS_DEFAULT_ADDRESS "nonce-tcp:" CACHE STRING "session bus default address" )
+ set (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "nonce-tcp:" CACHE STRING "system bus default address")
+ set (DBUS_SESSION_BUS_DEFAULT_ADDRESS "nonce-tcp:" CACHE STRING "session bus default address")
set (DBUS_SYSTEM_CONFIG_FILE "etc/dbus-1/system.conf")
set (DBUS_SESSION_CONFIG_FILE "etc/dbus-1/session.conf")
# bus-test expects a non empty string
set (DBUS_USER "Administrator")
else (WIN32)
- set (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:tmpdir=" CACHE STRING "system bus default address" )
- set (DBUS_SESSION_BUS_DEFAULT_ADDRESS "unix:path=${DBUS_SESSION_SOCKET_DIR}" CACHE STRING "session bus default address" )
+ set (DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:tmpdir=" CACHE STRING "system bus default address")
+ set (DBUS_SESSION_BUS_DEFAULT_ADDRESS "unix:path=${DBUS_SESSION_SOCKET_DIR}" CACHE STRING "session bus default address")
set (sysconfdir "")
set (configdir ${sysconfdir}/dbus-1 )
set (DBUS_SYSTEM_CONFIG_FILE ${configdir}/system.conf)
@@ -461,7 +463,7 @@ else (WIN32)
set (DBUS_USER "root")
endif (WIN32)
-set(DBUS_DAEMON_NAME dbus-daemon CACHE STRING "The name of the dbus daemon executable")
+set (DBUS_DAEMON_NAME "dbus-daemon" CACHE STRING "The name of the dbus daemon executable")
########### create config.h ###############
@@ -474,7 +476,7 @@ endif(MINGW)
# compiler definitions
add_definitions(-DHAVE_CONFIG_H=1)
-add_definitions(${DBUS_BUS_CFLAGS} -DDBUS_API_SUBJECT_TO_CHANGE)
+add_definitions(${DBUS_BUS_CFLAGS})
if (DBUS_BUILD_TESTS)
@@ -505,8 +507,12 @@ set (DBUS_INTERNAL_LIBRARY_DEFINITIONS "-DDBUS_STATIC_BUILD")
set (DBUS_INTERNAL_CLIENT_DEFINITIONS "-DDBUS_STATIC_BUILD")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h )
+
+if (WIN32)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/dbus-env.bat.cmake ${CMAKE_BINARY_DIR}/bin/dbus-env.bat )
install_files(/bin FILES ${CMAKE_BINARY_DIR}/bin/dbus-env.bat)
+endif()
+
add_definitions(-DHAVE_CONFIG_H=1)
########### subdirs ###############
@@ -617,3 +623,8 @@ endif(DBUS_DISABLE_CHECKS)
MESSAGE(" ")
INCLUDE(modules/CPackInstallConfig.cmake)
+
+add_custom_target(help-options
+ cmake -LH
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+)
diff --git a/cmake/config.h.cmake b/cmake/config.h.cmake
index aa2343ca..b4bfc802 100644
--- a/cmake/config.h.cmake
+++ b/cmake/config.h.cmake
@@ -253,10 +253,8 @@
#define _dbus_verbose_C_S _dbus_verbose
#endif
-#ifdef _MSC_VER
-#define DBUS_INLINE __inline
-#else
-#define DBUS_INLINE inline
+# if defined(_MSC_VER) && !defined(inline)
+#define inline __inline
#endif
#endif // _DBUS_CONFIG_H
diff --git a/cmake/test/CMakeLists.txt b/cmake/test/CMakeLists.txt
index 9a259d22..4ec702d7 100644
--- a/cmake/test/CMakeLists.txt
+++ b/cmake/test/CMakeLists.txt
@@ -2,24 +2,20 @@ project(test)
add_definitions(${DBUS_INTERNAL_CLIENT_DEFINITIONS})
-add_library(dbus_testutils STATIC
+add_library(dbus-testutils STATIC
${CMAKE_SOURCE_DIR}/../test/test-utils.h
${CMAKE_SOURCE_DIR}/../test/test-utils.c
)
-target_link_libraries(dbus_testutils ${DBUS_INTERNAL_LIBRARIES})
+target_link_libraries(dbus-testutils ${DBUS_INTERNAL_LIBRARIES})
add_subdirectory( name-test )
set (test-service_SOURCES
${CMAKE_SOURCE_DIR}/../test/test-service.c
- ${CMAKE_SOURCE_DIR}/../test/test-utils.c
- ${CMAKE_SOURCE_DIR}/../test/test-utils.h
)
set (test-names_SOURCES
${CMAKE_SOURCE_DIR}/../test/test-names.c
- ${CMAKE_SOURCE_DIR}/../test/test-utils.c
- ${CMAKE_SOURCE_DIR}/../test/test-utils.h
)
set (break_loader_SOURCES
@@ -28,8 +24,6 @@ set (break_loader_SOURCES
set (test-shell-service_SOURCES
${CMAKE_SOURCE_DIR}/../test/test-shell-service.c
- ${CMAKE_SOURCE_DIR}/../test/test-utils.c
- ${CMAKE_SOURCE_DIR}/../test/test-utils.h
)
set (shell-test_SOURCES
@@ -53,17 +47,17 @@ set (test-sleep-forever_SOURCES
)
add_executable(test-service ${test-service_SOURCES})
-target_link_libraries(test-service ${DBUS_INTERNAL_LIBRARIES})
+target_link_libraries(test-service dbus-testutils)
add_executable(test-names ${test-names_SOURCES})
-target_link_libraries(test-names ${DBUS_INTERNAL_LIBRARIES})
+target_link_libraries(test-names dbus-testutils)
add_executable(shell-test ${shell-test_SOURCES})
target_link_libraries(shell-test ${DBUS_INTERNAL_LIBRARIES})
ADD_TEST(shell-test ${EXECUTABLE_OUTPUT_PATH}/shell-test${EXT})
add_executable(test-shell-service ${test-shell-service_SOURCES})
-target_link_libraries(test-shell-service ${DBUS_INTERNAL_LIBRARIES})
+target_link_libraries(test-shell-service dbus-testutils)
add_executable(spawn-test ${spawn-test_SOURCES})
target_link_libraries(spawn-test ${DBUS_INTERNAL_LIBRARIES})
diff --git a/cmake/test/name-test/CMakeLists.txt b/cmake/test/name-test/CMakeLists.txt
index 25ec7f65..80b9908b 100644
--- a/cmake/test/name-test/CMakeLists.txt
+++ b/cmake/test/name-test/CMakeLists.txt
@@ -21,19 +21,19 @@ target_link_libraries(test-ids ${DBUS_INTERNAL_LIBRARIES})
ADD_TEST(test-ids ${EXECUTABLE_OUTPUT_PATH}/test-ids)
add_executable(test-shutdown ${NAMEtest-DIR}/test-shutdown.c)
-target_link_libraries(test-shutdown ${DBUS_INTERNAL_LIBRARIES} dbus_testutils)
+target_link_libraries(test-shutdown dbus-testutils)
ADD_TEST(test-shutdown ${EXECUTABLE_OUTPUT_PATH}/test-shutdown)
add_executable(test-privserver ${NAMEtest-DIR}/test-privserver.c)
-target_link_libraries(test-privserver ${DBUS_INTERNAL_LIBRARIES} dbus_testutils)
+target_link_libraries(test-privserver dbus-testutils)
ADD_TEST(test-privserver ${EXECUTABLE_OUTPUT_PATH}/test-privserver)
add_executable(test-privserver-client ${NAMEtest-DIR}/test-privserver-client.c)
-target_link_libraries(test-privserver-client ${DBUS_INTERNAL_LIBRARIES} dbus_testutils)
+target_link_libraries(test-privserver-client dbus-testutils)
ADD_TEST(test-privserver-client ${EXECUTABLE_OUTPUT_PATH}/test-privserver-client)
add_executable(test-autolaunch ${NAMEtest-DIR}/test-autolaunch.c)
-target_link_libraries(test-autolaunch ${DBUS_INTERNAL_LIBRARIES} dbus_testutils)
+target_link_libraries(test-autolaunch dbus-testutils)
ADD_TEST(test-autolaunch ${EXECUTABLE_OUTPUT_PATH}/test-autolaunch)
endif (DBUS_BUILD_TESTS)
diff --git a/cmake/tools/CMakeLists.txt b/cmake/tools/CMakeLists.txt
index e91a5094..101c7e60 100644
--- a/cmake/tools/CMakeLists.txt
+++ b/cmake/tools/CMakeLists.txt
@@ -33,14 +33,6 @@ set (dbus_cleanup_sockets_SOURCES
../../tools/dbus-cleanup-sockets.c
)
-set (dbus_viewer_SOURCES
- ../../tools/dbus-names-model.c
- ../../tools/dbus-names-model.h
- ../../tools/dbus-tree-view.c
- ../../tools/dbus-tree-view.h
- ../../tools/dbus-viewer.c
-)
-
add_executable(dbus-send ${dbus_send_SOURCES})
target_link_libraries(dbus-send ${DBUS_LIBRARIES})
install_targets(/bin dbus-send )
diff --git a/configure.ac b/configure.ac
index ad046e06..10575df5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,8 +2,8 @@ dnl -*- mode: m4 -*-
AC_PREREQ([2.63])
m4_define([dbus_major_version], [1])
-m4_define([dbus_minor_version], [4])
-m4_define([dbus_micro_version], [15])
+m4_define([dbus_minor_version], [5])
+m4_define([dbus_micro_version], [7])
m4_define([dbus_version],
[dbus_major_version.dbus_minor_version.dbus_micro_version])
AC_INIT([dbus],[dbus_version],[https://bugs.freedesktop.org/enter_bug.cgi?product=dbus],[dbus])
@@ -32,16 +32,16 @@ AC_DEFINE_UNQUOTED(DBUS_DAEMON_NAME,"dbus-daemon",[Name of executable])
#
## increment if the interface has additions, changes, removals.
-LT_CURRENT=8
+LT_CURRENT=9
## increment any time the source changes; set to
## 0 if you increment CURRENT
-LT_REVISION=7
+LT_REVISION=3
## increment if any interfaces have been added; set to 0
## if any interfaces have been changed or removed. removal has
## precedence over adding, so set to 0 if both happened.
-LT_AGE=5
+LT_AGE=6
AC_SUBST(LT_CURRENT)
AC_SUBST(LT_REVISION)
@@ -287,6 +287,12 @@ AC_CHECK_SIZEOF(void *)
AC_CHECK_SIZEOF(long long)
AC_CHECK_SIZEOF(__int64)
+AC_ARG_WITH([64-bit],
+ [AS_HELP_STRING([--without-64-bit],
+ [If you have to use this option, please report it as a bug])],
+ [],
+ [with_64_bit=yes])
+
### See what our 64 bit type is called
AC_MSG_CHECKING([64-bit integer type])
@@ -324,13 +330,32 @@ $ac_cv_sizeof___int64)
;;
esac
-if test -z "$dbusint64" ; then
+AS_IF(
+ [test "x$with_64_bit" = xno],
+ [
DBUS_INT64_TYPE="no_int64_type_detected"
DBUS_HAVE_INT64=0
DBUS_INT64_CONSTANT=
DBUS_UINT64_CONSTANT=
- AC_MSG_RESULT([none found])
-else
+ AC_MSG_RESULT([disabled via --without-64-bit])
+ ],
+ dnl else if
+ [test -z "$dbusint64"],
+ [AC_MSG_RESULT([not found])
+ AC_MSG_ERROR([Could not find a 64-bit integer type.
+
+Please report a bug here with details of your platform and compiler:
+
+ http://bugs.freedesktop.org/enter_bug.cgi?product=DBus&component=core
+
+To compile D-Bus with all 64-bit integer types removed (not recommended), use
+the option "--without-64-bit".
+
+This option is likely to be removed in future, unless you report that your
+platform needs it.])
+ ],
+ dnl else
+ [
DBUS_INT64_TYPE="$dbusint64"
DBUS_HAVE_INT64=1
DBUS_INT64_CONSTANT="$dbusint64_constant"
@@ -339,7 +364,7 @@ else
AC_DEFINE_UNQUOTED(DBUS_INT64_PRINTF_MODIFIER, [$dbusint64_printf_modifier], [Define to printf modifier for 64 bit integer type])
fi
AC_MSG_RESULT($DBUS_INT64_TYPE)
-fi
+ ])
AC_SUBST(DBUS_INT64_TYPE)
AC_SUBST(DBUS_INT64_CONSTANT)
@@ -865,6 +890,8 @@ if $dbus_use_libxml; then
XML_LIBS=$LIBXML_LIBS
XML_CFLAGS=$LIBXML_CFLAGS
fi
+AC_SUBST([XML_CFLAGS])
+AC_SUBST([XML_LIBS])
# Thread lib detection
AC_CHECK_FUNC(pthread_cond_timedwait,[AC_CHECK_LIB(pthread,pthread_cond_timedwait,
@@ -895,6 +922,8 @@ fi
fi
LIBS="$save_libs"
+AC_SUBST([THREAD_LIBS])
+
# SELinux detection
if test x$enable_selinux = xno ; then
have_selinux=no;
@@ -1062,7 +1091,9 @@ if test x$have_libaudit = xyes ; then
AC_DEFINE(HAVE_LIBAUDIT,1,[audit daemon SELinux support])
fi
-# Check for ADT API
+AC_SUBST([SELINUX_LIBS])
+
+# Check for ADT API (Solaris Basic Security Mode auditing)
AC_MSG_CHECKING(for ADT API)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <bsm/adt.h>
@@ -1078,6 +1109,7 @@ then
else
AC_MSG_RESULT(no)
fi
+AC_SUBST([ADT_LIBS])
# Check for SCM_RIGHTS
AC_MSG_CHECKING([for SCM_RIGHTS])
@@ -1099,26 +1131,11 @@ if test x$dbus_win = xyes ; then
fi
fi
+AC_SUBST([NETWORK_libs])
+
#### Set up final flags
-DBUS_CLIENT_CFLAGS=
-DBUS_CLIENT_LIBS="$THREAD_LIBS $NETWORK_libs"
-AC_SUBST(DBUS_CLIENT_CFLAGS)
-AC_SUBST(DBUS_CLIENT_LIBS)
-
-DBUS_BUS_CFLAGS="$XML_CFLAGS"
-DBUS_BUS_LIBS="$XML_LIBS $SELINUX_LIBS $THREAD_LIBS $ADT_LIBS $NETWORK_libs"
-AC_SUBST(DBUS_BUS_CFLAGS)
-AC_SUBST(DBUS_BUS_LIBS)
-
-DBUS_LAUNCHER_CFLAGS="$XML_CFLAGS"
-DBUS_LAUNCHER_LIBS="$XML_LIBS $THREAD_LIBS $NETWORK_libs"
-AC_SUBST(DBUS_LAUNCHER_CFLAGS)
-AC_SUBST(DBUS_LAUNCHER_LIBS)
-
-DBUS_TEST_CFLAGS=
-DBUS_TEST_LIBS="$THREAD_LIBS $NETWORK_libs"
-AC_SUBST(DBUS_TEST_CFLAGS)
-AC_SUBST(DBUS_TEST_LIBS)
+LIBDBUS_LIBS="$THREAD_LIBS $NETWORK_libs"
+AC_SUBST([LIBDBUS_LIBS])
### X11 detection
DBUS_X_LIBS=
@@ -1535,6 +1552,15 @@ AH_VERBATIM(_DARWIN_ENVIRON,
#endif
])
+AC_ARG_ENABLE([stats],
+ [AS_HELP_STRING([--enable-stats],
+ [enable bus daemon usage statistics])],
+ [], [enable_stats=no])
+if test "x$enable_stats" = xyes; then
+ AC_DEFINE([DBUS_ENABLE_STATS], [1],
+ [Define to enable bus daemon usage statistics])
+fi
+
AC_CONFIG_FILES([
Doxyfile
dbus/versioninfo.rc
@@ -1610,6 +1636,7 @@ echo "
Building verbose mode: ${enable_verbose_mode}
Building assertions: ${enable_asserts}
Building checks: ${enable_checks}
+ Building bus stats API: ${enable_stats}
Building SELinux support: ${have_selinux}
Building inotify support: ${have_inotify}
Building dnotify support: ${have_dnotify}
@@ -1660,3 +1687,16 @@ if test x$dbus_use_libxml = xtrue; then
echo
echo "WARNING: You have chosen to use libxml as your xml parser however this code path is not maintained by the D-Bus developers and if it breaks you get to keep the pieces. If you have selected this option in err please reconfigure with expat (e.g. --with-xml=expat)."
fi
+
+if test "x$DBUS_HAVE_INT64" = x0; then
+ AC_MSG_WARN([You have disabled 64-bit integers via --without-64-bit.
+
+ This removes parts of the standard D-Bus API and ABI (the 't' and 'x'
+ typecodes, the dbus_int64_t and dbus_uint64_t types, etc.) and should only be
+ used if your compiler lacks support for 64-bit integers. Please report a bug
+ with details of your platform and compiler.
+
+ This option is likely to be removed in future, unless the D-Bus developers
+ receive reports that it is still needed.
+ ])
+fi
diff --git a/dbus-1-uninstalled.pc.in b/dbus-1-uninstalled.pc.in
index 082222d6..f0072325 100644
--- a/dbus-1-uninstalled.pc.in
+++ b/dbus-1-uninstalled.pc.in
@@ -13,5 +13,5 @@ Name: dbus
Description: Free desktop message bus (uninstalled copy)
Version: @VERSION@
Libs: ${abs_top_builddir}/dbus/libdbus-1.la
-Libs.private: @DBUS_CLIENT_LIBS@
+Libs.private: @LIBDBUS_LIBS@
Cflags: -I${abs_top_srcdir}
diff --git a/dbus-1.pc.in b/dbus-1.pc.in
index e3e63c4f..7201e07f 100644
--- a/dbus-1.pc.in
+++ b/dbus-1.pc.in
@@ -12,5 +12,6 @@ daemondir=@DBUS_DAEMONDIR@
Name: dbus
Description: Free desktop message bus
Version: @VERSION@
-Libs: -L${libdir} -ldbus-1 @DBUS_CLIENT_LIBS@
+Libs: -L${libdir} -ldbus-1
+Libs.private: @LIBDBUS_LIBS@
Cflags: -I${includedir}/dbus-1.0 -I${libdir}/dbus-1.0/include
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
index 094773c9..3c44ae49 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -1,12 +1,17 @@
configdir=$(sysconfdir)/dbus-1
-INCLUDES = -I$(top_builddir) -I$(top_srcdir) \
- $(DBUS_CLIENT_CFLAGS) \
+AM_CPPFLAGS = \
+ -I$(top_builddir) \
+ -I$(top_srcdir) \
-DDBUS_COMPILATION \
-DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\" \
-DDBUS_SYSTEM_CONFIG_FILE=\""$(configdir)/system.conf"\" \
- -DDBUS_SESSION_CONFIG_FILE=\""$(configdir)/session.conf"\"
+ -DDBUS_SESSION_CONFIG_FILE=\""$(configdir)/session.conf"\" \
+ $(NULL)
+
+# if assertions are enabled, improve backtraces
+AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
dbusincludedir=$(includedir)/dbus-1.0/dbus
dbusarchincludedir=$(libdir)/dbus-1.0/include/dbus
@@ -27,7 +32,6 @@ dbus_res = versioninfo.o
dbus_res_ldflag = -Wl,$(dbus_res)
no_undefined = -no-undefined
export_symbols =
-export_symvols_internal =
libdbus_1_la_DEPENDENCIES = $(dbus_res)
intllibs =
@@ -39,7 +43,6 @@ no_undefined =
## don't export symbols that start with "_" (we use this
## convention for internal symbols)
export_symbols = -export-symbols-regex "^[^_].*"
-export_symbols_internal =
intllibs = @LTLIBINTL@
@@ -188,9 +191,6 @@ DBUS_LIB_SOURCES= \
dbus-watch.c \
dbus-watch.h
-## dbus-md5.c \
-## dbus-md5.h \
-
### source code that goes in the installed client library
### AND is generic utility functionality used by the
### daemon or test programs (all symbols in here should
@@ -261,13 +261,23 @@ EXTRA_DIST=dbus-arch-deps.h.in
## and is only used for static linking within the dbus package.
noinst_LTLIBRARIES=libdbus-internal.la
-libdbus_1_la_CPPFLAGS= -Ddbus_1_EXPORTS
-libdbus_1_la_LIBADD= $(DBUS_CLIENT_LIBS)
-libdbus_1_la_LDFLAGS= $(export_symbols) -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -no-undefined @R_DYNAMIC_LDFLAG@
-
-libdbus_internal_la_CPPFLAGS = -DDBUS_STATIC_BUILD
-libdbus_internal_la_LIBADD=$(DBUS_CLIENT_LIBS)
-libdbus_internal_la_LDFLAGS=$(export_symbols_internal) @R_DYNAMIC_LDFLAG@
+libdbus_1_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -Ddbus_1_EXPORTS \
+ $(NULL)
+libdbus_1_la_LIBADD= $(LIBDBUS_LIBS)
+libdbus_1_la_LDFLAGS = \
+ $(AM_LDFLAGS) \
+ $(export_symbols) \
+ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+ -no-undefined \
+ $(NULL)
+
+libdbus_internal_la_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -DDBUS_STATIC_BUILD \
+ $(NULL)
+libdbus_internal_la_LIBADD=$(LIBDBUS_LIBS)
noinst_PROGRAMS =
@@ -279,8 +289,7 @@ endif
dbus_test_SOURCES= \
dbus-test-main.c
-dbus_test_LDADD=libdbus-internal.la $(DBUS_TEST_LIBS)
-dbus_test_LDFLAGS=@R_DYNAMIC_LDFLAG@
+dbus_test_LDADD = libdbus-internal.la
## mop up the gcov files
clean-local:
diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
index 8cb82eb8..f05ddea4 100644
--- a/dbus/dbus-bus.c
+++ b/dbus/dbus-bus.c
@@ -661,6 +661,8 @@ dbus_bus_register (DBusConnection *connection,
_dbus_return_val_if_error_is_set (error, FALSE);
retval = FALSE;
+ message = NULL;
+ reply = NULL;
_DBUS_LOCK (bus_datas);
@@ -668,18 +670,16 @@ dbus_bus_register (DBusConnection *connection,
if (bd == NULL)
{
_DBUS_SET_OOM (error);
- _DBUS_UNLOCK (bus_datas);
- return FALSE;
+ goto out;
}
if (bd->unique_name != NULL)
{
_dbus_verbose ("Ignoring attempt to register the same DBusConnection %s with the message bus a second time.\n",
bd->unique_name);
- _DBUS_UNLOCK (bus_datas);
-
/* Success! */
- return TRUE;
+ retval = TRUE;
+ goto out;
}
message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
@@ -690,15 +690,11 @@ dbus_bus_register (DBusConnection *connection,
if (!message)
{
_DBUS_SET_OOM (error);
-
- _DBUS_UNLOCK (bus_datas);
- return FALSE;
+ goto out;
}
reply = dbus_connection_send_with_reply_and_block (connection, message, -1, error);
- dbus_message_unref (message);
-
if (reply == NULL)
goto out;
else if (dbus_set_error_from_message (error, reply))
@@ -718,14 +714,17 @@ dbus_bus_register (DBusConnection *connection,
retval = TRUE;
out:
+ _DBUS_UNLOCK (bus_datas);
+
+ if (message)
+ dbus_message_unref (message);
+
if (reply)
dbus_message_unref (reply);
if (!retval)
_DBUS_ASSERT_ERROR_IS_SET (error);
- _DBUS_UNLOCK (bus_datas);
-
return retval;
}
@@ -1434,11 +1433,17 @@ send_no_return_values (DBusConnection *connection,
* If you pass #NULL for the error, this function will not
* block; the match thus won't be added until you flush the
* connection, and if there's an error adding the match
- * (only possible error is lack of resources in the bus),
- * you won't find out about it.
+ * you won't find out about it. This is generally acceptable, since the
+ * possible errors (including a lack of resources in the bus, the connection
+ * having exceeded its quota of active match rules, or the match rule being
+ * unparseable) are generally unrecoverable.
*
* If you pass non-#NULL for the error this function will
- * block until it gets a reply.
+ * block until it gets a reply. This may be useful when using match rule keys
+ * introduced in recent versions of D-Bus, like 'arg0namespace', to allow the
+ * application to fall back to less efficient match rules supported by older
+ * versions of the daemon if the running version is not new enough; or when
+ * using user-supplied rules rather than rules hard-coded at compile time.
*
* Normal API conventions would have the function return
* a boolean value indicating whether the error was set,
diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h
index cdf3f59d..4cc27610 100644
--- a/dbus/dbus-connection-internal.h
+++ b/dbus/dbus-connection-internal.h
@@ -54,7 +54,7 @@ void _dbus_connection_queue_received_message_link (DBusConnection
DBusList *link);
dbus_bool_t _dbus_connection_has_messages_to_send_unlocked (DBusConnection *connection);
DBusMessage* _dbus_connection_get_message_to_send (DBusConnection *connection);
-void _dbus_connection_message_sent (DBusConnection *connection,
+void _dbus_connection_message_sent_unlocked (DBusConnection *connection,
DBusMessage *message);
dbus_bool_t _dbus_connection_add_watch_unlocked (DBusConnection *connection,
DBusWatch *watch);
@@ -103,6 +103,19 @@ void _dbus_connection_test_get_locks (DBusConnectio
DBusCondVar **dispatch_cond_loc,
DBusCondVar **io_path_cond_loc);
+/* if DBUS_ENABLE_STATS */
+void _dbus_connection_get_stats (DBusConnection *connection,
+ dbus_uint32_t *in_messages,
+ dbus_uint32_t *in_bytes,
+ dbus_uint32_t *in_fds,
+ dbus_uint32_t *in_peak_bytes,
+ dbus_uint32_t *in_peak_fds,
+ dbus_uint32_t *out_messages,
+ dbus_uint32_t *out_bytes,
+ dbus_uint32_t *out_fds,
+ dbus_uint32_t *out_peak_bytes,
+ dbus_uint32_t *out_peak_fds);
+
/* This _dbus_bus_* stuff doesn't really belong here, but dbus-bus-internal.h seems
* silly for one function
*/
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index 8b8310dd..cb1da8c1 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -38,6 +38,7 @@
#include "dbus-protocol.h"
#include "dbus-dataslot.h"
#include "dbus-string.h"
+#include "dbus-signature.h"
#include "dbus-pending-call.h"
#include "dbus-object-tree.h"
#include "dbus-threads-internal.h"
@@ -69,11 +70,7 @@
TOOK_LOCK_CHECK (connection); \
} while (0)
-#define CONNECTION_UNLOCK(connection) do { \
- if (TRACE_LOCKS) { _dbus_verbose ("UNLOCK\n"); } \
- RELEASING_LOCK_CHECK (connection); \
- _dbus_mutex_unlock ((connection)->mutex); \
- } while (0)
+#define CONNECTION_UNLOCK(connection) _dbus_connection_unlock (connection)
#define SLOTS_LOCK(connection) do { \
_dbus_mutex_lock ((connection)->slot_mutex); \
@@ -255,6 +252,7 @@ struct DBusConnection
DBusList *outgoing_messages; /**< Queue of messages we need to send, send the end of the list first. */
DBusList *incoming_messages; /**< Queue of messages we have received, end of the list received most recently. */
+ DBusList *expired_messages; /**< Messages that will be released when we next unlock. */
DBusMessage *message_borrowed; /**< Filled in if the first incoming message has been borrowed;
* dispatch_acquired will be set by the borrower
@@ -289,9 +287,6 @@ struct DBusConnection
DBusDispatchStatus last_dispatch_status; /**< The last dispatch status we reported to the application. */
- DBusList *link_cache; /**< A cache of linked list links to prevent contention
- * for the global linked list mempool lock
- */
DBusObjectTree *objects; /**< Object path handlers registered with this connection */
char *server_guid; /**< GUID of server if we are in shared_connections, #NULL if server GUID is unknown or connection is private */
@@ -389,7 +384,31 @@ _dbus_connection_lock (DBusConnection *connection)
void
_dbus_connection_unlock (DBusConnection *connection)
{
- CONNECTION_UNLOCK (connection);
+ DBusList *expired_messages;
+ DBusList *iter;
+
+ if (TRACE_LOCKS)
+ {
+ _dbus_verbose ("UNLOCK\n");
+ }
+
+ /* If we had messages that expired (fell off the incoming or outgoing
+ * queues) while we were locked, actually release them now */
+ expired_messages = connection->expired_messages;
+ connection->expired_messages = NULL;
+
+ RELEASING_LOCK_CHECK (connection);
+ _dbus_mutex_unlock (connection->mutex);
+
+ for (iter = _dbus_list_pop_first_link (&expired_messages);
+ iter != NULL;
+ iter = _dbus_list_pop_first_link (&expired_messages))
+ {
+ DBusMessage *message = iter->data;
+
+ dbus_message_unref (message);
+ _dbus_list_free_link (iter);
+ }
}
/**
@@ -608,8 +627,8 @@ _dbus_connection_get_message_to_send (DBusConnection *connection)
* @param message the message that was sent.
*/
void
-_dbus_connection_message_sent (DBusConnection *connection,
- DBusMessage *message)
+_dbus_connection_message_sent_unlocked (DBusConnection *connection,
+ DBusMessage *message)
{
DBusList *link;
@@ -624,11 +643,10 @@ _dbus_connection_message_sent (DBusConnection *connection,
_dbus_assert (link != NULL);
_dbus_assert (link->data == message);
- /* Save this link in the link cache */
_dbus_list_unlink (&connection->outgoing_messages,
link);
- _dbus_list_prepend_link (&connection->link_cache, link);
-
+ _dbus_list_prepend_link (&connection->expired_messages, link);
+
connection->n_outgoing -= 1;
_dbus_verbose ("Message %p (%s %s %s %s '%s') removed from outgoing queue %p, %d left to send\n",
@@ -646,12 +664,11 @@ _dbus_connection_message_sent (DBusConnection *connection,
dbus_message_get_signature (message),
connection, connection->n_outgoing);
- /* Save this link in the link cache also */
- _dbus_message_remove_counter (message, connection->outgoing_counter,
- &link);
- _dbus_list_prepend_link (&connection->link_cache, link);
-
- dbus_message_unref (message);
+ /* It's OK that in principle we call the notify function, because for the
+ * outgoing limit, there isn't one */
+ _dbus_message_remove_counter (message, connection->outgoing_counter);
+
+ /* The message will actually be unreffed when we unlock */
}
/** Function to be called in protected_change_watch() with refcount held */
@@ -1923,31 +1940,13 @@ _dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
if (preallocated == NULL)
return NULL;
- if (connection->link_cache != NULL)
- {
- preallocated->queue_link =
- _dbus_list_pop_first_link (&connection->link_cache);
- preallocated->queue_link->data = NULL;
- }
- else
- {
- preallocated->queue_link = _dbus_list_alloc_link (NULL);
- if (preallocated->queue_link == NULL)
- goto failed_0;
- }
-
- if (connection->link_cache != NULL)
- {
- preallocated->counter_link =
- _dbus_list_pop_first_link (&connection->link_cache);
- preallocated->counter_link->data = connection->outgoing_counter;
- }
- else
- {
- preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
- if (preallocated->counter_link == NULL)
- goto failed_1;
- }
+ preallocated->queue_link = _dbus_list_alloc_link (NULL);
+ if (preallocated->queue_link == NULL)
+ goto failed_0;
+
+ preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
+ if (preallocated->counter_link == NULL)
+ goto failed_1;
_dbus_counter_ref (preallocated->counter_link->data);
@@ -1976,6 +1975,8 @@ _dbus_connection_send_preallocated_unlocked_no_update (DBusConnection *con
_dbus_list_prepend_link (&connection->outgoing_messages,
preallocated->queue_link);
+ /* It's OK that we'll never call the notify function, because for the
+ * outgoing limit, there isn't one */
_dbus_message_add_counter_link (message,
preallocated->counter_link);
@@ -2640,9 +2641,7 @@ free_outgoing_message (void *element,
DBusMessage *message = element;
DBusConnection *connection = data;
- _dbus_message_remove_counter (message,
- connection->outgoing_counter,
- NULL);
+ _dbus_message_remove_counter (message, connection->outgoing_counter);
dbus_message_unref (message);
}
@@ -2724,8 +2723,6 @@ _dbus_connection_last_unref (DBusConnection *connection)
_dbus_list_free_link (connection->disconnect_message_link);
}
- _dbus_list_clear (&connection->link_cache);
-
_dbus_condvar_free_at_location (&connection->dispatch_cond);
_dbus_condvar_free_at_location (&connection->io_path_cond);
@@ -3049,7 +3046,7 @@ dbus_connection_can_send_type(DBusConnection *connection,
{
_dbus_return_val_if_fail (connection != NULL, FALSE);
- if (!_dbus_type_is_valid(type))
+ if (!dbus_type_is_valid (type))
return FALSE;
if (type != DBUS_TYPE_UNIX_FD)
@@ -3277,6 +3274,7 @@ reply_handler_timeout (void *data)
DBusPendingCall *pending = data;
connection = _dbus_pending_call_get_connection_and_lock (pending);
+ _dbus_connection_ref_unlocked (connection);
_dbus_pending_call_queue_timeout_error_unlocked (pending,
connection);
@@ -3289,6 +3287,7 @@ reply_handler_timeout (void *data)
/* Unlocks, and calls out to user code */
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
+ dbus_connection_unref (connection);
return TRUE;
}
@@ -4140,7 +4139,7 @@ notify_disconnected_unlocked (DBusConnection *connection)
while ((link = _dbus_list_get_last_link (&connection->outgoing_messages)))
{
- _dbus_connection_message_sent (connection, link->data);
+ _dbus_connection_message_sent_unlocked (connection, link->data);
}
}
}
@@ -4325,44 +4324,48 @@ static DBusHandlerResult
_dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
DBusMessage *message)
{
+ dbus_bool_t sent = FALSE;
+ DBusMessage *ret = NULL;
+ DBusList *expire_link;
+
if (connection->route_peer_messages && dbus_message_get_destination (message) != NULL)
{
/* This means we're letting the bus route this message */
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
- else if (dbus_message_is_method_call (message,
- DBUS_INTERFACE_PEER,
- "Ping"))
+
+ if (!dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
+ {
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ }
+
+ /* Preallocate a linked-list link, so that if we need to dispose of a
+ * message, we can attach it to the expired list */
+ expire_link = _dbus_list_alloc_link (NULL);
+
+ if (!expire_link)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ if (dbus_message_is_method_call (message,
+ DBUS_INTERFACE_PEER,
+ "Ping"))
{
- DBusMessage *ret;
- dbus_bool_t sent;
-
ret = dbus_message_new_method_return (message);
if (ret == NULL)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
+ goto out;
- dbus_message_unref (ret);
-
- if (!sent)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- return DBUS_HANDLER_RESULT_HANDLED;
+ sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
}
else if (dbus_message_is_method_call (message,
DBUS_INTERFACE_PEER,
"GetMachineId"))
{
- DBusMessage *ret;
- dbus_bool_t sent;
DBusString uuid;
ret = dbus_message_new_method_return (message);
if (ret == NULL)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
+ goto out;
- sent = FALSE;
_dbus_string_init (&uuid);
if (_dbus_get_local_machine_uuid_encoded (&uuid))
{
@@ -4375,43 +4378,38 @@ _dbus_connection_peer_filter_unlocked_no_update (DBusConnection *connection,
}
}
_dbus_string_free (&uuid);
-
- dbus_message_unref (ret);
-
- if (!sent)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- return DBUS_HANDLER_RESULT_HANDLED;
}
- else if (dbus_message_has_interface (message, DBUS_INTERFACE_PEER))
+ else
{
/* We need to bounce anything else with this interface, otherwise apps
* could start extending the interface and when we added extensions
* here to DBusConnection we'd break those apps.
*/
-
- DBusMessage *ret;
- dbus_bool_t sent;
-
ret = dbus_message_new_error (message,
DBUS_ERROR_UNKNOWN_METHOD,
"Unknown method invoked on org.freedesktop.DBus.Peer interface");
if (ret == NULL)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
+ goto out;
+
sent = _dbus_connection_send_unlocked_no_update (connection, ret, NULL);
-
- dbus_message_unref (ret);
-
- if (!sent)
- return DBUS_HANDLER_RESULT_NEED_MEMORY;
-
- return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+out:
+ if (ret == NULL)
+ {
+ _dbus_list_free_link (expire_link);
}
else
{
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ /* It'll be safe to unref the reply when we unlock */
+ expire_link->data = ret;
+ _dbus_list_prepend_link (&connection->expired_messages, expire_link);
}
+
+ if (!sent)
+ return DBUS_HANDLER_RESULT_NEED_MEMORY;
+
+ return DBUS_HANDLER_RESULT_HANDLED;
}
/**
@@ -4481,6 +4479,7 @@ dbus_connection_dispatch (DBusConnection *connection)
DBusPendingCall *pending;
dbus_int32_t reply_serial;
DBusDispatchStatus status;
+ dbus_bool_t found_object;
_dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
@@ -4642,7 +4641,8 @@ dbus_connection_dispatch (DBusConnection *connection)
HAVE_LOCK_CHECK (connection);
result = _dbus_object_tree_dispatch_and_unlock (connection->objects,
- message);
+ message,
+ &found_object);
CONNECTION_LOCK (connection);
@@ -4657,10 +4657,11 @@ dbus_connection_dispatch (DBusConnection *connection)
DBusMessage *reply;
DBusString str;
DBusPreallocatedSend *preallocated;
+ DBusList *expire_link;
_dbus_verbose (" sending error %s\n",
DBUS_ERROR_UNKNOWN_METHOD);
-
+
if (!_dbus_string_init (&str))
{
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
@@ -4681,7 +4682,7 @@ dbus_connection_dispatch (DBusConnection *connection)
}
reply = dbus_message_new_error (message,
- DBUS_ERROR_UNKNOWN_METHOD,
+ found_object ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_OBJECT,
_dbus_string_get_const_data (&str));
_dbus_string_free (&str);
@@ -4691,11 +4692,24 @@ dbus_connection_dispatch (DBusConnection *connection)
_dbus_verbose ("no memory for error reply in dispatch\n");
goto out;
}
-
+
+ expire_link = _dbus_list_alloc_link (reply);
+
+ if (expire_link == NULL)
+ {
+ dbus_message_unref (reply);
+ result = DBUS_HANDLER_RESULT_NEED_MEMORY;
+ _dbus_verbose ("no memory for error send in dispatch\n");
+ goto out;
+ }
+
preallocated = _dbus_connection_preallocate_send_unlocked (connection);
if (preallocated == NULL)
{
+ _dbus_list_free_link (expire_link);
+ /* It's OK that this is finalized, because it hasn't been seen by
+ * anything that could attach user callbacks */
dbus_message_unref (reply);
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
_dbus_verbose ("no memory for error send in dispatch\n");
@@ -4704,9 +4718,9 @@ dbus_connection_dispatch (DBusConnection *connection)
_dbus_connection_send_preallocated_unlocked_no_update (connection, preallocated,
reply, NULL);
+ /* reply will be freed when we release the lock */
+ _dbus_list_prepend_link (&connection->expired_messages, expire_link);
- dbus_message_unref (reply);
-
result = DBUS_HANDLER_RESULT_HANDLED;
}
@@ -4732,20 +4746,35 @@ dbus_connection_dispatch (DBusConnection *connection)
*/
_dbus_connection_putback_message_link_unlocked (connection,
message_link);
+ /* now we don't want to free them */
+ message_link = NULL;
+ message = NULL;
}
else
{
_dbus_verbose (" ... done dispatching\n");
-
- _dbus_list_free_link (message_link);
- dbus_message_unref (message); /* don't want the message to count in max message limits
- * in computing dispatch status below
- */
}
-
+
_dbus_connection_release_dispatch (connection);
HAVE_LOCK_CHECK (connection);
+ if (message != NULL)
+ {
+ /* We don't want this message to count in maximum message limits when
+ * computing the dispatch status, below. We have to drop the lock
+ * temporarily, because finalizing a message can trigger callbacks.
+ *
+ * We have a reference to the connection, and we don't use any cached
+ * pointers to the connection's internals below this point, so it should
+ * be safe to drop the lock and take it back. */
+ CONNECTION_UNLOCK (connection);
+ dbus_message_unref (message);
+ CONNECTION_LOCK (connection);
+ }
+
+ if (message_link != NULL)
+ _dbus_list_free_link (message_link);
+
_dbus_verbose ("before final status update\n");
status = _dbus_connection_get_dispatch_status_unlocked (connection);
@@ -5509,10 +5538,13 @@ dbus_connection_remove_filter (DBusConnection *connection,
}
/**
- * Registers a handler for a given path in the object hierarchy.
- * The given vtable handles messages sent to exactly the given path.
+ * Registers a handler for a given path or subsection in the object
+ * hierarchy. The given vtable handles messages sent to exactly the
+ * given path or also for paths bellow that, depending on fallback
+ * parameter.
*
* @param connection the connection
+ * @param fallback whether to handle messages also for "subdirectory"
* @param path a '/' delimited string of path elements
* @param vtable the virtual table
* @param user_data data to pass to functions in the vtable
@@ -5520,20 +5552,16 @@ dbus_connection_remove_filter (DBusConnection *connection,
* @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
* #DBUS_ERROR_OBJECT_PATH_IN_USE) is reported
*/
-dbus_bool_t
-dbus_connection_try_register_object_path (DBusConnection *connection,
- const char *path,
- const DBusObjectPathVTable *vtable,
- void *user_data,
- DBusError *error)
+static dbus_bool_t
+_dbus_connection_register_object_path (DBusConnection *connection,
+ dbus_bool_t fallback,
+ const char *path,
+ const DBusObjectPathVTable *vtable,
+ void *user_data,
+ DBusError *error)
{
char **decomposed_path;
dbus_bool_t retval;
-
- _dbus_return_val_if_fail (connection != NULL, FALSE);
- _dbus_return_val_if_fail (path != NULL, FALSE);
- _dbus_return_val_if_fail (path[0] == '/', FALSE);
- _dbus_return_val_if_fail (vtable != NULL, FALSE);
if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
return FALSE;
@@ -5541,7 +5569,7 @@ dbus_connection_try_register_object_path (DBusConnection *connectio
CONNECTION_LOCK (connection);
retval = _dbus_object_tree_register (connection->objects,
- FALSE,
+ fallback,
(const char **) decomposed_path, vtable,
user_data, error);
@@ -5556,6 +5584,33 @@ dbus_connection_try_register_object_path (DBusConnection *connectio
* Registers a handler for a given path in the object hierarchy.
* The given vtable handles messages sent to exactly the given path.
*
+ * @param connection the connection
+ * @param path a '/' delimited string of path elements
+ * @param vtable the virtual table
+ * @param user_data data to pass to functions in the vtable
+ * @param error address where an error can be returned
+ * @returns #FALSE if an error (#DBUS_ERROR_NO_MEMORY or
+ * #DBUS_ERROR_OBJECT_PATH_IN_USE) is reported
+ */
+dbus_bool_t
+dbus_connection_try_register_object_path (DBusConnection *connection,
+ const char *path,
+ const DBusObjectPathVTable *vtable,
+ void *user_data,
+ DBusError *error)
+{
+ _dbus_return_val_if_fail (connection != NULL, FALSE);
+ _dbus_return_val_if_fail (path != NULL, FALSE);
+ _dbus_return_val_if_fail (path[0] == '/', FALSE);
+ _dbus_return_val_if_fail (vtable != NULL, FALSE);
+
+ return _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, error);
+}
+
+/**
+ * Registers a handler for a given path in the object hierarchy.
+ * The given vtable handles messages sent to exactly the given path.
+ *
* It is a bug to call this function for object paths which already
* have a handler. Use dbus_connection_try_register_object_path() if this
* might be the case.
@@ -5573,7 +5628,6 @@ dbus_connection_register_object_path (DBusConnection *connection,
const DBusObjectPathVTable *vtable,
void *user_data)
{
- char **decomposed_path;
dbus_bool_t retval;
DBusError error = DBUS_ERROR_INIT;
@@ -5582,19 +5636,7 @@ dbus_connection_register_object_path (DBusConnection *connection,
_dbus_return_val_if_fail (path[0] == '/', FALSE);
_dbus_return_val_if_fail (vtable != NULL, FALSE);
- if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
- return FALSE;
-
- CONNECTION_LOCK (connection);
-
- retval = _dbus_object_tree_register (connection->objects,
- FALSE,
- (const char **) decomposed_path, vtable,
- user_data, &error);
-
- CONNECTION_UNLOCK (connection);
-
- dbus_free_string_array (decomposed_path);
+ retval = _dbus_connection_register_object_path (connection, FALSE, path, vtable, user_data, &error);
if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
{
@@ -5627,29 +5669,12 @@ dbus_connection_try_register_fallback (DBusConnection *connection,
void *user_data,
DBusError *error)
{
- char **decomposed_path;
- dbus_bool_t retval;
-
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (path != NULL, FALSE);
_dbus_return_val_if_fail (path[0] == '/', FALSE);
_dbus_return_val_if_fail (vtable != NULL, FALSE);
- if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
- return FALSE;
-
- CONNECTION_LOCK (connection);
-
- retval = _dbus_object_tree_register (connection->objects,
- TRUE,
- (const char **) decomposed_path, vtable,
- user_data, error);
-
- CONNECTION_UNLOCK (connection);
-
- dbus_free_string_array (decomposed_path);
-
- return retval;
+ return _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, error);
}
/**
@@ -5675,7 +5700,6 @@ dbus_connection_register_fallback (DBusConnection *connection,
const DBusObjectPathVTable *vtable,
void *user_data)
{
- char **decomposed_path;
dbus_bool_t retval;
DBusError error = DBUS_ERROR_INIT;
@@ -5684,19 +5708,7 @@ dbus_connection_register_fallback (DBusConnection *connection,
_dbus_return_val_if_fail (path[0] == '/', FALSE);
_dbus_return_val_if_fail (vtable != NULL, FALSE);
- if (!_dbus_decompose_path (path, strlen (path), &decomposed_path, NULL))
- return FALSE;
-
- CONNECTION_LOCK (connection);
-
- retval = _dbus_object_tree_register (connection->objects,
- TRUE,
- (const char **) decomposed_path, vtable,
- user_data, &error);
-
- CONNECTION_UNLOCK (connection);
-
- dbus_free_string_array (decomposed_path);
+ retval = _dbus_connection_register_object_path (connection, TRUE, path, vtable, user_data, &error);
if (dbus_error_has_name (&error, DBUS_ERROR_OBJECT_PATH_IN_USE))
{
@@ -6156,6 +6168,47 @@ dbus_connection_get_outgoing_size (DBusConnection *connection)
return res;
}
+#ifdef DBUS_ENABLE_STATS
+void
+_dbus_connection_get_stats (DBusConnection *connection,
+ dbus_uint32_t *in_messages,
+ dbus_uint32_t *in_bytes,
+ dbus_uint32_t *in_fds,
+ dbus_uint32_t *in_peak_bytes,
+ dbus_uint32_t *in_peak_fds,
+ dbus_uint32_t *out_messages,
+ dbus_uint32_t *out_bytes,
+ dbus_uint32_t *out_fds,
+ dbus_uint32_t *out_peak_bytes,
+ dbus_uint32_t *out_peak_fds)
+{
+ CONNECTION_LOCK (connection);
+
+ if (in_messages != NULL)
+ *in_messages = connection->n_incoming;
+
+ _dbus_transport_get_stats (connection->transport,
+ in_bytes, in_fds, in_peak_bytes, in_peak_fds);
+
+ if (out_messages != NULL)
+ *out_messages = connection->n_outgoing;
+
+ if (out_bytes != NULL)
+ *out_bytes = _dbus_counter_get_size_value (connection->outgoing_counter);
+
+ if (out_fds != NULL)
+ *out_fds = _dbus_counter_get_unix_fd_value (connection->outgoing_counter);
+
+ if (out_peak_bytes != NULL)
+ *out_peak_bytes = _dbus_counter_get_peak_size_value (connection->outgoing_counter);
+
+ if (out_peak_fds != NULL)
+ *out_peak_fds = _dbus_counter_get_peak_unix_fd_value (connection->outgoing_counter);
+
+ CONNECTION_UNLOCK (connection);
+}
+#endif /* DBUS_ENABLE_STATS */
+
/**
* Gets the approximate number of uni fds of all messages in the
* outgoing message queue.
diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c
index 5e864ce3..fcea0790 100644
--- a/dbus/dbus-internals.c
+++ b/dbus/dbus-internals.c
@@ -301,9 +301,6 @@ static dbus_bool_t verbose = TRUE;
#include <pthread.h>
#endif
-#ifdef _MSC_VER
-#define inline
-#endif
#ifdef DBUS_USE_OUTPUT_DEBUG_STRING
static char module_name[1024];
#endif
@@ -350,7 +347,6 @@ _dbus_verbose_init (void)
static char *_dbus_file_path_extract_elements_from_tail(const char *file,int level)
{
static int prefix = -1;
- char *p;
if (prefix == -1)
{
diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c
index 6a16ed60..d4d74f69 100644
--- a/dbus/dbus-list.c
+++ b/dbus/dbus-list.c
@@ -146,6 +146,18 @@ link_after (DBusList **list,
}
}
+#ifdef DBUS_ENABLE_STATS
+void
+_dbus_list_get_stats (dbus_uint32_t *in_use_p,
+ dbus_uint32_t *in_free_list_p,
+ dbus_uint32_t *allocated_p)
+{
+ _DBUS_LOCK (list);
+ _dbus_mem_pool_get_stats (list_pool, in_use_p, in_free_list_p, allocated_p);
+ _DBUS_UNLOCK (list);
+}
+#endif
+
/** @} */
/**
diff --git a/dbus/dbus-list.h b/dbus/dbus-list.h
index 663ad257..2e346d5e 100644
--- a/dbus/dbus-list.h
+++ b/dbus/dbus-list.h
@@ -84,8 +84,6 @@ void _dbus_list_prepend_link (DBusList **list,
dbus_bool_t _dbus_list_length_is_one (DBusList **list);
-
-
void _dbus_list_foreach (DBusList **list,
DBusForeachFunction function,
void *data);
@@ -93,6 +91,11 @@ void _dbus_list_foreach (DBusList **list,
#define _dbus_list_get_next_link(list, link) ((link)->next == *(list) ? NULL : (link)->next)
#define _dbus_list_get_prev_link(list, link) ((link) == *(list) ? NULL : (link)->prev)
+/* if DBUS_ENABLE_STATS */
+void _dbus_list_get_stats (dbus_uint32_t *in_use_p,
+ dbus_uint32_t *in_free_list_p,
+ dbus_uint32_t *allocated_p);
+
DBUS_END_DECLS
#endif /* DBUS_LIST_H */
diff --git a/dbus/dbus-mainloop.c b/dbus/dbus-mainloop.c
index 43159a70..b49c9b2c 100644
--- a/dbus/dbus-mainloop.c
+++ b/dbus/dbus-mainloop.c
@@ -26,6 +26,7 @@
#ifndef DOXYGEN_SHOULD_SKIP_THIS
+#include <dbus/dbus-hash.h>
#include <dbus/dbus-list.h>
#include <dbus/dbus-sysdeps.h>
#include <dbus/dbus-watch.h>
@@ -56,7 +57,9 @@ watch_flags_to_string (int flags)
struct DBusLoop
{
int refcount;
- DBusList *callbacks;
+ /** fd => dbus_malloc'd DBusList ** of references to DBusWatch */
+ DBusHashTable *watches;
+ DBusList *timeouts;
int callback_list_serial;
int watch_count;
int timeout_count;
@@ -64,69 +67,48 @@ struct DBusLoop
DBusList *need_dispatch;
};
-typedef enum
+static short
+watch_flags_to_poll_events (unsigned int flags)
{
- CALLBACK_WATCH,
- CALLBACK_TIMEOUT
-} CallbackType;
+ short events = 0;
-typedef struct
-{
- int refcount;
- CallbackType type;
- void *data;
- DBusFreeFunction free_data_func;
-} Callback;
+ if (flags & DBUS_WATCH_READABLE)
+ events |= _DBUS_POLLIN;
+ if (flags & DBUS_WATCH_WRITABLE)
+ events |= _DBUS_POLLOUT;
-typedef struct
+ return events;
+}
+
+static unsigned int
+watch_flags_from_poll_revents (short revents)
{
- Callback callback;
- DBusWatchFunction function;
- DBusWatch *watch;
- /* last watch handle failed due to OOM */
- unsigned int last_iteration_oom : 1;
-} WatchCallback;
+ unsigned int condition = 0;
+
+ if (revents & _DBUS_POLLIN)
+ condition |= DBUS_WATCH_READABLE;
+ if (revents & _DBUS_POLLOUT)
+ condition |= DBUS_WATCH_WRITABLE;
+ if (revents & _DBUS_POLLHUP)
+ condition |= DBUS_WATCH_HANGUP;
+ if (revents & _DBUS_POLLERR)
+ condition |= DBUS_WATCH_ERROR;
+
+ return condition;
+}
typedef struct
{
- Callback callback;
+ int refcount;
DBusTimeout *timeout;
- DBusTimeoutFunction function;
unsigned long last_tv_sec;
unsigned long last_tv_usec;
} TimeoutCallback;
-#define WATCH_CALLBACK(callback) ((WatchCallback*)callback)
#define TIMEOUT_CALLBACK(callback) ((TimeoutCallback*)callback)
-static WatchCallback*
-watch_callback_new (DBusWatch *watch,
- DBusWatchFunction function,
- void *data,
- DBusFreeFunction free_data_func)
-{
- WatchCallback *cb;
-
- cb = dbus_new (WatchCallback, 1);
- if (cb == NULL)
- return NULL;
-
- cb->watch = watch;
- cb->function = function;
- cb->last_iteration_oom = FALSE;
- cb->callback.refcount = 1;
- cb->callback.type = CALLBACK_WATCH;
- cb->callback.data = data;
- cb->callback.free_data_func = free_data_func;
-
- return cb;
-}
-
static TimeoutCallback*
-timeout_callback_new (DBusTimeout *timeout,
- DBusTimeoutFunction function,
- void *data,
- DBusFreeFunction free_data_func)
+timeout_callback_new (DBusTimeout *timeout)
{
TimeoutCallback *cb;
@@ -135,19 +117,14 @@ timeout_callback_new (DBusTimeout *timeout,
return NULL;
cb->timeout = timeout;
- cb->function = function;
_dbus_get_current_time (&cb->last_tv_sec,
&cb->last_tv_usec);
- cb->callback.refcount = 1;
- cb->callback.type = CALLBACK_TIMEOUT;
- cb->callback.data = data;
- cb->callback.free_data_func = free_data_func;
-
+ cb->refcount = 1;
return cb;
}
-static Callback *
-callback_ref (Callback *cb)
+static TimeoutCallback *
+timeout_callback_ref (TimeoutCallback *cb)
{
_dbus_assert (cb->refcount > 0);
@@ -157,7 +134,7 @@ callback_ref (Callback *cb)
}
static void
-callback_unref (Callback *cb)
+timeout_callback_unref (TimeoutCallback *cb)
{
_dbus_assert (cb->refcount > 0);
@@ -165,54 +142,30 @@ callback_unref (Callback *cb)
if (cb->refcount == 0)
{
- if (cb->free_data_func)
- (* cb->free_data_func) (cb->data);
-
dbus_free (cb);
}
}
-static dbus_bool_t
-add_callback (DBusLoop *loop,
- Callback *cb)
+static void
+free_watch_table_entry (void *data)
{
- if (!_dbus_list_append (&loop->callbacks, cb))
- return FALSE;
+ DBusList **watches = data;
+ DBusWatch *watch;
- loop->callback_list_serial += 1;
+ /* DBusHashTable sometimes calls free_function(NULL) even if you never
+ * have NULL as a value */
+ if (watches == NULL)
+ return;
- switch (cb->type)
+ for (watch = _dbus_list_pop_first (watches);
+ watch != NULL;
+ watch = _dbus_list_pop_first (watches))
{
- case CALLBACK_WATCH:
- loop->watch_count += 1;
- break;
- case CALLBACK_TIMEOUT:
- loop->timeout_count += 1;
- break;
+ _dbus_watch_unref (watch);
}
-
- return TRUE;
-}
-static void
-remove_callback (DBusLoop *loop,
- DBusList *link)
-{
- Callback *cb = link->data;
-
- switch (cb->type)
- {
- case CALLBACK_WATCH:
- loop->watch_count -= 1;
- break;
- case CALLBACK_TIMEOUT:
- loop->timeout_count -= 1;
- break;
- }
-
- callback_unref (cb);
- _dbus_list_remove_link (&loop->callbacks, link);
- loop->callback_list_serial += 1;
+ _dbus_assert (*watches == NULL);
+ dbus_free (watches);
}
DBusLoop*
@@ -224,8 +177,17 @@ _dbus_loop_new (void)
if (loop == NULL)
return NULL;
+ loop->watches = _dbus_hash_table_new (DBUS_HASH_INT, NULL,
+ free_watch_table_entry);
+
+ if (loop->watches == NULL)
+ {
+ dbus_free (loop);
+ return NULL;
+ }
+
loop->refcount = 1;
-
+
return loop;
}
@@ -255,82 +217,169 @@ _dbus_loop_unref (DBusLoop *loop)
dbus_connection_unref (connection);
}
-
+
+ _dbus_hash_table_unref (loop->watches);
dbus_free (loop);
}
}
+static DBusList **
+ensure_watch_table_entry (DBusLoop *loop,
+ int fd)
+{
+ DBusList **watches;
+
+ watches = _dbus_hash_table_lookup_int (loop->watches, fd);
+
+ if (watches == NULL)
+ {
+ watches = dbus_new0 (DBusList *, 1);
+
+ if (watches == NULL)
+ return watches;
+
+ if (!_dbus_hash_table_insert_int (loop->watches, fd, watches))
+ {
+ dbus_free (watches);
+ watches = NULL;
+ }
+ }
+
+ return watches;
+}
+
+static void
+cull_watches_for_invalid_fd (DBusLoop *loop,
+ int fd)
+{
+ DBusList *link;
+ DBusList *next;
+ DBusList **watches;
+
+ _dbus_warn ("invalid request, socket fd %d not open\n", fd);
+ watches = _dbus_hash_table_lookup_int (loop->watches, fd);
+
+ if (watches != NULL)
+ {
+ for (link = _dbus_list_get_first_link (watches);
+ link != NULL;
+ link = _dbus_list_get_next_link (watches, link))
+ _dbus_watch_invalidate (link->data);
+ }
+
+ _dbus_hash_table_remove_int (loop->watches, fd);
+}
+
+static void
+gc_watch_table_entry (DBusLoop *loop,
+ DBusList **watches,
+ int fd)
+{
+ /* If watches is already NULL we have nothing to do */
+ if (watches == NULL)
+ return;
+
+ /* We can't GC hash table entries if they're non-empty lists */
+ if (*watches != NULL)
+ return;
+
+ _dbus_hash_table_remove_int (loop->watches, fd);
+}
+
dbus_bool_t
-_dbus_loop_add_watch (DBusLoop *loop,
- DBusWatch *watch,
- DBusWatchFunction function,
- void *data,
- DBusFreeFunction free_data_func)
+_dbus_loop_add_watch (DBusLoop *loop,
+ DBusWatch *watch)
{
- WatchCallback *wcb;
+ int fd;
+ DBusList **watches;
- wcb = watch_callback_new (watch, function, data, free_data_func);
- if (wcb == NULL)
+ fd = dbus_watch_get_socket (watch);
+ _dbus_assert (fd != -1);
+
+ watches = ensure_watch_table_entry (loop, fd);
+
+ if (watches == NULL)
return FALSE;
- if (!add_callback (loop, (Callback*) wcb))
+ if (_dbus_list_append (watches, _dbus_watch_ref (watch)))
{
- wcb->callback.free_data_func = NULL; /* don't want to have this side effect */
- callback_unref ((Callback*) wcb);
- return FALSE;
+ loop->callback_list_serial += 1;
+ loop->watch_count += 1;
}
-
+ else
+ {
+ _dbus_watch_unref (watch);
+ gc_watch_table_entry (loop, watches, fd);
+
+ return FALSE;
+ }
+
return TRUE;
}
void
-_dbus_loop_remove_watch (DBusLoop *loop,
- DBusWatch *watch,
- DBusWatchFunction function,
- void *data)
+_dbus_loop_remove_watch (DBusLoop *loop,
+ DBusWatch *watch)
{
+ DBusList **watches;
DBusList *link;
-
- link = _dbus_list_get_first_link (&loop->callbacks);
- while (link != NULL)
- {
- DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
- Callback *this = link->data;
+ int fd;
+
+ /* This relies on people removing watches before they invalidate them,
+ * which has been safe since fd.o #33336 was fixed. Assert about it
+ * so we don't regress. */
+ fd = dbus_watch_get_socket (watch);
+ _dbus_assert (fd != -1);
+
+ watches = _dbus_hash_table_lookup_int (loop->watches, fd);
- if (this->type == CALLBACK_WATCH &&
- WATCH_CALLBACK (this)->watch == watch &&
- this->data == data &&
- WATCH_CALLBACK (this)->function == function)
+ if (watches != NULL)
+ {
+ link = _dbus_list_get_first_link (watches);
+ while (link != NULL)
{
- remove_callback (loop, link);
-
- return;
- }
-
- link = next;
- }
+ DBusList *next = _dbus_list_get_next_link (watches, link);
+ DBusWatch *this = link->data;
+
+ if (this == watch)
+ {
+ _dbus_list_remove_link (watches, link);
+ loop->callback_list_serial += 1;
+ loop->watch_count -= 1;
+ _dbus_watch_unref (this);
+
+ /* if that was the last watch for that fd, drop the hash table
+ * entry too */
+ gc_watch_table_entry (loop, watches, fd);
+
+ return;
+ }
- _dbus_warn ("could not find watch %p function %p data %p to remove\n",
- watch, (void *)function, data);
+ link = next;
+ }
+ }
+
+ _dbus_warn ("could not find watch %p to remove\n", watch);
}
dbus_bool_t
-_dbus_loop_add_timeout (DBusLoop *loop,
- DBusTimeout *timeout,
- DBusTimeoutFunction function,
- void *data,
- DBusFreeFunction free_data_func)
+_dbus_loop_add_timeout (DBusLoop *loop,
+ DBusTimeout *timeout)
{
TimeoutCallback *tcb;
- tcb = timeout_callback_new (timeout, function, data, free_data_func);
+ tcb = timeout_callback_new (timeout);
if (tcb == NULL)
return FALSE;
- if (!add_callback (loop, (Callback*) tcb))
+ if (_dbus_list_append (&loop->timeouts, tcb))
+ {
+ loop->callback_list_serial += 1;
+ loop->timeout_count += 1;
+ }
+ else
{
- tcb->callback.free_data_func = NULL; /* don't want to have this side effect */
- callback_unref ((Callback*) tcb);
+ timeout_callback_unref (tcb);
return FALSE;
}
@@ -338,34 +387,31 @@ _dbus_loop_add_timeout (DBusLoop *loop,
}
void
-_dbus_loop_remove_timeout (DBusLoop *loop,
- DBusTimeout *timeout,
- DBusTimeoutFunction function,
- void *data)
+_dbus_loop_remove_timeout (DBusLoop *loop,
+ DBusTimeout *timeout)
{
DBusList *link;
- link = _dbus_list_get_first_link (&loop->callbacks);
+ link = _dbus_list_get_first_link (&loop->timeouts);
while (link != NULL)
{
- DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
- Callback *this = link->data;
+ DBusList *next = _dbus_list_get_next_link (&loop->timeouts, link);
+ TimeoutCallback *this = link->data;
- if (this->type == CALLBACK_TIMEOUT &&
- TIMEOUT_CALLBACK (this)->timeout == timeout &&
- this->data == data &&
- TIMEOUT_CALLBACK (this)->function == function)
+ if (this->timeout == timeout)
{
- remove_callback (loop, link);
-
+ _dbus_list_remove_link (&loop->timeouts, link);
+ loop->callback_list_serial += 1;
+ loop->timeout_count -= 1;
+ timeout_callback_unref (this);
+
return;
}
link = next;
}
- _dbus_warn ("could not find timeout %p function %p data %p to remove\n",
- timeout, (void *)function, data);
+ _dbus_warn ("could not find timeout %p to remove\n", timeout);
}
/* Convolutions from GLib, there really must be a better way
@@ -525,8 +571,6 @@ _dbus_loop_iterate (DBusLoop *loop,
DBusPollFD *fds;
DBusPollFD stack_fds[N_STACK_DESCRIPTORS];
int n_fds;
- WatchCallback **watches_for_fds;
- WatchCallback *stack_watches_for_fds[N_STACK_DESCRIPTORS];
int i;
DBusList *link;
int n_ready;
@@ -534,11 +578,11 @@ _dbus_loop_iterate (DBusLoop *loop,
long timeout;
dbus_bool_t oom_watch_pending;
int orig_depth;
-
+ DBusHashIter hash_iter;
+
retval = FALSE;
fds = NULL;
- watches_for_fds = NULL;
n_fds = 0;
oom_watch_pending = FALSE;
orig_depth = loop->depth;
@@ -547,8 +591,9 @@ _dbus_loop_iterate (DBusLoop *loop,
_dbus_verbose ("Iteration block=%d depth=%d timeout_count=%d watch_count=%d\n",
block, loop->depth, loop->timeout_count, loop->watch_count);
#endif
-
- if (loop->callbacks == NULL)
+
+ if (_dbus_hash_table_get_n_entries (loop->watches) == 0 &&
+ loop->timeouts == NULL)
goto next_iteration;
if (loop->watch_count > N_STACK_DESCRIPTORS)
@@ -560,41 +605,40 @@ _dbus_loop_iterate (DBusLoop *loop,
_dbus_wait_for_memory ();
fds = dbus_new0 (DBusPollFD, loop->watch_count);
}
-
- watches_for_fds = dbus_new (WatchCallback*, loop->watch_count);
- while (watches_for_fds == NULL)
- {
- _dbus_wait_for_memory ();
- watches_for_fds = dbus_new (WatchCallback*, loop->watch_count);
- }
}
else
{
fds = stack_fds;
- watches_for_fds = stack_watches_for_fds;
}
/* fill our array of fds and watches */
n_fds = 0;
- link = _dbus_list_get_first_link (&loop->callbacks);
- while (link != NULL)
+ _dbus_hash_iter_init (loop->watches, &hash_iter);
+
+ while (_dbus_hash_iter_next (&hash_iter))
{
- DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
- Callback *cb = link->data;
- if (cb->type == CALLBACK_WATCH)
+ DBusList **watches;
+ unsigned int flags;
+ int fd;
+
+ fd = _dbus_hash_iter_get_int_key (&hash_iter);
+ watches = _dbus_hash_iter_get_value (&hash_iter);
+ flags = 0;
+
+ for (link = _dbus_list_get_first_link (watches);
+ link != NULL;
+ link = _dbus_list_get_next_link (watches, link))
{
- unsigned int flags;
- WatchCallback *wcb = WATCH_CALLBACK (cb);
- int fd = dbus_watch_get_socket (wcb->watch);
+ DBusWatch *watch = link->data;
- if (wcb->last_iteration_oom)
+ if (_dbus_watch_get_oom_last_time (watch))
{
/* we skip this one this time, but reenable it next time,
* and have a timeout on this iteration
*/
- wcb->last_iteration_oom = FALSE;
+ _dbus_watch_set_oom_last_time (watch, FALSE);
oom_watch_pending = TRUE;
-
+
retval = TRUE; /* return TRUE here to keep the loop going,
* since we don't know the watch is inactive
*/
@@ -604,49 +648,35 @@ _dbus_loop_iterate (DBusLoop *loop,
fd);
#endif
}
- else if (_DBUS_UNLIKELY (fd == -1))
+ else if (dbus_watch_get_enabled (watch))
{
- _dbus_warn ("watch %p was invalidated but not removed; "
- "removing it now\n", wcb->watch);
- _dbus_loop_remove_watch (loop, wcb->watch, wcb->function,
- ((Callback *)wcb)->data);
+ flags |= dbus_watch_get_flags (watch);
}
- else if (dbus_watch_get_enabled (wcb->watch))
- {
- watches_for_fds[n_fds] = wcb;
+ }
- callback_ref (cb);
-
- flags = dbus_watch_get_flags (wcb->watch);
-
- fds[n_fds].fd = fd;
- fds[n_fds].revents = 0;
- fds[n_fds].events = 0;
- if (flags & DBUS_WATCH_READABLE)
- fds[n_fds].events |= _DBUS_POLLIN;
- if (flags & DBUS_WATCH_WRITABLE)
- fds[n_fds].events |= _DBUS_POLLOUT;
+ if (flags != 0)
+ {
+ fds[n_fds].fd = fd;
+ fds[n_fds].revents = 0;
+ fds[n_fds].events = watch_flags_to_poll_events (flags);
#if MAINLOOP_SPEW
- _dbus_verbose (" polling watch on fd %d %s\n",
- fd, watch_flags_to_string (flags));
+ _dbus_verbose (" polling watch on fd %d %s\n",
+ loop->fds[loop->n_fds].fd, watch_flags_to_string (flags));
#endif
- n_fds += 1;
- }
- else
- {
+ n_fds += 1;
+ }
+ else
+ {
#if MAINLOOP_SPEW
- _dbus_verbose (" skipping disabled watch on fd %d %s\n",
- fd,
- watch_flags_to_string (dbus_watch_get_flags (wcb->watch)));
+ _dbus_verbose (" skipping disabled watch on fd %d %s\n",
+ fd,
+ watch_flags_to_string (dbus_watch_get_flags (watch)));
#endif
- }
}
-
- link = next;
}
-
+
timeout = -1;
if (loop->timeout_count > 0)
{
@@ -654,17 +684,15 @@ _dbus_loop_iterate (DBusLoop *loop,
unsigned long tv_usec;
_dbus_get_current_time (&tv_sec, &tv_usec);
-
- link = _dbus_list_get_first_link (&loop->callbacks);
+
+ link = _dbus_list_get_first_link (&loop->timeouts);
while (link != NULL)
{
- DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
- Callback *cb = link->data;
+ DBusList *next = _dbus_list_get_next_link (&loop->timeouts, link);
+ TimeoutCallback *tcb = link->data;
- if (cb->type == CALLBACK_TIMEOUT &&
- dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout))
+ if (dbus_timeout_get_enabled (tcb->timeout))
{
- TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb);
int msecs_remaining;
check_timeout (tv_sec, tv_usec, tcb, &msecs_remaining);
@@ -685,7 +713,7 @@ _dbus_loop_iterate (DBusLoop *loop,
break; /* it's not going to get shorter... */
}
#if MAINLOOP_SPEW
- else if (cb->type == CALLBACK_TIMEOUT)
+ else
{
_dbus_verbose (" skipping disabled timeout\n");
}
@@ -726,22 +754,20 @@ _dbus_loop_iterate (DBusLoop *loop,
_dbus_get_current_time (&tv_sec, &tv_usec);
/* It'd be nice to avoid this O(n) thingy here */
- link = _dbus_list_get_first_link (&loop->callbacks);
+ link = _dbus_list_get_first_link (&loop->timeouts);
while (link != NULL)
{
- DBusList *next = _dbus_list_get_next_link (&loop->callbacks, link);
- Callback *cb = link->data;
+ DBusList *next = _dbus_list_get_next_link (&loop->timeouts, link);
+ TimeoutCallback *tcb = link->data;
if (initial_serial != loop->callback_list_serial)
goto next_iteration;
if (loop->depth != orig_depth)
goto next_iteration;
-
- if (cb->type == CALLBACK_TIMEOUT &&
- dbus_timeout_get_enabled (TIMEOUT_CALLBACK (cb)->timeout))
+
+ if (dbus_timeout_get_enabled (tcb->timeout))
{
- TimeoutCallback *tcb = TIMEOUT_CALLBACK (cb);
int msecs_remaining;
if (check_timeout (tv_sec, tv_usec,
@@ -754,9 +780,11 @@ _dbus_loop_iterate (DBusLoop *loop,
#if MAINLOOP_SPEW
_dbus_verbose (" invoking timeout\n");
#endif
-
- (* tcb->function) (tcb->timeout,
- cb->data);
+
+ /* can theoretically return FALSE on OOM, but we just
+ * let it fire again later - in practice that's what
+ * every wrapper callback in dbus-daemon used to do */
+ dbus_timeout_handle (tcb->timeout);
retval = TRUE;
}
@@ -768,7 +796,7 @@ _dbus_loop_iterate (DBusLoop *loop,
}
}
#if MAINLOOP_SPEW
- else if (cb->type == CALLBACK_TIMEOUT)
+ else
{
_dbus_verbose (" skipping invocation of disabled timeout\n");
}
@@ -780,9 +808,12 @@ _dbus_loop_iterate (DBusLoop *loop,
if (n_ready > 0)
{
- i = 0;
- while (i < n_fds)
+ for (i = 0; i < n_fds; i++)
{
+ DBusList **watches;
+ DBusList *next;
+ unsigned int condition;
+
/* FIXME I think this "restart if we change the watches"
* approach could result in starving watches
* toward the end of the list.
@@ -793,54 +824,62 @@ _dbus_loop_iterate (DBusLoop *loop,
if (loop->depth != orig_depth)
goto next_iteration;
- if (fds[i].revents != 0)
+ if (fds[i].revents == 0)
+ continue;
+
+ if (_DBUS_UNLIKELY (fds[i].revents & _DBUS_POLLNVAL))
{
- WatchCallback *wcb;
- unsigned int condition;
-
- wcb = watches_for_fds[i];
-
- condition = 0;
- if (fds[i].revents & _DBUS_POLLIN)
- condition |= DBUS_WATCH_READABLE;
- if (fds[i].revents & _DBUS_POLLOUT)
- condition |= DBUS_WATCH_WRITABLE;
- if (fds[i].revents & _DBUS_POLLHUP)
- condition |= DBUS_WATCH_HANGUP;
- if (fds[i].revents & _DBUS_POLLERR)
- condition |= DBUS_WATCH_ERROR;
-
- /* condition may still be 0 if we got some
- * weird POLLFOO thing like POLLWRBAND
- */
-
- if (condition != 0 &&
- dbus_watch_get_enabled (wcb->watch))
+ cull_watches_for_invalid_fd (loop, fds[i].fd);
+ goto next_iteration;
+ }
+
+ condition = watch_flags_from_poll_revents (fds[i].revents);
+
+ /* condition may still be 0 if we got some
+ * weird POLLFOO thing like POLLWRBAND
+ */
+ if (condition == 0)
+ continue;
+
+ watches = _dbus_hash_table_lookup_int (loop->watches, fds[i].fd);
+
+ if (watches == NULL)
+ continue;
+
+ for (link = _dbus_list_get_first_link (watches);
+ link != NULL;
+ link = next)
+ {
+ DBusWatch *watch = link->data;
+
+ next = _dbus_list_get_next_link (watches, link);
+
+ if (dbus_watch_get_enabled (watch))
{
- if (!(* wcb->function) (wcb->watch,
- condition,
- ((Callback*)wcb)->data))
- wcb->last_iteration_oom = TRUE;
+ dbus_bool_t oom;
+
+ oom = !dbus_watch_handle (watch, condition);
+
+ if (oom)
+ {
+ _dbus_watch_set_oom_last_time (watch, TRUE);
+ }
#if MAINLOOP_SPEW
- _dbus_verbose (" Invoked watch, oom = %d\n",
- wcb->last_iteration_oom);
+ _dbus_verbose (" Invoked watch, oom = %d\n", oom);
#endif
-
retval = TRUE;
- }
- if (_DBUS_UNLIKELY (fds[i].revents & _DBUS_POLLNVAL))
- {
- _dbus_warn ("invalid request, socket fd %d not open\n",
- fds[i].fd);
- _dbus_watch_invalidate (wcb->watch);
- _dbus_loop_remove_watch (loop, wcb->watch, wcb->function,
- ((Callback *)wcb)->data);
+ /* We re-check this every time, in case the callback
+ * added/removed watches, which might make our position in
+ * the linked list invalid. See the FIXME above. */
+ if (initial_serial != loop->callback_list_serial)
+ goto next_iteration;
+
+ if (loop->depth != orig_depth)
+ goto next_iteration;
}
}
-
- ++i;
}
}
@@ -851,19 +890,7 @@ _dbus_loop_iterate (DBusLoop *loop,
if (fds && fds != stack_fds)
dbus_free (fds);
- if (watches_for_fds)
- {
- i = 0;
- while (i < n_fds)
- {
- callback_unref (&watches_for_fds[i]->callback);
- ++i;
- }
-
- if (watches_for_fds != stack_watches_for_fds)
- dbus_free (watches_for_fds);
- }
-
+
if (_dbus_loop_dispatch (loop))
retval = TRUE;
diff --git a/dbus/dbus-mainloop.h b/dbus/dbus-mainloop.h
index 656f8231..a3417adb 100644
--- a/dbus/dbus-mainloop.h
+++ b/dbus/dbus-mainloop.h
@@ -33,30 +33,18 @@ typedef struct DBusLoop DBusLoop;
typedef dbus_bool_t (* DBusWatchFunction) (DBusWatch *watch,
unsigned int condition,
void *data);
-typedef void (* DBusTimeoutFunction) (DBusTimeout *timeout,
- void *data);
DBusLoop* _dbus_loop_new (void);
DBusLoop* _dbus_loop_ref (DBusLoop *loop);
void _dbus_loop_unref (DBusLoop *loop);
dbus_bool_t _dbus_loop_add_watch (DBusLoop *loop,
- DBusWatch *watch,
- DBusWatchFunction function,
- void *data,
- DBusFreeFunction free_data_func);
+ DBusWatch *watch);
void _dbus_loop_remove_watch (DBusLoop *loop,
- DBusWatch *watch,
- DBusWatchFunction function,
- void *data);
+ DBusWatch *watch);
dbus_bool_t _dbus_loop_add_timeout (DBusLoop *loop,
- DBusTimeout *timeout,
- DBusTimeoutFunction function,
- void *data,
- DBusFreeFunction free_data_func);
+ DBusTimeout *timeout);
void _dbus_loop_remove_timeout (DBusLoop *loop,
- DBusTimeout *timeout,
- DBusTimeoutFunction function,
- void *data);
+ DBusTimeout *timeout);
dbus_bool_t _dbus_loop_queue_dispatch (DBusLoop *loop,
DBusConnection *connection);
diff --git a/dbus/dbus-marshal-basic.c b/dbus/dbus-marshal-basic.c
index 215cc954..085ec5d4 100644
--- a/dbus/dbus-marshal-basic.c
+++ b/dbus/dbus-marshal-basic.c
@@ -1264,44 +1264,6 @@ _dbus_type_get_alignment (int typecode)
}
}
-
-/**
- * Return #TRUE if the typecode is a valid typecode.
- * #DBUS_TYPE_INVALID surprisingly enough is not considered valid, and
- * random unknown bytes aren't either. This function is safe with
- * untrusted data.
- *
- * @returns #TRUE if valid
- */
-dbus_bool_t
-_dbus_type_is_valid (int typecode)
-{
- switch (typecode)
- {
- case DBUS_TYPE_BYTE:
- case DBUS_TYPE_BOOLEAN:
- case DBUS_TYPE_INT16:
- case DBUS_TYPE_UINT16:
- case DBUS_TYPE_INT32:
- case DBUS_TYPE_UINT32:
- case DBUS_TYPE_INT64:
- case DBUS_TYPE_UINT64:
- case DBUS_TYPE_DOUBLE:
- case DBUS_TYPE_STRING:
- case DBUS_TYPE_OBJECT_PATH:
- case DBUS_TYPE_SIGNATURE:
- case DBUS_TYPE_ARRAY:
- case DBUS_TYPE_STRUCT:
- case DBUS_TYPE_DICT_ENTRY:
- case DBUS_TYPE_VARIANT:
- case DBUS_TYPE_UNIX_FD:
- return TRUE;
-
- default:
- return FALSE;
- }
-}
-
/**
* Returns a string describing the given type.
*
diff --git a/dbus/dbus-marshal-basic.h b/dbus/dbus-marshal-basic.h
index 0c27fc9e..3c448dff 100644
--- a/dbus/dbus-marshal-basic.h
+++ b/dbus/dbus-marshal-basic.h
@@ -254,7 +254,6 @@ dbus_uint32_t _dbus_marshal_read_uint32 (const DBusString *str,
int pos,
int byte_order,
int *new_pos);
-dbus_bool_t _dbus_type_is_valid (int typecode);
int _dbus_type_get_alignment (int typecode);
dbus_bool_t _dbus_type_is_fixed (int typecode);
int _dbus_type_get_alignment (int typecode);
diff --git a/dbus/dbus-marshal-header.c b/dbus/dbus-marshal-header.c
index a6c9b80d..28984f4c 100644
--- a/dbus/dbus-marshal-header.c
+++ b/dbus/dbus-marshal-header.c
@@ -165,6 +165,20 @@ _dbus_header_cache_one (DBusHeader *header,
}
/**
+ * Returns the header's byte order.
+ *
+ * @param header the header
+ * @returns the byte order
+ */
+char
+_dbus_header_get_byte_order (const DBusHeader *header)
+{
+ _dbus_assert (_dbus_string_get_length (&header->data) > BYTE_ORDER_OFFSET);
+
+ return (char) _dbus_string_get_byte (&header->data, BYTE_ORDER_OFFSET);
+}
+
+/**
* Revalidates the fields cache
*
* @param header the header
@@ -184,7 +198,7 @@ _dbus_header_cache_revalidate (DBusHeader *header)
}
_dbus_type_reader_init (&reader,
- header->byte_order,
+ _dbus_header_get_byte_order (header),
&_dbus_header_signature_str,
FIELDS_ARRAY_SIGNATURE_OFFSET,
&header->data,
@@ -398,7 +412,7 @@ _dbus_header_set_serial (DBusHeader *header,
_dbus_marshal_set_uint32 (&header->data,
SERIAL_OFFSET,
serial,
- header->byte_order);
+ _dbus_header_get_byte_order (header));
}
/**
@@ -412,7 +426,7 @@ _dbus_header_get_serial (DBusHeader *header)
{
return _dbus_marshal_read_uint32 (&header->data,
SERIAL_OFFSET,
- header->byte_order,
+ _dbus_header_get_byte_order (header),
NULL);
}
@@ -422,15 +436,12 @@ _dbus_header_get_serial (DBusHeader *header)
* _dbus_header_create().
*
* @param header header to re-initialize
- * @param byte_order byte order of the header
*/
void
-_dbus_header_reinit (DBusHeader *header,
- int byte_order)
+_dbus_header_reinit (DBusHeader *header)
{
_dbus_string_set_length (&header->data, 0);
- header->byte_order = byte_order;
header->padding = 0;
_dbus_header_cache_invalidate_all (header);
@@ -445,13 +456,12 @@ _dbus_header_reinit (DBusHeader *header,
* @returns #FALSE if not enough memory
*/
dbus_bool_t
-_dbus_header_init (DBusHeader *header,
- int byte_order)
+_dbus_header_init (DBusHeader *header)
{
if (!_dbus_string_init_preallocated (&header->data, 32))
return FALSE;
- _dbus_header_reinit (header, byte_order);
+ _dbus_header_reinit (header);
return TRUE;
}
@@ -514,6 +524,7 @@ _dbus_header_copy (const DBusHeader *header,
*/
dbus_bool_t
_dbus_header_create (DBusHeader *header,
+ int byte_order,
int message_type,
const char *destination,
const char *path,
@@ -526,6 +537,8 @@ _dbus_header_create (DBusHeader *header,
DBusTypeWriter writer;
DBusTypeWriter array;
+ _dbus_assert (byte_order == DBUS_LITTLE_ENDIAN ||
+ byte_order == DBUS_BIG_ENDIAN);
_dbus_assert (((interface || message_type != DBUS_MESSAGE_TYPE_SIGNAL) && member) ||
(error_name) ||
!(interface || member || error_name));
@@ -534,12 +547,12 @@ _dbus_header_create (DBusHeader *header,
if (!reserve_header_padding (header))
return FALSE;
- _dbus_type_writer_init_values_only (&writer, header->byte_order,
+ _dbus_type_writer_init_values_only (&writer, byte_order,
&_dbus_header_signature_str, 0,
&header->data,
HEADER_END_BEFORE_PADDING (header));
- v_BYTE = header->byte_order;
+ v_BYTE = byte_order;
if (!_dbus_type_writer_write_basic (&writer, DBUS_TYPE_BYTE,
&v_BYTE))
goto oom;
@@ -911,7 +924,8 @@ load_and_validate_field (DBusHeader *header,
_dbus_assert (bad_string_code != DBUS_VALID);
len = _dbus_marshal_read_uint32 (value_str, value_pos,
- header->byte_order, NULL);
+ _dbus_header_get_byte_order (header),
+ NULL);
#if 0
_dbus_verbose ("Validating string header field; code %d if fails\n",
@@ -1042,7 +1056,6 @@ _dbus_header_load (DBusHeader *header,
_dbus_type_reader_next (&reader);
_dbus_assert (v_byte == byte_order);
- header->byte_order = byte_order;
/* MESSAGE TYPE */
_dbus_assert (_dbus_type_reader_get_current_type (&reader) == DBUS_TYPE_BYTE);
@@ -1184,7 +1197,7 @@ _dbus_header_update_lengths (DBusHeader *header,
_dbus_marshal_set_uint32 (&header->data,
BODY_LENGTH_OFFSET,
body_len,
- header->byte_order);
+ _dbus_header_get_byte_order (header));
}
static dbus_bool_t
@@ -1198,7 +1211,7 @@ find_field_for_modification (DBusHeader *header,
retval = FALSE;
_dbus_type_reader_init (realign_root,
- header->byte_order,
+ _dbus_header_get_byte_order (header),
&_dbus_header_signature_str,
FIELDS_ARRAY_SIGNATURE_OFFSET,
&header->data,
@@ -1271,7 +1284,7 @@ _dbus_header_set_field_basic (DBusHeader *header,
DBusTypeWriter array;
_dbus_type_writer_init_values_only (&writer,
- header->byte_order,
+ _dbus_header_get_byte_order (header),
&_dbus_header_signature_str,
FIELDS_ARRAY_SIGNATURE_OFFSET,
&header->data,
@@ -1341,7 +1354,7 @@ _dbus_header_get_field_basic (DBusHeader *header,
_dbus_marshal_read_basic (&header->data,
header->fields[field].value_pos,
- type, value, header->byte_order,
+ type, value, _dbus_header_get_byte_order (header),
NULL);
return TRUE;
@@ -1468,21 +1481,19 @@ void
_dbus_header_byteswap (DBusHeader *header,
int new_order)
{
- unsigned char byte_order;
+ char byte_order;
- if (header->byte_order == new_order)
- return;
+ byte_order = _dbus_header_get_byte_order (header);
- byte_order = _dbus_string_get_byte (&header->data, BYTE_ORDER_OFFSET);
- _dbus_assert (header->byte_order == byte_order);
+ if (byte_order == new_order)
+ return;
_dbus_marshal_byteswap (&_dbus_header_signature_str,
- 0, header->byte_order,
+ 0, byte_order,
new_order,
&header->data, 0);
_dbus_string_set_byte (&header->data, BYTE_ORDER_OFFSET, new_order);
- header->byte_order = new_order;
}
/** @} */
diff --git a/dbus/dbus-marshal-header.h b/dbus/dbus-marshal-header.h
index fd16c5f0..350fe5c4 100644
--- a/dbus/dbus-marshal-header.h
+++ b/dbus/dbus-marshal-header.h
@@ -59,12 +59,11 @@ struct DBusHeader
dbus_uint32_t byte_order : 8; /**< byte order of header */
};
-dbus_bool_t _dbus_header_init (DBusHeader *header,
- int byte_order);
+dbus_bool_t _dbus_header_init (DBusHeader *header);
void _dbus_header_free (DBusHeader *header);
-void _dbus_header_reinit (DBusHeader *header,
- int byte_order);
+void _dbus_header_reinit (DBusHeader *header);
dbus_bool_t _dbus_header_create (DBusHeader *header,
+ int byte_order,
int type,
const char *destination,
const char *path,
@@ -122,6 +121,7 @@ dbus_bool_t _dbus_header_load (DBusHeader *header,
int len);
void _dbus_header_byteswap (DBusHeader *header,
int new_order);
+char _dbus_header_get_byte_order (const DBusHeader *header);
diff --git a/dbus/dbus-marshal-recursive-util.c b/dbus/dbus-marshal-recursive-util.c
index 3508bb0d..345b891f 100644
--- a/dbus/dbus-marshal-recursive-util.c
+++ b/dbus/dbus-marshal-recursive-util.c
@@ -3326,7 +3326,6 @@ dict_write_value (TestTypeNode *node,
DBusString dict_entry_signature;
int i;
int n_entries;
- int entry_value_type;
TestTypeNode *child;
n_entries = node->klass->subclass_detail;
@@ -3363,9 +3362,7 @@ dict_write_value (TestTypeNode *node,
if (!_dbus_string_append_byte (&dict_entry_signature,
DBUS_DICT_ENTRY_END_CHAR))
goto oom;
-
- entry_value_type = _dbus_first_type_in_signature (&entry_value_signature, 0);
-
+
if (!_dbus_type_writer_recurse (writer, DBUS_TYPE_ARRAY,
&dict_entry_signature, 0,
&sub))
diff --git a/dbus/dbus-marshal-validate.c b/dbus/dbus-marshal-validate.c
index 4304467d..9187a3e9 100644
--- a/dbus/dbus-marshal-validate.c
+++ b/dbus/dbus-marshal-validate.c
@@ -250,7 +250,7 @@ _dbus_validate_signature_with_reason (const DBusString *type_str,
if (last == DBUS_DICT_ENTRY_BEGIN_CHAR)
{
- if (!(_dbus_type_is_valid (*p) && dbus_type_is_basic (*p)))
+ if (!(dbus_type_is_valid (*p) && dbus_type_is_basic (*p)))
{
result = DBUS_INVALID_DICT_KEY_MUST_BE_BASIC_TYPE;
goto out;
@@ -393,7 +393,7 @@ validate_body_helper (DBusTypeReader *reader,
{
int array_elem_type = _dbus_type_reader_get_element_type (reader);
- if (!_dbus_type_is_valid (array_elem_type))
+ if (!dbus_type_is_valid (array_elem_type))
{
return DBUS_INVALID_UNKNOWN_TYPECODE;
}
@@ -1082,23 +1082,11 @@ _dbus_validate_error_name (const DBusString *str,
((c) >= 'a' && (c) <= 'z') || \
((c) == '_') || ((c) == '-'))
-/**
- * Checks that the given range of the string is a valid bus name in
- * the D-Bus protocol. This includes a length restriction, etc., see
- * the specification.
- *
- * @todo this is inconsistent with most of DBusString in that
- * it allows a start,len range that extends past the string end.
- *
- * @param str the string
- * @param start first byte index to check
- * @param len number of bytes to check
- * @returns #TRUE if the byte range exists and is a valid name
- */
-dbus_bool_t
-_dbus_validate_bus_name (const DBusString *str,
- int start,
- int len)
+static dbus_bool_t
+_dbus_validate_bus_name_full (const DBusString *str,
+ int start,
+ int len,
+ dbus_bool_t is_namespace)
{
const unsigned char *s;
const unsigned char *end;
@@ -1176,13 +1164,55 @@ _dbus_validate_bus_name (const DBusString *str,
++s;
}
- if (_DBUS_UNLIKELY (last_dot == NULL))
+ if (!is_namespace && _DBUS_UNLIKELY (last_dot == NULL))
return FALSE;
return TRUE;
}
/**
+ * Checks that the given range of the string is a valid bus name in
+ * the D-Bus protocol. This includes a length restriction, etc., see
+ * the specification.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_validate_bus_name (const DBusString *str,
+ int start,
+ int len)
+{
+ return _dbus_validate_bus_name_full (str, start, len, FALSE);
+}
+
+/**
+ * Checks that the given range of the string is a prefix of a valid bus name in
+ * the D-Bus protocol. Unlike _dbus_validate_bus_name(), this accepts strings
+ * with only one period-separated component.
+ *
+ * @todo this is inconsistent with most of DBusString in that
+ * it allows a start,len range that extends past the string end.
+ *
+ * @param str the string
+ * @param start first byte index to check
+ * @param len number of bytes to check
+ * @returns #TRUE if the byte range exists and is a valid name
+ */
+dbus_bool_t
+_dbus_validate_bus_namespace (const DBusString *str,
+ int start,
+ int len)
+{
+ return _dbus_validate_bus_name_full (str, start, len, TRUE);
+}
+
+/**
* Checks that the given range of the string is a valid message type
* signature in the D-Bus protocol.
*
diff --git a/dbus/dbus-marshal-validate.h b/dbus/dbus-marshal-validate.h
index 1d2e26b8..06434201 100644
--- a/dbus/dbus-marshal-validate.h
+++ b/dbus/dbus-marshal-validate.h
@@ -144,6 +144,9 @@ dbus_bool_t _dbus_validate_error_name (const DBusString *str,
dbus_bool_t _dbus_validate_bus_name (const DBusString *str,
int start,
int len);
+dbus_bool_t _dbus_validate_bus_namespace (const DBusString *str,
+ int start,
+ int len);
dbus_bool_t _dbus_validate_signature (const DBusString *str,
int start,
int len);
diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c
index ee40e82b..c5f46413 100644
--- a/dbus/dbus-memory.c
+++ b/dbus/dbus-memory.c
@@ -233,7 +233,6 @@ _dbus_get_fail_alloc_failures (void)
}
#ifdef DBUS_BUILD_TESTS
-static dbus_bool_t called = 0;
/**
* Called when about to alloc some memory; if
* it returns #TRUE, then the allocation should
@@ -248,6 +247,8 @@ _dbus_decrement_fail_alloc_counter (void)
_dbus_initialize_malloc_debug ();
#ifdef DBUS_WIN_FIXME
{
+ static dbus_bool_t called = 0;
+
if (!called)
{
_dbus_verbose("TODO: memory allocation testing errors disabled for now\n");
diff --git a/dbus/dbus-mempool.c b/dbus/dbus-mempool.c
index 680586b7..563bffc6 100644
--- a/dbus/dbus-mempool.c
+++ b/dbus/dbus-mempool.c
@@ -390,6 +390,48 @@ _dbus_mem_pool_dealloc (DBusMemPool *pool,
}
}
+#ifdef DBUS_ENABLE_STATS
+void
+_dbus_mem_pool_get_stats (DBusMemPool *pool,
+ dbus_uint32_t *in_use_p,
+ dbus_uint32_t *in_free_list_p,
+ dbus_uint32_t *allocated_p)
+{
+ DBusMemBlock *block;
+ DBusFreedElement *freed;
+ dbus_uint32_t in_use = 0;
+ dbus_uint32_t in_free_list = 0;
+ dbus_uint32_t allocated = 0;
+
+ if (pool != NULL)
+ {
+ in_use = pool->element_size * pool->allocated_elements;
+
+ for (freed = pool->free_elements; freed != NULL; freed = freed->next)
+ {
+ in_free_list += pool->element_size;
+ }
+
+ for (block = pool->blocks; block != NULL; block = block->next)
+ {
+ if (block == pool->blocks)
+ allocated += pool->block_size;
+ else
+ allocated += block->used_so_far;
+ }
+ }
+
+ if (in_use_p != NULL)
+ *in_use_p = in_use;
+
+ if (in_free_list_p != NULL)
+ *in_free_list_p = in_free_list;
+
+ if (allocated_p != NULL)
+ *allocated_p = allocated;
+}
+#endif /* DBUS_ENABLE_STATS */
+
/** @} */
#ifdef DBUS_BUILD_TESTS
diff --git a/dbus/dbus-mempool.h b/dbus/dbus-mempool.h
index afe52472..6693eeb2 100644
--- a/dbus/dbus-mempool.h
+++ b/dbus/dbus-mempool.h
@@ -39,6 +39,12 @@ void* _dbus_mem_pool_alloc (DBusMemPool *pool);
dbus_bool_t _dbus_mem_pool_dealloc (DBusMemPool *pool,
void *element);
+/* if DBUS_ENABLE_STATS */
+void _dbus_mem_pool_get_stats (DBusMemPool *pool,
+ dbus_uint32_t *in_use_p,
+ dbus_uint32_t *in_free_list_p,
+ dbus_uint32_t *allocated_p);
+
DBUS_END_DECLS
#endif /* DBUS_MEMPOOL_H */
diff --git a/dbus/dbus-message-factory.c b/dbus/dbus-message-factory.c
index 7ecf8270..efa4e029 100644
--- a/dbus/dbus-message-factory.c
+++ b/dbus/dbus-message-factory.c
@@ -27,6 +27,7 @@
#ifdef DBUS_BUILD_TESTS
#include "dbus-message-factory.h"
#include "dbus-message-private.h"
+#include "dbus-signature.h"
#include "dbus-test.h"
#include <stdio.h>
@@ -169,6 +170,7 @@ generate_many_bodies_inner (DBusMessageDataIter *iter,
DBusMessage *message;
DBusString signature;
DBusString body;
+ char byte_order;
/* Keeping this small makes things go faster */
message = dbus_message_new_method_call ("o.z.F",
@@ -178,13 +180,15 @@ generate_many_bodies_inner (DBusMessageDataIter *iter,
if (message == NULL)
_dbus_assert_not_reached ("oom");
+ byte_order = _dbus_header_get_byte_order (&message->header);
+
set_reply_serial (message);
if (!_dbus_string_init (&signature) || !_dbus_string_init (&body))
_dbus_assert_not_reached ("oom");
if (dbus_internal_do_not_use_generate_bodies (iter_get_sequence (iter),
- message->byte_order,
+ byte_order,
&signature, &body))
{
const char *v_SIGNATURE;
@@ -201,7 +205,7 @@ generate_many_bodies_inner (DBusMessageDataIter *iter,
_dbus_marshal_set_uint32 (&message->header.data, BODY_LENGTH_OFFSET,
_dbus_string_get_length (&message->body),
- message->byte_order);
+ byte_order);
*message_p = message;
}
@@ -577,15 +581,18 @@ generate_special (DBusMessageDataIter *iter,
}
else if (item_seq == 8)
{
+ char byte_order;
+
message = simple_method_call ();
+ byte_order = _dbus_header_get_byte_order (&message->header);
generate_from_message (data, expected_validity, message);
_dbus_marshal_set_uint32 (data, BODY_LENGTH_OFFSET,
DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
- message->byte_order);
+ byte_order);
_dbus_marshal_set_uint32 (data, FIELDS_ARRAY_LENGTH_OFFSET,
DBUS_MAXIMUM_MESSAGE_LENGTH / 2 + 4,
- message->byte_order);
+ byte_order);
*expected_validity = DBUS_INVALID_MESSAGE_TOO_LONG;
}
else if (item_seq == 9)
@@ -935,6 +942,9 @@ generate_byte_changed (DBusMessageDataIter *iter,
return TRUE;
}
+#if 0
+/* This is really expensive and doesn't add too much coverage */
+
static dbus_bool_t
find_next_typecode (DBusMessageDataIter *iter,
DBusString *data,
@@ -978,7 +988,7 @@ find_next_typecode (DBusMessageDataIter *iter,
_dbus_assert (byte_seq < _dbus_string_get_length (data));
- if (_dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq)))
+ if (dbus_type_is_valid (_dbus_string_get_byte (data, byte_seq)))
break;
else
iter_next (iter);
@@ -1017,7 +1027,7 @@ static const int typecodes[] = {
DBUS_TYPE_UNIX_FD,
255 /* random invalid typecode */
};
-
+
static dbus_bool_t
generate_typecode_changed (DBusMessageDataIter *iter,
DBusString *data,
@@ -1074,6 +1084,7 @@ generate_typecode_changed (DBusMessageDataIter *iter,
*expected_validity = DBUS_VALIDITY_UNKNOWN;
return TRUE;
}
+#endif
typedef struct
{
diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h
index 870934b9..d4e8a6c5 100644
--- a/dbus/dbus-message-internal.h
+++ b/dbus/dbus-message-internal.h
@@ -46,8 +46,7 @@ dbus_bool_t _dbus_message_add_counter (DBusMessage *message,
void _dbus_message_add_counter_link (DBusMessage *message,
DBusList *link);
void _dbus_message_remove_counter (DBusMessage *message,
- DBusCounter *counter,
- DBusList **link_return);
+ DBusCounter *counter);
DBusMessageLoader* _dbus_message_loader_new (void);
DBusMessageLoader* _dbus_message_loader_ref (DBusMessageLoader *loader);
diff --git a/dbus/dbus-message-private.h b/dbus/dbus-message-private.h
index c5e3b3ea..e64258ca 100644
--- a/dbus/dbus-message-private.h
+++ b/dbus/dbus-message-private.h
@@ -102,8 +102,6 @@ struct DBusMessage
DBusString body; /**< Body network data. */
- char byte_order; /**< Message byte order. */
-
unsigned int locked : 1; /**< Message being sent, no modifications allowed. */
#ifndef DBUS_DISABLE_CHECKS
diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c
index a95ad0fa..cc1cfa17 100644
--- a/dbus/dbus-message.c
+++ b/dbus/dbus-message.c
@@ -115,8 +115,11 @@ _dbus_message_byteswap (DBusMessage *message)
{
const DBusString *type_str;
int type_pos;
-
- if (message->byte_order == DBUS_COMPILER_BYTE_ORDER)
+ 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");
@@ -124,13 +127,13 @@ _dbus_message_byteswap (DBusMessage *message)
get_const_signature (&message->header, &type_str, &type_pos);
_dbus_marshal_byteswap (type_str, type_pos,
- message->byte_order,
+ byte_order,
DBUS_COMPILER_BYTE_ORDER,
&message->body, 0);
- message->byte_order = DBUS_COMPILER_BYTE_ORDER;
-
_dbus_header_byteswap (&message->header, DBUS_COMPILER_BYTE_ORDER);
+ _dbus_assert (_dbus_header_get_byte_order (&message->header) ==
+ DBUS_COMPILER_BYTE_ORDER);
}
/** byte-swap the message if it doesn't match our byte order.
@@ -139,9 +142,7 @@ _dbus_message_byteswap (DBusMessage *message)
* Otherwise should not be called since it would do needless
* work.
*/
-#define ensure_byte_order(message) \
- if (message->byte_order != DBUS_COMPILER_BYTE_ORDER) \
- _dbus_message_byteswap (message)
+#define ensure_byte_order(message) _dbus_message_byteswap (message)
/**
* Gets the data to be sent over the network for this message.
@@ -217,6 +218,11 @@ dbus_message_set_serial (DBusMessage *message,
* itself not incremented. Ownership of link and counter refcount is
* passed to the message.
*
+ * This function may be called with locks held. As a result, the counter's
+ * notify function is not called; the caller is expected to either call
+ * _dbus_counter_notify() on the counter when they are no longer holding
+ * locks, or take the same action that would be taken by the notify function.
+ *
* @param message the message
* @param link link with counter as data
*/
@@ -260,6 +266,11 @@ _dbus_message_add_counter_link (DBusMessage *message,
* of this message, and decremented by the size/unix fds of this
* message when this message if finalized.
*
+ * This function may be called with locks held. As a result, the counter's
+ * notify function is not called; the caller is expected to either call
+ * _dbus_counter_notify() on the counter when they are no longer holding
+ * locks, or take the same action that would be taken by the notify function.
+ *
* @param message the message
* @param counter the counter
* @returns #FALSE if no memory
@@ -285,13 +296,11 @@ _dbus_message_add_counter (DBusMessage *message,
* decrements the counter by the size/unix fds of this message.
*
* @param message the message
- * @param link_return return the link used
* @param counter the counter
*/
void
_dbus_message_remove_counter (DBusMessage *message,
- DBusCounter *counter,
- DBusList **link_return)
+ DBusCounter *counter)
{
DBusList *link;
@@ -299,12 +308,7 @@ _dbus_message_remove_counter (DBusMessage *message,
counter);
_dbus_assert (link != NULL);
- _dbus_list_unlink (&message->counters,
- link);
- if (link_return)
- *link_return = link;
- else
- _dbus_list_free_link (link);
+ _dbus_list_remove_link (&message->counters, link);
_dbus_counter_adjust_size (counter, - message->size_counter_delta);
@@ -312,6 +316,7 @@ _dbus_message_remove_counter (DBusMessage *message,
_dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
#endif
+ _dbus_counter_notify (counter);
_dbus_counter_unref (counter);
}
@@ -574,6 +579,7 @@ free_counter (void *element,
_dbus_counter_adjust_unix_fd (counter, - message->unix_fd_counter_delta);
#endif
+ _dbus_counter_notify (counter);
_dbus_counter_unref (counter);
}
@@ -662,15 +668,19 @@ dbus_message_cache_or_finalize (DBusMessage *message)
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\n");
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 != iter->message->byte_order)
+ if (iter->u.reader.byte_order != byte_order)
{
_dbus_warn_check_failed ("dbus message changed byte order since iterator was created\n");
return FALSE;
@@ -680,7 +690,7 @@ _dbus_message_iter_check (DBusMessageRealIter *iter)
}
else if (iter->iter_type == DBUS_MESSAGE_ITER_TYPE_WRITER)
{
- if (iter->u.writer.byte_order != iter->message->byte_order)
+ if (iter->u.writer.byte_order != byte_order)
{
_dbus_warn_check_failed ("dbus message changed byte order since append iterator was created\n");
return FALSE;
@@ -1092,7 +1102,6 @@ dbus_message_new_empty_header (void)
_dbus_atomic_inc (&message->refcount);
- message->byte_order = DBUS_COMPILER_BYTE_ORDER;
message->locked = FALSE;
#ifndef DBUS_DISABLE_CHECKS
message->in_cache = FALSE;
@@ -1112,12 +1121,12 @@ dbus_message_new_empty_header (void)
if (from_cache)
{
- _dbus_header_reinit (&message->header, message->byte_order);
+ _dbus_header_reinit (&message->header);
_dbus_string_set_length (&message->body, 0);
}
else
{
- if (!_dbus_header_init (&message->header, message->byte_order))
+ if (!_dbus_header_init (&message->header))
{
dbus_free (message);
return NULL;
@@ -1158,6 +1167,7 @@ dbus_message_new (int message_type)
return NULL;
if (!_dbus_header_create (&message->header,
+ DBUS_COMPILER_BYTE_ORDER,
message_type,
NULL, NULL, NULL, NULL, NULL))
{
@@ -1211,6 +1221,7 @@ dbus_message_new_method_call (const char *destination,
return NULL;
if (!_dbus_header_create (&message->header,
+ DBUS_COMPILER_BYTE_ORDER,
DBUS_MESSAGE_TYPE_METHOD_CALL,
destination, path, interface, method, NULL))
{
@@ -1245,6 +1256,7 @@ dbus_message_new_method_return (DBusMessage *method_call)
return NULL;
if (!_dbus_header_create (&message->header,
+ DBUS_COMPILER_BYTE_ORDER,
DBUS_MESSAGE_TYPE_METHOD_RETURN,
sender, NULL, NULL, NULL, NULL))
{
@@ -1297,6 +1309,7 @@ dbus_message_new_signal (const char *path,
return NULL;
if (!_dbus_header_create (&message->header,
+ DBUS_COMPILER_BYTE_ORDER,
DBUS_MESSAGE_TYPE_SIGNAL,
NULL, path, interface, name, NULL))
{
@@ -1347,6 +1360,7 @@ dbus_message_new_error (DBusMessage *reply_to,
return NULL;
if (!_dbus_header_create (&message->header,
+ DBUS_COMPILER_BYTE_ORDER,
DBUS_MESSAGE_TYPE_ERROR,
sender, NULL, NULL, NULL, error_name))
{
@@ -1451,7 +1465,7 @@ dbus_message_copy (const DBusMessage *message)
return NULL;
_dbus_atomic_inc (&retval->refcount);
- retval->byte_order = message->byte_order;
+
retval->locked = FALSE;
#ifndef DBUS_DISABLE_CHECKS
retval->generation = message->generation;
@@ -1937,7 +1951,7 @@ dbus_message_iter_init (DBusMessage *message,
DBUS_MESSAGE_ITER_TYPE_READER);
_dbus_type_reader_init (&real->u.reader,
- message->byte_order,
+ _dbus_header_get_byte_order (&message->header),
type_str, type_pos,
&message->body,
0);
@@ -2292,7 +2306,7 @@ dbus_message_iter_init_append (DBusMessage *message,
* due to OOM.
*/
_dbus_type_writer_init_types_delayed (&real->u.writer,
- message->byte_order,
+ _dbus_header_get_byte_order (&message->header),
&message->body,
_dbus_string_get_length (&message->body));
}
@@ -4003,8 +4017,6 @@ load_message (DBusMessageLoader *loader,
_dbus_assert (validity == DBUS_VALID);
- message->byte_order = byte_order;
-
/* 2. VALIDATE BODY */
if (mode != DBUS_VALIDATION_MODE_WE_TRUST_THIS_DATA_ABSOLUTELY)
{
diff --git a/dbus/dbus-nonce.c b/dbus/dbus-nonce.c
index d30b2535..e74c2dd5 100644
--- a/dbus/dbus-nonce.c
+++ b/dbus/dbus-nonce.c
@@ -196,7 +196,6 @@ _dbus_send_nonce (int fd, const DBusString *noncefile, DBusError *error)
{
dbus_bool_t read_result;
int send_result;
- size_t sendLen;
DBusString nonce;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -240,7 +239,6 @@ do_noncefile_create (DBusNonceFile *noncefile,
DBusError *error,
dbus_bool_t use_subdir)
{
- dbus_bool_t ret;
DBusString randomStr;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
diff --git a/dbus/dbus-object-tree.c b/dbus/dbus-object-tree.c
index d244045c..172c9d95 100644
--- a/dbus/dbus-object-tree.c
+++ b/dbus/dbus-object-tree.c
@@ -745,7 +745,8 @@ handle_default_introspect_and_unlock (DBusObjectTree *tree,
*/
DBusHandlerResult
_dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree,
- DBusMessage *message)
+ DBusMessage *message,
+ dbus_bool_t *found_object)
{
char **path;
dbus_bool_t exact_match;
@@ -791,6 +792,9 @@ _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree,
/* Find the deepest path that covers the path in the message */
subtree = find_handler (tree, (const char**) path, &exact_match);
+ if (found_object)
+ *found_object = !!subtree;
+
/* Build a list of all paths that cover the path in the message */
list = NULL;
@@ -1391,7 +1395,7 @@ do_test_dispatch (DBusObjectTree *tree,
++j;
}
- result = _dbus_object_tree_dispatch_and_unlock (tree, message);
+ result = _dbus_object_tree_dispatch_and_unlock (tree, message, NULL);
if (result == DBUS_HANDLER_RESULT_NEED_MEMORY)
goto oom;
diff --git a/dbus/dbus-object-tree.h b/dbus/dbus-object-tree.h
index 022dd93f..5576c25d 100644
--- a/dbus/dbus-object-tree.h
+++ b/dbus/dbus-object-tree.h
@@ -42,7 +42,8 @@ dbus_bool_t _dbus_object_tree_register (DBusObjectTree
void _dbus_object_tree_unregister_and_unlock (DBusObjectTree *tree,
const char **path);
DBusHandlerResult _dbus_object_tree_dispatch_and_unlock (DBusObjectTree *tree,
- DBusMessage *message);
+ DBusMessage *message,
+ dbus_bool_t *found_object);
void* _dbus_object_tree_get_user_data_unlocked (DBusObjectTree *tree,
const char **path);
void _dbus_object_tree_free_all_unlocked (DBusObjectTree *tree);
diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c
index cfb2bafe..f9613195 100644
--- a/dbus/dbus-pending-call.c
+++ b/dbus/dbus-pending-call.c
@@ -353,6 +353,8 @@ _dbus_pending_call_set_timeout_error_unlocked (DBusPendingCall *pending,
reply_link = _dbus_list_alloc_link (reply);
if (reply_link == NULL)
{
+ /* it's OK to unref this, nothing that could have attached a callback
+ * has ever seen it */
dbus_message_unref (reply);
return FALSE;
}
diff --git a/dbus/dbus-resources.c b/dbus/dbus-resources.c
index 5f7001cc..42aedf58 100644
--- a/dbus/dbus-resources.c
+++ b/dbus/dbus-resources.c
@@ -58,11 +58,17 @@ struct DBusCounter
long size_value; /**< current size counter value */
long unix_fd_value; /**< current unix fd counter value */
+#ifdef DBUS_ENABLE_STATS
+ long peak_size_value; /**< largest ever size counter value */
+ long peak_unix_fd_value; /**< largest ever unix fd counter value */
+#endif
+
long notify_size_guard_value; /**< call notify function when crossing this size value */
long notify_unix_fd_guard_value; /**< call notify function when crossing this unix fd value */
DBusCounterNotifyFunction notify_function; /**< notify function */
void *notify_data; /**< data for notify function */
+ dbus_bool_t notify_pending : 1; /**< TRUE if the guard value has been crossed */
};
/** @} */ /* end of resource limits internals docs */
@@ -91,10 +97,16 @@ _dbus_counter_new (void)
counter->size_value = 0;
counter->unix_fd_value = 0;
+#ifdef DBUS_ENABLE_STATS
+ counter->peak_size_value = 0;
+ counter->peak_unix_fd_value = 0;
+#endif
+
counter->notify_size_guard_value = 0;
counter->notify_unix_fd_guard_value = 0;
counter->notify_function = NULL;
counter->notify_data = NULL;
+ counter->notify_pending = FALSE;
return counter;
}
@@ -138,8 +150,9 @@ _dbus_counter_unref (DBusCounter *counter)
/**
* Adjusts the value of the size counter by the given
* delta which may be positive or negative.
- * Calls the notify function from _dbus_counter_set_notify()
- * if that function has been specified.
+ *
+ * This function may be called with locks held. After calling it, when
+ * any relevant locks are no longer held you must call _dbus_counter_notify().
*
* @param counter the counter
* @param delta value to add to the size counter's current value
@@ -152,6 +165,11 @@ _dbus_counter_adjust_size (DBusCounter *counter,
counter->size_value += delta;
+#ifdef DBUS_ENABLE_STATS
+ if (counter->peak_size_value < counter->size_value)
+ counter->peak_size_value = counter->size_value;
+#endif
+
#if 0
_dbus_verbose ("Adjusting counter %ld by %ld = %ld\n",
old, delta, counter->size_value);
@@ -162,14 +180,33 @@ _dbus_counter_adjust_size (DBusCounter *counter,
counter->size_value >= counter->notify_size_guard_value) ||
(old >= counter->notify_size_guard_value &&
counter->size_value < counter->notify_size_guard_value)))
- (* counter->notify_function) (counter, counter->notify_data);
+ counter->notify_pending = TRUE;
+}
+
+/**
+ * Calls the notify function from _dbus_counter_set_notify(),
+ * if that function has been specified and the counter has crossed the
+ * guard value (in either direction) since the last call to this function.
+ *
+ * This function must not be called with locks held, since it can call out
+ * to user code.
+ */
+void
+_dbus_counter_notify (DBusCounter *counter)
+{
+ if (counter->notify_pending)
+ {
+ counter->notify_pending = FALSE;
+ (* counter->notify_function) (counter, counter->notify_data);
+ }
}
/**
* Adjusts the value of the unix fd counter by the given
* delta which may be positive or negative.
- * Calls the notify function from _dbus_counter_set_notify()
- * if that function has been specified.
+ *
+ * This function may be called with locks held. After calling it, when
+ * any relevant locks are no longer held you must call _dbus_counter_notify().
*
* @param counter the counter
* @param delta value to add to the unix fds counter's current value
@@ -182,6 +219,11 @@ _dbus_counter_adjust_unix_fd (DBusCounter *counter,
counter->unix_fd_value += delta;
+#ifdef DBUS_ENABLE_STATS
+ if (counter->peak_unix_fd_value < counter->unix_fd_value)
+ counter->peak_unix_fd_value = counter->unix_fd_value;
+#endif
+
#if 0
_dbus_verbose ("Adjusting counter %ld by %ld = %ld\n",
old, delta, counter->unix_fd_value);
@@ -192,7 +234,7 @@ _dbus_counter_adjust_unix_fd (DBusCounter *counter,
counter->unix_fd_value >= counter->notify_unix_fd_guard_value) ||
(old >= counter->notify_unix_fd_guard_value &&
counter->unix_fd_value < counter->notify_unix_fd_guard_value)))
- (* counter->notify_function) (counter, counter->notify_data);
+ counter->notify_pending = TRUE;
}
/**
@@ -241,6 +283,21 @@ _dbus_counter_set_notify (DBusCounter *counter,
counter->notify_unix_fd_guard_value = unix_fd_guard_value;
counter->notify_function = function;
counter->notify_data = user_data;
+ counter->notify_pending = FALSE;
+}
+
+#ifdef DBUS_ENABLE_STATS
+long
+_dbus_counter_get_peak_size_value (DBusCounter *counter)
+{
+ return counter->peak_size_value;
}
+long
+_dbus_counter_get_peak_unix_fd_value (DBusCounter *counter)
+{
+ return counter->peak_unix_fd_value;
+}
+#endif
+
/** @} */ /* end of resource limits exported API */
diff --git a/dbus/dbus-resources.h b/dbus/dbus-resources.h
index 4763a97f..781a5756 100644
--- a/dbus/dbus-resources.h
+++ b/dbus/dbus-resources.h
@@ -42,6 +42,7 @@ void _dbus_counter_adjust_size (DBusCounter *counter,
long delta);
void _dbus_counter_adjust_unix_fd (DBusCounter *counter,
long delta);
+void _dbus_counter_notify (DBusCounter *counter);
long _dbus_counter_get_size_value (DBusCounter *counter);
long _dbus_counter_get_unix_fd_value (DBusCounter *counter);
@@ -51,6 +52,9 @@ void _dbus_counter_set_notify (DBusCounter *counter,
DBusCounterNotifyFunction function,
void *user_data);
+/* if DBUS_ENABLE_STATS */
+long _dbus_counter_get_peak_size_value (DBusCounter *counter);
+long _dbus_counter_get_peak_unix_fd_value (DBusCounter *counter);
DBUS_END_DECLS
diff --git a/dbus/dbus-server-socket.c b/dbus/dbus-server-socket.c
index e8a24e48..8e31da9d 100644
--- a/dbus/dbus-server-socket.c
+++ b/dbus/dbus-server-socket.c
@@ -89,10 +89,8 @@ handle_new_client_fd_and_unlock (DBusServer *server,
DBusConnection *connection;
DBusTransport *transport;
DBusNewConnectionFunction new_connection_function;
- DBusServerSocket* socket_server;
void *new_connection_data;
- socket_server = (DBusServerSocket*)server;
_dbus_verbose ("Creating new client connection with fd %d\n", client_fd);
HAVE_LOCK_CHECK (server);
@@ -236,6 +234,7 @@ socket_disconnect (DBusServer *server)
{
_dbus_server_remove_watch (server,
socket_server->watch[i]);
+ _dbus_watch_invalidate (socket_server->watch[i]);
_dbus_watch_unref (socket_server->watch[i]);
socket_server->watch[i] = NULL;
}
diff --git a/dbus/dbus-signature.c b/dbus/dbus-signature.c
index 9c13ff43..c130de5b 100644
--- a/dbus/dbus-signature.c
+++ b/dbus/dbus-signature.c
@@ -284,7 +284,8 @@ dbus_signature_validate_single (const char *signature,
* container types. #DBUS_TYPE_INVALID is not a container type.
*
* It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
- * to this function. The valid type-codes are defined by dbus-protocol.h.
+ * to this function. The valid type-codes are defined by dbus-protocol.h
+ * and can be checked with dbus_type_is_valid().
*
* @param typecode either a valid type-code or DBUS_TYPE_INVALID
* @returns #TRUE if type is a container
@@ -293,7 +294,7 @@ dbus_bool_t
dbus_type_is_container (int typecode)
{
/* only reasonable (non-line-noise) typecodes are allowed */
- _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
+ _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
FALSE);
return TYPE_IS_CONTAINER (typecode);
}
@@ -307,7 +308,8 @@ dbus_type_is_container (int typecode)
* type.
*
* It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
- * to this function. The valid type-codes are defined by dbus-protocol.h.
+ * to this function. The valid type-codes are defined by dbus-protocol.h
+ * and can be checked with dbus_type_is_valid().
*
* @param typecode either a valid type-code or DBUS_TYPE_INVALID
* @returns #TRUE if type is basic
@@ -316,7 +318,7 @@ dbus_bool_t
dbus_type_is_basic (int typecode)
{
/* only reasonable (non-line-noise) typecodes are allowed */
- _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
+ _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
FALSE);
/* everything that isn't invalid or a container */
@@ -337,7 +339,8 @@ dbus_type_is_basic (int typecode)
* function.
*
* It is an error to pass an invalid type-code, other than DBUS_TYPE_INVALID,
- * to this function. The valid type-codes are defined by dbus-protocol.h.
+ * to this function. The valid type-codes are defined by dbus-protocol.h
+ * and can be checked with dbus_type_is_valid().
*
* @param typecode either a valid type-code or DBUS_TYPE_INVALID
* @returns #FALSE if the type can occupy different lengths
@@ -346,7 +349,7 @@ dbus_bool_t
dbus_type_is_fixed (int typecode)
{
/* only reasonable (non-line-noise) typecodes are allowed */
- _dbus_return_val_if_fail (_dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
+ _dbus_return_val_if_fail (dbus_type_is_valid (typecode) || typecode == DBUS_TYPE_INVALID,
FALSE);
switch (typecode)
@@ -367,6 +370,44 @@ dbus_type_is_fixed (int typecode)
}
}
+/**
+ * Return #TRUE if the argument is a valid typecode.
+ * #DBUS_TYPE_INVALID surprisingly enough is not considered valid, and
+ * random unknown bytes aren't either. This function is safe with
+ * untrusted data.
+ *
+ * @param typecode a potential type-code
+ * @returns #TRUE if valid
+ */
+dbus_bool_t
+dbus_type_is_valid (int typecode)
+{
+ switch (typecode)
+ {
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ case DBUS_TYPE_DOUBLE:
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_OBJECT_PATH:
+ case DBUS_TYPE_SIGNATURE:
+ case DBUS_TYPE_ARRAY:
+ case DBUS_TYPE_STRUCT:
+ case DBUS_TYPE_DICT_ENTRY:
+ case DBUS_TYPE_VARIANT:
+ case DBUS_TYPE_UNIX_FD:
+ return TRUE;
+
+ default:
+ return FALSE;
+ }
+}
+
/** @} */ /* end of DBusSignature group */
#ifdef DBUS_BUILD_TESTS
diff --git a/dbus/dbus-signature.h b/dbus/dbus-signature.h
index ebf00c1e..443941c8 100644
--- a/dbus/dbus-signature.h
+++ b/dbus/dbus-signature.h
@@ -79,6 +79,9 @@ dbus_bool_t dbus_signature_validate_single (const char *signatur
DBusError *error);
DBUS_EXPORT
+dbus_bool_t dbus_type_is_valid (int typecode);
+
+DBUS_EXPORT
dbus_bool_t dbus_type_is_basic (int typecode);
DBUS_EXPORT
dbus_bool_t dbus_type_is_container (int typecode);
diff --git a/dbus/dbus-spawn-win.c b/dbus/dbus-spawn-win.c
index 8ac837ed..df073722 100644
--- a/dbus/dbus-spawn-win.c
+++ b/dbus/dbus-spawn-win.c
@@ -81,6 +81,8 @@ struct DBusBabysitter
DBusWatchList *watches;
DBusWatch *sitter_watch;
+ DBusBabysitterFinishedFunc finished_cb;
+ void *finished_data;
dbus_bool_t have_spawn_errno;
int spawn_errno;
@@ -154,6 +156,27 @@ _dbus_babysitter_ref (DBusBabysitter *sitter)
return sitter;
}
+static void
+close_socket_to_babysitter (DBusBabysitter *sitter)
+{
+ _dbus_verbose ("Closing babysitter\n");
+
+ if (sitter->sitter_watch != NULL)
+ {
+ _dbus_assert (sitter->watches != NULL);
+ _dbus_watch_list_remove_watch (sitter->watches, sitter->sitter_watch);
+ _dbus_watch_invalidate (sitter->sitter_watch);
+ _dbus_watch_unref (sitter->sitter_watch);
+ sitter->sitter_watch = NULL;
+ }
+
+ if (sitter->socket_to_babysitter != -1)
+ {
+ _dbus_close_socket (sitter->socket_to_babysitter, NULL);
+ sitter->socket_to_babysitter = -1;
+ }
+}
+
/**
* Decrement the reference count on the babysitter object.
*
@@ -172,11 +195,7 @@ _dbus_babysitter_unref (DBusBabysitter *sitter)
if (sitter->refcount == 0)
{
- if (sitter->socket_to_babysitter != -1)
- {
- _dbus_close_socket (sitter->socket_to_babysitter, NULL);
- sitter->socket_to_babysitter = -1;
- }
+ close_socket_to_babysitter (sitter);
if (sitter->socket_to_main != -1)
{
@@ -372,9 +391,15 @@ handle_watch (DBusWatch *watch,
*/
PING();
- _dbus_close_socket (sitter->socket_to_babysitter, NULL);
+ close_socket_to_babysitter (sitter);
PING();
- sitter->socket_to_babysitter = -1;
+
+ if (_dbus_babysitter_get_child_exited (sitter) &&
+ sitter->finished_cb != NULL)
+ {
+ sitter->finished_cb (sitter, sitter->finished_data);
+ sitter->finished_cb = NULL;
+ }
return TRUE;
}
@@ -668,6 +693,12 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
PING();
if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
{
+ /* we need to free it early so the destructor won't try to remove it
+ * without it having been added, which DBusLoop doesn't allow */
+ _dbus_watch_invalidate (sitter->sitter_watch);
+ _dbus_watch_unref (sitter->sitter_watch);
+ sitter->sitter_watch = NULL;
+
_DBUS_SET_OOM (error);
goto out0;
}
@@ -713,6 +744,15 @@ out0:
return FALSE;
}
+void
+_dbus_babysitter_set_result_function (DBusBabysitter *sitter,
+ DBusBabysitterFinishedFunc finished,
+ void *user_data)
+{
+ sitter->finished_cb = finished;
+ sitter->finished_data = user_data;
+}
+
#ifdef DBUS_BUILD_TESTS
#define LIVE_CHILDREN(sitter) ((sitter)->child_handle != NULL)
diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c
index a1bab3df..a4652a3e 100644
--- a/dbus/dbus-spawn.c
+++ b/dbus/dbus-spawn.c
@@ -205,6 +205,9 @@ struct DBusBabysitter
DBusWatch *error_watch; /**< Error pipe watch */
DBusWatch *sitter_watch; /**< Sitter pipe watch */
+ DBusBabysitterFinishedFunc finished_cb;
+ void *finished_data;
+
int errnum; /**< Error number */
int status; /**< Exit status code */
unsigned int have_child_status : 1; /**< True if child status has been reaped */
@@ -257,6 +260,9 @@ _dbus_babysitter_ref (DBusBabysitter *sitter)
return sitter;
}
+static void close_socket_to_babysitter (DBusBabysitter *sitter);
+static void close_error_pipe_from_child (DBusBabysitter *sitter);
+
/**
* Decrement the reference count on the babysitter object.
* When the reference count of the babysitter object reaches
@@ -273,25 +279,17 @@ _dbus_babysitter_unref (DBusBabysitter *sitter)
sitter->refcount -= 1;
if (sitter->refcount == 0)
- {
- if (sitter->socket_to_babysitter >= 0)
- {
- /* If we haven't forked other babysitters
- * since this babysitter and socket were
- * created then this close will cause the
- * babysitter to wake up from poll with
- * a hangup and then the babysitter will
- * quit itself.
- */
- _dbus_close_socket (sitter->socket_to_babysitter, NULL);
- sitter->socket_to_babysitter = -1;
- }
+ {
+ /* If we haven't forked other babysitters
+ * since this babysitter and socket were
+ * created then this close will cause the
+ * babysitter to wake up from poll with
+ * a hangup and then the babysitter will
+ * quit itself.
+ */
+ close_socket_to_babysitter (sitter);
- if (sitter->error_pipe_from_child >= 0)
- {
- _dbus_close_socket (sitter->error_pipe_from_child, NULL);
- sitter->error_pipe_from_child = -1;
- }
+ close_error_pipe_from_child (sitter);
if (sitter->sitter_pid > 0)
{
@@ -341,21 +339,7 @@ _dbus_babysitter_unref (DBusBabysitter *sitter)
sitter->sitter_pid = -1;
}
-
- if (sitter->error_watch)
- {
- _dbus_watch_invalidate (sitter->error_watch);
- _dbus_watch_unref (sitter->error_watch);
- sitter->error_watch = NULL;
- }
- if (sitter->sitter_watch)
- {
- _dbus_watch_invalidate (sitter->sitter_watch);
- _dbus_watch_unref (sitter->sitter_watch);
- sitter->sitter_watch = NULL;
- }
-
if (sitter->watches)
_dbus_watch_list_free (sitter->watches);
@@ -476,16 +460,42 @@ static void
close_socket_to_babysitter (DBusBabysitter *sitter)
{
_dbus_verbose ("Closing babysitter\n");
- _dbus_close_socket (sitter->socket_to_babysitter, NULL);
- sitter->socket_to_babysitter = -1;
+
+ if (sitter->sitter_watch != NULL)
+ {
+ _dbus_assert (sitter->watches != NULL);
+ _dbus_watch_list_remove_watch (sitter->watches, sitter->sitter_watch);
+ _dbus_watch_invalidate (sitter->sitter_watch);
+ _dbus_watch_unref (sitter->sitter_watch);
+ sitter->sitter_watch = NULL;
+ }
+
+ if (sitter->socket_to_babysitter >= 0)
+ {
+ _dbus_close_socket (sitter->socket_to_babysitter, NULL);
+ sitter->socket_to_babysitter = -1;
+ }
}
static void
close_error_pipe_from_child (DBusBabysitter *sitter)
{
_dbus_verbose ("Closing child error\n");
- _dbus_close_socket (sitter->error_pipe_from_child, NULL);
- sitter->error_pipe_from_child = -1;
+
+ if (sitter->error_watch != NULL)
+ {
+ _dbus_assert (sitter->watches != NULL);
+ _dbus_watch_list_remove_watch (sitter->watches, sitter->error_watch);
+ _dbus_watch_invalidate (sitter->error_watch);
+ _dbus_watch_unref (sitter->error_watch);
+ sitter->error_watch = NULL;
+ }
+
+ if (sitter->error_pipe_from_child >= 0)
+ {
+ _dbus_close_socket (sitter->error_pipe_from_child, NULL);
+ sitter->error_pipe_from_child = -1;
+ }
}
static void
@@ -752,7 +762,7 @@ handle_watch (DBusWatch *watch,
unsigned int condition,
void *data)
{
- DBusBabysitter *sitter = data;
+ DBusBabysitter *sitter = _dbus_babysitter_ref (data);
int revents;
int fd;
@@ -775,31 +785,19 @@ handle_watch (DBusWatch *watch,
babysitter_iteration (sitter, FALSE))
;
- /* Those might have closed the sockets we're watching. Before returning
- * to the main loop, we must sort that out. */
+ /* fd.o #32992: if the handle_* methods closed their sockets, they previously
+ * didn't always remove the watches. Check that we don't regress. */
+ _dbus_assert (sitter->socket_to_babysitter != -1 || sitter->sitter_watch == NULL);
+ _dbus_assert (sitter->error_pipe_from_child != -1 || sitter->error_watch == NULL);
- if (sitter->error_watch != NULL && sitter->error_pipe_from_child == -1)
+ if (_dbus_babysitter_get_child_exited (sitter) &&
+ sitter->finished_cb != NULL)
{
- _dbus_watch_invalidate (sitter->error_watch);
-
- if (sitter->watches != NULL)
- _dbus_watch_list_remove_watch (sitter->watches, sitter->error_watch);
-
- _dbus_watch_unref (sitter->error_watch);
- sitter->error_watch = NULL;
- }
-
- if (sitter->sitter_watch != NULL && sitter->socket_to_babysitter == -1)
- {
- _dbus_watch_invalidate (sitter->sitter_watch);
-
- if (sitter->watches != NULL)
- _dbus_watch_list_remove_watch (sitter->watches, sitter->sitter_watch);
-
- _dbus_watch_unref (sitter->sitter_watch);
- sitter->sitter_watch = NULL;
+ sitter->finished_cb (sitter, sitter->finished_data);
+ sitter->finished_cb = NULL;
}
+ _dbus_babysitter_unref (sitter);
return TRUE;
}
@@ -1189,6 +1187,12 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
if (!_dbus_watch_list_add_watch (sitter->watches, sitter->error_watch))
{
+ /* we need to free it early so the destructor won't try to remove it
+ * without it having been added, which DBusLoop doesn't allow */
+ _dbus_watch_invalidate (sitter->error_watch);
+ _dbus_watch_unref (sitter->error_watch);
+ sitter->error_watch = NULL;
+
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto cleanup_and_fail;
}
@@ -1204,6 +1208,12 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
if (!_dbus_watch_list_add_watch (sitter->watches, sitter->sitter_watch))
{
+ /* we need to free it early so the destructor won't try to remove it
+ * without it having been added, which DBusLoop doesn't allow */
+ _dbus_watch_invalidate (sitter->sitter_watch);
+ _dbus_watch_unref (sitter->sitter_watch);
+ sitter->sitter_watch = NULL;
+
dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
goto cleanup_and_fail;
}
@@ -1298,6 +1308,15 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
return FALSE;
}
+void
+_dbus_babysitter_set_result_function (DBusBabysitter *sitter,
+ DBusBabysitterFinishedFunc finished,
+ void *user_data)
+{
+ sitter->finished_cb = finished;
+ sitter->finished_data = user_data;
+}
+
/** @} */
#ifdef DBUS_BUILD_TESTS
diff --git a/dbus/dbus-spawn.h b/dbus/dbus-spawn.h
index 5af54b72..a8814fb9 100644
--- a/dbus/dbus-spawn.h
+++ b/dbus/dbus-spawn.h
@@ -35,12 +35,18 @@ typedef void (* DBusSpawnChildSetupFunc) (void *user_data);
typedef struct DBusBabysitter DBusBabysitter;
+typedef void (* DBusBabysitterFinishedFunc) (DBusBabysitter *sitter,
+ void *user_data);
+
dbus_bool_t _dbus_spawn_async_with_babysitter (DBusBabysitter **sitter_p,
char **argv,
char **env,
DBusSpawnChildSetupFunc child_setup,
void *user_data,
DBusError *error);
+void _dbus_babysitter_set_result_function (DBusBabysitter *sitter,
+ DBusBabysitterFinishedFunc finished,
+ void *user_data);
DBusBabysitter* _dbus_babysitter_ref (DBusBabysitter *sitter);
void _dbus_babysitter_unref (DBusBabysitter *sitter);
void _dbus_babysitter_kill_child (DBusBabysitter *sitter);
diff --git a/dbus/dbus-string-private.h b/dbus/dbus-string-private.h
index b17c2b9f..2a4043a0 100644
--- a/dbus/dbus-string-private.h
+++ b/dbus/dbus-string-private.h
@@ -45,7 +45,6 @@ typedef struct
unsigned char *str; /**< String data, plus nul termination */
int len; /**< Length without nul */
int allocated; /**< Allocated size of data */
- int max_length; /**< Max length of this string, without nul byte */
unsigned int constant : 1; /**< String data is not owned by DBusString */
unsigned int locked : 1; /**< DBusString has been locked and can't be changed */
unsigned int invalid : 1; /**< DBusString is invalid (e.g. already freed) */
@@ -65,17 +64,24 @@ _DBUS_STATIC_ASSERT (sizeof (DBusRealString) == sizeof (DBusString));
*/
/**
- * This is the maximum max length (and thus also the maximum length)
- * of a DBusString
+ * The maximum length of a DBusString
*/
-#define _DBUS_STRING_MAX_MAX_LENGTH (_DBUS_INT32_MAX - _DBUS_STRING_ALLOCATION_PADDING)
+#define _DBUS_STRING_MAX_LENGTH (_DBUS_INT32_MAX - _DBUS_STRING_ALLOCATION_PADDING)
/**
* Checks a bunch of assertions about a string object
*
* @param real the DBusRealString
*/
-#define DBUS_GENERIC_STRING_PREAMBLE(real) _dbus_assert ((real) != NULL); _dbus_assert (!(real)->invalid); _dbus_assert ((real)->len >= 0); _dbus_assert ((real)->allocated >= 0); _dbus_assert ((real)->max_length >= 0); _dbus_assert ((real)->len <= ((real)->allocated - _DBUS_STRING_ALLOCATION_PADDING)); _dbus_assert ((real)->len <= (real)->max_length)
+#define DBUS_GENERIC_STRING_PREAMBLE(real) \
+ do { \
+ _dbus_assert ((real) != NULL); \
+ _dbus_assert (!(real)->invalid); \
+ _dbus_assert ((real)->len >= 0); \
+ _dbus_assert ((real)->allocated >= 0); \
+ _dbus_assert ((real)->len <= ((real)->allocated - _DBUS_STRING_ALLOCATION_PADDING)); \
+ _dbus_assert ((real)->len <= _DBUS_STRING_MAX_LENGTH); \
+ } while (0)
/**
* Checks assertions about a string object that needs to be
diff --git a/dbus/dbus-string-util.c b/dbus/dbus-string-util.c
index 4d42bb0b..421ac1b4 100644
--- a/dbus/dbus-string-util.c
+++ b/dbus/dbus-string-util.c
@@ -120,26 +120,6 @@ _dbus_string_find_byte_backward (const DBusString *str,
#include <stdio.h>
static void
-test_max_len (DBusString *str,
- int max_len)
-{
- if (max_len > 0)
- {
- if (!_dbus_string_set_length (str, max_len - 1))
- _dbus_assert_not_reached ("setting len to one less than max should have worked");
- }
-
- if (!_dbus_string_set_length (str, max_len))
- _dbus_assert_not_reached ("setting len to max len should have worked");
-
- if (_dbus_string_set_length (str, max_len + 1))
- _dbus_assert_not_reached ("setting len to one more than max len should not have worked");
-
- if (!_dbus_string_set_length (str, 0))
- _dbus_assert_not_reached ("setting len to zero should have worked");
-}
-
-static void
test_hex_roundtrip (const unsigned char *data,
int len)
{
@@ -232,25 +212,6 @@ test_roundtrips (TestRoundtripFunc func)
}
}
-#ifdef DBUS_BUILD_TESTS
-/* The max length thing is sort of a historical artifact
- * from a feature that turned out to be dumb; perhaps
- * we should purge it entirely. The problem with
- * the feature is that it looks like memory allocation
- * failure, but is not a transient or resolvable failure.
- */
-static void
-set_max_length (DBusString *str,
- int max_length)
-{
- DBusRealString *real;
-
- real = (DBusRealString*) str;
-
- real->max_length = max_length;
-}
-#endif /* DBUS_BUILD_TESTS */
-
/**
* @ingroup DBusStringInternals
* Unit test for DBusString.
@@ -266,26 +227,12 @@ _dbus_string_test (void)
{
DBusString str;
DBusString other;
- int i, end;
+ int i, a, end;
long v;
double d;
int lens[] = { 0, 1, 2, 3, 4, 5, 10, 16, 17, 18, 25, 31, 32, 33, 34, 35, 63, 64, 65, 66, 67, 68, 69, 70, 71, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136 };
char *s;
dbus_unichar_t ch;
-
- i = 0;
- while (i < _DBUS_N_ELEMENTS (lens))
- {
- if (!_dbus_string_init (&str))
- _dbus_assert_not_reached ("failed to init string");
-
- set_max_length (&str, lens[i]);
-
- test_max_len (&str, lens[i]);
- _dbus_string_free (&str);
-
- ++i;
- }
/* Test shortening and setting length */
i = 0;
@@ -296,8 +243,6 @@ _dbus_string_test (void)
if (!_dbus_string_init (&str))
_dbus_assert_not_reached ("failed to init string");
- set_max_length (&str, lens[i]);
-
if (!_dbus_string_set_length (&str, lens[i]))
_dbus_assert_not_reached ("failed to set string length");
@@ -513,10 +458,94 @@ _dbus_string_test (void)
_dbus_assert (_dbus_string_get_length (&other) == i * 2 - 1);
_dbus_assert (_dbus_string_equal_c_str (&other,
"HelloHello WorldWorle"));
-
+
_dbus_string_free (&str);
_dbus_string_free (&other);
+
+ /* Different tests are provided because different behaviours are
+ * implemented in _dbus_string_replace_len() in function of replacing and
+ * replaced lengths
+ */
+
+ if (!_dbus_string_init (&str))
+ _dbus_assert_not_reached ("failed to init string");
+
+ if (!_dbus_string_append (&str, "Hello World"))
+ _dbus_assert_not_reached ("could not append to string");
+
+ i = _dbus_string_get_length (&str);
+ if (!_dbus_string_init (&other))
+ _dbus_assert_not_reached ("could not init string");
+
+ if (!_dbus_string_append (&other, "Foo String"))
+ _dbus_assert_not_reached ("could not append to string");
+
+ a = _dbus_string_get_length (&other);
+
+ if (!_dbus_string_replace_len (&str, 0, 6,
+ &other, 4, 0))
+ _dbus_assert_not_reached ("could not replace 0 length");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 6);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "Foo Hello String"));
+
+ if (!_dbus_string_replace_len (&str, 5, 6,
+ &other,
+ _dbus_string_get_length (&other),
+ 0))
+ _dbus_assert_not_reached ("could not replace at the end");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 6 + 6);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "Foo Hello String World"));
+
+ if (!_dbus_string_replace_len (&str, 0, 5,
+ &other,
+ _dbus_string_get_length (&other) - 5,
+ 5))
+ _dbus_assert_not_reached ("could not replace same length");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 6 + 6);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "Foo Hello String Hello"));
+
+ if (!_dbus_string_replace_len (&str, 6, 5,
+ &other, 4, 12))
+ _dbus_assert_not_reached ("could not replace with shorter string");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 5);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "Foo World Hello"));
+
+ if (!_dbus_string_replace_len (&str, 0, 1,
+ &other, 0, 3))
+ _dbus_assert_not_reached ("could not replace at the beginning");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 3);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "H World Hello"));
+
+ if (!_dbus_string_replace_len (&str, 6, 5,
+ &other,
+ _dbus_string_get_length (&other) - 5,
+ 5))
+ _dbus_assert_not_reached ("could not replace same length");
+
+ _dbus_assert (_dbus_string_get_length (&str) == i);
+ _dbus_assert (_dbus_string_get_length (&other) == a + 3);
+ _dbus_assert (_dbus_string_equal_c_str (&other,
+ "H World World"));
+
+ _dbus_string_free (&str);
+ _dbus_string_free (&other);
+
/* Check append/get unichar */
if (!_dbus_string_init (&str))
diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c
index ca3a670b..6658abd4 100644
--- a/dbus/dbus-string.c
+++ b/dbus/dbus-string.c
@@ -154,7 +154,6 @@ _dbus_string_init_preallocated (DBusString *str,
real->len = 0;
real->str[real->len] = '\0';
- real->max_length = _DBUS_STRING_MAX_MAX_LENGTH;
real->constant = FALSE;
real->locked = FALSE;
real->invalid = FALSE;
@@ -178,25 +177,6 @@ _dbus_string_init (DBusString *str)
return _dbus_string_init_preallocated (str, 0);
}
-#ifdef DBUS_BUILD_TESTS
-/* The max length thing is sort of a historical artifact
- * from a feature that turned out to be dumb; perhaps
- * we should purge it entirely. The problem with
- * the feature is that it looks like memory allocation
- * failure, but is not a transient or resolvable failure.
- */
-static void
-set_max_length (DBusString *str,
- int max_length)
-{
- DBusRealString *real;
-
- real = (DBusRealString*) str;
-
- real->max_length = max_length;
-}
-#endif /* DBUS_BUILD_TESTS */
-
/**
* Initializes a constant string. The value parameter is not copied
* (should be static), and the string may never be modified.
@@ -235,7 +215,7 @@ _dbus_string_init_const_len (DBusString *str,
_dbus_assert (str != NULL);
_dbus_assert (len == 0 || value != NULL);
- _dbus_assert (len <= _DBUS_STRING_MAX_MAX_LENGTH);
+ _dbus_assert (len <= _DBUS_STRING_MAX_LENGTH);
_dbus_assert (len >= 0);
real = (DBusRealString*) str;
@@ -243,7 +223,6 @@ _dbus_string_init_const_len (DBusString *str,
real->str = (unsigned char*) value;
real->len = len;
real->allocated = real->len + _DBUS_STRING_ALLOCATION_PADDING; /* a lie, just to avoid special-case assertions... */
- real->max_length = real->len + 1;
real->constant = TRUE;
real->locked = TRUE;
real->invalid = FALSE;
@@ -336,8 +315,8 @@ reallocate_for_length (DBusRealString *real,
/* at least double our old allocation to avoid O(n), avoiding
* overflow
*/
- if (real->allocated > (_DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
- new_allocated = _DBUS_STRING_MAX_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
+ if (real->allocated > (_DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING) / 2)
+ new_allocated = _DBUS_STRING_MAX_LENGTH + _DBUS_STRING_ALLOCATION_PADDING;
else
new_allocated = real->allocated * 2;
@@ -400,7 +379,7 @@ set_length (DBusRealString *real,
/* Note, we are setting the length not including nul termination */
/* exceeding max length is the same as failure to allocate memory */
- if (_DBUS_UNLIKELY (new_length > real->max_length))
+ if (_DBUS_UNLIKELY (new_length > _DBUS_STRING_MAX_LENGTH))
return FALSE;
else if (new_length > (real->allocated - _DBUS_STRING_ALLOCATION_PADDING) &&
_DBUS_UNLIKELY (!reallocate_for_length (real, new_length)))
@@ -421,7 +400,7 @@ open_gap (int len,
if (len == 0)
return TRUE;
- if (len > dest->max_length - dest->len)
+ if (len > _DBUS_STRING_MAX_LENGTH - dest->len)
return FALSE; /* detected overflow of dest->len + len below */
if (!set_length (dest, dest->len + len))
@@ -640,7 +619,6 @@ dbus_bool_t
_dbus_string_steal_data (DBusString *str,
char **data_return)
{
- int old_max_length;
DBUS_STRING_PREAMBLE (str);
_dbus_assert (data_return != NULL);
@@ -648,8 +626,6 @@ _dbus_string_steal_data (DBusString *str,
*data_return = (char*) real->str;
- old_max_length = real->max_length;
-
/* reset the string */
if (!_dbus_string_init (str))
{
@@ -660,64 +636,9 @@ _dbus_string_steal_data (DBusString *str,
return FALSE;
}
- real->max_length = old_max_length;
-
return TRUE;
}
-#ifdef DBUS_BUILD_TESTS
-/**
- * Like _dbus_string_get_data_len(), but removes the gotten data from
- * the original string. The caller must free the data returned. This
- * function may fail due to lack of memory, and return #FALSE.
- * The returned string is nul-terminated and has length len.
- *
- * @todo this function is broken because on failure it
- * may corrupt the source string.
- *
- * @param str the string
- * @param data_return location to return the buffer
- * @param start the start of segment to steal
- * @param len the length of segment to steal
- * @returns #TRUE on success
- */
-dbus_bool_t
-_dbus_string_steal_data_len (DBusString *str,
- char **data_return,
- int start,
- int len)
-{
- DBusString dest;
- DBUS_STRING_PREAMBLE (str);
- _dbus_assert (data_return != NULL);
- _dbus_assert (start >= 0);
- _dbus_assert (len >= 0);
- _dbus_assert (start <= real->len);
- _dbus_assert (len <= real->len - start);
-
- if (!_dbus_string_init (&dest))
- return FALSE;
-
- set_max_length (&dest, real->max_length);
-
- if (!_dbus_string_move_len (str, start, len, &dest, 0))
- {
- _dbus_string_free (&dest);
- return FALSE;
- }
-
- _dbus_warn ("Broken code in _dbus_string_steal_data_len(), see @todo, FIXME\n");
- if (!_dbus_string_steal_data (&dest, data_return))
- {
- _dbus_string_free (&dest);
- return FALSE;
- }
-
- _dbus_string_free (&dest);
- return TRUE;
-}
-#endif /* DBUS_BUILD_TESTS */
-
/**
* Copies the data from the string into a char*
*
@@ -785,53 +706,6 @@ _dbus_string_copy_to_buffer_with_nul (const DBusString *str,
memcpy (buffer, real->str, real->len+1);
}
-#ifdef DBUS_BUILD_TESTS
-/**
- * Copies a segment of the string into a char*
- *
- * @param str the string
- * @param data_return place to return the data
- * @param start start index
- * @param len length to copy
- * @returns #FALSE if no memory
- */
-dbus_bool_t
-_dbus_string_copy_data_len (const DBusString *str,
- char **data_return,
- int start,
- int len)
-{
- DBusString dest;
-
- DBUS_CONST_STRING_PREAMBLE (str);
- _dbus_assert (data_return != NULL);
- _dbus_assert (start >= 0);
- _dbus_assert (len >= 0);
- _dbus_assert (start <= real->len);
- _dbus_assert (len <= real->len - start);
-
- if (!_dbus_string_init (&dest))
- return FALSE;
-
- set_max_length (&dest, real->max_length);
-
- if (!_dbus_string_copy_len (str, start, len, &dest, 0))
- {
- _dbus_string_free (&dest);
- return FALSE;
- }
-
- if (!_dbus_string_steal_data (&dest, data_return))
- {
- _dbus_string_free (&dest);
- return FALSE;
- }
-
- _dbus_string_free (&dest);
- return TRUE;
-}
-#endif /* DBUS_BUILD_TESTS */
-
/* Only have the function if we don't have the macro */
#ifndef _dbus_string_get_length
/**
@@ -867,7 +741,7 @@ _dbus_string_lengthen (DBusString *str,
DBUS_STRING_PREAMBLE (str);
_dbus_assert (additional_length >= 0);
- if (_DBUS_UNLIKELY (additional_length > real->max_length - real->len))
+ if (_DBUS_UNLIKELY (additional_length > _DBUS_STRING_MAX_LENGTH - real->len))
return FALSE; /* would overflow */
return set_length (real,
@@ -933,7 +807,7 @@ align_insert_point_then_open_gap (DBusString *str,
gap_pos = _DBUS_ALIGN_VALUE (insert_at, alignment);
new_len = real->len + (gap_pos - insert_at) + gap_size;
- if (_DBUS_UNLIKELY (new_len > (unsigned long) real->max_length))
+ if (_DBUS_UNLIKELY (new_len > (unsigned long) _DBUS_STRING_MAX_LENGTH))
return FALSE;
delta = new_len - real->len;
@@ -1045,7 +919,7 @@ _dbus_string_append (DBusString *str,
_dbus_assert (buffer != NULL);
buffer_len = strlen (buffer);
- if (buffer_len > (unsigned long) real->max_length)
+ if (buffer_len > (unsigned long) _DBUS_STRING_MAX_LENGTH)
return FALSE;
return append (real, buffer, buffer_len);
@@ -1392,7 +1266,7 @@ _dbus_string_append_unichar (DBusString *str,
len = 6;
}
- if (len > (real->max_length - real->len))
+ if (len > (_DBUS_STRING_MAX_LENGTH - real->len))
return FALSE; /* real->len + len would overflow */
if (!set_length (real, real->len + len))
@@ -1541,9 +1415,6 @@ _dbus_string_copy (const DBusString *source,
* Like _dbus_string_move(), but can move a segment from
* the middle of the source string.
*
- * @todo this doesn't do anything with max_length field.
- * we should probably just kill the max_length field though.
- *
* @param source the source string
* @param start first byte of source string to move
* @param len length of segment to move
@@ -1638,15 +1509,6 @@ _dbus_string_copy_len (const DBusString *source,
/**
* Replaces a segment of dest string with a segment of source string.
*
- * @todo optimize the case where the two lengths are the same, and
- * avoid memmoving the data in the trailing part of the string twice.
- *
- * @todo avoid inserting the source into dest, then deleting
- * the replaced chunk of dest (which creates a potentially large
- * intermediate string). Instead, extend the replaced chunk
- * of dest with padding to the same size as the source chunk,
- * then copy in the source bytes.
- *
* @param source the source string
* @param start where to start copying the source string
* @param len length of segment to copy
@@ -1672,11 +1534,37 @@ _dbus_string_replace_len (const DBusString *source,
_dbus_assert (replace_at <= real_dest->len);
_dbus_assert (replace_len <= real_dest->len - replace_at);
- if (!copy (real_source, start, len,
- real_dest, replace_at))
- return FALSE;
+ if (len == replace_len)
+ {
+ memmove (real_dest->str + replace_at,
+ real_source->str + start, len);
+ }
+ else if (len < replace_len)
+ {
+ memmove (real_dest->str + replace_at,
+ real_source->str + start, len);
+ delete (real_dest, replace_at + len,
+ replace_len - len);
+ }
+ else
+ {
+ int diff;
+
+ _dbus_assert (len > replace_len);
+
+ diff = len - replace_len;
- delete (real_dest, replace_at + len, replace_len);
+ /* First of all we check if destination string can be enlarged as
+ * required, then we overwrite previous bytes
+ */
+
+ if (!copy (real_source, start + replace_len, diff,
+ real_dest, replace_at + replace_len))
+ return FALSE;
+
+ memmove (real_dest->str + replace_at,
+ real_source->str + start, replace_len);
+ }
return TRUE;
}
diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h
index 2f1ed31c..2f1fe878 100644
--- a/dbus/dbus-string.h
+++ b/dbus/dbus-string.h
@@ -48,11 +48,10 @@ struct DBusString
#endif
int dummy2; /**< placeholder */
int dummy3; /**< placeholder */
- int dummy4; /**< placeholder */
- unsigned int dummy5 : 1; /**< placeholder */
- unsigned int dummy6 : 1; /**< placeholder */
- unsigned int dummy7 : 1; /**< placeholder */
- unsigned int dummy8 : 3; /**< placeholder */
+ unsigned int dummy_bit1 : 1; /**< placeholder */
+ unsigned int dummy_bit2 : 1; /**< placeholder */
+ unsigned int dummy_bit3 : 1; /**< placeholder */
+ unsigned int dummy_bits : 3; /**< placeholder */
};
#ifdef DBUS_DISABLE_ASSERT
@@ -324,7 +323,6 @@ void _dbus_string_zero (DBusString *str);
sizeof(_dbus_static_string_##name), \
sizeof(_dbus_static_string_##name) + \
_DBUS_STRING_ALLOCATION_PADDING, \
- sizeof(_dbus_static_string_##name), \
TRUE, TRUE, FALSE, 0 }
DBUS_END_DECLS
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index e69f3b59..bd101835 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -132,13 +132,6 @@ _dbus_open_socket (int *fd_p,
}
}
-dbus_bool_t
-_dbus_open_tcp_socket (int *fd,
- DBusError *error)
-{
- return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
-}
-
/**
* Opens a UNIX domain socket (as in the socket() call).
* Does not bind the socket.
@@ -149,7 +142,7 @@ _dbus_open_tcp_socket (int *fd,
* @param error return location for an error
* @returns #FALSE if error is set
*/
-dbus_bool_t
+static dbus_bool_t
_dbus_open_unix_socket (int *fd,
DBusError *error)
{
@@ -2500,8 +2493,6 @@ void
_dbus_get_current_time (long *tv_sec,
long *tv_usec)
{
- struct timeval t;
-
#ifdef HAVE_MONOTONIC_CLOCK
struct timespec ts;
clock_gettime (CLOCK_MONOTONIC, &ts);
@@ -2511,6 +2502,8 @@ _dbus_get_current_time (long *tv_sec,
if (tv_usec)
*tv_usec = ts.tv_nsec / 1000;
#else
+ struct timeval t;
+
gettimeofday (&t, NULL);
if (tv_sec)
@@ -3428,10 +3421,10 @@ _dbus_lookup_launchd_socket (DBusString *socket_path,
#endif
}
+#ifdef DBUS_ENABLE_LAUNCHD
static dbus_bool_t
_dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
{
-#ifdef DBUS_ENABLE_LAUNCHD
dbus_bool_t valid_socket;
DBusString socket_path;
@@ -3473,12 +3466,8 @@ _dbus_lookup_session_address_launchd (DBusString *address, DBusError *error)
_dbus_string_free(&socket_path);
return TRUE;
-#else
- dbus_set_error(error, DBUS_ERROR_NOT_SUPPORTED,
- "can't lookup session address from launchd; launchd support not compiled in");
- return FALSE;
-#endif
}
+#endif
/**
* Determines the address of the session bus by querying a
diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h
index d7022b07..200ec8a3 100644
--- a/dbus/dbus-sysdeps-unix.h
+++ b/dbus/dbus-sysdeps-unix.h
@@ -63,8 +63,6 @@ _dbus_write_two (int fd,
int start2,
int len2);
-dbus_bool_t _dbus_open_unix_socket (int *fd,
- DBusError *error);
int _dbus_connect_unix_socket (const char *path,
dbus_bool_t abstract,
DBusError *error);
diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c
index a80f6430..805c919d 100644
--- a/dbus/dbus-sysdeps-util-unix.c
+++ b/dbus/dbus-sysdeps-util-unix.c
@@ -389,7 +389,6 @@ _dbus_request_file_descriptor_limit (unsigned int limit)
#ifdef HAVE_SETRLIMIT
struct rlimit lim;
struct rlimit target_lim;
- unsigned int current_limit;
/* No point to doing this practically speaking
* if we're not uid 0. We expect the system
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index 54a4cd7e..f66efaad 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -121,8 +121,6 @@ typedef unsigned long dbus_gid_t;
*
*/
-dbus_bool_t _dbus_open_tcp_socket (int *fd,
- DBusError *error);
dbus_bool_t _dbus_close_socket (int fd,
DBusError *error);
int _dbus_read_socket (int fd,
diff --git a/dbus/dbus-test.h b/dbus/dbus-test.h
index 0238b0ce..982577fb 100644
--- a/dbus/dbus-test.h
+++ b/dbus/dbus-test.h
@@ -29,7 +29,6 @@
#include <dbus/dbus-marshal-validate.h>
dbus_bool_t _dbus_hash_test (void);
-dbus_bool_t _dbus_dict_test (void);
dbus_bool_t _dbus_list_test (void);
dbus_bool_t _dbus_marshal_test (void);
dbus_bool_t _dbus_marshal_recursive_test (void);
@@ -44,7 +43,6 @@ dbus_bool_t _dbus_address_test (void);
dbus_bool_t _dbus_server_test (void);
dbus_bool_t _dbus_message_test (const char *test_data_dir);
dbus_bool_t _dbus_auth_test (const char *test_data_dir);
-dbus_bool_t _dbus_md5_test (void);
dbus_bool_t _dbus_sha_test (const char *test_data_dir);
dbus_bool_t _dbus_keyring_test (void);
dbus_bool_t _dbus_data_slot_test (void);
diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c
index 1d4c2bf7..0673a8ce 100644
--- a/dbus/dbus-transport-socket.c
+++ b/dbus/dbus-transport-socket.c
@@ -677,8 +677,8 @@ do_writing (DBusTransport *transport)
_dbus_string_set_length (&socket_transport->encoded_outgoing, 0);
_dbus_string_compact (&socket_transport->encoded_outgoing, 2048);
- _dbus_connection_message_sent (transport->connection,
- message);
+ _dbus_connection_message_sent_unlocked (transport->connection,
+ message);
}
}
}
@@ -1278,8 +1278,10 @@ _dbus_transport_new_for_socket (int fd,
return (DBusTransport*) socket_transport;
failed_4:
+ _dbus_watch_invalidate (socket_transport->read_watch);
_dbus_watch_unref (socket_transport->read_watch);
failed_3:
+ _dbus_watch_invalidate (socket_transport->write_watch);
_dbus_watch_unref (socket_transport->write_watch);
failed_2:
_dbus_string_free (&socket_transport->encoded_incoming);
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index ba6bd4b4..f743d010 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -72,12 +72,16 @@ live_messages_notify (DBusCounter *counter,
_dbus_verbose ("Unix FD counter value is now %d\n",
(int) _dbus_counter_get_unix_fd_value (counter));
#endif
-
+
/* disable or re-enable the read watch for the transport if
* required.
*/
if (transport->vtable->live_messages_changed)
- (* transport->vtable->live_messages_changed) (transport);
+ {
+ _dbus_connection_lock (transport->connection);
+ (* transport->vtable->live_messages_changed) (transport);
+ _dbus_connection_unlock (transport->connection);
+ }
_dbus_transport_unref (transport);
}
@@ -1144,6 +1148,13 @@ _dbus_transport_queue_messages (DBusTransport *transport)
}
else
{
+ /* We didn't call the notify function when we added the counter, so
+ * catch up now. Since we have the connection's lock, it's desirable
+ * that we bypass the notify function and call this virtual method
+ * directly. */
+ if (transport->vtable->live_messages_changed)
+ (* transport->vtable->live_messages_changed) (transport);
+
/* pass ownership of link and message ref to connection */
_dbus_connection_queue_received_message_link (transport->connection,
link);
@@ -1482,4 +1493,26 @@ _dbus_transport_set_allow_anonymous (DBusTransport *transport,
transport->allow_anonymous = value != FALSE;
}
+#ifdef DBUS_ENABLE_STATS
+void
+_dbus_transport_get_stats (DBusTransport *transport,
+ dbus_uint32_t *queue_bytes,
+ dbus_uint32_t *queue_fds,
+ dbus_uint32_t *peak_queue_bytes,
+ dbus_uint32_t *peak_queue_fds)
+{
+ if (queue_bytes != NULL)
+ *queue_bytes = _dbus_counter_get_size_value (transport->live_messages);
+
+ if (queue_fds != NULL)
+ *queue_fds = _dbus_counter_get_unix_fd_value (transport->live_messages);
+
+ if (peak_queue_bytes != NULL)
+ *peak_queue_bytes = _dbus_counter_get_peak_size_value (transport->live_messages);
+
+ if (peak_queue_fds != NULL)
+ *peak_queue_fds = _dbus_counter_get_peak_unix_fd_value (transport->live_messages);
+}
+#endif /* DBUS_ENABLE_STATS */
+
/** @} */
diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h
index 0db048a2..4b821517 100644
--- a/dbus/dbus-transport.h
+++ b/dbus/dbus-transport.h
@@ -97,6 +97,12 @@ dbus_bool_t _dbus_transport_set_auth_mechanisms (DBusTransport
void _dbus_transport_set_allow_anonymous (DBusTransport *transport,
dbus_bool_t value);
+/* if DBUS_ENABLE_STATS */
+void _dbus_transport_get_stats (DBusTransport *transport,
+ dbus_uint32_t *queue_bytes,
+ dbus_uint32_t *queue_fds,
+ dbus_uint32_t *peak_queue_bytes,
+ dbus_uint32_t *peak_queue_fds);
DBUS_END_DECLS
diff --git a/dbus/dbus-watch.c b/dbus/dbus-watch.c
index 8d759e5e..b9f4ac23 100644
--- a/dbus/dbus-watch.c
+++ b/dbus/dbus-watch.c
@@ -50,6 +50,7 @@ struct DBusWatch
void *data; /**< Application data. */
DBusFreeFunction free_data_function; /**< Free the application data. */
unsigned int enabled : 1; /**< Whether it's enabled. */
+ unsigned int oom_last_time : 1; /**< Whether it was OOM last time. */
};
dbus_bool_t
@@ -58,6 +59,19 @@ _dbus_watch_get_enabled (DBusWatch *watch)
return watch->enabled;
}
+dbus_bool_t
+_dbus_watch_get_oom_last_time (DBusWatch *watch)
+{
+ return watch->oom_last_time;
+}
+
+void
+_dbus_watch_set_oom_last_time (DBusWatch *watch,
+ dbus_bool_t oom)
+{
+ watch->oom_last_time = oom;
+}
+
/**
* Creates a new DBusWatch. Used to add a file descriptor to be polled
* by a main loop.
@@ -129,6 +143,9 @@ _dbus_watch_unref (DBusWatch *watch)
watch->refcount -= 1;
if (watch->refcount == 0)
{
+ if (watch->fd != -1)
+ _dbus_warn ("this watch should have been invalidated");
+
dbus_watch_set_data (watch, NULL, NULL); /* call free_data_function */
if (watch->free_handler_data_function)
diff --git a/dbus/dbus-watch.h b/dbus/dbus-watch.h
index fa953ec1..dd23b862 100644
--- a/dbus/dbus-watch.h
+++ b/dbus/dbus-watch.h
@@ -76,6 +76,10 @@ void _dbus_watch_list_toggle_watch (DBusWatchList *watch_li
dbus_bool_t enabled);
dbus_bool_t _dbus_watch_get_enabled (DBusWatch *watch);
+dbus_bool_t _dbus_watch_get_oom_last_time (DBusWatch *watch);
+void _dbus_watch_set_oom_last_time (DBusWatch *watch,
+ dbus_bool_t oom);
+
/** @} */
DBUS_END_DECLS
diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml
index 836b64b7..7280cf17 100644
--- a/doc/dbus-specification.xml
+++ b/doc/dbus-specification.xml
@@ -6,8 +6,8 @@
<article id="index">
<articleinfo>
<title>D-Bus Specification</title>
- <releaseinfo>Version 0.15</releaseinfo>
- <date>3 November 2010</date>
+ <releaseinfo>Version 0.19</releaseinfo>
+ <date>UNRELEASED</date>
<authorgroup>
<author>
<firstname>Havoc</firstname>
@@ -49,6 +49,26 @@
</address>
</affiliation>
</author>
+ <author>
+ <firstname>Simon</firstname>
+ <surname>McVittie</surname>
+ <affiliation>
+ <orgname>Collabora Ltd.</orgname>
+ <address>
+ <email>simon.mcvittie@collabora.co.uk</email>
+ </address>
+ </affiliation>
+ </author>
+ <author>
+ <firstname>David</firstname>
+ <surname>Zeuthen</surname>
+ <affiliation>
+ <orgname>Red Hat, Inc.</orgname>
+ <address>
+ <email>davidz@redhat.com</email>
+ </address>
+ </affiliation>
+ </author>
</authorgroup>
<revhistory>
<revision>
@@ -58,6 +78,27 @@
<revremark></revremark>
</revision>
<revision>
+ <revnumber>0.18</revnumber>
+ <date>29 July 2011</date>
+ <authorinitials>smcv</authorinitials>
+ <revremark>define eavesdropping, unicast, broadcast; add eavesdrop
+ match keyword; promote type system to a top-level section</revremark>
+ </revision>
+ <revision>
+ <revnumber>0.17</revnumber>
+ <date>1 June 2011</date>
+ <authorinitials>smcv/davidz</authorinitials>
+ <revremark>define ObjectManager; reserve extra pseudo-type-codes used
+ by GVariant</revremark>
+ </revision>
+ <revision>
+ <revnumber>0.16</revnumber>
+ <date>11 April 2011</date>
+ <authorinitials></authorinitials>
+ <revremark>add path_namespace, arg0namespace; argNpath matches object
+ paths</revremark>
+ </revision>
+ <revision>
<revnumber>0.15</revnumber>
<date>3 November 2010</date>
<authorinitials></authorinitials>
@@ -230,27 +271,13 @@
</sect1>
- <sect1 id="message-protocol">
- <title>Message Protocol</title>
-
- <para>
- A <firstterm>message</firstterm> consists of a
- <firstterm>header</firstterm> and a <firstterm>body</firstterm>. If you
- think of a message as a package, the header is the address, and the body
- contains the package contents. The message delivery system uses the header
- information to figure out where to send the message and how to interpret
- it; the recipient interprets the body of the message.
- </para>
-
- <para>
- The body of the message is made up of zero or more
- <firstterm>arguments</firstterm>, which are typed values, such as an
- integer or a byte array.
- </para>
+ <sect1 id="type-system">
+ <title>Type System</title>
<para>
- Both header and body use the same type system and format for
- serializing data. Each type of value has a wire format.
+ D-Bus has a type system, in which values of various types can be
+ serialized into a sequence of bytes referred to as the
+ <firstterm>wire format</firstterm> in a standard way.
Converting a value from some other representation into the wire
format is called <firstterm>marshaling</firstterm> and converting
it back from the wire format is <firstterm>unmarshaling</firstterm>.
@@ -471,7 +498,10 @@
</row><row>
<entry><literal>STRUCT</literal></entry>
<entry>114 (ASCII 'r'), 40 (ASCII '('), 41 (ASCII ')')</entry>
- <entry>Struct</entry>
+ <entry>Struct; type code 114 'r' is reserved for use in
+ bindings and implementations to represent the general
+ concept of a struct, and must not appear in signatures
+ used on D-Bus.</entry>
</row><row>
<entry><literal>VARIANT</literal></entry>
<entry>118 (ASCII 'v') </entry>
@@ -479,12 +509,48 @@
</row><row>
<entry><literal>DICT_ENTRY</literal></entry>
<entry>101 (ASCII 'e'), 123 (ASCII '{'), 125 (ASCII '}') </entry>
- <entry>Entry in a dict or map (array of key-value pairs)</entry>
+ <entry>Entry in a dict or map (array of key-value pairs).
+ Type code 101 'e' is reserved for use in bindings and
+ implementations to represent the general concept of a
+ dict or dict-entry, and must not appear in signatures
+ used on D-Bus.</entry>
</row><row>
<entry><literal>UNIX_FD</literal></entry>
<entry>104 (ASCII 'h')</entry>
<entry>Unix file descriptor</entry>
</row>
+ <row>
+ <entry>(reserved)</entry>
+ <entry>109 (ASCII 'm')</entry>
+ <entry>Reserved for <ulink
+ url="https://bugs.freedesktop.org/show_bug.cgi?id=27857">a
+ 'maybe' type compatible with the one in GVariant</ulink>,
+ and must not appear in signatures used on D-Bus until
+ specified here</entry>
+ </row>
+ <row>
+ <entry>(reserved)</entry>
+ <entry>42 (ASCII '*')</entry>
+ <entry>Reserved for use in bindings/implementations to
+ represent any <firstterm>single complete type</firstterm>,
+ and must not appear in signatures used on D-Bus.</entry>
+ </row>
+ <row>
+ <entry>(reserved)</entry>
+ <entry>63 (ASCII '?')</entry>
+ <entry>Reserved for use in bindings/implementations to
+ represent any <firstterm>basic type</firstterm>, and must
+ not appear in signatures used on D-Bus.</entry>
+ </row>
+ <row>
+ <entry>(reserved)</entry>
+ <entry>64 (ASCII '@'), 38 (ASCII '&amp;'),
+ 94 (ASCII '^')</entry>
+ <entry>Reserved for internal use by bindings/implementations,
+ and must not appear in signatures used on D-Bus.
+ GVariant uses these type-codes to encode calling
+ conventions.</entry>
+ </row>
</tbody>
</tgroup>
</informaltable>
@@ -770,6 +836,31 @@
</sect2>
+ </sect1>
+
+ <sect1 id="message-protocol">
+ <title>Message Protocol</title>
+
+ <para>
+ A <firstterm>message</firstterm> consists of a
+ <firstterm>header</firstterm> and a <firstterm>body</firstterm>. If you
+ think of a message as a package, the header is the address, and the body
+ contains the package contents. The message delivery system uses the header
+ information to figure out where to send the message and how to interpret
+ it; the recipient interprets the body of the message.
+ </para>
+
+ <para>
+ The body of the message is made up of zero or more
+ <firstterm>arguments</firstterm>, which are typed values, such as an
+ integer or a byte array.
+ </para>
+
+ <para>
+ Both header and body use the D-Bus <link linkend="type-system">type
+ system</link> and format for serializing data.
+ </para>
+
<sect2 id="message-protocol-messages">
<title>Message Format</title>
@@ -2991,6 +3082,114 @@
annotation.
</para>
</sect2>
+
+ <sect2 id="standard-interfaces-objectmanager">
+ <title><literal>org.freedesktop.DBus.ObjectManager</literal></title>
+ <para>
+ An API can optionally make use of this interface for one or
+ more sub-trees of objects. The root of each sub-tree implements
+ this interface so other applications can get all objects,
+ interfaces and properties in a single method call. It is
+ appropriate to use this interface if users of the tree of
+ objects are expected to be interested in all interfaces of all
+ objects in the tree; a more granular API should be used if
+ users of the objects are expected to be interested in a small
+ subset of the objects, a small subset of their interfaces, or
+ both.
+ </para>
+ <para>
+ The method that applications can use to get all objects and
+ properties is <literal>GetManagedObjects</literal>:
+ </para>
+ <para>
+ <programlisting>
+ org.freedesktop.DBus.ObjectManager.GetManagedObjects (out DICT&lt;OBJPATH,DICT&lt;STRING,DICT&lt;STRING,VARIANT&gt;&gt;&gt; objpath_interfaces_and_properties);
+ </programlisting>
+ </para>
+ <para>
+ The return value of this method is a dict whose keys are
+ object paths. All returned object paths are children of the
+ object path implementing this interface, i.e. their object
+ paths start with the ObjectManager's object path plus '/'.
+ </para>
+ <para>
+ Each value is a dict whose keys are interfaces names. Each
+ value in this inner dict is the same dict that would be
+ returned by the <link
+ linkend="standard-interfaces-properties">org.freedesktop.DBus.Properties.GetAll()</link>
+ method for that combination of object path and interface. If
+ an interface has no properties, the empty dict is returned.
+ </para>
+ <para>
+ Changes are emitted using the following two signals:
+ </para>
+ <para>
+ <programlisting>
+ org.freedesktop.DBus.ObjectManager.InterfacesAdded (OBJPATH object_path,
+ DICT&lt;STRING,DICT&lt;STRING,VARIANT&gt;&gt; interfaces_and_properties);
+ org.freedesktop.DBus.ObjectManager.InterfacesRemoved (OBJPATH object_path,
+ ARRAY&lt;STRING&gt; interfaces);
+ </programlisting>
+ </para>
+ <para>
+ The <literal>InterfacesAdded</literal> signal is emitted when
+ either a new object is added or when an existing object gains
+ one or more interfaces. The
+ <literal>InterfacesRemoved</literal> signal is emitted
+ whenever an object is removed or it loses one or more
+ interfaces. The second parameter of the
+ <literal>InterfacesAdded</literal> signal contains a dict with
+ the interfaces and properties (if any) that have been added to
+ the given object path. Similarly, the second parameter of the
+ <literal>InterfacesRemoved</literal> signal contains an array
+ of the interfaces that were removed. Note that changes on
+ properties on existing interfaces are not reported using this
+ interface - an application should also monitor the existing <link
+ linkend="standard-interfaces-properties">PropertiesChanged</link>
+ signal on each object.
+ </para>
+ <para>
+ Applications SHOULD NOT export objects that are children of an
+ object (directly or otherwise) implementing this interface but
+ which are not returned in the reply from the
+ <literal>GetManagedObjects()</literal> method of this
+ interface on the given object.
+ </para>
+ <para>
+ The intent of the <literal>ObjectManager</literal> interface
+ is to make it easy to write a robust client
+ implementation. The trivial client implementation only needs
+ to make two method calls:
+ </para>
+ <para>
+ <programlisting>
+ org.freedesktop.DBus.AddMatch (bus_proxy,
+ "type='signal',name='org.example.App',path_namespace='/org/example/App'");
+ objects = org.freedesktop.DBus.ObjectManager.GetManagedObjects (app_proxy);
+ </programlisting>
+ </para>
+ <para>
+ on the message bus and the remote application's
+ <literal>ObjectManager</literal>, respectively. Whenever a new
+ remote object is created (or an existing object gains a new
+ interface), the <literal>InterfacesAdded</literal> signal is
+ emitted, and since this signal contains all properties for the
+ interfaces, no calls to the
+ <literal>org.freedesktop.Properties</literal> interface on the
+ remote object are needed. Additionally, since the initial
+ <literal>AddMatch()</literal> rule already includes signal
+ messages from the newly created child object, no new
+ <literal>AddMatch()</literal> call is needed.
+ </para>
+
+ <para>
+ <emphasis>
+ The <literal>org.freedesktop.DBus.ObjectManager</literal>
+ interface was added in version 0.17 of the D-Bus
+ specification.
+ </emphasis>
+ </para>
+ </sect2>
</sect1>
<sect1 id="introspection-format">
@@ -3193,39 +3392,10 @@
</para>
<para>
- Messages may have a <literal>DESTINATION</literal> field (see <xref
- linkend="message-protocol-header-fields"/>). If the
- <literal>DESTINATION</literal> field is present, it specifies a message
- recipient by name. Method calls and replies normally specify this field.
- The message bus must send messages (of any type) with the
- <literal>DESTINATION</literal> field set to the specified recipient,
- regardless of whether the recipient has set up a match rule matching
- the message.
- </para>
-
- <para>
- Signals normally do not specify a destination; they are sent to all
- applications with <firstterm>message matching rules</firstterm> that
- match the message.
- </para>
-
- <para>
- When the message bus receives a method call, if the
- <literal>DESTINATION</literal> field is absent, the call is taken to be
- a standard one-to-one message and interpreted by the message bus
- itself. For example, sending an
- <literal>org.freedesktop.DBus.Peer.Ping</literal> message with no
- <literal>DESTINATION</literal> will cause the message bus itself to
- reply to the ping immediately; the message bus will not make this
- message visible to other applications.
- </para>
-
- <para>
- Continuing the <literal>org.freedesktop.DBus.Peer.Ping</literal> example, if
- the ping message were sent with a <literal>DESTINATION</literal> name of
- <literal>com.yoyodyne.Screensaver</literal>, then the ping would be
- forwarded, and the Yoyodyne Corporation screensaver application would be
- expected to reply to the ping.
+ Applications may send <firstterm>unicast messages</firstterm> to
+ a specific recipient or to the message bus itself, or
+ <firstterm>broadcast messages</firstterm> to all interested recipients.
+ See <xref linkend="message-bus-routing"/> for details.
</para>
</sect2>
@@ -3659,20 +3829,122 @@
<sect2 id="message-bus-routing">
<title>Message Bus Message Routing</title>
+
+ <para>
+ Messages may have a <literal>DESTINATION</literal> field (see <xref
+ linkend="message-protocol-header-fields"/>), resulting in a
+ <firstterm>unicast message</firstterm>. If the
+ <literal>DESTINATION</literal> field is present, it specifies a message
+ recipient by name. Method calls and replies normally specify this field.
+ The message bus must send messages (of any type) with the
+ <literal>DESTINATION</literal> field set to the specified recipient,
+ regardless of whether the recipient has set up a match rule matching
+ the message.
+ </para>
+
+ <para>
+ When the message bus receives a signal, if the
+ <literal>DESTINATION</literal> field is absent, it is considered to
+ be a <firstterm>broadcast signal</firstterm>, and is sent to all
+ applications with <firstterm>message matching rules</firstterm> that
+ match the message. Most signal messages are broadcasts.
+ </para>
+
<para>
- FIXME
+ Unicast signal messages (those with a <literal>DESTINATION</literal>
+ field) are not commonly used, but they are treated like any unicast
+ message: they are delivered to the specified receipient,
+ regardless of its match rules. One use for unicast signals is to
+ avoid a race condition in which a signal is emitted before the intended
+ recipient can call <xref linkend="bus-messages-add-match"/> to
+ receive that signal: if the signal is sent directly to that recipient
+ using a unicast message, it does not need to add a match rule at all,
+ and there is no race condition. Another use for unicast signals,
+ on message buses whose security policy prevents eavesdropping, is to
+ send sensitive information which should only be visible to one
+ recipient.
</para>
+
+ <para>
+ When the message bus receives a method call, if the
+ <literal>DESTINATION</literal> field is absent, the call is taken to be
+ a standard one-to-one message and interpreted by the message bus
+ itself. For example, sending an
+ <literal>org.freedesktop.DBus.Peer.Ping</literal> message with no
+ <literal>DESTINATION</literal> will cause the message bus itself to
+ reply to the ping immediately; the message bus will not make this
+ message visible to other applications.
+ </para>
+
+ <para>
+ Continuing the <literal>org.freedesktop.DBus.Peer.Ping</literal> example, if
+ the ping message were sent with a <literal>DESTINATION</literal> name of
+ <literal>com.yoyodyne.Screensaver</literal>, then the ping would be
+ forwarded, and the Yoyodyne Corporation screensaver application would be
+ expected to reply to the ping.
+ </para>
+
+ <para>
+ Message bus implementations may impose a security policy which
+ prevents certain messages from being sent or received.
+ When a message cannot be sent or received due to a security
+ policy, the message bus should send an error reply, unless the
+ original message had the <literal>NO_REPLY</literal> flag.
+ </para>
+
+ <sect3 id="message-bus-routing-eavesdropping">
+ <title>Eavesdropping</title>
+ <para>
+ Receiving a unicast message whose <literal>DESTINATION</literal>
+ indicates a different recipient is called
+ <firstterm>eavesdropping</firstterm>. On a message bus which acts as
+ a security boundary (like the standard system bus), the security
+ policy should usually prevent eavesdropping, since unicast messages
+ are normally kept private and may contain security-sensitive
+ information.
+ </para>
+
+ <para>
+ Eavesdropping is mainly useful for debugging tools, such as
+ the <literal>dbus-monitor</literal> tool in the reference
+ implementation of D-Bus. Tools which eavesdrop on the message bus
+ should be careful to avoid sending a reply or error in response to
+ messages intended for a different client.
+ </para>
+
+ <para>
+ Clients may attempt to eavesdrop by adding match rules
+ (see <xref linkend="message-bus-routing-match-rules"/>) containing
+ the <literal>eavesdrop='true'</literal> match. If the message bus'
+ security policy does not allow eavesdropping, the match rule can
+ still be added, but will not have any practical effect. For
+ compatibility with older message bus implementations, if adding such
+ a match rule results in an error reply, the client may fall back to
+ adding the same rule with the <literal>eavesdrop</literal> match
+ omitted.
+ </para>
+ </sect3>
+
<sect3 id="message-bus-routing-match-rules">
<title>Match Rules</title>
<para>
- An important part of the message bus routing protocol is match
- rules. Match rules describe what messages can be sent to a client
- based on the contents of the message. When a message is routed
- through the bus it is compared to clients' match rules. If any
- of the rules match, the message is dispatched to the client.
- If none of the rules match the message never leaves the bus. This
- is an effective way to control traffic over the bus and to make sure
- only relevant message need to be processed by the client.
+ An important part of the message bus routing protocol is match
+ rules. Match rules describe the messages that should be sent to a
+ client, based on the contents of the message. Broadcast signals
+ are only sent to clients which have a suitable match rule: this
+ avoids waking up client processes to deal with signals that are
+ not relevant to that client.
+ </para>
+ <para>
+ Messages that list a client as their <literal>DESTINATION</literal>
+ do not need to match the client's match rules, and are sent to that
+ client regardless. As a result, match rules are mainly used to
+ receive a subset of broadcast signals.
+ </para>
+ <para>
+ Match rules can also be used for eavesdropping
+ (see <xref linkend="message-bus-routing-eavesdropping"/>),
+ if the security policy of the message bus allows it.
</para>
<para>
Match rules are added using the AddMatch bus method
@@ -3732,6 +4004,43 @@
path match is path='/org/freedesktop/Hal/Manager'</entry>
</row>
<row>
+ <entry><literal>path_namespace</literal></entry>
+ <entry>An object path</entry>
+ <entry>
+ <para>
+ Matches messages which are sent from or to an
+ object for which the object path is either the
+ given value, or that value followed by one or
+ more path components.
+ </para>
+
+ <para>
+ For example,
+ <literal>path_namespace='/com/example/foo'</literal>
+ would match signals sent by
+ <literal>/com/example/foo</literal>
+ or by
+ <literal>/com/example/foo/bar</literal>,
+ but not by
+ <literal>/com/example/foobar</literal>.
+ </para>
+
+ <para>
+ Using both <literal>path</literal> and
+ <literal>path_namespace</literal> in the same match
+ rule is not allowed.
+ </para>
+
+ <para>
+ <emphasis>
+ This match key was added in version 0.16 of the
+ D-Bus specification and implemented by the bus
+ daemon in dbus 1.5.0 and later.
+ </emphasis>
+ </para>
+ </entry>
+ </row>
+ <row>
<entry><literal>destination</literal></entry>
<entry>A unique name (see <xref linkend="term-unique-name"/>)</entry>
<entry>Matches messages which are being sent to the given unique name. An
@@ -3741,24 +4050,99 @@
<entry><literal>arg[0, 1, 2, 3, ...]</literal></entry>
<entry>Any string</entry>
<entry>Arg matches are special and are used for further restricting the
- match based on the arguments in the body of a message. As of this time
- only string arguments can be matched. An example of an argument match
+ match based on the arguments in the body of a message. Only arguments of type
+ STRING can be matched in this way. An example of an argument match
would be arg3='Foo'. Only argument indexes from 0 to 63 should be
accepted.</entry>
</row>
<row>
<entry><literal>arg[0, 1, 2, 3, ...]path</literal></entry>
<entry>Any string</entry>
- <entry>Argument path matches provide a specialised form of wildcard
- matching for path-like namespaces. As with normal argument matches,
- if the argument is exactly equal to the string given in the match
- rule then the rule is satisfied. Additionally, there is also a
- match when either the string given in the match rule or the
- appropriate message argument ends with '/' and is a prefix of the
- other. An example argument path match is arg0path='/aa/bb/'. This
- would match messages with first arguments of '/', '/aa/',
- '/aa/bb/', '/aa/bb/cc/' and '/aa/bb/cc'. It would not match
- messages with first arguments of '/aa/b', '/aa' or even '/aa/bb'.</entry>
+ <entry>
+ <para>Argument path matches provide a specialised form of wildcard matching for
+ path-like namespaces. They can match arguments whose type is either STRING or
+ OBJECT_PATH. As with normal argument matches,
+ if the argument is exactly equal to the string given in the match
+ rule then the rule is satisfied. Additionally, there is also a
+ match when either the string given in the match rule or the
+ appropriate message argument ends with '/' and is a prefix of the
+ other. An example argument path match is arg0path='/aa/bb/'. This
+ would match messages with first arguments of '/', '/aa/',
+ '/aa/bb/', '/aa/bb/cc/' and '/aa/bb/cc'. It would not match
+ messages with first arguments of '/aa/b', '/aa' or even '/aa/bb'.</para>
+
+ <para>This is intended for monitoring “directories” in file system-like
+ hierarchies, as used in the <citetitle>dconf</citetitle> configuration
+ system. An application interested in all nodes in a particular hierarchy would
+ monitor <literal>arg0path='/ca/example/foo/'</literal>. Then the service could
+ emit a signal with zeroth argument <literal>"/ca/example/foo/bar"</literal> to
+ represent a modification to the “bar” property, or a signal with zeroth
+ argument <literal>"/ca/example/"</literal> to represent atomic modification of
+ many properties within that directory, and the interested application would be
+ notified in both cases.</para>
+ <para>
+ <emphasis>
+ This match key was added in version 0.12 of the
+ D-Bus specification, implemented for STRING
+ arguments by the bus daemon in dbus 1.2.0 and later,
+ and implemented for OBJECT_PATH arguments in dbus 1.5.0
+ and later.
+ </emphasis>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry><literal>arg0namespace</literal></entry>
+ <entry>Like a bus name, except that the string is not
+ required to contain a '.' (period)</entry>
+ <entry>
+ <para>Match messages whose first argument is of type STRING, and is a bus name
+ or interface name within the specified namespace. This is primarily intended
+ for watching name owner changes for a group of related bus names, rather than
+ for a single name or all name changes.</para>
+
+ <para>Because every valid interface name is also a valid
+ bus name, this can also be used for messages whose
+ first argument is an interface name.</para>
+
+ <para>For example, the match rule
+ <literal>member='NameOwnerChanged',arg0namespace='com.example.backend'</literal>
+ matches name owner changes for bus names such as
+ <literal>com.example.backend.foo</literal>,
+ <literal>com.example.backend.foo.bar</literal>, and
+ <literal>com.example.backend</literal> itself.</para>
+
+ <para>See also <xref linkend='bus-messages-name-owner-changed'/>.</para>
+ <para>
+ <emphasis>
+ This match key was added in version 0.16 of the
+ D-Bus specification and implemented by the bus
+ daemon in dbus 1.5.0 and later.
+ </emphasis>
+ </para>
+ </entry>
+ </row>
+ <row>
+ <entry><literal>eavesdrop</literal></entry>
+ <entry><literal>'true'</literal>, <literal>'false'</literal></entry>
+ <entry>Since D-Bus 1.5.6, match rules do not
+ match messages which have a <literal>DESTINATION</literal>
+ field unless the match rule specifically
+ requests this
+ (see <xref linkend="message-bus-routing-eavesdropping"/>)
+ by specifying <literal>eavesdrop='true'</literal>
+ in the match rule. <literal>eavesdrop='false'</literal>
+ restores the default behaviour. Messages are
+ delivered to their <literal>DESTINATION</literal>
+ regardless of match rules, so this match does not
+ affect normal delivery of unicast messages.
+ If the message bus has a security policy which forbids
+ eavesdropping, this match may still be used without error,
+ but will not have any practical effect.
+ In older versions of D-Bus, this match was not allowed
+ in match rules, and all match rules behaved as if
+ <literal>eavesdrop='true'</literal> had been used.
+ </entry>
</row>
</tbody>
</tgroup>
diff --git a/test/Makefile.am b/test/Makefile.am
index e5fd756b..971299a9 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -4,9 +4,22 @@
SUBDIRS= . name-test
DIST_SUBDIRS=name-test
-INCLUDES=-I$(top_srcdir) $(DBUS_TEST_CFLAGS)
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ $(GLIB_CFLAGS) \
+ $(DBUS_GLIB_CFLAGS) \
+ $(NULL)
-libdbus_testutils_la_SOURCES = test-utils.h test-utils.c
+# improve backtraces from test stuff
+AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
+
+libdbus_testutils_la_SOURCES = \
+ test-utils.c \
+ test-utils.h \
+ $(NULL)
+libdbus_testutils_la_LIBADD = \
+ $(top_builddir)/dbus/libdbus-internal.la \
+ $(NULL)
noinst_LTLIBRARIES = libdbus-testutils.la
@@ -52,54 +65,27 @@ endif !DBUS_BUILD_TESTS
noinst_PROGRAMS= $(TEST_BINARIES)
-test_service_SOURCES= \
- test-service.c
-
-test_names_SOURCES= \
- test-names.c
-
-##break_loader_SOURCES= \
-## break-loader.c
-
-test_shell_service_SOURCES = \
- test-shell-service.c
-
-shell_test_SOURCES= \
- shell-test.c
-
-spawn_test_SOURCES= \
- spawn-test.c
-
-test_exit_SOURCES = \
- test-exit.c
-
-test_segfault_SOURCES = \
- test-segfault.c
-
-test_sleep_forever_SOURCES = \
- test-sleep-forever.c
-
-# This assumes that most tests will be linked to libdbus-internal;
-# tests linked to only the public libdbus have their own CPPFLAGS.
-AM_CPPFLAGS=-DDBUS_STATIC_BUILD
-TEST_LIBS=$(top_builddir)/dbus/libdbus-internal.la $(DBUS_TEST_LIBS)
+static_cppflags = \
+ $(AM_CPPFLAGS) \
+ -DDBUS_STATIC_BUILD \
+ $(NULL)
-test_service_LDADD=libdbus-testutils.la $(TEST_LIBS)
-test_service_LDFLAGS=@R_DYNAMIC_LDFLAG@
-test_names_LDADD=libdbus-testutils.la $(TEST_LIBS)
-test_names_LDFLAGS=@R_DYNAMIC_LDFLAG@
-## break_loader_LDADD= $(TEST_LIBS)
-## break_loader_LDFLAGS=@R_DYNAMIC_LDFLAG@
-test_shell_service_LDADD=libdbus-testutils.la $(TEST_LIBS)
-test_shell_service_LDFLAGS=@R_DYNAMIC_LDFLAG@
-shell_test_LDADD=libdbus-testutils.la $(TEST_LIBS)
-shell_test_LDFLAGS=@R_DYNAMIC_LDFLAG@
-spawn_test_LDADD=$(TEST_LIBS)
-spawn_test_LDFLAGS=@R_DYNAMIC_LDFLAG@
+test_service_CPPFLAGS = $(static_cppflags)
+test_service_LDADD = libdbus-testutils.la
+test_names_CPPFLAGS = $(static_cppflags)
+test_names_LDADD = libdbus-testutils.la
+## break_loader_CPPFLAGS = $(static_cppflags)
+## break_loader_LDADD = $(top_builddir)/dbus/libdbus-internal.la
+test_shell_service_CPPFLAGS = $(static_cppflags)
+test_shell_service_LDADD = libdbus-testutils.la
+shell_test_CPPFLAGS = $(static_cppflags)
+shell_test_LDADD = libdbus-testutils.la
+spawn_test_CPPFLAGS = $(static_cppflags)
+spawn_test_LDADD = $(top_builddir)/dbus/libdbus-internal.la
test_refs_SOURCES = internals/refs.c
-test_refs_CPPFLAGS = -DDBUS_STATIC_BUILD $(GLIB_CFLAGS)
-test_refs_LDADD = libdbus-testutils.la $(GLIB_LIBS) $(TEST_LIBS)
+test_refs_CPPFLAGS = $(static_cppflags)
+test_refs_LDADD = libdbus-testutils.la $(GLIB_LIBS)
EXTRA_DIST = dbus-test-runner
@@ -110,6 +96,7 @@ testexec_PROGRAMS =
installable_tests = \
test-corrupt \
test-dbus-daemon \
+ test-dbus-daemon-eavesdrop \
test-loopback \
test-marshal \
test-refs \
@@ -130,36 +117,33 @@ TESTS_ENVIRONMENT = \
$(NULL)
test_corrupt_SOURCES = corrupt.c
-test_corrupt_CPPFLAGS = $(GLIB_CFLAGS) $(DBUS_GLIB_CFLAGS)
-test_corrupt_LDFLAGS = @R_DYNAMIC_LDFLAG@
test_corrupt_LDADD = $(top_builddir)/dbus/libdbus-1.la \
$(GLIB_LIBS) \
$(DBUS_GLIB_LIBS)
test_loopback_SOURCES = loopback.c
-test_loopback_CPPFLAGS = $(GLIB_CFLAGS) $(DBUS_GLIB_CFLAGS)
-test_loopback_LDFLAGS = @R_DYNAMIC_LDFLAG@
test_loopback_LDADD = $(top_builddir)/dbus/libdbus-1.la \
$(GLIB_LIBS) \
$(DBUS_GLIB_LIBS)
test_relay_SOURCES = relay.c
-test_relay_CPPFLAGS = $(GLIB_CFLAGS) $(DBUS_GLIB_CFLAGS)
-test_relay_LDFLAGS = @R_DYNAMIC_LDFLAG@
test_relay_LDADD = $(top_builddir)/dbus/libdbus-1.la \
$(GLIB_LIBS) \
$(DBUS_GLIB_LIBS)
test_dbus_daemon_SOURCES = dbus-daemon.c
-test_dbus_daemon_CPPFLAGS = $(GLIB_CFLAGS) $(DBUS_GLIB_CFLAGS)
-test_dbus_daemon_LDFLAGS = @R_DYNAMIC_LDFLAG@
test_dbus_daemon_LDADD = $(top_builddir)/dbus/libdbus-1.la \
$(GLIB_LIBS) \
$(DBUS_GLIB_LIBS)
+test_dbus_daemon_eavesdrop_SOURCES = dbus-daemon-eavesdrop.c
+test_dbus_daemon_eavesdrop_CPPFLAGS = $(GLIB_CFLAGS) $(DBUS_GLIB_CFLAGS)
+test_dbus_daemon_eavesdrop_LDFLAGS = @R_DYNAMIC_LDFLAG@
+test_dbus_daemon_eavesdrop_LDADD = $(top_builddir)/dbus/libdbus-1.la \
+ $(GLIB_LIBS) \
+ $(DBUS_GLIB_LIBS)
+
test_marshal_SOURCES = marshal.c
-test_marshal_CPPFLAGS = $(GLIB_CFLAGS) $(DBUS_GLIB_CFLAGS)
-test_marshal_LDFLAGS = @R_DYNAMIC_LDFLAG@
test_marshal_LDADD = $(top_builddir)/dbus/libdbus-1.la \
$(GLIB_LIBS) \
$(DBUS_GLIB_LIBS)
diff --git a/test/break-loader.c b/test/break-loader.c
index 7bfa7227..542f36ff 100644
--- a/test/break-loader.c
+++ b/test/break-loader.c
@@ -446,7 +446,7 @@ randomly_change_one_type (const DBusString *orig_data,
{
int b;
b = _dbus_string_get_byte (mutated, i);
- if (_dbus_type_is_valid (b))
+ if (dbus_type_is_valid (b))
{
_dbus_string_set_byte (mutated, i, random_type ());
return;
diff --git a/test/data/valid-config-files/incoming-limit.conf b/test/data/valid-config-files/incoming-limit.conf
new file mode 100644
index 00000000..abfab3f7
--- /dev/null
+++ b/test/data/valid-config-files/incoming-limit.conf
@@ -0,0 +1,18 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <!-- Our well-known bus type, don't change this -->
+ <type>session</type>
+ <listen>unix:tmpdir=/tmp</listen>
+
+ <policy context="default">
+ <!-- Allow everything to be sent -->
+ <allow send_destination="*" eavesdrop="true"/>
+ <!-- Allow everything to be received -->
+ <allow eavesdrop="true"/>
+ <!-- Allow anyone to own anything -->
+ <allow own="*"/>
+ </policy>
+
+ <limit name="max_incoming_bytes">1</limit>
+</busconfig>
diff --git a/test/dbus-daemon-eavesdrop.c b/test/dbus-daemon-eavesdrop.c
new file mode 100644
index 00000000..6819ec13
--- /dev/null
+++ b/test/dbus-daemon-eavesdrop.c
@@ -0,0 +1,558 @@
+/* Integration tests for the eavesdrop=true|false keyword in DBusMatchRule
+ *
+ * Author: Cosimo Alfarano <cosimo.alfarano@collabora.co.uk>
+ * Based on: tests/dbus-daemon.c by Simon McVittie
+ * Copyright © 2010-2011 Nokia Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <string.h>
+
+#ifdef DBUS_WIN
+# include <windows.h>
+#else
+# include <signal.h>
+# include <unistd.h>
+#endif
+
+#define SENDER_NAME "test.eavesdrop.sender"
+#define SENDER_PATH "/test/eavesdrop/sender"
+#define SENDER_IFACE SENDER_NAME
+#define SENDER_SIGNAL_NAME "Signal"
+#define SENDER_STOPPER_NAME "Stopper"
+
+/* This rule is equivalent to the one added to a proxy connecting to
+ * SENDER_NAME+SENDER_IFACE, plus restricting on signal name.
+ * Being more restrictive, if the connection receives what we need, for sure
+ * the original proxy rule will match it */
+#define RECEIVER_RULE "sender='" SENDER_NAME "'," \
+ "interface='" SENDER_IFACE "'," \
+ "type='signal'," \
+ "member='" SENDER_SIGNAL_NAME "'"
+#define POLITELISTENER_RULE RECEIVER_RULE
+#define EAVESDROPPER_RULE RECEIVER_RULE ",eavesdrop=true"
+
+#define STOPPER_RULE "sender='" SENDER_NAME \
+ "',interface='" SENDER_IFACE "',type='signal',member='" SENDER_STOPPER_NAME "'"
+
+/* a connection received a signal to whom? */
+typedef enum {
+ NONE_YET = 0,
+ TO_ME,
+ TO_OTHER,
+ BROADCAST,
+} SignalDst;
+
+typedef struct {
+ DBusError e;
+ GError *ge;
+
+ gint daemon_pid;
+
+ /* eavedrop keyword tests */
+ DBusConnection *sender;
+ DBusConnection *receiver;
+ SignalDst receiver_dst;
+ dbus_bool_t receiver_got_stopper;
+ DBusConnection *eavesdropper;
+ SignalDst eavesdropper_dst;
+ dbus_bool_t eavesdropper_got_stopper;
+ DBusConnection *politelistener;
+ SignalDst politelistener_dst;
+ dbus_bool_t politelistener_got_stopper;
+} Fixture;
+
+#define assert_no_error(e) _assert_no_error (e, __FILE__, __LINE__)
+static void
+_assert_no_error (const DBusError *e,
+ const char *file,
+ int line)
+{
+ if (G_UNLIKELY (dbus_error_is_set (e)))
+ g_error ("%s:%d: expected success but got error: %s: %s",
+ file, line, e->name, e->message);
+}
+
+static gchar *
+spawn_dbus_daemon (gchar *binary,
+ gchar *configuration,
+ gint *daemon_pid)
+{
+ GError *error = NULL;
+ GString *address;
+ gint address_fd;
+ gchar *argv[] = {
+ binary,
+ configuration,
+ "--nofork",
+ "--print-address=1", /* stdout */
+ NULL
+ };
+
+ g_spawn_async_with_pipes (NULL, /* working directory */
+ argv,
+ NULL, /* envp */
+ G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+ NULL, /* child_setup */
+ NULL, /* user data */
+ daemon_pid,
+ NULL, /* child's stdin = /dev/null */
+ &address_fd,
+ NULL, /* child's stderr = our stderr */
+ &error);
+ g_assert_no_error (error);
+
+ address = g_string_new (NULL);
+
+ /* polling until the dbus-daemon writes out its address is a bit stupid,
+ * but at least it's simple, unlike dbus-launch... in principle we could
+ * use select() here, but life's too short */
+ while (1)
+ {
+ gssize bytes;
+ gchar buf[4096];
+ gchar *newline;
+
+ bytes = read (address_fd, buf, sizeof (buf));
+
+ if (bytes > 0)
+ g_string_append_len (address, buf, bytes);
+
+ newline = strchr (address->str, '\n');
+
+ if (newline != NULL)
+ {
+ g_string_truncate (address, newline - address->str);
+ break;
+ }
+
+ g_usleep (G_USEC_PER_SEC / 10);
+ }
+
+ return g_string_free (address, FALSE);
+}
+
+static DBusConnection *
+connect_to_bus (const gchar *address)
+{
+ DBusConnection *conn;
+ DBusError error = DBUS_ERROR_INIT;
+ dbus_bool_t ok;
+
+ conn = dbus_connection_open_private (address, &error);
+ assert_no_error (&error);
+ g_assert (conn != NULL);
+
+ ok = dbus_bus_register (conn, &error);
+ assert_no_error (&error);
+ g_assert (ok);
+ g_assert (dbus_bus_get_unique_name (conn) != NULL);
+
+ dbus_connection_setup_with_g_main (conn, NULL);
+ return conn;
+}
+
+/* send a unicast signal to <self> to ensure that no other connection
+ * listening is the actual recipient for the signal */
+static DBusHandlerResult
+sender_send_unicast_to_sender (Fixture *f)
+{
+ DBusError error = DBUS_ERROR_INIT;
+ DBusMessage *signal;
+
+ signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE,
+ SENDER_SIGNAL_NAME);
+ dbus_message_set_destination (signal, dbus_bus_get_unique_name (f->sender));
+
+ if (signal == NULL)
+ g_error ("OOM");
+
+ if (!dbus_connection_send (f->sender, signal, NULL))
+ g_error ("OOM");
+
+ dbus_message_unref (signal);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/* send a unicast signal to <receiver>, making <politelistener> and
+ * <eavesdropper> not a actual recipient for it */
+static DBusHandlerResult
+sender_send_unicast_to_receiver (Fixture *f)
+{
+ DBusError error = DBUS_ERROR_INIT;
+ DBusMessage *signal;
+
+ signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE, SENDER_SIGNAL_NAME);
+ dbus_message_set_destination (signal, dbus_bus_get_unique_name (f->receiver));
+
+ if (signal == NULL)
+ g_error ("OOM");
+
+ if (!dbus_connection_send (f->sender, signal, NULL))
+ g_error ("OOM");
+
+ dbus_message_unref (signal);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+static DBusHandlerResult
+sender_send_broadcast (Fixture *f)
+{
+ DBusError error = DBUS_ERROR_INIT;
+ DBusMessage *signal;
+
+ signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE, SENDER_SIGNAL_NAME);
+ dbus_message_set_destination (signal, NULL);
+
+ if (signal == NULL)
+ g_error ("OOM");
+
+ if (!dbus_connection_send (f->sender, signal, NULL))
+ g_error ("OOM");
+
+ dbus_message_unref (signal);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/* Send special broadcast signal to indicate that the connections can "stop"
+ * listening and check their results.
+ * DBus does not re-order messages, so when the three connections have received
+ * this signal, we are sure that any message sent before it has also been
+ * dispatched. */
+static DBusHandlerResult
+sender_send_stopper (Fixture *f)
+{
+ DBusError error = DBUS_ERROR_INIT;
+ DBusMessage *signal;
+
+ signal = dbus_message_new_signal (SENDER_PATH, SENDER_IFACE, SENDER_STOPPER_NAME);
+ dbus_message_set_destination (signal, NULL);
+
+ if (signal == NULL)
+ g_error ("OOM");
+
+ if (!dbus_connection_send (f->sender, signal, NULL))
+ g_error ("OOM");
+
+ dbus_message_unref (signal);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+/* Ignore NameAcquired, then depending on the signal received:
+ * - updates f-><conn>_dst based on the destination of the message
+ * - asserts that <conn> received the stop signal
+ */
+static DBusHandlerResult
+signal_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ Fixture *f = user_data;
+ SignalDst *dst = NULL;
+ DBusConnection **conn;
+ dbus_bool_t *got_stopper;
+
+ if (0 == strcmp (dbus_message_get_member (message), "NameAcquired"))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (connection == f->receiver)
+ {
+ dst = &(f->receiver_dst);
+ conn = &(f->receiver);
+ got_stopper = &(f->receiver_got_stopper);
+ }
+ else if (connection == f->eavesdropper)
+ {
+ dst = &(f->eavesdropper_dst);
+ conn = &(f->eavesdropper);
+ got_stopper = &(f->eavesdropper_got_stopper);
+ }
+ else if (connection == f->politelistener)
+ {
+ dst = &(f->politelistener_dst);
+ conn = &(f->politelistener);
+ got_stopper = &(f->politelistener_got_stopper);
+ }
+ else
+ {
+ g_error ("connection not matching");
+ }
+
+ if (0 == strcmp (dbus_message_get_member (message), SENDER_SIGNAL_NAME))
+ {
+ if (dbus_message_get_destination (message) == NULL)
+ *dst = BROADCAST;
+ else if (0 == strcmp (dbus_message_get_destination (message), dbus_bus_get_unique_name (*conn)))
+ *dst = TO_ME;
+ else /* if (dbus_message_get_destination (message) != NULL) */
+ *dst = TO_OTHER;
+ }
+ else if (0 == strcmp (dbus_message_get_member (message), SENDER_STOPPER_NAME))
+ {
+ *got_stopper = TRUE;
+ }
+ else
+ {
+ g_error ("got unknown member from message: %s",
+ dbus_message_get_member (message));
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+add_receiver_filter (Fixture *f)
+{
+ DBusError e = DBUS_ERROR_INIT;
+
+ dbus_bus_add_match (f->receiver, RECEIVER_RULE, &e);
+ assert_no_error (&e);
+ dbus_bus_add_match (f->receiver, STOPPER_RULE, &e);
+ assert_no_error (&e);
+
+ if (!dbus_connection_add_filter (f->receiver,
+ signal_filter, f, NULL))
+ g_error ("OOM");
+}
+
+static void
+add_eavesdropper_filter (Fixture *f)
+{
+ DBusError e = DBUS_ERROR_INIT;
+
+ dbus_bus_add_match (f->eavesdropper, EAVESDROPPER_RULE, &e);
+ assert_no_error (&e);
+ dbus_bus_add_match (f->eavesdropper, STOPPER_RULE, &e);
+ assert_no_error (&e);
+
+ if (!dbus_connection_add_filter (f->eavesdropper,
+ signal_filter, f, NULL))
+ g_error ("OOM");
+}
+
+static void
+add_politelistener_filter (Fixture *f)
+{
+ DBusError e = DBUS_ERROR_INIT;
+
+ dbus_bus_add_match (f->politelistener, POLITELISTENER_RULE, &e);
+ assert_no_error (&e);
+ dbus_bus_add_match (f->politelistener, STOPPER_RULE, &e);
+ assert_no_error (&e);
+
+ if (!dbus_connection_add_filter (f->politelistener,
+ signal_filter, f, NULL))
+ g_error ("OOM");
+}
+
+static void
+setup (Fixture *f,
+ gconstpointer context G_GNUC_UNUSED)
+{
+ gchar *dbus_daemon;
+ gchar *config;
+ gchar *address;
+
+ f->ge = NULL;
+ dbus_error_init (&f->e);
+
+ dbus_daemon = g_strdup (g_getenv ("DBUS_TEST_DAEMON"));
+
+ if (dbus_daemon == NULL)
+ dbus_daemon = g_strdup ("dbus-daemon");
+
+ if (g_getenv ("DBUS_TEST_SYSCONFDIR") != NULL)
+ {
+ config = g_strdup_printf ("--config-file=%s/dbus-1/session.conf",
+ g_getenv ("DBUS_TEST_SYSCONFDIR"));
+ }
+ else if (g_getenv ("DBUS_TEST_DATA") != NULL)
+ {
+ config = g_strdup_printf (
+ "--config-file=%s/valid-config-files/session.conf",
+ g_getenv ("DBUS_TEST_DATA"));
+ }
+ else
+ {
+ config = g_strdup ("--session");
+ }
+
+ address = spawn_dbus_daemon (dbus_daemon, config, &f->daemon_pid);
+
+ g_free (dbus_daemon);
+ g_free (config);
+
+ f->sender = connect_to_bus (address);
+ dbus_bus_request_name (f->sender, SENDER_NAME, DBUS_NAME_FLAG_DO_NOT_QUEUE,
+ &(f->e));
+ f->receiver = connect_to_bus (address);
+ f->eavesdropper = connect_to_bus (address);
+ f->politelistener = connect_to_bus (address);
+ add_receiver_filter (f);
+ add_politelistener_filter (f);
+ add_eavesdropper_filter (f);
+
+ g_free (address);
+}
+
+static void
+test_eavesdrop_broadcast (Fixture *f,
+ gconstpointer context G_GNUC_UNUSED)
+{
+ sender_send_broadcast (f);
+ sender_send_stopper (f);
+
+ while (!f->receiver_got_stopper ||
+ !f->politelistener_got_stopper ||
+ !f->eavesdropper_got_stopper)
+ g_main_context_iteration (NULL, TRUE);
+
+ /* all the three connection can receive a broadcast */
+ g_assert_cmpint (f->receiver_dst, ==, BROADCAST);
+ g_assert_cmpint (f->politelistener_dst, ==, BROADCAST);
+ g_assert_cmpint (f->eavesdropper_dst, ==, BROADCAST);
+}
+
+/* a way to say that none of the listening connection are destination of the
+ * signal */
+static void
+test_eavesdrop_unicast_to_sender (Fixture *f,
+ gconstpointer context G_GNUC_UNUSED)
+{
+ sender_send_unicast_to_sender (f);
+ sender_send_stopper (f);
+
+ while (!f->receiver_got_stopper ||
+ !f->politelistener_got_stopper ||
+ !f->eavesdropper_got_stopper)
+ g_main_context_iteration (NULL, TRUE);
+
+ /* not directed to it and not broadcasted, they cannot receive it */
+ g_assert_cmpint (f->receiver_dst, ==, NONE_YET);
+ g_assert_cmpint (f->politelistener_dst, ==, NONE_YET);
+ /* eavesdrop=true, it will receive the signal even though it's not directed
+ * to it */
+ g_assert_cmpint (f->eavesdropper_dst, ==, TO_OTHER);
+}
+
+static void
+test_eavesdrop_unicast_to_receiver (Fixture *f,
+ gconstpointer context G_GNUC_UNUSED)
+{
+ sender_send_unicast_to_receiver (f);
+ sender_send_stopper (f);
+
+ while (!f->receiver_got_stopper ||
+ !f->politelistener_got_stopper ||
+ !f->eavesdropper_got_stopper)
+ g_main_context_iteration (NULL, TRUE);
+
+ /* direct to him */
+ g_assert_cmpint (f->receiver_dst, ==, TO_ME);
+ /* not directed to it and not broadcasted, it cannot receive it */
+ g_assert_cmpint (f->politelistener_dst, ==, NONE_YET);
+ /* eavesdrop=true, it will receive the signal even though it's not directed
+ * to it */
+ g_assert_cmpint (f->eavesdropper_dst, ==, TO_OTHER);
+}
+
+static void
+teardown (Fixture *f,
+ gconstpointer context G_GNUC_UNUSED)
+{
+ dbus_error_free (&f->e);
+ g_clear_error (&f->ge);
+
+ if (f->sender != NULL)
+ {
+ dbus_connection_close (f->sender);
+ dbus_connection_unref (f->sender);
+ f->sender = NULL;
+ }
+
+ if (f->receiver != NULL)
+ {
+ dbus_connection_remove_filter (f->receiver,
+ signal_filter, f);
+
+ dbus_connection_close (f->receiver);
+ dbus_connection_unref (f->receiver);
+ f->receiver = NULL;
+ }
+
+ if (f->politelistener != NULL)
+ {
+ dbus_connection_remove_filter (f->politelistener,
+ signal_filter, f);
+
+ dbus_connection_close (f->politelistener);
+ dbus_connection_unref (f->politelistener);
+ f->politelistener = NULL;
+ }
+
+ if (f->eavesdropper != NULL)
+ {
+ dbus_connection_remove_filter (f->eavesdropper,
+ signal_filter, f);
+
+ dbus_connection_close (f->eavesdropper);
+ dbus_connection_unref (f->eavesdropper);
+ f->eavesdropper = NULL;
+ }
+
+#ifdef DBUS_WIN
+ TerminateProcess (f->daemon_pid, 1);
+#else
+ kill (f->daemon_pid, SIGTERM);
+#endif
+
+ g_spawn_close_pid (f->daemon_pid);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+ g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id=");
+
+ g_test_add ("/eavedrop/match_keyword/broadcast", Fixture, NULL,
+ setup, test_eavesdrop_broadcast, teardown);
+ g_test_add ("/eavedrop/match_keyword/unicast_to_receiver", Fixture, NULL,
+ setup, test_eavesdrop_unicast_to_receiver,
+ teardown);
+ g_test_add ("/eavedrop/match_keyword/unicast_to_sender", Fixture, NULL,
+ setup, test_eavesdrop_unicast_to_sender, teardown);
+
+ return g_test_run ();
+}
diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c
index e192c68f..cc871530 100644
--- a/test/dbus-daemon.c
+++ b/test/dbus-daemon.c
@@ -42,6 +42,8 @@
#endif
typedef struct {
+ gboolean skip;
+
DBusError e;
GError *ge;
@@ -149,8 +151,6 @@ echo_filter (DBusConnection *connection,
void *user_data)
{
DBusMessage *reply;
- DBusError error = DBUS_ERROR_INIT;
- int *sleep_ms = user_data;
if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -168,42 +168,63 @@ echo_filter (DBusConnection *connection,
return DBUS_HANDLER_RESULT_HANDLED;
}
+typedef struct {
+ const char *bug_ref;
+ guint min_messages;
+ const char *config_file;
+} Config;
+
static void
setup (Fixture *f,
- gconstpointer context G_GNUC_UNUSED)
+ gconstpointer context)
{
+ const Config *config = context;
gchar *dbus_daemon;
- gchar *config;
+ gchar *arg;
gchar *address;
f->ge = NULL;
dbus_error_init (&f->e);
- dbus_daemon = g_strdup (g_getenv ("DBUS_TEST_DAEMON"));
-
- if (dbus_daemon == NULL)
- dbus_daemon = g_strdup ("dbus-daemon");
+ if (config != NULL && config->config_file != NULL)
+ {
+ if (g_getenv ("DBUS_TEST_DATA") == NULL)
+ {
+ g_message ("SKIP: set DBUS_TEST_DATA to a directory containing %s",
+ config->config_file);
+ f->skip = TRUE;
+ return;
+ }
- if (g_getenv ("DBUS_TEST_SYSCONFDIR") != NULL)
+ arg = g_strdup_printf (
+ "--config-file=%s/%s",
+ g_getenv ("DBUS_TEST_DATA"), config->config_file);
+ }
+ else if (g_getenv ("DBUS_TEST_SYSCONFDIR") != NULL)
{
- config = g_strdup_printf ("--config-file=%s/dbus-1/session.conf",
+ arg = g_strdup_printf ("--config-file=%s/dbus-1/session.conf",
g_getenv ("DBUS_TEST_SYSCONFDIR"));
}
else if (g_getenv ("DBUS_TEST_DATA") != NULL)
{
- config = g_strdup_printf (
+ arg = g_strdup_printf (
"--config-file=%s/valid-config-files/session.conf",
g_getenv ("DBUS_TEST_DATA"));
}
else
{
- config = g_strdup ("--session");
+ arg = g_strdup ("--session");
}
- address = spawn_dbus_daemon (dbus_daemon, config, &f->daemon_pid);
+ dbus_daemon = g_strdup (g_getenv ("DBUS_TEST_DAEMON"));
+
+ if (dbus_daemon == NULL)
+ dbus_daemon = g_strdup ("dbus-daemon");
+
+ address = spawn_dbus_daemon (dbus_daemon, arg, &f->daemon_pid);
g_free (dbus_daemon);
- g_free (config);
+ g_free (arg);
f->left_conn = connect_to_bus (address);
f->right_conn = connect_to_bus (address);
@@ -230,16 +251,26 @@ pc_count (DBusPendingCall *pc,
static void
test_echo (Fixture *f,
- gconstpointer context G_GNUC_UNUSED)
+ gconstpointer context)
{
+ const Config *config = context;
guint count = 2000;
guint sent;
guint received = 0;
double elapsed;
+ if (f->skip)
+ return;
+
+ if (config != NULL && config->bug_ref != NULL)
+ g_test_bug (config->bug_ref);
+
if (g_test_perf ())
count = 100000;
+ if (config != NULL)
+ count = MAX (config->min_messages, count);
+
add_echo_filter (f);
g_test_timer_start ();
@@ -305,15 +336,23 @@ teardown (Fixture *f,
f->right_conn = NULL;
}
+ if (f->daemon_pid != 0)
+ {
#ifdef DBUS_WIN
- TerminateProcess (f->daemon_pid, 1);
+ TerminateProcess (f->daemon_pid, 1);
#else
- kill (f->daemon_pid, SIGTERM);
+ kill (f->daemon_pid, SIGTERM);
#endif
- g_spawn_close_pid (f->daemon_pid);
+ g_spawn_close_pid (f->daemon_pid);
+ f->daemon_pid = 0;
+ }
}
+static Config limited_config = {
+ "34393", 10000, "valid-config-files/incoming-limit.conf"
+};
+
int
main (int argc,
char **argv)
@@ -322,6 +361,8 @@ main (int argc,
g_test_bug_base ("https://bugs.freedesktop.org/show_bug.cgi?id=");
g_test_add ("/echo/session", Fixture, NULL, setup, test_echo, teardown);
+ g_test_add ("/echo/limited", Fixture, &limited_config,
+ setup, test_echo, teardown);
return g_test_run ();
}
diff --git a/test/marshal.c b/test/marshal.c
index 4cee9412..e9ac7e30 100644
--- a/test/marshal.c
+++ b/test/marshal.c
@@ -146,7 +146,6 @@ test_endian (Fixture *f,
gconstpointer arg)
{
const gchar *blob = arg;
- const gchar *native_blob;
char *output;
DBusMessage *m;
int len;
diff --git a/test/name-test/Makefile.am b/test/name-test/Makefile.am
index 5f11f0be..68fc33ec 100644
--- a/test/name-test/Makefile.am
+++ b/test/name-test/Makefile.am
@@ -1,4 +1,12 @@
-INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) $(DBUS_TEST_CFLAGS) -DDBUS_COMPILATION
+# Everything in this directory is statically-linked to libdbus-internal
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -DDBUS_COMPILATION \
+ -DDBUS_STATIC_BUILD \
+ $(NULL)
+
+# if assertions are enabled, improve backtraces
+AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
## note that TESTS has special meaning (stuff to use in make check)
## so if adding tests not to be run in make check, don't add them to
@@ -18,57 +26,14 @@ if DBUS_BUILD_TESTS
## build even when not doing "make check"
noinst_PROGRAMS=test-pending-call-dispatch test-pending-call-timeout test-threads-init test-ids test-shutdown test-privserver test-privserver-client test-autolaunch
-AM_CPPFLAGS = -DDBUS_STATIC_BUILD
-test_pending_call_dispatch_SOURCES = \
- test-pending-call-dispatch.c
-
-test_pending_call_dispatch_LDADD=$(top_builddir)/dbus/libdbus-internal.la $(DBUS_TEST_LIBS)
-test_pending_call_dispatch_LDFLAGS=@R_DYNAMIC_LDFLAG@
-
-test_pending_call_timeout_SOURCES = \
- test-pending-call-timeout.c
-
-test_pending_call_timeout_LDADD=$(top_builddir)/dbus/libdbus-internal.la $(DBUS_TEST_LIBS)
-test_pending_call_timeout_LDFLAGS=@R_DYNAMIC_LDFLAG@
-
-test_threads_init_SOURCES = \
- test-threads-init.c
-
-test_threads_init_LDADD=$(top_builddir)/dbus/libdbus-internal.la $(DBUS_TEST_LIBS)
-test_threads_init_LDFLAGS=@R_DYNAMIC_LDFLAG@
-
-test_ids_SOURCES = \
- test-ids.c
-
-test_ids_LDADD=$(top_builddir)/dbus/libdbus-internal.la $(DBUS_TEST_LIBS)
-test_ids_LDFLAGS=@R_DYNAMIC_LDFLAG@
-
-test_shutdown_SOURCES = \
- test-shutdown.c
-
-test_shutdown_CFLAGS=
-test_shutdown_LDADD=$(top_builddir)/dbus/libdbus-internal.la ../libdbus-testutils.la $(DBUS_TEST_LIBS)
-test_shutdown_LDFLAGS=@R_DYNAMIC_LDFLAG@
-
-test_privserver_SOURCES = \
- test-privserver.c
-
-test_privserver_CFLAGS=
-test_privserver_LDADD=$(top_builddir)/dbus/libdbus-internal.la ../libdbus-testutils.la $(DBUS_TEST_LIBS)
-test_privserver_LDFLAGS=@R_DYNAMIC_LDFLAG@
-
-test_privserver_client_SOURCES = \
- test-privserver-client.c
-
-test_privserver_client_CFLAGS=
-test_privserver_client_LDADD=$(top_builddir)/dbus/libdbus-internal.la ../libdbus-testutils.la $(DBUS_TEST_LIBS)
-test_privserver_client_LDFLAGS=@R_DYNAMIC_LDFLAG@
-
-test_autolaunch_SOURCES = \
- test-autolaunch.c
+test_pending_call_dispatch_LDADD=$(top_builddir)/dbus/libdbus-internal.la
+test_pending_call_timeout_LDADD=$(top_builddir)/dbus/libdbus-internal.la
+test_threads_init_LDADD=$(top_builddir)/dbus/libdbus-internal.la
+test_ids_LDADD=$(top_builddir)/dbus/libdbus-internal.la
-test_autolaunch_CFLAGS=
-test_autolaunch_LDADD=$(top_builddir)/dbus/libdbus-internal.la ../libdbus-testutils.la $(DBUS_TEST_LIBS)
-test_autolaunch_LDFLAGS=@R_DYNAMIC_LDFLAG@
+test_shutdown_LDADD=../libdbus-testutils.la
+test_privserver_LDADD=../libdbus-testutils.la
+test_privserver_client_LDADD=../libdbus-testutils.la
+test_autolaunch_LDADD=../libdbus-testutils.la
endif
diff --git a/test/name-test/test-privserver-client.c b/test/name-test/test-privserver-client.c
index 1c43faee..e7f48960 100644
--- a/test/name-test/test-privserver-client.c
+++ b/test/name-test/test-privserver-client.c
@@ -71,7 +71,6 @@ open_shutdown_private_connection (dbus_bool_t use_guid)
DBusMessage *reply;
DBusConnection *privconn;
char *addr;
- char *comma;
dbus_bool_t service_died;
dbus_bool_t private_conn_lost;
diff --git a/test/test-service.c b/test/test-service.c
index 6627ea75..7181fa38 100644
--- a/test/test-service.c
+++ b/test/test-service.c
@@ -477,7 +477,14 @@ main (int argc,
dbus_error_free (&error);
exit (1);
}
-
+
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+ {
+ fprintf (stderr, "Unable to acquire service: code %d\n", result);
+ _dbus_verbose ("*** Failed to acquire service: %d\n", result);
+ exit (1);
+ }
+
_dbus_verbose ("*** Test service entering main loop\n");
_dbus_loop_run (loop);
diff --git a/test/test-shell-service.c b/test/test-shell-service.c
index 57c16123..32a88329 100644
--- a/test/test-shell-service.c
+++ b/test/test-shell-service.c
@@ -176,6 +176,13 @@ main (int argc,
exit (1);
}
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+ {
+ fprintf (stderr, "Unable to acquire service: code %d\n", result);
+ _dbus_verbose ("*** Failed to acquire service: %d\n", result);
+ exit (1);
+ }
+
_dbus_verbose ("*** Test service entering main loop\n");
_dbus_loop_run (loop);
diff --git a/test/test-utils.c b/test/test-utils.c
index 05cd7535..4fd84fe8 100644
--- a/test/test-utils.c
+++ b/test/test-utils.c
@@ -9,23 +9,12 @@ typedef struct
} CData;
static dbus_bool_t
-connection_watch_callback (DBusWatch *watch,
- unsigned int condition,
- void *data)
-{
- return dbus_watch_handle (watch, condition);
-}
-
-static dbus_bool_t
add_watch (DBusWatch *watch,
void *data)
{
CData *cd = data;
- return _dbus_loop_add_watch (cd->loop,
- watch,
- connection_watch_callback,
- cd, NULL);
+ return _dbus_loop_add_watch (cd->loop, watch);
}
static void
@@ -34,16 +23,7 @@ remove_watch (DBusWatch *watch,
{
CData *cd = data;
- _dbus_loop_remove_watch (cd->loop,
- watch, connection_watch_callback, cd);
-}
-
-static void
-connection_timeout_callback (DBusTimeout *timeout,
- void *data)
-{
- /* Can return FALSE on OOM but we just let it fire again later */
- dbus_timeout_handle (timeout);
+ _dbus_loop_remove_watch (cd->loop, watch);
}
static dbus_bool_t
@@ -52,8 +32,7 @@ add_timeout (DBusTimeout *timeout,
{
CData *cd = data;
- return _dbus_loop_add_timeout (cd->loop,
- timeout, connection_timeout_callback, cd, NULL);
+ return _dbus_loop_add_timeout (cd->loop, timeout);
}
static void
@@ -62,8 +41,7 @@ remove_timeout (DBusTimeout *timeout,
{
CData *cd = data;
- _dbus_loop_remove_timeout (cd->loop,
- timeout, connection_timeout_callback, cd);
+ _dbus_loop_remove_timeout (cd->loop, timeout);
}
static void
@@ -226,27 +204,12 @@ serverdata_new (DBusLoop *loop,
}
static dbus_bool_t
-server_watch_callback (DBusWatch *watch,
- unsigned int condition,
- void *data)
-{
- /* FIXME this can be done in dbus-mainloop.c
- * if the code in activation.c for the babysitter
- * watch handler is fixed.
- */
-
- return dbus_watch_handle (watch, condition);
-}
-
-static dbus_bool_t
add_server_watch (DBusWatch *watch,
void *data)
{
ServerData *context = data;
- return _dbus_loop_add_watch (context->loop,
- watch, server_watch_callback, context,
- NULL);
+ return _dbus_loop_add_watch (context->loop, watch);
}
static void
@@ -255,16 +218,7 @@ remove_server_watch (DBusWatch *watch,
{
ServerData *context = data;
- _dbus_loop_remove_watch (context->loop,
- watch, server_watch_callback, context);
-}
-
-static void
-server_timeout_callback (DBusTimeout *timeout,
- void *data)
-{
- /* can return FALSE on OOM but we just let it fire again later */
- dbus_timeout_handle (timeout);
+ _dbus_loop_remove_watch (context->loop, watch);
}
static dbus_bool_t
@@ -273,8 +227,7 @@ add_server_timeout (DBusTimeout *timeout,
{
ServerData *context = data;
- return _dbus_loop_add_timeout (context->loop,
- timeout, server_timeout_callback, context, NULL);
+ return _dbus_loop_add_timeout (context->loop, timeout);
}
static void
@@ -283,8 +236,7 @@ remove_server_timeout (DBusTimeout *timeout,
{
ServerData *context = data;
- _dbus_loop_remove_timeout (context->loop,
- timeout, server_timeout_callback, context);
+ _dbus_loop_remove_timeout (context->loop, timeout);
}
dbus_bool_t
diff --git a/tools/Makefile.am b/tools/Makefile.am
index ce88c85f..08b90234 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,14 +1,28 @@
configdir=$(sysconfdir)/dbus-1
-INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_X_CFLAGS) -DDBUS_LOCALEDIR=\"@EXPANDED_DATADIR@/locale\" -DDBUS_COMPILATION -DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\"
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ $(DBUS_X_CFLAGS) \
+ -DDBUS_COMPILATION \
+ -DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\" \
+ $(NULL)
+
+# if assertions are enabled, improve backtraces
+AM_LDFLAGS = @R_DYNAMIC_LDFLAG@
+
+bin_PROGRAMS = \
+ dbus-launch \
+ dbus-monitor \
+ dbus-send \
+ $(NULL)
-extra_bin_programs=
if DBUS_UNIX
-extra_bin_programs += dbus-cleanup-sockets dbus-uuidgen
+bin_PROGRAMS += \
+ dbus-cleanup-sockets \
+ dbus-uuidgen \
+ $(NULL)
endif
-bin_PROGRAMS=dbus-launch dbus-send dbus-monitor $(extra_bin_programs)
-
dbus_send_SOURCES= \
dbus-print-message.c \
dbus-print-message.h \
@@ -36,17 +50,22 @@ dbus_cleanup_sockets_SOURCES= \
dbus_uuidgen_SOURCES= \
dbus-uuidgen.c
-dbus_send_LDADD= $(top_builddir)/dbus/libdbus-1.la $(DBUS_CLIENT_LIBS)
-dbus_send_LDFLAGS=@R_DYNAMIC_LDFLAG@
+dbus_send_LDADD = \
+ $(top_builddir)/dbus/libdbus-1.la \
+ $(NULL)
-dbus_monitor_LDADD= $(top_builddir)/dbus/libdbus-1.la $(DBUS_CLIENT_LIBS)
-dbus_monitor_LDFLAGS=@R_DYNAMIC_LDFLAG@
+dbus_monitor_LDADD = \
+ $(top_builddir)/dbus/libdbus-1.la \
+ $(NETWORK_libs) \
+ $(NULL)
-dbus_uuidgen_LDADD= $(top_builddir)/dbus/libdbus-1.la $(DBUS_CLIENT_LIBS)
-dbus_uuidgen_LDFLAGS=@R_DYNAMIC_LDFLAG@
+dbus_uuidgen_LDADD = \
+ $(top_builddir)/dbus/libdbus-1.la \
+ $(NULL)
-dbus_launch_LDADD= $(DBUS_X_LIBS) $(DBUS_CLIENT_LIBS)
-dbus_launch_LDFLAGS=@R_DYNAMIC_LDFLAG@
+dbus_launch_LDADD = \
+ $(DBUS_X_LIBS) \
+ $(NULL)
EXTRA_DIST = run-with-tmp-session-bus.sh strtoll.c strtoull.c
CLEANFILES = \
diff --git a/tools/dbus-monitor.c b/tools/dbus-monitor.c
index 5edb5c0b..a4b54782 100644
--- a/tools/dbus-monitor.c
+++ b/tools/dbus-monitor.c
@@ -35,6 +35,8 @@
#include "dbus-print-message.h"
+#define EAVESDROPPING_RULE "eavesdrop=true"
+
#ifdef DBUS_WIN
/* gettimeofday is not defined on windows */
@@ -76,6 +78,13 @@ gettimeofday (struct timeval *__p,
}
#endif
+inline static void
+oom (const char *doing)
+{
+ fprintf (stderr, "OOM while %s\n", doing);
+ exit (1);
+}
+
static DBusHandlerResult
monitor_filter_func (DBusConnection *connection,
DBusMessage *message,
@@ -230,14 +239,6 @@ only_one_type (dbus_bool_t *seen_bus_type,
}
}
-static dbus_bool_t sigint_received = FALSE;
-
-static void
-sigint_handler (int signum)
-{
- sigint_received = TRUE;
-}
-
int
main (int argc, char *argv[])
{
@@ -299,11 +300,21 @@ main (int argc, char *argv[])
else if (arg[0] == '-')
usage (argv[0], 1);
else {
- numFilters++;
- filters = (char **)realloc(filters, numFilters * sizeof(char *));
- filters[j] = (char *)malloc((strlen(arg) + 1) * sizeof(char *));
- snprintf(filters[j], strlen(arg) + 1, "%s", arg);
- j++;
+ unsigned int filter_len;
+ numFilters++;
+ /* Prepend a rule (and a comma) to enable the monitor to eavesdrop.
+ * Prepending allows the user to add eavesdrop=false at command line
+ * in order to disable eavesdropping when needed */
+ filter_len = strlen (EAVESDROPPING_RULE) + 1 + strlen (arg) + 1;
+
+ filters = (char **) realloc (filters, numFilters * sizeof (char *));
+ if (filters == NULL)
+ oom ("adding a new filter slot");
+ filters[j] = (char *) malloc (filter_len * sizeof (char *));
+ if (filters[j] == NULL)
+ oom ("adding a new filter");
+ snprintf (filters[j], filter_len, "%s,%s", EAVESDROPPING_RULE, arg);
+ j++;
}
}
@@ -369,22 +380,22 @@ main (int argc, char *argv[])
else
{
dbus_bus_add_match (connection,
- "type='signal'",
+ EAVESDROPPING_RULE ",type='signal'",
&error);
if (dbus_error_is_set (&error))
goto lose;
dbus_bus_add_match (connection,
- "type='method_call'",
+ EAVESDROPPING_RULE ",type='method_call'",
&error);
if (dbus_error_is_set (&error))
goto lose;
dbus_bus_add_match (connection,
- "type='method_return'",
+ EAVESDROPPING_RULE ",type='method_return'",
&error);
if (dbus_error_is_set (&error))
goto lose;
dbus_bus_add_match (connection,
- "type='error'",
+ EAVESDROPPING_RULE ",type='error'",
&error);
if (dbus_error_is_set (&error))
goto lose;
diff --git a/tools/dbus-viewer.c b/tools/dbus-viewer.c
deleted file mode 100644
index 2fd28474..00000000
--- a/tools/dbus-viewer.c
+++ /dev/null
@@ -1,617 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-/* dbus-viewer.c Graphical D-Bus frontend utility
- *
- * Copyright (C) 2003 Red Hat, Inc.
- *
- * 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 <stdlib.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <gtk/gtk.h>
-#include "dbus-tree-view.h"
-#include "dbus-names-model.h"
-#include <glib/dbus-gparser.h>
-#include <glib/dbus-gutils.h>
-#include <dbus/dbus-glib.h>
-#include <glib/gi18n.h>
-
-static void
-show_error_dialog (GtkWindow *transient_parent,
- GtkWidget **weak_ptr,
- const char *message_format,
- ...)
-{
- char *message;
- va_list args;
-
- if (message_format)
- {
- va_start (args, message_format);
- message = g_strdup_vprintf (message_format, args);
- va_end (args);
- }
- else
- message = NULL;
-
- if (weak_ptr == NULL || *weak_ptr == NULL)
- {
- GtkWidget *dialog;
- dialog = gtk_message_dialog_new (transient_parent,
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_ERROR,
- GTK_BUTTONS_CLOSE,
- message);
-
- g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (gtk_widget_destroy), NULL);
-
- if (weak_ptr != NULL)
- {
- *weak_ptr = dialog;
- g_object_add_weak_pointer (G_OBJECT (dialog), (void**)weak_ptr);
- }
-
- gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
-
- gtk_widget_show_all (dialog);
- }
- else
- {
- g_return_if_fail (GTK_IS_MESSAGE_DIALOG (*weak_ptr));
-
- gtk_label_set_text (GTK_LABEL (GTK_MESSAGE_DIALOG (*weak_ptr)->label), message);
-
- gtk_window_present (GTK_WINDOW (*weak_ptr));
- }
-}
-
-typedef struct
-{
- DBusGConnection *connection;
-
- GtkWidget *window;
- GtkWidget *treeview;
- GtkWidget *name_menu;
-
- GtkTreeModel *names_model;
-
- GtkWidget *error_dialog;
-
-} TreeWindow;
-
-
-static void
-tree_window_set_node (TreeWindow *w,
- NodeInfo *node)
-{
- char **path;
- const char *name;
-
- name = node_info_get_name (node);
- if (name == NULL ||
- name[0] != '/')
- {
- g_printerr (_("Assuming root node is at path /, since no absolute path is specified"));
- name = "/";
- }
-
- path = _dbus_gutils_split_path (name);
-
- dbus_tree_view_update (GTK_TREE_VIEW (w->treeview),
- (const char**) path,
- node);
-
- g_strfreev (path);
-}
-
-typedef struct
-{
- DBusGConnection *connection;
- char *service_name;
- GError *error;
- NodeInfo *node;
- TreeWindow *window; /* Not touched from child thread */
-} LoadFromServiceData;
-
-static gboolean
-load_child_nodes (const char *service_name,
- NodeInfo *parent,
- GString *path,
- GError **error)
-{
- DBusGConnection *connection;
- GSList *tmp;
-
- connection = dbus_g_bus_get (DBUS_BUS_SESSION, error);
- if (connection == NULL)
- return FALSE;
-
- tmp = node_info_get_nodes (parent);
- while (tmp != NULL)
- {
- DBusGProxy *proxy;
- char *data;
- NodeInfo *child;
- NodeInfo *complete_child;
- int save_len;
-
- complete_child = NULL;
-
- child = tmp->data;
-
- save_len = path->len;
-
- if (save_len > 1)
- g_string_append (path, "/");
- g_string_append (path, base_info_get_name ((BaseInfo*)child));
-
- if (*service_name == ':')
- {
- proxy = dbus_g_proxy_new_for_name (connection,
- service_name,
- path->str,
- DBUS_INTERFACE_INTROSPECTABLE);
- g_assert (proxy != NULL);
- }
- else
- {
- proxy = dbus_g_proxy_new_for_name_owner (connection,
- service_name,
- path->str,
- DBUS_INTERFACE_INTROSPECTABLE,
- error);
- if (proxy == NULL)
- goto done;
- }
-
- if (!dbus_g_proxy_call (proxy, "Introspect", error,
- G_TYPE_INVALID,
- G_TYPE_STRING, &data,
- G_TYPE_INVALID))
- goto done;
-
- complete_child = description_load_from_string (data, -1, error);
- g_free (data);
- if (complete_child == NULL)
- {
- g_printerr ("%s\n", data);
- goto done;
- }
-
- done:
- g_object_unref (proxy);
-
- if (complete_child == NULL)
- return FALSE;
-
- /* change complete_child's name to relative */
- base_info_set_name ((BaseInfo*)complete_child,
- base_info_get_name ((BaseInfo*)child));
-
- /* Stitch in complete_child rather than child */
- node_info_replace_node (parent, child, complete_child);
- node_info_unref (complete_child); /* ref still held by parent */
-
- /* Now recurse */
- if (!load_child_nodes (service_name, complete_child, path, error))
- return FALSE;
-
- /* restore path */
- g_string_set_size (path, save_len);
-
- tmp = tmp->next;
- }
-
- return TRUE;
-}
-
-static gboolean
-load_from_service_complete_idle (void *data)
-{
- /* Called in main thread */
- GThread *thread = data;
- LoadFromServiceData *d;
- NodeInfo *node;
-
- d = g_thread_join (thread);
-
- node = d->node;
-
- if (d->error)
- {
- g_assert (d->node == NULL);
- show_error_dialog (GTK_WINDOW (d->window->window), &d->window->error_dialog,
- _("Unable to load \"%s\": %s\n"),
- d->service_name, d->error->message);
- g_error_free (d->error);
- }
- else
- {
- g_assert (d->error == NULL);
-
- tree_window_set_node (d->window, node);
- node_info_unref (node);
- }
-
- g_free (d->service_name);
- dbus_g_connection_unref (d->connection);
- g_free (d);
-
- return FALSE;
-}
-
-static void*
-load_from_service_thread_func (void *thread_data)
-{
- DBusGProxy *root_proxy;
- const char *data;
- NodeInfo *node;
- GString *path;
- LoadFromServiceData *lfsd;
-
- lfsd = thread_data;
-
- node = NULL;
- path = NULL;
-
-#if 1
- /* this will end up autolaunching the service when we introspect it */
- root_proxy = dbus_g_proxy_new_for_name (lfsd->connection,
- lfsd->service_name,
- "/",
- DBUS_INTERFACE_INTROSPECTABLE);
- g_assert (root_proxy != NULL);
-#else
- /* this will be an error if the service doesn't exist */
- root_proxy = dbus_g_proxy_new_for_name_owner (lfsd->connection,
- lfsd->service_name,
- "/",
- DBUS_INTERFACE_INTROSPECTABLE,
- &lfsd->error);
- if (root_proxy == NULL)
- {
- g_printerr ("Failed to get owner of '%s'\n", lfsd->service_name);
- return lfsd->data;
- }
-#endif
-
- if (!dbus_g_proxy_call (root_proxy, "Introspect", &lfsd->error,
- G_TYPE_INVALID,
- G_TYPE_STRING, &data,
- G_TYPE_INVALID))
- {
- g_printerr ("Failed to Introspect() %s\n",
- dbus_g_proxy_get_bus_name (root_proxy));
- goto out;
- }
-
- node = description_load_from_string (data, -1, &lfsd->error);
-
- /* g_print ("%s\n", data); */
-
- if (node == NULL)
- goto out;
-
- base_info_set_name ((BaseInfo*)node, "/");
-
- path = g_string_new ("/");
-
- if (!load_child_nodes (dbus_g_proxy_get_bus_name (root_proxy),
- node, path, &lfsd->error))
- {
- node_info_unref (node);
- node = NULL;
- goto out;
- }
-
- out:
- g_object_unref (root_proxy);
-
- if (path)
- g_string_free (path, TRUE);
-
- lfsd->node = node;
- g_assert (lfsd->node || lfsd->error);
- g_assert (lfsd->node == NULL || lfsd->error == NULL);
-
- /* Add idle to main thread that will join us back */
- g_idle_add (load_from_service_complete_idle, g_thread_self ());
-
- return lfsd;
-}
-
-static void
-start_load_from_service (TreeWindow *w,
- DBusGConnection *connection,
- const char *service_name)
-{
- LoadFromServiceData *d;
-
- d = g_new0 (LoadFromServiceData, 1);
-
- d->connection = dbus_g_connection_ref (connection);
- d->service_name = g_strdup (service_name);
- d->error = NULL;
- d->node = NULL;
- d->window = w;
-
- g_thread_create (load_from_service_thread_func, d, TRUE, NULL);
-}
-
-static void
-tree_window_set_service (TreeWindow *w,
- const char *service_name)
-{
- start_load_from_service (w, w->connection, service_name);
-}
-
-static void
-name_combo_changed_callback (GtkComboBox *combo,
- TreeWindow *w)
-{
- GtkTreeIter iter;
-
- if (gtk_combo_box_get_active_iter (combo, &iter))
- {
- GtkTreeModel *model;
- char *text;
-
- model = gtk_combo_box_get_model (combo);
- gtk_tree_model_get (model, &iter, 0, &text, -1);
-
- if (text)
- {
- tree_window_set_service (w, text);
- g_free (text);
- }
- }
-}
-
-static void
-window_closed_callback (GtkWidget *window,
- TreeWindow *w)
-{
- g_assert (window == w->window);
- w->window = NULL;
- gtk_main_quit ();
-}
-
-static TreeWindow*
-tree_window_new (DBusGConnection *connection,
- GtkTreeModel *names_model)
-{
- TreeWindow *w;
- GtkWidget *sw;
- GtkWidget *vbox;
- GtkWidget *hbox;
- GtkWidget *combo;
-
- /* Should use glade, blah */
-
- w = g_new0 (TreeWindow, 1);
- w->window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- gtk_window_set_title (GTK_WINDOW (w->window), "D-Bus Viewer");
- gtk_window_set_default_size (GTK_WINDOW (w->window), 400, 500);
-
- g_signal_connect (w->window, "destroy", G_CALLBACK (window_closed_callback),
- w);
- gtk_container_set_border_width (GTK_CONTAINER (w->window), 6);
-
- vbox = gtk_vbox_new (FALSE, 6);
- gtk_container_add (GTK_CONTAINER (w->window), vbox);
-
- /* Create names option menu */
- if (connection)
- {
- GtkCellRenderer *cell;
-
- w->connection = connection;
-
- w->names_model = names_model;
-
- combo = gtk_combo_box_new_with_model (w->names_model);
-
- cell = gtk_cell_renderer_text_new ();
- gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, TRUE);
- gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), cell,
- "text", 0,
- NULL);
-
- gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
-
- g_signal_connect (combo, "changed",
- G_CALLBACK (name_combo_changed_callback),
- w);
- }
-
- /* Create tree view */
- hbox = gtk_hbox_new (FALSE, 6);
- gtk_container_add (GTK_CONTAINER (vbox), hbox);
-
- sw = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
- GTK_POLICY_AUTOMATIC,
- GTK_POLICY_AUTOMATIC);
-
- gtk_box_pack_start (GTK_BOX (hbox), sw, TRUE, TRUE, 0);
-
- w->treeview = dbus_tree_view_new ();
-
- gtk_container_add (GTK_CONTAINER (sw), w->treeview);
-
- /* Show everything */
- gtk_widget_show_all (w->window);
-
- return w;
-}
-
-static void
-usage (int ecode)
-{
- fprintf (stderr, "dbus-viewer [--version] [--help]\n");
- exit (ecode);
-}
-
-static void
-version (void)
-{
- printf ("D-Bus Message Bus Viewer %s\n"
- "Copyright (C) 2003 Red Hat, Inc.\n"
- "This is free software; see the source for copying conditions.\n"
- "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
- VERSION);
- exit (0);
-}
-
-int
-main (int argc, char **argv)
-{
- int i;
- GSList *files;
- gboolean end_of_args;
- GSList *tmp;
- gboolean services;
- DBusGConnection *connection;
- GError *error;
- GtkTreeModel *names_model;
-
- g_thread_init (NULL);
- dbus_g_thread_init ();
-
- bindtextdomain (GETTEXT_PACKAGE, DBUS_LOCALEDIR);
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- textdomain (GETTEXT_PACKAGE);
-
- gtk_init (&argc, &argv);
-
- services = FALSE;
- end_of_args = FALSE;
- files = NULL;
- i = 1;
- while (i < argc)
- {
- const char *arg = argv[i];
-
- if (!end_of_args)
- {
- if (strcmp (arg, "--help") == 0 ||
- strcmp (arg, "-h") == 0 ||
- strcmp (arg, "-?") == 0)
- usage (0);
- else if (strcmp (arg, "--version") == 0)
- version ();
- else if (strcmp (arg, "--services") == 0)
- services = TRUE;
- else if (arg[0] == '-' &&
- arg[1] == '-' &&
- arg[2] == '\0')
- end_of_args = TRUE;
- else if (arg[0] == '-')
- {
- usage (1);
- }
- else
- {
- files = g_slist_prepend (files, (char*) arg);
- }
- }
- else
- files = g_slist_prepend (files, (char*) arg);
-
- ++i;
- }
-
- if (services || files == NULL)
- {
- error = NULL;
- connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
- if (connection == NULL)
- {
- g_printerr ("Could not open bus connection: %s\n",
- error->message);
- g_error_free (error);
- exit (1);
- }
-
- g_assert (connection == dbus_g_bus_get (DBUS_BUS_SESSION, NULL));
-
- names_model = names_model_new (connection);
- }
- else
- {
- connection = NULL;
- names_model = NULL;
- }
-
- if (files == NULL)
- {
- TreeWindow *w;
-
- w = tree_window_new (connection, names_model);
- }
-
- files = g_slist_reverse (files);
-
- tmp = files;
- while (tmp != NULL)
- {
- const char *filename;
- TreeWindow *w;
-
- filename = tmp->data;
-
- if (services)
- {
- w = tree_window_new (connection, names_model);
- tree_window_set_service (w, filename);
- }
- else
- {
- NodeInfo *node;
-
- error = NULL;
- node = description_load_from_file (filename,
- &error);
-
- if (node == NULL)
- {
- g_assert (error != NULL);
- show_error_dialog (NULL, NULL,
- _("Unable to load \"%s\": %s\n"),
- filename, error->message);
- g_error_free (error);
- }
- else
- {
- w = tree_window_new (connection, names_model);
- tree_window_set_node (w, node);
- node_info_unref (node);
- }
- }
-
- tmp = tmp->next;
- }
-
- gtk_main ();
-
- return 0;
-}
-