2003-01-23 05:04:03 +00:00
<!doctype article PUBLIC "-//OASIS//DTD DocBook V3.1//EN" [
]>
<article id="index">
<artheader>
<title>D-BUS Protocol Specification</title>
2003-02-17 11:38:02 +00:00
<releaseinfo>Version 0.4</releaseinfo>
<date>17 February 2003</date>
2003-01-23 05:04:03 +00:00
<authorgroup>
<author>
<firstname>Havoc</firstname>
<surname>Pennington</surname>
<affiliation>
<address>
<email>hp@pobox.com</email>
</address>
</affiliation>
</author>
2003-02-02 17:36:46 +00:00
<author>
<firstname>Anders</firstname>
<surname>Carlsson</surname>
<affiliation>
<orgname>CodeFactory AB</orgname>
<address>
<email>andersca@codefactory.se</email>
</address>
</affiliation>
</author>
2003-01-23 05:04:03 +00:00
</authorgroup>
</artheader>
<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>
2003-02-10 03:14:29 +00:00
D-BUS is <emphasis>low-overhead</emphasis> because it uses a
2003-01-23 05:04:03 +00:00
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
does not require users to understand any complex concepts such as a
new type system or elaborate APIs. Libraries implementing D-BUS
may choose to abstract messages as "method calls" (see
2003-01-24 05:16:42 +00:00
<xref linkend="message-conventions-method">).
2003-01-23 05:04:03 +00:00
</para>
</listitem>
</itemizedlist>
</para>
<para>
The base D-BUS protocol is a peer-to-peer 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 D-BUS 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>
</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 inteprets 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>
<sect2 id="message-protocol-header-encoding">
<title>Header Encoding</title>
<para>
2003-01-31 03:49:42 +00:00
Following the mandatory fields, there are zero or more named fields (see
<xref linkend="message-protocol-header-fields">), and then nul bytes
padding the header such that its total length in bytes is a multiple of
8.
</para>
<para>
The header MUST begin with the following mandatory fields in the following
order:
<informaltable>
<tgroup cols=2>
<thead>
<row>
<entry>Size</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>1 byte</entry>
<entry>Endianness flag; ASCII 'l' for little-endian
or ASCII 'B' for big-endian.</entry>
</row>
<row>
<entry>1 byte</entry>
<entry>Bitwise OR of flags. Unknown flags
MUST be ignored. Currently-defined flags are described below.
</entry>
</row>
<row>
<entry>1 byte</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 0.
</entry>
</row>
<row>
<entry>1 byte</entry>
<entry>A nul byte, reserved for future use.
Any value for this byte MUST be accepted.
</entry>
</row>
<row>
<entry>4 bytes</entry>
<entry>An unsigned 32-bit integer in the
message's byte order, indicating the total length in bytes of
the header including named fields and any alignment padding.
MUST be a multiple of 8.
</entry>
</row>
<row>
<entry>4 bytes</entry>
<entry>An unsigned 32-bit integer in the
message's byte order, indicating the total length in bytes of
the message body.
</entry>
</row>
<row>
<entry>4 bytes</entry>
<entry>The message's serial number, a signed 32-bit integer in
the message's byte order. Applications MUST NOT reuse the same
serial number for different messages more often than 32-bit
integer wraparound. Serial numbers must be greater than
zero.
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
Flags that can appear in the second byte of the header:
2003-02-01 00:08:32 +00:00
<informaltable>
2003-01-31 03:49:42 +00:00
<tgroup cols=2>
<thead>
<row>
<entry>Hex value</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>0x1</entry>
<entry>This message is an error reply.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
2003-01-23 05:04:03 +00:00
</para>
</sect2>
<sect2 id="message-protocol-header-fields">
<title>Header Fields</title>
<para>
In addition to the required header information mentioned
in <xref linkend="message-protocol-header-encoding">,
the header may contain zero or more named
header fields. These fields are named to allow
future versions of this protocol specification to
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>
2003-02-01 00:08:32 +00:00
<para>
Header field names MUST consist of 4 non-nul bytes. The field name is
NOT nul terminated; it occupies exactly 4 bytes. Following the name,
the field MUST have a type code, and then a properly-aligned value
of that type.
See <xref linkend="message-protocol-arguments"> for a description
of how each type is encoded. If an implementation sees a header
field name that it does not understand, it MUST ignore
that field.
</para>
<para>
Here are the currently-defined named header fields:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Name</entry>
<entry>Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>name</entry>
<entry>STRING</entry>
<entry>The name of the message, such as org.freedesktop.Peer.Ping</entry>
</row>
<row>
<entry>rply</entry>
<entry>INT32</entry>
<entry>The serial number of the message this message is a reply
to. (The serial number is one of the mandatory header fields,
see <xref linkend="message-protocol-header-encoding">.)</entry>
</row>
<row>
<entry>srvc</entry>
<entry>STRING</entry>
<entry>The name of the service this message should be routed to.
Only used in combination with the message bus, see
<xref linkend="message-bus">.</entry>
</row>
<row>
<entry>sndr</entry>
<entry>STRING</entry>
2003-02-18 03:08:04 +00:00
<entry>The name of the base service that sent this message.
2003-02-01 00:08:32 +00:00
The message bus fills in this field; the field is
only meaningful in combination with the message bus.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
2003-01-31 03:49:42 +00:00
2003-01-23 05:04:03 +00:00
</sect2>
2003-01-31 03:49:42 +00:00
<sect2 id="message-protocol-header-padding">
<title>Header Alignment Padding</title>
<para>
To allow implementations to keep the header and the body in a single
buffer while keeping data types aligned, the total length of the header
must be a multiple of 8 bytes. To achieve this, the header MUST be padded
with nul bytes to align its total length on an 8-byte boundary.
The minimum number of padding bytes MUST be used. Because all possible
named fields use at least 8 bytes, implementations can distinguish
padding (which must be less than 8 bytes) from additional named fields
(which must be at least 8 bytes).
</para>
</sect2>
2003-01-23 05:04:03 +00:00
<sect2 id="message-protocol-arguments">
<title>Message Arguments</title>
<para>
The message body is made up of arguments. Each argument
is a type code, followed by the value of the argument
in a type-dependent format.
</para>
<para>
2003-02-18 04:39:05 +00:00
[FIXME perhaps we should add type BYTE with the primary
advantage being that it occupies 1 byte vs. 7 for UINT32,
or perhaps space savings aren't worth the complexity]
2003-01-24 05:16:42 +00:00
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Type name</entry>
<entry>Code</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>INVALID</entry>
<entry>0</entry>
<entry>Not a valid type code (error if it appears in a message)</entry>
</row><row>
<entry>NIL</entry>
<entry>1</entry>
<entry>Marks an "unset" or "nonexistent" argument</entry>
</row><row>
2003-02-24 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-internals.c: (_dbus_type_to_string):
* dbus/dbus-marshal.c: (_dbus_marshal_get_arg_end_pos),
(_dbus_marshal_validate_arg):
* dbus/dbus-message-builder.c: (_dbus_message_data_load):
* dbus/dbus-message.c: (dbus_message_append_args_valist),
(dbus_message_append_boolean), (dbus_message_append_boolean_array),
(dbus_message_get_args_valist), (dbus_message_iter_get_boolean),
(dbus_message_iter_get_int32), (dbus_message_iter_get_uint32),
(dbus_message_iter_get_double),
(dbus_message_iter_get_boolean_array), (message_iter_test):
* dbus/dbus-message.h:
* dbus/dbus-protocol.h:
* doc/dbus-specification.sgml:
* test/data/valid-messages/lots-of-arguments.message:
Add support for boolean and boolean array types.
2003-02-24 19:04:13 +00:00
<entry>BOOLEAN</entry>
<entry>2</entry>
2003-02-24 20:26:13 +00:00
<entry>Boolean value, 0 is FALSE and 1 is TRUE. Everything else is invalid.</entry>
2003-02-24 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-internals.c: (_dbus_type_to_string):
* dbus/dbus-marshal.c: (_dbus_marshal_get_arg_end_pos),
(_dbus_marshal_validate_arg):
* dbus/dbus-message-builder.c: (_dbus_message_data_load):
* dbus/dbus-message.c: (dbus_message_append_args_valist),
(dbus_message_append_boolean), (dbus_message_append_boolean_array),
(dbus_message_get_args_valist), (dbus_message_iter_get_boolean),
(dbus_message_iter_get_int32), (dbus_message_iter_get_uint32),
(dbus_message_iter_get_double),
(dbus_message_iter_get_boolean_array), (message_iter_test):
* dbus/dbus-message.h:
* dbus/dbus-protocol.h:
* doc/dbus-specification.sgml:
* test/data/valid-messages/lots-of-arguments.message:
Add support for boolean and boolean array types.
2003-02-24 19:04:13 +00:00
</row><row>
2003-01-24 05:16:42 +00:00
<entry>INT32</entry>
2003-02-24 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-internals.c: (_dbus_type_to_string):
* dbus/dbus-marshal.c: (_dbus_marshal_get_arg_end_pos),
(_dbus_marshal_validate_arg):
* dbus/dbus-message-builder.c: (_dbus_message_data_load):
* dbus/dbus-message.c: (dbus_message_append_args_valist),
(dbus_message_append_boolean), (dbus_message_append_boolean_array),
(dbus_message_get_args_valist), (dbus_message_iter_get_boolean),
(dbus_message_iter_get_int32), (dbus_message_iter_get_uint32),
(dbus_message_iter_get_double),
(dbus_message_iter_get_boolean_array), (message_iter_test):
* dbus/dbus-message.h:
* dbus/dbus-protocol.h:
* doc/dbus-specification.sgml:
* test/data/valid-messages/lots-of-arguments.message:
Add support for boolean and boolean array types.
2003-02-24 19:04:13 +00:00
<entry>3</entry>
2003-01-24 05:16:42 +00:00
<entry>32-bit signed integer</entry>
</row><row>
<entry>UINT32</entry>
2003-02-24 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-internals.c: (_dbus_type_to_string):
* dbus/dbus-marshal.c: (_dbus_marshal_get_arg_end_pos),
(_dbus_marshal_validate_arg):
* dbus/dbus-message-builder.c: (_dbus_message_data_load):
* dbus/dbus-message.c: (dbus_message_append_args_valist),
(dbus_message_append_boolean), (dbus_message_append_boolean_array),
(dbus_message_get_args_valist), (dbus_message_iter_get_boolean),
(dbus_message_iter_get_int32), (dbus_message_iter_get_uint32),
(dbus_message_iter_get_double),
(dbus_message_iter_get_boolean_array), (message_iter_test):
* dbus/dbus-message.h:
* dbus/dbus-protocol.h:
* doc/dbus-specification.sgml:
* test/data/valid-messages/lots-of-arguments.message:
Add support for boolean and boolean array types.
2003-02-24 19:04:13 +00:00
<entry>4</entry>
2003-01-24 05:16:42 +00:00
<entry>32-bit unsigned integer</entry>
</row><row>
<entry>DOUBLE</entry>
2003-02-24 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-internals.c: (_dbus_type_to_string):
* dbus/dbus-marshal.c: (_dbus_marshal_get_arg_end_pos),
(_dbus_marshal_validate_arg):
* dbus/dbus-message-builder.c: (_dbus_message_data_load):
* dbus/dbus-message.c: (dbus_message_append_args_valist),
(dbus_message_append_boolean), (dbus_message_append_boolean_array),
(dbus_message_get_args_valist), (dbus_message_iter_get_boolean),
(dbus_message_iter_get_int32), (dbus_message_iter_get_uint32),
(dbus_message_iter_get_double),
(dbus_message_iter_get_boolean_array), (message_iter_test):
* dbus/dbus-message.h:
* dbus/dbus-protocol.h:
* doc/dbus-specification.sgml:
* test/data/valid-messages/lots-of-arguments.message:
Add support for boolean and boolean array types.
2003-02-24 19:04:13 +00:00
<entry>5</entry>
2003-01-24 05:16:42 +00:00
<entry>IEEE 754 double</entry>
</row><row>
<entry>STRING</entry>
2003-02-24 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-internals.c: (_dbus_type_to_string):
* dbus/dbus-marshal.c: (_dbus_marshal_get_arg_end_pos),
(_dbus_marshal_validate_arg):
* dbus/dbus-message-builder.c: (_dbus_message_data_load):
* dbus/dbus-message.c: (dbus_message_append_args_valist),
(dbus_message_append_boolean), (dbus_message_append_boolean_array),
(dbus_message_get_args_valist), (dbus_message_iter_get_boolean),
(dbus_message_iter_get_int32), (dbus_message_iter_get_uint32),
(dbus_message_iter_get_double),
(dbus_message_iter_get_boolean_array), (message_iter_test):
* dbus/dbus-message.h:
* dbus/dbus-protocol.h:
* doc/dbus-specification.sgml:
* test/data/valid-messages/lots-of-arguments.message:
Add support for boolean and boolean array types.
2003-02-24 19:04:13 +00:00
<entry>6</entry>
2003-01-24 05:16:42 +00:00
<entry>UTF-8 string (<emphasis>must</emphasis> be valid UTF-8)</entry>
</row><row>
2003-02-24 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-internals.c: (_dbus_type_to_string):
* dbus/dbus-marshal.c: (_dbus_marshal_get_arg_end_pos),
(_dbus_marshal_validate_arg):
* dbus/dbus-message-builder.c: (_dbus_message_data_load):
* dbus/dbus-message.c: (dbus_message_append_args_valist),
(dbus_message_append_boolean), (dbus_message_append_boolean_array),
(dbus_message_get_args_valist), (dbus_message_iter_get_boolean),
(dbus_message_iter_get_int32), (dbus_message_iter_get_uint32),
(dbus_message_iter_get_double),
(dbus_message_iter_get_boolean_array), (message_iter_test):
* dbus/dbus-message.h:
* dbus/dbus-protocol.h:
* doc/dbus-specification.sgml:
* test/data/valid-messages/lots-of-arguments.message:
Add support for boolean and boolean array types.
2003-02-24 19:04:13 +00:00
<entry>BOOLEAN_ARRAY</entry>
<entry>7</entry>
<entry>Array of BOOLEAN</entry>
</row><row>
2003-01-24 05:16:42 +00:00
<entry>INT32_ARRAY</entry>
<entry>6</entry>
<entry>Array of INT32</entry>
</row><row>
<entry>UINT32_ARRAY</entry>
<entry>7</entry>
<entry>Array of UINT32</entry>
</row><row>
<entry>DOUBLE_ARRAY</entry>
<entry>8</entry>
<entry>Array of DOUBLE</entry>
</row><row>
<entry>BYTE_ARRAY</entry>
<entry>9</entry>
<entry>Array of bytes</entry>
</row><row>
<entry>STRING_ARRAY</entry>
<entry>10</entry>
<entry>Array of STRING</entry>
</row>
</tbody>
</tgroup>
</informaltable>
2003-01-23 05:04:03 +00:00
</para>
<para>
The types are encoded as follows:
2003-02-01 00:08:32 +00:00
<informaltable>
<tgroup cols=2>
<thead>
<row>
<entry>Type name</entry>
<entry>Encoding</entry>
</row>
</thead>
<tbody>
<row>
<entry>INVALID</entry>
<entry>Not applicable; cannot be encoded.</entry>
</row><row>
<entry>NIL</entry>
<entry>No data is encoded; the type code is followed immediately
by the type code of the next argument.</entry>
</row><row>
<entry>INT32</entry>
<entry>32-bit signed integer in the message's byte order, aligned to 4-byte boundary.</entry>
</row><row>
<entry>UINT32</entry>
<entry>32-bit unsigned integer in the message's byte order, aligned to 4-byte boundary.</entry>
</row><row>
<entry>DOUBLE</entry>
<entry>64-bit IEEE 754 double in the message's byte order, aligned to 8-byte boundary.</entry>
</row><row>
<entry>STRING</entry>
<entry>UINT32 aligned to 4-byte boundary indicating the string's
length in bytes excluding its terminating nul, followed by
string data of the given length, followed by a terminating nul
byte.
</entry>
</row><row>
<entry>INT32_ARRAY</entry>
<entry>UINT32 giving the number of values in the array,
followed by the given number of INT32 values.
</entry>
</row><row>
<entry>UINT32_ARRAY</entry>
<entry>UINT32 giving the number of values in the array,
followed by the given number of UINT32 values.
</entry>
</row><row>
<entry>DOUBLE_ARRAY</entry>
<entry>UINT32 giving the number of values in the array,
followed by the given number of DOUBLE values aligned
to 8-byte boundary.
</entry>
</row><row>
<entry>BYTE_ARRAY</entry>
<entry>UINT32 giving the number of values in the array,
followed by the given number of one-byte values.
</entry>
</row><row>
<entry>STRING_ARRAY</entry>
<entry>UINT32 giving the number of values in the array,
followed by the given number of STRING values.
</entry>
2003-03-10 Anders Carlsson <andersca@codefactory.se>
* dbus/dbus-marshal.c:
(_dbus_marshal_set_string):
Take a length argument so we can marshal the correct string
length.
(_dbus_marshal_dict), (_dbus_demarshal_dict),
(_dbus_marshal_get_arg_end_pos), (_dbus_marshal_validate_arg),
(_dbus_marshal_test):
* dbus/dbus-marshal.h:
Add support for marshalling and demarshalling dicts.
* dbus/dbus-message-builder.c: (_dbus_message_data_load):
Add support for TYPE DICT.
* dbus/dbus-message.c: (set_string_field):
Adjust header padding.
(dbus_message_append_args_valist), (dbus_message_append_dict),
(dbus_message_get_args_valist), (dbus_message_iter_get_arg_type),
(dbus_message_iter_get_dict), (_dbus_message_loader_return_buffer),
(check_message_handling), (check_have_valid_message):
* dbus/dbus-message.h:
Add functions for setting and getting dicts.
* dbus/dbus-protocol.h:
Add DBUS_TYPE_DICT.
* dbus/dbus.h:
Add dbus-dict.h
* doc/dbus-specification.sgml:
Add information about how dicts are marshalled.
* test/data/invalid-messages/dict-with-nil-value.message:
* test/data/invalid-messages/too-short-dict.message:
* test/data/valid-messages/dict-simple.message:
* test/data/valid-messages/dict.message:
Add sample messages containing dicts.
2003-03-10 00:13:55 +00:00
</row><row>
<entry>DICT</entry>
<entry>STRING_ARRAY with the keys, followed by the given
number of values encoded as type code as a byte followed by the encoded value.
</entry>
</row>
2003-02-01 00:08:32 +00:00
</tbody>
</tgroup>
</informaltable>
2003-01-23 05:04:03 +00:00
</para>
</sect2>
</sect1>
<sect1 id="auth-protocol">
<title>Authentication Protocol</title>
<para>
Before the flow of messages begins, two applications
must authenticate. A simple text protocol is used
for authentication; this protocol is a SASL profile,
and maps fairly directly from the SASL specification.
</para>
<para>
2003-02-17 11:04:18 +00:00
In examples, "C:" and "S:" indicate lines sent by the client and
server respectively.
2003-01-23 05:04:03 +00:00
</para>
2003-02-17 11:04:18 +00:00
<sect2 id="auth-protocol-overview">
<title>Protocol Overview</title>
<para>
2003-02-18 03:08:04 +00:00
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.
2003-02-17 11:04:18 +00:00
2003-02-18 03:08:04 +00:00
Commands from the client to the server are as follows:
2003-02-17 11:04:18 +00:00
2003-02-18 03:08:04 +00:00
<itemizedlist>
2003-02-17 11:04:18 +00:00
<listitem><para>AUTH [mechanism] [initial-response]</para></listitem>
<listitem><para>CANCEL</para></listitem
2003-02-18 03:08:04 +00:00
<listitem><para>BEGIN</para></listitem>
<listitem><para>DATA <data in base 64 encoding></para></listitem>
<listitem><para>ERROR [human-readable error explanation]</para></listitem>
2003-02-17 11:04:18 +00:00
</itemizedlist>
2003-02-18 03:08:04 +00:00
From server to client are as follows:
2003-02-17 11:04:18 +00:00
<itemizedlist>
<listitem><para>REJECTED <space-separated list of mechanism names></para></listitem>
<listitem><para>OK</para></listitem>
<listitem><para>DATA <data in base 64 encoding></para></listitem>
<listitem><para>ERROR</para></listitem>
</itemizedlist>
</para>
</sect2>
<sect2 id="auth-nul-byte">
<title>Special credentials-passing nul byte</title>
<para>
2003-02-18 03:08:04 +00:00
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.
2003-02-17 11:04:18 +00:00
</para>
</sect2>
<sect2 id="auth-command-auth">
<title>AUTH command</title>
2003-02-18 03:08:04 +00:00
<para>
If an AUTH command has no arguments, it is a request to list
available mechanisms. The server SHOULD respond with a REJECTED
command listing the mechanisms it understands.
</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 SHOULD send a REJECTED command listing the mechanisms
it does support.
</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, the
server should reject authentication by sending REJECTED.
</para>
<para>
If authentication succeeds after exchanging DATA commands,
an OK command should 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>
2003-02-17 11:04:18 +00:00
</sect2>
2003-02-18 03:08:04 +00:00
<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 base64-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>
</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 MUST continue as if the
command causing the ERROR had never been received.
</para>
</sect2>
<sect2 id="auth-examples">
2003-02-17 11:04:18 +00:00
<title>Authentication examples</title>
<para>
2003-02-18 03:08:04 +00:00
<figure>
2003-02-17 11:04:18 +00:00
<title>Example of successful magic cookie authentication</title>
<programlisting>
2003-02-18 03:08:04 +00:00
(MAGIC_COOKIE is a made up mechanism)
2003-01-23 05:04:03 +00:00
2003-02-18 03:08:04 +00:00
C: AUTH MAGIC_COOKIE BsAY3g4gBNo=
S: OK
C: BEGIN
2003-02-17 11:04:18 +00:00
</programlisting>
</figure>
2003-02-18 03:08:04 +00:00
<figure>
2003-02-17 11:04:18 +00:00
<title>Example of finding out mechanisms then picking one</title>
<programlisting>
2003-02-18 03:08:04 +00:00
C: AUTH
S: REJECTED KERBEROS_V4 SKEY
C: AUTH SKEY bW9yZ2Fu
S: DATA OTUgUWE1ODMwOA==
C: DATA Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: OK
C: BEGIN
2003-02-17 11:04:18 +00:00
</programlisting>
</figure>
2003-02-18 03:08:04 +00:00
<figure>
2003-02-17 11:04:18 +00:00
<title>Example of client sends unknown command then falls back to regular auth</title>
<programlisting>
2003-02-18 03:08:04 +00:00
C: FOOBAR
S: ERROR
C: AUTH MAGIC_COOKIE BsAY3g4gBNo=
S: OK
C: BEGIN
2003-02-17 11:04:18 +00:00
</programlisting>
</figure>
2003-02-18 03:08:04 +00:00
<figure>
2003-02-17 11:04:18 +00:00
<title>Example of server doesn't support initial auth mechanism</title>
<programlisting>
2003-02-18 03:08:04 +00:00
C: AUTH MAGIC_COOKIE BsAY3g4gBNo=
S: REJECTED KERBEROS_V4 SKEY
C: AUTH SKEY bW9yZ2Fu
S: DATA OTUgUWE1ODMwOA==
C: DATA Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: OK
C: BEGIN
2003-02-17 11:04:18 +00:00
</programlisting>
</figure>
2003-02-18 03:08:04 +00:00
<figure>
2003-02-17 11:04:18 +00:00
<title>Example of wrong password or the like followed by successful retry</title>
<programlisting>
2003-02-18 03:08:04 +00:00
C: AUTH MAGIC_COOKIE BsAY3g4gBNo=
S: REJECTED KERBEROS_V4 SKEY
C: AUTH SKEY bW9yZ2Fu
S: DATA OTUgUWE1ODMwOA==
C: DATA Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: REJECTED
C: AUTH SKEY bW9yZ2Fu
S: DATA OTUgUWE1ODMwOA==
C: DATA Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: OK
C: BEGIN
2003-02-17 11:04:18 +00:00
</programlisting>
</figure>
2003-02-18 03:08:04 +00:00
<figure>
2003-02-17 11:04:18 +00:00
<title>Example of skey cancelled and restarted</title>
<programlisting>
2003-02-18 03:08:04 +00:00
C: AUTH MAGIC_COOKIE BsAY3g4gBNo=
S: REJECTED KERBEROS_V4 SKEY
C: AUTH SKEY bW9yZ2Fu
S: DATA OTUgUWE1ODMwOA==
C: CANCEL
S: REJECTED
C: AUTH SKEY bW9yZ2Fu
S: DATA OTUgUWE1ODMwOA==
C: DATA Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
S: OK
C: BEGIN
2003-02-17 11:04:18 +00:00
</programlisting>
</figure>
</para>
</sect2>
2003-03-05 02:01:34 +00:00
<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>
Authentication proceeds as follows:
<itemizedlist>
<listitem>
<para>
The client sends the username it would like to authenticate
as.
</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
hex-encoded randomly-generated challenge string.
</para>
</listitem>
<listitem>
<para>
The client locates the cookie, and generates its own hex-encoded
randomly-generated challenge string. The client then
concatentates the server's hex-encoded challenge, a ":"
character, its own hex-encoded challenge, another ":" character,
and the hex-encoded cookie. It computes the SHA-1 hash of this
composite string. It sends back to the server the client's
hex-encoded challenge string, a space character, and the SHA-1
hash.
</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_global" 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.
</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>
2003-02-17 11:04:18 +00:00
</sect1>
2003-01-23 05:04:03 +00:00
<sect1 id="addresses">
<title>Server Addresses</title>
<para>
2003-02-02 17:36:46 +00:00
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.
2003-02-18 03:08:04 +00:00
[FIXME how do you escape colon, comma, and semicolon in the values of the key=value pairs?]
2003-02-02 17:36:46 +00:00
</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>
2003-02-18 03:08:04 +00:00
[FIXME clarify if attempting to connect to each is a requirement
or just a suggestion]
2003-02-02 17:36:46 +00:00
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>
<para>
2003-02-18 03:08:04 +00:00
[FIXME we need to specify in detail each transport and its possible arguments]
2003-02-02 17:36:46 +00:00
Currently, a transport over local UNIX sockets exists, a debug
transport that only works in-process and therefore can be used
for for unit testing also exists. It is possible that other
transports are added, such as a TCP/IP transport, and a
transport that works over X11.
2003-01-23 05:04:03 +00:00
</para>
</sect1>
2003-01-24 05:16:42 +00:00
<sect1 id="message-conventions">
<title>Message Conventions</title>
2003-01-23 05:04:03 +00:00
<para>
2003-01-24 05:16:42 +00:00
This section documents conventions that are not essential to D-BUS
functionality, but should generally be followed in order to simplify
programmer's lives.
2003-01-23 05:04:03 +00:00
</para>
2003-01-24 05:16:42 +00:00
<sect2 id="message-conventions-naming">
<title>Message Naming</title>
<para>
Messages are normally named in the form
"org.freedesktop.Peer.Ping", which has three
distinct components:
<variablelist>
<varlistentry>
<term>Namespace e.g. <literal>org.freedesktop</literal></term>
<listitem>
<para>
Message names have a Java-style namespace: a reversed domain
name. The components of the domain are normally lowercase.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Package or object e.g. <literal>Peer</literal></term>
<listitem>
<para>
The next part of the message name can be thought of as the name
of a singleton object, or as the name of a package of related
messages. More than one dot-separated component might be used
here. (Note that D-BUS does not define any idea of object
instances or object references.) The package or object name is
capitalized LikeThis.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Method or operation e.g. <literal>Ping</literal></term>
<listitem>
<para>
The final part of the message name is the most specific, and
should be a verb indicating an operation to be performed on the
object. The method or operation name is capitalized LikeThis.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
<para>
2003-02-01 00:08:32 +00:00
A reply to a message conventionally has the same name as the message
being replied to. When following method call conventions (see <xref
2003-02-18 03:08:04 +00:00
linkend="message-conventions-method">), this convention is mandatory,
2003-02-01 00:08:32 +00:00
because a message with multiple possible replies can't be mapped
to method call semantics without special-case code.
2003-01-24 05:16:42 +00:00
</para>
</sect2>
<sect2 id="message-conventions-method">
<title>Method Call Mapping</title>
<para>
Some implementations of D-BUS may present an API that translates object
method calls into D-BUS messages. This document does not specify in
detail how such an API should look or work. However, it does specify how
message-based protocols should be designed to be friendly to such an
API.
</para>
<para>
Remember that D-BUS does not have object references or object instances.
So when one application sends the message
<literal>org.freedesktop.Peer.Ping</literal>, it sends it to another
application, not to any kind of sub-portion of that application.
However, a convenience API used within the recipient application may
route all messages that start with
<literal>org.freedesktop.Peer</literal> to a particular object instance,
and may invoke the <literal>Ping()</literal> method on said instance in
order to handle the message. This is a convenience API based on
method calls.
</para>
<para>
A "method call" consists of a message and, optionally, a reply to that
message. The name of the "method" is the last component of the message,
for example, <literal>org.freedesktop.Peer.Ping</literal> would map to
the method <literal>Ping()</literal> on some object.
</para>
<para>
Arguments to a method may be considered "in" (processed by the
recipient of the message), or "out" (returned to the sender of the
message in the reply). "inout" arguments are both sent and received,
2003-02-01 00:08:32 +00:00
i.e. the caller passes in a value which is modified. An "inout" argument
is equivalent to an "in" argument, followed by an "out" argument.
2003-01-24 05:16:42 +00:00
</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>
2003-02-01 00:08:32 +00:00
<para>
The standard reply message MUST have the same name as the message being
replied to, and MUST set the "rply" header field to the serial
number of the message being replied to.
</para>
<para>
If an error occurs, an error reply may be sent in place of the
standard reply. Error replies can be identified by a special
header flag, see <xref linkend="message-protocol-header-encoding">.
Error replies have a name which reflects the type of
error that occurred. Error replies would generally
be mapped to exceptions in a programming language.
</para>
2003-02-18 04:43:35 +00:00
<para>
[FIXME discuss mapping of broadcast messages + matching rules
to signals and slots]
</para>
2003-01-24 05:16:42 +00:00
</sect2>
2003-01-23 05:04:03 +00:00
</sect1>
<sect1 id="standard-messages">
<title>Standard Peer-to-Peer Messages</title>
<para>
2003-01-24 05:16:42 +00:00
In the following message definitions, "method call notation" is presented
in addition to simply listing the message names and arguments. The special
type name ANY means any type other than NIL, and the special type name
ANY_OR_NIL means any valid type.
[FIXME the messages here are just made up to illustrate the
format for defining them]
2003-01-23 05:04:03 +00:00
</para>
<sect2 id="standard-messages-ping">
2003-01-24 05:16:42 +00:00
<title><literal>org.freedesktop.Peer.Ping</literal></title>
<para>
As a method:
<programlisting>
void Ping ()
</programlisting>
</para>
<para>
On receipt of the message <literal>org.freedesktop.Peer.Ping</literal>,
an application should reply with
2003-02-01 00:08:32 +00:00
<literal>org.freedesktop.Peer.Ping</literal>. Neither the
2003-01-24 05:16:42 +00:00
message nor its reply have any arguments.
2003-02-18 03:08:04 +00:00
[FIXME the messages here are just made up to illustrate the
format for defining them]
2003-01-24 05:16:42 +00:00
</para>
</sect2>
<sect2 id="standard-messages-get-props">
<title><literal>org.freedesktop.Props.Get</literal></title>
<para>
As a method:
<programlisting>
ANY_OR_NIL Get (in STRING property_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 property to get</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>ANY_OR_NIL</entry>
<entry>The value of the property. The type depends on the property.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
2003-01-23 05:04:03 +00:00
<para>
2003-01-24 05:16:42 +00:00
2003-02-18 03:08:04 +00:00
[FIXME the messages here are just made up to illustrate the
format for defining them]
2003-01-23 05:04:03 +00:00
</para>
</sect2>
</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 send and receive messages from
the message bus, as in the peer-to-peer case.
</para>
<para>
The message bus keeps track of a set of
<firstterm>services</firstterm>. A service is simply a name, such
as <literal>com.yoyodyne.Screensaver</literal>, which can be
<firstterm>owned</firstterm> by one of the connected applications.
The message bus itself always owns the special service
<literal>org.freedesktop.DBus</literal>.
</para>
<para>
Messages may have a <literal>srvc</literal> field (see <xref
2003-02-18 03:08:04 +00:00
linkend="message-protocol-header-fields">). When the message bus
receives a message, if the <literal>srvc</literal> field is absent, the
message is taken to be a standard peer-to-peer message and interpreted
by the message bus itself. For example, sending
2003-01-23 05:04:03 +00:00
an <literal>org.freedesktop.Peer.Ping</literal> message with no
<literal>srvc</literal> will cause the message bus itself to reply
to the ping immediately; the message bus would never make
this message visible to other applications.
</para>
<para>
If the <literal>srvc</literal> field is present, then it indicates a
request for the message bus to route the message. In the usual case,
messages are routed to the owner of the named service.
Messages may also be <firstterm>broadcast</firstterm>
by sending them to the special service
2003-02-18 03:08:04 +00:00
<literal>org.freedesktop.Broadcast</literal>. Broadcast messages are
sent to all applications with <firstterm>message matching
rules</firstterm> that match the message.
2003-01-23 05:04:03 +00:00
</para>
<para>
Continuing the <literal>org.freedesktop.Peer.Ping</literal> example, if
the ping message were sent with a <literal>srvc</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. If
<literal>org.freedesktop.Peer.Ping</literal> were sent to
<literal>org.freedesktop.Broadcast</literal>, then multiple applications
might receive the ping, and all would normally reply to it.
</para>
</sect2>
2003-02-17 09:59:23 +00:00
2003-02-18 03:08:04 +00:00
<sect2 id="message-bus-services">
<title>Message Bus Services</title>
2003-02-17 09:59:23 +00:00
<para>
2003-02-18 03:08:04 +00:00
A service is a name that identifies a certain application. Each
application connected to the message bus has at least one service name
assigned at connection time and returned in response to the
<literal>org.freedesktop.DBus.Hello</literal> message.
This automatically-assigned service name is called
the application's <firstterm>base service</firstterm>.
Base service names are unique and MUST never be reused for two different
applications.
2003-02-17 09:59:23 +00:00
</para>
<para>
2003-02-18 03:08:04 +00:00
[FIXME I think we should define the format of the base service name,
and specify that a regular service name can never be in that
format; this allows us to categorically prevent "spoofing" - for
example perhaps the base service name starts with a certain
character that no real service name can start with]
2003-02-17 09:59:23 +00:00
</para>
<para>
2003-02-18 03:08:04 +00:00
An application can request additional service names to be associated
with it using the
2003-02-17 09:59:23 +00:00
<literal>org.freedesktop.DBus.AcquireService</literal>
2003-02-18 03:08:04 +00:00
message. [FIXME what service names are allowed; ASCII or unicode;
length limit; etc.]
2003-02-17 09:59:23 +00:00
</para>
<para>
2003-02-18 03:08:04 +00:00
[FIXME this needs more detail, and should move the service-related message
descriptions up into this section perhaps]
2003-02-17 09:59:23 +00:00
Service ownership handling can be specified in the flags part
of the <literal>org.freedesktop.DBus.AcquireService</literal>
2003-02-18 03:08:04 +00:00
message. If an application specifies the
DBUS_SERVICE_FLAGS_PROHIBIT_REPLACEMENT flag, then all applications
2003-02-17 09:59:23 +00:00
trying to acquire the service will be put in a queue. When the
primary owner disconnects from the bus or removes ownership
2003-02-18 03:08:04 +00:00
from the service, the next application in the queue will be the
2003-02-17 09:59:23 +00:00
primary owner. If the DBUS_SERVICE_FLAGS_PROHIBIT_REPLACEMENT
flag is not specified, then the primary owner will lose
2003-02-18 03:08:04 +00:00
ownership whenever another application requests ownership of the
2003-02-17 09:59:23 +00:00
service.
2003-01-23 05:04:03 +00:00
</para>
2003-03-04 23:02:40 +00:00
<para>
When a client disconnects from the bus, all the services that
the clients own are deleted, or in the case of a service that
prohibits replacement, ownership is transferred to the next
client in the queue, if any.
</para>
2003-01-23 05:04:03 +00:00
</sect2>
2003-02-18 03:08:04 +00:00
<sect2 id="message-bus-routing">
<title>Message Bus Message Routing</title>
<para>
When a message is received by the message bus, the message's
<literal>sndr</literal> header field MUST be set to the base service of
the application which sent the message. If the service already has
a <literal>sndr</literal> field, the pre-existing field is replaced.
This rule means that a replies are always sent to the base service name,
i.e. to the same application that sent the message being replied to.
</para>
<para>
[FIXME go into detail about broadcast, multicast, unicast, etc.]
</para>
</sect2>
2003-01-23 05:04:03 +00:00
<sect2 id="message-bus-activation">
<title>Message Bus Service Activation</title>
<para>
2003-02-18 03:08:04 +00:00
<firstterm>Activation</firstterm> means to locate a service
owner for a service that is currently unowned. For now, it
means to launch an executable that will take ownership of
a particular service.
2003-02-17 09:59:23 +00:00
</para>
<para>
2003-02-18 03:08:04 +00:00
To find an executable corresponding to a particular service, the bus
daemon looks for <firstterm>service description files</firstterm>.
Service description files define a mapping from service names to
executables. Different kinds of message bus will look for these files
in different places, see <xref linkend="message-bus-types">.
</para>
<para>
2003-03-04 23:02:40 +00:00
[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.
2003-02-17 09:59:23 +00:00
<figure>
<title>Example service description file</title>
<programlisting>
# Sample service description file
[D-BUS Service]
Name=org.gnome.ConfigurationDatabase
Exec=gconfd-2
</programlisting>
</figure>
</para>
<para>
2003-03-04 23:02:40 +00:00
When an application requests a service to be activated, the
bus daemon tries to find it in the list of activation
entries. 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?]
2003-02-17 09:59:23 +00:00
</para>
<para>
The executable launched will have the environment variable
2003-02-18 03:08:04 +00:00
<literal>DBUS_BUS_ADDRESS</literal> set to the address of the
message bus so it can connect and register the appropriate services.
2003-01-23 05:04:03 +00:00
</para>
2003-03-04 23:02:40 +00:00
<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>
2003-01-23 05:04:03 +00:00
</sect2>
2003-02-18 03:08:04 +00:00
<sect2 id="message-bus-types">
<title>Standard Message Bus Instances</title>
2003-01-23 05:04:03 +00:00
<para>
Two standard message bus instances are defined here, along with how
2003-02-18 03:08:04 +00:00
to locate them and where their service files live.
2003-01-23 05:04:03 +00:00
</para>
2003-02-18 03:08:04 +00:00
<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. [specify
how to find the address of the login session message bus via
environment variable and/or X 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.
[specify how to find the address of the system message bus]
</para>
<para>
[FIXME specify location of system bus .service files]
</para>
</sect3>
</sect2>
<sect2 id="message-bus-messages">
<title>Message Bus Messages</title>
2003-01-23 05:04:03 +00:00
<para>
2003-02-18 03:08:04 +00:00
The special message bus service <literal>org.freedesktop.DBus</literal>
responds to a number of messages, allowing applications to
interact with the message bus.
2003-01-23 05:04:03 +00:00
</para>
2003-02-18 03:08:04 +00:00
<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>Name of the service assigned to the application</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 service. If an application tries to send
a message to another application, or a message to the message bus
service that isn't the
<literal>org.freedesktop.DBus.Hello</literal> message, it will
be disconnected from the bus.
</para>
<para>
The reply message contains the name of the application's base service.
</para>
</sect3>
<sect3 id="bus-messages-list-services">
<title><literal>org.freedesktop.DBus.ListServices</literal></title>
<para>
As a method:
<programlisting>
STRING_ARRAY ListServices ()
</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_ARRAY</entry>
<entry>Array of strings where each string is the name of a service</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
Returns a list of all existing services registered with the message bus.
</para>
</sect3>
<sect3 id="bus-messages-service-exists">
<title><literal>org.freedesktop.DBus.ServiceExists</literal></title>
<para>
As a method:
<programlisting>
UINT32 ServiceExists (in STRING service_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 service</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, 1 if the service exists and 0 otherwise</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
Checks if a service with a specified name exists.
</para>
</sect3>
<sect3 id="bus-messages-acquire-service">
<title><literal>org.freedesktop.DBus.AcquireService</literal></title>
<para>
As a method:
<programlisting>
UINT32 AcquireService (in STRING service_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 service</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>
Tries to become owner of a specific service. The flags
specified can be the following values logically ORed together:
<informaltable>
<tgroup cols=3>
<thead>
<row>
<entry>Identifier</entry>
<entry>Value</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>DBUS_SERVICE_FLAGS_PROHIBIT_REPLACEMENT</entry>
<entry>0x1</entry>
<entry>
If the application succeeds in being the owner of the specified service,
then ownership of the service can't be transferred until the service
disconnects. If this flag is not set, then any application trying to become
the owner of the service will succeed and the previous owner will be
sent a <literal>org.freedesktop.DBus.ServiceLost</literal> message.
</entry>
</row>
<row>
<entry>DBUS_SERVICE_FLAGS_REPLACE_EXISTING</entry>
<entry>0x2</entry>
<entry>Only become the owner of the service if there is no current owner.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
[FIXME if it's one of the following values, why are the values
done as flags instead of just 0, 1, 2, 3, 4]
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_SERVICE_REPLY_PRIMARY_OWNER</entry>
<entry>0x1</entry>
<entry>The application is now the primary owner of the service.</entry>
</row>
<row>
<entry>DBUS_SERVICE_REPLY_IN_QUEUE</entry>
<entry>0x2</entry>
<entry>The service already has an owner which do not want to give up ownership and therefore the application has been put in a queue.</entry>
</row>
<row>
<entry>DBUS_SERVICE_REPLY_SERVICE_EXISTS</entry>
<entry>0x4</entry>
<entry>The service does already have a primary owner, and DBUS_SERVICE_FLAG_REPLACE_EXISTING was not specified when trying to acquire the service.</entry>
</row>
<row>
<entry>DBUS_SERVICE_REPLY_ALREADY_OWNER</entry>
<entry>0x8</entry>
<entry>The application trying to request ownership of the service is already the owner of it.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
</sect3>
<sect3 id="bus-messages-service-acquired">
<title><literal>org.freedesktop.DBus.ServiceAcquired</literal></title>
<para>
As a method:
<programlisting>
ServiceAcquired (in STRING service_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 service</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
<entry>Flags</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
This message is sent to a specific application when it becomes the
primary owner of a service.
</para>
</sect3>
<sect3 id="bus-messages-service-lost">
<title><literal>org.freedesktop.DBus.ServiceLost</literal></title>
<para>
As a method:
<programlisting>
ServiceLost (in STRING service_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 service</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
<entry>Flags</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
This message is sent to a specific application when it loses primary
ownership of a service.
[FIXME instead of ServiceLost/ServiceCreated going only to
a specific app, why not just OwnerChanged that covers both
lost and created and changed owner and deleted]
</para>
</sect3>
<sect3 id="bus-messages-service-created">
<title><literal>org.freedesktop.DBus.ServiceCreated</literal></title>
<para>
As a method:
<programlisting>
ServiceCreated (in STRING service_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 service</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
<entry>Flags</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
This message is broadcast to all applications when a service has been
successfully registered on the message bus.
</para>
</sect3>
<sect3 id="bus-messages-service-deleted">
<title><literal>org.freedesktop.DBus.ServiceDeleted</literal></title>
<para>
As a method:
<programlisting>
ServiceDeleted (in STRING service_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 service</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
<entry>Flags</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
This message is broadcast to all applications when a service has been
deleted from the message bus.
</para>
</sect3>
<sect3 id="bus-messages-activate-service">
<title><literal>org.freedesktop.DBus.ActivateService</literal></title>
<para>
As a method:
<programlisting>
2003-03-16 22:29:14 +00:00
UINT32 ActivateService (in STRING service_name, in UINT32 flags)
2003-02-18 03:08:04 +00:00
</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 activate</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
<entry>Flags (currently not used)</entry>
</row>
</tbody>
</tgroup>
</informaltable>
2003-03-16 22:29:14 +00:00
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>Result code; DBUS_ACTIVATION_REPLY_ACTIVATED if
the service was activated successfutly or
DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE if the service is
already active.</entry>
</row>
</tbody>
</tgroup>
</informaltable>
2003-02-18 03:08:04 +00:00
</para>
<para>
Tries to launch the executable associated with a service. For more information, see <xref linkend="message-bus-activation">.
[FIXME need semantics in much more detail here; for example,
if I activate a service then send it a message, is the message
queued for the new service or is there a race]
</para>
</sect3>
2003-01-23 05:04:03 +00:00
</sect2>
2003-02-18 03:08:04 +00:00
2003-01-23 05:04:03 +00:00
</sect1>
2003-02-17 09:59:23 +00:00
<!--
2003-01-23 05:04:03 +00:00
<appendix id="implementation-notes">
<title>Implementation notes</title>
<sect1 id="implementation-notes-subsection">
<title></title>
<para>
</para>
</sect1>
</appendix>
2003-02-17 09:59:23 +00:00
-->
2003-01-23 05:04:03 +00:00
<glossary><title>Glossary</title>
<para>
This glossary defines some of the terms used in this specification.
</para>
2003-02-18 03:08:04 +00:00
<glossentry id="term-activation"><glossterm>Activation</glossterm>
<glossdef>
<para>
The process of creating an owner for a particular service,
typically by launching an executable.
</para>
</glossdef>
</glossentry>
<glossentry id="term-base-service"><glossterm>Base Service</glossterm>
<glossdef>
<para>
The special service automatically assigned to an application by the
message bus. This service may never change owner, and the service
name will be unique (never reused during the lifetime of the
message bus).
</para>
</glossdef>
</glossentry>
2003-01-23 05:04:03 +00:00
<glossentry id="term-broadcast"><glossterm>Broadcast</glossterm>
<glossdef>
<para>
A message sent to the special <literal>org.freedesktop.Broadcast</literal>
service; the message bus will forward the broadcast message
2003-02-18 03:08:04 +00:00
to all applications that have expressed interest in it.
2003-01-23 05:04:03 +00:00
</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 broadcasts messages between a group of applications
connected to the message bus. It also manages
<firstterm>services</firstterm>.
</para>
</glossdef>
</glossentry>
<glossentry id="term-service"><glossterm>Service</glossterm>
<glossdef>
<para>
A service is simply a named application that other
applications can refer to. For example, the
hypothetical <literal>com.yoyodyne.Screensaver</literal>
service might accept messages that affect
a screensaver from Yoyodyne Corporation.
An application is said to <firstterm>own</firstterm>
a service if the message bus has associated the
application with the service name.
</para>
</glossdef>
</glossentry>
2003-02-18 03:08:04 +00:00
<glossentry id="term-service-description-files"><glossterm>Service Description Files</glossterm>
<glossdef>
<para>
".service files" tell the bus how to activate a particular service.
See <xref linkend="term-activation">
</para>
</glossdef>
</glossentry>
2003-01-23 05:04:03 +00:00
</glossary>
</article>