<article id="index">
<articleinfo>
<title>D-BUS Specification</title>
- <releaseinfo>Version 0.8</releaseinfo>
- <date>06 September 2003</date>
+ <releaseinfo>Version 0.11</releaseinfo>
+ <date>6 February 2005</date>
<authorgroup>
<author>
<firstname>Havoc</firstname>
</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.
+ 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 interoperablity, for example a file
+ 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. 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>
+
</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
<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.
+ <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>
+ 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>
- 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.
+ 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>
- 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>Type of message. Unknown types MUST be ignored.
- Currently-defined types are described below.
- </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>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, an unsigned 32-bit integer in
- the message's byte order. The serial number is a cookie used to
- identify message replies; thus all outstanding unreplied-to messages
- from the same connection MUST have a different serial number.
- Zero is not a valid serial number, but all other numbers are
- allowed.
- </entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
+ 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>
- Types that can appear in the second byte of the header:
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Conventional name</entry>
- <entry>Decimal value</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>INVALID</entry>
- <entry>0</entry>
- <entry>This is an invalid type, if seen in a message
- the connection should be dropped immediately.</entry>
- </row>
- <row>
- <entry>METHOD_CALL</entry>
- <entry>1</entry>
- <entry>Method call.</entry>
- </row>
- <row>
- <entry>METHOD_RETURN</entry>
- <entry>2</entry>
- <entry>Method reply with returned data.</entry>
- </row>
- <row>
- <entry>ERROR</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>SIGNAL</entry>
- <entry>4</entry>
- <entry>Signal emission.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
+ 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>
- 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>NO_REPLY_EXPECTED</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.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
+ <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>
+ <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>
- </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. 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.
+ 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>
- Header field names MUST consist of a single byte, possible values
- of which are defined below. Following the name, the field MUST have
- a type code represented as a single unsigned byte, 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.
+ <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>
- Here are the currently-defined named header fields:
- <informaltable>
- <tgroup cols="3">
- <thead>
- <row>
- <entry>Conventional Name</entry>
- <entry>Decimal Value</entry>
- <entry>Type</entry>
- <entry>Description</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry>INVALID</entry>
- <entry>0</entry>
- <entry>INVALID</entry>
- <entry>Not a valid field name (error if it appears in a message)</entry>
- </row>
- <row>
- <entry>PATH</entry>
- <entry>1</entry>
- <entry>OBJECT_PATH</entry>
- <entry>The object to send the message to; objects are identified by
- a path, "/foo/bar"</entry>
- </row>
- <row>
- <entry>INTERFACE</entry>
- <entry>2</entry>
- <entry>STRING</entry>
- <entry>The interface to invoke a method call on, or
- that a signal is emitted from. e.g. "org.freedesktop.Introspectable"</entry>
- </row>
- <row>
- <entry>MEMBER</entry>
- <entry>3</entry>
- <entry>STRING</entry>
- <entry>The member, either the method name or signal name.
- e.g. "Frobate"</entry>
- </row>
- <row>
- <entry>ERROR_NAME</entry>
- <entry>4</entry>
- <entry>STRING</entry>
- <entry>The name of the error that occurred, for errors</entry>
- </row>
- <row>
- <entry>REPLY_SERIAL</entry>
- <entry>5</entry>
- <entry>UINT32</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>SERVICE</entry>
- <entry>6</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>SENDER_SERVICE</entry>
- <entry>7</entry>
- <entry>STRING</entry>
- <entry>Sender service. The name of the base service that sent
- this message. The message bus fills in this field; the field is
- only meaningful in combination with the message bus.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
+ 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>
- </sect2>
- <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 zero is an
- invalid field name, implementations can distinguish padding (which must be
- zero initialized) from additional named fields.
+ 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>
- </sect2>
- <sect2 id="message-protocol-arguments">
- <title>Message Arguments</title>
<para>
- The message body is made up of arguments. Each argument is a type code,
- represented by a single unsigned byte, followed by the aligned value of
- the argument in a type-dependent format. Alignment padding between the
- typecode and the value is initialized to zero.
+ 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>Type name</entry>
+ <entry>Conventional Name</entry>
<entry>Code</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
- <entry>INVALID</entry>
+ <entry><literal>INVALID</literal></entry>
<entry>0 (ASCII NUL)</entry>
- <entry>Not a valid type code (error if it appears in a message)</entry>
- </row><row>
- <entry>NIL</entry>
- <entry>118 (ASCII 'v') </entry>
- <entry>Marks a "void"/"unset"/"nonexistent"/"null" argument</entry>
+ <entry>Not a valid type code, used to terminate signatures</entry>
</row><row>
- <entry>BYTE</entry>
+ <entry><literal>BYTE</literal></entry>
<entry>121 (ASCII 'y')</entry>
<entry>8-bit unsigned integer</entry>
</row><row>
- <entry>BOOLEAN</entry>
+ <entry><literal>BOOLEAN</literal></entry>
<entry>98 (ASCII 'b')</entry>
- <entry>Boolean value, 0 is FALSE and 1 is TRUE. Everything else is invalid.</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>INT32</entry>
+ <entry><literal>INT32</literal></entry>
<entry>105 (ASCII 'i')</entry>
<entry>32-bit signed integer</entry>
</row><row>
- <entry>UINT32</entry>
+ <entry><literal>UINT32</literal></entry>
<entry>117 (ASCII 'u')</entry>
<entry>32-bit unsigned integer</entry>
</row><row>
- <entry>INT64</entry>
+ <entry><literal>INT64</literal></entry>
<entry>120 (ASCII 'x')</entry>
<entry>64-bit signed integer</entry>
</row><row>
- <entry>UINT64</entry>
+ <entry><literal>UINT64</literal></entry>
<entry>116 (ASCII 't')</entry>
<entry>64-bit unsigned integer</entry>
</row><row>
- <entry>DOUBLE</entry>
+ <entry><literal>DOUBLE</literal></entry>
<entry>100 (ASCII 'd')</entry>
<entry>IEEE 754 double</entry>
</row><row>
- <entry>STRING</entry>
+ <entry><literal>STRING</literal></entry>
<entry>115 (ASCII 's')</entry>
- <entry>UTF-8 string (<emphasis>must</emphasis> be valid UTF-8). Must be zero terminated. </entry>
+ <entry>UTF-8 string (<emphasis>must</emphasis> be valid UTF-8). Must be nul terminated.</entry>
</row><row>
- <entry>CUSTOM</entry>
- <entry>99 (ASCII 'c')</entry>
- <entry>A named byte array, used for custom types</entry>
- </row><row>
- <entry>ARRAY</entry>
+ <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>DICT</entry>
- <entry>109 (ASCII 'm')</entry>
- <entry>A dictionary of key/value pairs</entry>
+ <entry><literal>STRUCT</literal></entry>
+ <entry>114 (ASCII 'r'), 40 (ASCII '('), 41 (ASCII ')')</entry>
+ <entry>Struct</entry>
</row><row>
- <entry>OBJECT_PATH</entry>
- <entry>111 (ASCII 'o')</entry>
- <entry>Name of an object</entry>
+ <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>
- The types are encoded as follows:
+ 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="2">
+ <tgroup cols="3">
<thead>
<row>
- <entry>Type name</entry>
+ <entry>Conventional Name</entry>
<entry>Encoding</entry>
+ <entry>Alignment</entry>
</row>
</thead>
<tbody>
<row>
- <entry>INVALID</entry>
- <entry>Not applicable; cannot be encoded.</entry>
+ <entry><literal>INVALID</literal></entry>
+ <entry>Not applicable; cannot be marshaled.</entry>
+ <entry>N/A</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>
+ <entry><literal>BYTE</literal></entry>
+ <entry>A single 8-bit byte.</entry>
+ <entry>1</entry>
</row><row>
- <entry>BYTE</entry>
- <entry>A byte.</entry>
+ <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>BOOLEAN</entry>
- <entry>A byte, with valid values 0 and 1.</entry>
+ <entry><literal>INT16</literal></entry>
+ <entry>16-bit signed integer in the message's byte order.</entry>
+ <entry>2</entry>
</row><row>
- <entry>INT32</entry>
- <entry>32-bit signed integer in the message's byte order, aligned to 4-byte boundary.</entry>
+ <entry><literal>UINT16</literal></entry>
+ <entry>16-bit unsigned integer in the message's byte order.</entry>
+ <entry>2</entry>
</row><row>
- <entry>UINT32</entry>
- <entry>32-bit unsigned integer in the message's byte order, aligned to 4-byte boundary.</entry>
+ <entry><literal>INT32</literal></entry>
+ <entry>32-bit signed integer in the message's byte order.</entry>
+ <entry>4</entry>
</row><row>
- <entry>INT64</entry>
- <entry>64-bit signed integer in the message's byte order, aligned to 8-byte boundary.</entry>
+ <entry><literal>UINT32</literal></entry>
+ <entry>32-bit unsigned integer in the message's byte order.</entry>
+ <entry>4</entry>
</row><row>
- <entry>UINT64</entry>
- <entry>64-bit unsigned integer in the message's byte order, aligned to 8-byte boundary.</entry>
+ <entry><literal>INT64</literal></entry>
+ <entry>64-bit signed integer in the message's byte order.</entry>
+ <entry>8</entry>
</row><row>
- <entry>DOUBLE</entry>
- <entry>64-bit IEEE 754 double in the message's byte order, aligned to 8-byte boundary.</entry>
+ <entry><literal>UINT64</literal></entry>
+ <entry>64-bit unsigned integer in the message's byte order.</entry>
+ <entry>8</entry>
</row><row>
- <entry>STRING</entry>
- <entry>UINT32 aligned to 4-byte boundary indicating the string's
+ <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
string data of the given length, followed by a terminating nul
byte.
</entry>
+ <entry>
+ 4 (for the length)
+ </entry>
</row><row>
- <entry>CUSTOM</entry>
- <entry>A string (encoded as the STRING type above) giving the
- name of the type followed by an UINT32 aligned to 4-byte boundary
- indicating the data length in bytes, followed by the data.
- The string has some restrictions on its content, see
- <xref linkend="message-protocol-names"/>.
+ <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>ARRAY</entry>
- <entry>A sequence of bytes giving the element type of the array, terminated
- by a type different from ARRAY (just one byte for one-dimensional arrays, but
- larger for multi-dimensional arrays), followed by an UINT32 (aligned to 4 bytes)
- giving the length of the array data in bytes. This is followed by each array entry
- encoded the way it would normally be encoded, except arrays, which are encoded
- without the type information, since that is already declared above. Arrays containing
- NIL are not allowed.
+ <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>DICT</entry>
- <entry>UINT32 giving the length of the dictionary data in bytes.
- This is followed by a number of keyname/value pairs, where the
- keyname is encoded as a STRING above, and the value is encoded
- as a byte with typecode and how that type normally would be encoded
- alone.
+ <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" is OK, "ii" is not.
+ </entry>
+ <entry>
+ 1 (alignment of the signature)
</entry>
</row><row>
- <entry>OBJECT_PATH</entry>
- <entry>Encoded as if it were a STRING.
+ <entry><literal>DICT_ENTRY</literal></entry>
+ <entry>
+ Identical to STRUCT.
+ </entry>
+ <entry>
+ 8
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
- </sect2>
-
- <sect2 id="message-protocol-names">
- <title>Valid names</title>
- <para>
- The various names in D-BUS messages have some restrictions.
- </para>
- <sect3 id="message-protocol-names-interface">
- <title>Interface names</title>
+
+ <sect3 id="message-protocol-marshaling-object-path">
+ <title>Valid Object Paths</title>
+
<para>
- Interfaces have names with type STRING, meaning that
- they must be valid UTF-8. However, there are also some
- additional restrictions that apply to interface names
- specifically:
+ 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>They are composed of 1 or more elements separated by
- a period ('.') character. All elements must contain at least
- one character.
- </para>
+ <listitem>
+ <para>
+ The path may be of any length.
+ </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>
+ <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>
-
- <listitem><para>They must contain at least one '.' (period)
- character (and thus at least two elements).
- </para></listitem>
-
- <listitem><para>They must not begin with a '.' (period) character.</para></listitem>
- <listitem><para>They must not exceed 256 bytes in length.</para></listitem>
- <listitem><para>They must be at least 1 byte in length.</para></listitem>
- </itemizedlist>
- </para>
- </sect3>
- <sect3 id="message-protocol-names-service">
- <title>Service names</title>
- <para>
- Service names have the same restrictions as interface names, with a
- special exception for base services. A base service name's first
- element must start with a colon (':') character. After the colon, any
- characters in the range "[A-Z][a-z][0-9]_" may appear. Elements after
- the first must follow the usual rules, except that they may start with
- a digit. Service names not starting with a colon have none of these
- exceptions and follow the same rules as interface names.
- </para>
- </sect3>
- <sect3 id="message-protocol-names-method">
- <title>Method names</title>
- <para>
- Method 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 256 bytes in length</para></listitem>
- <listitem><para>Must be at least 1 byte in length</para></listitem>
</itemizedlist>
</para>
- </sect3>
- <sect3 id="message-protocol-names-path">
- <title>Path names</title>
- <para>
- A path (type OBJECT_PATH) must begin with an ASCII '/' (slash)
- character. Paths may not end with a slash character unless the path is
- the one-byte string "/". Two slash characters may not appear adjacent
- to one another (the empty string is not a valid "subdirectory"). Paths
- may not exceed 256 bytes in length.
- </para>
- </sect3>
- <sect3 id="message-protocol-names-error">
- <title>Error names</title>
- <para>
- Error names have the same restrictions as interface names.
- </para>
- </sect3>
- <sect3 id="message-protocol-names-custom">
- <title>Custom types</title>
- <para>
- Custom type names for values of type CUSTOM follow the same
- restrictions as interface names.
- </para>
- </sect3>
- </sect2>
-
- <sect2 id="message-protocol-types">
- <title>Message types</title>
- <para>
- Each of the message types (METHOD_CALL, METHOD_RETURN, ERROR, and
- SIGNAL) has its own expected usage conventions and header fields.
- </para>
- <sect3 id="message-protocol-types-method">
- <title>Method Calls, Returns, and Errors</title>
- <para>
- Some messages invoke an operation on a remote object. These are
- called method call messages and have the type tag METHOD_CALL. Such
- messages map naturally to methods on objects in a typical program.
- </para>
- <para>
- A method call message is expected to have a MEMBER header field
- indicating the name of the method. Optionally, the message has an
- INTERFACE field giving the interface the method is a part of. In the
- absence of an INTERFACE 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 should not require an interface field.
- </para>
- <para>
- Method call messages also include a PATH field indicating the
- object to invoke the method on. If the call is passing through
- a message bus, the message will also have a SERVICE field giving
- the service to receive the message.
- </para>
- <para>
- When an application handles a method call message, it is expected to
- return a reply. The reply is identified by a REPLY_SERIAL header field
- indicating the serial number of the METHOD_CALL being replied to. The
- reply can have one of two types; either METHOD_RETURN or ERROR.
- </para>
- <para>
- If the reply has type METHOD_RETURN, the arguments to the reply message
- are the return value(s) or "out parameters" of the method call.
- If the reply has type ERROR, 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 METHOD_RETURN
- reply is expected, so the caller will know the method
- was successfully processed.
- </para>
- <para>
- The METHOD_RETURN or ERROR reply message MUST have the REPLY_SERIAL
- header field. If this field is missing, it should be treated as
- a corrupt message.
- </para>
- <para>
- If a METHOD_CALL message has the flag NO_REPLY_EXPECTED,
- 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 METHOD_RETURN or ERROR).
- However, it is also acceptable to ignore the NO_REPLY_EXPECTED
- flag and reply anyway.
- </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 METHOD_CALL), or "out" (which implies
- returned in the METHOD_RETURN). 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>
- </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 SIGNAL.
- It must have three header fields: PATH giving the object
- the signal was emitted from, plus INTERFACE and MEMBER giving
- the fully-qualified name of the signal.
- </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.ActivateService (in STRING service_name, in UINT32 flags,
- out UINT32 resultcode)
- </programlisting>
- This means INTERFACE = org.freedesktop.DBus, MEMBER = ActivateService,
- METHOD_CALL arguments are STRING and UINT32, METHOD_RETURN argument
- is UINT32. Remember that the MEMBER 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::ActivateService (const char *service_name,
- unsigned int flags);
- </programlisting>
- or equally valid, the return value could be done as an argument:
- <programlisting>
- void org::freedesktop::DBus::ActivateService (const char *service_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.ServiceLost (STRING service_name)
- </programlisting>
- Signals don't specify "in" vs. "out" because only
- a single direction is possible.
- </para>
- <para>
- In this ad hoc notation, the special type name ANY means any type
- other than NIL, and the special type name ANY_OR_NIL means any valid
- type.
- </para>
+
+ <sect3 id="message-protocol-marshaling-signature">
+ <title>Valid Signatures</title>
<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.
+ 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>
- </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 base 64 encoding></para></listitem>
- <listitem><para>ERROR [human-readable error explanation]</para></listitem>
- </itemizedlist>
+ <sect2 id="message-protocol-messages">
+ <title>Message Format</title>
- From server to client are as follows:
-
- <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>
- 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.
+ 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>
- A nul byte in any context other than the initial byte is an error;
- the protocol is ASCII-only.
+ 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 credentials sent along with the nul byte may be used with the
- SASL mechanism EXTERNAL.
+ The message body need not end on an 8-byte boundary.
</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 SHOULD respond with a REJECTED
- command listing the mechanisms it understands.
+ 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>
- 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.
+ 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>
- 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.
+ 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 0.
+ FIXME this field is stupid and pointless to put in
+ every message.
+ </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.
+ </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>
- 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.
+ <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>
- 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.
+ 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.
+ </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.
+ </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="auth-command-cancel">
- <title>CANCEL Command</title>
+
+ <sect2 id="message-protocol-names">
+ <title>Valid Names</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.
+ The various names in D-BUS messages have some restrictions.
</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.
+ 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>
- Some SASL mechanisms support sending an "empty string";
- FIXME we need some way to do this.
+ 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.
+ </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 idiosyncracy 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>
+ 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_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>
- <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>
+ </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. This globally unique ID must
+ be created by filling the first 4 bytes with a 32-bit UNIX time since the
+ epoch, and the remaining 12 bytes with random bytes. If present, the GUID
+ may be used to distinguish one server from another. A server should use a
+ different GUID 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 GUIDs to distinguish
+ the kinds of connection.
+ </para>
+
+ <para>
+ The intent of the GUID 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.
+ </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>
- 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.
+ 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 i
+ do not show up in the file system.
</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.
+ When a socket is opened by the D-Bus library it truncates the path
+ name right befor 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>
- <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>
+ </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="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 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.
+ The <literal>org.freedesktop.DBus.Peer</literal> interface
+ has one method:
+ <programlisting>
+ org.freedesktop.DBus.Peer.Ping ()
+ </programlisting>
</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.
+ 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 should simply handle this method on behalf of
+ all objects, though it doesn't yet. (The point is, you're really pinging
+ the peer process, not a specific object.)
</para>
</sect2>
- <sect2 id="auth-command-error">
- <title>ERROR Command</title>
+
+ <sect2 id="standard-interfaces-introspectable">
+ <title><literal>org.freedesktop.DBus.Introspectable</literal></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.
+ This interface has one method:
+ <programlisting>
+ org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data)
+ </programlisting>
</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.
+ 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>
- </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 BsAY3g4gBNo=
- S: OK
- 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 bW9yZ2Fu
- S: DATA OTUgUWE1ODMwOA==
- C: DATA Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
- S: OK
- 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 BsAY3g4gBNo=
- S: OK
- C: BEGIN
- </programlisting>
- </figure>
- <figure>
- <title>Example of server doesn't support initial auth mechanism</title>
- <programlisting>
- C: AUTH MAGIC_COOKIE BsAY3g4gBNo=
- S: REJECTED KERBEROS_V4 SKEY
- C: AUTH SKEY bW9yZ2Fu
- S: DATA OTUgUWE1ODMwOA==
- C: DATA Rk9VUiBNQU5OIFNPT04gRklSIFZBUlkgTUFTSA==
- S: OK
- C: BEGIN
- </programlisting>
- </figure>
- <figure>
- <title>Example of wrong password or the like followed by successful retry</title>
- <programlisting>
- 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
- </programlisting>
- </figure>
- <figure>
- <title>Example of skey cancelled and restarted</title>
- <programlisting>
- 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
- </programlisting>
- </figure>
+ <para>
+ <xref linkend="introspection-format"/> describes the format of this XML string.
</para>
</sect2>
- <sect2 id="auth-states">
- <title>Authentication state diagrams</title>
-
+ <sect2 id="standard-interfaces-properties">
+ <title><literal>org.freedesktop.DBus.Properties</literal></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.
+ 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);
+ </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>
- <sect3 id="auth-states-client">
- <title>Client states</title>
-
- <formalpara>
- <title><emphasis>Start</emphasis></title>
- <para>
- <itemizedlist>
- <listitem><para>send AUTH with initial data -> <emphasis>WaitingForData</emphasis></para></listitem>
- <listitem><para>send AUTH with no initial data -> <emphasis>WaitingForData</emphasis> or <emphasis>NeedSendData</emphasis> (depends on mechanism)</para></listitem>
- </itemizedlist>
- The <emphasis>Start</emphasis> state is stateful (it has a list of
- available mechanisms and those 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>
-
- <formalpara>
- <title><emphasis>WaitingForData</emphasis></title>
- <para>
-
- <itemizedlist>
- <listitem><para>receive OK -> <emphasis>NeedSendBegin</emphasis></para></listitem>
- <listitem><para>receive REJECTED -> <emphasis>Start</emphasis></para></listitem>
- <listitem><para>receive ERROR -> <emphasis>Start</emphasis></para></listitem>
- <listitem><para>receive DATA -> <emphasis>NeedSendData</emphasis></para></listitem>
- <listitem><para>receive anything else -> <emphasis>NeedSendError</emphasis></para></listitem>
- </itemizedlist>
- When going back to <emphasis>Start</emphasis>, the mechanism in
- progress should be marked as failed and not retried (at least not
- with the same parameters). When receiving REJECTED with a list of
- mechanisms, the list should be recorded and used to select
- a mechanism.
- </para>
- </formalpara>
-
- <formalpara>
- <title><emphasis>NeedSendData</emphasis></title>
+ <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>
- <itemizedlist>
- <listitem><para>send DATA -> <emphasis>WaitingForData</emphasis></para></listitem>
- <listitem><para>send CANCEL -> <emphasis>Start</emphasis></para></listitem>
- </itemizedlist>
+ 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>
- </formalpara>
-
- <formalpara>
- <title><emphasis>NeedSendError</emphasis></title>
+ </listitem>
+ <listitem>
<para>
-
- <itemizedlist>
- <listitem><para>send ERROR -> return to previous state</para></listitem>
- </itemizedlist>
+ 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>
- </formalpara>
-
- <formalpara>
- <title><emphasis>NeedSendBegin</emphasis></title>
+ </listitem>
+ <listitem>
<para>
-
- <itemizedlist>
- <listitem><para>send BEGIN -> Authorized</para></listitem>
- </itemizedlist>
+ 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>
- </formalpara>
-
- <formalpara>
- <title><emphasis>Authorized</emphasis></title>
+ </listitem>
+ <listitem>
<para>
- This is the end state, flow of messages begins.
+ The possible directions are "in" and "out",
+ unlike CORBA there is no "inout"
</para>
- </formalpara>
-
- </sect3>
-
- <sect3 id="auth-states-server">
- <title>Server states</title>
-
- <formalpara>
- <title><emphasis>WaitingForAuth</emphasis></title>
+ </listitem>
+ <listitem>
<para>
- <itemizedlist>
- <listitem><para>receive AUTH with initial response -> <emphasis>NeedSendData</emphasis></para></listitem>
- <listitem><para>receive AUTH without initial response -> <emphasis>NeedSendData</emphasis> or <emphasis>WaitingForData</emphasis> depending on mechanism</para></listitem>
- </itemizedlist>
+ The possible property access flags are
+ "readwrite", "read", and "write"
</para>
- </formalpara>
-
- <formalpara>
- <title><emphasis>NeedSendData</emphasis></title>
+ </listitem>
+ <listitem>
<para>
- <itemizedlist>
- <listitem><para>send DATA -> <emphasis>WaitingForData</emphasis></para></listitem>
- <listitem><para>send ERROR -> <emphasis>WaitingForData</emphasis></para></listitem>
- <listitem><para>send REJECTED -> <emphasis>WaitingForAuth</emphasis></para></listitem>
- <listitem><para>send OK -> <emphasis>WaitingForBegin</emphasis></para></listitem>
- </itemizedlist>
+ Multiple interfaces can of course be listed for
+ one <node>.
</para>
- </formalpara>
-
- <formalpara>
- <title><emphasis>WaitingForData</emphasis></title>
+ </listitem>
+ <listitem>
<para>
- <itemizedlist>
- <listitem><para>receive DATA -> <emphasis>NeedSendData</emphasis></para></listitem>
- <listitem><para>receive CANCEL -> <emphasis>NeedSendRejected</emphasis></para></listitem>
- <listitem><para>receive ERROR -> <emphasis>NeedSendRejected</emphasis></para></listitem>
- <listitem><para>receive anything else -> <emphasis>NeedSendError</emphasis></para></listitem>
- </itemizedlist>
+ The "name" attribute on arguments is optional.
</para>
- </formalpara>
+ </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>
- <formalpara>
- <title><emphasis>NeedSendError</emphasis></title>
- <para>
-
- <itemizedlist>
- <listitem><para>send ERROR -> return to previous state</para></listitem>
- </itemizedlist>
- </para>
- </formalpara>
+ <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>
- <formalpara>
- <title><emphasis>NeedSendRejected</emphasis></title>
- <para>
-
- <itemizedlist>
- <listitem><para>send REJECTED -> <emphasis>WaitingForAuth</emphasis></para></listitem>
- </itemizedlist>
- </para>
- </formalpara>
+ <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>
- <formalpara>
- <title><emphasis>WaitingForBegin</emphasis></title>
- <para>
-
- <itemizedlist>
- <listitem><para>receive BEGIN -> <emphasis>Authorized</emphasis></para></listitem>
- <listitem><para>receive anything else -> <emphasis>NeedSendError</emphasis></para></listitem>
- </itemizedlist>
- </para>
- </formalpara>
+ <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>
- <formalpara>
- <title><emphasis>Authorized</emphasis></title>
- <para>
- This is the end state, flow of messages begins.
- </para>
- </formalpara>
+ <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>
- </sect3>
-
+ <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="auth-mechanisms">
- <title>Authentication mechanisms</title>
+
+ <sect2 id="message-bus-names">
+ <title>Message Bus Names</title>
<para>
- This section describes some new authentication mechanisms.
- D-BUS also allows any standard SASL mechanism of course.
+ 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>
- <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>
+ 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>
- 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.
+ 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>
- A cookie file contains one cookie per line. Each line
- has three space-separated fields:
+ 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>
- 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.
+ 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>
- </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>
+ 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>
- 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.
+ 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>
- The pruned and possibly added-to cookie file
- must be resaved atomically (using a temporary
- file which is rename()'d).
+ 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>
- The lock must be dropped by deleting the lockfile.
+ 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>
- Clients need not lock the file in order to load it,
- because servers are required to save the file atomically.
+ 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>
- </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.
- [FIXME how do you escape colon, comma, and semicolon in the values of the key=value pairs?]
- </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>
- [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>
- <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>
- </sect1>
+ <para>
+ The flags argument contains any of the following values logically ORed
+ together:
- <sect1 id="standard-messages">
- <title>Standard Peer-to-Peer Messages</title>
- <para>
- See <xref linkend="message-protocol-types-notation"/> for details on
- the notation used in this section.
- </para>
- <sect2 id="standard-messages-ping">
- <title><literal>org.freedesktop.Peer.Ping</literal></title>
- <para>
- <programlisting>
- org.freedesktop.Peer.Ping ()
- </programlisting>
- </para>
- <para>
- On receipt of the METHOD_CALL
- message <literal>org.freedesktop.Peer.Ping</literal>, an application
- should do nothing other than reply with a METHOD_RETURN as usual.
- </para>
- </sect2>
+ <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>
- <sect2 id="standard-messages-get-props">
- <title><literal>org.freedesktop.Props.Get</literal></title>
- <para>
- [FIXME this is just a bogus made-up method that isn't implemented
- or thought through, to save an example of table formatting for the
- argument descriptions]
- <programlisting>
- org.freedesktop.Props.Get (in STRING property_name,
- out ANY_OR_NIL property_value)
- </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>in STRING</entry>
- <entry>Name of the property to get</entry>
- </row>
- <row>
- <entry>1</entry>
- <entry>out ANY_OR_NIL</entry>
- <entry>The value of the property. The type depends on the property.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
- </sect2>
- </sect1>
+ 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.
- <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 or more of the connected
- applications. The message bus itself always owns the special service
- <literal>org.freedesktop.DBus</literal>.
- </para>
- <para>
- Services may have <firstterm>secondary owners</firstterm>. Secondary owners
- of a service are kept in a queue; if the primary owner of a service
- disconnects, or releases the service, the next secondary owner becomes
- the new owner of the service.
- </para>
- <para>
- Messages may have a <literal>SERVICE</literal> field (see <xref
- linkend="message-protocol-header-fields"/>). When the message bus
- receives a message, if the <literal>SERVICE</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
- an <literal>org.freedesktop.Peer.Ping</literal> message with no
- <literal>SERVICE</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>SERVICE</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
- <literal>org.freedesktop.DBus.Broadcast</literal>. Broadcast messages are
- sent to all applications with <firstterm>message matching
- rules</firstterm> that match the message.
- </para>
- <para>
- Continuing the <literal>org.freedesktop.Peer.Ping</literal> example, if
- the ping message were sent with a <literal>SERVICE</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.DBus.Broadcast</literal>, then multiple applications
- might receive the ping, and all would normally reply to it.
- </para>
+ </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-services">
- <title>Message Bus Services</title>
- <para>
- 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.
- </para>
- <para>
- Ownership of the base service is a prerequisite for interaction with
- the message bus. It logically follows that the base service is always
- the first service that an application comes to own, and the last
- service that it loses ownership of.
- </para>
- <para>
- Base service names must begin with the character ':' (ASCII colon
- character); service names that are not base service names must not begin
- with this character. (The bus must reject any attempt by an application
- to manually create a service name beginning with ':'.) This restriction
- categorically prevents "spoofing"; messages sent to a base service name
- will always go to a single application instance and that instance only.
- </para>
- <para>
- An application can request additional service names to be associated
- with it using the
- <literal>org.freedesktop.DBus.AcquireService</literal>
- message. [FIXME what service names are allowed; ASCII or unicode;
- length limit; etc.]
- </para>
- <para>
- [FIXME this needs more detail, and should move the service-related message
- descriptions up into this section perhaps]
- Service ownership handling can be specified in the flags part
- of the <literal>org.freedesktop.DBus.AcquireService</literal>
- message. If an application specifies the
- DBUS_SERVICE_FLAGS_PROHIBIT_REPLACEMENT flag, then all applications
- trying to acquire the service will be put in a queue. When the
- primary owner disconnects from the bus or removes ownership
- from the service, the next application in the queue will be the
- primary owner. If the DBUS_SERVICE_FLAGS_PROHIBIT_REPLACEMENT
- flag is not specified, then the primary owner will lose
- ownership whenever another application requests ownership of the
- service.
- </para>
- <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>
- </sect2>
<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.
+ FIXME
</para>
+ </sect2>
+ <sect2 id="message-bus-starting-services">
+ <title>Message Bus Starting Services</title>
<para>
- [FIXME go into detail about broadcast, multicast, unicast, etc.]
+ 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>
- </sect2>
- <sect2 id="message-bus-activation">
- <title>Message Bus Service Activation</title>
<para>
- <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.
+ 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 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"/>.
+ 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
+ [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.
+ 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]
- Name=org.gnome.ConfigurationDatabase
+ Names=org.freedesktop.ConfigurationDatabase;org.gnome.GConf;
Exec=/usr/libexec/gconfd-2
</programlisting>
</figure>
</para>
<para>
- 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?]
+ 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_ACTIVATION_ADDRESS</literal> set to the address of the
- message bus so it can connect and register the appropriate services.
+ <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
- activating 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_ACTIVATION_BUS_TYPE</literal> environment variable if it is one
+ 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 activated executable must still connect to the address given
- in <literal>DBUS_ACTIVATION_ADDRESS</literal>, but may assume that the
+ 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>
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">
changes in the printer queue, and so forth.
</para>
<para>
- The address of the login session message bus is given
+ 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
<sect2 id="message-bus-messages">
<title>Message Bus Messages</title>
<para>
- The special message bus service <literal>org.freedesktop.DBus</literal>
- responds to a number of messages, allowing applications to
- interact with the message bus.
+ The special message bus name <literal>org.freedesktop.DBus</literal>
+ responds to a number of additional messages.
</para>
<sect3 id="bus-messages-hello">
<row>
<entry>0</entry>
<entry>STRING</entry>
- <entry>Name of the service assigned to the application</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 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. If a client wishes to
- disconnect from the bus, it just has to disconnect from the
- transport used. No de-registration message is necessary.
+ 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>
- The reply message contains the name of the application's base service.
+ 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-services">
- <title><literal>org.freedesktop.DBus.ListServices</literal></title>
+ <sect3 id="bus-messages-list-names">
+ <title><literal>org.freedesktop.DBus.ListNames</literal></title>
<para>
As a method:
<programlisting>
- STRING_ARRAY ListServices ()
+ ARRAY of STRING ListNames ()
</programlisting>
Reply arguments:
<informaltable>
<tbody>
<row>
<entry>0</entry>
- <entry>STRING_ARRAY</entry>
- <entry>Array of strings where each string is the name of a service</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 existing services registered with the message bus.
+ Returns a list of all currently-owned names on the bus.
</para>
</sect3>
- <sect3 id="bus-messages-service-exists">
- <title><literal>org.freedesktop.DBus.ServiceExists</literal></title>
+ <sect3 id="bus-messages-name-exists">
+ <title><literal>org.freedesktop.DBus.NameHasOwner</literal></title>
<para>
As a method:
<programlisting>
- BOOLEAN ServiceExists (in STRING service_name)
+ BOOLEAN NameHasOwner (in STRING name)
</programlisting>
Message arguments:
<informaltable>
<row>
<entry>0</entry>
<entry>STRING</entry>
- <entry>Name of the service</entry>
+ <entry>Name to check</entry>
</row>
</tbody>
</tgroup>
<row>
<entry>0</entry>
<entry>BOOLEAN</entry>
- <entry>Return value, true if the service exists</entry>
+ <entry>Return value, true if the name exists</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</para>
<para>
- Checks if a service with a specified name exists.
+ Checks if the specified name exists (currently has an owner).
</para>
</sect3>
- <sect3 id="bus-messages-acquire-service">
- <title><literal>org.freedesktop.DBus.AcquireService</literal></title>
+ <sect3 id="bus-messages-name-owner-changed">
+ <title><literal>org.freedesktop.DBus.NameOwnerChanged</literal></title>
<para>
- As a method:
+ This is a signal:
<programlisting>
- UINT32 AcquireService (in STRING service_name)
+ NameOwnerChanged (STRING name, STRING old_owner, STRING new_owner)
</programlisting>
Message arguments:
<informaltable>
<row>
<entry>0</entry>
<entry>STRING</entry>
- <entry>Name of the service</entry>
+ <entry>Name with a new owner</entry>
</row>
<row>
<entry>1</entry>
- <entry>UINT32</entry>
- <entry>Flags</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>
- Reply arguments:
+ </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>
<tbody>
<row>
<entry>0</entry>
- <entry>UINT32</entry>
- <entry>Return value</entry>
+ <entry>STRING</entry>
+ <entry>Name which was lost</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>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 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>
+ This signal is sent to a specific application when it loses
+ ownership of a name.
</para>
</sect3>
- <sect3 id="bus-messages-service-acquired">
- <title><literal>org.freedesktop.DBus.ServiceAcquired</literal></title>
+
+ <sect3 id="bus-messages-name-acquired">
+ <title><literal>org.freedesktop.DBus.NameAcquired</literal></title>
<para>
- As a method:
+ This is a signal:
<programlisting>
- ServiceAcquired (in STRING service_name)
+ NameAcquired (STRING name)
</programlisting>
Message arguments:
<informaltable>
<row>
<entry>0</entry>
<entry>STRING</entry>
- <entry>Name of the service</entry>
+ <entry>Name which was acquired</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.
+ This signal is sent to a specific application when it gains
+ ownership of a name.
</para>
</sect3>
- <sect3 id="bus-messages-service-lost">
- <title><literal>org.freedesktop.DBus.ServiceLost</literal></title>
+
+ <sect3 id="bus-messages-start-service-by-name">
+ <title><literal>org.freedesktop.DBus.StartServiceByName</literal></title>
<para>
As a method:
<programlisting>
- ServiceLost (in STRING service_name)
+ UINT32 StartServiceByName (in STRING name, in UINT32 flags)
</programlisting>
Message arguments:
<informaltable>
<row>
<entry>0</entry>
<entry>STRING</entry>
- <entry>Name of the service</entry>
+ <entry>Name of the service to start</entry>
</row>
<row>
<entry>1</entry>
<entry>UINT32</entry>
- <entry>Flags</entry>
+ <entry>Flags (currently not used)</entry>
</row>
</tbody>
</tgroup>
</informaltable>
- </para>
- <para>
- This message is sent to a specific application when it loses primary
- ownership of a service.
+ 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"/>.
- [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:
+ The return value can be one of the following values:
<informaltable>
<tgroup cols="3">
<thead>
<row>
- <entry>Argument</entry>
- <entry>Type</entry>
+ <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>0</entry>
- <entry>STRING</entry>
- <entry>Name of the service</entry>
+ <entry>DBUS_START_REPLY_ALREADY_RUNNING</entry>
+ <entry>2</entry>
+ <entry>A connection already owns the given name.</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.
+ </tgroup>
+ </informaltable>
</para>
+
</sect3>
- <sect3 id="bus-messages-service-deleted">
- <title><literal>org.freedesktop.DBus.ServiceDeleted</literal></title>
+ <sect3 id="bus-messages-get-name-owner">
+ <title><literal>org.freedesktop.DBus.GetNameOwner</literal></title>
<para>
As a method:
<programlisting>
- ServiceDeleted (in STRING service_name)
+ STRING GetNameOwner (in STRING name)
</programlisting>
Message arguments:
<informaltable>
<row>
<entry>0</entry>
<entry>STRING</entry>
- <entry>Name of the service</entry>
+ <entry>Name to get the owner of</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>
+ 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-activate-service">
- <title><literal>org.freedesktop.DBus.ActivateService</literal></title>
+ <sect3 id="bus-messages-get-connection-unix-user">
+ <title><literal>org.freedesktop.DBus.GetConnectionUnixUser</literal></title>
<para>
As a method:
<programlisting>
- UINT32 ActivateService (in STRING service_name, in UINT32 flags)
+ UINT32 GetConnectionUnixUser (in STRING connection_name)
</programlisting>
Message arguments:
<informaltable>
<row>
<entry>0</entry>
<entry>STRING</entry>
- <entry>Name of the service to activate</entry>
+ <entry>Name of the connection to query</entry>
</row>
- <row>
- <entry>1</entry>
- <entry>UINT32</entry>
- <entry>Flags (currently not used)</entry>
- </row>
</tbody>
</tgroup>
</informaltable>
<row>
<entry>0</entry>
<entry>UINT32</entry>
- <entry>Return value</entry>
+ <entry>unix user id</entry>
</row>
</tbody>
</tgroup>
</informaltable>
- 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>
- <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_ACTIVATION_REPLY_ACTIVATED</entry>
- <entry>0x0</entry>
- <entry>The service was activated successfully.</entry>
- </row>
- <row>
- <entry>DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE</entry>
- <entry>0x1</entry>
- <entry>The service is already active.</entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
- </para>
-
- </sect3>
-
- <sect3 id="bus-messages-out-of-memory">
- <title><literal>org.freedesktop.DBus.Error.NoMemory</literal></title>
- <para>
- As a method:
- <programlisting>
- void NoMemory ()
- </programlisting>
- </para>
- <para>
- Sent by the message bus when it can't process a message due to an out of memory failure.
- </para>
+ 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-service-does-not-exist">
- <title><literal>org.freedesktop.DBus.Error.ServiceDoesNotExist</literal></title>
- <para>
- As a method:
- <programlisting>
- void ServiceDoesNotExist (in STRING error)
- </programlisting>
- </para>
- <para>
- Sent by the message bus as a reply to a client that tried to send a message to a service that doesn't exist.
- </para>
- </sect3>
</sect2>
</sect1>
This glossary defines some of the terms used in this specification.
</para>
- <glossentry id="term-activation"><glossterm>Activation</glossterm>
+ <glossentry id="term-bus-name"><glossterm>Bus Name</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>
-
- <glossentry id="term-broadcast"><glossterm>Broadcast</glossterm>
- <glossdef>
- <para>
- A message sent to the special <literal>org.freedesktop.DBus.Broadcast</literal>
- service; the message bus will forward the broadcast message
- to all applications that have expressed interest in it.
+ 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>
<glossdef>
<para>
The message bus is a special application that forwards
- or broadcasts messages between a group of applications
+ or routes messages between a group of applications
connected to the message bus. It also manages
- <firstterm>services</firstterm>.
+ <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 message and service
- names. The convention used is the same as Java uses for
- defining classes: a reversed domain name.
+ 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> or
- <firstterm>object reference</firstterm>.
+ 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="term-path"><glossterm>Path</glossterm>
+ <glossentry id="one-to-one"><glossterm>One-to-One</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>
+ 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="peer-to-peer"><glossterm>Peer-to-peer</glossterm>
+ <glossentry id="term-path"><glossterm>Path</glossterm>
<glossdef>
- <para>
- An application talking directly to another application, without going through a message bus.
+ <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-secondary-owner"><glossterm>Secondary service owner</glossterm>
+
+ <glossentry id="term-queued-owner"><glossterm>Queued Name Owner</glossterm>
<glossdef>
<para>
- Each service has a primary owner; messages sent to the service name
- go to the primary owner. However, certain services also maintain
- a queue of secondary owners "waiting in the wings." If
- the primary owner releases the service, then the first secondary
- owner in the queue automatically becomes the primary owner.
+ 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 simply a named list of applications. 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.
- Services may also have <firstterm>secondary owners</firstterm> (see
- <xref linkend="term-secondary-owner"/>).
+ 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-name"><glossterm>Service name</glossterm>
+
+ <glossentry id="term-service-description-files"><glossterm>Service Description Files</glossterm>
<glossdef>
- <para>
- The name used when referring to a service. If the service is
- a base service it has a unique service name, for example
- ":1-20", and otherwise it should be namespaced.
+ <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-service-description-files"><glossterm>Service Description Files</glossterm>
+
+ <glossentry id="term-unique-name"><glossterm>Unique Connection Name</glossterm>
<glossdef>
<para>
- ".service files" tell the bus how to activate a particular service.
- See <xref linkend="term-activation"/>
+ 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>