diff options
| author | Simon McVittie <smcv@debian.org> | 2011-01-31 17:37:59 +0000 |
|---|---|---|
| committer | Simon McVittie <smcv@debian.org> | 2011-01-31 17:37:59 +0000 |
| commit | 24fbe571516161d48b499d587f9adb3e683dbf88 (patch) | |
| tree | 7d70909156dcf587d91f693b8e1216eb4e0465e1 /doc | |
| parent | 9b72896b3730a9fceb961be28bb95762a7b4e9d6 (diff) | |
| download | dbus-upstream/1.2.24.tar.gz | |
Imported Upstream version 1.2.24upstream/1.2.24
Diffstat (limited to 'doc')
| -rw-r--r-- | doc/Makefile.am | 41 | ||||
| -rw-r--r-- | doc/Makefile.in | 463 | ||||
| -rw-r--r-- | doc/TODO | 155 | ||||
| -rw-r--r-- | doc/busconfig.dtd | 65 | ||||
| -rw-r--r-- | doc/dbus-faq.html | 437 | ||||
| -rw-r--r-- | doc/dbus-faq.xml | 674 | ||||
| -rw-r--r-- | doc/dbus-specification.html | 2081 | ||||
| -rw-r--r-- | doc/dbus-specification.xml | 4086 | ||||
| -rw-r--r-- | doc/dbus-test-plan.html | 141 | ||||
| -rw-r--r-- | doc/dbus-test-plan.xml | 232 | ||||
| -rw-r--r-- | doc/dbus-tutorial.html | 991 | ||||
| -rw-r--r-- | doc/dbus-tutorial.xml | 1667 | ||||
| -rw-r--r-- | doc/dcop-howto.txt | 559 | ||||
| -rw-r--r-- | doc/diagram.png | bin | 0 -> 78762 bytes | |||
| -rw-r--r-- | doc/diagram.svg | 590 | ||||
| -rw-r--r-- | doc/file-boilerplate.c | 27 | ||||
| -rw-r--r-- | doc/introspect.dtd | 37 | ||||
| -rw-r--r-- | doc/introspect.xsl | 106 | ||||
| -rw-r--r-- | doc/system-activation.txt | 80 |
19 files changed, 12432 insertions, 0 deletions
diff --git a/doc/Makefile.am b/doc/Makefile.am new file mode 100644 index 00000000..f76335f6 --- /dev/null +++ b/doc/Makefile.am @@ -0,0 +1,41 @@ +EXTRA_DIST= \ + busconfig.dtd \ + diagram.png \ + diagram.svg \ + introspect.dtd \ + dbus-faq.xml \ + dbus-specification.xml \ + dbus-test-plan.xml \ + dbus-tutorial.xml \ + dcop-howto.txt \ + file-boilerplate.c \ + introspect.xsl \ + system-activation.txt + +HTML_FILES= \ + dbus-faq.html \ + dbus-specification.html \ + dbus-test-plan.html \ + dbus-tutorial.html + +if DBUS_XML_DOCS_ENABLED +all-local: $(HTML_FILES) + +EXTRA_DIST += $(HTML_FILES) + +dbus-specification.html: dbus-specification.xml + $(XMLTO) html-nochunks $< + +dbus-test-plan.html: dbus-test-plan.xml + $(XMLTO) html-nochunks $< + +dbus-tutorial.html: dbus-tutorial.xml + $(XMLTO) html-nochunks $< + +dbus-faq.html: dbus-faq.xml + $(XMLTO) html-nochunks $< + +endif + +maintainer-clean-local: + rm -f $(HTML_FILES) diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 00000000..05386f6f --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,463 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@DBUS_XML_DOCS_ENABLED_TRUE@am__append_1 = $(HTML_FILES) +subdir = doc +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in TODO +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ + $(top_srcdir)/configure.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +SOURCES = +DIST_SOURCES = +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_BINDIR = @DBUS_BINDIR@ +DBUS_BUS_CFLAGS = @DBUS_BUS_CFLAGS@ +DBUS_BUS_LIBS = @DBUS_BUS_LIBS@ +DBUS_CLIENT_CFLAGS = @DBUS_CLIENT_CFLAGS@ +DBUS_CLIENT_LIBS = @DBUS_CLIENT_LIBS@ +DBUS_CONSOLE_AUTH_DIR = @DBUS_CONSOLE_AUTH_DIR@ +DBUS_CONSOLE_OWNER_FILE = @DBUS_CONSOLE_OWNER_FILE@ +DBUS_DAEMONDIR = @DBUS_DAEMONDIR@ +DBUS_DATADIR = @DBUS_DATADIR@ +DBUS_HAVE_INT64 = @DBUS_HAVE_INT64@ +DBUS_INT16_TYPE = @DBUS_INT16_TYPE@ +DBUS_INT32_TYPE = @DBUS_INT32_TYPE@ +DBUS_INT64_CONSTANT = @DBUS_INT64_CONSTANT@ +DBUS_INT64_TYPE = @DBUS_INT64_TYPE@ +DBUS_LAUNCHER_CFLAGS = @DBUS_LAUNCHER_CFLAGS@ +DBUS_LAUNCHER_LIBS = @DBUS_LAUNCHER_LIBS@ +DBUS_LIBEXECDIR = @DBUS_LIBEXECDIR@ +DBUS_MAJOR_VERSION = @DBUS_MAJOR_VERSION@ +DBUS_MICRO_VERSION = @DBUS_MICRO_VERSION@ +DBUS_MINOR_VERSION = @DBUS_MINOR_VERSION@ +DBUS_PATH_OR_ABSTRACT = @DBUS_PATH_OR_ABSTRACT@ +DBUS_SESSION_SOCKET_DIR = @DBUS_SESSION_SOCKET_DIR@ +DBUS_SYSTEM_BUS_DEFAULT_ADDRESS = @DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@ +DBUS_SYSTEM_PID_FILE = @DBUS_SYSTEM_PID_FILE@ +DBUS_SYSTEM_SOCKET = @DBUS_SYSTEM_SOCKET@ +DBUS_TEST_CFLAGS = @DBUS_TEST_CFLAGS@ +DBUS_TEST_LIBS = @DBUS_TEST_LIBS@ +DBUS_UINT64_CONSTANT = @DBUS_UINT64_CONSTANT@ +DBUS_USER = @DBUS_USER@ +DBUS_VERSION = @DBUS_VERSION@ +DBUS_X_CFLAGS = @DBUS_X_CFLAGS@ +DBUS_X_LIBS = @DBUS_X_LIBS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +EXPANDED_BINDIR = @EXPANDED_BINDIR@ +EXPANDED_DATADIR = @EXPANDED_DATADIR@ +EXPANDED_LIBDIR = @EXPANDED_LIBDIR@ +EXPANDED_LIBEXECDIR = @EXPANDED_LIBEXECDIR@ +EXPANDED_LOCALSTATEDIR = @EXPANDED_LOCALSTATEDIR@ +EXPANDED_SYSCONFDIR = @EXPANDED_SYSCONFDIR@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBXML_CFLAGS = @LIBXML_CFLAGS@ +LIBXML_LIBS = @LIBXML_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PIC_CFLAGS = @PIC_CFLAGS@ +PIC_LDFLAGS = @PIC_LDFLAGS@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +R_DYNAMIC_LDFLAG = @R_DYNAMIC_LDFLAG@ +SECTION_FLAGS = @SECTION_FLAGS@ +SECTION_LDFLAGS = @SECTION_LDFLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TEST_BUS_BINARY = @TEST_BUS_BINARY@ +TEST_EXIT_BINARY = @TEST_EXIT_BINARY@ +TEST_INVALID_SERVICE_DIR = @TEST_INVALID_SERVICE_DIR@ +TEST_INVALID_SERVICE_SYSTEM_DIR = @TEST_INVALID_SERVICE_SYSTEM_DIR@ +TEST_LAUNCH_HELPER_BINARY = @TEST_LAUNCH_HELPER_BINARY@ +TEST_PRIVSERVER_BINARY = @TEST_PRIVSERVER_BINARY@ +TEST_SEGFAULT_BINARY = @TEST_SEGFAULT_BINARY@ +TEST_SERVICE_BINARY = @TEST_SERVICE_BINARY@ +TEST_SHELL_SERVICE_BINARY = @TEST_SHELL_SERVICE_BINARY@ +TEST_SLEEP_FOREVER_BINARY = @TEST_SLEEP_FOREVER_BINARY@ +TEST_SOCKET_DIR = @TEST_SOCKET_DIR@ +TEST_VALID_SERVICE_DIR = @TEST_VALID_SERVICE_DIR@ +TEST_VALID_SERVICE_SYSTEM_DIR = @TEST_VALID_SERVICE_SYSTEM_DIR@ +VERSION = @VERSION@ +XMKMF = @XMKMF@ +XMLTO = @XMLTO@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +EXTRA_DIST = busconfig.dtd diagram.png diagram.svg introspect.dtd \ + dbus-faq.xml dbus-specification.xml dbus-test-plan.xml \ + dbus-tutorial.xml dcop-howto.txt file-boilerplate.c \ + introspect.xsl system-activation.txt $(am__append_1) +HTML_FILES = \ + dbus-faq.html \ + dbus-specification.html \ + dbus-test-plan.html \ + dbus-tutorial.html + +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu doc/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags: TAGS +TAGS: + +ctags: CTAGS +CTAGS: + + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +@DBUS_XML_DOCS_ENABLED_FALSE@all-local: +all-am: Makefile all-local +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic \ + maintainer-clean-local + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool distclean distclean-generic distclean-libtool \ + distdir dvi dvi-am html html-am info info-am install \ + install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-local mostlyclean mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am uninstall uninstall-am + + +@DBUS_XML_DOCS_ENABLED_TRUE@all-local: $(HTML_FILES) + +@DBUS_XML_DOCS_ENABLED_TRUE@dbus-specification.html: dbus-specification.xml +@DBUS_XML_DOCS_ENABLED_TRUE@ $(XMLTO) html-nochunks $< + +@DBUS_XML_DOCS_ENABLED_TRUE@dbus-test-plan.html: dbus-test-plan.xml +@DBUS_XML_DOCS_ENABLED_TRUE@ $(XMLTO) html-nochunks $< + +@DBUS_XML_DOCS_ENABLED_TRUE@dbus-tutorial.html: dbus-tutorial.xml +@DBUS_XML_DOCS_ENABLED_TRUE@ $(XMLTO) html-nochunks $< + +@DBUS_XML_DOCS_ENABLED_TRUE@dbus-faq.html: dbus-faq.xml +@DBUS_XML_DOCS_ENABLED_TRUE@ $(XMLTO) html-nochunks $< + +maintainer-clean-local: + rm -f $(HTML_FILES) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/doc/TODO b/doc/TODO new file mode 100644 index 00000000..eb4e797f --- /dev/null +++ b/doc/TODO @@ -0,0 +1,155 @@ +Important for 1.2 +=== + + - System bus activation + + - Windows port + +Important for 1.0 GLib Bindings +=== + + - Test point-to-point mode + + - Add support for getting sender + + - format_version in the object info doesn't look like it's handled correctly. The creator + of the object info should specify some fixed number per struct version; the library + should handle only specific numbers it knows about. There's no assumption that all + numbers >= the given one are compatible. The idea is that new versions of the lib + can offer totally different object info structs, but old versions + keep working. + +Important for 1.0 Python bindings +=== + + - Hammer down API + + - Fix removing of signals from the match tree + + - Fix refcounting and userdata lifecycles + + - Write a generic mainloop + +Might as Well for 1.0 +=== + + - protocol version in each message is pretty silly + +Can Be Post 1.0 +=== + + - revamp dbus-launch a bit, + see http://lists.freedesktop.org/archives/dbus/2006-October/005906.html + for some thoughts. + + - clean up the creds issue on *BSD's in dbus/dbus-sysdeps-unix.c. + They should work as is but we need to rearange it to make it + clearer which method is being used. configure.in should + be fixed up to make that decition. + + - _dbus_connection_unref_unlocked() is essentially always broken because + the connection finalizer calls non-unlocked functions. One fix is to make + the finalizer run with the lock held, but since it calls out to the app that may + be pretty broken. More likely all the uses of unref_unlocked are just wrong. + + - if the GUID is obtained only during authentication, not in the address, + we could still share the connection + + - Allow a dbus_g_proxy_to_string()/g_object_to_string() that + would convert the proxy to an "IOR" and dbus_g_proxy_from_string() + that would decode; using these, dbus-glib users could avoid + DBusConnection entirely. Of course the same applies to other kinds + of binding. This would use dbus_connection_open()'s connection-sharing + feature to avoid massive proliferation of connections. + + - DBusWatchList/TimeoutList duplicate a lot of code, as do + protected_change_watch/protected_change_timeout in dbus-connection.c + and dbus-server.c. This could all be mopped up, cut-and-paste + fixed, code size reduced. + + - change .service files to allow Names=list in addition to Name=string + + - The message bus internal code still says "service" for + "name", "base service" for "unique name", "activate" for + "start"; would be nice to clean up. + + - Property list feature on message bus (list of properties associated + with a connection). May also include message matching rules + that involve the properties of the source or destination + connection. + + - Disconnecting the remote end on invalid UTF-8 is probably not a good + idea. The definition of "valid" is slightly fuzzy. I think it might + be better to just silently "fix" the UTF-8, or perhaps return an error. + + - build and install the Doxygen manual in Makefile when --enable-docs + + - if you send the same message to multiple connections, the serial number + will only be right for one of them. Probably need to just write() the serial + number, rather than putting it in the DBusMessage, or something. + + - perhaps the bus driver should have properties that reflect attributes + of the session, such as hostname, architecture, operating system, + etc. Could be useful for code that wants to special-case behavior + for a particular host or class of hosts, for example. + + - currently the security policy stuff for messages to/from + the bus driver is kind of strange; basically it's hardcoded that + you can always talk to the driver, but the default config file + has rules for it anyway, or something. it's conceptually + screwy at the moment. + + - when making a method call, if the call serial were globally unique, + we could forward the call serial along with any method calls made + as a result of the first method call, and allow reentrancy that was + strictly part of the call stack of said method call. But I don't + really see how to do this without making the user pass around the + call serial to all method calls all the time, or disallowing + async calls. + + If done post 1.0 will probably be an optional/ugly-API type + of thing. + + - I don't want to introduce DBusObject, but refcounting and object + data could still be factored out into an internal "base class" + perhaps. + + - Keep convenience wrappers in sync with bus methods + + - document the auth protocol as a set of states and transitions, and + then reimplement it in those terms + + - recursive dispatch, see dbus_connection_dispatch() + + - do we need per-display activation; if so I'd like to do this by setting a + "display ID" property on screen 0, with a GUID, and keying activation by + said GUID. Otherwise you get all kinds of unrobust + string/hostname-based mess. per-screen is then done by appending screen number + to the display. If displays have a deterministic ID like this, you can + do per-display by simply including GUID in the service name. + + - optimization and profiling! + + - Match rules aren't in the spec (probably a lot of methods on the bus + are not) + + - the "break loader" and valid/invalid message tests are all disabled; + they need to be fixed and re-enabled with the new message args stuff. + I think I want to drop the .message files thing and just have code + that generates messages, more like the tests for + dbus-marshal-recursive.c (this is mostly done now, just needs some + cleanup) + + - just before 1.0, try a HAVE_INT64=0 build and be sure it runs + + - Windows port needs recursive mutexes + +Should Be Post 1.0 +=== + + - look into supporting the concept of a "connection" generically + (what does this TODO item mean?) + + - test/name-test should be named test/with-bus or something like that + + diff --git a/doc/busconfig.dtd b/doc/busconfig.dtd new file mode 100644 index 00000000..0cc519b4 --- /dev/null +++ b/doc/busconfig.dtd @@ -0,0 +1,65 @@ +<!ELEMENT busconfig (user | + type | + fork | + keep_umask | + listen | + pidfile | + includedir | + servicedir | + servicehelper | + auth | + include | + policy | + limit | + selinux)*> + +<!ELEMENT user (#PCDATA)> +<!ELEMENT listen (#PCDATA)> +<!ELEMENT includedir (#PCDATA)> +<!ELEMENT servicedir (#PCDATA)> +<!ELEMENT servicehelper (#PCDATA)> +<!ELEMENT auth (#PCDATA)> +<!ELEMENT type (#PCDATA)> +<!ELEMENT pidfile (#PCDATA)> +<!ELEMENT fork EMPTY> +<!ELEMENT keep_umask EMPTY> + +<!ELEMENT include (#PCDATA)> +<!ATTLIST include + ignore_missing (yes|no) "no" + if_selinux_enabled (yes|no) "no" + selinux_root_relative (yes|no) "no"> + +<!ELEMENT policy (allow|deny)*> +<!ATTLIST policy + context (default|mandatory) #IMPLIED + user CDATA #IMPLIED + group CDATA #IMPLIED + at_console (yes|no) #IMPLIED> + +<!ELEMENT allow EMPTY> +<!ATTLIST allow + user CDATA #IMPLIED + send CDATA #IMPLIED + receive CDATA #IMPLIED + own CDATA #IMPLIED + send_to CDATA #IMPLIED + receive_from CDATA #IMPLIED> + +<!ELEMENT deny EMPTY> +<!ATTLIST deny + user CDATA #IMPLIED + send CDATA #IMPLIED + receive CDATA #IMPLIED + own CDATA #IMPLIED + send_to CDATA #IMPLIED + receive_from CDATA #IMPLIED> + +<!ELEMENT limit (#PCDATA)> +<!ATTLIST limit name CDATA #REQUIRED> + +<!ELEMENT selinux (associate)*> +<!ELEMENT associate EMPTY> +<!ATTLIST associate + own CDATA #REQUIRED + context CDATA #REQUIRED> diff --git a/doc/dbus-faq.html b/doc/dbus-faq.html new file mode 100644 index 00000000..dff70fad --- /dev/null +++ b/doc/dbus-faq.html @@ -0,0 +1,437 @@ +<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>D-Bus FAQ</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="article" title="D-Bus FAQ"><div class="titlepage"><div><div><h2 class="title"><a name="index"></a>D-Bus FAQ</h2></div><div><div class="authorgroup"><div class="author"><h3 class="author"><span class="firstname">Havoc</span> <span class="surname">Pennington</span></h3><div class="affiliation"><span class="orgname">Red Hat, Inc.<br></span><div class="address"><p><br> + <code class="email"><<a class="email" href="mailto:hp@pobox.com">hp@pobox.com</a>></code><br> + </p></div></div></div><div class="author"><h3 class="author"><span class="firstname">David</span> <span class="othername">A</span> <span class="surname">Wheeler</span></h3></div></div></div><div><p class="releaseinfo">Version 0.3</p></div></div><hr></div><div class="qandaset" title="Frequently Asked Questions"><a name="faq"></a><dl><dt>1. <a href="#id319467"> + What is D-Bus? + </a></dt><dt>2. <a href="#id322828"> + Is D-Bus stable/finished? + </a></dt><dt>3. <a href="#id322854"> + How is the reference implementation licensed? Can I use it in + proprietary applications? + </a></dt><dt>4. <a href="#id319923"> + What is the difference between a bus name, and object path, + and an interface? + </a></dt><dt>5. <a href="#service"> + What is a "service"? + </a></dt><dt>6. <a href="#components"> + Is D-Bus a "component system"? + </a></dt><dt>7. <a href="#speed"> + How fast is the D-Bus reference implementation? + </a></dt><dt>8. <a href="#size"> + How large is the D-Bus reference implementation? + </a></dt><dt>9. <a href="#other-ipc"> + How does D-Bus differ from other interprocess communication + or networking protocols? + </a></dt><dt>10. <a href="#corba"> + How does D-Bus differ from CORBA? + </a></dt><dt>11. <a href="#xmlrpcsoap"> + How does D-Bus differ from XML-RPC and SOAP? + </a></dt><dt>12. <a href="#dce"> + How does D-Bus differ from DCE? + </a></dt><dt>13. <a href="#dcom"> + How does D-Bus differ from DCOM and COM? + </a></dt><dt>14. <a href="#internet-communications-engine"> + How does D-Bus differ from ZeroC's Internet Communications Engine (Ice) + </a></dt><dt>15. <a href="#inter-client-exchange"> + How does D-Bus differ from Inter-Client Exchange (ICE)? + </a></dt><dt>16. <a href="#dcop"> + How does D-Bus differ from DCOP? + </a></dt><dt>17. <a href="#yet-more-ipc"> + How does D-Bus differ from [yet more IPC mechanisms]? + </a></dt><dt>18. <a href="#which-ipc"> + Which IPC mechanism should I use? + </a></dt><dt>19. <a href="#id359012"> + How can I submit a bug or patch? + </a></dt></dl><table border="0" width="100%" summary="Q and A Set"><col align="left" width="1%"><col><tbody><tr class="question" title="1."><td align="left" valign="top"><a name="id319467"></a><a name="id322798"></a><p><b>1.</b></p></td><td align="left" valign="top"><p> + What is D-Bus? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + This is probably best answered by reading the D-Bus <a class="ulink" href="dbus-tutorial.html" target="_top">tutorial</a> or + the introduction to the <a class="ulink" href="dbus-specification.html" target="_top">specification</a>. In + short, it is a system consisting of 1) a wire protocol for exposing a + typical object-oriented language/framework to other applications; and + 2) a bus daemon that allows applications to find and monitor one another. + Phrased differently, D-Bus is 1) an interprocess communication (IPC) system and 2) some higher-level + structure (lifecycle tracking, service activation, security policy) provided by two bus daemons, + one systemwide and one per-user-session. + </p></td></tr><tr class="question" title="2."><td align="left" valign="top"><a name="id322828"></a><a name="id322830"></a><p><b>2.</b></p></td><td align="left" valign="top"><p> + Is D-Bus stable/finished? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + The low-level library "libdbus" and the protocol specification are considered + ABI stable. The <a class="ulink" href="README" target="_top">README</a> + file has a discussion of the API/ABI stability guarantees. + Higher-level bindings (such as those for Qt, GLib, Python, Java, C#) each + have their own release schedules and degree of maturity, not linked to + the low-level library and bus daemon release. Check the project page for + the binding you're considering to understand that project's policies. + </p></td></tr><tr class="question" title="3."><td align="left" valign="top"><a name="id322854"></a><a name="id322856"></a><p><b>3.</b></p></td><td align="left" valign="top"><p> + How is the reference implementation licensed? Can I use it in + proprietary applications? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + The short answer is yes, you can use it in proprietary applications. + You should read the <a class="ulink" href="COPYING" target="_top">COPYING</a> file, which + offers you the choice of two licenses. These are the GPL and the + AFL. The GPL requires that your application be licensed under the GPL + as well. The AFL is an "X-style" or "BSD-style" license compatible + with proprietary licensing, but it does have some requirements; in + particular it prohibits you from filing a lawsuit alleging that the + D-Bus software infringes your patents <span class="emphasis"><em>while you continue to + use D-Bus</em></span>. If you're going to sue, you have to stop using + the software. Read the licenses to determine their meaning, this FAQ + entry is not intended to change the meaning or terms of the licenses. + </p></td></tr><tr class="question" title="4."><td align="left" valign="top"><a name="id319923"></a><a name="id319925"></a><p><b>4.</b></p></td><td align="left" valign="top"><p> + What is the difference between a bus name, and object path, + and an interface? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + If you imagine a C++ program that implements a network service, then + the bus name is the hostname of the computer running this C++ program, + the object path is a C++ object instance pointer, and an interface is + a C++ class (a pure virtual or abstract class, to be exact). + </p><p> + In Java terms, the object path is an object reference, + and an interface is a Java interface. + </p><p> + People get confused because if they write an application + with a single object instance and a single interface, + then the bus name, object path, and interface look + redundant. For example, you might have a text editor + that uses the bus name <code class="literal">org.freedesktop.TextEditor</code>, + has a global singleton object called + <code class="literal">/org/freedesktop/TextEditor</code>, and + that singleton object could implement the interface + <code class="literal">org.freedesktop.TextEditor</code>. + </p><p> + However, a text editor application could as easily own multiple bus + names (for example, <code class="literal">org.kde.KWrite</code> in addition to + generic <code class="literal">TextEditor</code>), have multiple objects (maybe + <code class="literal">/org/kde/documents/4352</code> where the number changes + according to the document), and each object could implement multiple + interfaces, such as <code class="literal">org.freedesktop.DBus.Introspectable</code>, + <code class="literal">org.freedesktop.BasicTextField</code>, + <code class="literal">org.kde.RichTextDocument</code>. + </p></td></tr><tr class="question" title="5."><td align="left" valign="top"><a name="service"></a><a name="id320018"></a><p><b>5.</b></p></td><td align="left" valign="top"><p> + What is a "service"? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + A service is a program that can be launched by the bus daemon + to provide some functionality to other programs. Services + are normally launched according to the bus name they will + have. + </p><p> + People often misuse the word "service" for any + bus name, but this tends to be ambiguous and confusing so is discouraged. + In the D-Bus docs we try to use "service" only when talking about + programs the bus knows how to launch, i.e. a service always has a + .service file. + </p></td></tr><tr class="question" title="6."><td align="left" valign="top"><a name="components"></a><a name="id320045"></a><p><b>6.</b></p></td><td align="left" valign="top"><p> + Is D-Bus a "component system"? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + It helps to keep these concepts separate in your mind: + </p><div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem"><p> + Object/component system + </p></li><li class="listitem"><p> + GUI control/widget embedding interfaces + </p></li><li class="listitem"><p> + Interprocess communication system or wire protocol + </p></li></ol></div><p> + </p><p> + D-Bus is not a component system. "Component system" was originally + defined by COM, and was essentially a workaround for the limitations + of the C++ object system (adding introspection, runtime location of + objects, ABI guarantees, and so forth). With the C# language and CLR, + Microsoft added these features to the primary object system, leaving + COM obsolete. Similarly, Java has much less need for something like + COM than C++ did. Even QObject (from Qt) and GObject (from GLib) offer + some of the same features found in COM. + </p><p> + Component systems are not about GUI control embedding. Embedding + a spreadsheet in a word processor document is a matter of defining + some specific <span class="emphasis"><em>interfaces</em></span> that objects + can implement. These interfaces provide methods related to + GUI controls. So an object implementing those interfaces + can be embedded. + </p><p> + The word "component" just means "object with some fancy features" and + in modern languages all objects are effectively "components." + </p><p> + So components are fancy objects, and some objects are GUI controls. + </p><p> + A third, unrelated feature is interprocess communication or IPC. + D-Bus is an IPC system. Given an object (or "component" if you must), + you can expose the functionality of that object over an IPC system. + Examples of IPC systems are DCOM, CORBA, SOAP, XML-RPC, and D-Bus. + You can use any of these IPC systems with any object/component system, + though some of them are "tuned" for specific object systems. + You can think of an IPC system primarily as a wire protocol. + </p><p> + If you combine an IPC system with a set of GUI control interfaces, + then you can have an out-of-process or dynamically-loaded GUI control. + </p><p> + Another related concept is the <em class="firstterm">plugin</em> or + <em class="firstterm">extension</em>. Generic plugin systems such as the + <a class="ulink" href="http://eclipse.org" target="_top">Eclipse</a> system are not so different + from component/object systems, though perhaps a "plugin" tends to be a + bundle of objects with a user-visible name and can be + downloaded/packaged as a unit. + </p></td></tr><tr class="question" title="7."><td align="left" valign="top"><a name="speed"></a><a name="id319564"></a><p><b>7.</b></p></td><td align="left" valign="top"><p> + How fast is the D-Bus reference implementation? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + Of course it depends a bit on what you're doing. + <a class="ulink" href="http://lists.freedesktop.org/pipermail/dbus/2004-November/001779.html" target="_top"> + This mail</a> contains some benchmarking. At the time of that + benchmark, D-Bus one-to-one communication was about 2.5x slower than + simply pushing the data raw over a socket. After the recent rewrite of + the marshaling code, D-Bus is slower than that because a lot of + optimization work was lost. But it can probably be sped up again. + </p><p> + D-Bus communication with the intermediate bus daemon should be + (and as last profiled, was) about twice as slow as one-to-one + mode, because a round trip involves four socket reads/writes rather + than two socket reads/writes. + </p><p> + The overhead comes from a couple of places; part of it is simply + "abstraction penalty" (there are layers of code to support + multiple main loops, multiple transport types, security, etc.). + Probably the largest part comes from data validation + (because the reference implementation does not trust incoming data). + It would be simple to add a "no validation" mode, but probably + not a good idea all things considered. + </p><p> + Raw bandwidth isn't the only concern; D-Bus is designed to + enable asynchronous communication and avoid round trips. + This is frequently a more important performance issue + than throughput. + </p></td></tr><tr class="question" title="8."><td align="left" valign="top"><a name="size"></a><a name="id319610"></a><p><b>8.</b></p></td><td align="left" valign="top"><p> + How large is the D-Bus reference implementation? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + A production build (with assertions, unit tests, and verbose logging + disabled) is on the order of a 150K shared library. + </p><p> + A much, much smaller implementation would be possible by omitting out + of memory handling, hardcoding a main loop (or always using blocking + I/O), skipping validation, and otherwise simplifying things. + </p></td></tr><tr class="question" title="9."><td align="left" valign="top"><a name="other-ipc"></a><a name="id358326"></a><p><b>9.</b></p></td><td align="left" valign="top"><p> + How does D-Bus differ from other interprocess communication + or networking protocols? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + Keep in mind, it is not only an IPC system; it also includes + lifecycle tracking, service activation, security policy, and other + higher-level structure and assumptions. + </p><p> + The best place to start is to read the D-Bus <a class="ulink" href="dbus-tutorial.html" target="_top">tutorial</a>, so + you have a concrete idea what D-Bus actually is. If you + understand other protocols on a wire format level, you + may also want to read the D-Bus <a class="ulink" href="dbus-specification.html" target="_top">specification</a> to see what + D-Bus looks like on a low level. + </p><p> + As the <a class="ulink" href="dbus-tutorial.html" target="_top">tutorial</a> and <a class="ulink" href="dbus-specification.html" target="_top">specification</a> both explain, D-Bus is tuned + for some specific use cases. Thus, it probably isn't tuned + for what you want to do, unless you are doing the things + D-Bus was designed for. Don't make the mistake of thinking + that any system involving "IPC" is the same thing. + </p><p> + The D-Bus authors would not recommend using D-Bus + for applications where it doesn't make sense. + The following questions compare D-Bus to some other + protocols primarily to help you understand D-Bus + and decide whether it's appropriate; D-Bus is neither intended + nor claimed to be the right choice for every application. + </p><p> + It should be possible to bridge D-Bus to other IPC systems, + just as D-Bus can be bridged to object systems. + </p><p> + Note: the D-Bus mailing list subscribers are <span class="emphasis"><em>very much not + interested</em></span> in debating which IPC system is the One True + System. So if you want to discuss that, please use another forum. + </p></td></tr><tr class="question" title="10."><td align="left" valign="top"><a name="corba"></a><a name="id358398"></a><p><b>10.</b></p></td><td align="left" valign="top"><p> + How does D-Bus differ from CORBA? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + Start by reading <a class="xref" href="#other-ipc" title="9.">Q: 9</a>. + </p><p> + <a class="ulink" href="http://www.omg.org" target="_top">CORBA</a> is designed to support + object-oriented IPC between objects, automatically marshalling + parameters as necessary. CORBA is strongly supported by the <a class="ulink" href="http://www.omg.org" target="_top">Open Management Group (OMG)</a>, which + produces various standards and supporting documents for CORBA and has + the backing of many large organizations. There are many CORBA ORBs + available, both proprietary ORBs and free / open source software ORBs + (the latter include <a class="ulink" href="http://orbit-resource.sourceforge.net/" target="_top">ORBit</a>, <a class="ulink" href="http://www.mico.org/" target="_top">MICO</a>, and <a class="ulink" href="http://www.theaceorb.com/" target="_top">The ACE Orb (TAO)</a>). Many + organizations continue to use CORBA ORBs for various kinds of IPC. + </p><p> + Both GNOME and KDE have used CORBA and then moved away from it. KDE + had more success with a system called DCOP, and GNOME layered a system + called Bonobo on top of CORBA. Without custom extensions, CORBA does + not support many of the things one wants to do in a desktop + environment with the GNOME/KDE architecture. + </p><p> + CORBA on the other hand has a number of features of interest for + enterprise and web application development, though XML systems such as + SOAP are the latest fad. + </p><p> + Like D-Bus, CORBA uses a fast binary protocol (IIOP). Both systems + work in terms of objects and methods, and have concepts such as + "oneway" calls. Only D-Bus has direct support for "signals" as in + GLib/Qt (or Java listeners, or C# delegates). + </p><p> + D-Bus hardcodes and specifies a lot of things that CORBA leaves open-ended, + because CORBA is more generic and D-Bus has two specific use-cases in mind. + This makes D-Bus a bit simpler. + </p><p> + However, unlike CORBA D-Bus does <span class="emphasis"><em>not</em></span> specify the + API for the language bindings. Instead, "native" bindings adapted + specifically to the conventions of a framework such as QObject, + GObject, C#, Java, Python, etc. are encouraged. The libdbus reference + implementation is designed to be a backend for bindings of this + nature, rather than to be used directly. The rationale is that an IPC + system API should not "leak" all over a program; it should come into + play only just before data goes over the wire. As an aside, OMG is + apparently working on a simpler C++ binding for CORBA. + </p><p> + Many CORBA implementations such as ORBit are faster than the libdbus + reference implementation. One reason is that D-Bus considers data + from the other end of the connection to be untrusted and extensively + validates it. But generally speaking other priorities were placed + ahead of raw speed in the libdbus implementation. A fast D-Bus + implementation along the lines of ORBit should be possible, of course. + </p><p> + On a more trivial note, D-Bus involves substantially fewer acronyms + than CORBA. + </p></td></tr><tr class="question" title="11."><td align="left" valign="top"><a name="xmlrpcsoap"></a><a name="id319108"></a><p><b>11.</b></p></td><td align="left" valign="top"><p> + How does D-Bus differ from XML-RPC and SOAP? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + Start by reading <a class="xref" href="#other-ipc" title="9.">Q: 9</a>. + </p><p> + In <a class="ulink" href="http://www.w3.org/TR/SOAP/" target="_top">SOAP</a> and <a class="ulink" href="http://www.xmlrpc.com" target="_top">XML-RPC</a>, RPC calls are transformed + into an XML-based format, then sent over the wire (typically using the + HTTP protocol), where they are processed and returned. XML-RPC is the + simple protocol (its spec is only a page or two), and SOAP is the + full-featured protocol. + </p><p> + XML-RPC and SOAP impose XML parsing overhead that is normally + irrelevant in the context of the Internet, but significant for + constant fine-grained IPC among applications in a desktop session. + </p><p> + D-Bus offers persistent connections and with the bus daemon + supports lifecycle tracking of other applications connected + to the bus. With XML-RPC and SOAP, typically each method call + exists in isolation and has its own HTTP connection. + </p></td></tr><tr class="question" title="12."><td align="left" valign="top"><a name="dce"></a><a name="id358723"></a><p><b>12.</b></p></td><td align="left" valign="top"><p> + How does D-Bus differ from DCE? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + Start by reading <a class="xref" href="#other-ipc" title="9.">Q: 9</a>. + </p><p> + <a class="ulink" href="http://www.opengroup.org/dce/" target="_top">Distributed Computing + Environment (DCE)</a> is an industry-standard vendor-neutral + standard that includes an IPC mechanism. <a class="ulink" href="http://www.opengroup.org/comm/press/05-01-12.htm" target="_top">The Open Group + has released an implementation as open source software</a>. DCE + is quite capable, and includes a vast amount of functionality such as + a distributed time service. As the name implies, DCE is intended for + use in a large, multi-computer distributed application. D-Bus would + not be well-suited for this. + </p></td></tr><tr class="question" title="13."><td align="left" valign="top"><a name="dcom"></a><a name="id358763"></a><p><b>13.</b></p></td><td align="left" valign="top"><p> + How does D-Bus differ from DCOM and COM? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + Start by reading <a class="xref" href="#other-ipc" title="9.">Q: 9</a>. + </p><p> + Comparing D-Bus to COM is apples and oranges; + see <a class="xref" href="#components" title="6.">Q: 6</a>. + </p><p> + DCOM (distributed COM) is a Windows IPC system designed for use with + the COM object system. It's similar in some ways to DCE and CORBA. + </p></td></tr><tr class="question" title="14."><td align="left" valign="top"><a name="internet-communications-engine"></a><a name="id358799"></a><p><b>14.</b></p></td><td align="left" valign="top"><p> + How does D-Bus differ from ZeroC's Internet Communications Engine (Ice) + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + Start by reading <a class="xref" href="#other-ipc" title="9.">Q: 9</a>. + </p><p> + The <a class="ulink" href="http://www.zeroc.com/ice.html" target="_top"> Internet + Communications Engine (Ice)</a> is a powerful IPC mechanism more + on the level of SOAP or CORBA than D-Bus. Ice has a "dual-license" + business around it; i.e. you can use it under the GPL, or pay for a + proprietary license. + </p></td></tr><tr class="question" title="15."><td align="left" valign="top"><a name="inter-client-exchange"></a><a name="id358832"></a><p><b>15.</b></p></td><td align="left" valign="top"><p> + How does D-Bus differ from Inter-Client Exchange (ICE)? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + <a class="ulink" href="http://www.x.org/X11R6.8.1/docs/ICE/ice.pdf" target="_top">ICE</a> + was developed for the X Session Management protocol (XSMP), as part of + the X Window System (X11R6.1). The idea was to allow desktop sessions + to contain nongraphical clients in addition to X clients. + </p><p> + ICE is a binary protocol designed for desktop use, and KDE's DCOP + builds on ICE. ICE is substantially simpler than D-Bus (in contrast + to most of the other IPC systems mentioned here, which are more + complex). ICE doesn't really define a mapping to objects and methods + (DCOP adds that layer). The reference implementation of ICE (libICE) + is often considered to be horrible (and horribly insecure). + </p><p> + DCOP and XSMP are the only two widely-used applications of ICE, + and both could in principle be replaced by D-Bus. (Though whether + GNOME and KDE will bother is an open question.) + </p></td></tr><tr class="question" title="16."><td align="left" valign="top"><a name="dcop"></a><a name="id358871"></a><p><b>16.</b></p></td><td align="left" valign="top"><p> + How does D-Bus differ from DCOP? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + Start by reading <a class="xref" href="#other-ipc" title="9.">Q: 9</a>. + </p><p> + D-Bus is intentionally pretty similar to <a class="ulink" href="http://developer.kde.org/documentation/library/kdeqt/dcop.html" target="_top">DCOP</a>, + and can be thought of as a "DCOP the next generation" suitable for + sharing between the various open source desktop projects. + </p><p> + D-Bus is a bit more complex than DCOP, though the Qt binding for D-Bus + should not be more complex for programmers. The additional complexity + of D-Bus arises from its separation of object references vs. bus names + vs. interfaces as distinct concepts, and its support for one-to-one + connections in addition to connections over the bus. The libdbus + reference implementation has a lot of API to support multiple bindings + and main loops, and performs data validation and out-of-memory handling + in order to support secure applications such as the systemwide bus. + </p><p> + D-Bus is probably somewhat slower than DCOP due to data validation + and more "layers" in the reference implementation. A comparison + hasn't been posted to the list though. + </p><p> + At this time, KDE has not committed to using D-Bus, but there have + been discussions of KDE bridging D-Bus and DCOP, or even changing + DCOP's implementation to use D-Bus internally (so that GNOME and KDE + would end up using exactly the same bus). See the KDE mailing list + archives for some of these discussions. + </p></td></tr><tr class="question" title="17."><td align="left" valign="top"><a name="yet-more-ipc"></a><a name="id358929"></a><p><b>17.</b></p></td><td align="left" valign="top"><p> + How does D-Bus differ from [yet more IPC mechanisms]? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + Start by reading <a class="xref" href="#other-ipc" title="9.">Q: 9</a>. + </p><p> + There are countless uses of network sockets in the world. <a class="ulink" href="http://www.mbus.org/" target="_top">MBUS</a>, Sun ONC/RPC, Jabber/XMPP, + SIP, are some we can think of quickly. + </p></td></tr><tr class="question" title="18."><td align="left" valign="top"><a name="which-ipc"></a><a name="id358962"></a><p><b>18.</b></p></td><td align="left" valign="top"><p> + Which IPC mechanism should I use? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + Start by reading <a class="xref" href="#other-ipc" title="9.">Q: 9</a>. + </p><p> + If you're writing an Internet or Intranet application, XML-RPC or SOAP + work for many people. These are standard, available for most + languages, simple to debug and easy to use. + </p><p> + If you're writing a desktop application for UNIX, + then D-Bus is of course our recommendation for + talking to other parts of the desktop session. + </p><p> + D-Bus is also designed for communications between system daemons and + communications between the desktop and system daemons. + </p><p> + If you're doing something complicated such as clustering, + distributed swarms, peer-to-peer, or whatever then + the authors of this FAQ don't have expertise in these + areas and you should ask someone else or try a search engine. + D-Bus is most likely a poor choice but could be appropriate + for some things. + </p><p> + Note: the D-Bus mailing list is probably not the place to + discuss which system is appropriate for your application, + though you are welcome to ask specific questions about + D-Bus <span class="emphasis"><em>after reading this FAQ, the tutorial, and + searching the list archives</em></span>. The best way + to search the list archives is probably to use + an Internet engine such as Google. On Google, + include "site:freedesktop.org" in your search. + </p></td></tr><tr class="question" title="19."><td align="left" valign="top"><a name="id359012"></a><a name="id359014"></a><p><b>19.</b></p></td><td align="left" valign="top"><p> + How can I submit a bug or patch? + </p></td></tr><tr class="answer"><td align="left" valign="top"></td><td align="left" valign="top"><p> + The D-Bus <a class="ulink" href="http://dbus.freedesktop.org" target="_top">web site</a> + has a link to the bug tracker, which is the best place to store + patches. You can also post them to the list, especially if you want + to discuss the patch or get feedback. + </p></td></tr></tbody></table></div></div></body></html> diff --git a/doc/dbus-faq.xml b/doc/dbus-faq.xml new file mode 100644 index 00000000..69ac3f15 --- /dev/null +++ b/doc/dbus-faq.xml @@ -0,0 +1,674 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" +"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" +[ +]> + +<article id="index"> + <articleinfo> + <title>D-Bus FAQ</title> + <releaseinfo>Version 0.3</releaseinfo> + <date>17 November 2006</date> + <authorgroup> + <author> + <firstname>Havoc</firstname> + <surname>Pennington</surname> + <affiliation> + <orgname>Red Hat, Inc.</orgname> + <address> + <email>hp@pobox.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>David</firstname> + <othername role="mi">A</othername> + <surname>Wheeler</surname> + </author> + </authorgroup> + </articleinfo> + + <qandaset id="faq"> + + <qandaentry> + <question> + <para> + What is D-Bus? + </para> + </question> + <answer> + <para> + This is probably best answered by reading the D-Bus <ulink url="dbus-tutorial.html">tutorial</ulink> or + the introduction to the <ulink url="dbus-specification.html">specification</ulink>. In + short, it is a system consisting of 1) a wire protocol for exposing a + typical object-oriented language/framework to other applications; and + 2) a bus daemon that allows applications to find and monitor one another. + Phrased differently, D-Bus is 1) an interprocess communication (IPC) system and 2) some higher-level + structure (lifecycle tracking, service activation, security policy) provided by two bus daemons, + one systemwide and one per-user-session. + </para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para> + Is D-Bus stable/finished? + </para> + </question> + <answer> + <para> + The low-level library "libdbus" and the protocol specification are considered + ABI stable. The <ulink url="README">README</ulink> + file has a discussion of the API/ABI stability guarantees. + Higher-level bindings (such as those for Qt, GLib, Python, Java, C#) each + have their own release schedules and degree of maturity, not linked to + the low-level library and bus daemon release. Check the project page for + the binding you're considering to understand that project's policies. + </para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para> + How is the reference implementation licensed? Can I use it in + proprietary applications? + </para> + </question> + <answer> + <para> + The short answer is yes, you can use it in proprietary applications. + You should read the <ulink url="COPYING">COPYING</ulink> file, which + offers you the choice of two licenses. These are the GPL and the + AFL. The GPL requires that your application be licensed under the GPL + as well. The AFL is an "X-style" or "BSD-style" license compatible + with proprietary licensing, but it does have some requirements; in + particular it prohibits you from filing a lawsuit alleging that the + D-Bus software infringes your patents <emphasis>while you continue to + use D-Bus</emphasis>. If you're going to sue, you have to stop using + the software. Read the licenses to determine their meaning, this FAQ + entry is not intended to change the meaning or terms of the licenses. + </para> + </answer> + </qandaentry> + + <qandaentry> + <question> + <para> + What is the difference between a bus name, and object path, + and an interface? + </para> + </question> + <answer> + <para> + If you imagine a C++ program that implements a network service, then + the bus name is the hostname of the computer running this C++ program, + the object path is a C++ object instance pointer, and an interface is + a C++ class (a pure virtual or abstract class, to be exact). + </para> + <para> + In Java terms, the object path is an object reference, + and an interface is a Java interface. + </para> + <para> + People get confused because if they write an application + with a single object instance and a single interface, + then the bus name, object path, and interface look + redundant. For example, you might have a text editor + that uses the bus name <literal>org.freedesktop.TextEditor</literal>, + has a global singleton object called + <literal>/org/freedesktop/TextEditor</literal>, and + that singleton object could implement the interface + <literal>org.freedesktop.TextEditor</literal>. + </para> + <para> + However, a text editor application could as easily own multiple bus + names (for example, <literal>org.kde.KWrite</literal> in addition to + generic <literal>TextEditor</literal>), have multiple objects (maybe + <literal>/org/kde/documents/4352</literal> where the number changes + according to the document), and each object could implement multiple + interfaces, such as <literal>org.freedesktop.DBus.Introspectable</literal>, + <literal>org.freedesktop.BasicTextField</literal>, + <literal>org.kde.RichTextDocument</literal>. + </para> + </answer> + </qandaentry> + + + <qandaentry id="service"> + <question> + <para> + What is a "service"? + </para> + </question> + <answer> + <para> + A service is a program that can be launched by the bus daemon + to provide some functionality to other programs. Services + are normally launched according to the bus name they will + have. + </para> + <para> + People often misuse the word "service" for any + bus name, but this tends to be ambiguous and confusing so is discouraged. + In the D-Bus docs we try to use "service" only when talking about + programs the bus knows how to launch, i.e. a service always has a + .service file. + </para> + </answer> + </qandaentry> + + <qandaentry id="components"> + <question> + <para> + Is D-Bus a "component system"? + </para> + </question> + <answer> + <para> + It helps to keep these concepts separate in your mind: + <orderedlist> + <listitem> + <para> + Object/component system + </para> + </listitem> + <listitem> + <para> + GUI control/widget embedding interfaces + </para> + </listitem> + <listitem> + <para> + Interprocess communication system or wire protocol + </para> + </listitem> + </orderedlist> + </para> + <para> + D-Bus is not a component system. "Component system" was originally + defined by COM, and was essentially a workaround for the limitations + of the C++ object system (adding introspection, runtime location of + objects, ABI guarantees, and so forth). With the C# language and CLR, + Microsoft added these features to the primary object system, leaving + COM obsolete. Similarly, Java has much less need for something like + COM than C++ did. Even QObject (from Qt) and GObject (from GLib) offer + some of the same features found in COM. + </para> + <para> + Component systems are not about GUI control embedding. Embedding + a spreadsheet in a word processor document is a matter of defining + some specific <emphasis>interfaces</emphasis> that objects + can implement. These interfaces provide methods related to + GUI controls. So an object implementing those interfaces + can be embedded. + </para> + <para> + The word "component" just means "object with some fancy features" and + in modern languages all objects are effectively "components." + </para> + <para> + So components are fancy objects, and some objects are GUI controls. + </para> + <para> + A third, unrelated feature is interprocess communication or IPC. + D-Bus is an IPC system. Given an object (or "component" if you must), + you can expose the functionality of that object over an IPC system. + Examples of IPC systems are DCOM, CORBA, SOAP, XML-RPC, and D-Bus. + You can use any of these IPC systems with any object/component system, + though some of them are "tuned" for specific object systems. + You can think of an IPC system primarily as a wire protocol. + </para> + <para> + If you combine an IPC system with a set of GUI control interfaces, + then you can have an out-of-process or dynamically-loaded GUI control. + </para> + <para> + Another related concept is the <firstterm>plugin</firstterm> or + <firstterm>extension</firstterm>. Generic plugin systems such as the + <ulink url="http://eclipse.org">Eclipse</ulink> system are not so different + from component/object systems, though perhaps a "plugin" tends to be a + bundle of objects with a user-visible name and can be + downloaded/packaged as a unit. + </para> + </answer> + </qandaentry> + + <qandaentry id="speed"> + <question> + <para> + How fast is the D-Bus reference implementation? + </para> + </question> + <answer> + <para> + Of course it depends a bit on what you're doing. + <ulink url="http://lists.freedesktop.org/pipermail/dbus/2004-November/001779.html"> + This mail</ulink> contains some benchmarking. At the time of that + benchmark, D-Bus one-to-one communication was about 2.5x slower than + simply pushing the data raw over a socket. After the recent rewrite of + the marshaling code, D-Bus is slower than that because a lot of + optimization work was lost. But it can probably be sped up again. + </para> + <para> + D-Bus communication with the intermediate bus daemon should be + (and as last profiled, was) about twice as slow as one-to-one + mode, because a round trip involves four socket reads/writes rather + than two socket reads/writes. + </para> + <para> + The overhead comes from a couple of places; part of it is simply + "abstraction penalty" (there are layers of code to support + multiple main loops, multiple transport types, security, etc.). + Probably the largest part comes from data validation + (because the reference implementation does not trust incoming data). + It would be simple to add a "no validation" mode, but probably + not a good idea all things considered. + </para> + <para> + Raw bandwidth isn't the only concern; D-Bus is designed to + enable asynchronous communication and avoid round trips. + This is frequently a more important performance issue + than throughput. + </para> + </answer> + </qandaentry> + + + <qandaentry id="size"> + <question> + <para> + How large is the D-Bus reference implementation? + </para> + </question> + <answer> + <para> + A production build (with assertions, unit tests, and verbose logging + disabled) is on the order of a 150K shared library. + </para> + <para> + A much, much smaller implementation would be possible by omitting out + of memory handling, hardcoding a main loop (or always using blocking + I/O), skipping validation, and otherwise simplifying things. + </para> + </answer> + </qandaentry> + + <qandaentry id="other-ipc"> + <question> + <para> + How does D-Bus differ from other interprocess communication + or networking protocols? + </para> + </question> + <answer> + <para> + Keep in mind, it is not only an IPC system; it also includes + lifecycle tracking, service activation, security policy, and other + higher-level structure and assumptions. + </para> + <para> + The best place to start is to read the D-Bus <ulink url="dbus-tutorial.html">tutorial</ulink>, so + you have a concrete idea what D-Bus actually is. If you + understand other protocols on a wire format level, you + may also want to read the D-Bus <ulink url="dbus-specification.html">specification</ulink> to see what + D-Bus looks like on a low level. + </para> + <para> + As the <ulink url="dbus-tutorial.html">tutorial</ulink> and <ulink url="dbus-specification.html">specification</ulink> both explain, D-Bus is tuned + for some specific use cases. Thus, it probably isn't tuned + for what you want to do, unless you are doing the things + D-Bus was designed for. Don't make the mistake of thinking + that any system involving "IPC" is the same thing. + </para> + <para> + The D-Bus authors would not recommend using D-Bus + for applications where it doesn't make sense. + The following questions compare D-Bus to some other + protocols primarily to help you understand D-Bus + and decide whether it's appropriate; D-Bus is neither intended + nor claimed to be the right choice for every application. + </para> + <para> + It should be possible to bridge D-Bus to other IPC systems, + just as D-Bus can be bridged to object systems. + </para> + <para> + Note: the D-Bus mailing list subscribers are <emphasis>very much not + interested</emphasis> in debating which IPC system is the One True + System. So if you want to discuss that, please use another forum. + </para> + </answer> + </qandaentry> + + + <qandaentry id="corba"> + <question> + <para> + How does D-Bus differ from CORBA? + </para> + </question> + <answer> + <para> + Start by reading <xref linkend="other-ipc"/>. + </para> + <para> + <ulink url="http://www.omg.org">CORBA</ulink> is designed to support + object-oriented IPC between objects, automatically marshalling + parameters as necessary. CORBA is strongly supported by the <ulink + url="http://www.omg.org">Open Management Group (OMG)</ulink>, which + produces various standards and supporting documents for CORBA and has + the backing of many large organizations. There are many CORBA ORBs + available, both proprietary ORBs and free / open source software ORBs + (the latter include <ulink + url="http://orbit-resource.sourceforge.net/">ORBit</ulink>, <ulink + url="http://www.mico.org/">MICO</ulink>, and <ulink + url="http://www.theaceorb.com/">The ACE Orb (TAO)</ulink>). Many + organizations continue to use CORBA ORBs for various kinds of IPC. + </para> + <para> + Both GNOME and KDE have used CORBA and then moved away from it. KDE + had more success with a system called DCOP, and GNOME layered a system + called Bonobo on top of CORBA. Without custom extensions, CORBA does + not support many of the things one wants to do in a desktop + environment with the GNOME/KDE architecture. + </para> + <para> + CORBA on the other hand has a number of features of interest for + enterprise and web application development, though XML systems such as + SOAP are the latest fad. + </para> + <para> + Like D-Bus, CORBA uses a fast binary protocol (IIOP). Both systems + work in terms of objects and methods, and have concepts such as + "oneway" calls. Only D-Bus has direct support for "signals" as in + GLib/Qt (or Java listeners, or C# delegates). + </para> + <para> + D-Bus hardcodes and specifies a lot of things that CORBA leaves open-ended, + because CORBA is more generic and D-Bus has two specific use-cases in mind. + This makes D-Bus a bit simpler. + </para> + <para> + However, unlike CORBA D-Bus does <emphasis>not</emphasis> specify the + API for the language bindings. Instead, "native" bindings adapted + specifically to the conventions of a framework such as QObject, + GObject, C#, Java, Python, etc. are encouraged. The libdbus reference + implementation is designed to be a backend for bindings of this + nature, rather than to be used directly. The rationale is that an IPC + system API should not "leak" all over a program; it should come into + play only just before data goes over the wire. As an aside, OMG is + apparently working on a simpler C++ binding for CORBA. + </para> + <para> + Many CORBA implementations such as ORBit are faster than the libdbus + reference implementation. One reason is that D-Bus considers data + from the other end of the connection to be untrusted and extensively + validates it. But generally speaking other priorities were placed + ahead of raw speed in the libdbus implementation. A fast D-Bus + implementation along the lines of ORBit should be possible, of course. + </para> + <para> + On a more trivial note, D-Bus involves substantially fewer acronyms + than CORBA. + </para> + </answer> + </qandaentry> + + + <qandaentry id="xmlrpcsoap"> + <question> + <para> + How does D-Bus differ from XML-RPC and SOAP? + </para> + </question> + <answer> + <para> + Start by reading <xref linkend="other-ipc"/>. + </para> + <para> + In <ulink url="http://www.w3.org/TR/SOAP/">SOAP</ulink> and <ulink + url="http://www.xmlrpc.com">XML-RPC</ulink>, RPC calls are transformed + into an XML-based format, then sent over the wire (typically using the + HTTP protocol), where they are processed and returned. XML-RPC is the + simple protocol (its spec is only a page or two), and SOAP is the + full-featured protocol. + </para> + <para> + XML-RPC and SOAP impose XML parsing overhead that is normally + irrelevant in the context of the Internet, but significant for + constant fine-grained IPC among applications in a desktop session. + </para> + <para> + D-Bus offers persistent connections and with the bus daemon + supports lifecycle tracking of other applications connected + to the bus. With XML-RPC and SOAP, typically each method call + exists in isolation and has its own HTTP connection. + </para> + </answer> + </qandaentry> + + <qandaentry id="dce"> + <question> + <para> + How does D-Bus differ from DCE? + </para> + </question> + <answer> + <para> + Start by reading <xref linkend="other-ipc"/>. + </para> + <para> + <ulink url="http://www.opengroup.org/dce/">Distributed Computing + Environment (DCE)</ulink> is an industry-standard vendor-neutral + standard that includes an IPC mechanism. <ulink + url="http://www.opengroup.org/comm/press/05-01-12.htm">The Open Group + has released an implementation as open source software</ulink>. DCE + is quite capable, and includes a vast amount of functionality such as + a distributed time service. As the name implies, DCE is intended for + use in a large, multi-computer distributed application. D-Bus would + not be well-suited for this. + </para> + </answer> + </qandaentry> + + + <qandaentry id="dcom"> + <question> + <para> + How does D-Bus differ from DCOM and COM? + </para> + </question> + <answer> + <para> + Start by reading <xref linkend="other-ipc"/>. + </para> + <para> + Comparing D-Bus to COM is apples and oranges; + see <xref linkend="components"/>. + </para> + <para> + DCOM (distributed COM) is a Windows IPC system designed for use with + the COM object system. It's similar in some ways to DCE and CORBA. + </para> + </answer> + </qandaentry> + + <qandaentry id="internet-communications-engine"> + <question> + <para> + How does D-Bus differ from ZeroC's Internet Communications Engine (Ice) + </para> + </question> + <answer> + <para> + Start by reading <xref linkend="other-ipc"/>. + </para> + <para> + The <ulink url="http://www.zeroc.com/ice.html"> Internet + Communications Engine (Ice)</ulink> is a powerful IPC mechanism more + on the level of SOAP or CORBA than D-Bus. Ice has a "dual-license" + business around it; i.e. you can use it under the GPL, or pay for a + proprietary license. + </para> + </answer> + </qandaentry> + + <qandaentry id="inter-client-exchange"> + <question> + <para> + How does D-Bus differ from Inter-Client Exchange (ICE)? + </para> + </question> + <answer> + <para> + <ulink url="http://www.x.org/X11R6.8.1/docs/ICE/ice.pdf">ICE</ulink> + was developed for the X Session Management protocol (XSMP), as part of + the X Window System (X11R6.1). The idea was to allow desktop sessions + to contain nongraphical clients in addition to X clients. + </para> + <para> + ICE is a binary protocol designed for desktop use, and KDE's DCOP + builds on ICE. ICE is substantially simpler than D-Bus (in contrast + to most of the other IPC systems mentioned here, which are more + complex). ICE doesn't really define a mapping to objects and methods + (DCOP adds that layer). The reference implementation of ICE (libICE) + is often considered to be horrible (and horribly insecure). + </para> + <para> + DCOP and XSMP are the only two widely-used applications of ICE, + and both could in principle be replaced by D-Bus. (Though whether + GNOME and KDE will bother is an open question.) + </para> + </answer> + </qandaentry> + + + + <qandaentry id="dcop"> + <question> + <para> + How does D-Bus differ from DCOP? + </para> + </question> + <answer> + <para> + Start by reading <xref linkend="other-ipc"/>. + </para> + <para> + D-Bus is intentionally pretty similar to <ulink + url="http://developer.kde.org/documentation/library/kdeqt/dcop.html">DCOP</ulink>, + and can be thought of as a "DCOP the next generation" suitable for + sharing between the various open source desktop projects. + </para> + <para> + D-Bus is a bit more complex than DCOP, though the Qt binding for D-Bus + should not be more complex for programmers. The additional complexity + of D-Bus arises from its separation of object references vs. bus names + vs. interfaces as distinct concepts, and its support for one-to-one + connections in addition to connections over the bus. The libdbus + reference implementation has a lot of API to support multiple bindings + and main loops, and performs data validation and out-of-memory handling + in order to support secure applications such as the systemwide bus. + </para> + <para> + D-Bus is probably somewhat slower than DCOP due to data validation + and more "layers" in the reference implementation. A comparison + hasn't been posted to the list though. + </para> + <para> + At this time, KDE has not committed to using D-Bus, but there have + been discussions of KDE bridging D-Bus and DCOP, or even changing + DCOP's implementation to use D-Bus internally (so that GNOME and KDE + would end up using exactly the same bus). See the KDE mailing list + archives for some of these discussions. + </para> + </answer> + </qandaentry> + + + <qandaentry id="yet-more-ipc"> + <question> + <para> + How does D-Bus differ from [yet more IPC mechanisms]? + </para> + </question> + <answer> + <para> + Start by reading <xref linkend="other-ipc"/>. + </para> + <para> + There are countless uses of network sockets in the world. <ulink + url="http://www.mbus.org/">MBUS</ulink>, Sun ONC/RPC, Jabber/XMPP, + SIP, are some we can think of quickly. + </para> + </answer> + </qandaentry> + + + <qandaentry id="which-ipc"> + <question> + <para> + Which IPC mechanism should I use? + </para> + </question> + <answer> + <para> + Start by reading <xref linkend="other-ipc"/>. + </para> + <para> + If you're writing an Internet or Intranet application, XML-RPC or SOAP + work for many people. These are standard, available for most + languages, simple to debug and easy to use. + </para> + <para> + If you're writing a desktop application for UNIX, + then D-Bus is of course our recommendation for + talking to other parts of the desktop session. + </para> + <para> + D-Bus is also designed for communications between system daemons and + communications between the desktop and system daemons. + </para> + <para> + If you're doing something complicated such as clustering, + distributed swarms, peer-to-peer, or whatever then + the authors of this FAQ don't have expertise in these + areas and you should ask someone else or try a search engine. + D-Bus is most likely a poor choice but could be appropriate + for some things. + </para> + <para> + Note: the D-Bus mailing list is probably not the place to + discuss which system is appropriate for your application, + though you are welcome to ask specific questions about + D-Bus <emphasis>after reading this FAQ, the tutorial, and + searching the list archives</emphasis>. The best way + to search the list archives is probably to use + an Internet engine such as Google. On Google, + include "site:freedesktop.org" in your search. + </para> + </answer> + </qandaentry> + + + <qandaentry> + <question> + <para> + How can I submit a bug or patch? + </para> + </question> + <answer> + <para> + The D-Bus <ulink url="http://dbus.freedesktop.org">web site</ulink> + has a link to the bug tracker, which is the best place to store + patches. You can also post them to the list, especially if you want + to discuss the patch or get feedback. + </para> + </answer> + </qandaentry> + + </qandaset> + +</article> diff --git a/doc/dbus-specification.html b/doc/dbus-specification.html new file mode 100644 index 00000000..18006de5 --- /dev/null +++ b/doc/dbus-specification.html @@ -0,0 +1,2081 @@ +<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>D-Bus Specification</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="article" title="D-Bus Specification"><div class="titlepage"><div><div><h2 class="title"><a name="index"></a>D-Bus Specification</h2></div><div><div class="authorgroup"><div class="author"><h3 class="author"><span class="firstname">Havoc</span> <span class="surname">Pennington</span></h3><div class="affiliation"><span class="orgname">Red Hat, Inc.<br></span><div class="address"><p><br> + <code class="email"><<a class="email" href="mailto:hp@pobox.com">hp@pobox.com</a>></code><br> + </p></div></div></div><div class="author"><h3 class="author"><span class="firstname">Anders</span> <span class="surname">Carlsson</span></h3><div class="affiliation"><span class="orgname">CodeFactory AB<br></span><div class="address"><p><br> + <code class="email"><<a class="email" href="mailto:andersca@codefactory.se">andersca@codefactory.se</a>></code><br> + </p></div></div></div><div class="author"><h3 class="author"><span class="firstname">Alexander</span> <span class="surname">Larsson</span></h3><div class="affiliation"><span class="orgname">Red Hat, Inc.<br></span><div class="address"><p><br> + <code class="email"><<a class="email" href="mailto:alexl@redhat.com">alexl@redhat.com</a>></code><br> + </p></div></div></div></div></div><div><p class="releaseinfo">Version 0.12</p></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#introduction">Introduction</a></span></dt><dd><dl><dt><span class="sect2"><a href="#stability">Protocol and Specification Stability</a></span></dt></dl></dd><dt><span class="sect1"><a href="#message-protocol">Message Protocol</a></span></dt><dd><dl><dt><span class="sect2"><a href="#message-protocol-signatures">Type Signatures</a></span></dt><dt><span class="sect2"><a href="#message-protocol-marshaling">Marshaling (Wire Format)</a></span></dt><dt><span class="sect2"><a href="#message-protocol-messages">Message Format</a></span></dt><dt><span class="sect2"><a href="#message-protocol-names">Valid Names</a></span></dt><dt><span class="sect2"><a href="#message-protocol-types">Message Types</a></span></dt><dt><span class="sect2"><a href="#message-protocol-handling-invalid">Invalid Protocol and Spec Extensions</a></span></dt></dl></dd><dt><span class="sect1"><a href="#auth-protocol">Authentication Protocol</a></span></dt><dd><dl><dt><span class="sect2"><a href="#auth-protocol-overview">Protocol Overview</a></span></dt><dt><span class="sect2"><a href="#auth-nul-byte">Special credentials-passing nul byte</a></span></dt><dt><span class="sect2"><a href="#auth-command-auth">AUTH command</a></span></dt><dt><span class="sect2"><a href="#auth-command-cancel">CANCEL Command</a></span></dt><dt><span class="sect2"><a href="#auth-command-data">DATA Command</a></span></dt><dt><span class="sect2"><a href="#auth-command-begin">BEGIN Command</a></span></dt><dt><span class="sect2"><a href="#auth-command-rejected">REJECTED Command</a></span></dt><dt><span class="sect2"><a href="#auth-command-ok">OK Command</a></span></dt><dt><span class="sect2"><a href="#auth-command-error">ERROR Command</a></span></dt><dt><span class="sect2"><a href="#auth-examples">Authentication examples</a></span></dt><dt><span class="sect2"><a href="#auth-states">Authentication state diagrams</a></span></dt><dt><span class="sect2"><a href="#auth-mechanisms">Authentication mechanisms</a></span></dt></dl></dd><dt><span class="sect1"><a href="#addresses">Server Addresses</a></span></dt><dt><span class="sect1"><a href="#transports">Transports</a></span></dt><dd><dl><dt><span class="sect2"><a href="#transports-unix-domain-sockets">Unix Domain Sockets</a></span></dt></dl></dd><dt><span class="sect1"><a href="#naming-conventions">Naming Conventions</a></span></dt><dt><span class="sect1"><a href="#uuids">UUIDs</a></span></dt><dt><span class="sect1"><a href="#standard-interfaces">Standard Interfaces</a></span></dt><dd><dl><dt><span class="sect2"><a href="#standard-interfaces-peer"><code class="literal">org.freedesktop.DBus.Peer</code></a></span></dt><dt><span class="sect2"><a href="#standard-interfaces-introspectable"><code class="literal">org.freedesktop.DBus.Introspectable</code></a></span></dt><dt><span class="sect2"><a href="#standard-interfaces-properties"><code class="literal">org.freedesktop.DBus.Properties</code></a></span></dt></dl></dd><dt><span class="sect1"><a href="#introspection-format">Introspection Data Format</a></span></dt><dt><span class="sect1"><a href="#message-bus">Message Bus Specification</a></span></dt><dd><dl><dt><span class="sect2"><a href="#message-bus-overview">Message Bus Overview</a></span></dt><dt><span class="sect2"><a href="#message-bus-names">Message Bus Names</a></span></dt><dt><span class="sect2"><a href="#message-bus-routing">Message Bus Message Routing</a></span></dt><dt><span class="sect2"><a href="#message-bus-starting-services">Message Bus Starting Services</a></span></dt><dt><span class="sect2"><a href="#message-bus-types">Well-known Message Bus Instances</a></span></dt><dt><span class="sect2"><a href="#message-bus-messages">Message Bus Messages</a></span></dt></dl></dd><dt><span class="glossary"><a href="#id324439">Glossary</a></span></dt></dl></div><div class="sect1" title="Introduction"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="introduction"></a>Introduction</h2></div></div></div><p> + D-Bus is a system for low-latency, low-overhead, easy to use + interprocess communication (IPC). In more detail: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + D-Bus is <span class="emphasis"><em>low-latency</em></span> because it is designed + to avoid round trips and allow asynchronous operation, much like + the X protocol. + </p></li><li class="listitem"><p> + D-Bus is <span class="emphasis"><em>low-overhead</em></span> because it uses a + binary protocol, and does not have to convert to and from a text + format such as XML. Because D-Bus is intended for potentially + high-resolution same-machine IPC, not primarily for Internet IPC, + this is an interesting optimization. + </p></li><li class="listitem"><p> + D-Bus is <span class="emphasis"><em>easy to use</em></span> because it works in terms + of <em class="firstterm">messages</em> rather than byte streams, and + automatically handles a lot of the hard IPC issues. Also, the D-Bus + library is designed to be wrapped in a way that lets developers use + their framework's existing object/type system, rather than learning + a new one specifically for IPC. + </p></li></ul></div><p> + </p><p> + The base D-Bus protocol is a one-to-one (peer-to-peer or client-server) + protocol, specified in <a class="xref" href="#message-protocol" title="Message Protocol">the section called “Message Protocol”</a>. That is, it is + a system for one application to talk to a single other + application. However, the primary intended application of the protocol is the + D-Bus <em class="firstterm">message bus</em>, specified in <a class="xref" href="#message-bus" title="Message Bus Specification">the section called “Message Bus Specification”</a>. The message bus is a special application that + accepts connections from multiple other applications, and forwards + messages among them. + </p><p> + Uses of D-Bus include notification of system changes (notification of when + a camera is plugged in to a computer, or a new version of some software + has been installed), or desktop interoperability, for example a file + monitoring service or a configuration service. + </p><p> + D-Bus is designed for two specific use cases: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + A "system bus" for notifications from the system to user sessions, + and to allow the system to request input from user sessions. + </p></li><li class="listitem"><p> + A "session bus" used to implement desktop environments such as + GNOME and KDE. + </p></li></ul></div><p> + D-Bus is not intended to be a generic IPC system for any possible + application, and intentionally omits many features found in other + IPC systems for this reason. + </p><p> + At the same time, the bus daemons offer a number of features not found in + other IPC systems, such as single-owner "bus names" (similar to X + selections), on-demand startup of services, and security policies. + In many ways, these features are the primary motivation for developing + D-Bus; other systems would have sufficed if IPC were the only goal. + </p><p> + D-Bus may turn out to be useful in unanticipated applications, but future + versions of this spec and the reference implementation probably will not + incorporate features that interfere with the core use cases. + </p><p> + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in RFC 2119. However, the + document could use a serious audit to be sure it makes sense to do + so. Also, they are not capitalized. + </p><div class="sect2" title="Protocol and Specification Stability"><div class="titlepage"><div><div><h3 class="title"><a name="stability"></a>Protocol and Specification Stability</h3></div></div></div><p> + The D-Bus protocol is frozen (only compatible extensions are allowed) as + of November 8, 2006. However, this specification could still use a fair + bit of work to make interoperable reimplementation possible without + reference to the D-Bus reference implementation. Thus, this + specification is not marked 1.0. To mark it 1.0, we'd like to see + someone invest significant effort in clarifying the specification + language, and growing the specification to cover more aspects of the + reference implementation's behavior. + </p><p> + Until this work is complete, any attempt to reimplement D-Bus will + probably require looking at the reference implementation and/or asking + questions on the D-Bus mailing list about intended behavior. + Questions on the list are very welcome. + </p><p> + Nonetheless, this document should be a useful starting point and is + to our knowledge accurate, though incomplete. + </p></div></div><div class="sect1" title="Message Protocol"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="message-protocol"></a>Message Protocol</h2></div></div></div><p> + A <em class="firstterm">message</em> consists of a + <em class="firstterm">header</em> and a <em class="firstterm">body</em>. 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. + </p><p> + The body of the message is made up of zero or more + <em class="firstterm">arguments</em>, which are typed values, such as an + integer or a byte array. + </p><p> + Both header and body use the same type system and format for + serializing data. Each type of value has a wire format. + Converting a value from some other representation into the wire + format is called <em class="firstterm">marshaling</em> and converting + it back from the wire format is <em class="firstterm">unmarshaling</em>. + </p><div class="sect2" title="Type Signatures"><div class="titlepage"><div><div><h3 class="title"><a name="message-protocol-signatures"></a>Type Signatures</h3></div></div></div><p> + The D-Bus protocol does not include type tags in the marshaled data; a + block of marshaled values must have a known <em class="firstterm">type + signature</em>. The type signature is made up of <em class="firstterm">type + codes</em>. A type code is an ASCII character representing the + type of a value. Because ASCII characters are used, the type signature + will always form a valid ASCII string. A simple string compare + determines whether two type signatures are equivalent. + </p><p> + As a simple example, the type code for 32-bit integer (<code class="literal">INT32</code>) is + the ASCII character 'i'. So the signature for a block of values + containing a single <code class="literal">INT32</code> would be: + </p><pre class="programlisting"> + "i" + </pre><p> + A block of values containing two <code class="literal">INT32</code> would have this signature: + </p><pre class="programlisting"> + "ii" + </pre><p> + </p><p> + All <em class="firstterm">basic</em> types work like + <code class="literal">INT32</code> in this example. To marshal and unmarshal + basic types, you simply read one value from the data + block corresponding to each type code in the signature. + In addition to basic types, there are four <em class="firstterm">container</em> + types: <code class="literal">STRUCT</code>, <code class="literal">ARRAY</code>, <code class="literal">VARIANT</code>, + and <code class="literal">DICT_ENTRY</code>. + </p><p> + <code class="literal">STRUCT</code> has a type code, ASCII character 'r', but this type + code does not appear in signatures. Instead, ASCII characters + '(' and ')' are used to mark the beginning and end of the struct. + So for example, a struct containing two integers would have this + signature: + </p><pre class="programlisting"> + "(ii)" + </pre><p> + Structs can be nested, so for example a struct containing + an integer and another struct: + </p><pre class="programlisting"> + "(i(ii))" + </pre><p> + The value block storing that struct would contain three integers; the + type signature allows you to distinguish "(i(ii))" from "((ii)i)" or + "(iii)" or "iii". + </p><p> + The <code class="literal">STRUCT</code> type code 'r' is not currently used in the D-Bus protocol, + but is useful in code that implements the protocol. This type code + is specified to allow such code to interoperate in non-protocol contexts. + </p><p> + Empty structures are not allowed; there must be at least one + type code between the parentheses. + </p><p> + <code class="literal">ARRAY</code> has ASCII character 'a' as type code. The array type code must be + followed by a <em class="firstterm">single complete type</em>. The single + complete type following the array is the type of each array element. So + the simple example is: + </p><pre class="programlisting"> + "ai" + </pre><p> + which is an array of 32-bit integers. But an array can be of any type, + such as this array-of-struct-with-two-int32-fields: + </p><pre class="programlisting"> + "a(ii)" + </pre><p> + Or this array of array of integer: + </p><pre class="programlisting"> + "aai" + </pre><p> + </p><p> + The phrase <em class="firstterm">single complete type</em> deserves some + definition. A single complete type is a basic type code, a variant type code, + an array with its element type, or a struct with its fields. + So the following signatures are not single complete types: + </p><pre class="programlisting"> + "aa" + </pre><p> + </p><pre class="programlisting"> + "(ii" + </pre><p> + </p><pre class="programlisting"> + "ii)" + </pre><p> + And the following signatures contain multiple complete types: + </p><pre class="programlisting"> + "ii" + </pre><p> + </p><pre class="programlisting"> + "aiai" + </pre><p> + </p><pre class="programlisting"> + "(ii)(ii)" + </pre><p> + Note however that a single complete type may <span class="emphasis"><em>contain</em></span> + multiple other single complete types. + </p><p> + <code class="literal">VARIANT</code> has ASCII character 'v' as its type code. A marshaled value of + type <code class="literal">VARIANT</code> will have the signature of a single complete type as part + of the <span class="emphasis"><em>value</em></span>. This signature will be followed by a + marshaled value of that type. + </p><p> + A <code class="literal">DICT_ENTRY</code> works exactly like a struct, but rather + than parentheses it uses curly braces, and it has more restrictions. + The restrictions are: it occurs only as an array element type; it has + exactly two single complete types inside the curly braces; the first + single complete type (the "key") must be a basic type rather than a + container type. Implementations must not accept dict entries outside of + arrays, must not accept dict entries with zero, one, or more than two + fields, and must not accept dict entries with non-basic-typed keys. A + dict entry is always a key-value pair. + </p><p> + The first field in the <code class="literal">DICT_ENTRY</code> is always the key. + A message is considered corrupt if the same key occurs twice in the same + array of <code class="literal">DICT_ENTRY</code>. However, for performance reasons + implementations are not required to reject dicts with duplicate keys. + </p><p> + In most languages, an array of dict entry would be represented as a + map, hash table, or dict object. + </p><p> + The following table summarizes the D-Bus types. + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Conventional Name</th><th>Code</th><th>Description</th></tr></thead><tbody><tr><td><code class="literal">INVALID</code></td><td>0 (ASCII NUL)</td><td>Not a valid type code, used to terminate signatures</td></tr><tr><td><code class="literal">BYTE</code></td><td>121 (ASCII 'y')</td><td>8-bit unsigned integer</td></tr><tr><td><code class="literal">BOOLEAN</code></td><td>98 (ASCII 'b')</td><td>Boolean value, 0 is <code class="literal">FALSE</code> and 1 is <code class="literal">TRUE</code>. Everything else is invalid.</td></tr><tr><td><code class="literal">INT16</code></td><td>110 (ASCII 'n')</td><td>16-bit signed integer</td></tr><tr><td><code class="literal">UINT16</code></td><td>113 (ASCII 'q')</td><td>16-bit unsigned integer</td></tr><tr><td><code class="literal">INT32</code></td><td>105 (ASCII 'i')</td><td>32-bit signed integer</td></tr><tr><td><code class="literal">UINT32</code></td><td>117 (ASCII 'u')</td><td>32-bit unsigned integer</td></tr><tr><td><code class="literal">INT64</code></td><td>120 (ASCII 'x')</td><td>64-bit signed integer</td></tr><tr><td><code class="literal">UINT64</code></td><td>116 (ASCII 't')</td><td>64-bit unsigned integer</td></tr><tr><td><code class="literal">DOUBLE</code></td><td>100 (ASCII 'd')</td><td>IEEE 754 double</td></tr><tr><td><code class="literal">STRING</code></td><td>115 (ASCII 's')</td><td>UTF-8 string (<span class="emphasis"><em>must</em></span> be valid UTF-8). Must be nul terminated and contain no other nul bytes.</td></tr><tr><td><code class="literal">OBJECT_PATH</code></td><td>111 (ASCII 'o')</td><td>Name of an object instance</td></tr><tr><td><code class="literal">SIGNATURE</code></td><td>103 (ASCII 'g')</td><td>A type signature</td></tr><tr><td><code class="literal">ARRAY</code></td><td>97 (ASCII 'a')</td><td>Array</td></tr><tr><td><code class="literal">STRUCT</code></td><td>114 (ASCII 'r'), 40 (ASCII '('), 41 (ASCII ')')</td><td>Struct</td></tr><tr><td><code class="literal">VARIANT</code></td><td>118 (ASCII 'v') </td><td>Variant type (the type of the value is part of the value itself)</td></tr><tr><td><code class="literal">DICT_ENTRY</code></td><td>101 (ASCII 'e'), 123 (ASCII '{'), 125 (ASCII '}') </td><td>Entry in a dict or map (array of key-value pairs)</td></tr></tbody></table></div><p> + </p></div><div class="sect2" title="Marshaling (Wire Format)"><div class="titlepage"><div><div><h3 class="title"><a name="message-protocol-marshaling"></a>Marshaling (Wire Format)</h3></div></div></div><p> + Given a type signature, a block of bytes can be converted into typed + values. This section describes the format of the block of bytes. Byte + order and alignment issues are handled uniformly for all D-Bus types. + </p><p> + A block of bytes has an associated byte order. The byte order + has to be discovered in some way; for D-Bus messages, the + byte order is part of the message header as described in + <a class="xref" href="#message-protocol-messages" title="Message Format">the section called “Message Format”</a>. For now, assume + that the byte order is known to be either little endian or big + endian. + </p><p> + Each value in a block of bytes is aligned "naturally," for example + 4-byte values are aligned to a 4-byte boundary, and 8-byte values to an + 8-byte boundary. To properly align a value, <em class="firstterm">alignment + padding</em> may be necessary. The alignment padding must always + be the minimum required padding to properly align the following value; + and it must always be made up of nul bytes. The alignment padding must + not be left uninitialized (it can't contain garbage), and more padding + than required must not be used. + </p><p> + Given all this, the types are marshaled on the wire as follows: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Conventional Name</th><th>Encoding</th><th>Alignment</th></tr></thead><tbody><tr><td><code class="literal">INVALID</code></td><td>Not applicable; cannot be marshaled.</td><td>N/A</td></tr><tr><td><code class="literal">BYTE</code></td><td>A single 8-bit byte.</td><td>1</td></tr><tr><td><code class="literal">BOOLEAN</code></td><td>As for <code class="literal">UINT32</code>, but only 0 and 1 are valid values.</td><td>4</td></tr><tr><td><code class="literal">INT16</code></td><td>16-bit signed integer in the message's byte order.</td><td>2</td></tr><tr><td><code class="literal">UINT16</code></td><td>16-bit unsigned integer in the message's byte order.</td><td>2</td></tr><tr><td><code class="literal">INT32</code></td><td>32-bit signed integer in the message's byte order.</td><td>4</td></tr><tr><td><code class="literal">UINT32</code></td><td>32-bit unsigned integer in the message's byte order.</td><td>4</td></tr><tr><td><code class="literal">INT64</code></td><td>64-bit signed integer in the message's byte order.</td><td>8</td></tr><tr><td><code class="literal">UINT64</code></td><td>64-bit unsigned integer in the message's byte order.</td><td>8</td></tr><tr><td><code class="literal">DOUBLE</code></td><td>64-bit IEEE 754 double in the message's byte order.</td><td>8</td></tr><tr><td><code class="literal">STRING</code></td><td>A <code class="literal">UINT32</code> indicating the string's + length in bytes excluding its terminating nul, followed by + non-nul string data of the given length, followed by a terminating nul + byte. + </td><td> + 4 (for the length) + </td></tr><tr><td><code class="literal">OBJECT_PATH</code></td><td>Exactly the same as <code class="literal">STRING</code> except the + content must be a valid object path (see below). + </td><td> + 4 (for the length) + </td></tr><tr><td><code class="literal">SIGNATURE</code></td><td>The same as <code class="literal">STRING</code> except the length is a single + byte (thus signatures have a maximum length of 255) + and the content must be a valid signature (see below). + </td><td> + 1 + </td></tr><tr><td><code class="literal">ARRAY</code></td><td> + A <code class="literal">UINT32</code> giving the length of the array data in bytes, followed by + alignment padding to the alignment boundary of the array element type, + followed by each array element. The array length is from the + end of the alignment padding to the end of the last element, + i.e. it does not include the padding after the length, + or any padding after the last element. + Arrays have a maximum length defined to be 2 to the 26th power or + 67108864. Implementations must not send or accept arrays exceeding this + length. + </td><td> + 4 (for the length) + </td></tr><tr><td><code class="literal">STRUCT</code></td><td> + A struct must start on an 8-byte boundary regardless of the + type of the struct fields. The struct value consists of each + field marshaled in sequence starting from that 8-byte + alignment boundary. + </td><td> + 8 + </td></tr><tr><td><code class="literal">VARIANT</code></td><td> + A variant type has a marshaled <code class="literal">SIGNATURE</code> + followed by a marshaled value with the type + given in the signature. + Unlike a message signature, the variant signature + can contain only a single complete type. + So "i", "ai" or "(ii)" is OK, but "ii" is not. + </td><td> + 1 (alignment of the signature) + </td></tr><tr><td><code class="literal">DICT_ENTRY</code></td><td> + Identical to STRUCT. + </td><td> + 8 + </td></tr></tbody></table></div><p> + </p><div class="sect3" title="Valid Object Paths"><div class="titlepage"><div><div><h4 class="title"><a name="message-protocol-marshaling-object-path"></a>Valid Object Paths</h4></div></div></div><p> + An object path is a name used to refer to an object instance. + Conceptually, each participant in a D-Bus message exchange may have + any number of object instances (think of C++ or Java objects) and each + such instance will have a path. Like a filesystem, the object + instances in an application form a hierarchical tree. + </p><p> + The following rules define a valid object path. Implementations must + not send or accept messages with invalid object paths. + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + The path may be of any length. + </p></li><li class="listitem"><p> + The path must begin with an ASCII '/' (integer 47) character, + and must consist of elements separated by slash characters. + </p></li><li class="listitem"><p> + Each element must only contain the ASCII characters + "[A-Z][a-z][0-9]_" + </p></li><li class="listitem"><p> + No element may be the empty string. + </p></li><li class="listitem"><p> + Multiple '/' characters cannot occur in sequence. + </p></li><li class="listitem"><p> + A trailing '/' character is not allowed unless the + path is the root path (a single '/' character). + </p></li></ul></div><p> + </p></div><div class="sect3" title="Valid Signatures"><div class="titlepage"><div><div><h4 class="title"><a name="message-protocol-marshaling-signature"></a>Valid Signatures</h4></div></div></div><p> + An implementation must not send or accept invalid signatures. + Valid signatures will conform to the following rules: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + The signature ends with a nul byte. + </p></li><li class="listitem"><p> + The signature is a list of single complete types. + Arrays must have element types, and structs must + have both open and close parentheses. + </p></li><li class="listitem"><p> + Only type codes and open and close parentheses are + allowed in the signature. The <code class="literal">STRUCT</code> type code + is not allowed in signatures, because parentheses + are used instead. + </p></li><li class="listitem"><p> + The maximum depth of container type nesting is 32 array type + codes and 32 open parentheses. This implies that the maximum + total depth of recursion is 64, for an "array of array of array + of ... struct of struct of struct of ..." where there are 32 + array and 32 struct. + </p></li><li class="listitem"><p> + The maximum length of a signature is 255. + </p></li><li class="listitem"><p> + Signatures must be nul-terminated. + </p></li></ul></div><p> + </p></div></div><div class="sect2" title="Message Format"><div class="titlepage"><div><div><h3 class="title"><a name="message-protocol-messages"></a>Message Format</h3></div></div></div><p> + A message consists of a header and a body. The header is a block of + values with a fixed signature and meaning. The body is a separate block + of values, with a signature specified in the header. + </p><p> + The length of the header must be a multiple of 8, allowing the body to + begin on an 8-byte boundary when storing the entire message in a single + buffer. If the header does not naturally end on an 8-byte boundary + up to 7 bytes of nul-initialized alignment padding must be added. + </p><p> + The message body need not end on an 8-byte boundary. + </p><p> + The maximum length of a message, including header, header alignment padding, + and body is 2 to the 27th power or 134217728. Implementations must not + send or accept messages exceeding this size. + </p><p> + The signature of the header is: + </p><pre class="programlisting"> + "yyyyuua(yv)" + </pre><p> + Written out more readably, this is: + </p><pre class="programlisting"> + BYTE, BYTE, BYTE, BYTE, UINT32, UINT32, ARRAY of STRUCT of (BYTE,VARIANT) + </pre><p> + </p><p> + These values have the following meanings: + </p><div class="informaltable"><table border="1"><colgroup><col><col></colgroup><thead><tr><th>Value</th><th>Description</th></tr></thead><tbody><tr><td>1st <code class="literal">BYTE</code></td><td>Endianness flag; ASCII 'l' for little-endian + or ASCII 'B' for big-endian. Both header and body are + in this endianness.</td></tr><tr><td>2nd <code class="literal">BYTE</code></td><td><em class="firstterm">Message type</em>. Unknown types must be ignored. + Currently-defined types are described below. + </td></tr><tr><td>3rd <code class="literal">BYTE</code></td><td>Bitwise OR of flags. Unknown flags + must be ignored. Currently-defined flags are described below. + </td></tr><tr><td>4th <code class="literal">BYTE</code></td><td>Major protocol version of the sending application. If + the major protocol version of the receiving application does not + match, the applications will not be able to communicate and the + D-Bus connection must be disconnected. The major protocol + version for this version of the specification is 1. + </td></tr><tr><td>1st <code class="literal">UINT32</code></td><td>Length in bytes of the message body, starting + from the end of the header. The header ends after + its alignment padding to an 8-boundary. + </td></tr><tr><td>2nd <code class="literal">UINT32</code></td><td>The serial of this message, used as a cookie + by the sender to identify the reply corresponding + to this request. This must not be zero. + </td></tr><tr><td><code class="literal">ARRAY</code> of <code class="literal">STRUCT</code> of (<code class="literal">BYTE</code>,<code class="literal">VARIANT</code>)</td><td>An array of zero or more <em class="firstterm">header + fields</em> where the byte is the field code, and the + variant is the field value. The message type determines + which fields are required. + </td></tr></tbody></table></div><p> + </p><p> + <em class="firstterm">Message types</em> that can appear in the second byte + of the header are: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Conventional name</th><th>Decimal value</th><th>Description</th></tr></thead><tbody><tr><td><code class="literal">INVALID</code></td><td>0</td><td>This is an invalid type.</td></tr><tr><td><code class="literal">METHOD_CALL</code></td><td>1</td><td>Method call.</td></tr><tr><td><code class="literal">METHOD_RETURN</code></td><td>2</td><td>Method reply with returned data.</td></tr><tr><td><code class="literal">ERROR</code></td><td>3</td><td>Error reply. If the first argument exists and is a + string, it is an error message.</td></tr><tr><td><code class="literal">SIGNAL</code></td><td>4</td><td>Signal emission.</td></tr></tbody></table></div><p> + </p><p> + Flags that can appear in the third byte of the header: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Conventional name</th><th>Hex value</th><th>Description</th></tr></thead><tbody><tr><td><code class="literal">NO_REPLY_EXPECTED</code></td><td>0x1</td><td>This message does not expect method return replies or + error replies; the reply can be omitted as an + optimization. However, it is compliant with this specification + to return the reply despite this flag and the only harm + from doing so is extra network traffic. + </td></tr><tr><td><code class="literal">NO_AUTO_START</code></td><td>0x2</td><td>The bus must not launch an owner + for the destination name in response to this message. + </td></tr></tbody></table></div><p> + </p><div class="sect3" title="Header Fields"><div class="titlepage"><div><div><h4 class="title"><a name="message-protocol-header-fields"></a>Header Fields</h4></div></div></div><p> + The array at the end of the header contains <em class="firstterm">header + fields</em>, where each field is a 1-byte field code followed + by a field value. A header must contain the required header fields for + its message type, and zero or more of any optional header + fields. Future versions of this protocol specification may add new + fields. Implementations must ignore fields they do not + understand. Implementations must not invent their own header fields; + only changes to this specification may introduce new header fields. + </p><p> + Again, if an implementation sees a header field code that it does not + expect, it must ignore that field, as it will be part of a new + (but compatible) version of this specification. This also applies + to known header fields appearing in unexpected messages, for + example: if a signal has a reply serial it must be ignored + even though it has no meaning as of this version of the spec. + </p><p> + However, implementations must not send or accept known header fields + with the wrong type stored in the field value. So for example a + message with an <code class="literal">INTERFACE</code> field of type + <code class="literal">UINT32</code> would be considered corrupt. + </p><p> + Here are the currently-defined header fields: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col><col><col></colgroup><thead><tr><th>Conventional Name</th><th>Decimal Code</th><th>Type</th><th>Required In</th><th>Description</th></tr></thead><tbody><tr><td><code class="literal">INVALID</code></td><td>0</td><td>N/A</td><td>not allowed</td><td>Not a valid field name (error if it appears in a message)</td></tr><tr><td><code class="literal">PATH</code></td><td>1</td><td><code class="literal">OBJECT_PATH</code></td><td><code class="literal">METHOD_CALL</code>, <code class="literal">SIGNAL</code></td><td>The object to send a call to, + or the object a signal is emitted from. + The special path + <code class="literal">/org/freedesktop/DBus/Local</code> is reserved; + implementations should not send messages with this path, + and the reference implementation of the bus daemon will + disconnect any application that attempts to do so. + </td></tr><tr><td><code class="literal">INTERFACE</code></td><td>2</td><td><code class="literal">STRING</code></td><td><code class="literal">SIGNAL</code></td><td> + The interface to invoke a method call on, or + that a signal is emitted from. Optional for + method calls, required for signals. + The special interface + <code class="literal">org.freedesktop.DBus.Local</code> is reserved; + implementations should not send messages with this + interface, and the reference implementation of the bus + daemon will disconnect any application that attempts to + do so. + </td></tr><tr><td><code class="literal">MEMBER</code></td><td>3</td><td><code class="literal">STRING</code></td><td><code class="literal">METHOD_CALL</code>, <code class="literal">SIGNAL</code></td><td>The member, either the method name or signal name.</td></tr><tr><td><code class="literal">ERROR_NAME</code></td><td>4</td><td><code class="literal">STRING</code></td><td><code class="literal">ERROR</code></td><td>The name of the error that occurred, for errors</td></tr><tr><td><code class="literal">REPLY_SERIAL</code></td><td>5</td><td><code class="literal">UINT32</code></td><td><code class="literal">ERROR</code>, <code class="literal">METHOD_RETURN</code></td><td>The serial number of the message this message is a reply + to. (The serial number is the second <code class="literal">UINT32</code> in the header.)</td></tr><tr><td><code class="literal">DESTINATION</code></td><td>6</td><td><code class="literal">STRING</code></td><td>optional</td><td>The name of the connection this message is intended for. + Only used in combination with the message bus, see + <a class="xref" href="#message-bus" title="Message Bus Specification">the section called “Message Bus Specification”</a>.</td></tr><tr><td><code class="literal">SENDER</code></td><td>7</td><td><code class="literal">STRING</code></td><td>optional</td><td>Unique name of the sending connection. + The message bus fills in this field so it is reliable; the field is + only meaningful in combination with the message bus.</td></tr><tr><td><code class="literal">SIGNATURE</code></td><td>8</td><td><code class="literal">SIGNATURE</code></td><td>optional</td><td>The signature of the message body. + If omitted, it is assumed to be the + empty signature "" (i.e. the body must be 0-length).</td></tr></tbody></table></div><p> + </p></div></div><div class="sect2" title="Valid Names"><div class="titlepage"><div><div><h3 class="title"><a name="message-protocol-names"></a>Valid Names</h3></div></div></div><p> + The various names in D-Bus messages have some restrictions. + </p><p> + There is a <em class="firstterm">maximum name length</em> + of 255 which applies to bus names, interfaces, and members. + </p><div class="sect3" title="Interface names"><div class="titlepage"><div><div><h4 class="title"><a name="message-protocol-names-interface"></a>Interface names</h4></div></div></div><p> + Interfaces have names with type <code class="literal">STRING</code>, meaning that + they must be valid UTF-8. However, there are also some + additional restrictions that apply to interface names + specifically: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>Interface names are composed of 1 or more elements separated by + a period ('.') character. All elements must contain at least + one character. + </p></li><li class="listitem"><p>Each element must only contain the ASCII characters + "[A-Z][a-z][0-9]_" and must not begin with a digit. + </p></li><li class="listitem"><p>Interface names must contain at least one '.' (period) + character (and thus at least two elements). + </p></li><li class="listitem"><p>Interface names must not begin with a '.' (period) character.</p></li><li class="listitem"><p>Interface names must not exceed the maximum name length.</p></li></ul></div><p> + </p></div><div class="sect3" title="Bus names"><div class="titlepage"><div><div><h4 class="title"><a name="message-protocol-names-bus"></a>Bus names</h4></div></div></div><p> + Connections have one or more bus names associated with them. + A connection has exactly one bus name that is a unique connection + name. The unique connection name remains with the connection for + its entire lifetime. + A bus name is of type <code class="literal">STRING</code>, + meaning that it must be valid UTF-8. However, there are also + some additional restrictions that apply to bus names + specifically: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>Bus names that start with a colon (':') + character are unique connection names. + </p></li><li class="listitem"><p>Bus names are composed of 1 or more elements separated by + a period ('.') character. All elements must contain at least + one character. + </p></li><li class="listitem"><p>Each element must only contain the ASCII characters + "[A-Z][a-z][0-9]_-". Only elements that are part of a unique + connection name may begin with a digit, elements in + other bus names must not begin with a digit. + </p></li><li class="listitem"><p>Bus names must contain at least one '.' (period) + character (and thus at least two elements). + </p></li><li class="listitem"><p>Bus names must not begin with a '.' (period) character.</p></li><li class="listitem"><p>Bus names must not exceed the maximum name length.</p></li></ul></div><p> + </p><p> + Note that the hyphen ('-') character is allowed in bus names but + not in interface names. + </p></div><div class="sect3" title="Member names"><div class="titlepage"><div><div><h4 class="title"><a name="message-protocol-names-member"></a>Member names</h4></div></div></div><p> + Member (i.e. method or signal) names: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>Must only contain the ASCII characters + "[A-Z][a-z][0-9]_" and may not begin with a + digit.</p></li><li class="listitem"><p>Must not contain the '.' (period) character.</p></li><li class="listitem"><p>Must not exceed the maximum name length.</p></li><li class="listitem"><p>Must be at least 1 byte in length.</p></li></ul></div><p> + </p></div><div class="sect3" title="Error names"><div class="titlepage"><div><div><h4 class="title"><a name="message-protocol-names-error"></a>Error names</h4></div></div></div><p> + Error names have the same restrictions as interface names. + </p></div></div><div class="sect2" title="Message Types"><div class="titlepage"><div><div><h3 class="title"><a name="message-protocol-types"></a>Message Types</h3></div></div></div><p> + Each of the message types (<code class="literal">METHOD_CALL</code>, <code class="literal">METHOD_RETURN</code>, <code class="literal">ERROR</code>, and + <code class="literal">SIGNAL</code>) has its own expected usage conventions and header fields. + This section describes these conventions. + </p><div class="sect3" title="Method Calls"><div class="titlepage"><div><div><h4 class="title"><a name="message-protocol-types-method"></a>Method Calls</h4></div></div></div><p> + Some messages invoke an operation on a remote object. These are + called method call messages and have the type tag <code class="literal">METHOD_CALL</code>. Such + messages map naturally to methods on objects in a typical program. + </p><p> + A method call message is required to have a <code class="literal">MEMBER</code> header field + indicating the name of the method. Optionally, the message has an + <code class="literal">INTERFACE</code> field giving the interface the method is a part of. In the + absence of an <code class="literal">INTERFACE</code> field, if two interfaces on the same object have + a method with the same name, it is undefined which of the two methods + will be invoked. Implementations may also choose to return an error in + this ambiguous case. However, if a method name is unique + implementations must not require an interface field. + </p><p> + Method call messages also include a <code class="literal">PATH</code> field + indicating the object to invoke the method on. If the call is passing + through a message bus, the message will also have a + <code class="literal">DESTINATION</code> field giving the name of the connection + to receive the message. + </p><p> + When an application handles a method call message, it is required to + return a reply. The reply is identified by a <code class="literal">REPLY_SERIAL</code> header field + indicating the serial number of the <code class="literal">METHOD_CALL</code> being replied to. The + reply can have one of two types; either <code class="literal">METHOD_RETURN</code> or <code class="literal">ERROR</code>. + </p><p> + If the reply has type <code class="literal">METHOD_RETURN</code>, the arguments to the reply message + are the return value(s) or "out parameters" of the method call. + If the reply has type <code class="literal">ERROR</code>, then an "exception" has been thrown, + and the call fails; no return value will be provided. It makes + no sense to send multiple replies to the same method call. + </p><p> + Even if a method call has no return values, a <code class="literal">METHOD_RETURN</code> + reply is required, so the caller will know the method + was successfully processed. + </p><p> + The <code class="literal">METHOD_RETURN</code> or <code class="literal">ERROR</code> reply message must have the <code class="literal">REPLY_SERIAL</code> + header field. + </p><p> + If a <code class="literal">METHOD_CALL</code> message has the flag <code class="literal">NO_REPLY_EXPECTED</code>, + then as an optimization the application receiving the method + call may choose to omit the reply message (regardless of + whether the reply would have been <code class="literal">METHOD_RETURN</code> or <code class="literal">ERROR</code>). + However, it is also acceptable to ignore the <code class="literal">NO_REPLY_EXPECTED</code> + flag and reply anyway. + </p><p> + Unless a message has the flag <code class="literal">NO_AUTO_START</code>, if the + destination name does not exist then a program to own the destination + name will be started before the message is delivered. The message + will be held until the new program is successfully started or has + failed to start; in case of failure, an error will be returned. This + flag is only relevant in the context of a message bus, it is ignored + during one-to-one communication with no intermediate bus. + </p><div class="sect4" title="Mapping method calls to native APIs"><div class="titlepage"><div><div><h5 class="title"><a name="message-protocol-types-method-apis"></a>Mapping method calls to native APIs</h5></div></div></div><p> + APIs for D-Bus may map method calls to a method call in a specific + programming language, such as C++, or may map a method call written + in an IDL to a D-Bus message. + </p><p> + In APIs of this nature, arguments to a method are often termed "in" + (which implies sent in the <code class="literal">METHOD_CALL</code>), or "out" (which implies + returned in the <code class="literal">METHOD_RETURN</code>). Some APIs such as CORBA also have + "inout" arguments, which are both sent and received, i.e. the caller + passes in a value which is modified. Mapped to D-Bus, an "inout" + argument is equivalent to an "in" argument, followed by an "out" + argument. You can't pass things "by reference" over the wire, so + "inout" is purely an illusion of the in-process API. + </p><p> + Given a method with zero or one return values, followed by zero or more + arguments, where each argument may be "in", "out", or "inout", the + caller constructs a message by appending each "in" or "inout" argument, + in order. "out" arguments are not represented in the caller's message. + </p><p> + The recipient constructs a reply by appending first the return value + if any, then each "out" or "inout" argument, in order. + "in" arguments are not represented in the reply message. + </p><p> + Error replies are normally mapped to exceptions in languages that have + exceptions. + </p><p> + In converting from native APIs to D-Bus, it is perhaps nice to + map D-Bus naming conventions ("FooBar") to native conventions + such as "fooBar" or "foo_bar" automatically. This is OK + as long as you can say that the native API is one that + was specifically written for D-Bus. It makes the most sense + when writing object implementations that will be exported + over the bus. Object proxies used to invoke remote D-Bus + objects probably need the ability to call any D-Bus method, + and thus a magic name mapping like this could be a problem. + </p><p> + This specification doesn't require anything of native API bindings; + the preceding is only a suggested convention for consistency + among bindings. + </p></div></div><div class="sect3" title="Signal Emission"><div class="titlepage"><div><div><h4 class="title"><a name="message-protocol-types-signal"></a>Signal Emission</h4></div></div></div><p> + Unlike method calls, signal emissions have no replies. + A signal emission is simply a single message of type <code class="literal">SIGNAL</code>. + It must have three header fields: <code class="literal">PATH</code> giving the object + the signal was emitted from, plus <code class="literal">INTERFACE</code> and <code class="literal">MEMBER</code> giving + the fully-qualified name of the signal. The <code class="literal">INTERFACE</code> header is required + for signals, though it is optional for method calls. + </p></div><div class="sect3" title="Errors"><div class="titlepage"><div><div><h4 class="title"><a name="message-protocol-types-errors"></a>Errors</h4></div></div></div><p> + Messages of type <code class="literal">ERROR</code> are most commonly replies + to a <code class="literal">METHOD_CALL</code>, but may be returned in reply + to any kind of message. The message bus for example + will return an <code class="literal">ERROR</code> in reply to a signal emission if + the bus does not have enough memory to send the signal. + </p><p> + An <code class="literal">ERROR</code> may have any arguments, but if the first + argument is a <code class="literal">STRING</code>, it must be an error message. + The error message may be logged or shown to the user + in some way. + </p></div><div class="sect3" title="Notation in this document"><div class="titlepage"><div><div><h4 class="title"><a name="message-protocol-types-notation"></a>Notation in this document</h4></div></div></div><p> + This document uses a simple pseudo-IDL to describe particular method + calls and signals. Here is an example of a method call: + </p><pre class="programlisting"> + org.freedesktop.DBus.StartServiceByName (in STRING name, in UINT32 flags, + out UINT32 resultcode) + </pre><p> + This means <code class="literal">INTERFACE</code> = org.freedesktop.DBus, <code class="literal">MEMBER</code> = StartServiceByName, + <code class="literal">METHOD_CALL</code> arguments are <code class="literal">STRING</code> and <code class="literal">UINT32</code>, <code class="literal">METHOD_RETURN</code> argument + is <code class="literal">UINT32</code>. Remember that the <code class="literal">MEMBER</code> field can't contain any '.' (period) + characters so it's known that the last part of the name in + the "IDL" is the member name. + </p><p> + In C++ that might end up looking like this: + </p><pre class="programlisting"> + unsigned int org::freedesktop::DBus::StartServiceByName (const char *name, + unsigned int flags); + </pre><p> + or equally valid, the return value could be done as an argument: + </p><pre class="programlisting"> + void org::freedesktop::DBus::StartServiceByName (const char *name, + unsigned int flags, + unsigned int *resultcode); + </pre><p> + It's really up to the API designer how they want to make + this look. You could design an API where the namespace wasn't used + in C++, using STL or Qt, using varargs, or whatever you wanted. + </p><p> + Signals are written as follows: + </p><pre class="programlisting"> + org.freedesktop.DBus.NameLost (STRING name) + </pre><p> + Signals don't specify "in" vs. "out" because only + a single direction is possible. + </p><p> + It isn't especially encouraged to use this lame pseudo-IDL in actual + API implementations; you might use the native notation for the + language you're using, or you might use COM or CORBA IDL, for example. + </p></div></div><div class="sect2" title="Invalid Protocol and Spec Extensions"><div class="titlepage"><div><div><h3 class="title"><a name="message-protocol-handling-invalid"></a>Invalid Protocol and Spec Extensions</h3></div></div></div><p> + For security reasons, the D-Bus protocol should be strictly parsed and + validated, with the exception of defined extension points. Any invalid + protocol or spec violations should result in immediately dropping the + connection without notice to the other end. Exceptions should be + carefully considered, e.g. an exception may be warranted for a + well-understood idiosyncrasy of a widely-deployed implementation. In + cases where the other end of a connection is 100% trusted and known to + be friendly, skipping validation for performance reasons could also make + sense in certain cases. + </p><p> + Generally speaking violations of the "must" requirements in this spec + should be considered possible attempts to exploit security, and violations + of the "should" suggestions should be considered legitimate (though perhaps + they should generate an error in some cases). + </p><p> + The following extension points are built in to D-Bus on purpose and must + not be treated as invalid protocol. The extension points are intended + for use by future versions of this spec, they are not intended for third + parties. At the moment, the only way a third party could extend D-Bus + without breaking interoperability would be to introduce a way to negotiate new + feature support as part of the auth protocol, using EXTENSION_-prefixed + commands. There is not yet a standard way to negotiate features. + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + In the authentication protocol (see <a class="xref" href="#auth-protocol" title="Authentication Protocol">the section called “Authentication Protocol”</a>) unknown + commands result in an ERROR rather than a disconnect. This enables + future extensions to the protocol. Commands starting with EXTENSION_ are + reserved for third parties. + </p></li><li class="listitem"><p> + The authentication protocol supports pluggable auth mechanisms. + </p></li><li class="listitem"><p> + The address format (see <a class="xref" href="#addresses" title="Server Addresses">the section called “Server Addresses”</a>) supports new + kinds of transport. + </p></li><li class="listitem"><p> + Messages with an unknown type (something other than + <code class="literal">METHOD_CALL</code>, <code class="literal">METHOD_RETURN</code>, + <code class="literal">ERROR</code>, <code class="literal">SIGNAL</code>) are ignored. + Unknown-type messages must still be well-formed in the same way + as the known messages, however. They still have the normal + header and body. + </p></li><li class="listitem"><p> + Header fields with an unknown or unexpected field code must be ignored, + though again they must still be well-formed. + </p></li><li class="listitem"><p> + New standard interfaces (with new methods and signals) can of course be added. + </p></li></ul></div><p> + </p></div></div><div class="sect1" title="Authentication Protocol"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="auth-protocol"></a>Authentication Protocol</h2></div></div></div><p> + Before the flow of messages begins, two applications must + authenticate. A simple plain-text protocol is used for + authentication; this protocol is a SASL profile, and maps fairly + directly from the SASL specification. The message encoding is + NOT used here, only plain text messages. + </p><p> + In examples, "C:" and "S:" indicate lines sent by the client and + server respectively. + </p><div class="sect2" title="Protocol Overview"><div class="titlepage"><div><div><h3 class="title"><a name="auth-protocol-overview"></a>Protocol Overview</h3></div></div></div><p> + The protocol is a line-based protocol, where each line ends with + \r\n. Each line begins with an all-caps ASCII command name containing + only the character range [A-Z_], a space, then any arguments for the + command, then the \r\n ending the line. The protocol is + case-sensitive. All bytes must be in the ASCII character set. + + Commands from the client to the server are as follows: + + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>AUTH [mechanism] [initial-response]</p></li><li class="listitem"><p>CANCEL</p></li><li class="listitem"><p>BEGIN</p></li><li class="listitem"><p>DATA <data in hex encoding></p></li><li class="listitem"><p>ERROR [human-readable error explanation]</p></li></ul></div><p> + + From server to client are as follows: + + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p>REJECTED <space-separated list of mechanism names></p></li><li class="listitem"><p>OK <GUID in hex></p></li><li class="listitem"><p>DATA <data in hex encoding></p></li><li class="listitem"><p>ERROR</p></li></ul></div><p> + </p><p> + Unofficial extensions to the command set must begin with the letters + "EXTENSION_", to avoid conflicts with future official commands. + For example, "EXTENSION_COM_MYDOMAIN_DO_STUFF". + </p></div><div class="sect2" title="Special credentials-passing nul byte"><div class="titlepage"><div><div><h3 class="title"><a name="auth-nul-byte"></a>Special credentials-passing nul byte</h3></div></div></div><p> + Immediately after connecting to the server, the client must send a + single nul byte. This byte may be accompanied by credentials + information on some operating systems that use sendmsg() with + SCM_CREDS or SCM_CREDENTIALS to pass credentials over UNIX domain + sockets. However, the nul byte must be sent even on other kinds of + socket, and even on operating systems that do not require a byte to be + sent in order to transmit credentials. The text protocol described in + this document begins after the single nul byte. If the first byte + received from the client is not a nul byte, the server may disconnect + that client. + </p><p> + A nul byte in any context other than the initial byte is an error; + the protocol is ASCII-only. + </p><p> + The credentials sent along with the nul byte may be used with the + SASL mechanism EXTERNAL. + </p></div><div class="sect2" title="AUTH command"><div class="titlepage"><div><div><h3 class="title"><a name="auth-command-auth"></a>AUTH command</h3></div></div></div><p> + If an AUTH command has no arguments, it is a request to list + available mechanisms. The server must respond with a REJECTED + command listing the mechanisms it understands, or with an error. + </p><p> + If an AUTH command specifies a mechanism, and the server supports + said mechanism, the server should begin exchanging SASL + challenge-response data with the client using DATA commands. + </p><p> + If the server does not support the mechanism given in the AUTH + command, it must send either a REJECTED command listing the mechanisms + it does support, or an error. + </p><p> + If the [initial-response] argument is provided, it is intended for use + with mechanisms that have no initial challenge (or an empty initial + challenge), as if it were the argument to an initial DATA command. If + the selected mechanism has an initial challenge and [initial-response] + was provided, the server should reject authentication by sending + REJECTED. + </p><p> + If authentication succeeds after exchanging DATA commands, + an OK command must be sent to the client. + </p><p> + The first octet received by the client after the \r\n of the OK + command must be the first octet of the authenticated/encrypted + stream of D-Bus messages. + </p><p> + The first octet received by the server after the \r\n of the BEGIN + command from the client must be the first octet of the + authenticated/encrypted stream of D-Bus messages. + </p></div><div class="sect2" title="CANCEL Command"><div class="titlepage"><div><div><h3 class="title"><a name="auth-command-cancel"></a>CANCEL Command</h3></div></div></div><p> + At any time up to sending the BEGIN command, the client may send a + CANCEL command. On receiving the CANCEL command, the server must + send a REJECTED command and abort the current authentication + exchange. + </p></div><div class="sect2" title="DATA Command"><div class="titlepage"><div><div><h3 class="title"><a name="auth-command-data"></a>DATA Command</h3></div></div></div><p> + The DATA command may come from either client or server, and simply + contains a hex-encoded block of data to be interpreted + according to the SASL mechanism in use. + </p><p> + Some SASL mechanisms support sending an "empty string"; + FIXME we need some way to do this. + </p></div><div class="sect2" title="BEGIN Command"><div class="titlepage"><div><div><h3 class="title"><a name="auth-command-begin"></a>BEGIN Command</h3></div></div></div><p> + The BEGIN command acknowledges that the client has received an + OK command from the server, and that the stream of messages + is about to begin. + </p><p> + The first octet received by the server after the \r\n of the BEGIN + command from the client must be the first octet of the + authenticated/encrypted stream of D-Bus messages. + </p></div><div class="sect2" title="REJECTED Command"><div class="titlepage"><div><div><h3 class="title"><a name="auth-command-rejected"></a>REJECTED Command</h3></div></div></div><p> + The REJECTED command indicates that the current authentication + exchange has failed, and further exchange of DATA is inappropriate. + The client would normally try another mechanism, or try providing + different responses to challenges. + </p><p> + Optionally, the REJECTED command has a space-separated list of + available auth mechanisms as arguments. If a server ever provides + a list of supported mechanisms, it must provide the same list + each time it sends a REJECTED message. Clients are free to + ignore all lists received after the first. + </p></div><div class="sect2" title="OK Command"><div class="titlepage"><div><div><h3 class="title"><a name="auth-command-ok"></a>OK Command</h3></div></div></div><p> + The OK command indicates that the client has been authenticated, + and that further communication will be a stream of D-Bus messages + (optionally encrypted, as negotiated) rather than this protocol. + </p><p> + The first octet received by the client after the \r\n of the OK + command must be the first octet of the authenticated/encrypted + stream of D-Bus messages. + </p><p> + The client must respond to the OK command by sending a BEGIN + command, followed by its stream of messages, or by disconnecting. + The server must not accept additional commands using this protocol + after the OK command has been sent. + </p><p> + The OK command has one argument, which is the GUID of the server. + See <a class="xref" href="#addresses" title="Server Addresses">the section called “Server Addresses”</a> for more on server GUIDs. + </p></div><div class="sect2" title="ERROR Command"><div class="titlepage"><div><div><h3 class="title"><a name="auth-command-error"></a>ERROR Command</h3></div></div></div><p> + The ERROR command indicates that either server or client did not + know a command, does not accept the given command in the current + context, or did not understand the arguments to the command. This + allows the protocol to be extended; a client or server can send a + command present or permitted only in new protocol versions, and if + an ERROR is received instead of an appropriate response, fall back + to using some other technique. + </p><p> + If an ERROR is sent, the server or client that sent the + error must continue as if the command causing the ERROR had never been + received. However, the the server or client receiving the error + should try something other than whatever caused the error; + if only canceling/rejecting the authentication. + </p><p> + If the D-Bus protocol changes incompatibly at some future time, + applications implementing the new protocol would probably be able to + check for support of the new protocol by sending a new command and + receiving an ERROR from applications that don't understand it. Thus the + ERROR feature of the auth protocol is an escape hatch that lets us + negotiate extensions or changes to the D-Bus protocol in the future. + </p></div><div class="sect2" title="Authentication examples"><div class="titlepage"><div><div><h3 class="title"><a name="auth-examples"></a>Authentication examples</h3></div></div></div><p> + </p><div class="figure"><a name="id320449"></a><p class="title"><b>Figure 1. Example of successful magic cookie authentication</b></p><div class="figure-contents"><pre class="programlisting"> + (MAGIC_COOKIE is a made up mechanism) + + C: AUTH MAGIC_COOKIE 3138363935333137393635383634 + S: OK 1234deadbeef + C: BEGIN + </pre></div></div><p><br class="figure-break"> + </p><div class="figure"><a name="id320464"></a><p class="title"><b>Figure 2. Example of finding out mechanisms then picking one</b></p><div class="figure-contents"><pre class="programlisting"> + C: AUTH + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </pre></div></div><p><br class="figure-break"> + </p><div class="figure"><a name="id320480"></a><p class="title"><b>Figure 3. Example of client sends unknown command then falls back to regular auth</b></p><div class="figure-contents"><pre class="programlisting"> + C: FOOBAR + S: ERROR + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: OK 1234deadbeef + C: BEGIN + </pre></div></div><p><br class="figure-break"> + </p><div class="figure"><a name="id320496"></a><p class="title"><b>Figure 4. Example of server doesn't support initial auth mechanism</b></p><div class="figure-contents"><pre class="programlisting"> + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </pre></div></div><p><br class="figure-break"> + </p><div class="figure"><a name="id320513"></a><p class="title"><b>Figure 5. Example of wrong password or the like followed by successful retry</b></p><div class="figure-contents"><pre class="programlisting"> + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: REJECTED + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </pre></div></div><p><br class="figure-break"> + </p><div class="figure"><a name="id320531"></a><p class="title"><b>Figure 6. Example of skey cancelled and restarted</b></p><div class="figure-contents"><pre class="programlisting"> + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: CANCEL + S: REJECTED + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </pre></div></div><p><br class="figure-break"> + </p></div><div class="sect2" title="Authentication state diagrams"><div class="titlepage"><div><div><h3 class="title"><a name="auth-states"></a>Authentication state diagrams</h3></div></div></div><p> + This section documents the auth protocol in terms of + a state machine for the client and the server. This is + probably the most robust way to implement the protocol. + </p><div class="sect3" title="Client states"><div class="titlepage"><div><div><h4 class="title"><a name="auth-states-client"></a>Client states</h4></div></div></div><p> + To more precisely describe the interaction between the + protocol state machine and the authentication mechanisms the + following notation is used: MECH(CHALL) means that the + server challenge CHALL was fed to the mechanism MECH, which + returns one of + + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + CONTINUE(RESP) means continue the auth conversation + and send RESP as the response to the server; + </p></li><li class="listitem"><p> + OK(RESP) means that after sending RESP to the server + the client side of the auth conversation is finished + and the server should return "OK"; + </p></li><li class="listitem"><p> + ERROR means that CHALL was invalid and could not be + processed. + </p></li></ul></div><p> + + Both RESP and CHALL may be empty. + </p><p> + The Client starts by getting an initial response from the + default mechanism and sends AUTH MECH RESP, or AUTH MECH if + the mechanism did not provide an initial response. If the + mechanism returns CONTINUE, the client starts in state + <span class="emphasis"><em>WaitingForData</em></span>, if the mechanism + returns OK the client starts in state + <span class="emphasis"><em>WaitingForOK</em></span>. + </p><p> + The client should keep track of available mechanisms and + which it mechanisms it has already attempted. This list is + used to decide which AUTH command to send. When the list is + exhausted, the client should give up and close the + connection. + </p><p title="WaitingForData"><b><span class="emphasis"><em>WaitingForData</em></span>. </b> + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + Receive DATA CHALL + </p><table border="0" summary="Simple list" class="simplelist"><tr><td> + MECH(CHALL) returns CONTINUE(RESP) → send + DATA RESP, goto + <span class="emphasis"><em>WaitingForData</em></span> + </td></tr><tr><td> + MECH(CHALL) returns OK(RESP) → send DATA + RESP, goto <span class="emphasis"><em>WaitingForOK</em></span> + </td></tr><tr><td> + MECH(CHALL) returns ERROR → send ERROR + [msg], goto <span class="emphasis"><em>WaitingForData</em></span> + </td></tr></table><p> + </p></li><li class="listitem"><p> + Receive REJECTED [mechs] → + send AUTH [next mech], goto + WaitingForData or <span class="emphasis"><em>WaitingForOK</em></span> + </p></li><li class="listitem"><p> + Receive ERROR → send + CANCEL, goto + <span class="emphasis"><em>WaitingForReject</em></span> + </p></li><li class="listitem"><p> + Receive OK → send + BEGIN, terminate auth + conversation, authenticated + </p></li><li class="listitem"><p> + Receive anything else → send + ERROR, goto + <span class="emphasis"><em>WaitingForData</em></span> + </p></li></ul></div><p title="WaitingForData"> + </p><p title="WaitingForOK"><b><span class="emphasis"><em>WaitingForOK</em></span>. </b> + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + Receive OK → send BEGIN, terminate auth + conversation, <span class="emphasis"><em>authenticated</em></span> + </p></li><li class="listitem"><p> + Receive REJECT [mechs] → send AUTH [next mech], + goto <span class="emphasis"><em>WaitingForData</em></span> or + <span class="emphasis"><em>WaitingForOK</em></span> + </p></li><li class="listitem"><p> + Receive DATA → send CANCEL, goto + <span class="emphasis"><em>WaitingForReject</em></span> + </p></li><li class="listitem"><p> + Receive ERROR → send CANCEL, goto + <span class="emphasis"><em>WaitingForReject</em></span> + </p></li><li class="listitem"><p> + Receive anything else → send ERROR, goto + <span class="emphasis"><em>WaitingForOK</em></span> + </p></li></ul></div><p title="WaitingForOK"> + </p><p title="WaitingForReject"><b><span class="emphasis"><em>WaitingForReject</em></span>. </b> + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + Receive REJECT [mechs] → send AUTH [next mech], + goto <span class="emphasis"><em>WaitingForData</em></span> or + <span class="emphasis"><em>WaitingForOK</em></span> + </p></li><li class="listitem"><p> + Receive anything else → terminate auth + conversation, disconnect + </p></li></ul></div><p title="WaitingForReject"> + </p></div><div class="sect3" title="Server states"><div class="titlepage"><div><div><h4 class="title"><a name="auth-states-server"></a>Server states</h4></div></div></div><p> + For the server MECH(RESP) means that the client response + RESP was fed to the the mechanism MECH, which returns one of + + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + CONTINUE(CHALL) means continue the auth conversation and + send CHALL as the challenge to the client; + </p></li><li class="listitem"><p> + OK means that the client has been successfully + authenticated; + </p></li><li class="listitem"><p> + REJECT means that the client failed to authenticate or + there was an error in RESP. + </p></li></ul></div><p> + + The server starts out in state + <span class="emphasis"><em>WaitingForAuth</em></span>. If the client is + rejected too many times the server must disconnect the + client. + </p><p title="WaitingForAuth"><b><span class="emphasis"><em>WaitingForAuth</em></span>. </b> + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + Receive AUTH → send REJECTED [mechs], goto + <span class="emphasis"><em>WaitingForAuth</em></span> + </p></li><li class="listitem"><p> + Receive AUTH MECH RESP + + </p><table border="0" summary="Simple list" class="simplelist"><tr><td> + MECH not valid mechanism → send REJECTED + [mechs], goto + <span class="emphasis"><em>WaitingForAuth</em></span> + </td></tr><tr><td> + MECH(RESP) returns CONTINUE(CHALL) → send + DATA CHALL, goto + <span class="emphasis"><em>WaitingForData</em></span> + </td></tr><tr><td> + MECH(RESP) returns OK → send OK, goto + <span class="emphasis"><em>WaitingForBegin</em></span> + </td></tr><tr><td> + MECH(RESP) returns REJECT → send REJECTED + [mechs], goto + <span class="emphasis"><em>WaitingForAuth</em></span> + </td></tr></table><p> + </p></li><li class="listitem"><p> + Receive BEGIN → terminate + auth conversation, disconnect + </p></li><li class="listitem"><p> + Receive ERROR → send REJECTED [mechs], goto + <span class="emphasis"><em>WaitingForAuth</em></span> + </p></li><li class="listitem"><p> + Receive anything else → send + ERROR, goto + <span class="emphasis"><em>WaitingForAuth</em></span> + </p></li></ul></div><p title="WaitingForAuth"> + </p><p title="WaitingForData"><b><span class="emphasis"><em>WaitingForData</em></span>. </b> + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + Receive DATA RESP + </p><table border="0" summary="Simple list" class="simplelist"><tr><td> + MECH(RESP) returns CONTINUE(CHALL) → send + DATA CHALL, goto + <span class="emphasis"><em>WaitingForData</em></span> + </td></tr><tr><td> + MECH(RESP) returns OK → send OK, goto + <span class="emphasis"><em>WaitingForBegin</em></span> + </td></tr><tr><td> + MECH(RESP) returns REJECT → send REJECTED + [mechs], goto + <span class="emphasis"><em>WaitingForAuth</em></span> + </td></tr></table><p> + </p></li><li class="listitem"><p> + Receive BEGIN → terminate auth conversation, + disconnect + </p></li><li class="listitem"><p> + Receive CANCEL → send REJECTED [mechs], goto + <span class="emphasis"><em>WaitingForAuth</em></span> + </p></li><li class="listitem"><p> + Receive ERROR → send REJECTED [mechs], goto + <span class="emphasis"><em>WaitingForAuth</em></span> + </p></li><li class="listitem"><p> + Receive anything else → send ERROR, goto + <span class="emphasis"><em>WaitingForData</em></span> + </p></li></ul></div><p title="WaitingForData"> + </p><p title="WaitingForBegin"><b><span class="emphasis"><em>WaitingForBegin</em></span>. </b> + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + Receive BEGIN → terminate auth conversation, + client authenticated + </p></li><li class="listitem"><p> + Receive CANCEL → send REJECTED [mechs], goto + <span class="emphasis"><em>WaitingForAuth</em></span> + </p></li><li class="listitem"><p> + Receive ERROR → send REJECTED [mechs], goto + <span class="emphasis"><em>WaitingForAuth</em></span> + </p></li><li class="listitem"><p> + Receive anything else → send ERROR, goto + <span class="emphasis"><em>WaitingForBegin</em></span> + </p></li></ul></div><p title="WaitingForBegin"> + </p></div></div><div class="sect2" title="Authentication mechanisms"><div class="titlepage"><div><div><h3 class="title"><a name="auth-mechanisms"></a>Authentication mechanisms</h3></div></div></div><p> + This section describes some new authentication mechanisms. + D-Bus also allows any standard SASL mechanism of course. + </p><div class="sect3" title="DBUS_COOKIE_SHA1"><div class="titlepage"><div><div><h4 class="title"><a name="auth-mechanisms-sha"></a>DBUS_COOKIE_SHA1</h4></div></div></div><p> + The DBUS_COOKIE_SHA1 mechanism is designed to establish that a client + has the ability to read a private file owned by the user being + authenticated. If the client can prove that it has access to a secret + cookie stored in this file, then the client is authenticated. + Thus the security of DBUS_COOKIE_SHA1 depends on a secure home + directory. + </p><p> + Throughout this description, "hex encoding" must output the digits + from a to f in lower-case; the digits A to F must not be used + in the DBUS_COOKIE_SHA1 mechanism. + </p><p> + Authentication proceeds as follows: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + The client sends the username it would like to authenticate + as, hex-encoded. + </p></li><li class="listitem"><p> + The server sends the name of its "cookie context" (see below); a + space character; the integer ID of the secret cookie the client + must demonstrate knowledge of; a space character; then a + randomly-generated challenge string, all of this hex-encoded into + one, single string. + </p></li><li class="listitem"><p> + The client locates the cookie and generates its own + randomly-generated challenge string. The client then concatenates + the server's decoded challenge, a ":" character, its own challenge, + another ":" character, and the cookie. It computes the SHA-1 hash + of this composite string as a hex digest. It concatenates the + client's challenge string, a space character, and the SHA-1 hex + digest, hex-encodes the result and sends it back to the server. + </p></li><li class="listitem"><p> + The server generates the same concatenated string used by the + client and computes its SHA-1 hash. It compares the hash with + the hash received from the client; if the two hashes match, the + client is authenticated. + </p></li></ul></div><p> + </p><p> + Each server has a "cookie context," which is a name that identifies a + set of cookies that apply to that server. A sample context might be + "org_freedesktop_session_bus". Context names must be valid ASCII, + nonzero length, and may not contain the characters slash ("/"), + backslash ("\"), space (" "), newline ("\n"), carriage return ("\r"), + tab ("\t"), or period ("."). There is a default context, + "org_freedesktop_general" that's used by servers that do not specify + otherwise. + </p><p> + Cookies are stored in a user's home directory, in the directory + <code class="filename">~/.dbus-keyrings/</code>. This directory must + not be readable or writable by other users. If it is, + clients and servers must ignore it. The directory + contains cookie files named after the cookie context. + </p><p> + A cookie file contains one cookie per line. Each line + has three space-separated fields: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + The cookie ID number, which must be a non-negative integer and + may not be used twice in the same file. + </p></li><li class="listitem"><p> + The cookie's creation time, in UNIX seconds-since-the-epoch + format. + </p></li><li class="listitem"><p> + The cookie itself, a hex-encoded random block of bytes. The cookie + may be of any length, though obviously security increases + as the length increases. + </p></li></ul></div><p> + </p><p> + Only server processes modify the cookie file. + They must do so with this procedure: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + Create a lockfile name by appending ".lock" to the name of the + cookie file. The server should attempt to create this file + using <code class="literal">O_CREAT | O_EXCL</code>. If file creation + fails, the lock fails. Servers should retry for a reasonable + period of time, then they may choose to delete an existing lock + to keep users from having to manually delete a stale + lock. <sup>[<a name="id321252" href="#ftn.id321252" class="footnote">1</a>]</sup> + </p></li><li class="listitem"><p> + Once the lockfile has been created, the server loads the cookie + file. It should then delete any cookies that are old (the + timeout can be fairly short), or more than a reasonable + time in the future (so that cookies never accidentally + become permanent, if the clock was set far into the future + at some point). If no recent keys remain, the + server may generate a new key. + </p></li><li class="listitem"><p> + The pruned and possibly added-to cookie file + must be resaved atomically (using a temporary + file which is rename()'d). + </p></li><li class="listitem"><p> + The lock must be dropped by deleting the lockfile. + </p></li></ul></div><p> + </p><p> + Clients need not lock the file in order to load it, + because servers are required to save the file atomically. + </p></div></div></div><div class="sect1" title="Server Addresses"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="addresses"></a>Server Addresses</h2></div></div></div><p> + Server addresses consist of a transport name followed by a colon, and + then an optional, comma-separated list of keys and values in the form key=value. + Each value is escaped. + </p><p> + For example: + </p><pre class="programlisting">unix:path=/tmp/dbus-test</pre><p> + Which is the address to a unix socket with the path /tmp/dbus-test. + </p><p> + Value escaping is similar to URI escaping but simpler. + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + The set of optionally-escaped bytes is: + <code class="literal">[0-9A-Za-z_-/.\]</code>. To escape, each + <span class="emphasis"><em>byte</em></span> (note, not character) which is not in the + set of optionally-escaped bytes must be replaced with an ASCII + percent (<code class="literal">%</code>) and the value of the byte in hex. + The hex value must always be two digits, even if the first digit is + zero. The optionally-escaped bytes may be escaped if desired. + </p></li><li class="listitem"><p> + To unescape, append each byte in the value; if a byte is an ASCII + percent (<code class="literal">%</code>) character then append the following + hex value instead. It is an error if a <code class="literal">%</code> byte + does not have two hex digits following. It is an error if a + non-optionally-escaped byte is seen unescaped. + </p></li></ul></div><p> + The set of optionally-escaped bytes is intended to preserve address + readability and convenience. + </p><p> + A server may specify a key-value pair with the key <code class="literal">guid</code> + and the value a hex-encoded 16-byte sequence. <a class="xref" href="#uuids" title="UUIDs">the section called “UUIDs”</a> + describes the format of the <code class="literal">guid</code> field. If present, + this UUID may be used to distinguish one server address from another. A + server should use a different UUID for each address it listens on. For + example, if a message bus daemon offers both UNIX domain socket and TCP + connections, but treats clients the same regardless of how they connect, + those two connections are equivalent post-connection but should have + distinct UUIDs to distinguish the kinds of connection. + </p><p> + The intent of the address UUID feature is to allow a client to avoid + opening multiple identical connections to the same server, by allowing the + client to check whether an address corresponds to an already-existing + connection. Comparing two addresses is insufficient, because addresses + can be recycled by distinct servers, and equivalent addresses may look + different if simply compared as strings (for example, the host in a TCP + address can be given as an IP address or as a hostname). + </p><p> + Note that the address key is <code class="literal">guid</code> even though the + rest of the API and documentation says "UUID," for historical reasons. + </p><p> + [FIXME clarify if attempting to connect to each is a requirement + or just a suggestion] + When connecting to a server, multiple server addresses can be + separated by a semi-colon. The library will then try to connect + to the first address and if that fails, it'll try to connect to + the next one specified, and so forth. For example + </p><pre class="programlisting">unix:path=/tmp/dbus-test;unix:path=/tmp/dbus-test2</pre><p> + </p></div><div class="sect1" title="Transports"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="transports"></a>Transports</h2></div></div></div><p> + [FIXME we need to specify in detail each transport and its possible arguments] + + Current transports include: unix domain sockets (including + abstract namespace on linux), TCP/IP, and a debug/testing transport using + in-process pipes. Future possible transports include one that + tunnels over X11 protocol. + </p><div class="sect2" title="Unix Domain Sockets"><div class="titlepage"><div><div><h3 class="title"><a name="transports-unix-domain-sockets"></a>Unix Domain Sockets</h3></div></div></div><p> + Unix domain sockets can be either paths in the file system or on Linux + kernels, they can be abstract which are similar to paths but + do not show up in the file system. + </p><p> + When a socket is opened by the D-Bus library it truncates the path + name right before the first trailing Nul byte. This is true for both + normal paths and abstract paths. Note that this is a departure from + previous versions of D-Bus that would create sockets with a fixed + length path name. Names which were shorter than the fixed length + would be padded by Nul bytes. + </p></div></div><div class="sect1" title="Naming Conventions"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="naming-conventions"></a>Naming Conventions</h2></div></div></div><p> + D-Bus namespaces are all lowercase and correspond to reversed domain + names, as with Java. e.g. "org.freedesktop" + </p><p> + Interface, signal, method, and property names are "WindowsStyleCaps", note + that the first letter is capitalized, unlike Java. + </p><p> + Object paths are normally all lowercase with underscores used rather than + hyphens. + </p></div><div class="sect1" title="UUIDs"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="uuids"></a>UUIDs</h2></div></div></div><p> + A working D-Bus implementation uses universally-unique IDs in two places. + First, each server address has a UUID identifying the address, + as described in <a class="xref" href="#addresses" title="Server Addresses">the section called “Server Addresses”</a>. Second, each operating + system kernel instance running a D-Bus client or server has a UUID + identifying that kernel, retrieved by invoking the method + org.freedesktop.DBus.Peer.GetMachineId() (see <a class="xref" href="#standard-interfaces-peer" title="org.freedesktop.DBus.Peer">the section called “<code class="literal">org.freedesktop.DBus.Peer</code>”</a>). + </p><p> + The term "UUID" in this document is intended literally, i.e. an + identifier that is universally unique. It is not intended to refer to + RFC4122, and in fact the D-Bus UUID is not compatible with that RFC. + </p><p> + The UUID must contain 128 bits of data and be hex-encoded. The + hex-encoded string may not contain hyphens or other non-hex-digit + characters, and it must be exactly 32 characters long. To generate a + UUID, the current reference implementation concatenates 96 bits of random + data followed by the 32-bit time in seconds since the UNIX epoch (in big + endian byte order). + </p><p> + It would also be acceptable and probably better to simply generate 128 + bits of random data, as long as the random number generator is of high + quality. The timestamp could conceivably help if the random bits are not + very random. With a quality random number generator, collisions are + extremely unlikely even with only 96 bits, so it's somewhat academic. + </p><p> + Implementations should, however, stick to random data for the first 96 bits + of the UUID. + </p></div><div class="sect1" title="Standard Interfaces"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="standard-interfaces"></a>Standard Interfaces</h2></div></div></div><p> + See <a class="xref" href="#message-protocol-types-notation" title="Notation in this document">the section called “Notation in this document”</a> for details on + the notation used in this section. There are some standard interfaces + that may be useful across various D-Bus applications. + </p><div class="sect2" title="org.freedesktop.DBus.Peer"><div class="titlepage"><div><div><h3 class="title"><a name="standard-interfaces-peer"></a><code class="literal">org.freedesktop.DBus.Peer</code></h3></div></div></div><p> + The <code class="literal">org.freedesktop.DBus.Peer</code> interface + has two methods: + </p><pre class="programlisting"> + org.freedesktop.DBus.Peer.Ping () + org.freedesktop.DBus.Peer.GetMachineId (out STRING machine_uuid) + </pre><p> + </p><p> + On receipt of the <code class="literal">METHOD_CALL</code> message + <code class="literal">org.freedesktop.DBus.Peer.Ping</code>, an application should do + nothing other than reply with a <code class="literal">METHOD_RETURN</code> as + usual. It does not matter which object path a ping is sent to. The + reference implementation handles this method automatically. + </p><p> + On receipt of the <code class="literal">METHOD_CALL</code> message + <code class="literal">org.freedesktop.DBus.Peer.GetMachineId</code>, an application should + reply with a <code class="literal">METHOD_RETURN</code> containing a hex-encoded + UUID representing the identity of the machine the process is running on. + This UUID must be the same for all processes on a single system at least + until that system next reboots. It should be the same across reboots + if possible, but this is not always possible to implement and is not + guaranteed. + It does not matter which object path a GetMachineId is sent to. The + reference implementation handles this method automatically. + </p><p> + The UUID is intended to be per-instance-of-the-operating-system, so may represent + a virtual machine running on a hypervisor, rather than a physical machine. + Basically if two processes see the same UUID, they should also see the same + shared memory, UNIX domain sockets, process IDs, and other features that require + a running OS kernel in common between the processes. + </p><p> + The UUID is often used where other programs might use a hostname. Hostnames + can change without rebooting, however, or just be "localhost" - so the UUID + is more robust. + </p><p> + <a class="xref" href="#uuids" title="UUIDs">the section called “UUIDs”</a> explains the format of the UUID. + </p></div><div class="sect2" title="org.freedesktop.DBus.Introspectable"><div class="titlepage"><div><div><h3 class="title"><a name="standard-interfaces-introspectable"></a><code class="literal">org.freedesktop.DBus.Introspectable</code></h3></div></div></div><p> + This interface has one method: + </p><pre class="programlisting"> + org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data) + </pre><p> + </p><p> + Objects instances may implement + <code class="literal">Introspect</code> which returns an XML description of + the object, including its interfaces (with signals and methods), objects + below it in the object path tree, and its properties. + </p><p> + <a class="xref" href="#introspection-format" title="Introspection Data Format">the section called “Introspection Data Format”</a> describes the format of this XML string. + </p></div><div class="sect2" title="org.freedesktop.DBus.Properties"><div class="titlepage"><div><div><h3 class="title"><a name="standard-interfaces-properties"></a><code class="literal">org.freedesktop.DBus.Properties</code></h3></div></div></div><p> + Many native APIs will have a concept of object <em class="firstterm">properties</em> + or <em class="firstterm">attributes</em>. These can be exposed via the + <code class="literal">org.freedesktop.DBus.Properties</code> interface. + </p><p> + </p><pre class="programlisting"> + org.freedesktop.DBus.Properties.Get (in STRING interface_name, + in STRING property_name, + out VARIANT value); + org.freedesktop.DBus.Properties.Set (in STRING interface_name, + in STRING property_name, + in VARIANT value); + org.freedesktop.DBus.Properties.GetAll (in STRING interface_name, + out DICT<STRING,VARIANT> props); + </pre><p> + </p><p> + The available properties and whether they are writable can be determined + by calling <code class="literal">org.freedesktop.DBus.Introspectable.Introspect</code>, + see <a class="xref" href="#standard-interfaces-introspectable" title="org.freedesktop.DBus.Introspectable">the section called “<code class="literal">org.freedesktop.DBus.Introspectable</code>”</a>. + </p><p> + An empty string may be provided for the interface name; in this case, + if there are multiple properties on an object with the same name, + the results are undefined (picking one by according to an arbitrary + deterministic rule, or returning an error, are the reasonable + possibilities). + </p></div></div><div class="sect1" title="Introspection Data Format"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="introspection-format"></a>Introspection Data Format</h2></div></div></div><p> + As described in <a class="xref" href="#standard-interfaces-introspectable" title="org.freedesktop.DBus.Introspectable">the section called “<code class="literal">org.freedesktop.DBus.Introspectable</code>”</a>, + objects may be introspected at runtime, returning an XML string + that describes the object. The same XML format may be used in + other contexts as well, for example as an "IDL" for generating + static language bindings. + </p><p> + Here is an example of introspection data: + </p><pre class="programlisting"> + <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> + <node name="/org/freedesktop/sample_object"> + <interface name="org.freedesktop.SampleInterface"> + <method name="Frobate"> + <arg name="foo" type="i" direction="in"/> + <arg name="bar" type="s" direction="out"/> + <arg name="baz" type="a{us}" direction="out"/> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </method> + <method name="Bazify"> + <arg name="bar" type="(iiu)" direction="in"/> + <arg name="bar" type="v" direction="out"/> + </method> + <method name="Mogrify"> + <arg name="bar" type="(iiav)" direction="in"/> + </method> + <signal name="Changed"> + <arg name="new_value" type="b"/> + </signal> + <property name="Bar" type="y" access="readwrite"/> + </interface> + <node name="child_of_sample_object"/> + <node name="another_child_of_sample_object"/> + </node> + </pre><p> + </p><p> + A more formal DTD and spec needs writing, but here are some quick notes. + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + Only the root <node> element can omit the node name, as it's + known to be the object that was introspected. If the root + <node> does have a name attribute, it must be an absolute + object path. If child <node> have object paths, they must be + relative. + </p></li><li class="listitem"><p> + If a child <node> has any sub-elements, then they + must represent a complete introspection of the child. + If a child <node> is empty, then it may or may + not have sub-elements; the child must be introspected + in order to find out. The intent is that if an object + knows that its children are "fast" to introspect + it can go ahead and return their information, but + otherwise it can omit it. + </p></li><li class="listitem"><p> + The direction element on <arg> may be omitted, + in which case it defaults to "in" for method calls + and "out" for signals. Signals only allow "out" + so while direction may be specified, it's pointless. + </p></li><li class="listitem"><p> + The possible directions are "in" and "out", + unlike CORBA there is no "inout" + </p></li><li class="listitem"><p> + The possible property access flags are + "readwrite", "read", and "write" + </p></li><li class="listitem"><p> + Multiple interfaces can of course be listed for + one <node>. + </p></li><li class="listitem"><p> + The "name" attribute on arguments is optional. + </p></li></ul></div><p> + </p><p> + Method, interface, property, and signal elements may have + "annotations", which are generic key/value pairs of metadata. + They are similar conceptually to Java's annotations and C# attributes. + Well-known annotations: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Name</th><th>Values (separated by ,)</th><th>Description</th></tr></thead><tbody><tr><td>org.freedesktop.DBus.Deprecated</td><td>true,false</td><td>Whether or not the entity is deprecated; defaults to false</td></tr><tr><td>org.freedesktop.DBus.GLib.CSymbol</td><td>(string)</td><td>The C symbol; may be used for methods and interfaces</td></tr><tr><td>org.freedesktop.DBus.Method.NoReply</td><td>true,false</td><td>If set, don't expect a reply to the method call; defaults to false.</td></tr></tbody></table></div></div><div class="sect1" title="Message Bus Specification"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="message-bus"></a>Message Bus Specification</h2></div></div></div><div class="sect2" title="Message Bus Overview"><div class="titlepage"><div><div><h3 class="title"><a name="message-bus-overview"></a>Message Bus Overview</h3></div></div></div><p> + The message bus accepts connections from one or more applications. + Once connected, applications can exchange messages with other + applications that are also connected to the bus. + </p><p> + In order to route messages among connections, the message bus keeps a + mapping from names to connections. Each connection has one + unique-for-the-lifetime-of-the-bus name automatically assigned. + Applications may request additional names for a connection. Additional + names are usually "well-known names" such as + "org.freedesktop.TextEditor". When a name is bound to a connection, + that connection is said to <em class="firstterm">own</em> the name. + </p><p> + The bus itself owns a special name, <code class="literal">org.freedesktop.DBus</code>. + This name routes messages to the bus, allowing applications to make + administrative requests. For example, applications can ask the bus + to assign a name to a connection. + </p><p> + Each name may have <em class="firstterm">queued owners</em>. When an + application requests a name for a connection and the name is already in + use, the bus will optionally add the connection to a queue waiting for + the name. If the current owner of the name disconnects or releases + the name, the next connection in the queue will become the new owner. + </p><p> + This feature causes the right thing to happen if you start two text + editors for example; the first one may request "org.freedesktop.TextEditor", + and the second will be queued as a possible owner of that name. When + the first exits, the second will take over. + </p><p> + Messages may have a <code class="literal">DESTINATION</code> field (see <a class="xref" href="#message-protocol-header-fields" title="Header Fields">the section called “Header Fields”</a>). If the + <code class="literal">DESTINATION</code> field is present, it specifies a message + recipient by name. Method calls and replies normally specify this field. + </p><p> + Signals normally do not specify a destination; they are sent to all + applications with <em class="firstterm">message matching rules</em> that + match the message. + </p><p> + When the message bus receives a method call, if the + <code class="literal">DESTINATION</code> 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 + <code class="literal">org.freedesktop.DBus.Peer.Ping</code> message with no + <code class="literal">DESTINATION</code> will cause the message bus itself to + reply to the ping immediately; the message bus will not make this + message visible to other applications. + </p><p> + Continuing the <code class="literal">org.freedesktop.DBus.Peer.Ping</code> example, if + the ping message were sent with a <code class="literal">DESTINATION</code> name of + <code class="literal">com.yoyodyne.Screensaver</code>, then the ping would be + forwarded, and the Yoyodyne Corporation screensaver application would be + expected to reply to the ping. + </p></div><div class="sect2" title="Message Bus Names"><div class="titlepage"><div><div><h3 class="title"><a name="message-bus-names"></a>Message Bus Names</h3></div></div></div><p> + Each connection has at least one name, assigned at connection time and + returned in response to the + <code class="literal">org.freedesktop.DBus.Hello</code> method call. This + automatically-assigned name is called the connection's <em class="firstterm">unique + name</em>. Unique names are never reused for two different + connections to the same bus. + </p><p> + Ownership of a unique name is a prerequisite for interaction with + the message bus. It logically follows that the unique name is always + the first name that an application comes to own, and the last + one that it loses ownership of. + </p><p> + Unique connection names must begin with the character ':' (ASCII colon + character); bus names that are not unique names must not begin + with this character. (The bus must reject any attempt by an application + to manually request a name beginning with ':'.) This restriction + categorically prevents "spoofing"; messages sent to a unique name + will always go to the expected connection. + </p><p> + When a connection is closed, all the names that it owns are deleted (or + transferred to the next connection in the queue if any). + </p><p> + A connection can request additional names to be associated with it using + the <code class="literal">org.freedesktop.DBus.RequestName</code> message. <a class="xref" href="#message-protocol-names-bus" title="Bus names">the section called “Bus names”</a> describes the format of a valid + name. These names can be released again using the + <code class="literal">org.freedesktop.DBus.ReleaseName</code> message. + </p><div class="sect3" title="org.freedesktop.DBus.RequestName"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-request-name"></a><code class="literal">org.freedesktop.DBus.RequestName</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + UINT32 RequestName (in STRING name, in UINT32 flags) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Name to request</td></tr><tr><td>1</td><td>UINT32</td><td>Flags</td></tr></tbody></table></div><p> + Reply arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>UINT32</td><td>Return value</td></tr></tbody></table></div><p> + </p><p> + This method call should be sent to + <code class="literal">org.freedesktop.DBus</code> and asks the message bus to + assign the given name to the method caller. Each name maintains a + queue of possible owners, where the head of the queue is the primary + or current owner of the name. Each potential owner in the queue + maintains the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and + DBUS_NAME_FLAG_DO_NOT_QUEUE settings from its latest RequestName + call. When RequestName is invoked the following occurs: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + If the method caller is currently the primary owner of the name, + the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and DBUS_NAME_FLAG_DO_NOT_QUEUE + values are updated with the values from the new RequestName call, + and nothing further happens. + </p></li><li class="listitem"><p> + If the current primary owner (head of the queue) has + DBUS_NAME_FLAG_ALLOW_REPLACEMENT set, and the RequestName + invocation has the DBUS_NAME_FLAG_REPLACE_EXISTING flag, then + the caller of RequestName replaces the current primary owner at + the head of the queue and the current primary owner moves to the + second position in the queue. If the caller of RequestName was + in the queue previously its flags are updated with the values from + the new RequestName in addition to moving it to the head of the queue. + </p></li><li class="listitem"><p> + If replacement is not possible, and the method caller is + currently in the queue but not the primary owner, its flags are + updated with the values from the new RequestName call. + </p></li><li class="listitem"><p> + If replacement is not possible, and the method caller is + currently not in the queue, the method caller is appended to the + queue. + </p></li><li class="listitem"><p> + If any connection in the queue has DBUS_NAME_FLAG_DO_NOT_QUEUE + set and is not the primary owner, it is removed from the + queue. This can apply to the previous primary owner (if it + was replaced) or the method caller (if it updated the + DBUS_NAME_FLAG_DO_NOT_QUEUE flag while still stuck in the + queue, or if it was just added to the queue with that flag set). + </p></li></ul></div><p> + </p><p> + Note that DBUS_NAME_FLAG_REPLACE_EXISTING results in "jumping the + queue," even if another application already in the queue had specified + DBUS_NAME_FLAG_REPLACE_EXISTING. This comes up if a primary owner + that does not allow replacement goes away, and the next primary owner + does allow replacement. In this case, queued items that specified + DBUS_NAME_FLAG_REPLACE_EXISTING <span class="emphasis"><em>do not</em></span> + automatically replace the new primary owner. In other words, + DBUS_NAME_FLAG_REPLACE_EXISTING is not saved, it is only used at the + time RequestName is called. This is deliberate to avoid an infinite loop + anytime two applications are both DBUS_NAME_FLAG_ALLOW_REPLACEMENT + and DBUS_NAME_FLAG_REPLACE_EXISTING. + </p><p> + The flags argument contains any of the following values logically ORed + together: + + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Conventional Name</th><th>Value</th><th>Description</th></tr></thead><tbody><tr><td>DBUS_NAME_FLAG_ALLOW_REPLACEMENT</td><td>0x1</td><td> + + If an application A specifies this flag and succeeds in + becoming the owner of the name, and another application B + later calls RequestName with the + DBUS_NAME_FLAG_REPLACE_EXISTING flag, then application A + will lose ownership and receive a + <code class="literal">org.freedesktop.DBus.NameLost</code> signal, and + application B will become the new owner. If DBUS_NAME_FLAG_ALLOW_REPLACEMENT + is not specified by application A, or DBUS_NAME_FLAG_REPLACE_EXISTING + is not specified by application B, then application B will not replace + application A as the owner. + + </td></tr><tr><td>DBUS_NAME_FLAG_REPLACE_EXISTING</td><td>0x2</td><td> + + Try to replace the current owner if there is one. If this + flag is not set the application will only become the owner of + the name if there is no current owner. If this flag is set, + the application will replace the current owner if + the current owner specified DBUS_NAME_FLAG_ALLOW_REPLACEMENT. + + </td></tr><tr><td>DBUS_NAME_FLAG_DO_NOT_QUEUE</td><td>0x4</td><td> + + Without this flag, if an application requests a name that is + already owned, the application will be placed in a queue to + own the name when the current owner gives it up. If this + flag is given, the application will not be placed in the + queue, the request for the name will simply fail. This flag + also affects behavior when an application is replaced as + name owner; by default the application moves back into the + waiting queue, unless this flag was provided when the application + became the name owner. + + </td></tr></tbody></table></div><p> + + The return code can be one of the following values: + + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Conventional Name</th><th>Value</th><th>Description</th></tr></thead><tbody><tr><td>DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER</td><td>1</td><td>The caller is now the primary owner of + the name, replacing any previous owner. Either the name had no + owner before, or the caller specified + DBUS_NAME_FLAG_REPLACE_EXISTING and the current owner specified + DBUS_NAME_FLAG_ALLOW_REPLACEMENT.</td></tr><tr><td>DBUS_REQUEST_NAME_REPLY_IN_QUEUE</td><td>2</td><td>The name already had an owner, + DBUS_NAME_FLAG_DO_NOT_QUEUE was not specified, and either + the current owner did not specify + DBUS_NAME_FLAG_ALLOW_REPLACEMENT or the requesting + application did not specify DBUS_NAME_FLAG_REPLACE_EXISTING. + </td></tr><tr><td>DBUS_REQUEST_NAME_REPLY_EXISTS</td><td>3</td><td>The name already has an owner, + DBUS_NAME_FLAG_DO_NOT_QUEUE was specified, and either + DBUS_NAME_FLAG_ALLOW_REPLACEMENT was not specified by the + current owner, or DBUS_NAME_FLAG_REPLACE_EXISTING was not + specified by the requesting application.</td></tr><tr><td>DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER</td><td>4</td><td>The application trying to request ownership of a name is already the owner of it.</td></tr></tbody></table></div><p> + </p></div><div class="sect3" title="org.freedesktop.DBus.ReleaseName"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-release-name"></a><code class="literal">org.freedesktop.DBus.ReleaseName</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + UINT32 ReleaseName (in STRING name) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Name to release</td></tr></tbody></table></div><p> + Reply arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>UINT32</td><td>Return value</td></tr></tbody></table></div><p> + </p><p> + This method call should be sent to + <code class="literal">org.freedesktop.DBus</code> and asks the message bus to + release the method caller's claim to the given name. If the caller is + the primary owner, a new primary owner will be selected from the + queue if any other owners are waiting. If the caller is waiting in + the queue for the name, the caller will removed from the queue and + will not be made an owner of the name if it later becomes available. + If there are no other owners in the queue for the name, it will be + removed from the bus entirely. + + The return code can be one of the following values: + + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Conventional Name</th><th>Value</th><th>Description</th></tr></thead><tbody><tr><td>DBUS_RELEASE_NAME_REPLY_RELEASED</td><td>1</td><td>The caller has released his claim on + the given name. Either the caller was the primary owner of + the name, and the name is now unused or taken by somebody + waiting in the queue for the name, or the caller was waiting + in the queue for the name and has now been removed from the + queue.</td></tr><tr><td>DBUS_RELEASE_NAME_REPLY_NON_EXISTENT</td><td>2</td><td>The given name does not exist on this bus.</td></tr><tr><td>DBUS_RELEASE_NAME_REPLY_NOT_OWNER</td><td>3</td><td>The caller was not the primary owner of this name, + and was also not waiting in the queue to own this name.</td></tr></tbody></table></div><p> + </p></div></div><div class="sect2" title="Message Bus Message Routing"><div class="titlepage"><div><div><h3 class="title"><a name="message-bus-routing"></a>Message Bus Message Routing</h3></div></div></div><p> + FIXME + </p><div class="sect3" title="Match Rules"><div class="titlepage"><div><div><h4 class="title"><a name="message-bus-routing-match-rules"></a>Match Rules</h4></div></div></div><p> + 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. + </p><p> + Match rules are added using the AddMatch bus method + (see xref linkend="bus-messages-add-match"/>). Rules are + specified as a string of comma separated key/value pairs. + Excluding a key from the rule indicates a wildcard match. + For instance excluding the the member from a match rule but + adding a sender would let all messages from that sender through. + An example of a complete rule would be + "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo',path='/bar/foo',destination=':452345.34',arg2='bar'" + </p><p> + The following table describes the keys that can be used to create + a match rule: + The following table summarizes the D-Bus types. + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Key</th><th>Possible Values</th><th>Description</th></tr></thead><tbody><tr><td><code class="literal">type</code></td><td>'signal', 'method_call', 'method_return', 'error'</td><td>Match on the message type. An example of a type match is type='signal'</td></tr><tr><td><code class="literal">sender</code></td><td>A bus or unique name (see <a class="xref" href="#term-bus-name" title="Bus Name">Bus Name</a> + and <a class="xref" href="#term-unique-name" title="Unique Connection Name">Unique Connection Name</a> respectively) + </td><td>Match messages sent by a particular sender. An example of a sender match + is sender='org.freedesktop.Hal'</td></tr><tr><td><code class="literal">interface</code></td><td>An interface name (see <a class="xref" href="#message-protocol-names-interface" title="Interface names">the section called “Interface names”</a>)</td><td>Match messages sent over or to a particular interface. An example of an + interface match is interface='org.freedesktop.Hal.Manager'. + If a message omits the interface header, it must not match any rule + that specifies this key.</td></tr><tr><td><code class="literal">member</code></td><td>Any valid method or signal name</td><td>Matches messages which have the give method or signal name. An example of + a member match is member='NameOwnerChanged'</td></tr><tr><td><code class="literal">path</code></td><td>An object path (see <a class="xref" href="#message-protocol-marshaling-object-path" title="Valid Object Paths">the section called “Valid Object Paths”</a>)</td><td>Matches messages which are sent from or to the given object. An example of a + path match is path='/org/freedesktop/Hal/Manager'</td></tr><tr><td><code class="literal">destination</code></td><td>A unique name (see <a class="xref" href="#term-unique-name" title="Unique Connection Name">Unique Connection Name</a>)</td><td>Matches messages which are being sent to the given unique name. An + example of a destination match is destination=':1.0'</td></tr><tr><td><code class="literal">arg[0, 1, 2, 3, ...]</code></td><td>Any string</td><td>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 + would be arg3='Foo'. Only argument indexes from 0 to 63 should be + accepted.</td></tr><tr><td><code class="literal">arg[0, 1, 2, 3, ...]path</code></td><td>Any string</td><td>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'.</td></tr></tbody></table></div><p> + </p></div></div><div class="sect2" title="Message Bus Starting Services"><div class="titlepage"><div><div><h3 class="title"><a name="message-bus-starting-services"></a>Message Bus Starting Services</h3></div></div></div><p> + The message bus can start applications on behalf of other applications. + In CORBA terms, this would be called <em class="firstterm">activation</em>. + An application that can be started in this way is called a + <em class="firstterm">service</em>. + </p><p> + With D-Bus, starting a service is normally done by name. That is, + applications ask the message bus to start some program that will own a + well-known name, such as <code class="literal">org.freedesktop.TextEditor</code>. + This implies a contract documented along with the name + <code class="literal">org.freedesktop.TextEditor</code> for which objects + the owner of that name will provide, and what interfaces those + objects will have. + </p><p> + To find an executable corresponding to a particular name, the bus daemon + looks for <em class="firstterm">service description files</em>. Service + description files define a mapping from names to executables. Different + kinds of message bus will look for these files in different places, see + <a class="xref" href="#message-bus-types" title="Well-known Message Bus Instances">the section called “Well-known Message Bus Instances”</a>. + </p><p> + [FIXME the file format should be much better specified than "similar to + .desktop entries" esp. since desktop entries are already + badly-specified. ;-)] Service description files have the ".service" file + extension. The message bus will only load service description files + ending with .service; all other files will be ignored. The file format + is similar to that of <a class="ulink" href="http://www.freedesktop.org/standards/desktop-entry-spec/desktop-entry-spec.html" target="_top">desktop + entries</a>. All service description files must be in UTF-8 + encoding. To ensure that there will be no name collisions, service files + must be namespaced using the same mechanism as messages and service + names. + + </p><div class="figure"><a name="id322982"></a><p class="title"><b>Figure 7. Example service description file</b></p><div class="figure-contents"><pre class="programlisting"> + # Sample service description file + [D-BUS Service] + Names=org.freedesktop.ConfigurationDatabase;org.gnome.GConf; + Exec=/usr/libexec/gconfd-2 + </pre></div></div><p><br class="figure-break"> + </p><p> + When an application asks to start a service by name, the bus daemon tries to + find a service that will own that name. It then tries to spawn the + executable associated with it. If this fails, it will report an + error. [FIXME what happens if two .service files offer the same service; + what kind of error is reported, should we have a way for the client to + choose one?] + </p><p> + The executable launched will have the environment variable + <code class="literal">DBUS_STARTER_ADDRESS</code> set to the address of the + message bus so it can connect and request the appropriate names. + </p><p> + The executable being launched may want to know whether the message bus + starting it is one of the well-known message buses (see <a class="xref" href="#message-bus-types" title="Well-known Message Bus Instances">the section called “Well-known Message Bus Instances”</a>). To facilitate this, the bus must also set + the <code class="literal">DBUS_STARTER_BUS_TYPE</code> environment variable if it is one + of the well-known buses. The currently-defined values for this variable + are <code class="literal">system</code> for the systemwide message bus, + and <code class="literal">session</code> for the per-login-session message + bus. The new executable must still connect to the address given + in <code class="literal">DBUS_STARTER_ADDRESS</code>, but may assume that the + resulting connection is to the well-known bus. + </p><p> + [FIXME there should be a timeout somewhere, either specified + in the .service file, by the client, or just a global value + and if the client being activated fails to connect within that + timeout, an error should be sent back.] + </p><div class="sect3" title="Message Bus Service Scope"><div class="titlepage"><div><div><h4 class="title"><a name="message-bus-starting-services-scope"></a>Message Bus Service Scope</h4></div></div></div><p> + The "scope" of a service is its "per-", such as per-session, + per-machine, per-home-directory, or per-display. The reference + implementation doesn't yet support starting services in a different + scope from the message bus itself. So e.g. if you start a service + on the session bus its scope is per-session. + </p><p> + We could add an optional scope to a bus name. For example, for + per-(display,session pair), we could have a unique ID for each display + generated automatically at login and set on screen 0 by executing a + special "set display ID" binary. The ID would be stored in a + <code class="literal">_DBUS_DISPLAY_ID</code> property and would be a string of + random bytes. This ID would then be used to scope names. + Starting/locating a service could be done by ID-name pair rather than + only by name. + </p><p> + Contrast this with a per-display scope. To achieve that, we would + want a single bus spanning all sessions using a given display. + So we might set a <code class="literal">_DBUS_DISPLAY_BUS_ADDRESS</code> + property on screen 0 of the display, pointing to this bus. + </p></div></div><div class="sect2" title="Well-known Message Bus Instances"><div class="titlepage"><div><div><h3 class="title"><a name="message-bus-types"></a>Well-known Message Bus Instances</h3></div></div></div><p> + Two standard message bus instances are defined here, along with how + to locate them and where their service files live. + </p><div class="sect3" title="Login session message bus"><div class="titlepage"><div><div><h4 class="title"><a name="message-bus-types-login"></a>Login session message bus</h4></div></div></div><p> + Each time a user logs in, a <em class="firstterm">login session message + bus</em> may be started. All applications in the user's login + session may interact with one another using this message bus. + </p><p> + The address of the login session message bus is given + in the <code class="literal">DBUS_SESSION_BUS_ADDRESS</code> environment + variable. If that variable is not set, applications may + also try to read the address from the X Window System root + window property <code class="literal">_DBUS_SESSION_BUS_ADDRESS</code>. + The root window property must have type <code class="literal">STRING</code>. + The environment variable should have precedence over the + root window property. + </p><p> + [FIXME specify location of .service files, probably using + DESKTOP_DIRS etc. from basedir specification, though login session + bus is not really desktop-specific] + </p></div><div class="sect3" title="System message bus"><div class="titlepage"><div><div><h4 class="title"><a name="message-bus-types-system"></a>System message bus</h4></div></div></div><p> + A computer may have a <em class="firstterm">system message bus</em>, + accessible to all applications on the system. This message bus may be + used to broadcast system events, such as adding new hardware devices, + changes in the printer queue, and so forth. + </p><p> + The address of the system message bus is given + in the <code class="literal">DBUS_SYSTEM_BUS_ADDRESS</code> environment + variable. If that variable is not set, applications should try + to connect to the well-known address + <code class="literal">unix:path=/var/run/dbus/system_bus_socket</code>. + <sup>[<a name="id323183" href="#ftn.id323183" class="footnote">2</a>]</sup> + </p><p> + [FIXME specify location of system bus .service files] + </p></div></div><div class="sect2" title="Message Bus Messages"><div class="titlepage"><div><div><h3 class="title"><a name="message-bus-messages"></a>Message Bus Messages</h3></div></div></div><p> + The special message bus name <code class="literal">org.freedesktop.DBus</code> + responds to a number of additional messages. + </p><div class="sect3" title="org.freedesktop.DBus.Hello"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-hello"></a><code class="literal">org.freedesktop.DBus.Hello</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + STRING Hello () + </pre><p> + Reply arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Unique name assigned to the connection</td></tr></tbody></table></div><p> + </p><p> + Before an application is able to send messages to other applications + it must send the <code class="literal">org.freedesktop.DBus.Hello</code> message + to the message bus to obtain a unique name. If an application without + a unique name tries to send a message to another application, or a + message to the message bus itself that isn't the + <code class="literal">org.freedesktop.DBus.Hello</code> message, it will be + disconnected from the bus. + </p><p> + There is no corresponding "disconnect" request; if a client wishes to + disconnect from the bus, it simply closes the socket (or other + communication channel). + </p></div><div class="sect3" title="org.freedesktop.DBus.ListNames"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-list-names"></a><code class="literal">org.freedesktop.DBus.ListNames</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + ARRAY of STRING ListNames () + </pre><p> + Reply arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>ARRAY of STRING</td><td>Array of strings where each string is a bus name</td></tr></tbody></table></div><p> + </p><p> + Returns a list of all currently-owned names on the bus. + </p></div><div class="sect3" title="org.freedesktop.DBus.ListActivatableNames"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-list-activatable-names"></a><code class="literal">org.freedesktop.DBus.ListActivatableNames</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + ARRAY of STRING ListActivatableNames () + </pre><p> + Reply arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>ARRAY of STRING</td><td>Array of strings where each string is a bus name</td></tr></tbody></table></div><p> + </p><p> + Returns a list of all names that can be activated on the bus. + </p></div><div class="sect3" title="org.freedesktop.DBus.NameHasOwner"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-name-exists"></a><code class="literal">org.freedesktop.DBus.NameHasOwner</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + BOOLEAN NameHasOwner (in STRING name) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Name to check</td></tr></tbody></table></div><p> + Reply arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>BOOLEAN</td><td>Return value, true if the name exists</td></tr></tbody></table></div><p> + </p><p> + Checks if the specified name exists (currently has an owner). + </p></div><div class="sect3" title="org.freedesktop.DBus.NameOwnerChanged"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-name-owner-changed"></a><code class="literal">org.freedesktop.DBus.NameOwnerChanged</code></h4></div></div></div><p> + This is a signal: + </p><pre class="programlisting"> + NameOwnerChanged (STRING name, STRING old_owner, STRING new_owner) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Name with a new owner</td></tr><tr><td>1</td><td>STRING</td><td>Old owner or empty string if none</td></tr><tr><td>2</td><td>STRING</td><td>New owner or empty string if none</td></tr></tbody></table></div><p> + </p><p> + This signal indicates that the owner of a name has changed. + It's also the signal to use to detect the appearance of + new names on the bus. + </p></div><div class="sect3" title="org.freedesktop.DBus.NameLost"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-name-lost"></a><code class="literal">org.freedesktop.DBus.NameLost</code></h4></div></div></div><p> + This is a signal: + </p><pre class="programlisting"> + NameLost (STRING name) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Name which was lost</td></tr></tbody></table></div><p> + </p><p> + This signal is sent to a specific application when it loses + ownership of a name. + </p></div><div class="sect3" title="org.freedesktop.DBus.NameAcquired"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-name-acquired"></a><code class="literal">org.freedesktop.DBus.NameAcquired</code></h4></div></div></div><p> + This is a signal: + </p><pre class="programlisting"> + NameAcquired (STRING name) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Name which was acquired</td></tr></tbody></table></div><p> + </p><p> + This signal is sent to a specific application when it gains + ownership of a name. + </p></div><div class="sect3" title="org.freedesktop.DBus.StartServiceByName"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-start-service-by-name"></a><code class="literal">org.freedesktop.DBus.StartServiceByName</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + UINT32 StartServiceByName (in STRING name, in UINT32 flags) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Name of the service to start</td></tr><tr><td>1</td><td>UINT32</td><td>Flags (currently not used)</td></tr></tbody></table></div><p> + Reply arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>UINT32</td><td>Return value</td></tr></tbody></table></div><p> + Tries to launch the executable associated with a name. For more information, see <a class="xref" href="#message-bus-starting-services" title="Message Bus Starting Services">the section called “Message Bus Starting Services”</a>. + + </p><p> + The return value can be one of the following values: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Identifier</th><th>Value</th><th>Description</th></tr></thead><tbody><tr><td>DBUS_START_REPLY_SUCCESS</td><td>1</td><td>The service was successfully started.</td></tr><tr><td>DBUS_START_REPLY_ALREADY_RUNNING</td><td>2</td><td>A connection already owns the given name.</td></tr></tbody></table></div><p> + </p></div><div class="sect3" title="org.freedesktop.DBus.UpdateActivationEnvironment"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-update-activation-environment"></a><code class="literal">org.freedesktop.DBus.UpdateActivationEnvironment</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + UpdateActivationEnvironment (in ARRAY of DICT<STRING,STRING> environment) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>ARRAY of DICT<STRING,STRING></td><td>Environment to add or update</td></tr></tbody></table></div><p> + Normally, session bus activated services inherit the environment of the bus daemon. This method adds to or modifies that environment when activating services. + </p><p> + Some bus instances, such as the standard system bus, may disable access to this method for some or all callers. + </p></div><div class="sect3" title="org.freedesktop.DBus.GetNameOwner"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-get-name-owner"></a><code class="literal">org.freedesktop.DBus.GetNameOwner</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + STRING GetNameOwner (in STRING name) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Name to get the owner of</td></tr></tbody></table></div><p> + Reply arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Return value, a unique connection name</td></tr></tbody></table></div><p> + Returns the unique connection name of the primary owner of the name + given. If the requested name doesn't have an owner, returns a + <code class="literal">org.freedesktop.DBus.Error.NameHasNoOwner</code> error. + </p></div><div class="sect3" title="org.freedesktop.DBus.GetConnectionUnixUser"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-get-connection-unix-user"></a><code class="literal">org.freedesktop.DBus.GetConnectionUnixUser</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + UINT32 GetConnectionUnixUser (in STRING connection_name) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Name of the connection to query</td></tr></tbody></table></div><p> + Reply arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>UINT32</td><td>unix user id</td></tr></tbody></table></div><p> + Returns the unix uid of the process connected to the server. If unable to + determine it, a <code class="literal">org.freedesktop.DBus.Error.Failed</code> + error is returned. + </p></div><div class="sect3" title="org.freedesktop.DBus.AddMatch"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-add-match"></a><code class="literal">org.freedesktop.DBus.AddMatch</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + AddMatch (in STRING rule) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Match rule to add to the connection</td></tr></tbody></table></div><p> + Adds a match rule to match messages going through the message bus (see <a class="xref" href="#message-bus-routing-match-rules" title="Match Rules">the section called “Match Rules”</a>). + If the bus does not have enough resources the <code class="literal">org.freedesktop.DBus.Error.OOM</code> + error is returned. + </p></div><div class="sect3" title="org.freedesktop.DBus.RemoveMatch"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-remove-match"></a><code class="literal">org.freedesktop.DBus.RemoveMatch</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + RemoveMatch (in STRING rule) + </pre><p> + Message arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Match rule to remove from the connection</td></tr></tbody></table></div><p> + Removes the first rule that matches (see <a class="xref" href="#message-bus-routing-match-rules" title="Match Rules">the section called “Match Rules”</a>). + If the rule is not found the <code class="literal">org.freedesktop.DBus.Error.MatchRuleNotFound</code> + error is returned. + </p></div><div class="sect3" title="org.freedesktop.DBus.GetId"><div class="titlepage"><div><div><h4 class="title"><a name="bus-messages-get-id"></a><code class="literal">org.freedesktop.DBus.GetId</code></h4></div></div></div><p> + As a method: + </p><pre class="programlisting"> + GetId (out STRING id) + </pre><p> + Reply arguments: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col></colgroup><thead><tr><th>Argument</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>0</td><td>STRING</td><td>Unique ID identifying the bus daemon</td></tr></tbody></table></div><p> + Gets the unique ID of the bus. The unique ID here is shared among all addresses the + bus daemon is listening on (TCP, UNIX domain socket, etc.) and its format is described in + <a class="xref" href="#uuids" title="UUIDs">the section called “UUIDs”</a>. Each address the bus is listening on also has its own unique + ID, as described in <a class="xref" href="#addresses" title="Server Addresses">the section called “Server Addresses”</a>. The per-bus and per-address IDs are not related. + There is also a per-machine ID, described in <a class="xref" href="#standard-interfaces-peer" title="org.freedesktop.DBus.Peer">the section called “<code class="literal">org.freedesktop.DBus.Peer</code>”</a> and returned + by org.freedesktop.DBus.Peer.GetMachineId(). + For a desktop session bus, the bus ID can be used as a way to uniquely identify a user's session. + </p></div></div></div><div class="glossary" title="Glossary"><div class="titlepage"><div><div><h2 class="title"><a name="id324439"></a>Glossary</h2></div></div></div><p> + This glossary defines some of the terms used in this specification. + </p><dl><dt><a name="term-bus-name"></a>Bus Name</dt><dd><p> + The message bus maintains an association between names and + connections. (Normally, there's one connection per application.) A + bus name is simply an identifier used to locate connections. For + example, the hypothetical <code class="literal">com.yoyodyne.Screensaver</code> + name might be used to send a message to a screensaver from Yoyodyne + Corporation. An application is said to <em class="firstterm">own</em> a + name if the message bus has associated the application's connection + with the name. Names may also have <em class="firstterm">queued + owners</em> (see <a class="xref" href="#term-queued-owner" title="Queued Name Owner">Queued Name Owner</a>). + The bus assigns a unique name to each connection, + see <a class="xref" href="#term-unique-name" title="Unique Connection Name">Unique Connection Name</a>. Other names + can be thought of as "well-known names" and are + used to find applications that offer specific functionality. + </p></dd><dt><a name="term-message"></a>Message</dt><dd><p> + A message is the atomic unit of communication via the D-Bus + protocol. It consists of a <em class="firstterm">header</em> and a + <em class="firstterm">body</em>; the body is made up of + <em class="firstterm">arguments</em>. + </p></dd><dt><a name="term-message-bus"></a>Message Bus</dt><dd><p> + The message bus is a special application that forwards + or routes messages between a group of applications + connected to the message bus. It also manages + <em class="firstterm">names</em> used for routing + messages. + </p></dd><dt><a name="term-name"></a>Name</dt><dd><p> + See <a class="xref" href="#term-bus-name" title="Bus Name">Bus Name</a>. "Name" may + also be used to refer to some of the other names + in D-Bus, such as interface names. + </p></dd><dt><a name="namespace"></a>Namespace</dt><dd><p> + Used to prevent collisions when defining new interfaces or bus + names. The convention used is the same one Java uses for defining + classes: a reversed domain name. + </p></dd><dt><a name="term-object"></a>Object</dt><dd><p> + Each application contains <em class="firstterm">objects</em>, which have + <em class="firstterm">interfaces</em> and + <em class="firstterm">methods</em>. Objects are referred to by a name, + called a <em class="firstterm">path</em>. + </p></dd><dt><a name="one-to-one"></a>One-to-One</dt><dd><p> + An application talking directly to another application, without going + through a message bus. One-to-one connections may be "peer to peer" or + "client to server." The D-Bus protocol has no concept of client + vs. server after a connection has authenticated; the flow of messages + is symmetrical (full duplex). + </p></dd><dt><a name="term-path"></a>Path</dt><dd><p> + Object references (object names) in D-Bus are organized into a + filesystem-style hierarchy, so each object is named by a path. As in + LDAP, there's no difference between "files" and "directories"; a path + can refer to an object, while still having child objects below it. + </p></dd><dt><a name="term-queued-owner"></a>Queued Name Owner</dt><dd><p> + Each bus name has a primary owner; messages sent to the name go to the + primary owner. However, certain names also maintain a queue of + secondary owners "waiting in the wings." If the primary owner releases + the name, then the first secondary owner in the queue automatically + becomes the new owner of the name. + </p></dd><dt><a name="term-service"></a>Service</dt><dd><p> + A service is an executable that can be launched by the bus daemon. + Services normally guarantee some particular features, for example they + may guarantee that they will request a specific name such as + "org.freedesktop.Screensaver", have a singleton object + "/org/freedesktop/Application", and that object will implement the + interface "org.freedesktop.ScreensaverControl". + </p></dd><dt><a name="term-service-description-files"></a>Service Description Files</dt><dd><p> + ".service files" tell the bus about service applications that can be + launched (see <a class="xref" href="#term-service" title="Service">Service</a>). Most importantly they + provide a mapping from bus names to services that will request those + names when they start up. + </p></dd><dt><a name="term-unique-name"></a>Unique Connection Name</dt><dd><p> + The special name automatically assigned to each connection by the + message bus. This name will never change owner, and will be unique + (never reused during the lifetime of the message bus). + It will begin with a ':' character. + </p></dd></dl></div><div class="footnotes"><br><hr width="100" align="left"><div class="footnote"><p><sup>[<a name="ftn.id321252" href="#id321252" class="para">1</a>] </sup>Lockfiles are used instead of real file + locking <code class="literal">fcntl()</code> because real locking + implementations are still flaky on network + filesystems.</p></div><div class="footnote"><p><sup>[<a name="ftn.id323183" href="#id323183" class="para">2</a>] </sup> + The D-Bus reference implementation actually honors the + <code class="literal">$(localstatedir)</code> configure option + for this address, on both client and server side. + </p></div></div></div></body></html> diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml new file mode 100644 index 00000000..b5866e53 --- /dev/null +++ b/doc/dbus-specification.xml @@ -0,0 +1,4086 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" +"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" +[ +]> + +<article id="index"> + <articleinfo> + <title>D-Bus Specification</title> + <releaseinfo>Version 0.12</releaseinfo> + <date>7 November 2006</date> + <authorgroup> + <author> + <firstname>Havoc</firstname> + <surname>Pennington</surname> + <affiliation> + <orgname>Red Hat, Inc.</orgname> + <address> + <email>hp@pobox.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Anders</firstname> + <surname>Carlsson</surname> + <affiliation> + <orgname>CodeFactory AB</orgname> + <address> + <email>andersca@codefactory.se</email> + </address> + </affiliation> + </author> + <author> + <firstname>Alexander</firstname> + <surname>Larsson</surname> + <affiliation> + <orgname>Red Hat, Inc.</orgname> + <address> + <email>alexl@redhat.com</email> + </address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + + <sect1 id="introduction"> + <title>Introduction</title> + <para> + D-Bus is a system for low-latency, low-overhead, easy to use + interprocess communication (IPC). In more detail: + <itemizedlist> + <listitem> + <para> + D-Bus is <emphasis>low-latency</emphasis> because it is designed + to avoid round trips and allow asynchronous operation, much like + the X protocol. + </para> + </listitem> + <listitem> + <para> + D-Bus is <emphasis>low-overhead</emphasis> because it uses a + binary protocol, and does not have to convert to and from a text + format such as XML. Because D-Bus is intended for potentially + high-resolution same-machine IPC, not primarily for Internet IPC, + this is an interesting optimization. + </para> + </listitem> + <listitem> + <para> + D-Bus is <emphasis>easy to use</emphasis> because it works in terms + of <firstterm>messages</firstterm> rather than byte streams, and + automatically handles a lot of the hard IPC issues. Also, the D-Bus + library is designed to be wrapped in a way that lets developers use + their framework's existing object/type system, rather than learning + a new one specifically for IPC. + </para> + </listitem> + </itemizedlist> + </para> + + <para> + The base D-Bus protocol is a one-to-one (peer-to-peer or client-server) + protocol, specified in <xref linkend="message-protocol"/>. That is, it is + a system for one application to talk to a single other + application. However, the primary intended application of the protocol is the + D-Bus <firstterm>message bus</firstterm>, specified in <xref + linkend="message-bus"/>. The message bus is a special application that + accepts connections from multiple other applications, and forwards + messages among them. + </para> + + <para> + Uses of D-Bus include notification of system changes (notification of when + a camera is plugged in to a computer, or a new version of some software + has been installed), or desktop interoperability, for example a file + monitoring service or a configuration service. + </para> + + <para> + D-Bus is designed for two specific use cases: + <itemizedlist> + <listitem> + <para> + A "system bus" for notifications from the system to user sessions, + and to allow the system to request input from user sessions. + </para> + </listitem> + <listitem> + <para> + A "session bus" used to implement desktop environments such as + GNOME and KDE. + </para> + </listitem> + </itemizedlist> + D-Bus is not intended to be a generic IPC system for any possible + application, and intentionally omits many features found in other + IPC systems for this reason. + </para> + + <para> + At the same time, the bus daemons offer a number of features not found in + other IPC systems, such as single-owner "bus names" (similar to X + selections), on-demand startup of services, and security policies. + In many ways, these features are the primary motivation for developing + D-Bus; other systems would have sufficed if IPC were the only goal. + </para> + + <para> + D-Bus may turn out to be useful in unanticipated applications, but future + versions of this spec and the reference implementation probably will not + incorporate features that interfere with the core use cases. + </para> + + <para> + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in RFC 2119. However, the + document could use a serious audit to be sure it makes sense to do + so. Also, they are not capitalized. + </para> + + <sect2 id="stability"> + <title>Protocol and Specification Stability</title> + <para> + The D-Bus protocol is frozen (only compatible extensions are allowed) as + of November 8, 2006. However, this specification could still use a fair + bit of work to make interoperable reimplementation possible without + reference to the D-Bus reference implementation. Thus, this + specification is not marked 1.0. To mark it 1.0, we'd like to see + someone invest significant effort in clarifying the specification + language, and growing the specification to cover more aspects of the + reference implementation's behavior. + </para> + <para> + Until this work is complete, any attempt to reimplement D-Bus will + probably require looking at the reference implementation and/or asking + questions on the D-Bus mailing list about intended behavior. + Questions on the list are very welcome. + </para> + <para> + Nonetheless, this document should be a useful starting point and is + to our knowledge accurate, though incomplete. + </para> + </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 same type system and format for + serializing data. Each type of value has a wire format. + 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>. + </para> + + <sect2 id="message-protocol-signatures"> + <title>Type Signatures</title> + + <para> + The D-Bus protocol does not include type tags in the marshaled data; a + block of marshaled values must have a known <firstterm>type + signature</firstterm>. The type signature is made up of <firstterm>type + codes</firstterm>. A type code is an ASCII character representing the + type of a value. Because ASCII characters are used, the type signature + will always form a valid ASCII string. A simple string compare + determines whether two type signatures are equivalent. + </para> + + <para> + As a simple example, the type code for 32-bit integer (<literal>INT32</literal>) is + the ASCII character 'i'. So the signature for a block of values + containing a single <literal>INT32</literal> would be: + <programlisting> + "i" + </programlisting> + A block of values containing two <literal>INT32</literal> would have this signature: + <programlisting> + "ii" + </programlisting> + </para> + + <para> + All <firstterm>basic</firstterm> types work like + <literal>INT32</literal> in this example. To marshal and unmarshal + basic types, you simply read one value from the data + block corresponding to each type code in the signature. + In addition to basic types, there are four <firstterm>container</firstterm> + types: <literal>STRUCT</literal>, <literal>ARRAY</literal>, <literal>VARIANT</literal>, + and <literal>DICT_ENTRY</literal>. + </para> + + <para> + <literal>STRUCT</literal> has a type code, ASCII character 'r', but this type + code does not appear in signatures. Instead, ASCII characters + '(' and ')' are used to mark the beginning and end of the struct. + So for example, a struct containing two integers would have this + signature: + <programlisting> + "(ii)" + </programlisting> + Structs can be nested, so for example a struct containing + an integer and another struct: + <programlisting> + "(i(ii))" + </programlisting> + The value block storing that struct would contain three integers; the + type signature allows you to distinguish "(i(ii))" from "((ii)i)" or + "(iii)" or "iii". + </para> + + <para> + The <literal>STRUCT</literal> type code 'r' is not currently used in the D-Bus protocol, + but is useful in code that implements the protocol. This type code + is specified to allow such code to interoperate in non-protocol contexts. + </para> + + <para> + Empty structures are not allowed; there must be at least one + type code between the parentheses. + </para> + + <para> + <literal>ARRAY</literal> has ASCII character 'a' as type code. The array type code must be + followed by a <firstterm>single complete type</firstterm>. The single + complete type following the array is the type of each array element. So + the simple example is: + <programlisting> + "ai" + </programlisting> + which is an array of 32-bit integers. But an array can be of any type, + such as this array-of-struct-with-two-int32-fields: + <programlisting> + "a(ii)" + </programlisting> + Or this array of array of integer: + <programlisting> + "aai" + </programlisting> + </para> + + <para> + The phrase <firstterm>single complete type</firstterm> deserves some + definition. A single complete type is a basic type code, a variant type code, + an array with its element type, or a struct with its fields. + So the following signatures are not single complete types: + <programlisting> + "aa" + </programlisting> + <programlisting> + "(ii" + </programlisting> + <programlisting> + "ii)" + </programlisting> + And the following signatures contain multiple complete types: + <programlisting> + "ii" + </programlisting> + <programlisting> + "aiai" + </programlisting> + <programlisting> + "(ii)(ii)" + </programlisting> + Note however that a single complete type may <emphasis>contain</emphasis> + multiple other single complete types. + </para> + + <para> + <literal>VARIANT</literal> has ASCII character 'v' as its type code. A marshaled value of + type <literal>VARIANT</literal> will have the signature of a single complete type as part + of the <emphasis>value</emphasis>. This signature will be followed by a + marshaled value of that type. + </para> + + <para> + A <literal>DICT_ENTRY</literal> works exactly like a struct, but rather + than parentheses it uses curly braces, and it has more restrictions. + The restrictions are: it occurs only as an array element type; it has + exactly two single complete types inside the curly braces; the first + single complete type (the "key") must be a basic type rather than a + container type. Implementations must not accept dict entries outside of + arrays, must not accept dict entries with zero, one, or more than two + fields, and must not accept dict entries with non-basic-typed keys. A + dict entry is always a key-value pair. + </para> + + <para> + The first field in the <literal>DICT_ENTRY</literal> is always the key. + A message is considered corrupt if the same key occurs twice in the same + array of <literal>DICT_ENTRY</literal>. However, for performance reasons + implementations are not required to reject dicts with duplicate keys. + </para> + + <para> + In most languages, an array of dict entry would be represented as a + map, hash table, or dict object. + </para> + + <para> + The following table summarizes the D-Bus types. + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Code</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>INVALID</literal></entry> + <entry>0 (ASCII NUL)</entry> + <entry>Not a valid type code, used to terminate signatures</entry> + </row><row> + <entry><literal>BYTE</literal></entry> + <entry>121 (ASCII 'y')</entry> + <entry>8-bit unsigned integer</entry> + </row><row> + <entry><literal>BOOLEAN</literal></entry> + <entry>98 (ASCII 'b')</entry> + <entry>Boolean value, 0 is <literal>FALSE</literal> and 1 is <literal>TRUE</literal>. Everything else is invalid.</entry> + </row><row> + <entry><literal>INT16</literal></entry> + <entry>110 (ASCII 'n')</entry> + <entry>16-bit signed integer</entry> + </row><row> + <entry><literal>UINT16</literal></entry> + <entry>113 (ASCII 'q')</entry> + <entry>16-bit unsigned integer</entry> + </row><row> + <entry><literal>INT32</literal></entry> + <entry>105 (ASCII 'i')</entry> + <entry>32-bit signed integer</entry> + </row><row> + <entry><literal>UINT32</literal></entry> + <entry>117 (ASCII 'u')</entry> + <entry>32-bit unsigned integer</entry> + </row><row> + <entry><literal>INT64</literal></entry> + <entry>120 (ASCII 'x')</entry> + <entry>64-bit signed integer</entry> + </row><row> + <entry><literal>UINT64</literal></entry> + <entry>116 (ASCII 't')</entry> + <entry>64-bit unsigned integer</entry> + </row><row> + <entry><literal>DOUBLE</literal></entry> + <entry>100 (ASCII 'd')</entry> + <entry>IEEE 754 double</entry> + </row><row> + <entry><literal>STRING</literal></entry> + <entry>115 (ASCII 's')</entry> + <entry>UTF-8 string (<emphasis>must</emphasis> be valid UTF-8). Must be nul terminated and contain no other nul bytes.</entry> + </row><row> + <entry><literal>OBJECT_PATH</literal></entry> + <entry>111 (ASCII 'o')</entry> + <entry>Name of an object instance</entry> + </row><row> + <entry><literal>SIGNATURE</literal></entry> + <entry>103 (ASCII 'g')</entry> + <entry>A type signature</entry> + </row><row> + <entry><literal>ARRAY</literal></entry> + <entry>97 (ASCII 'a')</entry> + <entry>Array</entry> + </row><row> + <entry><literal>STRUCT</literal></entry> + <entry>114 (ASCII 'r'), 40 (ASCII '('), 41 (ASCII ')')</entry> + <entry>Struct</entry> + </row><row> + <entry><literal>VARIANT</literal></entry> + <entry>118 (ASCII 'v') </entry> + <entry>Variant type (the type of the value is part of the value itself)</entry> + </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> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + + </sect2> + + <sect2 id="message-protocol-marshaling"> + <title>Marshaling (Wire Format)</title> + + <para> + Given a type signature, a block of bytes can be converted into typed + values. This section describes the format of the block of bytes. Byte + order and alignment issues are handled uniformly for all D-Bus types. + </para> + + <para> + A block of bytes has an associated byte order. The byte order + has to be discovered in some way; for D-Bus messages, the + byte order is part of the message header as described in + <xref linkend="message-protocol-messages"/>. For now, assume + that the byte order is known to be either little endian or big + endian. + </para> + + <para> + Each value in a block of bytes is aligned "naturally," for example + 4-byte values are aligned to a 4-byte boundary, and 8-byte values to an + 8-byte boundary. To properly align a value, <firstterm>alignment + padding</firstterm> may be necessary. The alignment padding must always + be the minimum required padding to properly align the following value; + and it must always be made up of nul bytes. The alignment padding must + not be left uninitialized (it can't contain garbage), and more padding + than required must not be used. + </para> + + <para> + Given all this, the types are marshaled on the wire as follows: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Encoding</entry> + <entry>Alignment</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>INVALID</literal></entry> + <entry>Not applicable; cannot be marshaled.</entry> + <entry>N/A</entry> + </row><row> + <entry><literal>BYTE</literal></entry> + <entry>A single 8-bit byte.</entry> + <entry>1</entry> + </row><row> + <entry><literal>BOOLEAN</literal></entry> + <entry>As for <literal>UINT32</literal>, but only 0 and 1 are valid values.</entry> + <entry>4</entry> + </row><row> + <entry><literal>INT16</literal></entry> + <entry>16-bit signed integer in the message's byte order.</entry> + <entry>2</entry> + </row><row> + <entry><literal>UINT16</literal></entry> + <entry>16-bit unsigned integer in the message's byte order.</entry> + <entry>2</entry> + </row><row> + <entry><literal>INT32</literal></entry> + <entry>32-bit signed integer in the message's byte order.</entry> + <entry>4</entry> + </row><row> + <entry><literal>UINT32</literal></entry> + <entry>32-bit unsigned integer in the message's byte order.</entry> + <entry>4</entry> + </row><row> + <entry><literal>INT64</literal></entry> + <entry>64-bit signed integer in the message's byte order.</entry> + <entry>8</entry> + </row><row> + <entry><literal>UINT64</literal></entry> + <entry>64-bit unsigned integer in the message's byte order.</entry> + <entry>8</entry> + </row><row> + <entry><literal>DOUBLE</literal></entry> + <entry>64-bit IEEE 754 double in the message's byte order.</entry> + <entry>8</entry> + </row><row> + <entry><literal>STRING</literal></entry> + <entry>A <literal>UINT32</literal> indicating the string's + length in bytes excluding its terminating nul, followed by + non-nul string data of the given length, followed by a terminating nul + byte. + </entry> + <entry> + 4 (for the length) + </entry> + </row><row> + <entry><literal>OBJECT_PATH</literal></entry> + <entry>Exactly the same as <literal>STRING</literal> except the + content must be a valid object path (see below). + </entry> + <entry> + 4 (for the length) + </entry> + </row><row> + <entry><literal>SIGNATURE</literal></entry> + <entry>The same as <literal>STRING</literal> except the length is a single + byte (thus signatures have a maximum length of 255) + and the content must be a valid signature (see below). + </entry> + <entry> + 1 + </entry> + </row><row> + <entry><literal>ARRAY</literal></entry> + <entry> + A <literal>UINT32</literal> giving the length of the array data in bytes, followed by + alignment padding to the alignment boundary of the array element type, + followed by each array element. The array length is from the + end of the alignment padding to the end of the last element, + i.e. it does not include the padding after the length, + or any padding after the last element. + Arrays have a maximum length defined to be 2 to the 26th power or + 67108864. Implementations must not send or accept arrays exceeding this + length. + </entry> + <entry> + 4 (for the length) + </entry> + </row><row> + <entry><literal>STRUCT</literal></entry> + <entry> + A struct must start on an 8-byte boundary regardless of the + type of the struct fields. The struct value consists of each + field marshaled in sequence starting from that 8-byte + alignment boundary. + </entry> + <entry> + 8 + </entry> + </row><row> + <entry><literal>VARIANT</literal></entry> + <entry> + A variant type has a marshaled <literal>SIGNATURE</literal> + followed by a marshaled value with the type + given in the signature. + Unlike a message signature, the variant signature + can contain only a single complete type. + So "i", "ai" or "(ii)" is OK, but "ii" is not. + </entry> + <entry> + 1 (alignment of the signature) + </entry> + </row><row> + <entry><literal>DICT_ENTRY</literal></entry> + <entry> + Identical to STRUCT. + </entry> + <entry> + 8 + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + + <sect3 id="message-protocol-marshaling-object-path"> + <title>Valid Object Paths</title> + + <para> + An object path is a name used to refer to an object instance. + Conceptually, each participant in a D-Bus message exchange may have + any number of object instances (think of C++ or Java objects) and each + such instance will have a path. Like a filesystem, the object + instances in an application form a hierarchical tree. + </para> + + <para> + The following rules define a valid object path. Implementations must + not send or accept messages with invalid object paths. + <itemizedlist> + <listitem> + <para> + The path may be of any length. + </para> + </listitem> + <listitem> + <para> + The path must begin with an ASCII '/' (integer 47) character, + and must consist of elements separated by slash characters. + </para> + </listitem> + <listitem> + <para> + Each element must only contain the ASCII characters + "[A-Z][a-z][0-9]_" + </para> + </listitem> + <listitem> + <para> + No element may be the empty string. + </para> + </listitem> + <listitem> + <para> + Multiple '/' characters cannot occur in sequence. + </para> + </listitem> + <listitem> + <para> + A trailing '/' character is not allowed unless the + path is the root path (a single '/' character). + </para> + </listitem> + </itemizedlist> + </para> + + </sect3> + + + <sect3 id="message-protocol-marshaling-signature"> + <title>Valid Signatures</title> + <para> + An implementation must not send or accept invalid signatures. + Valid signatures will conform to the following rules: + <itemizedlist> + <listitem> + <para> + The signature ends with a nul byte. + </para> + </listitem> + <listitem> + <para> + The signature is a list of single complete types. + Arrays must have element types, and structs must + have both open and close parentheses. + </para> + </listitem> + <listitem> + <para> + Only type codes and open and close parentheses are + allowed in the signature. The <literal>STRUCT</literal> type code + is not allowed in signatures, because parentheses + are used instead. + </para> + </listitem> + <listitem> + <para> + The maximum depth of container type nesting is 32 array type + codes and 32 open parentheses. This implies that the maximum + total depth of recursion is 64, for an "array of array of array + of ... struct of struct of struct of ..." where there are 32 + array and 32 struct. + </para> + </listitem> + <listitem> + <para> + The maximum length of a signature is 255. + </para> + </listitem> + <listitem> + <para> + Signatures must be nul-terminated. + </para> + </listitem> + </itemizedlist> + </para> + </sect3> + + </sect2> + + <sect2 id="message-protocol-messages"> + <title>Message Format</title> + + <para> + A message consists of a header and a body. The header is a block of + values with a fixed signature and meaning. The body is a separate block + of values, with a signature specified in the header. + </para> + + <para> + The length of the header must be a multiple of 8, allowing the body to + begin on an 8-byte boundary when storing the entire message in a single + buffer. If the header does not naturally end on an 8-byte boundary + up to 7 bytes of nul-initialized alignment padding must be added. + </para> + + <para> + The message body need not end on an 8-byte boundary. + </para> + + <para> + The maximum length of a message, including header, header alignment padding, + and body is 2 to the 27th power or 134217728. Implementations must not + send or accept messages exceeding this size. + </para> + + <para> + The signature of the header is: + <programlisting> + "yyyyuua(yv)" + </programlisting> + Written out more readably, this is: + <programlisting> + BYTE, BYTE, BYTE, BYTE, UINT32, UINT32, ARRAY of STRUCT of (BYTE,VARIANT) + </programlisting> + </para> + + <para> + These values have the following meanings: + <informaltable> + <tgroup cols="2"> + <thead> + <row> + <entry>Value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>1st <literal>BYTE</literal></entry> + <entry>Endianness flag; ASCII 'l' for little-endian + or ASCII 'B' for big-endian. Both header and body are + in this endianness.</entry> + </row> + <row> + <entry>2nd <literal>BYTE</literal></entry> + <entry><firstterm>Message type</firstterm>. Unknown types must be ignored. + Currently-defined types are described below. + </entry> + </row> + <row> + <entry>3rd <literal>BYTE</literal></entry> + <entry>Bitwise OR of flags. Unknown flags + must be ignored. Currently-defined flags are described below. + </entry> + </row> + <row> + <entry>4th <literal>BYTE</literal></entry> + <entry>Major protocol version of the sending application. If + the major protocol version of the receiving application does not + match, the applications will not be able to communicate and the + D-Bus connection must be disconnected. The major protocol + version for this version of the specification is 1. + </entry> + </row> + <row> + <entry>1st <literal>UINT32</literal></entry> + <entry>Length in bytes of the message body, starting + from the end of the header. The header ends after + its alignment padding to an 8-boundary. + </entry> + </row> + <row> + <entry>2nd <literal>UINT32</literal></entry> + <entry>The serial of this message, used as a cookie + by the sender to identify the reply corresponding + to this request. This must not be zero. + </entry> + </row> + <row> + <entry><literal>ARRAY</literal> of <literal>STRUCT</literal> of (<literal>BYTE</literal>,<literal>VARIANT</literal>)</entry> + <entry>An array of zero or more <firstterm>header + fields</firstterm> where the byte is the field code, and the + variant is the field value. The message type determines + which fields are required. + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + <firstterm>Message types</firstterm> that can appear in the second byte + of the header are: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional name</entry> + <entry>Decimal value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>INVALID</literal></entry> + <entry>0</entry> + <entry>This is an invalid type.</entry> + </row> + <row> + <entry><literal>METHOD_CALL</literal></entry> + <entry>1</entry> + <entry>Method call.</entry> + </row> + <row> + <entry><literal>METHOD_RETURN</literal></entry> + <entry>2</entry> + <entry>Method reply with returned data.</entry> + </row> + <row> + <entry><literal>ERROR</literal></entry> + <entry>3</entry> + <entry>Error reply. If the first argument exists and is a + string, it is an error message.</entry> + </row> + <row> + <entry><literal>SIGNAL</literal></entry> + <entry>4</entry> + <entry>Signal emission.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + Flags that can appear in the third byte of the header: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional name</entry> + <entry>Hex value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>NO_REPLY_EXPECTED</literal></entry> + <entry>0x1</entry> + <entry>This message does not expect method return replies or + error replies; the reply can be omitted as an + optimization. However, it is compliant with this specification + to return the reply despite this flag and the only harm + from doing so is extra network traffic. + </entry> + </row> + <row> + <entry><literal>NO_AUTO_START</literal></entry> + <entry>0x2</entry> + <entry>The bus must not launch an owner + for the destination name in response to this message. + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + + <sect3 id="message-protocol-header-fields"> + <title>Header Fields</title> + + <para> + The array at the end of the header contains <firstterm>header + fields</firstterm>, where each field is a 1-byte field code followed + by a field value. A header must contain the required header fields for + its message type, and zero or more of any optional header + fields. Future versions of this protocol specification may add new + fields. Implementations must ignore fields they do not + understand. Implementations must not invent their own header fields; + only changes to this specification may introduce new header fields. + </para> + + <para> + Again, if an implementation sees a header field code that it does not + expect, it must ignore that field, as it will be part of a new + (but compatible) version of this specification. This also applies + to known header fields appearing in unexpected messages, for + example: if a signal has a reply serial it must be ignored + even though it has no meaning as of this version of the spec. + </para> + + <para> + However, implementations must not send or accept known header fields + with the wrong type stored in the field value. So for example a + message with an <literal>INTERFACE</literal> field of type + <literal>UINT32</literal> would be considered corrupt. + </para> + + <para> + Here are the currently-defined header fields: + <informaltable> + <tgroup cols="5"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Decimal Code</entry> + <entry>Type</entry> + <entry>Required In</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>INVALID</literal></entry> + <entry>0</entry> + <entry>N/A</entry> + <entry>not allowed</entry> + <entry>Not a valid field name (error if it appears in a message)</entry> + </row> + <row> + <entry><literal>PATH</literal></entry> + <entry>1</entry> + <entry><literal>OBJECT_PATH</literal></entry> + <entry><literal>METHOD_CALL</literal>, <literal>SIGNAL</literal></entry> + <entry>The object to send a call to, + or the object a signal is emitted from. + The special path + <literal>/org/freedesktop/DBus/Local</literal> is reserved; + implementations should not send messages with this path, + and the reference implementation of the bus daemon will + disconnect any application that attempts to do so. + </entry> + </row> + <row> + <entry><literal>INTERFACE</literal></entry> + <entry>2</entry> + <entry><literal>STRING</literal></entry> + <entry><literal>SIGNAL</literal></entry> + <entry> + The interface to invoke a method call on, or + that a signal is emitted from. Optional for + method calls, required for signals. + The special interface + <literal>org.freedesktop.DBus.Local</literal> is reserved; + implementations should not send messages with this + interface, and the reference implementation of the bus + daemon will disconnect any application that attempts to + do so. + </entry> + </row> + <row> + <entry><literal>MEMBER</literal></entry> + <entry>3</entry> + <entry><literal>STRING</literal></entry> + <entry><literal>METHOD_CALL</literal>, <literal>SIGNAL</literal></entry> + <entry>The member, either the method name or signal name.</entry> + </row> + <row> + <entry><literal>ERROR_NAME</literal></entry> + <entry>4</entry> + <entry><literal>STRING</literal></entry> + <entry><literal>ERROR</literal></entry> + <entry>The name of the error that occurred, for errors</entry> + </row> + <row> + <entry><literal>REPLY_SERIAL</literal></entry> + <entry>5</entry> + <entry><literal>UINT32</literal></entry> + <entry><literal>ERROR</literal>, <literal>METHOD_RETURN</literal></entry> + <entry>The serial number of the message this message is a reply + to. (The serial number is the second <literal>UINT32</literal> in the header.)</entry> + </row> + <row> + <entry><literal>DESTINATION</literal></entry> + <entry>6</entry> + <entry><literal>STRING</literal></entry> + <entry>optional</entry> + <entry>The name of the connection this message is intended for. + Only used in combination with the message bus, see + <xref linkend="message-bus"/>.</entry> + </row> + <row> + <entry><literal>SENDER</literal></entry> + <entry>7</entry> + <entry><literal>STRING</literal></entry> + <entry>optional</entry> + <entry>Unique name of the sending connection. + The message bus fills in this field so it is reliable; the field is + only meaningful in combination with the message bus.</entry> + </row> + <row> + <entry><literal>SIGNATURE</literal></entry> + <entry>8</entry> + <entry><literal>SIGNATURE</literal></entry> + <entry>optional</entry> + <entry>The signature of the message body. + If omitted, it is assumed to be the + empty signature "" (i.e. the body must be 0-length).</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + </sect3> + </sect2> + + <sect2 id="message-protocol-names"> + <title>Valid Names</title> + <para> + The various names in D-Bus messages have some restrictions. + </para> + <para> + There is a <firstterm>maximum name length</firstterm> + of 255 which applies to bus names, interfaces, and members. + </para> + <sect3 id="message-protocol-names-interface"> + <title>Interface names</title> + <para> + Interfaces have names with type <literal>STRING</literal>, meaning that + they must be valid UTF-8. However, there are also some + additional restrictions that apply to interface names + specifically: + <itemizedlist> + <listitem><para>Interface names are composed of 1 or more elements separated by + a period ('.') character. All elements must contain at least + one character. + </para> + </listitem> + <listitem><para>Each element must only contain the ASCII characters + "[A-Z][a-z][0-9]_" and must not begin with a digit. + </para> + </listitem> + + <listitem><para>Interface names must contain at least one '.' (period) + character (and thus at least two elements). + </para></listitem> + + <listitem><para>Interface names must not begin with a '.' (period) character.</para></listitem> + <listitem><para>Interface names must not exceed the maximum name length.</para></listitem> + </itemizedlist> + </para> + </sect3> + <sect3 id="message-protocol-names-bus"> + <title>Bus names</title> + <para> + Connections have one or more bus names associated with them. + A connection has exactly one bus name that is a unique connection + name. The unique connection name remains with the connection for + its entire lifetime. + A bus name is of type <literal>STRING</literal>, + meaning that it must be valid UTF-8. However, there are also + some additional restrictions that apply to bus names + specifically: + <itemizedlist> + <listitem><para>Bus names that start with a colon (':') + character are unique connection names. + </para> + </listitem> + <listitem><para>Bus names are composed of 1 or more elements separated by + a period ('.') character. All elements must contain at least + one character. + </para> + </listitem> + <listitem><para>Each element must only contain the ASCII characters + "[A-Z][a-z][0-9]_-". Only elements that are part of a unique + connection name may begin with a digit, elements in + other bus names must not begin with a digit. + </para> + </listitem> + + <listitem><para>Bus names must contain at least one '.' (period) + character (and thus at least two elements). + </para></listitem> + + <listitem><para>Bus names must not begin with a '.' (period) character.</para></listitem> + <listitem><para>Bus names must not exceed the maximum name length.</para></listitem> + </itemizedlist> + </para> + <para> + Note that the hyphen ('-') character is allowed in bus names but + not in interface names. + </para> + </sect3> + <sect3 id="message-protocol-names-member"> + <title>Member names</title> + <para> + Member (i.e. method or signal) names: + <itemizedlist> + <listitem><para>Must only contain the ASCII characters + "[A-Z][a-z][0-9]_" and may not begin with a + digit.</para></listitem> + <listitem><para>Must not contain the '.' (period) character.</para></listitem> + <listitem><para>Must not exceed the maximum name length.</para></listitem> + <listitem><para>Must be at least 1 byte in length.</para></listitem> + </itemizedlist> + </para> + </sect3> + <sect3 id="message-protocol-names-error"> + <title>Error names</title> + <para> + Error names have the same restrictions as interface names. + </para> + </sect3> + </sect2> + + <sect2 id="message-protocol-types"> + <title>Message Types</title> + <para> + Each of the message types (<literal>METHOD_CALL</literal>, <literal>METHOD_RETURN</literal>, <literal>ERROR</literal>, and + <literal>SIGNAL</literal>) has its own expected usage conventions and header fields. + This section describes these conventions. + </para> + <sect3 id="message-protocol-types-method"> + <title>Method Calls</title> + <para> + Some messages invoke an operation on a remote object. These are + called method call messages and have the type tag <literal>METHOD_CALL</literal>. Such + messages map naturally to methods on objects in a typical program. + </para> + <para> + A method call message is required to have a <literal>MEMBER</literal> header field + indicating the name of the method. Optionally, the message has an + <literal>INTERFACE</literal> field giving the interface the method is a part of. In the + absence of an <literal>INTERFACE</literal> field, if two interfaces on the same object have + a method with the same name, it is undefined which of the two methods + will be invoked. Implementations may also choose to return an error in + this ambiguous case. However, if a method name is unique + implementations must not require an interface field. + </para> + <para> + Method call messages also include a <literal>PATH</literal> field + indicating the object to invoke the method on. If the call is passing + through a message bus, the message will also have a + <literal>DESTINATION</literal> field giving the name of the connection + to receive the message. + </para> + <para> + When an application handles a method call message, it is required to + return a reply. The reply is identified by a <literal>REPLY_SERIAL</literal> header field + indicating the serial number of the <literal>METHOD_CALL</literal> being replied to. The + reply can have one of two types; either <literal>METHOD_RETURN</literal> or <literal>ERROR</literal>. + </para> + <para> + If the reply has type <literal>METHOD_RETURN</literal>, the arguments to the reply message + are the return value(s) or "out parameters" of the method call. + If the reply has type <literal>ERROR</literal>, then an "exception" has been thrown, + and the call fails; no return value will be provided. It makes + no sense to send multiple replies to the same method call. + </para> + <para> + Even if a method call has no return values, a <literal>METHOD_RETURN</literal> + reply is required, so the caller will know the method + was successfully processed. + </para> + <para> + The <literal>METHOD_RETURN</literal> or <literal>ERROR</literal> reply message must have the <literal>REPLY_SERIAL</literal> + header field. + </para> + <para> + If a <literal>METHOD_CALL</literal> message has the flag <literal>NO_REPLY_EXPECTED</literal>, + then as an optimization the application receiving the method + call may choose to omit the reply message (regardless of + whether the reply would have been <literal>METHOD_RETURN</literal> or <literal>ERROR</literal>). + However, it is also acceptable to ignore the <literal>NO_REPLY_EXPECTED</literal> + flag and reply anyway. + </para> + <para> + Unless a message has the flag <literal>NO_AUTO_START</literal>, if the + destination name does not exist then a program to own the destination + name will be started before the message is delivered. The message + will be held until the new program is successfully started or has + failed to start; in case of failure, an error will be returned. This + flag is only relevant in the context of a message bus, it is ignored + during one-to-one communication with no intermediate bus. + </para> + <sect4 id="message-protocol-types-method-apis"> + <title>Mapping method calls to native APIs</title> + <para> + APIs for D-Bus may map method calls to a method call in a specific + programming language, such as C++, or may map a method call written + in an IDL to a D-Bus message. + </para> + <para> + In APIs of this nature, arguments to a method are often termed "in" + (which implies sent in the <literal>METHOD_CALL</literal>), or "out" (which implies + returned in the <literal>METHOD_RETURN</literal>). Some APIs such as CORBA also have + "inout" arguments, which are both sent and received, i.e. the caller + passes in a value which is modified. Mapped to D-Bus, an "inout" + argument is equivalent to an "in" argument, followed by an "out" + argument. You can't pass things "by reference" over the wire, so + "inout" is purely an illusion of the in-process API. + </para> + <para> + Given a method with zero or one return values, followed by zero or more + arguments, where each argument may be "in", "out", or "inout", the + caller constructs a message by appending each "in" or "inout" argument, + in order. "out" arguments are not represented in the caller's message. + </para> + <para> + The recipient constructs a reply by appending first the return value + if any, then each "out" or "inout" argument, in order. + "in" arguments are not represented in the reply message. + </para> + <para> + Error replies are normally mapped to exceptions in languages that have + exceptions. + </para> + <para> + In converting from native APIs to D-Bus, it is perhaps nice to + map D-Bus naming conventions ("FooBar") to native conventions + such as "fooBar" or "foo_bar" automatically. This is OK + as long as you can say that the native API is one that + was specifically written for D-Bus. It makes the most sense + when writing object implementations that will be exported + over the bus. Object proxies used to invoke remote D-Bus + objects probably need the ability to call any D-Bus method, + and thus a magic name mapping like this could be a problem. + </para> + <para> + This specification doesn't require anything of native API bindings; + the preceding is only a suggested convention for consistency + among bindings. + </para> + </sect4> + </sect3> + + <sect3 id="message-protocol-types-signal"> + <title>Signal Emission</title> + <para> + Unlike method calls, signal emissions have no replies. + A signal emission is simply a single message of type <literal>SIGNAL</literal>. + It must have three header fields: <literal>PATH</literal> giving the object + the signal was emitted from, plus <literal>INTERFACE</literal> and <literal>MEMBER</literal> giving + the fully-qualified name of the signal. The <literal>INTERFACE</literal> header is required + for signals, though it is optional for method calls. + </para> + </sect3> + + <sect3 id="message-protocol-types-errors"> + <title>Errors</title> + <para> + Messages of type <literal>ERROR</literal> are most commonly replies + to a <literal>METHOD_CALL</literal>, but may be returned in reply + to any kind of message. The message bus for example + will return an <literal>ERROR</literal> in reply to a signal emission if + the bus does not have enough memory to send the signal. + </para> + <para> + An <literal>ERROR</literal> may have any arguments, but if the first + argument is a <literal>STRING</literal>, it must be an error message. + The error message may be logged or shown to the user + in some way. + </para> + </sect3> + + <sect3 id="message-protocol-types-notation"> + <title>Notation in this document</title> + <para> + This document uses a simple pseudo-IDL to describe particular method + calls and signals. Here is an example of a method call: + <programlisting> + org.freedesktop.DBus.StartServiceByName (in STRING name, in UINT32 flags, + out UINT32 resultcode) + </programlisting> + This means <literal>INTERFACE</literal> = org.freedesktop.DBus, <literal>MEMBER</literal> = StartServiceByName, + <literal>METHOD_CALL</literal> arguments are <literal>STRING</literal> and <literal>UINT32</literal>, <literal>METHOD_RETURN</literal> argument + is <literal>UINT32</literal>. Remember that the <literal>MEMBER</literal> field can't contain any '.' (period) + characters so it's known that the last part of the name in + the "IDL" is the member name. + </para> + <para> + In C++ that might end up looking like this: + <programlisting> + unsigned int org::freedesktop::DBus::StartServiceByName (const char *name, + unsigned int flags); + </programlisting> + or equally valid, the return value could be done as an argument: + <programlisting> + void org::freedesktop::DBus::StartServiceByName (const char *name, + unsigned int flags, + unsigned int *resultcode); + </programlisting> + It's really up to the API designer how they want to make + this look. You could design an API where the namespace wasn't used + in C++, using STL or Qt, using varargs, or whatever you wanted. + </para> + <para> + Signals are written as follows: + <programlisting> + org.freedesktop.DBus.NameLost (STRING name) + </programlisting> + Signals don't specify "in" vs. "out" because only + a single direction is possible. + </para> + <para> + It isn't especially encouraged to use this lame pseudo-IDL in actual + API implementations; you might use the native notation for the + language you're using, or you might use COM or CORBA IDL, for example. + </para> + </sect3> + </sect2> + + <sect2 id="message-protocol-handling-invalid"> + <title>Invalid Protocol and Spec Extensions</title> + + <para> + For security reasons, the D-Bus protocol should be strictly parsed and + validated, with the exception of defined extension points. Any invalid + protocol or spec violations should result in immediately dropping the + connection without notice to the other end. Exceptions should be + carefully considered, e.g. an exception may be warranted for a + well-understood idiosyncrasy of a widely-deployed implementation. In + cases where the other end of a connection is 100% trusted and known to + be friendly, skipping validation for performance reasons could also make + sense in certain cases. + </para> + + <para> + Generally speaking violations of the "must" requirements in this spec + should be considered possible attempts to exploit security, and violations + of the "should" suggestions should be considered legitimate (though perhaps + they should generate an error in some cases). + </para> + + <para> + The following extension points are built in to D-Bus on purpose and must + not be treated as invalid protocol. The extension points are intended + for use by future versions of this spec, they are not intended for third + parties. At the moment, the only way a third party could extend D-Bus + without breaking interoperability would be to introduce a way to negotiate new + feature support as part of the auth protocol, using EXTENSION_-prefixed + commands. There is not yet a standard way to negotiate features. + <itemizedlist> + <listitem> + <para> + In the authentication protocol (see <xref linkend="auth-protocol"/>) unknown + commands result in an ERROR rather than a disconnect. This enables + future extensions to the protocol. Commands starting with EXTENSION_ are + reserved for third parties. + </para> + </listitem> + <listitem> + <para> + The authentication protocol supports pluggable auth mechanisms. + </para> + </listitem> + <listitem> + <para> + The address format (see <xref linkend="addresses"/>) supports new + kinds of transport. + </para> + </listitem> + <listitem> + <para> + Messages with an unknown type (something other than + <literal>METHOD_CALL</literal>, <literal>METHOD_RETURN</literal>, + <literal>ERROR</literal>, <literal>SIGNAL</literal>) are ignored. + Unknown-type messages must still be well-formed in the same way + as the known messages, however. They still have the normal + header and body. + </para> + </listitem> + <listitem> + <para> + Header fields with an unknown or unexpected field code must be ignored, + though again they must still be well-formed. + </para> + </listitem> + <listitem> + <para> + New standard interfaces (with new methods and signals) can of course be added. + </para> + </listitem> + </itemizedlist> + </para> + + </sect2> + + </sect1> + + <sect1 id="auth-protocol"> + <title>Authentication Protocol</title> + <para> + Before the flow of messages begins, two applications must + authenticate. A simple plain-text protocol is used for + authentication; this protocol is a SASL profile, and maps fairly + directly from the SASL specification. The message encoding is + NOT used here, only plain text messages. + </para> + <para> + In examples, "C:" and "S:" indicate lines sent by the client and + server respectively. + </para> + <sect2 id="auth-protocol-overview"> + <title>Protocol Overview</title> + <para> + The protocol is a line-based protocol, where each line ends with + \r\n. Each line begins with an all-caps ASCII command name containing + only the character range [A-Z_], a space, then any arguments for the + command, then the \r\n ending the line. The protocol is + case-sensitive. All bytes must be in the ASCII character set. + + Commands from the client to the server are as follows: + + <itemizedlist> + <listitem><para>AUTH [mechanism] [initial-response]</para></listitem> + <listitem><para>CANCEL</para></listitem> + <listitem><para>BEGIN</para></listitem> + <listitem><para>DATA <data in hex encoding></para></listitem> + <listitem><para>ERROR [human-readable error explanation]</para></listitem> + </itemizedlist> + + From server to client are as follows: + + <itemizedlist> + <listitem><para>REJECTED <space-separated list of mechanism names></para></listitem> + <listitem><para>OK <GUID in hex></para></listitem> + <listitem><para>DATA <data in hex encoding></para></listitem> + <listitem><para>ERROR</para></listitem> + </itemizedlist> + </para> + <para> + Unofficial extensions to the command set must begin with the letters + "EXTENSION_", to avoid conflicts with future official commands. + For example, "EXTENSION_COM_MYDOMAIN_DO_STUFF". + </para> + </sect2> + <sect2 id="auth-nul-byte"> + <title>Special credentials-passing nul byte</title> + <para> + Immediately after connecting to the server, the client must send a + single nul byte. This byte may be accompanied by credentials + information on some operating systems that use sendmsg() with + SCM_CREDS or SCM_CREDENTIALS to pass credentials over UNIX domain + sockets. However, the nul byte must be sent even on other kinds of + socket, and even on operating systems that do not require a byte to be + sent in order to transmit credentials. The text protocol described in + this document begins after the single nul byte. If the first byte + received from the client is not a nul byte, the server may disconnect + that client. + </para> + <para> + A nul byte in any context other than the initial byte is an error; + the protocol is ASCII-only. + </para> + <para> + The credentials sent along with the nul byte may be used with the + SASL mechanism EXTERNAL. + </para> + </sect2> + <sect2 id="auth-command-auth"> + <title>AUTH command</title> + <para> + If an AUTH command has no arguments, it is a request to list + available mechanisms. The server must respond with a REJECTED + command listing the mechanisms it understands, or with an error. + </para> + <para> + If an AUTH command specifies a mechanism, and the server supports + said mechanism, the server should begin exchanging SASL + challenge-response data with the client using DATA commands. + </para> + <para> + If the server does not support the mechanism given in the AUTH + command, it must send either a REJECTED command listing the mechanisms + it does support, or an error. + </para> + <para> + If the [initial-response] argument is provided, it is intended for use + with mechanisms that have no initial challenge (or an empty initial + challenge), as if it were the argument to an initial DATA command. If + the selected mechanism has an initial challenge and [initial-response] + was provided, the server should reject authentication by sending + REJECTED. + </para> + <para> + If authentication succeeds after exchanging DATA commands, + an OK command must be sent to the client. + </para> + <para> + The first octet received by the client after the \r\n of the OK + command must be the first octet of the authenticated/encrypted + stream of D-Bus messages. + </para> + <para> + The first octet received by the server after the \r\n of the BEGIN + command from the client must be the first octet of the + authenticated/encrypted stream of D-Bus messages. + </para> + </sect2> + <sect2 id="auth-command-cancel"> + <title>CANCEL Command</title> + <para> + At any time up to sending the BEGIN command, the client may send a + CANCEL command. On receiving the CANCEL command, the server must + send a REJECTED command and abort the current authentication + exchange. + </para> + </sect2> + <sect2 id="auth-command-data"> + <title>DATA Command</title> + <para> + The DATA command may come from either client or server, and simply + contains a hex-encoded block of data to be interpreted + according to the SASL mechanism in use. + </para> + <para> + Some SASL mechanisms support sending an "empty string"; + FIXME we need some way to do this. + </para> + </sect2> + <sect2 id="auth-command-begin"> + <title>BEGIN Command</title> + <para> + The BEGIN command acknowledges that the client has received an + OK command from the server, and that the stream of messages + is about to begin. + </para> + <para> + The first octet received by the server after the \r\n of the BEGIN + command from the client must be the first octet of the + authenticated/encrypted stream of D-Bus messages. + </para> + </sect2> + <sect2 id="auth-command-rejected"> + <title>REJECTED Command</title> + <para> + The REJECTED command indicates that the current authentication + exchange has failed, and further exchange of DATA is inappropriate. + The client would normally try another mechanism, or try providing + different responses to challenges. + </para><para> + Optionally, the REJECTED command has a space-separated list of + available auth mechanisms as arguments. If a server ever provides + a list of supported mechanisms, it must provide the same list + each time it sends a REJECTED message. Clients are free to + ignore all lists received after the first. + </para> + </sect2> + <sect2 id="auth-command-ok"> + <title>OK Command</title> + <para> + The OK command indicates that the client has been authenticated, + and that further communication will be a stream of D-Bus messages + (optionally encrypted, as negotiated) rather than this protocol. + </para> + <para> + The first octet received by the client after the \r\n of the OK + command must be the first octet of the authenticated/encrypted + stream of D-Bus messages. + </para> + <para> + The client must respond to the OK command by sending a BEGIN + command, followed by its stream of messages, or by disconnecting. + The server must not accept additional commands using this protocol + after the OK command has been sent. + </para> + <para> + The OK command has one argument, which is the GUID of the server. + See <xref linkend="addresses"/> for more on server GUIDs. + </para> + </sect2> + <sect2 id="auth-command-error"> + <title>ERROR Command</title> + <para> + The ERROR command indicates that either server or client did not + know a command, does not accept the given command in the current + context, or did not understand the arguments to the command. This + allows the protocol to be extended; a client or server can send a + command present or permitted only in new protocol versions, and if + an ERROR is received instead of an appropriate response, fall back + to using some other technique. + </para> + <para> + If an ERROR is sent, the server or client that sent the + error must continue as if the command causing the ERROR had never been + received. However, the the server or client receiving the error + should try something other than whatever caused the error; + if only canceling/rejecting the authentication. + </para> + <para> + If the D-Bus protocol changes incompatibly at some future time, + applications implementing the new protocol would probably be able to + check for support of the new protocol by sending a new command and + receiving an ERROR from applications that don't understand it. Thus the + ERROR feature of the auth protocol is an escape hatch that lets us + negotiate extensions or changes to the D-Bus protocol in the future. + </para> + </sect2> + <sect2 id="auth-examples"> + <title>Authentication examples</title> + + <para> + <figure> + <title>Example of successful magic cookie authentication</title> + <programlisting> + (MAGIC_COOKIE is a made up mechanism) + + C: AUTH MAGIC_COOKIE 3138363935333137393635383634 + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + <figure> + <title>Example of finding out mechanisms then picking one</title> + <programlisting> + C: AUTH + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + <figure> + <title>Example of client sends unknown command then falls back to regular auth</title> + <programlisting> + C: FOOBAR + S: ERROR + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + <figure> + <title>Example of server doesn't support initial auth mechanism</title> + <programlisting> + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + <figure> + <title>Example of wrong password or the like followed by successful retry</title> + <programlisting> + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: REJECTED + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + <figure> + <title>Example of skey cancelled and restarted</title> + <programlisting> + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: CANCEL + S: REJECTED + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + </para> + </sect2> + <sect2 id="auth-states"> + <title>Authentication state diagrams</title> + + <para> + This section documents the auth protocol in terms of + a state machine for the client and the server. This is + probably the most robust way to implement the protocol. + </para> + + <sect3 id="auth-states-client"> + <title>Client states</title> + + <para> + To more precisely describe the interaction between the + protocol state machine and the authentication mechanisms the + following notation is used: MECH(CHALL) means that the + server challenge CHALL was fed to the mechanism MECH, which + returns one of + + <itemizedlist> + <listitem> + <para> + CONTINUE(RESP) means continue the auth conversation + and send RESP as the response to the server; + </para> + </listitem> + + <listitem> + <para> + OK(RESP) means that after sending RESP to the server + the client side of the auth conversation is finished + and the server should return "OK"; + </para> + </listitem> + + <listitem> + <para> + ERROR means that CHALL was invalid and could not be + processed. + </para> + </listitem> + </itemizedlist> + + Both RESP and CHALL may be empty. + </para> + + <para> + The Client starts by getting an initial response from the + default mechanism and sends AUTH MECH RESP, or AUTH MECH if + the mechanism did not provide an initial response. If the + mechanism returns CONTINUE, the client starts in state + <emphasis>WaitingForData</emphasis>, if the mechanism + returns OK the client starts in state + <emphasis>WaitingForOK</emphasis>. + </para> + + <para> + The client should keep track of available mechanisms and + which it mechanisms it has already attempted. This list is + used to decide which AUTH command to send. When the list is + exhausted, the client should give up and close the + connection. + </para> + + <formalpara> + <title><emphasis>WaitingForData</emphasis></title> + <para> + <itemizedlist> + <listitem> + <para> + Receive DATA CHALL + <simplelist> + <member> + MECH(CHALL) returns CONTINUE(RESP) → send + DATA RESP, goto + <emphasis>WaitingForData</emphasis> + </member> + + <member> + MECH(CHALL) returns OK(RESP) → send DATA + RESP, goto <emphasis>WaitingForOK</emphasis> + </member> + + <member> + MECH(CHALL) returns ERROR → send ERROR + [msg], goto <emphasis>WaitingForData</emphasis> + </member> + </simplelist> + </para> + </listitem> + + <listitem> + <para> + Receive REJECTED [mechs] → + send AUTH [next mech], goto + WaitingForData or <emphasis>WaitingForOK</emphasis> + </para> + </listitem> + <listitem> + <para> + Receive ERROR → send + CANCEL, goto + <emphasis>WaitingForReject</emphasis> + </para> + </listitem> + <listitem> + <para> + Receive OK → send + BEGIN, terminate auth + conversation, authenticated + </para> + </listitem> + <listitem> + <para> + Receive anything else → send + ERROR, goto + <emphasis>WaitingForData</emphasis> + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + <formalpara> + <title><emphasis>WaitingForOK</emphasis></title> + <para> + <itemizedlist> + <listitem> + <para> + Receive OK → send BEGIN, terminate auth + conversation, <emphasis>authenticated</emphasis> + </para> + </listitem> + <listitem> + <para> + Receive REJECT [mechs] → send AUTH [next mech], + goto <emphasis>WaitingForData</emphasis> or + <emphasis>WaitingForOK</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive DATA → send CANCEL, goto + <emphasis>WaitingForReject</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive ERROR → send CANCEL, goto + <emphasis>WaitingForReject</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive anything else → send ERROR, goto + <emphasis>WaitingForOK</emphasis> + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + <formalpara> + <title><emphasis>WaitingForReject</emphasis></title> + <para> + <itemizedlist> + <listitem> + <para> + Receive REJECT [mechs] → send AUTH [next mech], + goto <emphasis>WaitingForData</emphasis> or + <emphasis>WaitingForOK</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive anything else → terminate auth + conversation, disconnect + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + </sect3> + + <sect3 id="auth-states-server"> + <title>Server states</title> + + <para> + For the server MECH(RESP) means that the client response + RESP was fed to the the mechanism MECH, which returns one of + + <itemizedlist> + <listitem> + <para> + CONTINUE(CHALL) means continue the auth conversation and + send CHALL as the challenge to the client; + </para> + </listitem> + + <listitem> + <para> + OK means that the client has been successfully + authenticated; + </para> + </listitem> + + <listitem> + <para> + REJECT means that the client failed to authenticate or + there was an error in RESP. + </para> + </listitem> + </itemizedlist> + + The server starts out in state + <emphasis>WaitingForAuth</emphasis>. If the client is + rejected too many times the server must disconnect the + client. + </para> + + <formalpara> + <title><emphasis>WaitingForAuth</emphasis></title> + <para> + <itemizedlist> + + <listitem> + <para> + Receive AUTH → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive AUTH MECH RESP + + <simplelist> + <member> + MECH not valid mechanism → send REJECTED + [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </member> + + <member> + MECH(RESP) returns CONTINUE(CHALL) → send + DATA CHALL, goto + <emphasis>WaitingForData</emphasis> + </member> + + <member> + MECH(RESP) returns OK → send OK, goto + <emphasis>WaitingForBegin</emphasis> + </member> + + <member> + MECH(RESP) returns REJECT → send REJECTED + [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </member> + </simplelist> + </para> + </listitem> + + <listitem> + <para> + Receive BEGIN → terminate + auth conversation, disconnect + </para> + </listitem> + + <listitem> + <para> + Receive ERROR → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive anything else → send + ERROR, goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + + <formalpara> + <title><emphasis>WaitingForData</emphasis></title> + <para> + <itemizedlist> + <listitem> + <para> + Receive DATA RESP + <simplelist> + <member> + MECH(RESP) returns CONTINUE(CHALL) → send + DATA CHALL, goto + <emphasis>WaitingForData</emphasis> + </member> + + <member> + MECH(RESP) returns OK → send OK, goto + <emphasis>WaitingForBegin</emphasis> + </member> + + <member> + MECH(RESP) returns REJECT → send REJECTED + [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </member> + </simplelist> + </para> + </listitem> + + <listitem> + <para> + Receive BEGIN → terminate auth conversation, + disconnect + </para> + </listitem> + + <listitem> + <para> + Receive CANCEL → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive ERROR → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive anything else → send ERROR, goto + <emphasis>WaitingForData</emphasis> + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + <formalpara> + <title><emphasis>WaitingForBegin</emphasis></title> + <para> + <itemizedlist> + <listitem> + <para> + Receive BEGIN → terminate auth conversation, + client authenticated + </para> + </listitem> + + <listitem> + <para> + Receive CANCEL → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive ERROR → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive anything else → send ERROR, goto + <emphasis>WaitingForBegin</emphasis> + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + </sect3> + + </sect2> + <sect2 id="auth-mechanisms"> + <title>Authentication mechanisms</title> + <para> + This section describes some new authentication mechanisms. + D-Bus also allows any standard SASL mechanism of course. + </para> + <sect3 id="auth-mechanisms-sha"> + <title>DBUS_COOKIE_SHA1</title> + <para> + The DBUS_COOKIE_SHA1 mechanism is designed to establish that a client + has the ability to read a private file owned by the user being + authenticated. If the client can prove that it has access to a secret + cookie stored in this file, then the client is authenticated. + Thus the security of DBUS_COOKIE_SHA1 depends on a secure home + directory. + </para> + <para> + Throughout this description, "hex encoding" must output the digits + from a to f in lower-case; the digits A to F must not be used + in the DBUS_COOKIE_SHA1 mechanism. + </para> + <para> + Authentication proceeds as follows: + <itemizedlist> + <listitem> + <para> + The client sends the username it would like to authenticate + as, hex-encoded. + </para> + </listitem> + <listitem> + <para> + The server sends the name of its "cookie context" (see below); a + space character; the integer ID of the secret cookie the client + must demonstrate knowledge of; a space character; then a + randomly-generated challenge string, all of this hex-encoded into + one, single string. + </para> + </listitem> + <listitem> + <para> + The client locates the cookie and generates its own + randomly-generated challenge string. The client then concatenates + the server's decoded challenge, a ":" character, its own challenge, + another ":" character, and the cookie. It computes the SHA-1 hash + of this composite string as a hex digest. It concatenates the + client's challenge string, a space character, and the SHA-1 hex + digest, hex-encodes the result and sends it back to the server. + </para> + </listitem> + <listitem> + <para> + The server generates the same concatenated string used by the + client and computes its SHA-1 hash. It compares the hash with + the hash received from the client; if the two hashes match, the + client is authenticated. + </para> + </listitem> + </itemizedlist> + </para> + <para> + Each server has a "cookie context," which is a name that identifies a + set of cookies that apply to that server. A sample context might be + "org_freedesktop_session_bus". Context names must be valid ASCII, + nonzero length, and may not contain the characters slash ("/"), + backslash ("\"), space (" "), newline ("\n"), carriage return ("\r"), + tab ("\t"), or period ("."). There is a default context, + "org_freedesktop_general" that's used by servers that do not specify + otherwise. + </para> + <para> + Cookies are stored in a user's home directory, in the directory + <filename>~/.dbus-keyrings/</filename>. This directory must + not be readable or writable by other users. If it is, + clients and servers must ignore it. The directory + contains cookie files named after the cookie context. + </para> + <para> + A cookie file contains one cookie per line. Each line + has three space-separated fields: + <itemizedlist> + <listitem> + <para> + The cookie ID number, which must be a non-negative integer and + may not be used twice in the same file. + </para> + </listitem> + <listitem> + <para> + The cookie's creation time, in UNIX seconds-since-the-epoch + format. + </para> + </listitem> + <listitem> + <para> + The cookie itself, a hex-encoded random block of bytes. The cookie + may be of any length, though obviously security increases + as the length increases. + </para> + </listitem> + </itemizedlist> + </para> + <para> + Only server processes modify the cookie file. + They must do so with this procedure: + <itemizedlist> + <listitem> + <para> + Create a lockfile name by appending ".lock" to the name of the + cookie file. The server should attempt to create this file + using <literal>O_CREAT | O_EXCL</literal>. If file creation + fails, the lock fails. Servers should retry for a reasonable + period of time, then they may choose to delete an existing lock + to keep users from having to manually delete a stale + lock. <footnote><para>Lockfiles are used instead of real file + locking <literal>fcntl()</literal> because real locking + implementations are still flaky on network + filesystems.</para></footnote> + </para> + </listitem> + <listitem> + <para> + Once the lockfile has been created, the server loads the cookie + file. It should then delete any cookies that are old (the + timeout can be fairly short), or more than a reasonable + time in the future (so that cookies never accidentally + become permanent, if the clock was set far into the future + at some point). If no recent keys remain, the + server may generate a new key. + </para> + </listitem> + <listitem> + <para> + The pruned and possibly added-to cookie file + must be resaved atomically (using a temporary + file which is rename()'d). + </para> + </listitem> + <listitem> + <para> + The lock must be dropped by deleting the lockfile. + </para> + </listitem> + </itemizedlist> + </para> + <para> + Clients need not lock the file in order to load it, + because servers are required to save the file atomically. + </para> + </sect3> + </sect2> + </sect1> + <sect1 id="addresses"> + <title>Server Addresses</title> + <para> + Server addresses consist of a transport name followed by a colon, and + then an optional, comma-separated list of keys and values in the form key=value. + Each value is escaped. + </para> + <para> + For example: + <programlisting>unix:path=/tmp/dbus-test</programlisting> + Which is the address to a unix socket with the path /tmp/dbus-test. + </para> + <para> + Value escaping is similar to URI escaping but simpler. + <itemizedlist> + <listitem> + <para> + The set of optionally-escaped bytes is: + <literal>[0-9A-Za-z_-/.\]</literal>. To escape, each + <emphasis>byte</emphasis> (note, not character) which is not in the + set of optionally-escaped bytes must be replaced with an ASCII + percent (<literal>%</literal>) and the value of the byte in hex. + The hex value must always be two digits, even if the first digit is + zero. The optionally-escaped bytes may be escaped if desired. + </para> + </listitem> + <listitem> + <para> + To unescape, append each byte in the value; if a byte is an ASCII + percent (<literal>%</literal>) character then append the following + hex value instead. It is an error if a <literal>%</literal> byte + does not have two hex digits following. It is an error if a + non-optionally-escaped byte is seen unescaped. + </para> + </listitem> + </itemizedlist> + The set of optionally-escaped bytes is intended to preserve address + readability and convenience. + </para> + + <para> + A server may specify a key-value pair with the key <literal>guid</literal> + and the value a hex-encoded 16-byte sequence. <xref linkend="uuids"/> + describes the format of the <literal>guid</literal> field. If present, + this UUID may be used to distinguish one server address from another. A + server should use a different UUID for each address it listens on. For + example, if a message bus daemon offers both UNIX domain socket and TCP + connections, but treats clients the same regardless of how they connect, + those two connections are equivalent post-connection but should have + distinct UUIDs to distinguish the kinds of connection. + </para> + + <para> + The intent of the address UUID feature is to allow a client to avoid + opening multiple identical connections to the same server, by allowing the + client to check whether an address corresponds to an already-existing + connection. Comparing two addresses is insufficient, because addresses + can be recycled by distinct servers, and equivalent addresses may look + different if simply compared as strings (for example, the host in a TCP + address can be given as an IP address or as a hostname). + </para> + + <para> + Note that the address key is <literal>guid</literal> even though the + rest of the API and documentation says "UUID," for historical reasons. + </para> + + <para> + [FIXME clarify if attempting to connect to each is a requirement + or just a suggestion] + When connecting to a server, multiple server addresses can be + separated by a semi-colon. The library will then try to connect + to the first address and if that fails, it'll try to connect to + the next one specified, and so forth. For example + <programlisting>unix:path=/tmp/dbus-test;unix:path=/tmp/dbus-test2</programlisting> + </para> + + </sect1> + + <sect1 id="transports"> + <title>Transports</title> + <para> + [FIXME we need to specify in detail each transport and its possible arguments] + + Current transports include: unix domain sockets (including + abstract namespace on linux), TCP/IP, and a debug/testing transport using + in-process pipes. Future possible transports include one that + tunnels over X11 protocol. + </para> + + <sect2 id="transports-unix-domain-sockets"> + <title>Unix Domain Sockets</title> + <para> + Unix domain sockets can be either paths in the file system or on Linux + kernels, they can be abstract which are similar to paths but + do not show up in the file system. + </para> + + <para> + When a socket is opened by the D-Bus library it truncates the path + name right before the first trailing Nul byte. This is true for both + normal paths and abstract paths. Note that this is a departure from + previous versions of D-Bus that would create sockets with a fixed + length path name. Names which were shorter than the fixed length + would be padded by Nul bytes. + </para> + </sect2> + </sect1> + + <sect1 id="naming-conventions"> + <title>Naming Conventions</title> + + <para> + D-Bus namespaces are all lowercase and correspond to reversed domain + names, as with Java. e.g. "org.freedesktop" + </para> + <para> + Interface, signal, method, and property names are "WindowsStyleCaps", note + that the first letter is capitalized, unlike Java. + </para> + <para> + Object paths are normally all lowercase with underscores used rather than + hyphens. + </para> + </sect1> + + <sect1 id="uuids"> + <title>UUIDs</title> + <para> + A working D-Bus implementation uses universally-unique IDs in two places. + First, each server address has a UUID identifying the address, + as described in <xref linkend="addresses"/>. Second, each operating + system kernel instance running a D-Bus client or server has a UUID + identifying that kernel, retrieved by invoking the method + org.freedesktop.DBus.Peer.GetMachineId() (see <xref + linkend="standard-interfaces-peer"/>). + </para> + <para> + The term "UUID" in this document is intended literally, i.e. an + identifier that is universally unique. It is not intended to refer to + RFC4122, and in fact the D-Bus UUID is not compatible with that RFC. + </para> + <para> + The UUID must contain 128 bits of data and be hex-encoded. The + hex-encoded string may not contain hyphens or other non-hex-digit + characters, and it must be exactly 32 characters long. To generate a + UUID, the current reference implementation concatenates 96 bits of random + data followed by the 32-bit time in seconds since the UNIX epoch (in big + endian byte order). + </para> + <para> + It would also be acceptable and probably better to simply generate 128 + bits of random data, as long as the random number generator is of high + quality. The timestamp could conceivably help if the random bits are not + very random. With a quality random number generator, collisions are + extremely unlikely even with only 96 bits, so it's somewhat academic. + </para> + <para> + Implementations should, however, stick to random data for the first 96 bits + of the UUID. + </para> + </sect1> + + <sect1 id="standard-interfaces"> + <title>Standard Interfaces</title> + <para> + See <xref linkend="message-protocol-types-notation"/> for details on + the notation used in this section. There are some standard interfaces + that may be useful across various D-Bus applications. + </para> + <sect2 id="standard-interfaces-peer"> + <title><literal>org.freedesktop.DBus.Peer</literal></title> + <para> + The <literal>org.freedesktop.DBus.Peer</literal> interface + has two methods: + <programlisting> + org.freedesktop.DBus.Peer.Ping () + org.freedesktop.DBus.Peer.GetMachineId (out STRING machine_uuid) + </programlisting> + </para> + <para> + On receipt of the <literal>METHOD_CALL</literal> message + <literal>org.freedesktop.DBus.Peer.Ping</literal>, an application should do + nothing other than reply with a <literal>METHOD_RETURN</literal> as + usual. It does not matter which object path a ping is sent to. The + reference implementation handles this method automatically. + </para> + <para> + On receipt of the <literal>METHOD_CALL</literal> message + <literal>org.freedesktop.DBus.Peer.GetMachineId</literal>, an application should + reply with a <literal>METHOD_RETURN</literal> containing a hex-encoded + UUID representing the identity of the machine the process is running on. + This UUID must be the same for all processes on a single system at least + until that system next reboots. It should be the same across reboots + if possible, but this is not always possible to implement and is not + guaranteed. + It does not matter which object path a GetMachineId is sent to. The + reference implementation handles this method automatically. + </para> + <para> + The UUID is intended to be per-instance-of-the-operating-system, so may represent + a virtual machine running on a hypervisor, rather than a physical machine. + Basically if two processes see the same UUID, they should also see the same + shared memory, UNIX domain sockets, process IDs, and other features that require + a running OS kernel in common between the processes. + </para> + <para> + The UUID is often used where other programs might use a hostname. Hostnames + can change without rebooting, however, or just be "localhost" - so the UUID + is more robust. + </para> + <para> + <xref linkend="uuids"/> explains the format of the UUID. + </para> + </sect2> + + <sect2 id="standard-interfaces-introspectable"> + <title><literal>org.freedesktop.DBus.Introspectable</literal></title> + <para> + This interface has one method: + <programlisting> + org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data) + </programlisting> + </para> + <para> + Objects instances may implement + <literal>Introspect</literal> which returns an XML description of + the object, including its interfaces (with signals and methods), objects + below it in the object path tree, and its properties. + </para> + <para> + <xref linkend="introspection-format"/> describes the format of this XML string. + </para> + </sect2> + <sect2 id="standard-interfaces-properties"> + <title><literal>org.freedesktop.DBus.Properties</literal></title> + <para> + Many native APIs will have a concept of object <firstterm>properties</firstterm> + or <firstterm>attributes</firstterm>. These can be exposed via the + <literal>org.freedesktop.DBus.Properties</literal> interface. + </para> + <para> + <programlisting> + org.freedesktop.DBus.Properties.Get (in STRING interface_name, + in STRING property_name, + out VARIANT value); + org.freedesktop.DBus.Properties.Set (in STRING interface_name, + in STRING property_name, + in VARIANT value); + org.freedesktop.DBus.Properties.GetAll (in STRING interface_name, + out DICT<STRING,VARIANT> props); + </programlisting> + </para> + <para> + The available properties and whether they are writable can be determined + by calling <literal>org.freedesktop.DBus.Introspectable.Introspect</literal>, + see <xref linkend="standard-interfaces-introspectable"/>. + </para> + <para> + An empty string may be provided for the interface name; in this case, + if there are multiple properties on an object with the same name, + the results are undefined (picking one by according to an arbitrary + deterministic rule, or returning an error, are the reasonable + possibilities). + </para> + </sect2> + </sect1> + + <sect1 id="introspection-format"> + <title>Introspection Data Format</title> + <para> + As described in <xref linkend="standard-interfaces-introspectable"/>, + objects may be introspected at runtime, returning an XML string + that describes the object. The same XML format may be used in + other contexts as well, for example as an "IDL" for generating + static language bindings. + </para> + <para> + Here is an example of introspection data: + <programlisting> + <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> + <node name="/org/freedesktop/sample_object"> + <interface name="org.freedesktop.SampleInterface"> + <method name="Frobate"> + <arg name="foo" type="i" direction="in"/> + <arg name="bar" type="s" direction="out"/> + <arg name="baz" type="a{us}" direction="out"/> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </method> + <method name="Bazify"> + <arg name="bar" type="(iiu)" direction="in"/> + <arg name="bar" type="v" direction="out"/> + </method> + <method name="Mogrify"> + <arg name="bar" type="(iiav)" direction="in"/> + </method> + <signal name="Changed"> + <arg name="new_value" type="b"/> + </signal> + <property name="Bar" type="y" access="readwrite"/> + </interface> + <node name="child_of_sample_object"/> + <node name="another_child_of_sample_object"/> + </node> + </programlisting> + </para> + <para> + A more formal DTD and spec needs writing, but here are some quick notes. + <itemizedlist> + <listitem> + <para> + Only the root <node> element can omit the node name, as it's + known to be the object that was introspected. If the root + <node> does have a name attribute, it must be an absolute + object path. If child <node> have object paths, they must be + relative. + </para> + </listitem> + <listitem> + <para> + If a child <node> has any sub-elements, then they + must represent a complete introspection of the child. + If a child <node> is empty, then it may or may + not have sub-elements; the child must be introspected + in order to find out. The intent is that if an object + knows that its children are "fast" to introspect + it can go ahead and return their information, but + otherwise it can omit it. + </para> + </listitem> + <listitem> + <para> + The direction element on <arg> may be omitted, + in which case it defaults to "in" for method calls + and "out" for signals. Signals only allow "out" + so while direction may be specified, it's pointless. + </para> + </listitem> + <listitem> + <para> + The possible directions are "in" and "out", + unlike CORBA there is no "inout" + </para> + </listitem> + <listitem> + <para> + The possible property access flags are + "readwrite", "read", and "write" + </para> + </listitem> + <listitem> + <para> + Multiple interfaces can of course be listed for + one <node>. + </para> + </listitem> + <listitem> + <para> + The "name" attribute on arguments is optional. + </para> + </listitem> + </itemizedlist> + </para> + <para> + Method, interface, property, and signal elements may have + "annotations", which are generic key/value pairs of metadata. + They are similar conceptually to Java's annotations and C# attributes. + Well-known annotations: + </para> + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Values (separated by ,)</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>org.freedesktop.DBus.Deprecated</entry> + <entry>true,false</entry> + <entry>Whether or not the entity is deprecated; defaults to false</entry> + </row> + <row> + <entry>org.freedesktop.DBus.GLib.CSymbol</entry> + <entry>(string)</entry> + <entry>The C symbol; may be used for methods and interfaces</entry> + </row> + <row> + <entry>org.freedesktop.DBus.Method.NoReply</entry> + <entry>true,false</entry> + <entry>If set, don't expect a reply to the method call; defaults to false.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </sect1> + <sect1 id="message-bus"> + <title>Message Bus Specification</title> + <sect2 id="message-bus-overview"> + <title>Message Bus Overview</title> + <para> + The message bus accepts connections from one or more applications. + Once connected, applications can exchange messages with other + applications that are also connected to the bus. + </para> + <para> + In order to route messages among connections, the message bus keeps a + mapping from names to connections. Each connection has one + unique-for-the-lifetime-of-the-bus name automatically assigned. + Applications may request additional names for a connection. Additional + names are usually "well-known names" such as + "org.freedesktop.TextEditor". When a name is bound to a connection, + that connection is said to <firstterm>own</firstterm> the name. + </para> + <para> + The bus itself owns a special name, <literal>org.freedesktop.DBus</literal>. + This name routes messages to the bus, allowing applications to make + administrative requests. For example, applications can ask the bus + to assign a name to a connection. + </para> + <para> + Each name may have <firstterm>queued owners</firstterm>. When an + application requests a name for a connection and the name is already in + use, the bus will optionally add the connection to a queue waiting for + the name. If the current owner of the name disconnects or releases + the name, the next connection in the queue will become the new owner. + </para> + + <para> + This feature causes the right thing to happen if you start two text + editors for example; the first one may request "org.freedesktop.TextEditor", + and the second will be queued as a possible owner of that name. When + the first exits, the second will take over. + </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. + </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. + </para> + </sect2> + + <sect2 id="message-bus-names"> + <title>Message Bus Names</title> + <para> + Each connection has at least one name, assigned at connection time and + returned in response to the + <literal>org.freedesktop.DBus.Hello</literal> method call. This + automatically-assigned name is called the connection's <firstterm>unique + name</firstterm>. Unique names are never reused for two different + connections to the same bus. + </para> + <para> + Ownership of a unique name is a prerequisite for interaction with + the message bus. It logically follows that the unique name is always + the first name that an application comes to own, and the last + one that it loses ownership of. + </para> + <para> + Unique connection names must begin with the character ':' (ASCII colon + character); bus names that are not unique names must not begin + with this character. (The bus must reject any attempt by an application + to manually request a name beginning with ':'.) This restriction + categorically prevents "spoofing"; messages sent to a unique name + will always go to the expected connection. + </para> + <para> + When a connection is closed, all the names that it owns are deleted (or + transferred to the next connection in the queue if any). + </para> + <para> + A connection can request additional names to be associated with it using + the <literal>org.freedesktop.DBus.RequestName</literal> message. <xref + linkend="message-protocol-names-bus"/> describes the format of a valid + name. These names can be released again using the + <literal>org.freedesktop.DBus.ReleaseName</literal> message. + </para> + + <sect3 id="bus-messages-request-name"> + <title><literal>org.freedesktop.DBus.RequestName</literal></title> + <para> + As a method: + <programlisting> + UINT32 RequestName (in STRING name, in UINT32 flags) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name to request</entry> + </row> + <row> + <entry>1</entry> + <entry>UINT32</entry> + <entry>Flags</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>UINT32</entry> + <entry>Return value</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + This method call should be sent to + <literal>org.freedesktop.DBus</literal> and asks the message bus to + assign the given name to the method caller. Each name maintains a + queue of possible owners, where the head of the queue is the primary + or current owner of the name. Each potential owner in the queue + maintains the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and + DBUS_NAME_FLAG_DO_NOT_QUEUE settings from its latest RequestName + call. When RequestName is invoked the following occurs: + <itemizedlist> + <listitem> + <para> + If the method caller is currently the primary owner of the name, + the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and DBUS_NAME_FLAG_DO_NOT_QUEUE + values are updated with the values from the new RequestName call, + and nothing further happens. + </para> + </listitem> + + <listitem> + <para> + If the current primary owner (head of the queue) has + DBUS_NAME_FLAG_ALLOW_REPLACEMENT set, and the RequestName + invocation has the DBUS_NAME_FLAG_REPLACE_EXISTING flag, then + the caller of RequestName replaces the current primary owner at + the head of the queue and the current primary owner moves to the + second position in the queue. If the caller of RequestName was + in the queue previously its flags are updated with the values from + the new RequestName in addition to moving it to the head of the queue. + </para> + </listitem> + + <listitem> + <para> + If replacement is not possible, and the method caller is + currently in the queue but not the primary owner, its flags are + updated with the values from the new RequestName call. + </para> + </listitem> + + <listitem> + <para> + If replacement is not possible, and the method caller is + currently not in the queue, the method caller is appended to the + queue. + </para> + </listitem> + + <listitem> + <para> + If any connection in the queue has DBUS_NAME_FLAG_DO_NOT_QUEUE + set and is not the primary owner, it is removed from the + queue. This can apply to the previous primary owner (if it + was replaced) or the method caller (if it updated the + DBUS_NAME_FLAG_DO_NOT_QUEUE flag while still stuck in the + queue, or if it was just added to the queue with that flag set). + </para> + </listitem> + </itemizedlist> + </para> + <para> + Note that DBUS_NAME_FLAG_REPLACE_EXISTING results in "jumping the + queue," even if another application already in the queue had specified + DBUS_NAME_FLAG_REPLACE_EXISTING. This comes up if a primary owner + that does not allow replacement goes away, and the next primary owner + does allow replacement. In this case, queued items that specified + DBUS_NAME_FLAG_REPLACE_EXISTING <emphasis>do not</emphasis> + automatically replace the new primary owner. In other words, + DBUS_NAME_FLAG_REPLACE_EXISTING is not saved, it is only used at the + time RequestName is called. This is deliberate to avoid an infinite loop + anytime two applications are both DBUS_NAME_FLAG_ALLOW_REPLACEMENT + and DBUS_NAME_FLAG_REPLACE_EXISTING. + </para> + <para> + The flags argument contains any of the following values logically ORed + together: + + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>DBUS_NAME_FLAG_ALLOW_REPLACEMENT</entry> + <entry>0x1</entry> + <entry> + + If an application A specifies this flag and succeeds in + becoming the owner of the name, and another application B + later calls RequestName with the + DBUS_NAME_FLAG_REPLACE_EXISTING flag, then application A + will lose ownership and receive a + <literal>org.freedesktop.DBus.NameLost</literal> signal, and + application B will become the new owner. If DBUS_NAME_FLAG_ALLOW_REPLACEMENT + is not specified by application A, or DBUS_NAME_FLAG_REPLACE_EXISTING + is not specified by application B, then application B will not replace + application A as the owner. + + </entry> + </row> + <row> + <entry>DBUS_NAME_FLAG_REPLACE_EXISTING</entry> + <entry>0x2</entry> + <entry> + + Try to replace the current owner if there is one. If this + flag is not set the application will only become the owner of + the name if there is no current owner. If this flag is set, + the application will replace the current owner if + the current owner specified DBUS_NAME_FLAG_ALLOW_REPLACEMENT. + + </entry> + </row> + <row> + <entry>DBUS_NAME_FLAG_DO_NOT_QUEUE</entry> + <entry>0x4</entry> + <entry> + + Without this flag, if an application requests a name that is + already owned, the application will be placed in a queue to + own the name when the current owner gives it up. If this + flag is given, the application will not be placed in the + queue, the request for the name will simply fail. This flag + also affects behavior when an application is replaced as + name owner; by default the application moves back into the + waiting queue, unless this flag was provided when the application + became the name owner. + + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + + The return code can be one of the following values: + + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER</entry> + <entry>1</entry> <entry>The caller is now the primary owner of + the name, replacing any previous owner. Either the name had no + owner before, or the caller specified + DBUS_NAME_FLAG_REPLACE_EXISTING and the current owner specified + DBUS_NAME_FLAG_ALLOW_REPLACEMENT.</entry> + </row> + <row> + <entry>DBUS_REQUEST_NAME_REPLY_IN_QUEUE</entry> + <entry>2</entry> + + <entry>The name already had an owner, + DBUS_NAME_FLAG_DO_NOT_QUEUE was not specified, and either + the current owner did not specify + DBUS_NAME_FLAG_ALLOW_REPLACEMENT or the requesting + application did not specify DBUS_NAME_FLAG_REPLACE_EXISTING. + </entry> + </row> + <row> + <entry>DBUS_REQUEST_NAME_REPLY_EXISTS</entry> <entry>3</entry> + <entry>The name already has an owner, + DBUS_NAME_FLAG_DO_NOT_QUEUE was specified, and either + DBUS_NAME_FLAG_ALLOW_REPLACEMENT was not specified by the + current owner, or DBUS_NAME_FLAG_REPLACE_EXISTING was not + specified by the requesting application.</entry> + </row> + <row> + <entry>DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER</entry> + <entry>4</entry> + <entry>The application trying to request ownership of a name is already the owner of it.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + </sect3> + + <sect3 id="bus-messages-release-name"> + <title><literal>org.freedesktop.DBus.ReleaseName</literal></title> + <para> + As a method: + <programlisting> + UINT32 ReleaseName (in STRING name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name to release</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>UINT32</entry> + <entry>Return value</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + This method call should be sent to + <literal>org.freedesktop.DBus</literal> and asks the message bus to + release the method caller's claim to the given name. If the caller is + the primary owner, a new primary owner will be selected from the + queue if any other owners are waiting. If the caller is waiting in + the queue for the name, the caller will removed from the queue and + will not be made an owner of the name if it later becomes available. + If there are no other owners in the queue for the name, it will be + removed from the bus entirely. + + The return code can be one of the following values: + + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>DBUS_RELEASE_NAME_REPLY_RELEASED</entry> + <entry>1</entry> <entry>The caller has released his claim on + the given name. Either the caller was the primary owner of + the name, and the name is now unused or taken by somebody + waiting in the queue for the name, or the caller was waiting + in the queue for the name and has now been removed from the + queue.</entry> + </row> + <row> + <entry>DBUS_RELEASE_NAME_REPLY_NON_EXISTENT</entry> + <entry>2</entry> + <entry>The given name does not exist on this bus.</entry> + </row> + <row> + <entry>DBUS_RELEASE_NAME_REPLY_NOT_OWNER</entry> + <entry>3</entry> + <entry>The caller was not the primary owner of this name, + and was also not waiting in the queue to own this name.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + </sect3> + </sect2> + + <sect2 id="message-bus-routing"> + <title>Message Bus Message Routing</title> + <para> + FIXME + </para> + <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. + </para> + <para> + Match rules are added using the AddMatch bus method + (see xref linkend="bus-messages-add-match"/>). Rules are + specified as a string of comma separated key/value pairs. + Excluding a key from the rule indicates a wildcard match. + For instance excluding the the member from a match rule but + adding a sender would let all messages from that sender through. + An example of a complete rule would be + "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo',path='/bar/foo',destination=':452345.34',arg2='bar'" + </para> + <para> + The following table describes the keys that can be used to create + a match rule: + The following table summarizes the D-Bus types. + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Key</entry> + <entry>Possible Values</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>type</literal></entry> + <entry>'signal', 'method_call', 'method_return', 'error'</entry> + <entry>Match on the message type. An example of a type match is type='signal'</entry> + </row> + <row> + <entry><literal>sender</literal></entry> + <entry>A bus or unique name (see <xref linkend="term-bus-name"/> + and <xref linkend="term-unique-name"/> respectively) + </entry> + <entry>Match messages sent by a particular sender. An example of a sender match + is sender='org.freedesktop.Hal'</entry> + </row> + <row> + <entry><literal>interface</literal></entry> + <entry>An interface name (see <xref linkend="message-protocol-names-interface"/>)</entry> + <entry>Match messages sent over or to a particular interface. An example of an + interface match is interface='org.freedesktop.Hal.Manager'. + If a message omits the interface header, it must not match any rule + that specifies this key.</entry> + </row> + <row> + <entry><literal>member</literal></entry> + <entry>Any valid method or signal name</entry> + <entry>Matches messages which have the give method or signal name. An example of + a member match is member='NameOwnerChanged'</entry> + </row> + <row> + <entry><literal>path</literal></entry> + <entry>An object path (see <xref linkend="message-protocol-marshaling-object-path"/>)</entry> + <entry>Matches messages which are sent from or to the given object. An example of a + path match is path='/org/freedesktop/Hal/Manager'</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 + example of a destination match is destination=':1.0'</entry> + </row> + <row> + <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 + 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> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + </sect3> + </sect2> + <sect2 id="message-bus-starting-services"> + <title>Message Bus Starting Services</title> + <para> + The message bus can start applications on behalf of other applications. + In CORBA terms, this would be called <firstterm>activation</firstterm>. + An application that can be started in this way is called a + <firstterm>service</firstterm>. + </para> + <para> + With D-Bus, starting a service is normally done by name. That is, + applications ask the message bus to start some program that will own a + well-known name, such as <literal>org.freedesktop.TextEditor</literal>. + This implies a contract documented along with the name + <literal>org.freedesktop.TextEditor</literal> for which objects + the owner of that name will provide, and what interfaces those + objects will have. + </para> + <para> + To find an executable corresponding to a particular name, the bus daemon + looks for <firstterm>service description files</firstterm>. Service + description files define a mapping from names to executables. Different + kinds of message bus will look for these files in different places, see + <xref linkend="message-bus-types"/>. + </para> + <para> + [FIXME the file format should be much better specified than "similar to + .desktop entries" esp. since desktop entries are already + badly-specified. ;-)] Service description files have the ".service" file + extension. The message bus will only load service description files + ending with .service; all other files will be ignored. The file format + is similar to that of <ulink + url="http://www.freedesktop.org/standards/desktop-entry-spec/desktop-entry-spec.html">desktop + entries</ulink>. All service description files must be in UTF-8 + encoding. To ensure that there will be no name collisions, service files + must be namespaced using the same mechanism as messages and service + names. + + <figure> + <title>Example service description file</title> + <programlisting> + # Sample service description file + [D-BUS Service] + Names=org.freedesktop.ConfigurationDatabase;org.gnome.GConf; + Exec=/usr/libexec/gconfd-2 + </programlisting> + </figure> + </para> + <para> + When an application asks to start a service by name, the bus daemon tries to + find a service that will own that name. It then tries to spawn the + executable associated with it. If this fails, it will report an + error. [FIXME what happens if two .service files offer the same service; + what kind of error is reported, should we have a way for the client to + choose one?] + </para> + <para> + The executable launched will have the environment variable + <literal>DBUS_STARTER_ADDRESS</literal> set to the address of the + message bus so it can connect and request the appropriate names. + </para> + <para> + The executable being launched may want to know whether the message bus + starting it is one of the well-known message buses (see <xref + linkend="message-bus-types"/>). To facilitate this, the bus must also set + the <literal>DBUS_STARTER_BUS_TYPE</literal> environment variable if it is one + of the well-known buses. The currently-defined values for this variable + are <literal>system</literal> for the systemwide message bus, + and <literal>session</literal> for the per-login-session message + bus. The new executable must still connect to the address given + in <literal>DBUS_STARTER_ADDRESS</literal>, but may assume that the + resulting connection is to the well-known bus. + </para> + <para> + [FIXME there should be a timeout somewhere, either specified + in the .service file, by the client, or just a global value + and if the client being activated fails to connect within that + timeout, an error should be sent back.] + </para> + + <sect3 id="message-bus-starting-services-scope"> + <title>Message Bus Service Scope</title> + <para> + The "scope" of a service is its "per-", such as per-session, + per-machine, per-home-directory, or per-display. The reference + implementation doesn't yet support starting services in a different + scope from the message bus itself. So e.g. if you start a service + on the session bus its scope is per-session. + </para> + <para> + We could add an optional scope to a bus name. For example, for + per-(display,session pair), we could have a unique ID for each display + generated automatically at login and set on screen 0 by executing a + special "set display ID" binary. The ID would be stored in a + <literal>_DBUS_DISPLAY_ID</literal> property and would be a string of + random bytes. This ID would then be used to scope names. + Starting/locating a service could be done by ID-name pair rather than + only by name. + </para> + <para> + Contrast this with a per-display scope. To achieve that, we would + want a single bus spanning all sessions using a given display. + So we might set a <literal>_DBUS_DISPLAY_BUS_ADDRESS</literal> + property on screen 0 of the display, pointing to this bus. + </para> + </sect3> + </sect2> + + <sect2 id="message-bus-types"> + <title>Well-known Message Bus Instances</title> + <para> + Two standard message bus instances are defined here, along with how + to locate them and where their service files live. + </para> + <sect3 id="message-bus-types-login"> + <title>Login session message bus</title> + <para> + Each time a user logs in, a <firstterm>login session message + bus</firstterm> may be started. All applications in the user's login + session may interact with one another using this message bus. + </para> + <para> + The address of the login session message bus is given + in the <literal>DBUS_SESSION_BUS_ADDRESS</literal> environment + variable. If that variable is not set, applications may + also try to read the address from the X Window System root + window property <literal>_DBUS_SESSION_BUS_ADDRESS</literal>. + The root window property must have type <literal>STRING</literal>. + The environment variable should have precedence over the + root window property. + </para> + <para> + [FIXME specify location of .service files, probably using + DESKTOP_DIRS etc. from basedir specification, though login session + bus is not really desktop-specific] + </para> + </sect3> + <sect3 id="message-bus-types-system"> + <title>System message bus</title> + <para> + A computer may have a <firstterm>system message bus</firstterm>, + accessible to all applications on the system. This message bus may be + used to broadcast system events, such as adding new hardware devices, + changes in the printer queue, and so forth. + </para> + <para> + The address of the system message bus is given + in the <literal>DBUS_SYSTEM_BUS_ADDRESS</literal> environment + variable. If that variable is not set, applications should try + to connect to the well-known address + <literal>unix:path=/var/run/dbus/system_bus_socket</literal>. + <footnote> + <para> + The D-Bus reference implementation actually honors the + <literal>$(localstatedir)</literal> configure option + for this address, on both client and server side. + </para> + </footnote> + </para> + <para> + [FIXME specify location of system bus .service files] + </para> + </sect3> + </sect2> + + <sect2 id="message-bus-messages"> + <title>Message Bus Messages</title> + <para> + The special message bus name <literal>org.freedesktop.DBus</literal> + responds to a number of additional messages. + </para> + + <sect3 id="bus-messages-hello"> + <title><literal>org.freedesktop.DBus.Hello</literal></title> + <para> + As a method: + <programlisting> + STRING Hello () + </programlisting> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Unique name assigned to the connection</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + Before an application is able to send messages to other applications + it must send the <literal>org.freedesktop.DBus.Hello</literal> message + to the message bus to obtain a unique name. If an application without + a unique name tries to send a message to another application, or a + message to the message bus itself that isn't the + <literal>org.freedesktop.DBus.Hello</literal> message, it will be + disconnected from the bus. + </para> + <para> + There is no corresponding "disconnect" request; if a client wishes to + disconnect from the bus, it simply closes the socket (or other + communication channel). + </para> + </sect3> + <sect3 id="bus-messages-list-names"> + <title><literal>org.freedesktop.DBus.ListNames</literal></title> + <para> + As a method: + <programlisting> + ARRAY of STRING ListNames () + </programlisting> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>ARRAY of STRING</entry> + <entry>Array of strings where each string is a bus name</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + Returns a list of all currently-owned names on the bus. + </para> + </sect3> + <sect3 id="bus-messages-list-activatable-names"> + <title><literal>org.freedesktop.DBus.ListActivatableNames</literal></title> + <para> + As a method: + <programlisting> + ARRAY of STRING ListActivatableNames () + </programlisting> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>ARRAY of STRING</entry> + <entry>Array of strings where each string is a bus name</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + Returns a list of all names that can be activated on the bus. + </para> + </sect3> + <sect3 id="bus-messages-name-exists"> + <title><literal>org.freedesktop.DBus.NameHasOwner</literal></title> + <para> + As a method: + <programlisting> + BOOLEAN NameHasOwner (in STRING name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name to check</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>BOOLEAN</entry> + <entry>Return value, true if the name exists</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + Checks if the specified name exists (currently has an owner). + </para> + </sect3> + + <sect3 id="bus-messages-name-owner-changed"> + <title><literal>org.freedesktop.DBus.NameOwnerChanged</literal></title> + <para> + This is a signal: + <programlisting> + NameOwnerChanged (STRING name, STRING old_owner, STRING new_owner) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name with a new owner</entry> + </row> + <row> + <entry>1</entry> + <entry>STRING</entry> + <entry>Old owner or empty string if none</entry> + </row> + <row> + <entry>2</entry> + <entry>STRING</entry> + <entry>New owner or empty string if none</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + This signal indicates that the owner of a name has changed. + It's also the signal to use to detect the appearance of + new names on the bus. + </para> + </sect3> + <sect3 id="bus-messages-name-lost"> + <title><literal>org.freedesktop.DBus.NameLost</literal></title> + <para> + This is a signal: + <programlisting> + NameLost (STRING name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name which was lost</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + This signal is sent to a specific application when it loses + ownership of a name. + </para> + </sect3> + + <sect3 id="bus-messages-name-acquired"> + <title><literal>org.freedesktop.DBus.NameAcquired</literal></title> + <para> + This is a signal: + <programlisting> + NameAcquired (STRING name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name which was acquired</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + This signal is sent to a specific application when it gains + ownership of a name. + </para> + </sect3> + + <sect3 id="bus-messages-start-service-by-name"> + <title><literal>org.freedesktop.DBus.StartServiceByName</literal></title> + <para> + As a method: + <programlisting> + UINT32 StartServiceByName (in STRING name, in UINT32 flags) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name of the service to start</entry> + </row> + <row> + <entry>1</entry> + <entry>UINT32</entry> + <entry>Flags (currently not used)</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>UINT32</entry> + <entry>Return value</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Tries to launch the executable associated with a name. For more information, see <xref linkend="message-bus-starting-services"/>. + + </para> + <para> + The return value can be one of the following values: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Identifier</entry> + <entry>Value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>DBUS_START_REPLY_SUCCESS</entry> + <entry>1</entry> + <entry>The service was successfully started.</entry> + </row> + <row> + <entry>DBUS_START_REPLY_ALREADY_RUNNING</entry> + <entry>2</entry> + <entry>A connection already owns the given name.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + + </sect3> + + <sect3 id="bus-messages-update-activation-environment"> + <title><literal>org.freedesktop.DBus.UpdateActivationEnvironment</literal></title> + <para> + As a method: + <programlisting> + UpdateActivationEnvironment (in ARRAY of DICT<STRING,STRING> environment) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>ARRAY of DICT<STRING,STRING></entry> + <entry>Environment to add or update</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Normally, session bus activated services inherit the environment of the bus daemon. This method adds to or modifies that environment when activating services. + </para> + <para> + Some bus instances, such as the standard system bus, may disable access to this method for some or all callers. + </para> + + </sect3> + + <sect3 id="bus-messages-get-name-owner"> + <title><literal>org.freedesktop.DBus.GetNameOwner</literal></title> + <para> + As a method: + <programlisting> + STRING GetNameOwner (in STRING name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name to get the owner of</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Return value, a unique connection name</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Returns the unique connection name of the primary owner of the name + given. If the requested name doesn't have an owner, returns a + <literal>org.freedesktop.DBus.Error.NameHasNoOwner</literal> error. + </para> + </sect3> + + <sect3 id="bus-messages-get-connection-unix-user"> + <title><literal>org.freedesktop.DBus.GetConnectionUnixUser</literal></title> + <para> + As a method: + <programlisting> + UINT32 GetConnectionUnixUser (in STRING connection_name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name of the connection to query</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>UINT32</entry> + <entry>unix user id</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Returns the unix uid of the process connected to the server. If unable to + determine it, a <literal>org.freedesktop.DBus.Error.Failed</literal> + error is returned. + </para> + </sect3> + + <sect3 id="bus-messages-add-match"> + <title><literal>org.freedesktop.DBus.AddMatch</literal></title> + <para> + As a method: + <programlisting> + AddMatch (in STRING rule) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Match rule to add to the connection</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Adds a match rule to match messages going through the message bus (see <xref linkend='message-bus-routing-match-rules'/>). + If the bus does not have enough resources the <literal>org.freedesktop.DBus.Error.OOM</literal> + error is returned. + </para> + </sect3> + <sect3 id="bus-messages-remove-match"> + <title><literal>org.freedesktop.DBus.RemoveMatch</literal></title> + <para> + As a method: + <programlisting> + RemoveMatch (in STRING rule) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Match rule to remove from the connection</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Removes the first rule that matches (see <xref linkend='message-bus-routing-match-rules'/>). + If the rule is not found the <literal>org.freedesktop.DBus.Error.MatchRuleNotFound</literal> + error is returned. + </para> + </sect3> + + <sect3 id="bus-messages-get-id"> + <title><literal>org.freedesktop.DBus.GetId</literal></title> + <para> + As a method: + <programlisting> + GetId (out STRING id) + </programlisting> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Unique ID identifying the bus daemon</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Gets the unique ID of the bus. The unique ID here is shared among all addresses the + bus daemon is listening on (TCP, UNIX domain socket, etc.) and its format is described in + <xref linkend="uuids"/>. Each address the bus is listening on also has its own unique + ID, as described in <xref linkend="addresses"/>. The per-bus and per-address IDs are not related. + There is also a per-machine ID, described in <xref linkend="standard-interfaces-peer"/> and returned + by org.freedesktop.DBus.Peer.GetMachineId(). + For a desktop session bus, the bus ID can be used as a way to uniquely identify a user's session. + </para> + </sect3> + + </sect2> + + </sect1> +<!-- + <appendix id="implementation-notes"> + <title>Implementation notes</title> + <sect1 id="implementation-notes-subsection"> + <title></title> + <para> + </para> + </sect1> + </appendix> +--> + + <glossary><title>Glossary</title> + <para> + This glossary defines some of the terms used in this specification. + </para> + + <glossentry id="term-bus-name"><glossterm>Bus Name</glossterm> + <glossdef> + <para> + The message bus maintains an association between names and + connections. (Normally, there's one connection per application.) A + bus name is simply an identifier used to locate connections. For + example, the hypothetical <literal>com.yoyodyne.Screensaver</literal> + name might be used to send a message to a screensaver from Yoyodyne + Corporation. An application is said to <firstterm>own</firstterm> a + name if the message bus has associated the application's connection + with the name. Names may also have <firstterm>queued + owners</firstterm> (see <xref linkend="term-queued-owner"/>). + The bus assigns a unique name to each connection, + see <xref linkend="term-unique-name"/>. Other names + can be thought of as "well-known names" and are + used to find applications that offer specific functionality. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-message"><glossterm>Message</glossterm> + <glossdef> + <para> + A message is the atomic unit of communication via the D-Bus + protocol. It consists of a <firstterm>header</firstterm> and a + <firstterm>body</firstterm>; the body is made up of + <firstterm>arguments</firstterm>. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-message-bus"><glossterm>Message Bus</glossterm> + <glossdef> + <para> + The message bus is a special application that forwards + or routes messages between a group of applications + connected to the message bus. It also manages + <firstterm>names</firstterm> used for routing + messages. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-name"><glossterm>Name</glossterm> + <glossdef> + <para> + See <xref linkend="term-bus-name"/>. "Name" may + also be used to refer to some of the other names + in D-Bus, such as interface names. + </para> + </glossdef> + </glossentry> + + <glossentry id="namespace"><glossterm>Namespace</glossterm> + <glossdef> + <para> + Used to prevent collisions when defining new interfaces or bus + names. The convention used is the same one Java uses for defining + classes: a reversed domain name. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-object"><glossterm>Object</glossterm> + <glossdef> + <para> + Each application contains <firstterm>objects</firstterm>, which have + <firstterm>interfaces</firstterm> and + <firstterm>methods</firstterm>. Objects are referred to by a name, + called a <firstterm>path</firstterm>. + </para> + </glossdef> + </glossentry> + + <glossentry id="one-to-one"><glossterm>One-to-One</glossterm> + <glossdef> + <para> + An application talking directly to another application, without going + through a message bus. One-to-one connections may be "peer to peer" or + "client to server." The D-Bus protocol has no concept of client + vs. server after a connection has authenticated; the flow of messages + is symmetrical (full duplex). + </para> + </glossdef> + </glossentry> + + <glossentry id="term-path"><glossterm>Path</glossterm> + <glossdef> + <para> + Object references (object names) in D-Bus are organized into a + filesystem-style hierarchy, so each object is named by a path. As in + LDAP, there's no difference between "files" and "directories"; a path + can refer to an object, while still having child objects below it. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-queued-owner"><glossterm>Queued Name Owner</glossterm> + <glossdef> + <para> + Each bus name has a primary owner; messages sent to the name go to the + primary owner. However, certain names also maintain a queue of + secondary owners "waiting in the wings." If the primary owner releases + the name, then the first secondary owner in the queue automatically + becomes the new owner of the name. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-service"><glossterm>Service</glossterm> + <glossdef> + <para> + A service is an executable that can be launched by the bus daemon. + Services normally guarantee some particular features, for example they + may guarantee that they will request a specific name such as + "org.freedesktop.Screensaver", have a singleton object + "/org/freedesktop/Application", and that object will implement the + interface "org.freedesktop.ScreensaverControl". + </para> + </glossdef> + </glossentry> + + <glossentry id="term-service-description-files"><glossterm>Service Description Files</glossterm> + <glossdef> + <para> + ".service files" tell the bus about service applications that can be + launched (see <xref linkend="term-service"/>). Most importantly they + provide a mapping from bus names to services that will request those + names when they start up. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-unique-name"><glossterm>Unique Connection Name</glossterm> + <glossdef> + <para> + The special name automatically assigned to each connection by the + message bus. This name will never change owner, and will be unique + (never reused during the lifetime of the message bus). + It will begin with a ':' character. + </para> + </glossdef> + </glossentry> + + </glossary> +</article> + diff --git a/doc/dbus-test-plan.html b/doc/dbus-test-plan.html new file mode 100644 index 00000000..e9e70a11 --- /dev/null +++ b/doc/dbus-test-plan.html @@ -0,0 +1,141 @@ +<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>D-Bus Test Plan</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="article" title="D-Bus Test Plan"><div class="titlepage"><div><div><h2 class="title"><a name="index"></a>D-Bus Test Plan</h2></div><div><div class="authorgroup"><div class="author"><h3 class="author"><span class="firstname">Anders</span> <span class="surname">Carlsson</span></h3><div class="affiliation"><span class="orgname">CodeFactory AB<br></span><div class="address"><p><code class="email"><<a class="email" href="mailto:andersca@codefactory.se">andersca@codefactory.se</a>></code></p></div></div></div></div></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#introduction">Introduction</a></span></dt><dd><dl><dt><span class="sect2"><a href="#importance-of-testing">The importance of testing</a></span></dt></dl></dd><dt><span class="sect1"><a href="#client-library">Testing the D-Bus client library</a></span></dt><dd><dl><dt><span class="sect2"><a href="#data-structures">Data Structures</a></span></dt><dt><span class="sect2"><a href="#message-loader">Message loader</a></span></dt><dt><span class="sect2"><a href="#authentication">Authentication</a></span></dt></dl></dd><dt><span class="sect1"><a href="#daemon">Testing the D-Bus bus daemon</a></span></dt><dd><dl><dt><span class="sect2"><a href="#debug-transport">The debug transport</a></span></dt><dt><span class="sect2"><a href="#bus-test">The bus-test program</a></span></dt></dl></dd><dt><span class="sect1"><a href="#other-tests">Other tests</a></span></dt><dd><dl><dt><span class="sect2"><a href="#oom-robustness">Out-Of-Memory robustness</a></span></dt><dt><span class="sect2"><a href="#leaks-and-other-stuff">Memory leaks and code robustness</a></span></dt></dl></dd></dl></div><div class="sect1" title="Introduction"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="introduction"></a>Introduction</h2></div></div></div><p> + This document tries to explain the details of the test plan for D-Bus + </p><div class="sect2" title="The importance of testing"><div class="titlepage"><div><div><h3 class="title"><a name="importance-of-testing"></a>The importance of testing</h3></div></div></div><p> + As with any big library or program, testing is important. It + can help find bugs and regressions and make the code better + overall. + </p><p> + D-Bus is a large and complex piece of software (about 25,000 + lines of code for the client library, and 2,500 lines of code + for the bus daemon) and it's therefore important to try to make sure + that all parts of the software is functioning correctly. + </p><p> + D-Bus can be built with support for testing by passing + <code class="literal">--enable-tests</code>. to the configure script. It + is recommended that production systems build without testing + since that reduces the D-Bus client library size. + </p></div></div><div class="sect1" title="Testing the D-Bus client library"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="client-library"></a>Testing the D-Bus client library</h2></div></div></div><p> + The tests for the client library consist of the dbus-test + program which is a unit test for all aspects of the client + library. Whenever a bug in the client library is found and + fixed, a test is added to make sure that the bug won't occur again. + </p><div class="sect2" title="Data Structures"><div class="titlepage"><div><div><h3 class="title"><a name="data-structures"></a>Data Structures</h3></div></div></div><p> + The D-Bus client library consists of some data structures that + are used internally; a linked list class, a hashtable class and + a string class. All aspects of those are tested by dbus-test. + </p></div><div class="sect2" title="Message loader"><div class="titlepage"><div><div><h3 class="title"><a name="message-loader"></a>Message loader</h3></div></div></div><p> + The message loader is the part of D-Bus that takes messages in + raw character form and parses them, turning them into DBusMessages. + </p><p> + This is one of the parts of D-Bus that + <span class="emphasis"><em>must</em></span> be absolutely bug-free and + robust. The message loader should be able to handle invalid + and incomplete messages without crashing. Not doing so is a + serious issue and can easily result in D-Bus being exploitable + to DoS attacks. + </p><p> + To solve these problems, there is a testing feature called the + Message Builder. The message builder can take a serialized + message in string-form and convert it into a raw character + string which can then be loaded by the message loader. + </p><div class="figure"><a name="id528362"></a><p class="title"><b>Figure 1. Example of a message in string form</b></p><div class="figure-contents"><pre class="programlisting"> + # Standard org.freedesktop.DBus.Hello message + + VALID_HEADER + FIELD_NAME name + TYPE STRING + STRING 'org.freedesktop.DBus.Hello' + FIELD_NAME srvc + TYPE STRING + STRING 'org.freedesktop.DBus' + ALIGN 8 + END_LENGTH Header + START_LENGTH Body + END_LENGTH Body + </pre></div></div><br class="figure-break"><p> + The file format of messages in string form is documented in + the D-Bus Reference Manual. + </p><p> + The message test part of dbus-test is using the message + builder to build different kinds of messages, both valid, + invalid, and invalid ones, to make sure that the loader won't + crash or leak memory of any of those, and that the loader + knows if a message is valid or not. + </p><p> + There is also a test program called + <code class="literal">break-loader</code> that loads a message in + string-form into raw character form using the message + builder. It then randomly changes the message, it can for + example replace single bytes of data or modify the length of + the message. This is to simulate network errors. The + break-loader program saves all the messages leading to errors + so it can easily be run for a long period of time. + </p></div><div class="sect2" title="Authentication"><div class="titlepage"><div><div><h3 class="title"><a name="authentication"></a>Authentication</h3></div></div></div><p> + For testing authentication, there is a testing feature that + can read authentication sequences from a file and play them + back to a dummy server and client to make sure that + authentication is working according to the specification. + </p><div class="figure"><a name="id524894"></a><p class="title"><b>Figure 2. Example of an authentication script</b></p><div class="figure-contents"><pre class="programlisting"> + ## this tests a successful auth of type EXTERNAL + + SERVER + SEND 'AUTH EXTERNAL USERNAME_HEX' + EXPECT_COMMAND OK + EXPECT_STATE WAITING_FOR_INPUT + SEND 'BEGIN' + EXPECT_STATE AUTHENTICATED + </pre></div></div><br class="figure-break"></div></div><div class="sect1" title="Testing the D-Bus bus daemon"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="daemon"></a>Testing the D-Bus bus daemon</h2></div></div></div><p> + Since the D-Bus bus daemon is using the D-Bus client library it + will benefit from all tests done on the client library, but + there is still the issue of testing client-server communication. + This is more complicated since it it may require another process + running. + </p><div class="sect2" title="The debug transport"><div class="titlepage"><div><div><h3 class="title"><a name="debug-transport"></a>The debug transport</h3></div></div></div><p> + In D-Bus, a <span class="emphasis"><em>transport</em></span> is a class that + handles sending and receiving raw data over a certain + medium. The transport that is used most in D-Bus is the UNIX + transport with sends and recevies data over a UNIX socket. A + transport that tunnels data through X11 client messages is + also under development. + </p><p> + The D-Bus debug transport is a specialized transport that + works in-process. This means that a client and server that + exists in the same process can talk to eachother without using + a socket. + </p></div><div class="sect2" title="The bus-test program"><div class="titlepage"><div><div><h3 class="title"><a name="bus-test"></a>The bus-test program</h3></div></div></div><p> + The bus-test program is a program that is used to test various + parts of the D-Bus bus daemon; robustness and that it conforms + to the specifications. + </p><p> + The test program has the necessary code from the bus daemon + linked in, and it uses the debug transport for + communication. This means that the bus daemon code can be + tested without the real bus actually running, which makes + testing easier. + </p><p> + The bus-test program should test all major features of the + bus, such as service registration, notification when things + occurs and message matching. + </p></div></div><div class="sect1" title="Other tests"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="other-tests"></a>Other tests</h2></div></div></div><div class="sect2" title="Out-Of-Memory robustness"><div class="titlepage"><div><div><h3 class="title"><a name="oom-robustness"></a>Out-Of-Memory robustness</h3></div></div></div><p> + Since D-Bus should be able to be used in embedded devices, and + also as a system service, it should be able to cope with + low-memory situations without exiting or crashing. + </p><p> + In practice, this means that both the client and server code + must be able to handle dbus_malloc returning NULL. + </p><p> + To test this, two environment variables + exist. <code class="literal">DBUS_MALLOC_FAIL_NTH</code> will make every + nth call to dbus_malloc return NULL, and + <code class="literal">DBUS_MALLOC_FAIL_GREATER_THAN</code> will make any + dbus_malloc call with a request for more than the specified + number of bytes fail. + </p></div><div class="sect2" title="Memory leaks and code robustness"><div class="titlepage"><div><div><h3 class="title"><a name="leaks-and-other-stuff"></a>Memory leaks and code robustness</h3></div></div></div><p> + Naturally there are some things that tests can't be written + for, for example things like memory leaks and out-of-bounds + memory reading or writing. + </p><p> + Luckily there exists good tools for catching such errors. One + free good tool is <a class="ulink" href="http://devel-home.kde.org/~sewardj/" target="_top">Valgrind</a>, which runs the program in a + virtual CPU which makes catching errors easy. All test programs can be run under Valgrind, + </p></div></div></div></body></html> diff --git a/doc/dbus-test-plan.xml b/doc/dbus-test-plan.xml new file mode 100644 index 00000000..e6aafb9a --- /dev/null +++ b/doc/dbus-test-plan.xml @@ -0,0 +1,232 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" +"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" +[ +]> + +<article id="index"> + <articleinfo> + <title>D-Bus Test Plan</title> + <date>14 February 2003</date> + <authorgroup> + <author> + <firstname>Anders</firstname> + <surname>Carlsson</surname> + <affiliation> + <orgname>CodeFactory AB</orgname> + <address><email>andersca@codefactory.se</email></address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + <sect1 id="introduction"> + <title>Introduction</title> + <para> + This document tries to explain the details of the test plan for D-Bus + </para> + <sect2 id="importance-of-testing"> + <title>The importance of testing</title> + <para> + As with any big library or program, testing is important. It + can help find bugs and regressions and make the code better + overall. + </para> + <para> + D-Bus is a large and complex piece of software (about 25,000 + lines of code for the client library, and 2,500 lines of code + for the bus daemon) and it's therefore important to try to make sure + that all parts of the software is functioning correctly. + </para> + <para> + D-Bus can be built with support for testing by passing + <literal>--enable-tests</literal>. to the configure script. It + is recommended that production systems build without testing + since that reduces the D-Bus client library size. + </para> + </sect2> + </sect1> + <sect1 id="client-library"> + <title>Testing the D-Bus client library</title> + <para> + The tests for the client library consist of the dbus-test + program which is a unit test for all aspects of the client + library. Whenever a bug in the client library is found and + fixed, a test is added to make sure that the bug won't occur again. + </para> + <sect2 id="data-structures"> + <title>Data Structures</title> + <para> + The D-Bus client library consists of some data structures that + are used internally; a linked list class, a hashtable class and + a string class. All aspects of those are tested by dbus-test. + </para> + </sect2> + <sect2 id="message-loader"> + <title>Message loader</title> + <para> + The message loader is the part of D-Bus that takes messages in + raw character form and parses them, turning them into DBusMessages. + </para> + <para> + This is one of the parts of D-Bus that + <emphasis>must</emphasis> be absolutely bug-free and + robust. The message loader should be able to handle invalid + and incomplete messages without crashing. Not doing so is a + serious issue and can easily result in D-Bus being exploitable + to DoS attacks. + </para> + <para> + To solve these problems, there is a testing feature called the + Message Builder. The message builder can take a serialized + message in string-form and convert it into a raw character + string which can then be loaded by the message loader. + </para> + <figure> + <title>Example of a message in string form</title> + <programlisting> + # Standard org.freedesktop.DBus.Hello message + + VALID_HEADER + FIELD_NAME name + TYPE STRING + STRING 'org.freedesktop.DBus.Hello' + FIELD_NAME srvc + TYPE STRING + STRING 'org.freedesktop.DBus' + ALIGN 8 + END_LENGTH Header + START_LENGTH Body + END_LENGTH Body + </programlisting> + </figure> + <para> + The file format of messages in string form is documented in + the D-Bus Reference Manual. + </para> + <para> + The message test part of dbus-test is using the message + builder to build different kinds of messages, both valid, + invalid, and invalid ones, to make sure that the loader won't + crash or leak memory of any of those, and that the loader + knows if a message is valid or not. + </para> + <para> + There is also a test program called + <literal>break-loader</literal> that loads a message in + string-form into raw character form using the message + builder. It then randomly changes the message, it can for + example replace single bytes of data or modify the length of + the message. This is to simulate network errors. The + break-loader program saves all the messages leading to errors + so it can easily be run for a long period of time. + </para> + </sect2> + <sect2 id="authentication"> + <title>Authentication</title> + <para> + For testing authentication, there is a testing feature that + can read authentication sequences from a file and play them + back to a dummy server and client to make sure that + authentication is working according to the specification. + </para> + <figure> + <title>Example of an authentication script</title> + <programlisting> + ## this tests a successful auth of type EXTERNAL + + SERVER + SEND 'AUTH EXTERNAL USERNAME_HEX' + EXPECT_COMMAND OK + EXPECT_STATE WAITING_FOR_INPUT + SEND 'BEGIN' + EXPECT_STATE AUTHENTICATED + </programlisting> + </figure> + </sect2> + </sect1> + <sect1 id="daemon"> + <title>Testing the D-Bus bus daemon</title> + <para> + Since the D-Bus bus daemon is using the D-Bus client library it + will benefit from all tests done on the client library, but + there is still the issue of testing client-server communication. + This is more complicated since it it may require another process + running. + </para> + <sect2 id="debug-transport"> + <title>The debug transport</title> + <para> + In D-Bus, a <emphasis>transport</emphasis> is a class that + handles sending and receiving raw data over a certain + medium. The transport that is used most in D-Bus is the UNIX + transport with sends and recevies data over a UNIX socket. A + transport that tunnels data through X11 client messages is + also under development. + </para> + <para> + The D-Bus debug transport is a specialized transport that + works in-process. This means that a client and server that + exists in the same process can talk to eachother without using + a socket. + </para> + </sect2> + <sect2 id="bus-test"> + <title>The bus-test program</title> + <para> + The bus-test program is a program that is used to test various + parts of the D-Bus bus daemon; robustness and that it conforms + to the specifications. + </para> + <para> + The test program has the necessary code from the bus daemon + linked in, and it uses the debug transport for + communication. This means that the bus daemon code can be + tested without the real bus actually running, which makes + testing easier. + </para> + <para> + The bus-test program should test all major features of the + bus, such as service registration, notification when things + occurs and message matching. + </para> + </sect2> + </sect1> + <sect1 id="other-tests"> + <title>Other tests</title> + + <sect2 id="oom-robustness"> + <title>Out-Of-Memory robustness</title> + <para> + Since D-Bus should be able to be used in embedded devices, and + also as a system service, it should be able to cope with + low-memory situations without exiting or crashing. + </para> + <para> + In practice, this means that both the client and server code + must be able to handle dbus_malloc returning NULL. + </para> + <para> + To test this, two environment variables + exist. <literal>DBUS_MALLOC_FAIL_NTH</literal> will make every + nth call to dbus_malloc return NULL, and + <literal>DBUS_MALLOC_FAIL_GREATER_THAN</literal> will make any + dbus_malloc call with a request for more than the specified + number of bytes fail. + </para> + </sect2> + + <sect2 id="leaks-and-other-stuff"> + <title>Memory leaks and code robustness</title> + <para> + Naturally there are some things that tests can't be written + for, for example things like memory leaks and out-of-bounds + memory reading or writing. + </para> + <para> + Luckily there exists good tools for catching such errors. One + free good tool is <ulink url="http://devel-home.kde.org/~sewardj/">Valgrind</ulink>, which runs the program in a + virtual CPU which makes catching errors easy. All test programs can be run under Valgrind, + </para> + </sect2> + </sect1> +</article> diff --git a/doc/dbus-tutorial.html b/doc/dbus-tutorial.html new file mode 100644 index 00000000..957afaf1 --- /dev/null +++ b/doc/dbus-tutorial.html @@ -0,0 +1,991 @@ +<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>D-Bus Tutorial</title><meta name="generator" content="DocBook XSL Stylesheets V1.75.2"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="article" title="D-Bus Tutorial"><div class="titlepage"><div><div><h2 class="title"><a name="index"></a>D-Bus Tutorial</h2></div><div><div class="authorgroup"><div class="author"><h3 class="author"><span class="firstname">Havoc</span> <span class="surname">Pennington</span></h3><div class="affiliation"><span class="orgname">Red Hat, Inc.<br></span><div class="address"><p><code class="email"><<a class="email" href="mailto:hp@pobox.com">hp@pobox.com</a>></code></p></div></div></div><div class="author"><h3 class="author"><span class="firstname">David</span> <span class="surname">Wheeler</span></h3></div><div class="author"><h3 class="author"><span class="firstname">John</span> <span class="surname">Palmieri</span></h3><div class="affiliation"><span class="orgname">Red Hat, Inc.<br></span><div class="address"><p><code class="email"><<a class="email" href="mailto:johnp@redhat.com">johnp@redhat.com</a>></code></p></div></div></div><div class="author"><h3 class="author"><span class="firstname">Colin</span> <span class="surname">Walters</span></h3><div class="affiliation"><span class="orgname">Red Hat, Inc.<br></span><div class="address"><p><code class="email"><<a class="email" href="mailto:walters@redhat.com">walters@redhat.com</a>></code></p></div></div></div></div></div><div><p class="releaseinfo">Version 0.5.0</p></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#meta">Tutorial Work In Progress</a></span></dt><dt><span class="sect1"><a href="#whatis">What is D-Bus?</a></span></dt><dd><dl><dt><span class="sect2"><a href="#uses">D-Bus applications</a></span></dt></dl></dd><dt><span class="sect1"><a href="#concepts">Concepts</a></span></dt><dd><dl><dt><span class="sect2"><a href="#objects">Native Objects and Object Paths</a></span></dt><dt><span class="sect2"><a href="#members">Methods and Signals</a></span></dt><dt><span class="sect2"><a href="#interfaces">Interfaces</a></span></dt><dt><span class="sect2"><a href="#proxies">Proxies</a></span></dt><dt><span class="sect2"><a href="#bus-names">Bus Names</a></span></dt><dt><span class="sect2"><a href="#addresses">Addresses</a></span></dt><dt><span class="sect2"><a href="#bigpicture">Big Conceptual Picture</a></span></dt><dt><span class="sect2"><a href="#messages">Messages - Behind the Scenes</a></span></dt><dt><span class="sect2"><a href="#callprocedure">Calling a Method - Behind the Scenes</a></span></dt><dt><span class="sect2"><a href="#signalprocedure">Emitting a Signal - Behind the Scenes</a></span></dt><dt><span class="sect2"><a href="#introspection">Introspection</a></span></dt></dl></dd><dt><span class="sect1"><a href="#glib-client">GLib API: Using Remote Objects</a></span></dt><dd><dl><dt><span class="sect2"><a href="#glib-typemappings">D-Bus - GLib type mappings</a></span></dt><dt><span class="sect2"><a href="#sample-program-1">A sample program</a></span></dt><dt><span class="sect2"><a href="#glib-program-setup">Program initalization</a></span></dt><dt><span class="sect2"><a href="#glib-method-invocation">Understanding method invocation</a></span></dt><dt><span class="sect2"><a href="#glib-signal-connection">Connecting to object signals</a></span></dt><dt><span class="sect2"><a href="#glib-error-handling">Error handling and remote exceptions</a></span></dt><dt><span class="sect2"><a href="#glib-more-examples">More examples of method invocation</a></span></dt><dt><span class="sect2"><a href="#glib-generated-bindings">Generated Bindings</a></span></dt></dl></dd><dt><span class="sect1"><a href="#glib-server">GLib API: Implementing Objects</a></span></dt><dd><dl><dt><span class="sect2"><a href="#glib-annotations">Server-side Annotations</a></span></dt></dl></dd><dt><span class="sect1"><a href="#python-client">Python API</a></span></dt><dt><span class="sect1"><a href="#qt-client">Qt API: Using Remote Objects</a></span></dt><dt><span class="sect1"><a href="#qt-server">Qt API: Implementing Objects</a></span></dt></dl></div><div class="sect1" title="Tutorial Work In Progress"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="meta"></a>Tutorial Work In Progress</h2></div></div></div><p> + This tutorial is not complete; it probably contains some useful information, but + also has plenty of gaps. Right now, you'll also need to refer to the D-Bus specification, + Doxygen reference documentation, and look at some examples of how other apps use D-Bus. + </p><p> + Enhancing the tutorial is definitely encouraged - send your patches or suggestions to the + mailing list. If you create a D-Bus binding, please add a section to the tutorial for your + binding, if only a short section with a couple of examples. + </p></div><div class="sect1" title="What is D-Bus?"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="whatis"></a>What is D-Bus?</h2></div></div></div><p> + D-Bus is a system for <em class="firstterm">interprocess communication</em> + (IPC). Architecturally, it has several layers: + + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + A library, <em class="firstterm">libdbus</em>, that allows two + applications to connect to each other and exchange messages. + </p></li><li class="listitem"><p> + A <em class="firstterm">message bus daemon</em> executable, built on + libdbus, that multiple applications can connect to. The daemon can + route messages from one application to zero or more other + applications. + </p></li><li class="listitem"><p> + <em class="firstterm">Wrapper libraries</em> or <em class="firstterm">bindings</em> + based on particular application frameworks. For example, libdbus-glib and + libdbus-qt. There are also bindings to languages such as + Python. These wrapper libraries are the API most people should use, + as they simplify the details of D-Bus programming. libdbus is + intended to be a low-level backend for the higher level bindings. + Much of the libdbus API is only useful for binding implementation. + </p></li></ul></div><p> + </p><p> + libdbus only supports one-to-one connections, just like a raw network + socket. However, rather than sending byte streams over the connection, you + send <em class="firstterm">messages</em>. Messages have a header identifying + the kind of message, and a body containing a data payload. libdbus also + abstracts the exact transport used (sockets vs. whatever else), and + handles details such as authentication. + </p><p> + The message bus daemon forms the hub of a wheel. Each spoke of the wheel + is a one-to-one connection to an application using libdbus. An + application sends a message to the bus daemon over its spoke, and the bus + daemon forwards the message to other connected applications as + appropriate. Think of the daemon as a router. + </p><p> + The bus daemon has multiple instances on a typical computer. The + first instance is a machine-global singleton, that is, a system daemon + similar to sendmail or Apache. This instance has heavy security + restrictions on what messages it will accept, and is used for systemwide + communication. The other instances are created one per user login session. + These instances allow applications in the user's session to communicate + with one another. + </p><p> + The systemwide and per-user daemons are separate. Normal within-session + IPC does not involve the systemwide message bus process and vice versa. + </p><div class="sect2" title="D-Bus applications"><div class="titlepage"><div><div><h3 class="title"><a name="uses"></a>D-Bus applications</h3></div></div></div><p> + There are many, many technologies in the world that have "Inter-process + communication" or "networking" in their stated purpose: <a class="ulink" href="http://www.omg.org" target="_top">CORBA</a>, <a class="ulink" href="http://www.opengroup.org/dce/" target="_top">DCE</a>, <a class="ulink" href="http://www.microsoft.com/com/" target="_top">DCOM</a>, <a class="ulink" href="http://developer.kde.org/documentation/library/kdeqt/dcop.html" target="_top">DCOP</a>, <a class="ulink" href="http://www.xmlrpc.com" target="_top">XML-RPC</a>, <a class="ulink" href="http://www.w3.org/TR/SOAP/" target="_top">SOAP</a>, <a class="ulink" href="http://www.mbus.org/" target="_top">MBUS</a>, <a class="ulink" href="http://www.zeroc.com/ice.html" target="_top">Internet Communications Engine (ICE)</a>, + and probably hundreds more. + Each of these is tailored for particular kinds of application. + D-Bus is designed for two specific cases: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + Communication between desktop applications in the same desktop + session; to allow integration of the desktop session as a whole, + and address issues of process lifecycle (when do desktop components + start and stop running). + </p></li><li class="listitem"><p> + Communication between the desktop session and the operating system, + where the operating system would typically include the kernel + and any system daemons or processes. + </p></li></ul></div><p> + </p><p> + For the within-desktop-session use case, the GNOME and KDE desktops + have significant previous experience with different IPC solutions + such as CORBA and DCOP. D-Bus is built on that experience and + carefully tailored to meet the needs of these desktop projects + in particular. D-Bus may or may not be appropriate for other + applications; the FAQ has some comparisons to other IPC systems. + </p><p> + The problem solved by the systemwide or communication-with-the-OS case + is explained well by the following text from the Linux Hotplug project: + </p><div class="blockquote"><blockquote class="blockquote"><p> + A gap in current Linux support is that policies with any sort of + dynamic "interact with user" component aren't currently + supported. For example, that's often needed the first time a network + adapter or printer is connected, and to determine appropriate places + to mount disk drives. It would seem that such actions could be + supported for any case where a responsible human can be identified: + single user workstations, or any system which is remotely + administered. + </p><p> + This is a classic "remote sysadmin" problem, where in this case + hotplugging needs to deliver an event from one security domain + (operating system kernel, in this case) to another (desktop for + logged-in user, or remote sysadmin). Any effective response must go + the other way: the remote domain taking some action that lets the + kernel expose the desired device capabilities. (The action can often + be taken asynchronously, for example letting new hardware be idle + until a meeting finishes.) At this writing, Linux doesn't have + widely adopted solutions to such problems. However, the new D-Bus + work may begin to solve that problem. + </p></blockquote></div><p> + </p><p> + D-Bus may happen to be useful for purposes other than the one it was + designed for. Its general properties that distinguish it from + other forms of IPC are: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + Binary protocol designed to be used asynchronously + (similar in spirit to the X Window System protocol). + </p></li><li class="listitem"><p> + Stateful, reliable connections held open over time. + </p></li><li class="listitem"><p> + The message bus is a daemon, not a "swarm" or + distributed architecture. + </p></li><li class="listitem"><p> + Many implementation and deployment issues are specified rather + than left ambiguous/configurable/pluggable. + </p></li><li class="listitem"><p> + Semantics are similar to the existing DCOP system, allowing + KDE to adopt it more easily. + </p></li><li class="listitem"><p> + Security features to support the systemwide mode of the + message bus. + </p></li></ul></div><p> + </p></div></div><div class="sect1" title="Concepts"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="concepts"></a>Concepts</h2></div></div></div><p> + Some basic concepts apply no matter what application framework you're + using to write a D-Bus application. The exact code you write will be + different for GLib vs. Qt vs. Python applications, however. + </p><p> + Here is a diagram (<a class="ulink" href="diagram.png" target="_top">png</a> <a class="ulink" href="diagram.svg" target="_top">svg</a>) that may help you visualize the concepts + that follow. + </p><div class="sect2" title="Native Objects and Object Paths"><div class="titlepage"><div><div><h3 class="title"><a name="objects"></a>Native Objects and Object Paths</h3></div></div></div><p> + Your programming framework probably defines what an "object" is like; + usually with a base class. For example: java.lang.Object, GObject, QObject, + python's base Object, or whatever. Let's call this a <em class="firstterm">native object</em>. + </p><p> + The low-level D-Bus protocol, and corresponding libdbus API, does not care about native objects. + However, it provides a concept called an + <em class="firstterm">object path</em>. The idea of an object path is that + higher-level bindings can name native object instances, and allow remote applications + to refer to them. + </p><p> + The object path + looks like a filesystem path, for example an object could be + named <code class="literal">/org/kde/kspread/sheets/3/cells/4/5</code>. + Human-readable paths are nice, but you are free to create an + object named <code class="literal">/com/mycompany/c5yo817y0c1y1c5b</code> + if it makes sense for your application. + </p><p> + Namespacing object paths is smart, by starting them with the components + of a domain name you own (e.g. <code class="literal">/org/kde</code>). This + keeps different code modules in the same process from stepping + on one another's toes. + </p></div><div class="sect2" title="Methods and Signals"><div class="titlepage"><div><div><h3 class="title"><a name="members"></a>Methods and Signals</h3></div></div></div><p> + Each object has <em class="firstterm">members</em>; the two kinds of member + are <em class="firstterm">methods</em> and + <em class="firstterm">signals</em>. Methods are operations that can be + invoked on an object, with optional input (aka arguments or "in + parameters") and output (aka return values or "out parameters"). + Signals are broadcasts from the object to any interested observers + of the object; signals may contain a data payload. + </p><p> + Both methods and signals are referred to by name, such as + "Frobate" or "OnClicked". + </p></div><div class="sect2" title="Interfaces"><div class="titlepage"><div><div><h3 class="title"><a name="interfaces"></a>Interfaces</h3></div></div></div><p> + Each object supports one or more <em class="firstterm">interfaces</em>. + Think of an interface as a named group of methods and signals, + just as it is in GLib or Qt or Java. Interfaces define the + <span class="emphasis"><em>type</em></span> of an object instance. + </p><p> + DBus identifies interfaces with a simple namespaced string, + something like <code class="literal">org.freedesktop.Introspectable</code>. + Most bindings will map these interface names directly to + the appropriate programming language construct, for example + to Java interfaces or C++ pure virtual classes. + </p></div><div class="sect2" title="Proxies"><div class="titlepage"><div><div><h3 class="title"><a name="proxies"></a>Proxies</h3></div></div></div><p> + A <em class="firstterm">proxy object</em> is a convenient native object created to + represent a remote object in another process. The low-level DBus API involves manually creating + a method call message, sending it, then manually receiving and processing + the method reply message. Higher-level bindings provide proxies as an alternative. + Proxies look like a normal native object; but when you invoke a method on the proxy + object, the binding converts it into a DBus method call message, waits for the reply + message, unpacks the return value, and returns it from the native method.. + </p><p> + In pseudocode, programming without proxies might look like this: + </p><pre class="programlisting"> + Message message = new Message("/remote/object/path", "MethodName", arg1, arg2); + Connection connection = getBusConnection(); + connection.send(message); + Message reply = connection.waitForReply(message); + if (reply.isError()) { + + } else { + Object returnValue = reply.getReturnValue(); + } + </pre><p> + </p><p> + Programming with proxies might look like this: + </p><pre class="programlisting"> + Proxy proxy = new Proxy(getBusConnection(), "/remote/object/path"); + Object returnValue = proxy.MethodName(arg1, arg2); + </pre><p> + </p></div><div class="sect2" title="Bus Names"><div class="titlepage"><div><div><h3 class="title"><a name="bus-names"></a>Bus Names</h3></div></div></div><p> + When each application connects to the bus daemon, the daemon immediately + assigns it a name, called the <em class="firstterm">unique connection name</em>. + A unique name begins with a ':' (colon) character. These names are never + reused during the lifetime of the bus daemon - that is, you know + a given name will always refer to the same application. + An example of a unique name might be + <code class="literal">:34-907</code>. The numbers after the colon have + no meaning other than their uniqueness. + </p><p> + When a name is mapped + to a particular application's connection, that application is said to + <em class="firstterm">own</em> that name. + </p><p> + Applications may ask to own additional <em class="firstterm">well-known + names</em>. For example, you could write a specification to + define a name called <code class="literal">com.mycompany.TextEditor</code>. + Your definition could specify that to own this name, an application + should have an object at the path + <code class="literal">/com/mycompany/TextFileManager</code> supporting the + interface <code class="literal">org.freedesktop.FileHandler</code>. + </p><p> + Applications could then send messages to this bus name, + object, and interface to execute method calls. + </p><p> + You could think of the unique names as IP addresses, and the + well-known names as domain names. So + <code class="literal">com.mycompany.TextEditor</code> might map to something like + <code class="literal">:34-907</code> just as <code class="literal">mycompany.com</code> maps + to something like <code class="literal">192.168.0.5</code>. + </p><p> + Names have a second important use, other than routing messages. They + are used to track lifecycle. When an application exits (or crashes), its + connection to the message bus will be closed by the operating system + kernel. The message bus then sends out notification messages telling + remaining applications that the application's names have lost their + owner. By tracking these notifications, your application can reliably + monitor the lifetime of other applications. + </p><p> + Bus names can also be used to coordinate single-instance applications. + If you want to be sure only one + <code class="literal">com.mycompany.TextEditor</code> application is running for + example, have the text editor application exit if the bus name already + has an owner. + </p></div><div class="sect2" title="Addresses"><div class="titlepage"><div><div><h3 class="title"><a name="addresses"></a>Addresses</h3></div></div></div><p> + Applications using D-Bus are either servers or clients. A server + listens for incoming connections; a client connects to a server. Once + the connection is established, it is a symmetric flow of messages; the + client-server distinction only matters when setting up the + connection. + </p><p> + If you're using the bus daemon, as you probably are, your application + will be a client of the bus daemon. That is, the bus daemon listens + for connections and your application initiates a connection to the bus + daemon. + </p><p> + A D-Bus <em class="firstterm">address</em> specifies where a server will + listen, and where a client will connect. For example, the address + <code class="literal">unix:path=/tmp/abcdef</code> specifies that the server will + listen on a UNIX domain socket at the path + <code class="literal">/tmp/abcdef</code> and the client will connect to that + socket. An address can also specify TCP/IP sockets, or any other + transport defined in future iterations of the D-Bus specification. + </p><p> + When using D-Bus with a message bus daemon, + libdbus automatically discovers the address of the per-session bus + daemon by reading an environment variable. It discovers the + systemwide bus daemon by checking a well-known UNIX domain socket path + (though you can override this address with an environment variable). + </p><p> + If you're using D-Bus without a bus daemon, it's up to you to + define which application will be the server and which will be + the client, and specify a mechanism for them to agree on + the server's address. This is an unusual case. + </p></div><div class="sect2" title="Big Conceptual Picture"><div class="titlepage"><div><div><h3 class="title"><a name="bigpicture"></a>Big Conceptual Picture</h3></div></div></div><p> + Pulling all these concepts together, to specify a particular + method call on a particular object instance, a number of + nested components have to be named: + </p><pre class="programlisting"> + Address -> [Bus Name] -> Path -> Interface -> Method + </pre><p> + The bus name is in brackets to indicate that it's optional -- you only + provide a name to route the method call to the right application + when using the bus daemon. If you have a direct connection to another + application, bus names aren't used; there's no bus daemon. + </p><p> + The interface is also optional, primarily for historical + reasons; DCOP does not require specifying the interface, + instead simply forbidding duplicate method names + on the same object instance. D-Bus will thus let you + omit the interface, but if your method name is ambiguous + it is undefined which method will be invoked. + </p></div><div class="sect2" title="Messages - Behind the Scenes"><div class="titlepage"><div><div><h3 class="title"><a name="messages"></a>Messages - Behind the Scenes</h3></div></div></div><p> + D-Bus works by sending messages between processes. If you're using + a sufficiently high-level binding, you may never work with messages directly. + </p><p> + There are 4 message types: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + Method call messages ask to invoke a method + on an object. + </p></li><li class="listitem"><p> + Method return messages return the results + of invoking a method. + </p></li><li class="listitem"><p> + Error messages return an exception caused by + invoking a method. + </p></li><li class="listitem"><p> + Signal messages are notifications that a given signal + has been emitted (that an event has occurred). + You could also think of these as "event" messages. + </p></li></ul></div><p> + </p><p> + A method call maps very simply to messages: you send a method call + message, and receive either a method return message or an error message + in reply. + </p><p> + Each message has a <em class="firstterm">header</em>, including <em class="firstterm">fields</em>, + and a <em class="firstterm">body</em>, including <em class="firstterm">arguments</em>. You can think + of the header as the routing information for the message, and the body as the payload. + Header fields might include the sender bus name, destination bus name, method or signal name, + and so forth. One of the header fields is a <em class="firstterm">type signature</em> describing the + values found in the body. For example, the letter "i" means "32-bit integer" so the signature + "ii" means the payload has two 32-bit integers. + </p></div><div class="sect2" title="Calling a Method - Behind the Scenes"><div class="titlepage"><div><div><h3 class="title"><a name="callprocedure"></a>Calling a Method - Behind the Scenes</h3></div></div></div><p> + A method call in DBus consists of two messages; a method call message sent from process A to process B, + and a matching method reply message sent from process B to process A. Both the call and the reply messages + are routed through the bus daemon. The caller includes a different serial number in each call message, and the + reply message includes this number to allow the caller to match replies to calls. + </p><p> + The call message will contain any arguments to the method. + The reply message may indicate an error, or may contain data returned by the method. + </p><p> + A method invocation in DBus happens as follows: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + The language binding may provide a proxy, such that invoking a method on + an in-process object invokes a method on a remote object in another process. If so, the + application calls a method on the proxy, and the proxy + constructs a method call message to send to the remote process. + </p></li><li class="listitem"><p> + For more low-level APIs, the application may construct a method call message itself, without + using a proxy. + </p></li><li class="listitem"><p> + In either case, the method call message contains: a bus name belonging to the remote process; the name of the method; + the arguments to the method; an object path inside the remote process; and optionally the name of the + interface that specifies the method. + </p></li><li class="listitem"><p> + The method call message is sent to the bus daemon. + </p></li><li class="listitem"><p> + The bus daemon looks at the destination bus name. If a process owns that name, + the bus daemon forwards the method call to that process. Otherwise, the bus daemon + creates an error message and sends it back as the reply to the method call message. + </p></li><li class="listitem"><p> + The receiving process unpacks the method call message. In a simple low-level API situation, it + may immediately run the method and send a method reply message to the bus daemon. + When using a high-level binding API, the binding might examine the object path, interface, + and method name, and convert the method call message into an invocation of a method on + a native object (GObject, java.lang.Object, QObject, etc.), then convert the return + value from the native method into a method reply message. + </p></li><li class="listitem"><p> + The bus daemon receives the method reply message and sends it to the process that + made the method call. + </p></li><li class="listitem"><p> + The process that made the method call looks at the method reply and makes use of any + return values included in the reply. The reply may also indicate that an error occurred. + When using a binding, the method reply message may be converted into the return value of + of a proxy method, or into an exception. + </p></li></ul></div><p> + </p><p> + The bus daemon never reorders messages. That is, if you send two method call messages to the same recipient, + they will be received in the order they were sent. The recipient is not required to reply to the calls + in order, however; for example, it may process each method call in a separate thread, and return reply messages + in an undefined order depending on when the threads complete. Method calls have a unique serial + number used by the method caller to match reply messages to call messages. + </p></div><div class="sect2" title="Emitting a Signal - Behind the Scenes"><div class="titlepage"><div><div><h3 class="title"><a name="signalprocedure"></a>Emitting a Signal - Behind the Scenes</h3></div></div></div><p> + A signal in DBus consists of a single message, sent by one process to any number of other processes. + That is, a signal is a unidirectional broadcast. The signal may contain arguments (a data payload), but + because it is a broadcast, it never has a "return value." Contrast this with a method call + (see <a class="xref" href="#callprocedure" title="Calling a Method - Behind the Scenes">the section called “Calling a Method - Behind the Scenes”</a>) where the method call message has a matching method reply message. + </p><p> + The emitter (aka sender) of a signal has no knowledge of the signal recipients. Recipients register + with the bus daemon to receive signals based on "match rules" - these rules would typically include the sender and + the signal name. The bus daemon sends each signal only to recipients who have expressed interest in that + signal. + </p><p> + A signal in DBus happens as follows: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + A signal message is created and sent to the bus daemon. When using the low-level API this may be + done manually, with certain bindings it may be done for you by the binding when a native object + emits a native signal or event. + </p></li><li class="listitem"><p> + The signal message contains the name of the interface that specifies the signal; + the name of the signal; the bus name of the process sending the signal; and + any arguments + </p></li><li class="listitem"><p> + Any process on the message bus can register "match rules" indicating which signals it + is interested in. The bus has a list of registered match rules. + </p></li><li class="listitem"><p> + The bus daemon examines the signal and determines which processes are interested in it. + It sends the signal message to these processes. + </p></li><li class="listitem"><p> + Each process receiving the signal decides what to do with it; if using a binding, + the binding may choose to emit a native signal on a proxy object. If using the + low-level API, the process may just look at the signal sender and name and decide + what to do based on that. + </p></li></ul></div><p> + </p></div><div class="sect2" title="Introspection"><div class="titlepage"><div><div><h3 class="title"><a name="introspection"></a>Introspection</h3></div></div></div><p> + D-Bus objects may support the interface <code class="literal">org.freedesktop.DBus.Introspectable</code>. + This interface has one method <code class="literal">Introspect</code> which takes no arguments and returns + an XML string. The XML string describes the interfaces, methods, and signals of the object. + See the D-Bus specification for more details on this introspection format. + </p></div></div><div class="sect1" title="GLib API: Using Remote Objects"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="glib-client"></a>GLib API: Using Remote Objects</h2></div></div></div><p> + The GLib binding is defined in the header file + <code class="literal"><dbus/dbus-glib.h></code>. + </p><div class="sect2" title="D-Bus - GLib type mappings"><div class="titlepage"><div><div><h3 class="title"><a name="glib-typemappings"></a>D-Bus - GLib type mappings</h3></div></div></div><p> + The heart of the GLib bindings for D-Bus is the mapping it + provides between D-Bus "type signatures" and GLib types + (<code class="literal">GType</code>). The D-Bus type system is composed of + a number of "basic" types, along with several "container" types. + </p><div class="sect3" title="Basic type mappings"><div class="titlepage"><div><div><h4 class="title"><a name="glib-basic-typemappings"></a>Basic type mappings</h4></div></div></div><p> + Below is a list of the basic types, along with their associated + mapping to a <code class="literal">GType</code>. + </p><div class="informaltable"><table border="1"><colgroup><col><col><col><col></colgroup><thead><tr><th>D-Bus basic type</th><th>GType</th><th>Free function</th><th>Notes</th></tr></thead><tbody><tr><td><code class="literal">BYTE</code></td><td><code class="literal">G_TYPE_UCHAR</code></td><td> </td><td> </td></tr><tr><td><code class="literal">BOOLEAN</code></td><td><code class="literal">G_TYPE_BOOLEAN</code></td><td> </td><td> </td></tr><tr><td><code class="literal">INT16</code></td><td><code class="literal">G_TYPE_INT</code></td><td> </td><td>Will be changed to a <code class="literal">G_TYPE_INT16</code> once GLib has it</td></tr><tr><td><code class="literal">UINT16</code></td><td><code class="literal">G_TYPE_UINT</code></td><td> </td><td>Will be changed to a <code class="literal">G_TYPE_UINT16</code> once GLib has it</td></tr><tr><td><code class="literal">INT32</code></td><td><code class="literal">G_TYPE_INT</code></td><td> </td><td>Will be changed to a <code class="literal">G_TYPE_INT32</code> once GLib has it</td></tr><tr><td><code class="literal">UINT32</code></td><td><code class="literal">G_TYPE_UINT</code></td><td> </td><td>Will be changed to a <code class="literal">G_TYPE_UINT32</code> once GLib has it</td></tr><tr><td><code class="literal">INT64</code></td><td><code class="literal">G_TYPE_GINT64</code></td><td> </td><td> </td></tr><tr><td><code class="literal">UINT64</code></td><td><code class="literal">G_TYPE_GUINT64</code></td><td> </td><td> </td></tr><tr><td><code class="literal">DOUBLE</code></td><td><code class="literal">G_TYPE_DOUBLE</code></td><td> </td><td> </td></tr><tr><td><code class="literal">STRING</code></td><td><code class="literal">G_TYPE_STRING</code></td><td><code class="literal">g_free</code></td><td> </td></tr><tr><td><code class="literal">OBJECT_PATH</code></td><td><code class="literal">DBUS_TYPE_G_PROXY</code></td><td><code class="literal">g_object_unref</code></td><td>The returned proxy does not have an interface set; use <code class="literal">dbus_g_proxy_set_interface</code> to invoke methods</td></tr></tbody></table></div><p> + As you can see, the basic mapping is fairly straightforward. + </p></div><div class="sect3" title="Container type mappings"><div class="titlepage"><div><div><h4 class="title"><a name="glib-container-typemappings"></a>Container type mappings</h4></div></div></div><p> + The D-Bus type system also has a number of "container" + types, such as <code class="literal">DBUS_TYPE_ARRAY</code> and + <code class="literal">DBUS_TYPE_STRUCT</code>. The D-Bus type system + is fully recursive, so one can for example have an array of + array of strings (i.e. type signature + <code class="literal">aas</code>). + </p><p> + However, not all of these types are in common use; for + example, at the time of this writing the author knows of no + one using <code class="literal">DBUS_TYPE_STRUCT</code>, or a + <code class="literal">DBUS_TYPE_ARRAY</code> containing any non-basic + type. The approach the GLib bindings take is pragmatic; try + to map the most common types in the most obvious way, and + let using less common and more complex types be less + "natural". + </p><p> + First, D-Bus type signatures which have an "obvious" + corresponding built-in GLib type are mapped using that type: + </p><div class="informaltable"><table border="1"><colgroup><col><col><col><col><col><col></colgroup><thead><tr><th>D-Bus type signature</th><th>Description</th><th>GType</th><th>C typedef</th><th>Free function</th><th>Notes</th></tr></thead><tbody><tr><td><code class="literal">as</code></td><td>Array of strings</td><td><code class="literal">G_TYPE_STRV</code></td><td><code class="literal">char **</code></td><td><code class="literal">g_strfreev</code></td><td> </td></tr><tr><td><code class="literal">v</code></td><td>Generic value container</td><td><code class="literal">G_TYPE_VALUE</code></td><td><code class="literal">GValue *</code></td><td><code class="literal">g_value_unset</code></td><td>The calling conventions for values expect that method callers have allocated return values; see below.</td></tr></tbody></table></div><p> + </p><p> + The next most common recursive type signatures are arrays of + basic values. The most obvious mapping for arrays of basic + types is a <code class="literal">GArray</code>. Now, GLib does not + provide a builtin <code class="literal">GType</code> for + <code class="literal">GArray</code>. However, we actually need more than + that - we need a "parameterized" type which includes the + contained type. Why we need this we will see below. + </p><p> + The approach taken is to create these types in the D-Bus GLib + bindings; however, there is nothing D-Bus specific about them. + In the future, we hope to include such "fundamental" types in GLib + itself. + </p><div class="informaltable"><table border="1"><colgroup><col><col><col><col><col><col></colgroup><thead><tr><th>D-Bus type signature</th><th>Description</th><th>GType</th><th>C typedef</th><th>Free function</th><th>Notes</th></tr></thead><tbody><tr><td><code class="literal">ay</code></td><td>Array of bytes</td><td><code class="literal">DBUS_TYPE_G_BYTE_ARRAY</code></td><td><code class="literal">GArray *</code></td><td>g_array_free</td><td> </td></tr><tr><td><code class="literal">au</code></td><td>Array of uint</td><td><code class="literal">DBUS_TYPE_G_UINT_ARRAY</code></td><td><code class="literal">GArray *</code></td><td>g_array_free</td><td> </td></tr><tr><td><code class="literal">ai</code></td><td>Array of int</td><td><code class="literal">DBUS_TYPE_G_INT_ARRAY</code></td><td><code class="literal">GArray *</code></td><td>g_array_free</td><td> </td></tr><tr><td><code class="literal">ax</code></td><td>Array of int64</td><td><code class="literal">DBUS_TYPE_G_INT64_ARRAY</code></td><td><code class="literal">GArray *</code></td><td>g_array_free</td><td> </td></tr><tr><td><code class="literal">at</code></td><td>Array of uint64</td><td><code class="literal">DBUS_TYPE_G_UINT64_ARRAY</code></td><td><code class="literal">GArray *</code></td><td>g_array_free</td><td> </td></tr><tr><td><code class="literal">ad</code></td><td>Array of double</td><td><code class="literal">DBUS_TYPE_G_DOUBLE_ARRAY</code></td><td><code class="literal">GArray *</code></td><td>g_array_free</td><td> </td></tr><tr><td><code class="literal">ab</code></td><td>Array of boolean</td><td><code class="literal">DBUS_TYPE_G_BOOLEAN_ARRAY</code></td><td><code class="literal">GArray *</code></td><td>g_array_free</td><td> </td></tr></tbody></table></div><p> + </p><p> + D-Bus also includes a special type DBUS_TYPE_DICT_ENTRY which + is only valid in arrays. It's intended to be mapped to a "dictionary" + type by bindings. The obvious GLib mapping here is GHashTable. Again, + however, there is no builtin <code class="literal">GType</code> for a GHashTable. + Moreover, just like for arrays, we need a parameterized type so that + the bindings can communiate which types are contained in the hash table. + </p><p> + At present, only strings are supported. Work is in progress to + include more types. + </p><div class="informaltable"><table border="1"><colgroup><col><col><col><col><col><col></colgroup><thead><tr><th>D-Bus type signature</th><th>Description</th><th>GType</th><th>C typedef</th><th>Free function</th><th>Notes</th></tr></thead><tbody><tr><td><code class="literal">a{ss}</code></td><td>Dictionary mapping strings to strings</td><td><code class="literal">DBUS_TYPE_G_STRING_STRING_HASHTABLE</code></td><td><code class="literal">GHashTable *</code></td><td>g_hash_table_destroy</td><td> </td></tr></tbody></table></div><p> + </p></div><div class="sect3" title="Arbitrarily recursive type mappings"><div class="titlepage"><div><div><h4 class="title"><a name="glib-generic-typemappings"></a>Arbitrarily recursive type mappings</h4></div></div></div><p> + Finally, it is possible users will want to write or invoke D-Bus + methods which have arbitrarily complex type signatures not + directly supported by these bindings. For this case, we have a + <code class="literal">DBusGValue</code> which acts as a kind of special + variant value which may be iterated over manually. The + <code class="literal">GType</code> associated is + <code class="literal">DBUS_TYPE_G_VALUE</code>. + </p><p> + TODO insert usage of <code class="literal">DBUS_TYPE_G_VALUE</code> here. + </p></div></div><div class="sect2" title="A sample program"><div class="titlepage"><div><div><h3 class="title"><a name="sample-program-1"></a>A sample program</h3></div></div></div><p>Here is a D-Bus program using the GLib bindings. +</p><pre class="programlisting"> +int +main (int argc, char **argv) +{ + DBusGConnection *connection; + GError *error; + DBusGProxy *proxy; + char **name_list; + char **name_list_ptr; + + g_type_init (); + + error = NULL; + connection = dbus_g_bus_get (DBUS_BUS_SESSION, + &error); + if (connection == NULL) + { + g_printerr ("Failed to open connection to bus: %s\n", + error->message); + g_error_free (error); + exit (1); + } + + /* Create a proxy object for the "bus driver" (name "org.freedesktop.DBus") */ + + proxy = dbus_g_proxy_new_for_name (connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + + /* Call ListNames method, wait for reply */ + error = NULL; + if (!dbus_g_proxy_call (proxy, "ListNames", &error, G_TYPE_INVALID, + G_TYPE_STRV, &name_list, G_TYPE_INVALID)) + { + /* Just do demonstrate remote exceptions versus regular GError */ + if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) + g_printerr ("Caught remote method exception %s: %s", + dbus_g_error_get_name (error), + error->message); + else + g_printerr ("Error: %s\n", error->message); + g_error_free (error); + exit (1); + } + + /* Print the results */ + + g_print ("Names on the message bus:\n"); + + for (name_list_ptr = name_list; *name_list_ptr; name_list_ptr++) + { + g_print (" %s\n", *name_list_ptr); + } + g_strfreev (name_list); + + g_object_unref (proxy); + + return 0; +} +</pre><p> + </p></div><div class="sect2" title="Program initalization"><div class="titlepage"><div><div><h3 class="title"><a name="glib-program-setup"></a>Program initalization</h3></div></div></div><p> + A connection to the bus is acquired using + <code class="literal">dbus_g_bus_get</code>. Next, a proxy + is created for the object "/org/freedesktop/DBus" with + interface <code class="literal">org.freedesktop.DBus</code> + on the service <code class="literal">org.freedesktop.DBus</code>. + This is a proxy for the message bus itself. + </p></div><div class="sect2" title="Understanding method invocation"><div class="titlepage"><div><div><h3 class="title"><a name="glib-method-invocation"></a>Understanding method invocation</h3></div></div></div><p> + You have a number of choices for method invocation. First, as + used above, <code class="literal">dbus_g_proxy_call</code> sends a + method call to the remote object, and blocks until a reply is + recieved. The outgoing arguments are specified in the varargs + array, terminated with <code class="literal">G_TYPE_INVALID</code>. + Next, pointers to return values are specified, followed again + by <code class="literal">G_TYPE_INVALID</code>. + </p><p> + To invoke a method asynchronously, use + <code class="literal">dbus_g_proxy_begin_call</code>. This returns a + <code class="literal">DBusGPendingCall</code> object; you may then set a + notification function using + <code class="literal">dbus_g_pending_call_set_notify</code>. + </p></div><div class="sect2" title="Connecting to object signals"><div class="titlepage"><div><div><h3 class="title"><a name="glib-signal-connection"></a>Connecting to object signals</h3></div></div></div><p> + You may connect to signals using + <code class="literal">dbus_g_proxy_add_signal</code> and + <code class="literal">dbus_g_proxy_connect_signal</code>. You must + invoke <code class="literal">dbus_g_proxy_add_signal</code> to specify + the signature of your signal handlers; you may then invoke + <code class="literal">dbus_g_proxy_connect_signal</code> multiple times. + </p><p> + Note that it will often be the case that there is no builtin + marshaller for the type signature of a remote signal. In that + case, you must generate a marshaller yourself by using + <span class="application">glib-genmarshal</span>, and then register + it using <code class="literal">dbus_g_object_register_marshaller</code>. + </p></div><div class="sect2" title="Error handling and remote exceptions"><div class="titlepage"><div><div><h3 class="title"><a name="glib-error-handling"></a>Error handling and remote exceptions</h3></div></div></div><p> + All of the GLib binding methods such as + <code class="literal">dbus_g_proxy_end_call</code> return a + <code class="literal">GError</code>. This <code class="literal">GError</code> can + represent two different things: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + An internal D-Bus error, such as an out-of-memory + condition, an I/O error, or a network timeout. Errors + generated by the D-Bus library itself have the domain + <code class="literal">DBUS_GERROR</code>, and a corresponding code + such as <code class="literal">DBUS_GERROR_NO_MEMORY</code>. It will + not be typical for applications to handle these errors + specifically. + </p></li><li class="listitem"><p> + A remote D-Bus exception, thrown by the peer, bus, or + service. D-Bus remote exceptions have both a textual + "name" and a "message". The GLib bindings store this + information in the <code class="literal">GError</code>, but some + special rules apply. + </p><p> + The set error will have the domain + <code class="literal">DBUS_GERROR</code> as above, and will also + have the code + <code class="literal">DBUS_GERROR_REMOTE_EXCEPTION</code>. In order + to access the remote exception name, you must use a + special accessor, such as + <code class="literal">dbus_g_error_has_name</code> or + <code class="literal">dbus_g_error_get_name</code>. The remote + exception detailed message is accessible via the regular + GError <code class="literal">message</code> member. + </p></li></ul></div><p> + </p></div><div class="sect2" title="More examples of method invocation"><div class="titlepage"><div><div><h3 class="title"><a name="glib-more-examples"></a>More examples of method invocation</h3></div></div></div><div class="sect3" title="Sending an integer and string, receiving an array of bytes"><div class="titlepage"><div><div><h4 class="title"><a name="glib-sending-stuff"></a>Sending an integer and string, receiving an array of bytes</h4></div></div></div><p> +</p><pre class="programlisting"> + GArray *arr; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "Foobar", &error, + G_TYPE_INT, 42, G_TYPE_STRING, "hello", + G_TYPE_INVALID, + DBUS_TYPE_G_UCHAR_ARRAY, &arr, G_TYPE_INVALID)) + { + /* Handle error */ + } + g_assert (arr != NULL); + printf ("got back %u values", arr->len); +</pre><p> + </p></div><div class="sect3" title="Sending a GHashTable"><div class="titlepage"><div><div><h4 class="title"><a name="glib-sending-hash"></a>Sending a GHashTable</h4></div></div></div><p> +</p><pre class="programlisting"> + GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal); + guint32 ret; + + g_hash_table_insert (hash, "foo", "bar"); + g_hash_table_insert (hash, "baz", "whee"); + + error = NULL; + if (!dbus_g_proxy_call (proxy, "HashSize", &error, + DBUS_TYPE_G_STRING_STRING_HASH, hash, G_TYPE_INVALID, + G_TYPE_UINT, &ret, G_TYPE_INVALID)) + { + /* Handle error */ + } + g_assert (ret == 2); + g_hash_table_destroy (hash); +</pre><p> + </p></div><div class="sect3" title="Receiving a boolean and a string"><div class="titlepage"><div><div><h4 class="title"><a name="glib-receiving-bool-int"></a>Receiving a boolean and a string</h4></div></div></div><p> +</p><pre class="programlisting"> + gboolean boolret; + char *strret; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "GetStuff", &error, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, &boolret, + G_TYPE_STRING, &strret, + G_TYPE_INVALID)) + { + /* Handle error */ + } + printf ("%s %s", boolret ? "TRUE" : "FALSE", strret); + g_free (strret); +</pre><p> + </p></div><div class="sect3" title="Sending two arrays of strings"><div class="titlepage"><div><div><h4 class="title"><a name="glib-sending-str-arrays"></a>Sending two arrays of strings</h4></div></div></div><p> +</p><pre class="programlisting"> + /* NULL terminate */ + char *strs_static[] = {"foo", "bar", "baz", NULL}; + /* Take pointer to array; cannot pass array directly */ + char **strs_static_p = strs_static; + char **strs_dynamic; + + strs_dynamic = g_new (char *, 4); + strs_dynamic[0] = g_strdup ("hello"); + strs_dynamic[1] = g_strdup ("world"); + strs_dynamic[2] = g_strdup ("!"); + /* NULL terminate */ + strs_dynamic[3] = NULL; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "TwoStrArrays", &error, + G_TYPE_STRV, strs_static_p, + G_TYPE_STRV, strs_dynamic, + G_TYPE_INVALID, + G_TYPE_INVALID)) + { + /* Handle error */ + } + g_strfreev (strs_dynamic); +</pre><p> + </p></div><div class="sect3" title="Sending a boolean, receiving an array of strings"><div class="titlepage"><div><div><h4 class="title"><a name="glib-getting-str-array"></a>Sending a boolean, receiving an array of strings</h4></div></div></div><p> +</p><pre class="programlisting"> + char **strs; + char **strs_p; + gboolean blah; + + error = NULL; + blah = TRUE; + if (!dbus_g_proxy_call (proxy, "GetStrs", &error, + G_TYPE_BOOLEAN, blah, + G_TYPE_INVALID, + G_TYPE_STRV, &strs, + G_TYPE_INVALID)) + { + /* Handle error */ + } + for (strs_p = strs; *strs_p; strs_p++) + printf ("got string: \"%s\"", *strs_p); + g_strfreev (strs); +</pre><p> + </p></div><div class="sect3" title="Sending a variant"><div class="titlepage"><div><div><h4 class="title"><a name="glib-sending-variant"></a>Sending a variant</h4></div></div></div><p> +</p><pre class="programlisting"> + GValue val = {0, }; + + g_value_init (&val, G_TYPE_STRING); + g_value_set_string (&val, "hello world"); + + error = NULL; + if (!dbus_g_proxy_call (proxy, "SendVariant", &error, + G_TYPE_VALUE, &val, G_TYPE_INVALID, + G_TYPE_INVALID)) + { + /* Handle error */ + } + g_assert (ret == 2); + g_value_unset (&val); +</pre><p> + </p></div><div class="sect3" title="Receiving a variant"><div class="titlepage"><div><div><h4 class="title"><a name="glib-receiving-variant"></a>Receiving a variant</h4></div></div></div><p> +</p><pre class="programlisting"> + GValue val = {0, }; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "GetVariant", &error, G_TYPE_INVALID, + G_TYPE_VALUE, &val, G_TYPE_INVALID)) + { + /* Handle error */ + } + if (G_VALUE_TYPE (&val) == G_TYPE_STRING) + printf ("%s\n", g_value_get_string (&val)); + else if (G_VALUE_TYPE (&val) == G_TYPE_INT) + printf ("%d\n", g_value_get_int (&val)); + else + ... + g_value_unset (&val); +</pre><p> + </p></div></div><div class="sect2" title="Generated Bindings"><div class="titlepage"><div><div><h3 class="title"><a name="glib-generated-bindings"></a>Generated Bindings</h3></div></div></div><p> + By using the Introspection XML files, convenient client-side bindings + can be automatically created to ease the use of a remote DBus object. + </p><p> + Here is a sample XML file which describes an object that exposes + one method, named <code class="literal">ManyArgs</code>. + </p><pre class="programlisting"> +<?xml version="1.0" encoding="UTF-8" ?> +<node name="/com/example/MyObject"> + <interface name="com.example.MyObject"> + <method name="ManyArgs"> + <arg type="u" name="x" direction="in" /> + <arg type="s" name="str" direction="in" /> + <arg type="d" name="trouble" direction="in" /> + <arg type="d" name="d_ret" direction="out" /> + <arg type="s" name="str_ret" direction="out" /> + </method> + </interface> +</node> +</pre><p> + </p><p> + Run <code class="literal">dbus-binding-tool --mode=glib-client + <em class="replaceable"><code>FILENAME</code></em> > + <em class="replaceable"><code>HEADER_NAME</code></em></code> to generate the header + file. For example: <span class="command"><strong>dbus-binding-tool --mode=glib-client + my-object.xml > my-object-bindings.h</strong></span>. This will generate + inline functions with the following prototypes: + </p><pre class="programlisting"> +/* This is a blocking call */ +gboolean +com_example_MyObject_many_args (DBusGProxy *proxy, const guint IN_x, + const char * IN_str, const gdouble IN_trouble, + gdouble* OUT_d_ret, char ** OUT_str_ret, + GError **error); + +/* This is a non-blocking call */ +DBusGProxyCall* +com_example_MyObject_many_args_async (DBusGProxy *proxy, const guint IN_x, + const char * IN_str, const gdouble IN_trouble, + com_example_MyObject_many_args_reply callback, + gpointer userdata); + +/* This is the typedef for the non-blocking callback */ +typedef void +(*com_example_MyObject_many_args_reply) +(DBusGProxy *proxy, gdouble OUT_d_ret, char * OUT_str_ret, + GError *error, gpointer userdata); +</pre><p> + The first argument in all functions is a <code class="literal">DBusGProxy + *</code>, which you should create with the usual + <code class="literal">dbus_g_proxy_new_*</code> functions. Following that are the + "in" arguments, and then either the "out" arguments and a + <code class="literal">GError *</code> for the synchronous (blocking) function, or + callback and user data arguments for the asynchronous (non-blocking) + function. The callback in the asynchronous function passes the + <code class="literal">DBusGProxy *</code>, the returned "out" arguments, an + <code class="literal">GError *</code> which is set if there was an error otherwise + <code class="literal">NULL</code>, and the user data. + </p><p> + As with the server-side bindings support (see <a class="xref" href="#glib-server" title="GLib API: Implementing Objects">the section called “GLib API: Implementing Objects”</a>), the exact behaviour of the client-side + bindings can be manipulated using "annotations". Currently the only + annotation used by the client bindings is + <code class="literal">org.freedesktop.DBus.GLib.NoReply</code>, which sets the + flag indicating that the client isn't expecting a reply to the method + call, so a reply shouldn't be sent. This is often used to speed up + rapid method calls where there are no "out" arguments, and not knowing + if the method succeeded is an acceptable compromise to half the traffic + on the bus. + </p></div></div><div class="sect1" title="GLib API: Implementing Objects"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="glib-server"></a>GLib API: Implementing Objects</h2></div></div></div><p> + At the moment, to expose a GObject via D-Bus, you must + write XML by hand which describes the methods exported + by the object. In the future, this manual step will + be obviated by the upcoming GLib introspection support. + </p><p> + Here is a sample XML file which describes an object that exposes + one method, named <code class="literal">ManyArgs</code>. +</p><pre class="programlisting"> +<?xml version="1.0" encoding="UTF-8" ?> + +<node name="/com/example/MyObject"> + + <interface name="com.example.MyObject"> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object"/> + <method name="ManyArgs"> + <!-- This is optional, and in this case is redunundant --> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object_many_args"/> + <arg type="u" name="x" direction="in" /> + <arg type="s" name="str" direction="in" /> + <arg type="d" name="trouble" direction="in" /> + <arg type="d" name="d_ret" direction="out" /> + <arg type="s" name="str_ret" direction="out" /> + </method> + </interface> +</node> +</pre><p> + </p><p> + This XML is in the same format as the D-Bus introspection XML + format. Except we must include an "annotation" which give the C + symbols corresponding to the object implementation prefix + (<code class="literal">my_object</code>). In addition, if particular + methods symbol names deviate from C convention + (i.e. <code class="literal">ManyArgs</code> -> + <code class="literal">many_args</code>), you may specify an annotation + giving the C symbol. + </p><p> + Once you have written this XML, run <code class="literal">dbus-binding-tool --mode=glib-server <em class="replaceable"><code>FILENAME</code></em> > <em class="replaceable"><code>HEADER_NAME</code></em>.</code> to + generate a header file. For example: <span class="command"><strong>dbus-binding-tool --mode=glib-server my-object.xml > my-object-glue.h</strong></span>. + </p><p> + Next, include the generated header in your program, and invoke + <code class="literal">dbus_g_object_class_install_info</code> in the class + initializer, passing the object class and "object info" included in the + header. For example: + </p><pre class="programlisting"> + dbus_g_object_type_install_info (COM_FOO_TYPE_MY_OBJECT, &com_foo_my_object_info); + </pre><p> + This should be done exactly once per object class. + </p><p> + To actually implement the method, just define a C function named e.g. + <code class="literal">my_object_many_args</code> in the same file as the info + header is included. At the moment, it is required that this function + conform to the following rules: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + The function must return a value of type <code class="literal">gboolean</code>; + <code class="literal">TRUE</code> on success, and <code class="literal">FALSE</code> + otherwise. + </p></li><li class="listitem"><p> + The first parameter is a pointer to an instance of the object. + </p></li><li class="listitem"><p> + Following the object instance pointer are the method + input values. + </p></li><li class="listitem"><p> + Following the input values are pointers to return values. + </p></li><li class="listitem"><p> + The final parameter must be a <code class="literal">GError **</code>. + If the function returns <code class="literal">FALSE</code> for an + error, the error parameter must be initalized with + <code class="literal">g_set_error</code>. + </p></li></ul></div><p> + </p><p> + Finally, you can export an object using <code class="literal">dbus_g_connection_register_g_object</code>. For example: + </p><pre class="programlisting"> + dbus_g_connection_register_g_object (connection, + "/com/foo/MyObject", + obj); + </pre><p> + </p><div class="sect2" title="Server-side Annotations"><div class="titlepage"><div><div><h3 class="title"><a name="glib-annotations"></a>Server-side Annotations</h3></div></div></div><p> + There are several annotations that are used when generating the + server-side bindings. The most common annotation is + <code class="literal">org.freedesktop.DBus.GLib.CSymbol</code> but there are other + annotations which are often useful. + </p><div class="variablelist"><dl><dt><span class="term"><code class="literal">org.freedesktop.DBus.GLib.CSymbol</code></span></dt><dd><p> + This annotation is used to specify the C symbol names for + the various types (interface, method, etc), if it differs from the + name DBus generates. + </p></dd><dt><span class="term"><code class="literal">org.freedesktop.DBus.GLib.Async</code></span></dt><dd><p> + This annotation marks the method implementation as an + asynchronous function, which doesn't return a response straight + away but will send the response at some later point to complete + the call. This is used to implement non-blocking services where + method calls can take time. + </p><p> + When a method is asynchronous, the function prototype is + different. It is required that the function conform to the + following rules: + </p><div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem"><p> + The function must return a value of type <code class="literal">gboolean</code>; + <code class="literal">TRUE</code> on success, and <code class="literal">FALSE</code> + otherwise. TODO: the return value is currently ignored. + </p></li><li class="listitem"><p> + The first parameter is a pointer to an instance of the object. + </p></li><li class="listitem"><p> + Following the object instance pointer are the method + input values. + </p></li><li class="listitem"><p> + The final parameter must be a + <code class="literal">DBusGMethodInvocation *</code>. This is used + when sending the response message back to the client, by + calling <code class="literal">dbus_g_method_return</code> or + <code class="literal">dbus_g_method_return_error</code>. + </p></li></ul></div><p> + </p></dd><dt><span class="term"><code class="literal">org.freedesktop.DBus.GLib.Const</code></span></dt><dd><p>This attribute can only be applied to "out" + <code class="literal"><arg></code> nodes, and specifies that the + parameter isn't being copied when returned. For example, this + turns a 's' argument from a <code class="literal">char **</code> to a + <code class="literal">const char **</code>, and results in the argument not + being freed by DBus after the message is sent. + </p></dd><dt><span class="term"><code class="literal">org.freedesktop.DBus.GLib.ReturnVal</code></span></dt><dd><p> + This attribute can only be applied to "out" + <code class="literal"><arg></code> nodes, and alters the expected + function signature. It currently can be set to two values: + <code class="literal">""</code> or <code class="literal">"error"</code>. The + argument marked with this attribute is not returned via a + pointer argument, but by the function's return value. If the + attribute's value is the empty string, the <code class="literal">GError + *</code> argument is also omitted so there is no standard way + to return an error value. This is very useful for interfacing + with existing code, as it is possible to match existing APIs. + If the attribute's value is <code class="literal">"error"</code>, then the + final argument is a <code class="literal">GError *</code> as usual. + </p><p> + Some examples to demonstrate the usage. This introspection XML: + </p><pre class="programlisting"> +<method name="Increment"> + <arg type="u" name="x" /> + <arg type="u" direction="out" /> +</method> + </pre><p> + Expects the following function declaration: + </p><pre class="programlisting"> +gboolean +my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error); + </pre><p> + </p><p> + This introspection XML: + </p><pre class="programlisting"> +<method name="IncrementRetval"> + <arg type="u" name="x" /> + <arg type="u" direction="out" > + <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value=""/> + </arg> +</method> + </pre><p> + Expects the following function declaration: + </p><pre class="programlisting"> +gint32 +my_object_increment_retval (MyObject *obj, gint32 x) + </pre><p> + </p><p> + This introspection XML: + </p><pre class="programlisting"> +<method name="IncrementRetvalError"> + <arg type="u" name="x" /> + <arg type="u" direction="out" > + <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value="error"/> + </arg> +</method> + </pre><p> + Expects the following function declaration: + </p><pre class="programlisting"> +gint32 +my_object_increment_retval_error (MyObject *obj, gint32 x, GError **error) + </pre><p> + </p></dd></dl></div><p> + </p></div></div><div class="sect1" title="Python API"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="python-client"></a>Python API</h2></div></div></div><p> + The Python API, dbus-python, is now documented separately in + <a class="ulink" href="http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html" target="_top">the dbus-python tutorial</a> (also available in doc/tutorial.txt, + and doc/tutorial.html if built with python-docutils, in the dbus-python + source distribution). + </p></div><div class="sect1" title="Qt API: Using Remote Objects"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="qt-client"></a>Qt API: Using Remote Objects</h2></div></div></div><p> + + The Qt bindings are not yet documented. + + </p></div><div class="sect1" title="Qt API: Implementing Objects"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="qt-server"></a>Qt API: Implementing Objects</h2></div></div></div><p> + The Qt bindings are not yet documented. + </p></div></div></body></html> diff --git a/doc/dbus-tutorial.xml b/doc/dbus-tutorial.xml new file mode 100644 index 00000000..5c385f0e --- /dev/null +++ b/doc/dbus-tutorial.xml @@ -0,0 +1,1667 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" +"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" +[ +]> + +<article id="index"> + <articleinfo> + <title>D-Bus Tutorial</title> + <releaseinfo>Version 0.5.0</releaseinfo> + <date>20 August 2006</date> + <authorgroup> + <author> + <firstname>Havoc</firstname> + <surname>Pennington</surname> + <affiliation> + <orgname>Red Hat, Inc.</orgname> + <address><email>hp@pobox.com</email></address> + </affiliation> + </author> + <author> + <firstname>David</firstname> + <surname>Wheeler</surname> + </author> + <author> + <firstname>John</firstname> + <surname>Palmieri</surname> + <affiliation> + <orgname>Red Hat, Inc.</orgname> + <address><email>johnp@redhat.com</email></address> + </affiliation> + </author> + <author> + <firstname>Colin</firstname> + <surname>Walters</surname> + <affiliation> + <orgname>Red Hat, Inc.</orgname> + <address><email>walters@redhat.com</email></address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + + <sect1 id="meta"> + <title>Tutorial Work In Progress</title> + + <para> + This tutorial is not complete; it probably contains some useful information, but + also has plenty of gaps. Right now, you'll also need to refer to the D-Bus specification, + Doxygen reference documentation, and look at some examples of how other apps use D-Bus. + </para> + + <para> + Enhancing the tutorial is definitely encouraged - send your patches or suggestions to the + mailing list. If you create a D-Bus binding, please add a section to the tutorial for your + binding, if only a short section with a couple of examples. + </para> + + </sect1> + + <sect1 id="whatis"> + <title>What is D-Bus?</title> + <para> + D-Bus is a system for <firstterm>interprocess communication</firstterm> + (IPC). Architecturally, it has several layers: + + <itemizedlist> + <listitem> + <para> + A library, <firstterm>libdbus</firstterm>, that allows two + applications to connect to each other and exchange messages. + </para> + </listitem> + <listitem> + <para> + A <firstterm>message bus daemon</firstterm> executable, built on + libdbus, that multiple applications can connect to. The daemon can + route messages from one application to zero or more other + applications. + </para> + </listitem> + <listitem> + <para> + <firstterm>Wrapper libraries</firstterm> or <firstterm>bindings</firstterm> + based on particular application frameworks. For example, libdbus-glib and + libdbus-qt. There are also bindings to languages such as + Python. These wrapper libraries are the API most people should use, + as they simplify the details of D-Bus programming. libdbus is + intended to be a low-level backend for the higher level bindings. + Much of the libdbus API is only useful for binding implementation. + </para> + </listitem> + </itemizedlist> + </para> + + <para> + libdbus only supports one-to-one connections, just like a raw network + socket. However, rather than sending byte streams over the connection, you + send <firstterm>messages</firstterm>. Messages have a header identifying + the kind of message, and a body containing a data payload. libdbus also + abstracts the exact transport used (sockets vs. whatever else), and + handles details such as authentication. + </para> + + <para> + The message bus daemon forms the hub of a wheel. Each spoke of the wheel + is a one-to-one connection to an application using libdbus. An + application sends a message to the bus daemon over its spoke, and the bus + daemon forwards the message to other connected applications as + appropriate. Think of the daemon as a router. + </para> + + <para> + The bus daemon has multiple instances on a typical computer. The + first instance is a machine-global singleton, that is, a system daemon + similar to sendmail or Apache. This instance has heavy security + restrictions on what messages it will accept, and is used for systemwide + communication. The other instances are created one per user login session. + These instances allow applications in the user's session to communicate + with one another. + </para> + + <para> + The systemwide and per-user daemons are separate. Normal within-session + IPC does not involve the systemwide message bus process and vice versa. + </para> + + <sect2 id="uses"> + <title>D-Bus applications</title> + <para> + There are many, many technologies in the world that have "Inter-process + communication" or "networking" in their stated purpose: <ulink + url="http://www.omg.org">CORBA</ulink>, <ulink + url="http://www.opengroup.org/dce/">DCE</ulink>, <ulink + url="http://www.microsoft.com/com/">DCOM</ulink>, <ulink + url="http://developer.kde.org/documentation/library/kdeqt/dcop.html">DCOP</ulink>, <ulink + url="http://www.xmlrpc.com">XML-RPC</ulink>, <ulink + url="http://www.w3.org/TR/SOAP/">SOAP</ulink>, <ulink + url="http://www.mbus.org/">MBUS</ulink>, <ulink + url="http://www.zeroc.com/ice.html">Internet Communications Engine (ICE)</ulink>, + and probably hundreds more. + Each of these is tailored for particular kinds of application. + D-Bus is designed for two specific cases: + <itemizedlist> + <listitem> + <para> + Communication between desktop applications in the same desktop + session; to allow integration of the desktop session as a whole, + and address issues of process lifecycle (when do desktop components + start and stop running). + </para> + </listitem> + <listitem> + <para> + Communication between the desktop session and the operating system, + where the operating system would typically include the kernel + and any system daemons or processes. + </para> + </listitem> + </itemizedlist> + </para> + <para> + For the within-desktop-session use case, the GNOME and KDE desktops + have significant previous experience with different IPC solutions + such as CORBA and DCOP. D-Bus is built on that experience and + carefully tailored to meet the needs of these desktop projects + in particular. D-Bus may or may not be appropriate for other + applications; the FAQ has some comparisons to other IPC systems. + </para> + <para> + The problem solved by the systemwide or communication-with-the-OS case + is explained well by the following text from the Linux Hotplug project: + <blockquote> + <para> + A gap in current Linux support is that policies with any sort of + dynamic "interact with user" component aren't currently + supported. For example, that's often needed the first time a network + adapter or printer is connected, and to determine appropriate places + to mount disk drives. It would seem that such actions could be + supported for any case where a responsible human can be identified: + single user workstations, or any system which is remotely + administered. + </para> + + <para> + This is a classic "remote sysadmin" problem, where in this case + hotplugging needs to deliver an event from one security domain + (operating system kernel, in this case) to another (desktop for + logged-in user, or remote sysadmin). Any effective response must go + the other way: the remote domain taking some action that lets the + kernel expose the desired device capabilities. (The action can often + be taken asynchronously, for example letting new hardware be idle + until a meeting finishes.) At this writing, Linux doesn't have + widely adopted solutions to such problems. However, the new D-Bus + work may begin to solve that problem. + </para> + </blockquote> + </para> + <para> + D-Bus may happen to be useful for purposes other than the one it was + designed for. Its general properties that distinguish it from + other forms of IPC are: + <itemizedlist> + <listitem> + <para> + Binary protocol designed to be used asynchronously + (similar in spirit to the X Window System protocol). + </para> + </listitem> + <listitem> + <para> + Stateful, reliable connections held open over time. + </para> + </listitem> + <listitem> + <para> + The message bus is a daemon, not a "swarm" or + distributed architecture. + </para> + </listitem> + <listitem> + <para> + Many implementation and deployment issues are specified rather + than left ambiguous/configurable/pluggable. + </para> + </listitem> + <listitem> + <para> + Semantics are similar to the existing DCOP system, allowing + KDE to adopt it more easily. + </para> + </listitem> + <listitem> + <para> + Security features to support the systemwide mode of the + message bus. + </para> + </listitem> + </itemizedlist> + </para> + </sect2> + </sect1> + <sect1 id="concepts"> + <title>Concepts</title> + <para> + Some basic concepts apply no matter what application framework you're + using to write a D-Bus application. The exact code you write will be + different for GLib vs. Qt vs. Python applications, however. + </para> + + <para> + Here is a diagram (<ulink url="diagram.png">png</ulink> <ulink + url="diagram.svg">svg</ulink>) that may help you visualize the concepts + that follow. + </para> + + <sect2 id="objects"> + <title>Native Objects and Object Paths</title> + <para> + Your programming framework probably defines what an "object" is like; + usually with a base class. For example: java.lang.Object, GObject, QObject, + python's base Object, or whatever. Let's call this a <firstterm>native object</firstterm>. + </para> + <para> + The low-level D-Bus protocol, and corresponding libdbus API, does not care about native objects. + However, it provides a concept called an + <firstterm>object path</firstterm>. The idea of an object path is that + higher-level bindings can name native object instances, and allow remote applications + to refer to them. + </para> + <para> + The object path + looks like a filesystem path, for example an object could be + named <literal>/org/kde/kspread/sheets/3/cells/4/5</literal>. + Human-readable paths are nice, but you are free to create an + object named <literal>/com/mycompany/c5yo817y0c1y1c5b</literal> + if it makes sense for your application. + </para> + <para> + Namespacing object paths is smart, by starting them with the components + of a domain name you own (e.g. <literal>/org/kde</literal>). This + keeps different code modules in the same process from stepping + on one another's toes. + </para> + </sect2> + + <sect2 id="members"> + <title>Methods and Signals</title> + + <para> + Each object has <firstterm>members</firstterm>; the two kinds of member + are <firstterm>methods</firstterm> and + <firstterm>signals</firstterm>. Methods are operations that can be + invoked on an object, with optional input (aka arguments or "in + parameters") and output (aka return values or "out parameters"). + Signals are broadcasts from the object to any interested observers + of the object; signals may contain a data payload. + </para> + + <para> + Both methods and signals are referred to by name, such as + "Frobate" or "OnClicked". + </para> + + </sect2> + + <sect2 id="interfaces"> + <title>Interfaces</title> + <para> + Each object supports one or more <firstterm>interfaces</firstterm>. + Think of an interface as a named group of methods and signals, + just as it is in GLib or Qt or Java. Interfaces define the + <emphasis>type</emphasis> of an object instance. + </para> + <para> + DBus identifies interfaces with a simple namespaced string, + something like <literal>org.freedesktop.Introspectable</literal>. + Most bindings will map these interface names directly to + the appropriate programming language construct, for example + to Java interfaces or C++ pure virtual classes. + </para> + </sect2> + + <sect2 id="proxies"> + <title>Proxies</title> + <para> + A <firstterm>proxy object</firstterm> is a convenient native object created to + represent a remote object in another process. The low-level DBus API involves manually creating + a method call message, sending it, then manually receiving and processing + the method reply message. Higher-level bindings provide proxies as an alternative. + Proxies look like a normal native object; but when you invoke a method on the proxy + object, the binding converts it into a DBus method call message, waits for the reply + message, unpacks the return value, and returns it from the native method.. + </para> + <para> + In pseudocode, programming without proxies might look like this: + <programlisting> + Message message = new Message("/remote/object/path", "MethodName", arg1, arg2); + Connection connection = getBusConnection(); + connection.send(message); + Message reply = connection.waitForReply(message); + if (reply.isError()) { + + } else { + Object returnValue = reply.getReturnValue(); + } + </programlisting> + </para> + <para> + Programming with proxies might look like this: + <programlisting> + Proxy proxy = new Proxy(getBusConnection(), "/remote/object/path"); + Object returnValue = proxy.MethodName(arg1, arg2); + </programlisting> + </para> + </sect2> + + <sect2 id="bus-names"> + <title>Bus Names</title> + + <para> + When each application connects to the bus daemon, the daemon immediately + assigns it a name, called the <firstterm>unique connection name</firstterm>. + A unique name begins with a ':' (colon) character. These names are never + reused during the lifetime of the bus daemon - that is, you know + a given name will always refer to the same application. + An example of a unique name might be + <literal>:34-907</literal>. The numbers after the colon have + no meaning other than their uniqueness. + </para> + + <para> + When a name is mapped + to a particular application's connection, that application is said to + <firstterm>own</firstterm> that name. + </para> + + <para> + Applications may ask to own additional <firstterm>well-known + names</firstterm>. For example, you could write a specification to + define a name called <literal>com.mycompany.TextEditor</literal>. + Your definition could specify that to own this name, an application + should have an object at the path + <literal>/com/mycompany/TextFileManager</literal> supporting the + interface <literal>org.freedesktop.FileHandler</literal>. + </para> + + <para> + Applications could then send messages to this bus name, + object, and interface to execute method calls. + </para> + + <para> + You could think of the unique names as IP addresses, and the + well-known names as domain names. So + <literal>com.mycompany.TextEditor</literal> might map to something like + <literal>:34-907</literal> just as <literal>mycompany.com</literal> maps + to something like <literal>192.168.0.5</literal>. + </para> + + <para> + Names have a second important use, other than routing messages. They + are used to track lifecycle. When an application exits (or crashes), its + connection to the message bus will be closed by the operating system + kernel. The message bus then sends out notification messages telling + remaining applications that the application's names have lost their + owner. By tracking these notifications, your application can reliably + monitor the lifetime of other applications. + </para> + + <para> + Bus names can also be used to coordinate single-instance applications. + If you want to be sure only one + <literal>com.mycompany.TextEditor</literal> application is running for + example, have the text editor application exit if the bus name already + has an owner. + </para> + + </sect2> + + <sect2 id="addresses"> + <title>Addresses</title> + + <para> + Applications using D-Bus are either servers or clients. A server + listens for incoming connections; a client connects to a server. Once + the connection is established, it is a symmetric flow of messages; the + client-server distinction only matters when setting up the + connection. + </para> + + <para> + If you're using the bus daemon, as you probably are, your application + will be a client of the bus daemon. That is, the bus daemon listens + for connections and your application initiates a connection to the bus + daemon. + </para> + + <para> + A D-Bus <firstterm>address</firstterm> specifies where a server will + listen, and where a client will connect. For example, the address + <literal>unix:path=/tmp/abcdef</literal> specifies that the server will + listen on a UNIX domain socket at the path + <literal>/tmp/abcdef</literal> and the client will connect to that + socket. An address can also specify TCP/IP sockets, or any other + transport defined in future iterations of the D-Bus specification. + </para> + + <para> + When using D-Bus with a message bus daemon, + libdbus automatically discovers the address of the per-session bus + daemon by reading an environment variable. It discovers the + systemwide bus daemon by checking a well-known UNIX domain socket path + (though you can override this address with an environment variable). + </para> + + <para> + If you're using D-Bus without a bus daemon, it's up to you to + define which application will be the server and which will be + the client, and specify a mechanism for them to agree on + the server's address. This is an unusual case. + </para> + + </sect2> + + <sect2 id="bigpicture"> + <title>Big Conceptual Picture</title> + + <para> + Pulling all these concepts together, to specify a particular + method call on a particular object instance, a number of + nested components have to be named: + <programlisting> + Address -> [Bus Name] -> Path -> Interface -> Method + </programlisting> + The bus name is in brackets to indicate that it's optional -- you only + provide a name to route the method call to the right application + when using the bus daemon. If you have a direct connection to another + application, bus names aren't used; there's no bus daemon. + </para> + + <para> + The interface is also optional, primarily for historical + reasons; DCOP does not require specifying the interface, + instead simply forbidding duplicate method names + on the same object instance. D-Bus will thus let you + omit the interface, but if your method name is ambiguous + it is undefined which method will be invoked. + </para> + + </sect2> + + <sect2 id="messages"> + <title>Messages - Behind the Scenes</title> + <para> + D-Bus works by sending messages between processes. If you're using + a sufficiently high-level binding, you may never work with messages directly. + </para> + <para> + There are 4 message types: + <itemizedlist> + <listitem> + <para> + Method call messages ask to invoke a method + on an object. + </para> + </listitem> + <listitem> + <para> + Method return messages return the results + of invoking a method. + </para> + </listitem> + <listitem> + <para> + Error messages return an exception caused by + invoking a method. + </para> + </listitem> + <listitem> + <para> + Signal messages are notifications that a given signal + has been emitted (that an event has occurred). + You could also think of these as "event" messages. + </para> + </listitem> + </itemizedlist> + </para> + <para> + A method call maps very simply to messages: you send a method call + message, and receive either a method return message or an error message + in reply. + </para> + <para> + Each message has a <firstterm>header</firstterm>, including <firstterm>fields</firstterm>, + and a <firstterm>body</firstterm>, including <firstterm>arguments</firstterm>. You can think + of the header as the routing information for the message, and the body as the payload. + Header fields might include the sender bus name, destination bus name, method or signal name, + and so forth. One of the header fields is a <firstterm>type signature</firstterm> describing the + values found in the body. For example, the letter "i" means "32-bit integer" so the signature + "ii" means the payload has two 32-bit integers. + </para> + </sect2> + + <sect2 id="callprocedure"> + <title>Calling a Method - Behind the Scenes</title> + + <para> + A method call in DBus consists of two messages; a method call message sent from process A to process B, + and a matching method reply message sent from process B to process A. Both the call and the reply messages + are routed through the bus daemon. The caller includes a different serial number in each call message, and the + reply message includes this number to allow the caller to match replies to calls. + </para> + + <para> + The call message will contain any arguments to the method. + The reply message may indicate an error, or may contain data returned by the method. + </para> + + <para> + A method invocation in DBus happens as follows: + <itemizedlist> + <listitem> + <para> + The language binding may provide a proxy, such that invoking a method on + an in-process object invokes a method on a remote object in another process. If so, the + application calls a method on the proxy, and the proxy + constructs a method call message to send to the remote process. + </para> + </listitem> + <listitem> + <para> + For more low-level APIs, the application may construct a method call message itself, without + using a proxy. + </para> + </listitem> + <listitem> + <para> + In either case, the method call message contains: a bus name belonging to the remote process; the name of the method; + the arguments to the method; an object path inside the remote process; and optionally the name of the + interface that specifies the method. + </para> + </listitem> + <listitem> + <para> + The method call message is sent to the bus daemon. + </para> + </listitem> + <listitem> + <para> + The bus daemon looks at the destination bus name. If a process owns that name, + the bus daemon forwards the method call to that process. Otherwise, the bus daemon + creates an error message and sends it back as the reply to the method call message. + </para> + </listitem> + <listitem> + <para> + The receiving process unpacks the method call message. In a simple low-level API situation, it + may immediately run the method and send a method reply message to the bus daemon. + When using a high-level binding API, the binding might examine the object path, interface, + and method name, and convert the method call message into an invocation of a method on + a native object (GObject, java.lang.Object, QObject, etc.), then convert the return + value from the native method into a method reply message. + </para> + </listitem> + <listitem> + <para> + The bus daemon receives the method reply message and sends it to the process that + made the method call. + </para> + </listitem> + <listitem> + <para> + The process that made the method call looks at the method reply and makes use of any + return values included in the reply. The reply may also indicate that an error occurred. + When using a binding, the method reply message may be converted into the return value of + of a proxy method, or into an exception. + </para> + </listitem> + </itemizedlist> + </para> + + <para> + The bus daemon never reorders messages. That is, if you send two method call messages to the same recipient, + they will be received in the order they were sent. The recipient is not required to reply to the calls + in order, however; for example, it may process each method call in a separate thread, and return reply messages + in an undefined order depending on when the threads complete. Method calls have a unique serial + number used by the method caller to match reply messages to call messages. + </para> + + </sect2> + + <sect2 id="signalprocedure"> + <title>Emitting a Signal - Behind the Scenes</title> + + <para> + A signal in DBus consists of a single message, sent by one process to any number of other processes. + That is, a signal is a unidirectional broadcast. The signal may contain arguments (a data payload), but + because it is a broadcast, it never has a "return value." Contrast this with a method call + (see <xref linkend="callprocedure"/>) where the method call message has a matching method reply message. + </para> + + <para> + The emitter (aka sender) of a signal has no knowledge of the signal recipients. Recipients register + with the bus daemon to receive signals based on "match rules" - these rules would typically include the sender and + the signal name. The bus daemon sends each signal only to recipients who have expressed interest in that + signal. + </para> + + <para> + A signal in DBus happens as follows: + <itemizedlist> + <listitem> + <para> + A signal message is created and sent to the bus daemon. When using the low-level API this may be + done manually, with certain bindings it may be done for you by the binding when a native object + emits a native signal or event. + </para> + </listitem> + <listitem> + <para> + The signal message contains the name of the interface that specifies the signal; + the name of the signal; the bus name of the process sending the signal; and + any arguments + </para> + </listitem> + <listitem> + <para> + Any process on the message bus can register "match rules" indicating which signals it + is interested in. The bus has a list of registered match rules. + </para> + </listitem> + <listitem> + <para> + The bus daemon examines the signal and determines which processes are interested in it. + It sends the signal message to these processes. + </para> + </listitem> + <listitem> + <para> + Each process receiving the signal decides what to do with it; if using a binding, + the binding may choose to emit a native signal on a proxy object. If using the + low-level API, the process may just look at the signal sender and name and decide + what to do based on that. + </para> + </listitem> + </itemizedlist> + </para> + + </sect2> + + <sect2 id="introspection"> + <title>Introspection</title> + + <para> + D-Bus objects may support the interface <literal>org.freedesktop.DBus.Introspectable</literal>. + This interface has one method <literal>Introspect</literal> which takes no arguments and returns + an XML string. The XML string describes the interfaces, methods, and signals of the object. + See the D-Bus specification for more details on this introspection format. + </para> + + </sect2> + + </sect1> + + <sect1 id="glib-client"> + <title>GLib API: Using Remote Objects</title> + + <para> + The GLib binding is defined in the header file + <literal><dbus/dbus-glib.h></literal>. + </para> + + <sect2 id="glib-typemappings"> + <title>D-Bus - GLib type mappings</title> + <para> + The heart of the GLib bindings for D-Bus is the mapping it + provides between D-Bus "type signatures" and GLib types + (<literal>GType</literal>). The D-Bus type system is composed of + a number of "basic" types, along with several "container" types. + </para> + <sect3 id="glib-basic-typemappings"> + <title>Basic type mappings</title> + <para> + Below is a list of the basic types, along with their associated + mapping to a <literal>GType</literal>. + <informaltable> + <tgroup cols="4"> + <thead> + <row> + <entry>D-Bus basic type</entry> + <entry>GType</entry> + <entry>Free function</entry> + <entry>Notes</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>BYTE</literal></entry> + <entry><literal>G_TYPE_UCHAR</literal></entry> + <entry></entry> + <entry></entry> + </row><row> + <entry><literal>BOOLEAN</literal></entry> + <entry><literal>G_TYPE_BOOLEAN</literal></entry> + <entry></entry> + <entry></entry> + </row><row> + <entry><literal>INT16</literal></entry> + <entry><literal>G_TYPE_INT</literal></entry> + <entry></entry> + <entry>Will be changed to a <literal>G_TYPE_INT16</literal> once GLib has it</entry> + </row><row> + <entry><literal>UINT16</literal></entry> + <entry><literal>G_TYPE_UINT</literal></entry> + <entry></entry> + <entry>Will be changed to a <literal>G_TYPE_UINT16</literal> once GLib has it</entry> + </row><row> + <entry><literal>INT32</literal></entry> + <entry><literal>G_TYPE_INT</literal></entry> + <entry></entry> + <entry>Will be changed to a <literal>G_TYPE_INT32</literal> once GLib has it</entry> + </row><row> + <entry><literal>UINT32</literal></entry> + <entry><literal>G_TYPE_UINT</literal></entry> + <entry></entry> + <entry>Will be changed to a <literal>G_TYPE_UINT32</literal> once GLib has it</entry> + </row><row> + <entry><literal>INT64</literal></entry> + <entry><literal>G_TYPE_GINT64</literal></entry> + <entry></entry> + <entry></entry> + </row><row> + <entry><literal>UINT64</literal></entry> + <entry><literal>G_TYPE_GUINT64</literal></entry> + <entry></entry> + <entry></entry> + </row><row> + <entry><literal>DOUBLE</literal></entry> + <entry><literal>G_TYPE_DOUBLE</literal></entry> + <entry></entry> + <entry></entry> + </row><row> + <entry><literal>STRING</literal></entry> + <entry><literal>G_TYPE_STRING</literal></entry> + <entry><literal>g_free</literal></entry> + <entry></entry> + </row><row> + <entry><literal>OBJECT_PATH</literal></entry> + <entry><literal>DBUS_TYPE_G_PROXY</literal></entry> + <entry><literal>g_object_unref</literal></entry> + <entry>The returned proxy does not have an interface set; use <literal>dbus_g_proxy_set_interface</literal> to invoke methods</entry> + </row> + </tbody> + </tgroup> + </informaltable> + As you can see, the basic mapping is fairly straightforward. + </para> + </sect3> + <sect3 id="glib-container-typemappings"> + <title>Container type mappings</title> + <para> + The D-Bus type system also has a number of "container" + types, such as <literal>DBUS_TYPE_ARRAY</literal> and + <literal>DBUS_TYPE_STRUCT</literal>. The D-Bus type system + is fully recursive, so one can for example have an array of + array of strings (i.e. type signature + <literal>aas</literal>). + </para> + <para> + However, not all of these types are in common use; for + example, at the time of this writing the author knows of no + one using <literal>DBUS_TYPE_STRUCT</literal>, or a + <literal>DBUS_TYPE_ARRAY</literal> containing any non-basic + type. The approach the GLib bindings take is pragmatic; try + to map the most common types in the most obvious way, and + let using less common and more complex types be less + "natural". + </para> + <para> + First, D-Bus type signatures which have an "obvious" + corresponding built-in GLib type are mapped using that type: + <informaltable> + <tgroup cols="6"> + <thead> + <row> + <entry>D-Bus type signature</entry> + <entry>Description</entry> + <entry>GType</entry> + <entry>C typedef</entry> + <entry>Free function</entry> + <entry>Notes</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>as</literal></entry> + <entry>Array of strings</entry> + <entry><literal>G_TYPE_STRV</literal></entry> + <entry><literal>char **</literal></entry> + <entry><literal>g_strfreev</literal></entry> + <entry></entry> + </row><row> + <entry><literal>v</literal></entry> + <entry>Generic value container</entry> + <entry><literal>G_TYPE_VALUE</literal></entry> + <entry><literal>GValue *</literal></entry> + <entry><literal>g_value_unset</literal></entry> + <entry>The calling conventions for values expect that method callers have allocated return values; see below.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + The next most common recursive type signatures are arrays of + basic values. The most obvious mapping for arrays of basic + types is a <literal>GArray</literal>. Now, GLib does not + provide a builtin <literal>GType</literal> for + <literal>GArray</literal>. However, we actually need more than + that - we need a "parameterized" type which includes the + contained type. Why we need this we will see below. + </para> + <para> + The approach taken is to create these types in the D-Bus GLib + bindings; however, there is nothing D-Bus specific about them. + In the future, we hope to include such "fundamental" types in GLib + itself. + <informaltable> + <tgroup cols="6"> + <thead> + <row> + <entry>D-Bus type signature</entry> + <entry>Description</entry> + <entry>GType</entry> + <entry>C typedef</entry> + <entry>Free function</entry> + <entry>Notes</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>ay</literal></entry> + <entry>Array of bytes</entry> + <entry><literal>DBUS_TYPE_G_BYTE_ARRAY</literal></entry> + <entry><literal>GArray *</literal></entry> + <entry>g_array_free</entry> + <entry></entry> + </row> + <row> + <entry><literal>au</literal></entry> + <entry>Array of uint</entry> + <entry><literal>DBUS_TYPE_G_UINT_ARRAY</literal></entry> + <entry><literal>GArray *</literal></entry> + <entry>g_array_free</entry> + <entry></entry> + </row> + <row> + <entry><literal>ai</literal></entry> + <entry>Array of int</entry> + <entry><literal>DBUS_TYPE_G_INT_ARRAY</literal></entry> + <entry><literal>GArray *</literal></entry> + <entry>g_array_free</entry> + <entry></entry> + </row> + <row> + <entry><literal>ax</literal></entry> + <entry>Array of int64</entry> + <entry><literal>DBUS_TYPE_G_INT64_ARRAY</literal></entry> + <entry><literal>GArray *</literal></entry> + <entry>g_array_free</entry> + <entry></entry> + </row> + <row> + <entry><literal>at</literal></entry> + <entry>Array of uint64</entry> + <entry><literal>DBUS_TYPE_G_UINT64_ARRAY</literal></entry> + <entry><literal>GArray *</literal></entry> + <entry>g_array_free</entry> + <entry></entry> + </row> + <row> + <entry><literal>ad</literal></entry> + <entry>Array of double</entry> + <entry><literal>DBUS_TYPE_G_DOUBLE_ARRAY</literal></entry> + <entry><literal>GArray *</literal></entry> + <entry>g_array_free</entry> + <entry></entry> + </row> + <row> + <entry><literal>ab</literal></entry> + <entry>Array of boolean</entry> + <entry><literal>DBUS_TYPE_G_BOOLEAN_ARRAY</literal></entry> + <entry><literal>GArray *</literal></entry> + <entry>g_array_free</entry> + <entry></entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + D-Bus also includes a special type DBUS_TYPE_DICT_ENTRY which + is only valid in arrays. It's intended to be mapped to a "dictionary" + type by bindings. The obvious GLib mapping here is GHashTable. Again, + however, there is no builtin <literal>GType</literal> for a GHashTable. + Moreover, just like for arrays, we need a parameterized type so that + the bindings can communiate which types are contained in the hash table. + </para> + <para> + At present, only strings are supported. Work is in progress to + include more types. + <informaltable> + <tgroup cols="6"> + <thead> + <row> + <entry>D-Bus type signature</entry> + <entry>Description</entry> + <entry>GType</entry> + <entry>C typedef</entry> + <entry>Free function</entry> + <entry>Notes</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>a{ss}</literal></entry> + <entry>Dictionary mapping strings to strings</entry> + <entry><literal>DBUS_TYPE_G_STRING_STRING_HASHTABLE</literal></entry> + <entry><literal>GHashTable *</literal></entry> + <entry>g_hash_table_destroy</entry> + <entry></entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + </sect3> + <sect3 id="glib-generic-typemappings"> + <title>Arbitrarily recursive type mappings</title> + <para> + Finally, it is possible users will want to write or invoke D-Bus + methods which have arbitrarily complex type signatures not + directly supported by these bindings. For this case, we have a + <literal>DBusGValue</literal> which acts as a kind of special + variant value which may be iterated over manually. The + <literal>GType</literal> associated is + <literal>DBUS_TYPE_G_VALUE</literal>. + </para> + <para> + TODO insert usage of <literal>DBUS_TYPE_G_VALUE</literal> here. + </para> + </sect3> + </sect2> + <sect2 id="sample-program-1"> + <title>A sample program</title> + <para>Here is a D-Bus program using the GLib bindings. +<programlisting> +int +main (int argc, char **argv) +{ + DBusGConnection *connection; + GError *error; + DBusGProxy *proxy; + char **name_list; + char **name_list_ptr; + + g_type_init (); + + error = NULL; + connection = dbus_g_bus_get (DBUS_BUS_SESSION, + &error); + if (connection == NULL) + { + g_printerr ("Failed to open connection to bus: %s\n", + error->message); + g_error_free (error); + exit (1); + } + + /* Create a proxy object for the "bus driver" (name "org.freedesktop.DBus") */ + + proxy = dbus_g_proxy_new_for_name (connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + + /* Call ListNames method, wait for reply */ + error = NULL; + if (!dbus_g_proxy_call (proxy, "ListNames", &error, G_TYPE_INVALID, + G_TYPE_STRV, &name_list, G_TYPE_INVALID)) + { + /* Just do demonstrate remote exceptions versus regular GError */ + if (error->domain == DBUS_GERROR && error->code == DBUS_GERROR_REMOTE_EXCEPTION) + g_printerr ("Caught remote method exception %s: %s", + dbus_g_error_get_name (error), + error->message); + else + g_printerr ("Error: %s\n", error->message); + g_error_free (error); + exit (1); + } + + /* Print the results */ + + g_print ("Names on the message bus:\n"); + + for (name_list_ptr = name_list; *name_list_ptr; name_list_ptr++) + { + g_print (" %s\n", *name_list_ptr); + } + g_strfreev (name_list); + + g_object_unref (proxy); + + return 0; +} +</programlisting> + </para> + </sect2> + <sect2 id="glib-program-setup"> + <title>Program initalization</title> + <para> + A connection to the bus is acquired using + <literal>dbus_g_bus_get</literal>. Next, a proxy + is created for the object "/org/freedesktop/DBus" with + interface <literal>org.freedesktop.DBus</literal> + on the service <literal>org.freedesktop.DBus</literal>. + This is a proxy for the message bus itself. + </para> + </sect2> + <sect2 id="glib-method-invocation"> + <title>Understanding method invocation</title> + <para> + You have a number of choices for method invocation. First, as + used above, <literal>dbus_g_proxy_call</literal> sends a + method call to the remote object, and blocks until a reply is + recieved. The outgoing arguments are specified in the varargs + array, terminated with <literal>G_TYPE_INVALID</literal>. + Next, pointers to return values are specified, followed again + by <literal>G_TYPE_INVALID</literal>. + </para> + <para> + To invoke a method asynchronously, use + <literal>dbus_g_proxy_begin_call</literal>. This returns a + <literal>DBusGPendingCall</literal> object; you may then set a + notification function using + <literal>dbus_g_pending_call_set_notify</literal>. + </para> + </sect2> + <sect2 id="glib-signal-connection"> + <title>Connecting to object signals</title> + <para> + You may connect to signals using + <literal>dbus_g_proxy_add_signal</literal> and + <literal>dbus_g_proxy_connect_signal</literal>. You must + invoke <literal>dbus_g_proxy_add_signal</literal> to specify + the signature of your signal handlers; you may then invoke + <literal>dbus_g_proxy_connect_signal</literal> multiple times. + </para> + <para> + Note that it will often be the case that there is no builtin + marshaller for the type signature of a remote signal. In that + case, you must generate a marshaller yourself by using + <application>glib-genmarshal</application>, and then register + it using <literal>dbus_g_object_register_marshaller</literal>. + </para> + </sect2> + <sect2 id="glib-error-handling"> + <title>Error handling and remote exceptions</title> + <para> + All of the GLib binding methods such as + <literal>dbus_g_proxy_end_call</literal> return a + <literal>GError</literal>. This <literal>GError</literal> can + represent two different things: + <itemizedlist> + <listitem> + <para> + An internal D-Bus error, such as an out-of-memory + condition, an I/O error, or a network timeout. Errors + generated by the D-Bus library itself have the domain + <literal>DBUS_GERROR</literal>, and a corresponding code + such as <literal>DBUS_GERROR_NO_MEMORY</literal>. It will + not be typical for applications to handle these errors + specifically. + </para> + </listitem> + <listitem> + <para> + A remote D-Bus exception, thrown by the peer, bus, or + service. D-Bus remote exceptions have both a textual + "name" and a "message". The GLib bindings store this + information in the <literal>GError</literal>, but some + special rules apply. + </para> + <para> + The set error will have the domain + <literal>DBUS_GERROR</literal> as above, and will also + have the code + <literal>DBUS_GERROR_REMOTE_EXCEPTION</literal>. In order + to access the remote exception name, you must use a + special accessor, such as + <literal>dbus_g_error_has_name</literal> or + <literal>dbus_g_error_get_name</literal>. The remote + exception detailed message is accessible via the regular + GError <literal>message</literal> member. + </para> + </listitem> + </itemizedlist> + </para> + </sect2> + <sect2 id="glib-more-examples"> + <title>More examples of method invocation</title> + <sect3 id="glib-sending-stuff"> + <title>Sending an integer and string, receiving an array of bytes</title> + <para> +<programlisting> + GArray *arr; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "Foobar", &error, + G_TYPE_INT, 42, G_TYPE_STRING, "hello", + G_TYPE_INVALID, + DBUS_TYPE_G_UCHAR_ARRAY, &arr, G_TYPE_INVALID)) + { + /* Handle error */ + } + g_assert (arr != NULL); + printf ("got back %u values", arr->len); +</programlisting> + </para> + </sect3> + <sect3 id="glib-sending-hash"> + <title>Sending a GHashTable</title> + <para> +<programlisting> + GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal); + guint32 ret; + + g_hash_table_insert (hash, "foo", "bar"); + g_hash_table_insert (hash, "baz", "whee"); + + error = NULL; + if (!dbus_g_proxy_call (proxy, "HashSize", &error, + DBUS_TYPE_G_STRING_STRING_HASH, hash, G_TYPE_INVALID, + G_TYPE_UINT, &ret, G_TYPE_INVALID)) + { + /* Handle error */ + } + g_assert (ret == 2); + g_hash_table_destroy (hash); +</programlisting> + </para> + </sect3> + <sect3 id="glib-receiving-bool-int"> + <title>Receiving a boolean and a string</title> + <para> +<programlisting> + gboolean boolret; + char *strret; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "GetStuff", &error, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, &boolret, + G_TYPE_STRING, &strret, + G_TYPE_INVALID)) + { + /* Handle error */ + } + printf ("%s %s", boolret ? "TRUE" : "FALSE", strret); + g_free (strret); +</programlisting> + </para> + </sect3> + <sect3 id="glib-sending-str-arrays"> + <title>Sending two arrays of strings</title> + <para> +<programlisting> + /* NULL terminate */ + char *strs_static[] = {"foo", "bar", "baz", NULL}; + /* Take pointer to array; cannot pass array directly */ + char **strs_static_p = strs_static; + char **strs_dynamic; + + strs_dynamic = g_new (char *, 4); + strs_dynamic[0] = g_strdup ("hello"); + strs_dynamic[1] = g_strdup ("world"); + strs_dynamic[2] = g_strdup ("!"); + /* NULL terminate */ + strs_dynamic[3] = NULL; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "TwoStrArrays", &error, + G_TYPE_STRV, strs_static_p, + G_TYPE_STRV, strs_dynamic, + G_TYPE_INVALID, + G_TYPE_INVALID)) + { + /* Handle error */ + } + g_strfreev (strs_dynamic); +</programlisting> + </para> + </sect3> + <sect3 id="glib-getting-str-array"> + <title>Sending a boolean, receiving an array of strings</title> + <para> +<programlisting> + char **strs; + char **strs_p; + gboolean blah; + + error = NULL; + blah = TRUE; + if (!dbus_g_proxy_call (proxy, "GetStrs", &error, + G_TYPE_BOOLEAN, blah, + G_TYPE_INVALID, + G_TYPE_STRV, &strs, + G_TYPE_INVALID)) + { + /* Handle error */ + } + for (strs_p = strs; *strs_p; strs_p++) + printf ("got string: \"%s\"", *strs_p); + g_strfreev (strs); +</programlisting> + </para> + </sect3> + <sect3 id="glib-sending-variant"> + <title>Sending a variant</title> + <para> +<programlisting> + GValue val = {0, }; + + g_value_init (&val, G_TYPE_STRING); + g_value_set_string (&val, "hello world"); + + error = NULL; + if (!dbus_g_proxy_call (proxy, "SendVariant", &error, + G_TYPE_VALUE, &val, G_TYPE_INVALID, + G_TYPE_INVALID)) + { + /* Handle error */ + } + g_assert (ret == 2); + g_value_unset (&val); +</programlisting> + </para> + </sect3> + <sect3 id="glib-receiving-variant"> + <title>Receiving a variant</title> + <para> +<programlisting> + GValue val = {0, }; + + error = NULL; + if (!dbus_g_proxy_call (proxy, "GetVariant", &error, G_TYPE_INVALID, + G_TYPE_VALUE, &val, G_TYPE_INVALID)) + { + /* Handle error */ + } + if (G_VALUE_TYPE (&val) == G_TYPE_STRING) + printf ("%s\n", g_value_get_string (&val)); + else if (G_VALUE_TYPE (&val) == G_TYPE_INT) + printf ("%d\n", g_value_get_int (&val)); + else + ... + g_value_unset (&val); +</programlisting> + </para> + </sect3> + </sect2> + + <sect2 id="glib-generated-bindings"> + <title>Generated Bindings</title> + <para> + By using the Introspection XML files, convenient client-side bindings + can be automatically created to ease the use of a remote DBus object. + </para> + <para> + Here is a sample XML file which describes an object that exposes + one method, named <literal>ManyArgs</literal>. + <programlisting> +<?xml version="1.0" encoding="UTF-8" ?> +<node name="/com/example/MyObject"> + <interface name="com.example.MyObject"> + <method name="ManyArgs"> + <arg type="u" name="x" direction="in" /> + <arg type="s" name="str" direction="in" /> + <arg type="d" name="trouble" direction="in" /> + <arg type="d" name="d_ret" direction="out" /> + <arg type="s" name="str_ret" direction="out" /> + </method> + </interface> +</node> +</programlisting> + </para> + <para> + Run <literal>dbus-binding-tool --mode=glib-client + <replaceable>FILENAME</replaceable> > + <replaceable>HEADER_NAME</replaceable></literal> to generate the header + file. For example: <command>dbus-binding-tool --mode=glib-client + my-object.xml > my-object-bindings.h</command>. This will generate + inline functions with the following prototypes: + <programlisting> +/* This is a blocking call */ +gboolean +com_example_MyObject_many_args (DBusGProxy *proxy, const guint IN_x, + const char * IN_str, const gdouble IN_trouble, + gdouble* OUT_d_ret, char ** OUT_str_ret, + GError **error); + +/* This is a non-blocking call */ +DBusGProxyCall* +com_example_MyObject_many_args_async (DBusGProxy *proxy, const guint IN_x, + const char * IN_str, const gdouble IN_trouble, + com_example_MyObject_many_args_reply callback, + gpointer userdata); + +/* This is the typedef for the non-blocking callback */ +typedef void +(*com_example_MyObject_many_args_reply) +(DBusGProxy *proxy, gdouble OUT_d_ret, char * OUT_str_ret, + GError *error, gpointer userdata); +</programlisting> + The first argument in all functions is a <literal>DBusGProxy + *</literal>, which you should create with the usual + <literal>dbus_g_proxy_new_*</literal> functions. Following that are the + "in" arguments, and then either the "out" arguments and a + <literal>GError *</literal> for the synchronous (blocking) function, or + callback and user data arguments for the asynchronous (non-blocking) + function. The callback in the asynchronous function passes the + <literal>DBusGProxy *</literal>, the returned "out" arguments, an + <literal>GError *</literal> which is set if there was an error otherwise + <literal>NULL</literal>, and the user data. + </para> + <para> + As with the server-side bindings support (see <xref + linkend="glib-server"/>), the exact behaviour of the client-side + bindings can be manipulated using "annotations". Currently the only + annotation used by the client bindings is + <literal>org.freedesktop.DBus.GLib.NoReply</literal>, which sets the + flag indicating that the client isn't expecting a reply to the method + call, so a reply shouldn't be sent. This is often used to speed up + rapid method calls where there are no "out" arguments, and not knowing + if the method succeeded is an acceptable compromise to half the traffic + on the bus. + </para> + </sect2> + </sect1> + + <sect1 id="glib-server"> + <title>GLib API: Implementing Objects</title> + <para> + At the moment, to expose a GObject via D-Bus, you must + write XML by hand which describes the methods exported + by the object. In the future, this manual step will + be obviated by the upcoming GLib introspection support. + </para> + <para> + Here is a sample XML file which describes an object that exposes + one method, named <literal>ManyArgs</literal>. +<programlisting> +<?xml version="1.0" encoding="UTF-8" ?> + +<node name="/com/example/MyObject"> + + <interface name="com.example.MyObject"> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object"/> + <method name="ManyArgs"> + <!-- This is optional, and in this case is redunundant --> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="my_object_many_args"/> + <arg type="u" name="x" direction="in" /> + <arg type="s" name="str" direction="in" /> + <arg type="d" name="trouble" direction="in" /> + <arg type="d" name="d_ret" direction="out" /> + <arg type="s" name="str_ret" direction="out" /> + </method> + </interface> +</node> +</programlisting> + </para> + <para> + This XML is in the same format as the D-Bus introspection XML + format. Except we must include an "annotation" which give the C + symbols corresponding to the object implementation prefix + (<literal>my_object</literal>). In addition, if particular + methods symbol names deviate from C convention + (i.e. <literal>ManyArgs</literal> -> + <literal>many_args</literal>), you may specify an annotation + giving the C symbol. + </para> + <para> + Once you have written this XML, run <literal>dbus-binding-tool --mode=glib-server <replaceable>FILENAME</replaceable> > <replaceable>HEADER_NAME</replaceable>.</literal> to + generate a header file. For example: <command>dbus-binding-tool --mode=glib-server my-object.xml > my-object-glue.h</command>. + </para> + <para> + Next, include the generated header in your program, and invoke + <literal>dbus_g_object_class_install_info</literal> in the class + initializer, passing the object class and "object info" included in the + header. For example: + <programlisting> + dbus_g_object_type_install_info (COM_FOO_TYPE_MY_OBJECT, &com_foo_my_object_info); + </programlisting> + This should be done exactly once per object class. + </para> + <para> + To actually implement the method, just define a C function named e.g. + <literal>my_object_many_args</literal> in the same file as the info + header is included. At the moment, it is required that this function + conform to the following rules: + <itemizedlist> + <listitem> + <para> + The function must return a value of type <literal>gboolean</literal>; + <literal>TRUE</literal> on success, and <literal>FALSE</literal> + otherwise. + </para> + </listitem> + <listitem> + <para> + The first parameter is a pointer to an instance of the object. + </para> + </listitem> + <listitem> + <para> + Following the object instance pointer are the method + input values. + </para> + </listitem> + <listitem> + <para> + Following the input values are pointers to return values. + </para> + </listitem> + <listitem> + <para> + The final parameter must be a <literal>GError **</literal>. + If the function returns <literal>FALSE</literal> for an + error, the error parameter must be initalized with + <literal>g_set_error</literal>. + </para> + </listitem> + </itemizedlist> + </para> + <para> + Finally, you can export an object using <literal>dbus_g_connection_register_g_object</literal>. For example: + <programlisting> + dbus_g_connection_register_g_object (connection, + "/com/foo/MyObject", + obj); + </programlisting> + </para> + + <sect2 id="glib-annotations"> + <title>Server-side Annotations</title> + <para> + There are several annotations that are used when generating the + server-side bindings. The most common annotation is + <literal>org.freedesktop.DBus.GLib.CSymbol</literal> but there are other + annotations which are often useful. + <variablelist> + <varlistentry> + <term><literal>org.freedesktop.DBus.GLib.CSymbol</literal></term> + <listitem> + <para> + This annotation is used to specify the C symbol names for + the various types (interface, method, etc), if it differs from the + name DBus generates. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>org.freedesktop.DBus.GLib.Async</literal></term> + <listitem> + <para> + This annotation marks the method implementation as an + asynchronous function, which doesn't return a response straight + away but will send the response at some later point to complete + the call. This is used to implement non-blocking services where + method calls can take time. + </para> + <para> + When a method is asynchronous, the function prototype is + different. It is required that the function conform to the + following rules: + <itemizedlist> + <listitem> + <para> + The function must return a value of type <literal>gboolean</literal>; + <literal>TRUE</literal> on success, and <literal>FALSE</literal> + otherwise. TODO: the return value is currently ignored. + </para> + </listitem> + <listitem> + <para> + The first parameter is a pointer to an instance of the object. + </para> + </listitem> + <listitem> + <para> + Following the object instance pointer are the method + input values. + </para> + </listitem> + <listitem> + <para> + The final parameter must be a + <literal>DBusGMethodInvocation *</literal>. This is used + when sending the response message back to the client, by + calling <literal>dbus_g_method_return</literal> or + <literal>dbus_g_method_return_error</literal>. + </para> + </listitem> + </itemizedlist> + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>org.freedesktop.DBus.GLib.Const</literal></term> + <listitem> + <para>This attribute can only be applied to "out" + <literal><arg></literal> nodes, and specifies that the + parameter isn't being copied when returned. For example, this + turns a 's' argument from a <literal>char **</literal> to a + <literal>const char **</literal>, and results in the argument not + being freed by DBus after the message is sent. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term><literal>org.freedesktop.DBus.GLib.ReturnVal</literal></term> + <listitem> + <para> + This attribute can only be applied to "out" + <literal><arg></literal> nodes, and alters the expected + function signature. It currently can be set to two values: + <literal>""</literal> or <literal>"error"</literal>. The + argument marked with this attribute is not returned via a + pointer argument, but by the function's return value. If the + attribute's value is the empty string, the <literal>GError + *</literal> argument is also omitted so there is no standard way + to return an error value. This is very useful for interfacing + with existing code, as it is possible to match existing APIs. + If the attribute's value is <literal>"error"</literal>, then the + final argument is a <literal>GError *</literal> as usual. + </para> + <para> + Some examples to demonstrate the usage. This introspection XML: + <programlisting> +<method name="Increment"> + <arg type="u" name="x" /> + <arg type="u" direction="out" /> +</method> + </programlisting> + Expects the following function declaration: + <programlisting> +gboolean +my_object_increment (MyObject *obj, gint32 x, gint32 *ret, GError **error); + </programlisting> + </para> + <para> + This introspection XML: + <programlisting> +<method name="IncrementRetval"> + <arg type="u" name="x" /> + <arg type="u" direction="out" > + <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value=""/> + </arg> +</method> + </programlisting> + Expects the following function declaration: + <programlisting> +gint32 +my_object_increment_retval (MyObject *obj, gint32 x) + </programlisting> + </para> + <para> + This introspection XML: + <programlisting> +<method name="IncrementRetvalError"> + <arg type="u" name="x" /> + <arg type="u" direction="out" > + <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value="error"/> + </arg> +</method> + </programlisting> + Expects the following function declaration: + <programlisting> +gint32 +my_object_increment_retval_error (MyObject *obj, gint32 x, GError **error) + </programlisting> + </para> + </listitem> + </varlistentry> + </variablelist> + </para> + </sect2> + </sect1> + + <sect1 id="python-client"> + <title>Python API</title> + <para> + The Python API, dbus-python, is now documented separately in + <ulink url="http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html">the dbus-python tutorial</ulink> (also available in doc/tutorial.txt, + and doc/tutorial.html if built with python-docutils, in the dbus-python + source distribution). + </para> + </sect1> + + <sect1 id="qt-client"> + <title>Qt API: Using Remote Objects</title> + <para> + + The Qt bindings are not yet documented. + + </para> + </sect1> + + <sect1 id="qt-server"> + <title>Qt API: Implementing Objects</title> + <para> + The Qt bindings are not yet documented. + </para> + </sect1> +</article> diff --git a/doc/dcop-howto.txt b/doc/dcop-howto.txt new file mode 100644 index 00000000..dfd3bcf8 --- /dev/null +++ b/doc/dcop-howto.txt @@ -0,0 +1,559 @@ + DCOP: Desktop COmmunications Protocol + + Preston Brown <pbrown@kde.org> + October 14, 1999 + + Revised and extended by Matthias Ettrich <ettrich@kde.org> + Mar 29, 2000 + + Extended with DCOP Signals by Waldo Bastian <bastian@kde.org> + Feb 19, 2001 + + +Motivation and Background: +-------------------------- + +The motivation behind building a protocol like DCOP is simple. For +the past year, we have been attempting to enable interprocess +communication between KDE applications. KDE already has an extremely +simple IPC mechanism called KWMcom, which is (was!) used for communicating +between the panel and the window manager for instance. It is about as +simple as it gets, passing messages via X Atoms. For this reason it +is limited in the size and complexity of the data that can be passed +(X atoms must be small to remain efficient) and it also makes it so +that X is required. CORBA was thought to be a more effective IPC/RPC +solution. However, after a year of attempting to make heavy use of +CORBA in KDE, we have realized that it is a bit slow and memory +intensive for simple use. It also has no authentication available. + +What we really needed was an extremely simple protocol with basic +authorization, along the lines of MIT-MAGIC-COOKIE, as used by X. It +would not be able to do NEARLY what CORBA was able to do, but for the +simple tasks required it would be sufficient. Some examples of such +tasks might be an application sending a message to the panel saying, +"I have started, stop displaying the 'application starting' wait +state," or having a new application that starts query to see if any +other applications of the same name are running. If they are, simply +call a function on the remote application to create a new window, +rather than starting a new process. + +Implementation: +--------------- + +DCOP is a simple IPC/RPC mechanism built to operate over sockets. +Either unix domain sockets or tcp/ip sockets are supported. DCOP is +built on top of the Inter Client Exchange (ICE) protocol, which comes +standard as a part of X11R6 and later. It also depends on Qt, but +beyond that it does not require any other libraries. Because of this, +it is extremely lightweight, enabling it to be linked into all KDE +applications with low overhead. + +Model: +------ + +The model is simple. Each application using DCOP is a client. They +communicate to each other through a DCOP server, which functions like +a traffic director, dispatching messages/calls to the proper +destinations. All clients are peers of each other. + +Two types of actions are possible with DCOP: "send and forget" +messages, which do not block, and "calls," which block waiting for +some data to be returned. + +Any data that will be sent is serialized (marshalled, for you CORBA +types) using the built-in QDataStream operators available in all of +the Qt classes. This is fast and easy. In fact it's so little work +that you can easily write the marshalling code by hand. In addition, +there's a simple IDL-like compiler available (dcopidl and dcopidl2cpp) +that generates stubs and skeletons for you. Using the dcopidl compiler +has the additional benefit of type safety. + +This HOWTO describes the manual method first and covers the dcopidl +compiler later. + +Establishing the Connection: +---------------------------- + +KApplication has gained a method called "KApplication::dcopClient()" +which returns a pointer to a DCOPClient instance. The first time this +method is called, the client class will be created. DCOPClients have +unique identifiers attached to them which are based on what +KApplication::name() returns. In fact, if there is only a single +instance of the program running, the appId will be equal to +KApplication::name(). + +To actually enable DCOP communication to begin, you must use +DCOPClient::attach(). This will attempt to attach to the DCOP server. +If no server is found or there is any other type of error, attach() +will return false. KApplication will catch a dcop signal and display an +appropriate error message box in that case. + +After connecting with the server via DCOPClient::attach(), you need to +register this appId with the server so it knows about you. Otherwise, +you are communicating anonymously. Use the +DCOPClient::registerAs(const QCString &name) to do so. In the simple +case: + +/* + * returns the appId that is actually registered, which _may_ be + * different from what you passed + */ +appId = client->registerAs(kApp->name()); + +If you never retrieve the DCOPClient pointer from KApplication, the +object will not be created and thus there will be no memory overhead. + +You may also detach from the server by calling DCOPClient::detach(). +If you wish to attach again you will need to re-register as well. If +you only wish to change the ID under which you are registered, simply +call DCOPClient::registerAs() with the new name. + +KUniqueApplication automatically registers itself to DCOP. If you +are using KUniqueApplication you should not attach or register +yourself, this is already done. The appId is by definition +equal to kapp->name(). You can retrieve the registered DCOP client +by calling kapp->dcopClient(). + +Sending Data to a Remote Application: +------------------------------------- + +To actually communicate, you have one of two choices. You may either +call the "send" or the "call" method. Both methods require three +identification parameters: an application identifier, a remote object, +a remote function. Sending is asynchronous (i.e. it returns immediately) +and may or may not result in your own application being sent a message at +some point in the future. Then "send" requires one and "call" requires +two data parameters. + +The remote object must be specified as an object hierarchy. That is, +if the toplevel object is called "fooObject" and has the child +"barObject", you would reference this object as "fooObject/barObject". +Functions must be described by a full function signature. If the +remote function is called "doIt", and it takes an int, it would be +described as "doIt(int)". Please note that the return type is not +specified here, as it is not part of the function signature (or at +least the C++ understanding of a function signature). You will get +the return type of a function back as an extra parameter to +DCOPClient::call(). See the section on call() for more details. + +In order to actually get the data to the remote client, it must be +"serialized" via a QDataStream operating on a QByteArray. This is how +the data parameter is "built". A few examples will make clear how this +works. + +Say you want to call "doIt" as described above, and not block (or wait +for a response). You will not receive the return value of the remotely +called function, but you will not hang while the RPC is processed either. +The return value of send() indicates whether DCOP communication succeeded +or not. + +QByteArray data; +QDataStream arg(data, IO_WriteOnly); +arg << 5; +if (!client->send("someAppId", "fooObject/barObject", "doIt(int)", + data)) + qDebug("there was some error using DCOP."); + +OK, now let's say we wanted to get the data back from the remotely +called function. You have to execute a call() instead of a send(). +The returned value will then be available in the data parameter "reply". +The actual return value of call() is still whether or not DCOP +communication was successful. + +QByteArray data, replyData; +QCString replyType; +QDataStream arg(data, IO_WriteOnly); +arg << 5; +if (!client->call("someAppId", "fooObject/barObject", "doIt(int)", + data, replyType, replyData)) + qDebug("there was some error using DCOP."); +else { + QDataStream reply(replyData, IO_ReadOnly); + if (replyType == "QString") { + QString result; + reply >> result; + print("the result is: %s",result.latin1()); + } else + qDebug("doIt returned an unexpected type of reply!"); +} + +N.B.: You cannot call() a method belonging to an application which has +registered with an unique numeric id appended to its textual name (see +dcopclient.h for more info). In this case, DCOP would not know which +application it should connect with to call the method. This is not an issue +with send(), as you can broadcast to all applications that have registered +with appname-<numeric_id> by using a wildcard (e.g. 'konsole-*'), which +will send your signal to all applications called 'konsole'. + +Receiving Data via DCOP: +------------------------ + +Currently the only real way to receive data from DCOP is to multiply +inherit from the normal class that you are inheriting (usually some +sort of QWidget subclass or QObject) as well as the DCOPObject class. +DCOPObject provides one very important method: DCOPObject::process(). +This is a pure virtual method that you must implement in order to +process DCOP messages that you receive. It takes a function +signature, QByteArray of parameters, and a reference to a QByteArray +for the reply data that you must fill in. + +Think of DCOPObject::process() as a sort of dispatch agent. In the +future, there will probably be a precompiler for your sources to write +this method for you. However, until that point you need to examine +the incoming function signature and take action accordingly. Here is +an example implementation. + +bool BarObject::process(const QCString &fun, const QByteArray &data, + QCString &replyType, QByteArray &replyData) +{ + if (fun == "doIt(int)") { + QDataStream arg(data, IO_ReadOnly); + int i; // parameter + arg >> i; + QString result = self->doIt (i); + QDataStream reply(replyData, IO_WriteOnly); + reply << result; + replyType = "QString"; + return true; + } else { + qDebug("unknown function call to BarObject::process()"); + return false; + } +} + +Receiving Calls and processing them: +------------------------------------ + +If your applications is able to process incoming function calls +right away the above code is all you need. When your application +needs to do more complex tasks you might want to do the processing +out of 'process' function call and send the result back later when +it becomes available. + +For this you can ask your DCOPClient for a transactionId. You can +then return from the 'process' function and when the result is +available finish the transaction. In the mean time your application +can receive incoming DCOP function calls from other clients. + +Such code could like this: + +bool BarObject::process(const QCString &fun, const QByteArray &data, + QCString &, QByteArray &) +{ + if (fun == "doIt(int)") { + QDataStream arg(data, IO_ReadOnly); + int i; // parameter + arg >> i; + QString result = self->doIt(i); + + DCOPClientTransaction *myTransaction; + myTransaction = kapp->dcopClient()->beginTransaction(); + + // start processing... + // Calls slotProcessingDone when finished. + startProcessing( myTransaction, i); + + return true; + } else { + qDebug("unknown function call to BarObject::process()"); + return false; + } +} + +slotProcessingDone(DCOPClientTransaction *myTransaction, const QString &result) +{ + QCString replyType = "QString"; + QByteArray replyData; + QDataStream reply(replyData, IO_WriteOnly); + reply << result; + kapp->dcopClient()->endTransaction( myTransaction, replyType, replyData ); +} + +DCOP Signals +------------ + +Sometimes a component wants to send notifications via DCOP to other +components but does not know which components will be interested in these +notifications. One could use a broadcast in such a case but this is a very +crude method. For a more sophisticated method DCOP signals have been invented. + +DCOP signals are very similair to Qt signals, there are some differences +though. A DCOP signal can be connected to a DCOP function. Whenever the DCOP +signal gets emitted, the DCOP functions to which the signal is connected are +being called. DCOP signals are, just like Qt signals, one way. They do not +provide a return value. + +A DCOP signal originates from a DCOP Object/DCOP Client combination (sender). +It can be connected to a function of another DCOP Object/DCOP Client +combination (receiver). + +There are two major differences between connections of Qt signals and +connections of DCOP signals. In DCOP, unlike Qt, a signal connections can +have an anonymous sender and, unlike Qt, a DCOP signal connection can be +non-volatile. + +With DCOP one can connect a signal without specifying the sending DCOP Object +or DCOP Client. In that case signals from any DCOP Object and/or DCOP Client +will be delivered. This allows the specification of certain events without +tying oneself to a certain object that implementes the events. + +Another DCOP feature are so called non-volatile connections. With Qt signal +connections, the connection gets deleted when either sender or receiver of +the signal gets deleted. A volatile DCOP signal connection will behave the +same. However, a non-volatile DCOP signal connection will not get deleted +when the sending object gets deleted. Once a new object gets created with +the same name as the original sending object, the connection will be restored. +There is no difference between the two when the receiving object gets deleted, +in that case the signal connection will always be deleted. + +A receiver can create a non-volatile connection while the sender doesn't (yet) +exist. An anonymous DCOP connection should always be non-volatile. + +The following example shows how KLauncher emits a signal whenever it notices +that an application that was started via KLauncher terminates. + + QByteArray params; + QDataStream stream(params, IO_WriteOnly); + stream << pid; + kapp->dcopClient()->emitDCOPSignal("clientDied(pid_t)", params); + +The task manager of the KDE panel connects to this signal. It uses an +anonymous connection (it doesn't require that the signal is being emitted +by KLauncher) that is non-volatile: + + connectDCOPSignal(0, 0, "clientDied(pid_t)", "clientDied(pid_t)", false); + +It connects the clientDied(pid_t) signal to its own clientDied(pid_t) DCOP +function. In this case the signal and the function to call have the same name. +This isn't needed as long as the arguments of both signal and receiving function +match. The receiving function may ignore one or more of the trailing arguments +of the signal. E.g. it is allowed to connect the clientDied(pid_t) signal to +a clientDied(void) DCOP function. + +Using the dcopidl compiler +--------------------- + +dcopidl makes setting up a DCOP server easy. Instead of having to implement +the process() method and unmarshalling (retrieving from QByteArray) parameters +manually, you can let dcopidl create the necessary code on your behalf. + +This also allows you to describe the interface for your class in a +single, separate header file. + +Writing an IDL file is very similar to writing a normal C++ header. An +exception is the keyword 'ASYNC'. It indicates that a call to this +function shall be processed asynchronously. For the C++ compiler, it +expands to 'void'. + +Example: + +#ifndef MY_INTERFACE_H +#define MY_INTERFACE_H + +#include <dcopobject.h> + +class MyInterface : virtual public DCOPObject +{ + K_DCOP + + k_dcop: + + virtual ASYNC myAsynchronousMethod(QString someParameter) = 0; + virtual QRect mySynchronousMethod() = 0; +}; + +#endif + +As you can see, you're essentially declaring an abstract base class, which +virtually inherits from DCOPObject. + +If you're using the standard KDE build scripts, then you can simply +add this file (which you would call MyInterface.h) to your sources +directory. Then you edit your Makefile.am, adding 'MyInterface.skel' +to your SOURCES list and MyInterface.h to include_HEADERS. + +The build scripts will use dcopidl to parse MyInterface.h, converting +it to an XML description in MyInterface.kidl. Next, a file called +MyInterface_skel.cpp will automatically be created, compiled and +linked with your binary. + +The next thing you have to do is to choose which of your classes will +implement the interface described in MyInterface.h. Alter the inheritance +of this class such that it virtually inherits from MyInterface. Then +add declarations to your class interface similar to those on MyInterface.h, +but virtual, not pure virtual. + +Example: + +class MyClass: public QObject, virtual public MyInterface +{ + Q_OBJECT + + public: + MyClass(); + ~MyClass(); + + ASYNC myAsynchronousMethod(QString someParameter); + QRect mySynchronousMethod(); +}; + +Note: (Qt issue) Remember that if you are inheriting from QObject, you must +place it first in the list of inherited classes. + +In the implementation of your class' ctor, you must explicitly initialize +those classes from which you are inheriting from. This is, of course, good +practise, but it is essential here as you need to tell DCOPObject the name of +the interface which your are implementing. + +Example: + +MyClass::MyClass() + : QObject(), + DCOPObject("MyInterface") +{ + // whatever... +} + +Now you can simply implement the methods you have declared in your interface, +exactly the same as you would normally. + +Example: + +void MyClass::myAsynchronousMethod(QString someParameter) +{ + qDebug("myAsyncMethod called with param `" + someParameter + "'"); +} + + +It is not necessary (though very clean) to define an interface as an +abstract class of its own, like we did in the example above. We could +just as well have defined a k_dcop section directly within MyClass: + +class MyClass: public QObject, virtual public DCOPObject +{ + Q_OBJECT + K_DCOP + + public: + MyClass(); + ~MyClass(); + + k_dcop: + ASYNC myAsynchronousMethod(QString someParameter); + QRect mySynchronousMethod(); +}; + +In addition to skeletons, dcopidl2cpp also generate stubs. Those make +it easy to call a DCOP interface without doing the marshalling +manually. To use a stub, add MyInterface.stub to the SOURCES list of +your Makefile.am. The stub class will then be called MyInterface_stub. + +Conclusion: +----------- + +Hopefully this document will get you well on your way into the world +of inter-process communication with KDE! Please direct all comments +and/or suggestions to Preston Brown <pbrown@kde.org> and Matthias +Ettrich <ettrich@kde.org>. + + +Inter-user communication +------------------------ + +Sometimes it might be interesting to use DCOP between processes +belonging to different users, e.g. a frontend process running +with the user's id, and a backend process running as root. + +To do this, two steps have to be taken: + +a) both processes need to talk to the same DCOP server +b) the authentication must be ensured + +For the first step, you simply pass the server address (as +found in .DCOPserver) to the second process. For the authentication, +you can use the ICEAUTHORITY environment variable to tell the +second process where to find the authentication information. +(Note that this implies that the second process is able to +read the authentication file, so it will probably only work +if the second process runs as root. If it should run as another +user, a similar approach to what kdesu does with xauth must +be taken. In fact, it would be a very good idea to add DCOP +support to kdesu!) + +For example + +ICEAUTHORITY=~user/.ICEauthority kdesu root -c kcmroot -dcopserver `cat ~user/.DCOPserver` + +will, after kdesu got the root password, execute kcmroot as root, talking +to the user's dcop server. + + +NOTE: DCOP communication is not encrypted, so please do not +pass important information around this way. + + +Performance Tests: +------------------ +A few back-of-the-napkin tests folks: + +Code: + +#include <kapplication.h> + +int main(int argc, char **argv) +{ + KApplication *app; + + app = new KApplication(argc, argv, "testit"); + return app->exec(); +} + +Compiled with: + +g++ -O2 -o testit testit.cpp -I$QTDIR/include -L$QTDIR/lib -lkdecore + +on Linux yields the following memory use statistics: + +VmSize: 8076 kB +VmLck: 0 kB +VmRSS: 4532 kB +VmData: 208 kB +VmStk: 20 kB +VmExe: 4 kB +VmLib: 6588 kB + +If I create the KApplication's DCOPClient, and call attach() and +registerAs(), it changes to this: + +VmSize: 8080 kB +VmLck: 0 kB +VmRSS: 4624 kB +VmData: 208 kB +VmStk: 20 kB +VmExe: 4 kB +VmLib: 6588 kB + +Basically it appears that using DCOP causes 100k more memory to be +resident, but no more data or stack. So this will be shared between all +processes, right? 100k to enable DCOP in all apps doesn't seem bad at +all. :) + +OK now for some timings. Just creating a KApplication and then exiting +(i.e. removing the call to KApplication::exec) takes this much time: + +0.28user 0.02system 0:00.32elapsed 92%CPU (0avgtext+0avgdata 0maxresident)k +0inputs+0outputs (1084major+62minor)pagefaults 0swaps + +I.e. about 1/3 of a second on my PII-233. Now, if we create our DCOP +object and attach to the server, it takes this long: + +0.27user 0.03system 0:00.34elapsed 87%CPU (0avgtext+0avgdata 0maxresident)k +0inputs+0outputs (1107major+65minor)pagefaults 0swaps + +I.e. about 1/3 of a second. Basically DCOPClient creation and attaching +gets lost in the statistical variation ("noise"). I was getting times +between .32 and .48 over several runs for both of the example programs, so +obviously system load is more relevant than the extra two calls to +DCOPClient::attach and DCOPClient::registerAs, as well as the actual +DCOPClient constructor time. + diff --git a/doc/diagram.png b/doc/diagram.png Binary files differnew file mode 100644 index 00000000..5cb84a99 --- /dev/null +++ b/doc/diagram.png diff --git a/doc/diagram.svg b/doc/diagram.svg new file mode 100644 index 00000000..193c5679 --- /dev/null +++ b/doc/diagram.svg @@ -0,0 +1,590 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" +"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + id="svg1" + sodipodi:version="0.32" + inkscape:version="0.39" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://web.resource.org/cc/" + xmlns:dc="http://purl.org/dc/elements/1.1/" + width="841.88975pt" + height="595.27559pt" + sodipodi:docbase="/home/hp/dbus-cvs/dbus/doc" + sodipodi:docname="diagram.svg"> + <defs + id="defs3"> + <marker + style="overflow:visible;" + id="Arrow1M" + refX="0.0" + refY="0.0" + orient="auto" + inkscape:stockid="Arrow1M"> + <path + transform="scale(0.4)" + style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;" + d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z " + id="path3519" + sodipodi:nodetypes="ccccc" /> + </marker> + <marker + style="overflow:visible;" + id="Arrow2L" + refX="0.0" + refY="0.0" + orient="auto" + inkscape:stockid="Arrow2L"> + <path + transform="scale(1.1) translate(-5,0)" + d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.9730900,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z " + style="font-size:12.0;fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;" + id="path3515" + sodipodi:nodetypes="cccc" /> + </marker> + </defs> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.90210318" + inkscape:cx="420.94487" + inkscape:cy="297.63779" + inkscape:window-width="1024" + inkscape:window-height="701" + showgrid="false" + inkscape:grid-bbox="false" + inkscape:grid-points="true" + inkscape:window-x="0" + inkscape:window-y="24" + gridspacingy="2.5000000mm" + gridspacingx="2.5000000mm" + showguides="true" + inkscape:guide-bbox="true"> + <sodipodi:guide + orientation="horizontal" + position="268.85797" + id="guide3566" /> + <sodipodi:guide + orientation="horizontal" + position="294.31223" + id="guide4235" /> + <sodipodi:guide + orientation="horizontal" + position="300.40909" + id="guide4882" /> + </sodipodi:namedview> + <metadata + id="metadata4"> + <rdf:RDF + id="RDF5"> + <cc:Work + rdf:about="" + id="Work6"> + <dc:format + id="format7">image/svg+xml</dc:format> + <dc:type + id="type9" + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <rect + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.7500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;" + id="rect908" + width="325.23203" + height="354.33072" + x="17.716536" + y="372.04724" /> + <text + xml:space="preserve" + style="font-size:18.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;" + x="70.778252" + y="712.73920" + id="text1532" + sodipodi:linespacing="100%"><tspan + id="tspan1533">Application Process 1</tspan></text> + <rect + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.5000000 2.5000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;" + id="rect1535" + width="148.46259" + height="46.656849" + x="106.29921" + y="378.54001" /> + <text + xml:space="preserve" + style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;" + x="180.61389" + y="400.40048" + id="text2158" + sodipodi:linespacing="100%"><tspan + id="tspan2159">DBusConnection</tspan><tspan + sodipodi:role="line" + id="tspan2161" + x="180.61389" + y="414.40048">Instance</tspan></text> + <rect + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.9950929;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.9950928 2.9950928 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;" + id="rect2170" + width="148.46259" + height="66.966240" + x="28.702768" + y="549.21259" /> + <text + xml:space="preserve" + style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;" + x="103.01745" + y="577.56586" + id="text2171" + sodipodi:linespacing="100%"><tspan + x="103.01745" + y="577.56586" + sodipodi:role="line" + id="tspan2176">C/C++/Python/etc.</tspan><tspan + x="103.01745" + y="591.56586" + sodipodi:role="line" + id="tspan2178">Object Instance</tspan></text> + <path + style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;" + id="path3535" + d="M 98.938952,408.61479 C 98.744753,409.20303 97.917886,409.67295 97.440945,410.11435 C 95.534947,411.94763 94.266934,414.11555 93.172614,416.33858 C 91.902056,419.02725 90.969281,421.79944 90.107252,424.59229 C 89.589105,426.27374 88.983534,427.90634 88.266907,429.53700 C 87.919667,430.33438 87.622593,431.17598 87.120464,431.91970 C 86.832222,432.30665 86.469422,432.65145 86.167985,433.03184 C 86.015931,433.22254 85.868997,433.41563 85.722131,433.60898 L 82.914336,433.11743 C 83.063402,432.91879 83.213428,432.72069 83.368121,432.52498 C 83.654681,432.15308 83.980737,431.80834 84.285389,431.44731 C 84.811957,430.77175 85.122523,429.97914 85.482400,429.23872 C 86.253056,427.64929 86.903084,426.03861 87.474578,424.39321 C 88.439548,421.58552 89.442843,418.78792 90.703938,416.05898 C 91.810966,413.77525 92.999191,411.45961 94.849464,409.50748 C 95.094704,409.24876 96.091789,407.90149 95.865737,408.61479 L 98.938952,408.61479 z " /> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;" + x="34.109497" + y="446.13382" + id="text3536"><tspan + id="tspan3537">Locate Object</tspan><tspan + sodipodi:role="line" + id="tspan3539" + x="34.109497" + y="458.13382">via Object Path</tspan></text> + <path + style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;" + id="path3541" + d="M 60.509867,462.78767 C 60.704066,463.37591 61.530933,463.84583 62.007874,464.28723 C 63.913872,466.12051 65.181885,468.28843 66.276205,470.51146 C 67.546763,473.20013 68.479538,475.97232 69.341567,478.76517 C 69.859714,480.44662 70.465285,482.07922 71.181912,483.70988 C 71.529152,484.50726 71.826226,485.34886 72.328355,486.09258 C 72.616597,486.47953 72.979397,486.82433 73.280834,487.20472 C 73.432888,487.39542 73.579822,487.58851 73.726688,487.78186 L 76.534483,487.29031 C 76.385417,487.09167 76.235391,486.89357 76.080698,486.69786 C 75.794138,486.32596 75.468082,485.98122 75.163430,485.62019 C 74.636862,484.94463 74.326296,484.15202 73.966419,483.41160 C 73.195763,481.82217 72.545735,480.21149 71.974241,478.56609 C 71.009271,475.75840 70.005976,472.96080 68.744881,470.23186 C 67.637853,467.94813 66.449628,465.63249 64.599355,463.68036 C 64.354115,463.42164 63.357030,462.07437 63.583082,462.78767 L 60.509867,462.78767 z " /> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;" + x="49.100315" + y="501.60959" + id="text3542" + sodipodi:linespacing="100%"><tspan + x="49.100315" + y="501.60959" + sodipodi:role="line" + id="tspan3547">Bindings Marshal</tspan><tspan + x="49.100315" + y="513.60959" + sodipodi:role="line" + id="tspan3549">to Method Call</tspan></text> + <path + style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;" + id="path3551" + d="M 95.295239,519.43211 C 95.101039,520.02035 94.274169,520.49027 93.797229,520.93167 C 91.891239,522.76495 90.623219,524.93287 89.528899,527.15590 C 88.258339,529.84457 87.325569,532.61676 86.463539,535.40961 C 85.945389,537.09106 85.339819,538.72366 84.623199,540.35432 C 84.275959,541.15170 83.978879,541.99330 83.476749,542.73702 C 83.188509,543.12397 82.825709,543.46877 82.524269,543.84916 C 82.372219,544.03986 82.225289,544.23295 82.078419,544.42630 L 79.270619,543.93475 C 79.419689,543.73611 79.569719,543.53801 79.724409,543.34230 C 80.010969,542.97040 80.337029,542.62566 80.641679,542.26463 C 81.168249,541.58907 81.478809,540.79646 81.838689,540.05604 C 82.609339,538.46661 83.259369,536.85593 83.830869,535.21053 C 84.795839,532.40284 85.799129,529.60524 87.060229,526.87630 C 88.167249,524.59257 89.355479,522.27693 91.205749,520.32480 C 91.450989,520.06608 92.448079,518.71881 92.222029,519.43211 L 95.295239,519.43211 z " /> + <path + style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;" + id="path3552" + d="M 261.83533,408.61479 C 262.02953,409.20303 262.85640,409.67295 263.33334,410.11435 C 265.23934,411.94763 266.50735,414.11555 267.60167,416.33858 C 268.87223,419.02725 269.80501,421.79944 270.66703,424.59229 C 271.18518,426.27374 271.79075,427.90634 272.50738,429.53700 C 272.85462,430.33438 273.15169,431.17598 273.65382,431.91970 C 273.94206,432.30665 274.30486,432.65145 274.60630,433.03184 C 274.75836,433.22254 274.90529,433.41563 275.05216,433.60898 L 277.85995,433.11743 C 277.71088,432.91879 277.56086,432.72069 277.40617,432.52498 C 277.11961,432.15308 276.79355,431.80834 276.48890,431.44731 C 275.96233,430.77175 275.65176,429.97914 275.29189,429.23872 C 274.52123,427.64929 273.87120,426.03861 273.29971,424.39321 C 272.33474,421.58552 271.33144,418.78792 270.07035,416.05898 C 268.96332,413.77525 267.77510,411.45961 265.92482,409.50748 C 265.67958,409.24876 264.68250,407.90149 264.90855,408.61479 L 261.83533,408.61479 z " /> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;" + x="223.98749" + y="446.13382" + id="text3553" + sodipodi:linespacing="100%"><tspan + x="223.98749" + y="446.13382" + sodipodi:role="line" + id="tspan3562">Marshal Method</tspan><tspan + x="223.98749" + y="458.13382" + sodipodi:role="line" + id="tspan3564">Call to Message</tspan></text> + <path + style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;" + id="path3567" + d="M 278.96485,463.29453 C 278.77065,463.88277 277.94378,464.35269 277.46684,464.79409 C 275.56085,466.62737 274.29283,468.79529 273.19851,471.01832 C 271.92795,473.70699 270.99518,476.47918 270.13315,479.27203 C 269.61500,480.95348 269.00943,482.58608 268.29281,484.21674 C 267.94557,485.01412 267.64849,485.85572 267.14636,486.59944 C 266.85812,486.98639 266.49532,487.33119 266.19388,487.71158 C 266.04183,487.90228 265.89490,488.09537 265.74803,488.28872 L 262.94023,487.79717 C 263.08930,487.59853 263.23933,487.40043 263.39402,487.20472 C 263.68058,486.83282 264.00664,486.48808 264.31129,486.12705 C 264.83786,485.45149 265.14842,484.65888 265.50830,483.91846 C 266.27895,482.32903 266.92898,480.71835 267.50048,479.07295 C 268.46545,476.26526 269.46874,473.46766 270.72984,470.73872 C 271.83686,468.45499 273.02509,466.13935 274.87536,464.18722 C 275.12060,463.92850 276.11769,462.58123 275.89164,463.29453 L 278.96485,463.29453 z " /> + <rect + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.7377086;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.7377084 2.7377084 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;" + id="rect3568" + width="124.01746" + height="66.979813" + x="189.79265" + y="495.08902" /> + <text + xml:space="preserve" + style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;" + x="248.94049" + y="523.44220" + id="text3569" + sodipodi:linespacing="100%"><tspan + x="248.94049" + y="523.44220" + sodipodi:role="line" + id="tspan3574">Bindings Proxy</tspan><tspan + x="248.94049" + y="537.44220" + sodipodi:role="line" + id="tspan3576">Object Instance</tspan></text> + <path + style="fill:#000000;fill-opacity:1.0000000;fill-rule:nonzero;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;" + id="path3578" + d="M 259.03547,566.92913 C 259.22967,567.51737 260.05653,567.98729 260.53348,568.42869 C 262.43947,570.26197 263.70749,572.42989 264.80181,574.65292 C 266.07236,577.34159 267.00514,580.11378 267.86717,582.90663 C 268.38532,584.58808 268.99089,586.22068 269.70751,587.85134 C 270.05475,588.64872 270.35183,589.49032 270.85396,590.23404 C 271.14220,590.62099 271.50500,590.96579 271.80644,591.34618 C 271.95849,591.53688 272.10542,591.72997 272.25229,591.92332 L 275.06008,591.43177 C 274.91102,591.23313 274.76099,591.03503 274.60630,590.83932 C 274.31974,590.46742 273.99368,590.12268 273.68903,589.76165 C 273.16246,589.08609 272.85190,588.29348 272.49202,587.55306 C 271.72136,585.96363 271.07134,584.35295 270.49984,582.70755 C 269.53487,579.89986 268.53158,577.10226 267.27048,574.37332 C 266.16345,572.08959 264.97523,569.77395 263.12496,567.82182 C 262.87972,567.56310 261.88263,566.21583 262.10868,566.92913 L 259.03547,566.92913 z " /> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;" + x="217.40741" + y="607.90881" + id="text3579" + sodipodi:linespacing="100%"><tspan + x="217.40741" + y="607.90881" + sodipodi:role="line" + id="tspan3584">Application Code</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.96172028pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);" + d="M 26.574803,408.60009 C 26.574803,539.68912 26.574803,539.68911 26.574803,531.49606" + id="path3586" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;" + x="25.977146" + y="386.45212" + id="text4220" + sodipodi:linespacing="100%"><tspan + id="tspan4221">Incoming</tspan><tspan + sodipodi:role="line" + id="tspan4223" + x="25.977146" + y="398.45212">Call</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:end;writing-mode:lr;" + x="335.61411" + y="386.45212" + id="text4226" + sodipodi:linespacing="100%"><tspan + x="335.61411" + y="386.45212" + sodipodi:role="line" + id="tspan4231">Outgoing</tspan><tspan + x="335.61411" + y="398.45212" + sodipodi:role="line" + id="tspan4233">Call</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:0.96172028pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-start:url(#Arrow1M);marker-end:none;" + d="M 327.75591,416.33858 C 327.75591,547.42761 327.75591,547.42760 327.75591,539.23455" + id="path4236" + sodipodi:nodetypes="cc" /> + <rect + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:5.7914310;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;" + id="rect4870" + width="885.86591" + height="310.27252" + x="88.582680" + y="8.8582621" /> + <text + xml:space="preserve" + style="font-size:18.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;" + x="515.42737" + y="305.44489" + id="text4871" + sodipodi:linespacing="100%"><tspan + x="515.42737" + y="305.44489" + sodipodi:role="line" + id="tspan4874">Bus Daemon Process</tspan></text> + <rect + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:3.7500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;" + id="rect4876" + width="325.23203" + height="354.33072" + x="708.66144" + y="373.08359" /> + <text + xml:space="preserve" + style="font-size:18.000000;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;" + x="761.72314" + y="713.77551" + id="text4877" + sodipodi:linespacing="100%"><tspan + x="761.72314" + y="713.77551" + sodipodi:role="line" + id="tspan4880">Application Process 2</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;" + x="823.49664" + y="505.18018" + id="text4883" + sodipodi:linespacing="100%"><tspan + x="823.49664" + y="505.18018" + sodipodi:role="line" + id="tspan4888">Same Stuff as in</tspan><tspan + x="823.49664" + y="517.18018" + sodipodi:role="line" + id="tspan4890">Process 1</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;" + x="47.891071" + y="638.05420" + id="text4892" + sodipodi:linespacing="100%"><tspan + x="47.891071" + y="638.05420" + sodipodi:role="line" + id="tspan4901">(Object Instance Has</tspan><tspan + x="47.891071" + y="650.05420" + sodipodi:role="line" + id="tspan4903">1 or More Interfaces)</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-start:url(#Arrow1M);marker-end:url(#Arrow1M);stroke-dasharray:none;" + d="M 162.57260,358.02041 C 165.25213,354.60516 186.01858,328.13688 184.00893,330.69832" + id="path4905" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;" + x="190.57170" + y="342.62018" + id="text5539"><tspan + id="tspan5540">Socket</tspan><tspan + sodipodi:role="line" + id="tspan5544" + x="190.57170" + y="354.62018">(Bidirectional Message Stream)</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.2500000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-opacity:1.0000000;marker-start:url(#Arrow1M);marker-end:url(#Arrow1M);" + d="M 827.53876,363.18897 C 824.85916,359.77372 804.09276,333.30544 806.10236,335.86688" + id="path5546" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;" + x="840.79150" + y="345.73135" + id="text5547"><tspan + id="tspan5548">Socket</tspan><tspan + sodipodi:role="line" + id="tspan5550" + x="840.79150" + y="357.73135">(Bidirectional Message Stream)</tspan></text> + <rect + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.5000000 2.5000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;" + id="rect5552" + width="148.46259" + height="46.656849" + x="124.01575" + y="263.38251" /> + <text + xml:space="preserve" + style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;" + x="198.33043" + y="285.24298" + id="text5553" + sodipodi:linespacing="100%"><tspan + id="tspan5554">DBusConnection</tspan><tspan + sodipodi:role="line" + id="tspan5556" + x="198.33043" + y="299.24298">Instance</tspan></text> + <rect + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.5000000 2.5000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;" + id="rect5558" + width="148.46259" + height="46.656849" + x="719.64764" + y="263.38251" /> + <text + xml:space="preserve" + style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;" + x="793.96234" + y="285.24298" + id="text5559" + sodipodi:linespacing="100%"><tspan + id="tspan5560">DBusConnection</tspan><tspan + sodipodi:role="line" + id="tspan5562" + x="793.96234" + y="299.24298">Instance</tspan></text> + <rect + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.5000000 2.5000000 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;" + id="rect5564" + width="148.46259" + height="46.656849" + x="763.77222" + y="378.54001" /> + <text + xml:space="preserve" + style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;" + x="838.08691" + y="400.40048" + id="text5565" + sodipodi:linespacing="100%"><tspan + id="tspan5566">DBusConnection</tspan><tspan + sodipodi:role="line" + id="tspan5568" + x="838.08691" + y="414.40048">Instance</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);" + d="M 186.02362,248.03149 C 106.29921,26.574797 372.04724,26.574797 372.04724,26.574797" + id="path5571" + sodipodi:nodetypes="cc" /> + <rect + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:2.1854961;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4.0000000;stroke-dasharray:2.1854960 2.1854960 ;stroke-dashoffset:0.0000000;stroke-opacity:1.0000000;" + id="rect6205" + width="148.46259" + height="35.656227" + x="391.89175" + y="17.493374" /> + <text + xml:space="preserve" + style="font-size:14.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;" + x="466.20642" + y="39.577003" + id="text6206" + sodipodi:linespacing="100%"><tspan + x="466.20642" + y="39.577003" + sodipodi:role="line" + id="tspan6211">Message Dispatcher</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);" + d="M 806.10236,248.03149 C 814.96063,17.716530 549.21260,26.574797 558.07087,26.574797" + id="path6213" + sodipodi:nodetypes="cc" /> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:start;writing-mode:lr;" + x="380.24341" + y="71.125053" + id="text6214" + sodipodi:linespacing="100%"><tspan + x="380.24341" + y="71.125053" + sodipodi:role="line" + id="tspan6860">if (message is signal)</tspan><tspan + x="380.24341" + y="83.125053" + sodipodi:role="line" + id="tspan6862"> broadcast</tspan><tspan + x="380.24341" + y="95.125053" + sodipodi:role="line" + id="tspan6864">else</tspan><tspan + x="380.24341" + y="107.12505" + sodipodi:role="line" + id="tspan6866"> find destination named by message</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);" + d="M 380.90551,79.724404 C 177.16536,53.149601 203.74016,256.88976 203.74016,248.03149" + id="path6868" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);" + d="M 451.77165,79.724404 C 788.38583,44.291333 779.52756,256.88976 779.52756,248.03149" + id="path6869" + sodipodi:nodetypes="cc" /> + <rect + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#6a6a6a;stroke-width:2.5000000;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;stroke-miterlimit:4.0000000;stroke-dasharray:1.2500000,1.2500000;stroke-dashoffset:0.0000000;" + id="rect7503" + width="318.89764" + height="168.30708" + x="345.47244" + y="115.15748" /> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr;" + x="507.10016" + y="132.70409" + id="text8137" + sodipodi:linespacing="100%"><tspan + id="tspan8138">Destination Table</tspan></text> + <text + xml:space="preserve" + style="font-size:12.000000;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;font-family:Bitstream Vera Sans;font-stretch:normal;font-variant:normal;text-anchor:start;writing-mode:lr;" + x="422.71124" + y="158.39366" + id="text8140" + sodipodi:linespacing="120%"><tspan + x="422.71124" + y="158.39366" + sodipodi:role="line" + id="tspan8818">Connection 1</tspan><tspan + x="422.71124" + y="172.79366" + sodipodi:role="line" + id="tspan8820">Connection 2</tspan><tspan + x="422.71124" + y="187.19366" + sodipodi:role="line" + id="tspan8822">"The Session Manager"</tspan><tspan + x="422.71124" + y="201.59366" + sodipodi:role="line" + id="tspan8824">"The Window Manager"</tspan><tspan + x="422.71124" + y="215.99366" + sodipodi:role="line" + id="tspan8826">"The Screensaver"</tspan><tspan + x="422.71124" + y="230.39366" + sodipodi:role="line" + id="tspan8828">"The Text Editor"</tspan><tspan + x="422.71124" + y="244.79366" + sodipodi:role="line" + id="tspan8830">"The Hardware Directory"</tspan><tspan + x="422.71124" + y="259.19367" + sodipodi:role="line" + id="tspan8832">"The Address Book"</tspan><tspan + x="422.71124" + y="273.59367" + sodipodi:role="line" + id="tspan8834">"The Dictionary"</tspan></text> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);" + d="M 416.33858,150.59055 C 239.17323,97.440935 221.45669,256.88976 221.45669,248.03149" + id="path8179" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);" + d="M 504.92126,168.30708 C 726.37795,106.29921 770.66929,265.74802 761.81102,239.17322" + id="path8180" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;" + d="" + id="path8181" + sodipodi:nodetypes="" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);" + d="M 584.64567,239.17322 C 717.51969,194.88188 761.81102,256.88976 752.95276,248.03149" + id="path8182" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-opacity:0.75000000;fill-rule:evenodd;stroke:#000000;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;marker-end:url(#Arrow1M);" + d="M 416.33858,177.16535 C 301.18111,124.01574 230.31496,265.74803 239.17323,248.03149" + id="path8184" + sodipodi:nodetypes="cc" /> +</svg> diff --git a/doc/file-boilerplate.c b/doc/file-boilerplate.c new file mode 100644 index 00000000..bc365f80 --- /dev/null +++ b/doc/file-boilerplate.c @@ -0,0 +1,27 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* FILENAME BRIEF FILE DESCRIPTION + * + * Copyright (C) YEAR COPYRIGHT HOLDER + * + * 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 DBUS_FOO_H +#define DBUS_FOO_H + +#endif /* DBUS_FOO_H */ diff --git a/doc/introspect.dtd b/doc/introspect.dtd new file mode 100644 index 00000000..ba263d32 --- /dev/null +++ b/doc/introspect.dtd @@ -0,0 +1,37 @@ +<!-- DTD for D-Bus Introspection data --> +<!-- (C) 2005-02-02 David A. Wheeler; released under the D-Bus licenses, + GNU GPL version 2 (or greater) and AFL 1.1 (or greater) --> + +<!-- see D-Bus specification for documentation --> + +<!ELEMENT node (node|interface)*> +<!ATTLIST node name CDATA #IMPLIED> + +<!ELEMENT interface (method|signal|property|annotation)*> +<!ATTLIST interface name CDATA #REQUIRED> + +<!ELEMENT method (arg|annotation)*> +<!ATTLIST method name CDATA #REQUIRED> + +<!ELEMENT signal (arg|annotation)*> +<!ATTLIST signal name CDATA #REQUIRED> + +<!ELEMENT arg EMPTY> +<!ATTLIST arg name CDATA #IMPLIED> +<!ATTLIST arg type CDATA #REQUIRED> +<!-- Method arguments SHOULD include "direction", + while signal and error arguments SHOULD not (since there's no point). + The DTD format can't express that subtlety. --> +<!ATTLIST arg direction (in|out) "in"> + +<!-- AKA "attribute" --> +<!ELEMENT property (annotation)*> +<!ATTLIST property name CDATA #REQUIRED> +<!ATTLIST property type CDATA #REQUIRED> +<!ATTLIST property access (read|write|readwrite) #REQUIRED> + +<!ELEMENT annotation EMPTY> <!-- Generic metadata --> +<!ATTLIST annotation name CDATA #REQUIRED> +<!ATTLIST annotation value CDATA #REQUIRED> + + diff --git a/doc/introspect.xsl b/doc/introspect.xsl new file mode 100644 index 00000000..2a344741 --- /dev/null +++ b/doc/introspect.xsl @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="ISO-8859-15"?> +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml"> + +<!-- + Copyright (C) 2005 Lennart Poettering. + + 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 +--> + +<!-- $Id$ --> + +<xsl:output method="xml" version="1.0" encoding="iso-8859-15" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" indent="yes"/> + +<xsl:template match="/"> + <html> + <head> + <title>DBUS Introspection data</title> + <style type="text/css"> + body { color: black; background-color: white } + h1 { font-family: sans-serif } + ul { list-style-type: none; margin-bottom: 10px } + li { font-family: sans-serif } + .keyword { font-style: italic } + .type { font-weight: bold } + .symbol { font-family: monospace } + .interface { padding: 10px; margin: 10px } + </style> + </head> + <body> + <xsl:for-each select="node/interface"> + <div class="interface"> + <h1> + <span class="keyword">interface</span><xsl:text> </xsl:text> + <span class="symbol"><xsl:value-of select="@name"/></span> + </h1> + + <ul> + + <xsl:apply-templates select="annotation"/> + + <xsl:for-each select="method|signal|property"> + <li> + <span class="keyword"><xsl:value-of select="name()"/></span> + <xsl:text> </xsl:text> + <span class="symbol"><xsl:value-of select="@name"/></span> + + <ul> + <xsl:apply-templates select="annotation"/> + <xsl:for-each select="arg"> + <li> + <span class="keyword"> + <xsl:choose> + <xsl:when test="@direction != """> + <xsl:value-of select="@direction"/> + </xsl:when> + <xsl:when test="name(..) = "signal""> + out + </xsl:when> + <xsl:otherwise> + in + </xsl:otherwise> + </xsl:choose> + </span> + + <xsl:text> </xsl:text> + + <span class="type"><xsl:value-of select="@type"/></span><xsl:text> </xsl:text> + <span class="symbol"><xsl:value-of select="@name"/></span><xsl:text> </xsl:text> + </li> + </xsl:for-each> + </ul> + + </li> + </xsl:for-each> + + </ul> + </div> + </xsl:for-each> + </body> + </html> +</xsl:template> + + +<xsl:template match="annotation"> + <li> + <span class="keyword">annotation</span> + <code><xsl:value-of select="@name"/></code><xsl:text> = </xsl:text> + <code><xsl:value-of select="@value"/></code> + </li> +</xsl:template> + +</xsl:stylesheet> diff --git a/doc/system-activation.txt b/doc/system-activation.txt new file mode 100644 index 00000000..dd195f75 --- /dev/null +++ b/doc/system-activation.txt @@ -0,0 +1,80 @@ +D-BUS System Activation + +Introduction: + +The dbus-daemon runs as the dbus user, and is therefore unprivileged. +Earlier attempts [1] by David Zeuthen at launching system scripts using a +custom DBUS protocol were reviewed, but deemed too difficult to audit, and +also due to a multi-threaded design, too difficult to test. +In the next few paragraphs I will outline a simpler setuid approach for +launching daemons as a configured user. + +Scope: + +Launching programs using dbus has been a topic of interest for many months. +This would allow simple systems to only start services that are needed, +and that are automatically started only when first requested. +This removes the need for an init system, and means that we can trivially +startup services in parallel. +This has immediate pressing need for OLPC, with a longer term evaluation for +perhaps Fedora and RHEL. + +Details: + +Setuid applications have to used only when absolutely necessary. +In this implementation I have an single executable, +dbus-daemon-launch-helper, with the ownership root:dbus. +This has the permissions 4750, i.e. u+rwx g+rx +setuid. +It is located in /usr/libexec/ and thus is not designed to be invoked by a +user directly. + +The helper must not be passed input that can be changed maliciously, and +therefore passing a random path with user id is totally out of the question. +In this implementation a similar idea as discussed with Davids' patch was +taken, that to pass a single name argument to the helper. +The service filename of "org.me.test.service" is then searched for in +/usr/share/dbus-1/system-services or other specified directories. + +If applications want to be activated on the system _and_ session busses, then +service files should be installed in both directories. + +A typical service file would look like: + +[D-BUS Service] +Name=org.me.test +Exec=/usr/sbin/dbus-test-server.py +User=ftp + +This gives the user to switch to, and also the path of the executable. +The service name must match that specified in the /etc/dbus-1/system.d conf file. + +Precautions taken: + +* Only the bus name is passed to the helper, and this is validated +* We are super paranoid about the user that called us, and what permissions we have. +* We clear all environment variables except for DBUS_VERBOSE which is used for debugging +* Anything out of the ordinary causes the helper to abort. + +Launching services: + +Trivial methods on services can be called directly and the launch helper will +start the service and execute the method on the service. The lauching of the +service is completely transparent to the caller, e.g.: + +dbus-send --system --print-reply \ + --dest=org.freedesktop.Hal \ + /org/freedesktop/Hal/Manager \ + org.freedesktop.Hal.Manager.DeviceExists \ + string:/org/freedesktop/Hal/devices/computer + +If you wish to activate the service without calling a well known method, +the standard dbus method StartServiceByName can be used: + +dbus-send --system --print-reply \ + --dest=org.freedesktop.DBus \ + /org/freedesktop/DBus \ + org.freedesktop.DBus.StartServiceByName \ + string:org.freedesktop.Hal uint32:0 + +[1] http://lists.freedesktop.org/archives/dbus/2006-October/006096.html + |
