diff options
Diffstat (limited to 'doc/dbus-specification.xml')
-rw-r--r-- | doc/dbus-specification.xml | 4086 |
1 files changed, 4086 insertions, 0 deletions
diff --git a/doc/dbus-specification.xml b/doc/dbus-specification.xml new file mode 100644 index 00000000..b5866e53 --- /dev/null +++ b/doc/dbus-specification.xml @@ -0,0 +1,4086 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" +"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" +[ +]> + +<article id="index"> + <articleinfo> + <title>D-Bus Specification</title> + <releaseinfo>Version 0.12</releaseinfo> + <date>7 November 2006</date> + <authorgroup> + <author> + <firstname>Havoc</firstname> + <surname>Pennington</surname> + <affiliation> + <orgname>Red Hat, Inc.</orgname> + <address> + <email>hp@pobox.com</email> + </address> + </affiliation> + </author> + <author> + <firstname>Anders</firstname> + <surname>Carlsson</surname> + <affiliation> + <orgname>CodeFactory AB</orgname> + <address> + <email>andersca@codefactory.se</email> + </address> + </affiliation> + </author> + <author> + <firstname>Alexander</firstname> + <surname>Larsson</surname> + <affiliation> + <orgname>Red Hat, Inc.</orgname> + <address> + <email>alexl@redhat.com</email> + </address> + </affiliation> + </author> + </authorgroup> + </articleinfo> + + <sect1 id="introduction"> + <title>Introduction</title> + <para> + D-Bus is a system for low-latency, low-overhead, easy to use + interprocess communication (IPC). In more detail: + <itemizedlist> + <listitem> + <para> + D-Bus is <emphasis>low-latency</emphasis> because it is designed + to avoid round trips and allow asynchronous operation, much like + the X protocol. + </para> + </listitem> + <listitem> + <para> + D-Bus is <emphasis>low-overhead</emphasis> because it uses a + binary protocol, and does not have to convert to and from a text + format such as XML. Because D-Bus is intended for potentially + high-resolution same-machine IPC, not primarily for Internet IPC, + this is an interesting optimization. + </para> + </listitem> + <listitem> + <para> + D-Bus is <emphasis>easy to use</emphasis> because it works in terms + of <firstterm>messages</firstterm> rather than byte streams, and + automatically handles a lot of the hard IPC issues. Also, the D-Bus + library is designed to be wrapped in a way that lets developers use + their framework's existing object/type system, rather than learning + a new one specifically for IPC. + </para> + </listitem> + </itemizedlist> + </para> + + <para> + The base D-Bus protocol is a one-to-one (peer-to-peer or client-server) + protocol, specified in <xref linkend="message-protocol"/>. That is, it is + a system for one application to talk to a single other + application. However, the primary intended application of the protocol is the + D-Bus <firstterm>message bus</firstterm>, specified in <xref + linkend="message-bus"/>. The message bus is a special application that + accepts connections from multiple other applications, and forwards + messages among them. + </para> + + <para> + Uses of D-Bus include notification of system changes (notification of when + a camera is plugged in to a computer, or a new version of some software + has been installed), or desktop interoperability, for example a file + monitoring service or a configuration service. + </para> + + <para> + D-Bus is designed for two specific use cases: + <itemizedlist> + <listitem> + <para> + A "system bus" for notifications from the system to user sessions, + and to allow the system to request input from user sessions. + </para> + </listitem> + <listitem> + <para> + A "session bus" used to implement desktop environments such as + GNOME and KDE. + </para> + </listitem> + </itemizedlist> + D-Bus is not intended to be a generic IPC system for any possible + application, and intentionally omits many features found in other + IPC systems for this reason. + </para> + + <para> + At the same time, the bus daemons offer a number of features not found in + other IPC systems, such as single-owner "bus names" (similar to X + selections), on-demand startup of services, and security policies. + In many ways, these features are the primary motivation for developing + D-Bus; other systems would have sufficed if IPC were the only goal. + </para> + + <para> + D-Bus may turn out to be useful in unanticipated applications, but future + versions of this spec and the reference implementation probably will not + incorporate features that interfere with the core use cases. + </para> + + <para> + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in RFC 2119. However, the + document could use a serious audit to be sure it makes sense to do + so. Also, they are not capitalized. + </para> + + <sect2 id="stability"> + <title>Protocol and Specification Stability</title> + <para> + The D-Bus protocol is frozen (only compatible extensions are allowed) as + of November 8, 2006. However, this specification could still use a fair + bit of work to make interoperable reimplementation possible without + reference to the D-Bus reference implementation. Thus, this + specification is not marked 1.0. To mark it 1.0, we'd like to see + someone invest significant effort in clarifying the specification + language, and growing the specification to cover more aspects of the + reference implementation's behavior. + </para> + <para> + Until this work is complete, any attempt to reimplement D-Bus will + probably require looking at the reference implementation and/or asking + questions on the D-Bus mailing list about intended behavior. + Questions on the list are very welcome. + </para> + <para> + Nonetheless, this document should be a useful starting point and is + to our knowledge accurate, though incomplete. + </para> + </sect2> + + </sect1> + + <sect1 id="message-protocol"> + <title>Message Protocol</title> + + <para> + A <firstterm>message</firstterm> consists of a + <firstterm>header</firstterm> and a <firstterm>body</firstterm>. If you + think of a message as a package, the header is the address, and the body + contains the package contents. The message delivery system uses the header + information to figure out where to send the message and how to interpret + it; the recipient interprets the body of the message. + </para> + + <para> + The body of the message is made up of zero or more + <firstterm>arguments</firstterm>, which are typed values, such as an + integer or a byte array. + </para> + + <para> + Both header and body use the same type system and format for + serializing data. Each type of value has a wire format. + Converting a value from some other representation into the wire + format is called <firstterm>marshaling</firstterm> and converting + it back from the wire format is <firstterm>unmarshaling</firstterm>. + </para> + + <sect2 id="message-protocol-signatures"> + <title>Type Signatures</title> + + <para> + The D-Bus protocol does not include type tags in the marshaled data; a + block of marshaled values must have a known <firstterm>type + signature</firstterm>. The type signature is made up of <firstterm>type + codes</firstterm>. A type code is an ASCII character representing the + type of a value. Because ASCII characters are used, the type signature + will always form a valid ASCII string. A simple string compare + determines whether two type signatures are equivalent. + </para> + + <para> + As a simple example, the type code for 32-bit integer (<literal>INT32</literal>) is + the ASCII character 'i'. So the signature for a block of values + containing a single <literal>INT32</literal> would be: + <programlisting> + "i" + </programlisting> + A block of values containing two <literal>INT32</literal> would have this signature: + <programlisting> + "ii" + </programlisting> + </para> + + <para> + All <firstterm>basic</firstterm> types work like + <literal>INT32</literal> in this example. To marshal and unmarshal + basic types, you simply read one value from the data + block corresponding to each type code in the signature. + In addition to basic types, there are four <firstterm>container</firstterm> + types: <literal>STRUCT</literal>, <literal>ARRAY</literal>, <literal>VARIANT</literal>, + and <literal>DICT_ENTRY</literal>. + </para> + + <para> + <literal>STRUCT</literal> has a type code, ASCII character 'r', but this type + code does not appear in signatures. Instead, ASCII characters + '(' and ')' are used to mark the beginning and end of the struct. + So for example, a struct containing two integers would have this + signature: + <programlisting> + "(ii)" + </programlisting> + Structs can be nested, so for example a struct containing + an integer and another struct: + <programlisting> + "(i(ii))" + </programlisting> + The value block storing that struct would contain three integers; the + type signature allows you to distinguish "(i(ii))" from "((ii)i)" or + "(iii)" or "iii". + </para> + + <para> + The <literal>STRUCT</literal> type code 'r' is not currently used in the D-Bus protocol, + but is useful in code that implements the protocol. This type code + is specified to allow such code to interoperate in non-protocol contexts. + </para> + + <para> + Empty structures are not allowed; there must be at least one + type code between the parentheses. + </para> + + <para> + <literal>ARRAY</literal> has ASCII character 'a' as type code. The array type code must be + followed by a <firstterm>single complete type</firstterm>. The single + complete type following the array is the type of each array element. So + the simple example is: + <programlisting> + "ai" + </programlisting> + which is an array of 32-bit integers. But an array can be of any type, + such as this array-of-struct-with-two-int32-fields: + <programlisting> + "a(ii)" + </programlisting> + Or this array of array of integer: + <programlisting> + "aai" + </programlisting> + </para> + + <para> + The phrase <firstterm>single complete type</firstterm> deserves some + definition. A single complete type is a basic type code, a variant type code, + an array with its element type, or a struct with its fields. + So the following signatures are not single complete types: + <programlisting> + "aa" + </programlisting> + <programlisting> + "(ii" + </programlisting> + <programlisting> + "ii)" + </programlisting> + And the following signatures contain multiple complete types: + <programlisting> + "ii" + </programlisting> + <programlisting> + "aiai" + </programlisting> + <programlisting> + "(ii)(ii)" + </programlisting> + Note however that a single complete type may <emphasis>contain</emphasis> + multiple other single complete types. + </para> + + <para> + <literal>VARIANT</literal> has ASCII character 'v' as its type code. A marshaled value of + type <literal>VARIANT</literal> will have the signature of a single complete type as part + of the <emphasis>value</emphasis>. This signature will be followed by a + marshaled value of that type. + </para> + + <para> + A <literal>DICT_ENTRY</literal> works exactly like a struct, but rather + than parentheses it uses curly braces, and it has more restrictions. + The restrictions are: it occurs only as an array element type; it has + exactly two single complete types inside the curly braces; the first + single complete type (the "key") must be a basic type rather than a + container type. Implementations must not accept dict entries outside of + arrays, must not accept dict entries with zero, one, or more than two + fields, and must not accept dict entries with non-basic-typed keys. A + dict entry is always a key-value pair. + </para> + + <para> + The first field in the <literal>DICT_ENTRY</literal> is always the key. + A message is considered corrupt if the same key occurs twice in the same + array of <literal>DICT_ENTRY</literal>. However, for performance reasons + implementations are not required to reject dicts with duplicate keys. + </para> + + <para> + In most languages, an array of dict entry would be represented as a + map, hash table, or dict object. + </para> + + <para> + The following table summarizes the D-Bus types. + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Code</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>INVALID</literal></entry> + <entry>0 (ASCII NUL)</entry> + <entry>Not a valid type code, used to terminate signatures</entry> + </row><row> + <entry><literal>BYTE</literal></entry> + <entry>121 (ASCII 'y')</entry> + <entry>8-bit unsigned integer</entry> + </row><row> + <entry><literal>BOOLEAN</literal></entry> + <entry>98 (ASCII 'b')</entry> + <entry>Boolean value, 0 is <literal>FALSE</literal> and 1 is <literal>TRUE</literal>. Everything else is invalid.</entry> + </row><row> + <entry><literal>INT16</literal></entry> + <entry>110 (ASCII 'n')</entry> + <entry>16-bit signed integer</entry> + </row><row> + <entry><literal>UINT16</literal></entry> + <entry>113 (ASCII 'q')</entry> + <entry>16-bit unsigned integer</entry> + </row><row> + <entry><literal>INT32</literal></entry> + <entry>105 (ASCII 'i')</entry> + <entry>32-bit signed integer</entry> + </row><row> + <entry><literal>UINT32</literal></entry> + <entry>117 (ASCII 'u')</entry> + <entry>32-bit unsigned integer</entry> + </row><row> + <entry><literal>INT64</literal></entry> + <entry>120 (ASCII 'x')</entry> + <entry>64-bit signed integer</entry> + </row><row> + <entry><literal>UINT64</literal></entry> + <entry>116 (ASCII 't')</entry> + <entry>64-bit unsigned integer</entry> + </row><row> + <entry><literal>DOUBLE</literal></entry> + <entry>100 (ASCII 'd')</entry> + <entry>IEEE 754 double</entry> + </row><row> + <entry><literal>STRING</literal></entry> + <entry>115 (ASCII 's')</entry> + <entry>UTF-8 string (<emphasis>must</emphasis> be valid UTF-8). Must be nul terminated and contain no other nul bytes.</entry> + </row><row> + <entry><literal>OBJECT_PATH</literal></entry> + <entry>111 (ASCII 'o')</entry> + <entry>Name of an object instance</entry> + </row><row> + <entry><literal>SIGNATURE</literal></entry> + <entry>103 (ASCII 'g')</entry> + <entry>A type signature</entry> + </row><row> + <entry><literal>ARRAY</literal></entry> + <entry>97 (ASCII 'a')</entry> + <entry>Array</entry> + </row><row> + <entry><literal>STRUCT</literal></entry> + <entry>114 (ASCII 'r'), 40 (ASCII '('), 41 (ASCII ')')</entry> + <entry>Struct</entry> + </row><row> + <entry><literal>VARIANT</literal></entry> + <entry>118 (ASCII 'v') </entry> + <entry>Variant type (the type of the value is part of the value itself)</entry> + </row><row> + <entry><literal>DICT_ENTRY</literal></entry> + <entry>101 (ASCII 'e'), 123 (ASCII '{'), 125 (ASCII '}') </entry> + <entry>Entry in a dict or map (array of key-value pairs)</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + + </sect2> + + <sect2 id="message-protocol-marshaling"> + <title>Marshaling (Wire Format)</title> + + <para> + Given a type signature, a block of bytes can be converted into typed + values. This section describes the format of the block of bytes. Byte + order and alignment issues are handled uniformly for all D-Bus types. + </para> + + <para> + A block of bytes has an associated byte order. The byte order + has to be discovered in some way; for D-Bus messages, the + byte order is part of the message header as described in + <xref linkend="message-protocol-messages"/>. For now, assume + that the byte order is known to be either little endian or big + endian. + </para> + + <para> + Each value in a block of bytes is aligned "naturally," for example + 4-byte values are aligned to a 4-byte boundary, and 8-byte values to an + 8-byte boundary. To properly align a value, <firstterm>alignment + padding</firstterm> may be necessary. The alignment padding must always + be the minimum required padding to properly align the following value; + and it must always be made up of nul bytes. The alignment padding must + not be left uninitialized (it can't contain garbage), and more padding + than required must not be used. + </para> + + <para> + Given all this, the types are marshaled on the wire as follows: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Encoding</entry> + <entry>Alignment</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>INVALID</literal></entry> + <entry>Not applicable; cannot be marshaled.</entry> + <entry>N/A</entry> + </row><row> + <entry><literal>BYTE</literal></entry> + <entry>A single 8-bit byte.</entry> + <entry>1</entry> + </row><row> + <entry><literal>BOOLEAN</literal></entry> + <entry>As for <literal>UINT32</literal>, but only 0 and 1 are valid values.</entry> + <entry>4</entry> + </row><row> + <entry><literal>INT16</literal></entry> + <entry>16-bit signed integer in the message's byte order.</entry> + <entry>2</entry> + </row><row> + <entry><literal>UINT16</literal></entry> + <entry>16-bit unsigned integer in the message's byte order.</entry> + <entry>2</entry> + </row><row> + <entry><literal>INT32</literal></entry> + <entry>32-bit signed integer in the message's byte order.</entry> + <entry>4</entry> + </row><row> + <entry><literal>UINT32</literal></entry> + <entry>32-bit unsigned integer in the message's byte order.</entry> + <entry>4</entry> + </row><row> + <entry><literal>INT64</literal></entry> + <entry>64-bit signed integer in the message's byte order.</entry> + <entry>8</entry> + </row><row> + <entry><literal>UINT64</literal></entry> + <entry>64-bit unsigned integer in the message's byte order.</entry> + <entry>8</entry> + </row><row> + <entry><literal>DOUBLE</literal></entry> + <entry>64-bit IEEE 754 double in the message's byte order.</entry> + <entry>8</entry> + </row><row> + <entry><literal>STRING</literal></entry> + <entry>A <literal>UINT32</literal> indicating the string's + length in bytes excluding its terminating nul, followed by + non-nul string data of the given length, followed by a terminating nul + byte. + </entry> + <entry> + 4 (for the length) + </entry> + </row><row> + <entry><literal>OBJECT_PATH</literal></entry> + <entry>Exactly the same as <literal>STRING</literal> except the + content must be a valid object path (see below). + </entry> + <entry> + 4 (for the length) + </entry> + </row><row> + <entry><literal>SIGNATURE</literal></entry> + <entry>The same as <literal>STRING</literal> except the length is a single + byte (thus signatures have a maximum length of 255) + and the content must be a valid signature (see below). + </entry> + <entry> + 1 + </entry> + </row><row> + <entry><literal>ARRAY</literal></entry> + <entry> + A <literal>UINT32</literal> giving the length of the array data in bytes, followed by + alignment padding to the alignment boundary of the array element type, + followed by each array element. The array length is from the + end of the alignment padding to the end of the last element, + i.e. it does not include the padding after the length, + or any padding after the last element. + Arrays have a maximum length defined to be 2 to the 26th power or + 67108864. Implementations must not send or accept arrays exceeding this + length. + </entry> + <entry> + 4 (for the length) + </entry> + </row><row> + <entry><literal>STRUCT</literal></entry> + <entry> + A struct must start on an 8-byte boundary regardless of the + type of the struct fields. The struct value consists of each + field marshaled in sequence starting from that 8-byte + alignment boundary. + </entry> + <entry> + 8 + </entry> + </row><row> + <entry><literal>VARIANT</literal></entry> + <entry> + A variant type has a marshaled <literal>SIGNATURE</literal> + followed by a marshaled value with the type + given in the signature. + Unlike a message signature, the variant signature + can contain only a single complete type. + So "i", "ai" or "(ii)" is OK, but "ii" is not. + </entry> + <entry> + 1 (alignment of the signature) + </entry> + </row><row> + <entry><literal>DICT_ENTRY</literal></entry> + <entry> + Identical to STRUCT. + </entry> + <entry> + 8 + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + + <sect3 id="message-protocol-marshaling-object-path"> + <title>Valid Object Paths</title> + + <para> + An object path is a name used to refer to an object instance. + Conceptually, each participant in a D-Bus message exchange may have + any number of object instances (think of C++ or Java objects) and each + such instance will have a path. Like a filesystem, the object + instances in an application form a hierarchical tree. + </para> + + <para> + The following rules define a valid object path. Implementations must + not send or accept messages with invalid object paths. + <itemizedlist> + <listitem> + <para> + The path may be of any length. + </para> + </listitem> + <listitem> + <para> + The path must begin with an ASCII '/' (integer 47) character, + and must consist of elements separated by slash characters. + </para> + </listitem> + <listitem> + <para> + Each element must only contain the ASCII characters + "[A-Z][a-z][0-9]_" + </para> + </listitem> + <listitem> + <para> + No element may be the empty string. + </para> + </listitem> + <listitem> + <para> + Multiple '/' characters cannot occur in sequence. + </para> + </listitem> + <listitem> + <para> + A trailing '/' character is not allowed unless the + path is the root path (a single '/' character). + </para> + </listitem> + </itemizedlist> + </para> + + </sect3> + + + <sect3 id="message-protocol-marshaling-signature"> + <title>Valid Signatures</title> + <para> + An implementation must not send or accept invalid signatures. + Valid signatures will conform to the following rules: + <itemizedlist> + <listitem> + <para> + The signature ends with a nul byte. + </para> + </listitem> + <listitem> + <para> + The signature is a list of single complete types. + Arrays must have element types, and structs must + have both open and close parentheses. + </para> + </listitem> + <listitem> + <para> + Only type codes and open and close parentheses are + allowed in the signature. The <literal>STRUCT</literal> type code + is not allowed in signatures, because parentheses + are used instead. + </para> + </listitem> + <listitem> + <para> + The maximum depth of container type nesting is 32 array type + codes and 32 open parentheses. This implies that the maximum + total depth of recursion is 64, for an "array of array of array + of ... struct of struct of struct of ..." where there are 32 + array and 32 struct. + </para> + </listitem> + <listitem> + <para> + The maximum length of a signature is 255. + </para> + </listitem> + <listitem> + <para> + Signatures must be nul-terminated. + </para> + </listitem> + </itemizedlist> + </para> + </sect3> + + </sect2> + + <sect2 id="message-protocol-messages"> + <title>Message Format</title> + + <para> + A message consists of a header and a body. The header is a block of + values with a fixed signature and meaning. The body is a separate block + of values, with a signature specified in the header. + </para> + + <para> + The length of the header must be a multiple of 8, allowing the body to + begin on an 8-byte boundary when storing the entire message in a single + buffer. If the header does not naturally end on an 8-byte boundary + up to 7 bytes of nul-initialized alignment padding must be added. + </para> + + <para> + The message body need not end on an 8-byte boundary. + </para> + + <para> + The maximum length of a message, including header, header alignment padding, + and body is 2 to the 27th power or 134217728. Implementations must not + send or accept messages exceeding this size. + </para> + + <para> + The signature of the header is: + <programlisting> + "yyyyuua(yv)" + </programlisting> + Written out more readably, this is: + <programlisting> + BYTE, BYTE, BYTE, BYTE, UINT32, UINT32, ARRAY of STRUCT of (BYTE,VARIANT) + </programlisting> + </para> + + <para> + These values have the following meanings: + <informaltable> + <tgroup cols="2"> + <thead> + <row> + <entry>Value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>1st <literal>BYTE</literal></entry> + <entry>Endianness flag; ASCII 'l' for little-endian + or ASCII 'B' for big-endian. Both header and body are + in this endianness.</entry> + </row> + <row> + <entry>2nd <literal>BYTE</literal></entry> + <entry><firstterm>Message type</firstterm>. Unknown types must be ignored. + Currently-defined types are described below. + </entry> + </row> + <row> + <entry>3rd <literal>BYTE</literal></entry> + <entry>Bitwise OR of flags. Unknown flags + must be ignored. Currently-defined flags are described below. + </entry> + </row> + <row> + <entry>4th <literal>BYTE</literal></entry> + <entry>Major protocol version of the sending application. If + the major protocol version of the receiving application does not + match, the applications will not be able to communicate and the + D-Bus connection must be disconnected. The major protocol + version for this version of the specification is 1. + </entry> + </row> + <row> + <entry>1st <literal>UINT32</literal></entry> + <entry>Length in bytes of the message body, starting + from the end of the header. The header ends after + its alignment padding to an 8-boundary. + </entry> + </row> + <row> + <entry>2nd <literal>UINT32</literal></entry> + <entry>The serial of this message, used as a cookie + by the sender to identify the reply corresponding + to this request. This must not be zero. + </entry> + </row> + <row> + <entry><literal>ARRAY</literal> of <literal>STRUCT</literal> of (<literal>BYTE</literal>,<literal>VARIANT</literal>)</entry> + <entry>An array of zero or more <firstterm>header + fields</firstterm> where the byte is the field code, and the + variant is the field value. The message type determines + which fields are required. + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + <firstterm>Message types</firstterm> that can appear in the second byte + of the header are: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional name</entry> + <entry>Decimal value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>INVALID</literal></entry> + <entry>0</entry> + <entry>This is an invalid type.</entry> + </row> + <row> + <entry><literal>METHOD_CALL</literal></entry> + <entry>1</entry> + <entry>Method call.</entry> + </row> + <row> + <entry><literal>METHOD_RETURN</literal></entry> + <entry>2</entry> + <entry>Method reply with returned data.</entry> + </row> + <row> + <entry><literal>ERROR</literal></entry> + <entry>3</entry> + <entry>Error reply. If the first argument exists and is a + string, it is an error message.</entry> + </row> + <row> + <entry><literal>SIGNAL</literal></entry> + <entry>4</entry> + <entry>Signal emission.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + Flags that can appear in the third byte of the header: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional name</entry> + <entry>Hex value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>NO_REPLY_EXPECTED</literal></entry> + <entry>0x1</entry> + <entry>This message does not expect method return replies or + error replies; the reply can be omitted as an + optimization. However, it is compliant with this specification + to return the reply despite this flag and the only harm + from doing so is extra network traffic. + </entry> + </row> + <row> + <entry><literal>NO_AUTO_START</literal></entry> + <entry>0x2</entry> + <entry>The bus must not launch an owner + for the destination name in response to this message. + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + + <sect3 id="message-protocol-header-fields"> + <title>Header Fields</title> + + <para> + The array at the end of the header contains <firstterm>header + fields</firstterm>, where each field is a 1-byte field code followed + by a field value. A header must contain the required header fields for + its message type, and zero or more of any optional header + fields. Future versions of this protocol specification may add new + fields. Implementations must ignore fields they do not + understand. Implementations must not invent their own header fields; + only changes to this specification may introduce new header fields. + </para> + + <para> + Again, if an implementation sees a header field code that it does not + expect, it must ignore that field, as it will be part of a new + (but compatible) version of this specification. This also applies + to known header fields appearing in unexpected messages, for + example: if a signal has a reply serial it must be ignored + even though it has no meaning as of this version of the spec. + </para> + + <para> + However, implementations must not send or accept known header fields + with the wrong type stored in the field value. So for example a + message with an <literal>INTERFACE</literal> field of type + <literal>UINT32</literal> would be considered corrupt. + </para> + + <para> + Here are the currently-defined header fields: + <informaltable> + <tgroup cols="5"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Decimal Code</entry> + <entry>Type</entry> + <entry>Required In</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>INVALID</literal></entry> + <entry>0</entry> + <entry>N/A</entry> + <entry>not allowed</entry> + <entry>Not a valid field name (error if it appears in a message)</entry> + </row> + <row> + <entry><literal>PATH</literal></entry> + <entry>1</entry> + <entry><literal>OBJECT_PATH</literal></entry> + <entry><literal>METHOD_CALL</literal>, <literal>SIGNAL</literal></entry> + <entry>The object to send a call to, + or the object a signal is emitted from. + The special path + <literal>/org/freedesktop/DBus/Local</literal> is reserved; + implementations should not send messages with this path, + and the reference implementation of the bus daemon will + disconnect any application that attempts to do so. + </entry> + </row> + <row> + <entry><literal>INTERFACE</literal></entry> + <entry>2</entry> + <entry><literal>STRING</literal></entry> + <entry><literal>SIGNAL</literal></entry> + <entry> + The interface to invoke a method call on, or + that a signal is emitted from. Optional for + method calls, required for signals. + The special interface + <literal>org.freedesktop.DBus.Local</literal> is reserved; + implementations should not send messages with this + interface, and the reference implementation of the bus + daemon will disconnect any application that attempts to + do so. + </entry> + </row> + <row> + <entry><literal>MEMBER</literal></entry> + <entry>3</entry> + <entry><literal>STRING</literal></entry> + <entry><literal>METHOD_CALL</literal>, <literal>SIGNAL</literal></entry> + <entry>The member, either the method name or signal name.</entry> + </row> + <row> + <entry><literal>ERROR_NAME</literal></entry> + <entry>4</entry> + <entry><literal>STRING</literal></entry> + <entry><literal>ERROR</literal></entry> + <entry>The name of the error that occurred, for errors</entry> + </row> + <row> + <entry><literal>REPLY_SERIAL</literal></entry> + <entry>5</entry> + <entry><literal>UINT32</literal></entry> + <entry><literal>ERROR</literal>, <literal>METHOD_RETURN</literal></entry> + <entry>The serial number of the message this message is a reply + to. (The serial number is the second <literal>UINT32</literal> in the header.)</entry> + </row> + <row> + <entry><literal>DESTINATION</literal></entry> + <entry>6</entry> + <entry><literal>STRING</literal></entry> + <entry>optional</entry> + <entry>The name of the connection this message is intended for. + Only used in combination with the message bus, see + <xref linkend="message-bus"/>.</entry> + </row> + <row> + <entry><literal>SENDER</literal></entry> + <entry>7</entry> + <entry><literal>STRING</literal></entry> + <entry>optional</entry> + <entry>Unique name of the sending connection. + The message bus fills in this field so it is reliable; the field is + only meaningful in combination with the message bus.</entry> + </row> + <row> + <entry><literal>SIGNATURE</literal></entry> + <entry>8</entry> + <entry><literal>SIGNATURE</literal></entry> + <entry>optional</entry> + <entry>The signature of the message body. + If omitted, it is assumed to be the + empty signature "" (i.e. the body must be 0-length).</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + </sect3> + </sect2> + + <sect2 id="message-protocol-names"> + <title>Valid Names</title> + <para> + The various names in D-Bus messages have some restrictions. + </para> + <para> + There is a <firstterm>maximum name length</firstterm> + of 255 which applies to bus names, interfaces, and members. + </para> + <sect3 id="message-protocol-names-interface"> + <title>Interface names</title> + <para> + Interfaces have names with type <literal>STRING</literal>, meaning that + they must be valid UTF-8. However, there are also some + additional restrictions that apply to interface names + specifically: + <itemizedlist> + <listitem><para>Interface names are composed of 1 or more elements separated by + a period ('.') character. All elements must contain at least + one character. + </para> + </listitem> + <listitem><para>Each element must only contain the ASCII characters + "[A-Z][a-z][0-9]_" and must not begin with a digit. + </para> + </listitem> + + <listitem><para>Interface names must contain at least one '.' (period) + character (and thus at least two elements). + </para></listitem> + + <listitem><para>Interface names must not begin with a '.' (period) character.</para></listitem> + <listitem><para>Interface names must not exceed the maximum name length.</para></listitem> + </itemizedlist> + </para> + </sect3> + <sect3 id="message-protocol-names-bus"> + <title>Bus names</title> + <para> + Connections have one or more bus names associated with them. + A connection has exactly one bus name that is a unique connection + name. The unique connection name remains with the connection for + its entire lifetime. + A bus name is of type <literal>STRING</literal>, + meaning that it must be valid UTF-8. However, there are also + some additional restrictions that apply to bus names + specifically: + <itemizedlist> + <listitem><para>Bus names that start with a colon (':') + character are unique connection names. + </para> + </listitem> + <listitem><para>Bus names are composed of 1 or more elements separated by + a period ('.') character. All elements must contain at least + one character. + </para> + </listitem> + <listitem><para>Each element must only contain the ASCII characters + "[A-Z][a-z][0-9]_-". Only elements that are part of a unique + connection name may begin with a digit, elements in + other bus names must not begin with a digit. + </para> + </listitem> + + <listitem><para>Bus names must contain at least one '.' (period) + character (and thus at least two elements). + </para></listitem> + + <listitem><para>Bus names must not begin with a '.' (period) character.</para></listitem> + <listitem><para>Bus names must not exceed the maximum name length.</para></listitem> + </itemizedlist> + </para> + <para> + Note that the hyphen ('-') character is allowed in bus names but + not in interface names. + </para> + </sect3> + <sect3 id="message-protocol-names-member"> + <title>Member names</title> + <para> + Member (i.e. method or signal) names: + <itemizedlist> + <listitem><para>Must only contain the ASCII characters + "[A-Z][a-z][0-9]_" and may not begin with a + digit.</para></listitem> + <listitem><para>Must not contain the '.' (period) character.</para></listitem> + <listitem><para>Must not exceed the maximum name length.</para></listitem> + <listitem><para>Must be at least 1 byte in length.</para></listitem> + </itemizedlist> + </para> + </sect3> + <sect3 id="message-protocol-names-error"> + <title>Error names</title> + <para> + Error names have the same restrictions as interface names. + </para> + </sect3> + </sect2> + + <sect2 id="message-protocol-types"> + <title>Message Types</title> + <para> + Each of the message types (<literal>METHOD_CALL</literal>, <literal>METHOD_RETURN</literal>, <literal>ERROR</literal>, and + <literal>SIGNAL</literal>) has its own expected usage conventions and header fields. + This section describes these conventions. + </para> + <sect3 id="message-protocol-types-method"> + <title>Method Calls</title> + <para> + Some messages invoke an operation on a remote object. These are + called method call messages and have the type tag <literal>METHOD_CALL</literal>. Such + messages map naturally to methods on objects in a typical program. + </para> + <para> + A method call message is required to have a <literal>MEMBER</literal> header field + indicating the name of the method. Optionally, the message has an + <literal>INTERFACE</literal> field giving the interface the method is a part of. In the + absence of an <literal>INTERFACE</literal> field, if two interfaces on the same object have + a method with the same name, it is undefined which of the two methods + will be invoked. Implementations may also choose to return an error in + this ambiguous case. However, if a method name is unique + implementations must not require an interface field. + </para> + <para> + Method call messages also include a <literal>PATH</literal> field + indicating the object to invoke the method on. If the call is passing + through a message bus, the message will also have a + <literal>DESTINATION</literal> field giving the name of the connection + to receive the message. + </para> + <para> + When an application handles a method call message, it is required to + return a reply. The reply is identified by a <literal>REPLY_SERIAL</literal> header field + indicating the serial number of the <literal>METHOD_CALL</literal> being replied to. The + reply can have one of two types; either <literal>METHOD_RETURN</literal> or <literal>ERROR</literal>. + </para> + <para> + If the reply has type <literal>METHOD_RETURN</literal>, the arguments to the reply message + are the return value(s) or "out parameters" of the method call. + If the reply has type <literal>ERROR</literal>, then an "exception" has been thrown, + and the call fails; no return value will be provided. It makes + no sense to send multiple replies to the same method call. + </para> + <para> + Even if a method call has no return values, a <literal>METHOD_RETURN</literal> + reply is required, so the caller will know the method + was successfully processed. + </para> + <para> + The <literal>METHOD_RETURN</literal> or <literal>ERROR</literal> reply message must have the <literal>REPLY_SERIAL</literal> + header field. + </para> + <para> + If a <literal>METHOD_CALL</literal> message has the flag <literal>NO_REPLY_EXPECTED</literal>, + then as an optimization the application receiving the method + call may choose to omit the reply message (regardless of + whether the reply would have been <literal>METHOD_RETURN</literal> or <literal>ERROR</literal>). + However, it is also acceptable to ignore the <literal>NO_REPLY_EXPECTED</literal> + flag and reply anyway. + </para> + <para> + Unless a message has the flag <literal>NO_AUTO_START</literal>, if the + destination name does not exist then a program to own the destination + name will be started before the message is delivered. The message + will be held until the new program is successfully started or has + failed to start; in case of failure, an error will be returned. This + flag is only relevant in the context of a message bus, it is ignored + during one-to-one communication with no intermediate bus. + </para> + <sect4 id="message-protocol-types-method-apis"> + <title>Mapping method calls to native APIs</title> + <para> + APIs for D-Bus may map method calls to a method call in a specific + programming language, such as C++, or may map a method call written + in an IDL to a D-Bus message. + </para> + <para> + In APIs of this nature, arguments to a method are often termed "in" + (which implies sent in the <literal>METHOD_CALL</literal>), or "out" (which implies + returned in the <literal>METHOD_RETURN</literal>). Some APIs such as CORBA also have + "inout" arguments, which are both sent and received, i.e. the caller + passes in a value which is modified. Mapped to D-Bus, an "inout" + argument is equivalent to an "in" argument, followed by an "out" + argument. You can't pass things "by reference" over the wire, so + "inout" is purely an illusion of the in-process API. + </para> + <para> + Given a method with zero or one return values, followed by zero or more + arguments, where each argument may be "in", "out", or "inout", the + caller constructs a message by appending each "in" or "inout" argument, + in order. "out" arguments are not represented in the caller's message. + </para> + <para> + The recipient constructs a reply by appending first the return value + if any, then each "out" or "inout" argument, in order. + "in" arguments are not represented in the reply message. + </para> + <para> + Error replies are normally mapped to exceptions in languages that have + exceptions. + </para> + <para> + In converting from native APIs to D-Bus, it is perhaps nice to + map D-Bus naming conventions ("FooBar") to native conventions + such as "fooBar" or "foo_bar" automatically. This is OK + as long as you can say that the native API is one that + was specifically written for D-Bus. It makes the most sense + when writing object implementations that will be exported + over the bus. Object proxies used to invoke remote D-Bus + objects probably need the ability to call any D-Bus method, + and thus a magic name mapping like this could be a problem. + </para> + <para> + This specification doesn't require anything of native API bindings; + the preceding is only a suggested convention for consistency + among bindings. + </para> + </sect4> + </sect3> + + <sect3 id="message-protocol-types-signal"> + <title>Signal Emission</title> + <para> + Unlike method calls, signal emissions have no replies. + A signal emission is simply a single message of type <literal>SIGNAL</literal>. + It must have three header fields: <literal>PATH</literal> giving the object + the signal was emitted from, plus <literal>INTERFACE</literal> and <literal>MEMBER</literal> giving + the fully-qualified name of the signal. The <literal>INTERFACE</literal> header is required + for signals, though it is optional for method calls. + </para> + </sect3> + + <sect3 id="message-protocol-types-errors"> + <title>Errors</title> + <para> + Messages of type <literal>ERROR</literal> are most commonly replies + to a <literal>METHOD_CALL</literal>, but may be returned in reply + to any kind of message. The message bus for example + will return an <literal>ERROR</literal> in reply to a signal emission if + the bus does not have enough memory to send the signal. + </para> + <para> + An <literal>ERROR</literal> may have any arguments, but if the first + argument is a <literal>STRING</literal>, it must be an error message. + The error message may be logged or shown to the user + in some way. + </para> + </sect3> + + <sect3 id="message-protocol-types-notation"> + <title>Notation in this document</title> + <para> + This document uses a simple pseudo-IDL to describe particular method + calls and signals. Here is an example of a method call: + <programlisting> + org.freedesktop.DBus.StartServiceByName (in STRING name, in UINT32 flags, + out UINT32 resultcode) + </programlisting> + This means <literal>INTERFACE</literal> = org.freedesktop.DBus, <literal>MEMBER</literal> = StartServiceByName, + <literal>METHOD_CALL</literal> arguments are <literal>STRING</literal> and <literal>UINT32</literal>, <literal>METHOD_RETURN</literal> argument + is <literal>UINT32</literal>. Remember that the <literal>MEMBER</literal> field can't contain any '.' (period) + characters so it's known that the last part of the name in + the "IDL" is the member name. + </para> + <para> + In C++ that might end up looking like this: + <programlisting> + unsigned int org::freedesktop::DBus::StartServiceByName (const char *name, + unsigned int flags); + </programlisting> + or equally valid, the return value could be done as an argument: + <programlisting> + void org::freedesktop::DBus::StartServiceByName (const char *name, + unsigned int flags, + unsigned int *resultcode); + </programlisting> + It's really up to the API designer how they want to make + this look. You could design an API where the namespace wasn't used + in C++, using STL or Qt, using varargs, or whatever you wanted. + </para> + <para> + Signals are written as follows: + <programlisting> + org.freedesktop.DBus.NameLost (STRING name) + </programlisting> + Signals don't specify "in" vs. "out" because only + a single direction is possible. + </para> + <para> + It isn't especially encouraged to use this lame pseudo-IDL in actual + API implementations; you might use the native notation for the + language you're using, or you might use COM or CORBA IDL, for example. + </para> + </sect3> + </sect2> + + <sect2 id="message-protocol-handling-invalid"> + <title>Invalid Protocol and Spec Extensions</title> + + <para> + For security reasons, the D-Bus protocol should be strictly parsed and + validated, with the exception of defined extension points. Any invalid + protocol or spec violations should result in immediately dropping the + connection without notice to the other end. Exceptions should be + carefully considered, e.g. an exception may be warranted for a + well-understood idiosyncrasy of a widely-deployed implementation. In + cases where the other end of a connection is 100% trusted and known to + be friendly, skipping validation for performance reasons could also make + sense in certain cases. + </para> + + <para> + Generally speaking violations of the "must" requirements in this spec + should be considered possible attempts to exploit security, and violations + of the "should" suggestions should be considered legitimate (though perhaps + they should generate an error in some cases). + </para> + + <para> + The following extension points are built in to D-Bus on purpose and must + not be treated as invalid protocol. The extension points are intended + for use by future versions of this spec, they are not intended for third + parties. At the moment, the only way a third party could extend D-Bus + without breaking interoperability would be to introduce a way to negotiate new + feature support as part of the auth protocol, using EXTENSION_-prefixed + commands. There is not yet a standard way to negotiate features. + <itemizedlist> + <listitem> + <para> + In the authentication protocol (see <xref linkend="auth-protocol"/>) unknown + commands result in an ERROR rather than a disconnect. This enables + future extensions to the protocol. Commands starting with EXTENSION_ are + reserved for third parties. + </para> + </listitem> + <listitem> + <para> + The authentication protocol supports pluggable auth mechanisms. + </para> + </listitem> + <listitem> + <para> + The address format (see <xref linkend="addresses"/>) supports new + kinds of transport. + </para> + </listitem> + <listitem> + <para> + Messages with an unknown type (something other than + <literal>METHOD_CALL</literal>, <literal>METHOD_RETURN</literal>, + <literal>ERROR</literal>, <literal>SIGNAL</literal>) are ignored. + Unknown-type messages must still be well-formed in the same way + as the known messages, however. They still have the normal + header and body. + </para> + </listitem> + <listitem> + <para> + Header fields with an unknown or unexpected field code must be ignored, + though again they must still be well-formed. + </para> + </listitem> + <listitem> + <para> + New standard interfaces (with new methods and signals) can of course be added. + </para> + </listitem> + </itemizedlist> + </para> + + </sect2> + + </sect1> + + <sect1 id="auth-protocol"> + <title>Authentication Protocol</title> + <para> + Before the flow of messages begins, two applications must + authenticate. A simple plain-text protocol is used for + authentication; this protocol is a SASL profile, and maps fairly + directly from the SASL specification. The message encoding is + NOT used here, only plain text messages. + </para> + <para> + In examples, "C:" and "S:" indicate lines sent by the client and + server respectively. + </para> + <sect2 id="auth-protocol-overview"> + <title>Protocol Overview</title> + <para> + The protocol is a line-based protocol, where each line ends with + \r\n. Each line begins with an all-caps ASCII command name containing + only the character range [A-Z_], a space, then any arguments for the + command, then the \r\n ending the line. The protocol is + case-sensitive. All bytes must be in the ASCII character set. + + Commands from the client to the server are as follows: + + <itemizedlist> + <listitem><para>AUTH [mechanism] [initial-response]</para></listitem> + <listitem><para>CANCEL</para></listitem> + <listitem><para>BEGIN</para></listitem> + <listitem><para>DATA <data in hex encoding></para></listitem> + <listitem><para>ERROR [human-readable error explanation]</para></listitem> + </itemizedlist> + + From server to client are as follows: + + <itemizedlist> + <listitem><para>REJECTED <space-separated list of mechanism names></para></listitem> + <listitem><para>OK <GUID in hex></para></listitem> + <listitem><para>DATA <data in hex encoding></para></listitem> + <listitem><para>ERROR</para></listitem> + </itemizedlist> + </para> + <para> + Unofficial extensions to the command set must begin with the letters + "EXTENSION_", to avoid conflicts with future official commands. + For example, "EXTENSION_COM_MYDOMAIN_DO_STUFF". + </para> + </sect2> + <sect2 id="auth-nul-byte"> + <title>Special credentials-passing nul byte</title> + <para> + Immediately after connecting to the server, the client must send a + single nul byte. This byte may be accompanied by credentials + information on some operating systems that use sendmsg() with + SCM_CREDS or SCM_CREDENTIALS to pass credentials over UNIX domain + sockets. However, the nul byte must be sent even on other kinds of + socket, and even on operating systems that do not require a byte to be + sent in order to transmit credentials. The text protocol described in + this document begins after the single nul byte. If the first byte + received from the client is not a nul byte, the server may disconnect + that client. + </para> + <para> + A nul byte in any context other than the initial byte is an error; + the protocol is ASCII-only. + </para> + <para> + The credentials sent along with the nul byte may be used with the + SASL mechanism EXTERNAL. + </para> + </sect2> + <sect2 id="auth-command-auth"> + <title>AUTH command</title> + <para> + If an AUTH command has no arguments, it is a request to list + available mechanisms. The server must respond with a REJECTED + command listing the mechanisms it understands, or with an error. + </para> + <para> + If an AUTH command specifies a mechanism, and the server supports + said mechanism, the server should begin exchanging SASL + challenge-response data with the client using DATA commands. + </para> + <para> + If the server does not support the mechanism given in the AUTH + command, it must send either a REJECTED command listing the mechanisms + it does support, or an error. + </para> + <para> + If the [initial-response] argument is provided, it is intended for use + with mechanisms that have no initial challenge (or an empty initial + challenge), as if it were the argument to an initial DATA command. If + the selected mechanism has an initial challenge and [initial-response] + was provided, the server should reject authentication by sending + REJECTED. + </para> + <para> + If authentication succeeds after exchanging DATA commands, + an OK command must be sent to the client. + </para> + <para> + The first octet received by the client after the \r\n of the OK + command must be the first octet of the authenticated/encrypted + stream of D-Bus messages. + </para> + <para> + The first octet received by the server after the \r\n of the BEGIN + command from the client must be the first octet of the + authenticated/encrypted stream of D-Bus messages. + </para> + </sect2> + <sect2 id="auth-command-cancel"> + <title>CANCEL Command</title> + <para> + At any time up to sending the BEGIN command, the client may send a + CANCEL command. On receiving the CANCEL command, the server must + send a REJECTED command and abort the current authentication + exchange. + </para> + </sect2> + <sect2 id="auth-command-data"> + <title>DATA Command</title> + <para> + The DATA command may come from either client or server, and simply + contains a hex-encoded block of data to be interpreted + according to the SASL mechanism in use. + </para> + <para> + Some SASL mechanisms support sending an "empty string"; + FIXME we need some way to do this. + </para> + </sect2> + <sect2 id="auth-command-begin"> + <title>BEGIN Command</title> + <para> + The BEGIN command acknowledges that the client has received an + OK command from the server, and that the stream of messages + is about to begin. + </para> + <para> + The first octet received by the server after the \r\n of the BEGIN + command from the client must be the first octet of the + authenticated/encrypted stream of D-Bus messages. + </para> + </sect2> + <sect2 id="auth-command-rejected"> + <title>REJECTED Command</title> + <para> + The REJECTED command indicates that the current authentication + exchange has failed, and further exchange of DATA is inappropriate. + The client would normally try another mechanism, or try providing + different responses to challenges. + </para><para> + Optionally, the REJECTED command has a space-separated list of + available auth mechanisms as arguments. If a server ever provides + a list of supported mechanisms, it must provide the same list + each time it sends a REJECTED message. Clients are free to + ignore all lists received after the first. + </para> + </sect2> + <sect2 id="auth-command-ok"> + <title>OK Command</title> + <para> + The OK command indicates that the client has been authenticated, + and that further communication will be a stream of D-Bus messages + (optionally encrypted, as negotiated) rather than this protocol. + </para> + <para> + The first octet received by the client after the \r\n of the OK + command must be the first octet of the authenticated/encrypted + stream of D-Bus messages. + </para> + <para> + The client must respond to the OK command by sending a BEGIN + command, followed by its stream of messages, or by disconnecting. + The server must not accept additional commands using this protocol + after the OK command has been sent. + </para> + <para> + The OK command has one argument, which is the GUID of the server. + See <xref linkend="addresses"/> for more on server GUIDs. + </para> + </sect2> + <sect2 id="auth-command-error"> + <title>ERROR Command</title> + <para> + The ERROR command indicates that either server or client did not + know a command, does not accept the given command in the current + context, or did not understand the arguments to the command. This + allows the protocol to be extended; a client or server can send a + command present or permitted only in new protocol versions, and if + an ERROR is received instead of an appropriate response, fall back + to using some other technique. + </para> + <para> + If an ERROR is sent, the server or client that sent the + error must continue as if the command causing the ERROR had never been + received. However, the the server or client receiving the error + should try something other than whatever caused the error; + if only canceling/rejecting the authentication. + </para> + <para> + If the D-Bus protocol changes incompatibly at some future time, + applications implementing the new protocol would probably be able to + check for support of the new protocol by sending a new command and + receiving an ERROR from applications that don't understand it. Thus the + ERROR feature of the auth protocol is an escape hatch that lets us + negotiate extensions or changes to the D-Bus protocol in the future. + </para> + </sect2> + <sect2 id="auth-examples"> + <title>Authentication examples</title> + + <para> + <figure> + <title>Example of successful magic cookie authentication</title> + <programlisting> + (MAGIC_COOKIE is a made up mechanism) + + C: AUTH MAGIC_COOKIE 3138363935333137393635383634 + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + <figure> + <title>Example of finding out mechanisms then picking one</title> + <programlisting> + C: AUTH + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + <figure> + <title>Example of client sends unknown command then falls back to regular auth</title> + <programlisting> + C: FOOBAR + S: ERROR + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + <figure> + <title>Example of server doesn't support initial auth mechanism</title> + <programlisting> + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + <figure> + <title>Example of wrong password or the like followed by successful retry</title> + <programlisting> + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: REJECTED + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + <figure> + <title>Example of skey cancelled and restarted</title> + <programlisting> + C: AUTH MAGIC_COOKIE 3736343435313230333039 + S: REJECTED KERBEROS_V4 SKEY + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: CANCEL + S: REJECTED + C: AUTH SKEY 7ab83f32ee + S: DATA 8799cabb2ea93e + C: DATA 8ac876e8f68ee9809bfa876e6f9876g8fa8e76e98f + S: OK 1234deadbeef + C: BEGIN + </programlisting> + </figure> + </para> + </sect2> + <sect2 id="auth-states"> + <title>Authentication state diagrams</title> + + <para> + This section documents the auth protocol in terms of + a state machine for the client and the server. This is + probably the most robust way to implement the protocol. + </para> + + <sect3 id="auth-states-client"> + <title>Client states</title> + + <para> + To more precisely describe the interaction between the + protocol state machine and the authentication mechanisms the + following notation is used: MECH(CHALL) means that the + server challenge CHALL was fed to the mechanism MECH, which + returns one of + + <itemizedlist> + <listitem> + <para> + CONTINUE(RESP) means continue the auth conversation + and send RESP as the response to the server; + </para> + </listitem> + + <listitem> + <para> + OK(RESP) means that after sending RESP to the server + the client side of the auth conversation is finished + and the server should return "OK"; + </para> + </listitem> + + <listitem> + <para> + ERROR means that CHALL was invalid and could not be + processed. + </para> + </listitem> + </itemizedlist> + + Both RESP and CHALL may be empty. + </para> + + <para> + The Client starts by getting an initial response from the + default mechanism and sends AUTH MECH RESP, or AUTH MECH if + the mechanism did not provide an initial response. If the + mechanism returns CONTINUE, the client starts in state + <emphasis>WaitingForData</emphasis>, if the mechanism + returns OK the client starts in state + <emphasis>WaitingForOK</emphasis>. + </para> + + <para> + The client should keep track of available mechanisms and + which it mechanisms it has already attempted. This list is + used to decide which AUTH command to send. When the list is + exhausted, the client should give up and close the + connection. + </para> + + <formalpara> + <title><emphasis>WaitingForData</emphasis></title> + <para> + <itemizedlist> + <listitem> + <para> + Receive DATA CHALL + <simplelist> + <member> + MECH(CHALL) returns CONTINUE(RESP) → send + DATA RESP, goto + <emphasis>WaitingForData</emphasis> + </member> + + <member> + MECH(CHALL) returns OK(RESP) → send DATA + RESP, goto <emphasis>WaitingForOK</emphasis> + </member> + + <member> + MECH(CHALL) returns ERROR → send ERROR + [msg], goto <emphasis>WaitingForData</emphasis> + </member> + </simplelist> + </para> + </listitem> + + <listitem> + <para> + Receive REJECTED [mechs] → + send AUTH [next mech], goto + WaitingForData or <emphasis>WaitingForOK</emphasis> + </para> + </listitem> + <listitem> + <para> + Receive ERROR → send + CANCEL, goto + <emphasis>WaitingForReject</emphasis> + </para> + </listitem> + <listitem> + <para> + Receive OK → send + BEGIN, terminate auth + conversation, authenticated + </para> + </listitem> + <listitem> + <para> + Receive anything else → send + ERROR, goto + <emphasis>WaitingForData</emphasis> + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + <formalpara> + <title><emphasis>WaitingForOK</emphasis></title> + <para> + <itemizedlist> + <listitem> + <para> + Receive OK → send BEGIN, terminate auth + conversation, <emphasis>authenticated</emphasis> + </para> + </listitem> + <listitem> + <para> + Receive REJECT [mechs] → send AUTH [next mech], + goto <emphasis>WaitingForData</emphasis> or + <emphasis>WaitingForOK</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive DATA → send CANCEL, goto + <emphasis>WaitingForReject</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive ERROR → send CANCEL, goto + <emphasis>WaitingForReject</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive anything else → send ERROR, goto + <emphasis>WaitingForOK</emphasis> + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + <formalpara> + <title><emphasis>WaitingForReject</emphasis></title> + <para> + <itemizedlist> + <listitem> + <para> + Receive REJECT [mechs] → send AUTH [next mech], + goto <emphasis>WaitingForData</emphasis> or + <emphasis>WaitingForOK</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive anything else → terminate auth + conversation, disconnect + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + </sect3> + + <sect3 id="auth-states-server"> + <title>Server states</title> + + <para> + For the server MECH(RESP) means that the client response + RESP was fed to the the mechanism MECH, which returns one of + + <itemizedlist> + <listitem> + <para> + CONTINUE(CHALL) means continue the auth conversation and + send CHALL as the challenge to the client; + </para> + </listitem> + + <listitem> + <para> + OK means that the client has been successfully + authenticated; + </para> + </listitem> + + <listitem> + <para> + REJECT means that the client failed to authenticate or + there was an error in RESP. + </para> + </listitem> + </itemizedlist> + + The server starts out in state + <emphasis>WaitingForAuth</emphasis>. If the client is + rejected too many times the server must disconnect the + client. + </para> + + <formalpara> + <title><emphasis>WaitingForAuth</emphasis></title> + <para> + <itemizedlist> + + <listitem> + <para> + Receive AUTH → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive AUTH MECH RESP + + <simplelist> + <member> + MECH not valid mechanism → send REJECTED + [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </member> + + <member> + MECH(RESP) returns CONTINUE(CHALL) → send + DATA CHALL, goto + <emphasis>WaitingForData</emphasis> + </member> + + <member> + MECH(RESP) returns OK → send OK, goto + <emphasis>WaitingForBegin</emphasis> + </member> + + <member> + MECH(RESP) returns REJECT → send REJECTED + [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </member> + </simplelist> + </para> + </listitem> + + <listitem> + <para> + Receive BEGIN → terminate + auth conversation, disconnect + </para> + </listitem> + + <listitem> + <para> + Receive ERROR → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive anything else → send + ERROR, goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + + <formalpara> + <title><emphasis>WaitingForData</emphasis></title> + <para> + <itemizedlist> + <listitem> + <para> + Receive DATA RESP + <simplelist> + <member> + MECH(RESP) returns CONTINUE(CHALL) → send + DATA CHALL, goto + <emphasis>WaitingForData</emphasis> + </member> + + <member> + MECH(RESP) returns OK → send OK, goto + <emphasis>WaitingForBegin</emphasis> + </member> + + <member> + MECH(RESP) returns REJECT → send REJECTED + [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </member> + </simplelist> + </para> + </listitem> + + <listitem> + <para> + Receive BEGIN → terminate auth conversation, + disconnect + </para> + </listitem> + + <listitem> + <para> + Receive CANCEL → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive ERROR → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive anything else → send ERROR, goto + <emphasis>WaitingForData</emphasis> + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + <formalpara> + <title><emphasis>WaitingForBegin</emphasis></title> + <para> + <itemizedlist> + <listitem> + <para> + Receive BEGIN → terminate auth conversation, + client authenticated + </para> + </listitem> + + <listitem> + <para> + Receive CANCEL → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive ERROR → send REJECTED [mechs], goto + <emphasis>WaitingForAuth</emphasis> + </para> + </listitem> + + <listitem> + <para> + Receive anything else → send ERROR, goto + <emphasis>WaitingForBegin</emphasis> + </para> + </listitem> + </itemizedlist> + </para> + </formalpara> + + </sect3> + + </sect2> + <sect2 id="auth-mechanisms"> + <title>Authentication mechanisms</title> + <para> + This section describes some new authentication mechanisms. + D-Bus also allows any standard SASL mechanism of course. + </para> + <sect3 id="auth-mechanisms-sha"> + <title>DBUS_COOKIE_SHA1</title> + <para> + The DBUS_COOKIE_SHA1 mechanism is designed to establish that a client + has the ability to read a private file owned by the user being + authenticated. If the client can prove that it has access to a secret + cookie stored in this file, then the client is authenticated. + Thus the security of DBUS_COOKIE_SHA1 depends on a secure home + directory. + </para> + <para> + Throughout this description, "hex encoding" must output the digits + from a to f in lower-case; the digits A to F must not be used + in the DBUS_COOKIE_SHA1 mechanism. + </para> + <para> + Authentication proceeds as follows: + <itemizedlist> + <listitem> + <para> + The client sends the username it would like to authenticate + as, hex-encoded. + </para> + </listitem> + <listitem> + <para> + The server sends the name of its "cookie context" (see below); a + space character; the integer ID of the secret cookie the client + must demonstrate knowledge of; a space character; then a + randomly-generated challenge string, all of this hex-encoded into + one, single string. + </para> + </listitem> + <listitem> + <para> + The client locates the cookie and generates its own + randomly-generated challenge string. The client then concatenates + the server's decoded challenge, a ":" character, its own challenge, + another ":" character, and the cookie. It computes the SHA-1 hash + of this composite string as a hex digest. It concatenates the + client's challenge string, a space character, and the SHA-1 hex + digest, hex-encodes the result and sends it back to the server. + </para> + </listitem> + <listitem> + <para> + The server generates the same concatenated string used by the + client and computes its SHA-1 hash. It compares the hash with + the hash received from the client; if the two hashes match, the + client is authenticated. + </para> + </listitem> + </itemizedlist> + </para> + <para> + Each server has a "cookie context," which is a name that identifies a + set of cookies that apply to that server. A sample context might be + "org_freedesktop_session_bus". Context names must be valid ASCII, + nonzero length, and may not contain the characters slash ("/"), + backslash ("\"), space (" "), newline ("\n"), carriage return ("\r"), + tab ("\t"), or period ("."). There is a default context, + "org_freedesktop_general" that's used by servers that do not specify + otherwise. + </para> + <para> + Cookies are stored in a user's home directory, in the directory + <filename>~/.dbus-keyrings/</filename>. This directory must + not be readable or writable by other users. If it is, + clients and servers must ignore it. The directory + contains cookie files named after the cookie context. + </para> + <para> + A cookie file contains one cookie per line. Each line + has three space-separated fields: + <itemizedlist> + <listitem> + <para> + The cookie ID number, which must be a non-negative integer and + may not be used twice in the same file. + </para> + </listitem> + <listitem> + <para> + The cookie's creation time, in UNIX seconds-since-the-epoch + format. + </para> + </listitem> + <listitem> + <para> + The cookie itself, a hex-encoded random block of bytes. The cookie + may be of any length, though obviously security increases + as the length increases. + </para> + </listitem> + </itemizedlist> + </para> + <para> + Only server processes modify the cookie file. + They must do so with this procedure: + <itemizedlist> + <listitem> + <para> + Create a lockfile name by appending ".lock" to the name of the + cookie file. The server should attempt to create this file + using <literal>O_CREAT | O_EXCL</literal>. If file creation + fails, the lock fails. Servers should retry for a reasonable + period of time, then they may choose to delete an existing lock + to keep users from having to manually delete a stale + lock. <footnote><para>Lockfiles are used instead of real file + locking <literal>fcntl()</literal> because real locking + implementations are still flaky on network + filesystems.</para></footnote> + </para> + </listitem> + <listitem> + <para> + Once the lockfile has been created, the server loads the cookie + file. It should then delete any cookies that are old (the + timeout can be fairly short), or more than a reasonable + time in the future (so that cookies never accidentally + become permanent, if the clock was set far into the future + at some point). If no recent keys remain, the + server may generate a new key. + </para> + </listitem> + <listitem> + <para> + The pruned and possibly added-to cookie file + must be resaved atomically (using a temporary + file which is rename()'d). + </para> + </listitem> + <listitem> + <para> + The lock must be dropped by deleting the lockfile. + </para> + </listitem> + </itemizedlist> + </para> + <para> + Clients need not lock the file in order to load it, + because servers are required to save the file atomically. + </para> + </sect3> + </sect2> + </sect1> + <sect1 id="addresses"> + <title>Server Addresses</title> + <para> + Server addresses consist of a transport name followed by a colon, and + then an optional, comma-separated list of keys and values in the form key=value. + Each value is escaped. + </para> + <para> + For example: + <programlisting>unix:path=/tmp/dbus-test</programlisting> + Which is the address to a unix socket with the path /tmp/dbus-test. + </para> + <para> + Value escaping is similar to URI escaping but simpler. + <itemizedlist> + <listitem> + <para> + The set of optionally-escaped bytes is: + <literal>[0-9A-Za-z_-/.\]</literal>. To escape, each + <emphasis>byte</emphasis> (note, not character) which is not in the + set of optionally-escaped bytes must be replaced with an ASCII + percent (<literal>%</literal>) and the value of the byte in hex. + The hex value must always be two digits, even if the first digit is + zero. The optionally-escaped bytes may be escaped if desired. + </para> + </listitem> + <listitem> + <para> + To unescape, append each byte in the value; if a byte is an ASCII + percent (<literal>%</literal>) character then append the following + hex value instead. It is an error if a <literal>%</literal> byte + does not have two hex digits following. It is an error if a + non-optionally-escaped byte is seen unescaped. + </para> + </listitem> + </itemizedlist> + The set of optionally-escaped bytes is intended to preserve address + readability and convenience. + </para> + + <para> + A server may specify a key-value pair with the key <literal>guid</literal> + and the value a hex-encoded 16-byte sequence. <xref linkend="uuids"/> + describes the format of the <literal>guid</literal> field. If present, + this UUID may be used to distinguish one server address from another. A + server should use a different UUID for each address it listens on. For + example, if a message bus daemon offers both UNIX domain socket and TCP + connections, but treats clients the same regardless of how they connect, + those two connections are equivalent post-connection but should have + distinct UUIDs to distinguish the kinds of connection. + </para> + + <para> + The intent of the address UUID feature is to allow a client to avoid + opening multiple identical connections to the same server, by allowing the + client to check whether an address corresponds to an already-existing + connection. Comparing two addresses is insufficient, because addresses + can be recycled by distinct servers, and equivalent addresses may look + different if simply compared as strings (for example, the host in a TCP + address can be given as an IP address or as a hostname). + </para> + + <para> + Note that the address key is <literal>guid</literal> even though the + rest of the API and documentation says "UUID," for historical reasons. + </para> + + <para> + [FIXME clarify if attempting to connect to each is a requirement + or just a suggestion] + When connecting to a server, multiple server addresses can be + separated by a semi-colon. The library will then try to connect + to the first address and if that fails, it'll try to connect to + the next one specified, and so forth. For example + <programlisting>unix:path=/tmp/dbus-test;unix:path=/tmp/dbus-test2</programlisting> + </para> + + </sect1> + + <sect1 id="transports"> + <title>Transports</title> + <para> + [FIXME we need to specify in detail each transport and its possible arguments] + + Current transports include: unix domain sockets (including + abstract namespace on linux), TCP/IP, and a debug/testing transport using + in-process pipes. Future possible transports include one that + tunnels over X11 protocol. + </para> + + <sect2 id="transports-unix-domain-sockets"> + <title>Unix Domain Sockets</title> + <para> + Unix domain sockets can be either paths in the file system or on Linux + kernels, they can be abstract which are similar to paths but + do not show up in the file system. + </para> + + <para> + When a socket is opened by the D-Bus library it truncates the path + name right before the first trailing Nul byte. This is true for both + normal paths and abstract paths. Note that this is a departure from + previous versions of D-Bus that would create sockets with a fixed + length path name. Names which were shorter than the fixed length + would be padded by Nul bytes. + </para> + </sect2> + </sect1> + + <sect1 id="naming-conventions"> + <title>Naming Conventions</title> + + <para> + D-Bus namespaces are all lowercase and correspond to reversed domain + names, as with Java. e.g. "org.freedesktop" + </para> + <para> + Interface, signal, method, and property names are "WindowsStyleCaps", note + that the first letter is capitalized, unlike Java. + </para> + <para> + Object paths are normally all lowercase with underscores used rather than + hyphens. + </para> + </sect1> + + <sect1 id="uuids"> + <title>UUIDs</title> + <para> + A working D-Bus implementation uses universally-unique IDs in two places. + First, each server address has a UUID identifying the address, + as described in <xref linkend="addresses"/>. Second, each operating + system kernel instance running a D-Bus client or server has a UUID + identifying that kernel, retrieved by invoking the method + org.freedesktop.DBus.Peer.GetMachineId() (see <xref + linkend="standard-interfaces-peer"/>). + </para> + <para> + The term "UUID" in this document is intended literally, i.e. an + identifier that is universally unique. It is not intended to refer to + RFC4122, and in fact the D-Bus UUID is not compatible with that RFC. + </para> + <para> + The UUID must contain 128 bits of data and be hex-encoded. The + hex-encoded string may not contain hyphens or other non-hex-digit + characters, and it must be exactly 32 characters long. To generate a + UUID, the current reference implementation concatenates 96 bits of random + data followed by the 32-bit time in seconds since the UNIX epoch (in big + endian byte order). + </para> + <para> + It would also be acceptable and probably better to simply generate 128 + bits of random data, as long as the random number generator is of high + quality. The timestamp could conceivably help if the random bits are not + very random. With a quality random number generator, collisions are + extremely unlikely even with only 96 bits, so it's somewhat academic. + </para> + <para> + Implementations should, however, stick to random data for the first 96 bits + of the UUID. + </para> + </sect1> + + <sect1 id="standard-interfaces"> + <title>Standard Interfaces</title> + <para> + See <xref linkend="message-protocol-types-notation"/> for details on + the notation used in this section. There are some standard interfaces + that may be useful across various D-Bus applications. + </para> + <sect2 id="standard-interfaces-peer"> + <title><literal>org.freedesktop.DBus.Peer</literal></title> + <para> + The <literal>org.freedesktop.DBus.Peer</literal> interface + has two methods: + <programlisting> + org.freedesktop.DBus.Peer.Ping () + org.freedesktop.DBus.Peer.GetMachineId (out STRING machine_uuid) + </programlisting> + </para> + <para> + On receipt of the <literal>METHOD_CALL</literal> message + <literal>org.freedesktop.DBus.Peer.Ping</literal>, an application should do + nothing other than reply with a <literal>METHOD_RETURN</literal> as + usual. It does not matter which object path a ping is sent to. The + reference implementation handles this method automatically. + </para> + <para> + On receipt of the <literal>METHOD_CALL</literal> message + <literal>org.freedesktop.DBus.Peer.GetMachineId</literal>, an application should + reply with a <literal>METHOD_RETURN</literal> containing a hex-encoded + UUID representing the identity of the machine the process is running on. + This UUID must be the same for all processes on a single system at least + until that system next reboots. It should be the same across reboots + if possible, but this is not always possible to implement and is not + guaranteed. + It does not matter which object path a GetMachineId is sent to. The + reference implementation handles this method automatically. + </para> + <para> + The UUID is intended to be per-instance-of-the-operating-system, so may represent + a virtual machine running on a hypervisor, rather than a physical machine. + Basically if two processes see the same UUID, they should also see the same + shared memory, UNIX domain sockets, process IDs, and other features that require + a running OS kernel in common between the processes. + </para> + <para> + The UUID is often used where other programs might use a hostname. Hostnames + can change without rebooting, however, or just be "localhost" - so the UUID + is more robust. + </para> + <para> + <xref linkend="uuids"/> explains the format of the UUID. + </para> + </sect2> + + <sect2 id="standard-interfaces-introspectable"> + <title><literal>org.freedesktop.DBus.Introspectable</literal></title> + <para> + This interface has one method: + <programlisting> + org.freedesktop.DBus.Introspectable.Introspect (out STRING xml_data) + </programlisting> + </para> + <para> + Objects instances may implement + <literal>Introspect</literal> which returns an XML description of + the object, including its interfaces (with signals and methods), objects + below it in the object path tree, and its properties. + </para> + <para> + <xref linkend="introspection-format"/> describes the format of this XML string. + </para> + </sect2> + <sect2 id="standard-interfaces-properties"> + <title><literal>org.freedesktop.DBus.Properties</literal></title> + <para> + Many native APIs will have a concept of object <firstterm>properties</firstterm> + or <firstterm>attributes</firstterm>. These can be exposed via the + <literal>org.freedesktop.DBus.Properties</literal> interface. + </para> + <para> + <programlisting> + org.freedesktop.DBus.Properties.Get (in STRING interface_name, + in STRING property_name, + out VARIANT value); + org.freedesktop.DBus.Properties.Set (in STRING interface_name, + in STRING property_name, + in VARIANT value); + org.freedesktop.DBus.Properties.GetAll (in STRING interface_name, + out DICT<STRING,VARIANT> props); + </programlisting> + </para> + <para> + The available properties and whether they are writable can be determined + by calling <literal>org.freedesktop.DBus.Introspectable.Introspect</literal>, + see <xref linkend="standard-interfaces-introspectable"/>. + </para> + <para> + An empty string may be provided for the interface name; in this case, + if there are multiple properties on an object with the same name, + the results are undefined (picking one by according to an arbitrary + deterministic rule, or returning an error, are the reasonable + possibilities). + </para> + </sect2> + </sect1> + + <sect1 id="introspection-format"> + <title>Introspection Data Format</title> + <para> + As described in <xref linkend="standard-interfaces-introspectable"/>, + objects may be introspected at runtime, returning an XML string + that describes the object. The same XML format may be used in + other contexts as well, for example as an "IDL" for generating + static language bindings. + </para> + <para> + Here is an example of introspection data: + <programlisting> + <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> + <node name="/org/freedesktop/sample_object"> + <interface name="org.freedesktop.SampleInterface"> + <method name="Frobate"> + <arg name="foo" type="i" direction="in"/> + <arg name="bar" type="s" direction="out"/> + <arg name="baz" type="a{us}" direction="out"/> + <annotation name="org.freedesktop.DBus.Deprecated" value="true"/> + </method> + <method name="Bazify"> + <arg name="bar" type="(iiu)" direction="in"/> + <arg name="bar" type="v" direction="out"/> + </method> + <method name="Mogrify"> + <arg name="bar" type="(iiav)" direction="in"/> + </method> + <signal name="Changed"> + <arg name="new_value" type="b"/> + </signal> + <property name="Bar" type="y" access="readwrite"/> + </interface> + <node name="child_of_sample_object"/> + <node name="another_child_of_sample_object"/> + </node> + </programlisting> + </para> + <para> + A more formal DTD and spec needs writing, but here are some quick notes. + <itemizedlist> + <listitem> + <para> + Only the root <node> element can omit the node name, as it's + known to be the object that was introspected. If the root + <node> does have a name attribute, it must be an absolute + object path. If child <node> have object paths, they must be + relative. + </para> + </listitem> + <listitem> + <para> + If a child <node> has any sub-elements, then they + must represent a complete introspection of the child. + If a child <node> is empty, then it may or may + not have sub-elements; the child must be introspected + in order to find out. The intent is that if an object + knows that its children are "fast" to introspect + it can go ahead and return their information, but + otherwise it can omit it. + </para> + </listitem> + <listitem> + <para> + The direction element on <arg> may be omitted, + in which case it defaults to "in" for method calls + and "out" for signals. Signals only allow "out" + so while direction may be specified, it's pointless. + </para> + </listitem> + <listitem> + <para> + The possible directions are "in" and "out", + unlike CORBA there is no "inout" + </para> + </listitem> + <listitem> + <para> + The possible property access flags are + "readwrite", "read", and "write" + </para> + </listitem> + <listitem> + <para> + Multiple interfaces can of course be listed for + one <node>. + </para> + </listitem> + <listitem> + <para> + The "name" attribute on arguments is optional. + </para> + </listitem> + </itemizedlist> + </para> + <para> + Method, interface, property, and signal elements may have + "annotations", which are generic key/value pairs of metadata. + They are similar conceptually to Java's annotations and C# attributes. + Well-known annotations: + </para> + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Name</entry> + <entry>Values (separated by ,)</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>org.freedesktop.DBus.Deprecated</entry> + <entry>true,false</entry> + <entry>Whether or not the entity is deprecated; defaults to false</entry> + </row> + <row> + <entry>org.freedesktop.DBus.GLib.CSymbol</entry> + <entry>(string)</entry> + <entry>The C symbol; may be used for methods and interfaces</entry> + </row> + <row> + <entry>org.freedesktop.DBus.Method.NoReply</entry> + <entry>true,false</entry> + <entry>If set, don't expect a reply to the method call; defaults to false.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </sect1> + <sect1 id="message-bus"> + <title>Message Bus Specification</title> + <sect2 id="message-bus-overview"> + <title>Message Bus Overview</title> + <para> + The message bus accepts connections from one or more applications. + Once connected, applications can exchange messages with other + applications that are also connected to the bus. + </para> + <para> + In order to route messages among connections, the message bus keeps a + mapping from names to connections. Each connection has one + unique-for-the-lifetime-of-the-bus name automatically assigned. + Applications may request additional names for a connection. Additional + names are usually "well-known names" such as + "org.freedesktop.TextEditor". When a name is bound to a connection, + that connection is said to <firstterm>own</firstterm> the name. + </para> + <para> + The bus itself owns a special name, <literal>org.freedesktop.DBus</literal>. + This name routes messages to the bus, allowing applications to make + administrative requests. For example, applications can ask the bus + to assign a name to a connection. + </para> + <para> + Each name may have <firstterm>queued owners</firstterm>. When an + application requests a name for a connection and the name is already in + use, the bus will optionally add the connection to a queue waiting for + the name. If the current owner of the name disconnects or releases + the name, the next connection in the queue will become the new owner. + </para> + + <para> + This feature causes the right thing to happen if you start two text + editors for example; the first one may request "org.freedesktop.TextEditor", + and the second will be queued as a possible owner of that name. When + the first exits, the second will take over. + </para> + + <para> + Messages may have a <literal>DESTINATION</literal> field (see <xref + linkend="message-protocol-header-fields"/>). If the + <literal>DESTINATION</literal> field is present, it specifies a message + recipient by name. Method calls and replies normally specify this field. + </para> + + <para> + Signals normally do not specify a destination; they are sent to all + applications with <firstterm>message matching rules</firstterm> that + match the message. + </para> + + <para> + When the message bus receives a method call, if the + <literal>DESTINATION</literal> field is absent, the call is taken to be + a standard one-to-one message and interpreted by the message bus + itself. For example, sending an + <literal>org.freedesktop.DBus.Peer.Ping</literal> message with no + <literal>DESTINATION</literal> will cause the message bus itself to + reply to the ping immediately; the message bus will not make this + message visible to other applications. + </para> + + <para> + Continuing the <literal>org.freedesktop.DBus.Peer.Ping</literal> example, if + the ping message were sent with a <literal>DESTINATION</literal> name of + <literal>com.yoyodyne.Screensaver</literal>, then the ping would be + forwarded, and the Yoyodyne Corporation screensaver application would be + expected to reply to the ping. + </para> + </sect2> + + <sect2 id="message-bus-names"> + <title>Message Bus Names</title> + <para> + Each connection has at least one name, assigned at connection time and + returned in response to the + <literal>org.freedesktop.DBus.Hello</literal> method call. This + automatically-assigned name is called the connection's <firstterm>unique + name</firstterm>. Unique names are never reused for two different + connections to the same bus. + </para> + <para> + Ownership of a unique name is a prerequisite for interaction with + the message bus. It logically follows that the unique name is always + the first name that an application comes to own, and the last + one that it loses ownership of. + </para> + <para> + Unique connection names must begin with the character ':' (ASCII colon + character); bus names that are not unique names must not begin + with this character. (The bus must reject any attempt by an application + to manually request a name beginning with ':'.) This restriction + categorically prevents "spoofing"; messages sent to a unique name + will always go to the expected connection. + </para> + <para> + When a connection is closed, all the names that it owns are deleted (or + transferred to the next connection in the queue if any). + </para> + <para> + A connection can request additional names to be associated with it using + the <literal>org.freedesktop.DBus.RequestName</literal> message. <xref + linkend="message-protocol-names-bus"/> describes the format of a valid + name. These names can be released again using the + <literal>org.freedesktop.DBus.ReleaseName</literal> message. + </para> + + <sect3 id="bus-messages-request-name"> + <title><literal>org.freedesktop.DBus.RequestName</literal></title> + <para> + As a method: + <programlisting> + UINT32 RequestName (in STRING name, in UINT32 flags) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name to request</entry> + </row> + <row> + <entry>1</entry> + <entry>UINT32</entry> + <entry>Flags</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>UINT32</entry> + <entry>Return value</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + This method call should be sent to + <literal>org.freedesktop.DBus</literal> and asks the message bus to + assign the given name to the method caller. Each name maintains a + queue of possible owners, where the head of the queue is the primary + or current owner of the name. Each potential owner in the queue + maintains the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and + DBUS_NAME_FLAG_DO_NOT_QUEUE settings from its latest RequestName + call. When RequestName is invoked the following occurs: + <itemizedlist> + <listitem> + <para> + If the method caller is currently the primary owner of the name, + the DBUS_NAME_FLAG_ALLOW_REPLACEMENT and DBUS_NAME_FLAG_DO_NOT_QUEUE + values are updated with the values from the new RequestName call, + and nothing further happens. + </para> + </listitem> + + <listitem> + <para> + If the current primary owner (head of the queue) has + DBUS_NAME_FLAG_ALLOW_REPLACEMENT set, and the RequestName + invocation has the DBUS_NAME_FLAG_REPLACE_EXISTING flag, then + the caller of RequestName replaces the current primary owner at + the head of the queue and the current primary owner moves to the + second position in the queue. If the caller of RequestName was + in the queue previously its flags are updated with the values from + the new RequestName in addition to moving it to the head of the queue. + </para> + </listitem> + + <listitem> + <para> + If replacement is not possible, and the method caller is + currently in the queue but not the primary owner, its flags are + updated with the values from the new RequestName call. + </para> + </listitem> + + <listitem> + <para> + If replacement is not possible, and the method caller is + currently not in the queue, the method caller is appended to the + queue. + </para> + </listitem> + + <listitem> + <para> + If any connection in the queue has DBUS_NAME_FLAG_DO_NOT_QUEUE + set and is not the primary owner, it is removed from the + queue. This can apply to the previous primary owner (if it + was replaced) or the method caller (if it updated the + DBUS_NAME_FLAG_DO_NOT_QUEUE flag while still stuck in the + queue, or if it was just added to the queue with that flag set). + </para> + </listitem> + </itemizedlist> + </para> + <para> + Note that DBUS_NAME_FLAG_REPLACE_EXISTING results in "jumping the + queue," even if another application already in the queue had specified + DBUS_NAME_FLAG_REPLACE_EXISTING. This comes up if a primary owner + that does not allow replacement goes away, and the next primary owner + does allow replacement. In this case, queued items that specified + DBUS_NAME_FLAG_REPLACE_EXISTING <emphasis>do not</emphasis> + automatically replace the new primary owner. In other words, + DBUS_NAME_FLAG_REPLACE_EXISTING is not saved, it is only used at the + time RequestName is called. This is deliberate to avoid an infinite loop + anytime two applications are both DBUS_NAME_FLAG_ALLOW_REPLACEMENT + and DBUS_NAME_FLAG_REPLACE_EXISTING. + </para> + <para> + The flags argument contains any of the following values logically ORed + together: + + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>DBUS_NAME_FLAG_ALLOW_REPLACEMENT</entry> + <entry>0x1</entry> + <entry> + + If an application A specifies this flag and succeeds in + becoming the owner of the name, and another application B + later calls RequestName with the + DBUS_NAME_FLAG_REPLACE_EXISTING flag, then application A + will lose ownership and receive a + <literal>org.freedesktop.DBus.NameLost</literal> signal, and + application B will become the new owner. If DBUS_NAME_FLAG_ALLOW_REPLACEMENT + is not specified by application A, or DBUS_NAME_FLAG_REPLACE_EXISTING + is not specified by application B, then application B will not replace + application A as the owner. + + </entry> + </row> + <row> + <entry>DBUS_NAME_FLAG_REPLACE_EXISTING</entry> + <entry>0x2</entry> + <entry> + + Try to replace the current owner if there is one. If this + flag is not set the application will only become the owner of + the name if there is no current owner. If this flag is set, + the application will replace the current owner if + the current owner specified DBUS_NAME_FLAG_ALLOW_REPLACEMENT. + + </entry> + </row> + <row> + <entry>DBUS_NAME_FLAG_DO_NOT_QUEUE</entry> + <entry>0x4</entry> + <entry> + + Without this flag, if an application requests a name that is + already owned, the application will be placed in a queue to + own the name when the current owner gives it up. If this + flag is given, the application will not be placed in the + queue, the request for the name will simply fail. This flag + also affects behavior when an application is replaced as + name owner; by default the application moves back into the + waiting queue, unless this flag was provided when the application + became the name owner. + + </entry> + </row> + </tbody> + </tgroup> + </informaltable> + + The return code can be one of the following values: + + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER</entry> + <entry>1</entry> <entry>The caller is now the primary owner of + the name, replacing any previous owner. Either the name had no + owner before, or the caller specified + DBUS_NAME_FLAG_REPLACE_EXISTING and the current owner specified + DBUS_NAME_FLAG_ALLOW_REPLACEMENT.</entry> + </row> + <row> + <entry>DBUS_REQUEST_NAME_REPLY_IN_QUEUE</entry> + <entry>2</entry> + + <entry>The name already had an owner, + DBUS_NAME_FLAG_DO_NOT_QUEUE was not specified, and either + the current owner did not specify + DBUS_NAME_FLAG_ALLOW_REPLACEMENT or the requesting + application did not specify DBUS_NAME_FLAG_REPLACE_EXISTING. + </entry> + </row> + <row> + <entry>DBUS_REQUEST_NAME_REPLY_EXISTS</entry> <entry>3</entry> + <entry>The name already has an owner, + DBUS_NAME_FLAG_DO_NOT_QUEUE was specified, and either + DBUS_NAME_FLAG_ALLOW_REPLACEMENT was not specified by the + current owner, or DBUS_NAME_FLAG_REPLACE_EXISTING was not + specified by the requesting application.</entry> + </row> + <row> + <entry>DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER</entry> + <entry>4</entry> + <entry>The application trying to request ownership of a name is already the owner of it.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + </sect3> + + <sect3 id="bus-messages-release-name"> + <title><literal>org.freedesktop.DBus.ReleaseName</literal></title> + <para> + As a method: + <programlisting> + UINT32 ReleaseName (in STRING name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name to release</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>UINT32</entry> + <entry>Return value</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + This method call should be sent to + <literal>org.freedesktop.DBus</literal> and asks the message bus to + release the method caller's claim to the given name. If the caller is + the primary owner, a new primary owner will be selected from the + queue if any other owners are waiting. If the caller is waiting in + the queue for the name, the caller will removed from the queue and + will not be made an owner of the name if it later becomes available. + If there are no other owners in the queue for the name, it will be + removed from the bus entirely. + + The return code can be one of the following values: + + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Conventional Name</entry> + <entry>Value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>DBUS_RELEASE_NAME_REPLY_RELEASED</entry> + <entry>1</entry> <entry>The caller has released his claim on + the given name. Either the caller was the primary owner of + the name, and the name is now unused or taken by somebody + waiting in the queue for the name, or the caller was waiting + in the queue for the name and has now been removed from the + queue.</entry> + </row> + <row> + <entry>DBUS_RELEASE_NAME_REPLY_NON_EXISTENT</entry> + <entry>2</entry> + <entry>The given name does not exist on this bus.</entry> + </row> + <row> + <entry>DBUS_RELEASE_NAME_REPLY_NOT_OWNER</entry> + <entry>3</entry> + <entry>The caller was not the primary owner of this name, + and was also not waiting in the queue to own this name.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + </sect3> + </sect2> + + <sect2 id="message-bus-routing"> + <title>Message Bus Message Routing</title> + <para> + FIXME + </para> + <sect3 id="message-bus-routing-match-rules"> + <title>Match Rules</title> + <para> + An important part of the message bus routing protocol is match + rules. Match rules describe what messages can be sent to a client + based on the contents of the message. When a message is routed + through the bus it is compared to clients' match rules. If any + of the rules match, the message is dispatched to the client. + If none of the rules match the message never leaves the bus. This + is an effective way to control traffic over the bus and to make sure + only relevant message need to be processed by the client. + </para> + <para> + Match rules are added using the AddMatch bus method + (see xref linkend="bus-messages-add-match"/>). Rules are + specified as a string of comma separated key/value pairs. + Excluding a key from the rule indicates a wildcard match. + For instance excluding the the member from a match rule but + adding a sender would let all messages from that sender through. + An example of a complete rule would be + "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo',path='/bar/foo',destination=':452345.34',arg2='bar'" + </para> + <para> + The following table describes the keys that can be used to create + a match rule: + The following table summarizes the D-Bus types. + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Key</entry> + <entry>Possible Values</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry><literal>type</literal></entry> + <entry>'signal', 'method_call', 'method_return', 'error'</entry> + <entry>Match on the message type. An example of a type match is type='signal'</entry> + </row> + <row> + <entry><literal>sender</literal></entry> + <entry>A bus or unique name (see <xref linkend="term-bus-name"/> + and <xref linkend="term-unique-name"/> respectively) + </entry> + <entry>Match messages sent by a particular sender. An example of a sender match + is sender='org.freedesktop.Hal'</entry> + </row> + <row> + <entry><literal>interface</literal></entry> + <entry>An interface name (see <xref linkend="message-protocol-names-interface"/>)</entry> + <entry>Match messages sent over or to a particular interface. An example of an + interface match is interface='org.freedesktop.Hal.Manager'. + If a message omits the interface header, it must not match any rule + that specifies this key.</entry> + </row> + <row> + <entry><literal>member</literal></entry> + <entry>Any valid method or signal name</entry> + <entry>Matches messages which have the give method or signal name. An example of + a member match is member='NameOwnerChanged'</entry> + </row> + <row> + <entry><literal>path</literal></entry> + <entry>An object path (see <xref linkend="message-protocol-marshaling-object-path"/>)</entry> + <entry>Matches messages which are sent from or to the given object. An example of a + path match is path='/org/freedesktop/Hal/Manager'</entry> + </row> + <row> + <entry><literal>destination</literal></entry> + <entry>A unique name (see <xref linkend="term-unique-name"/>)</entry> + <entry>Matches messages which are being sent to the given unique name. An + example of a destination match is destination=':1.0'</entry> + </row> + <row> + <entry><literal>arg[0, 1, 2, 3, ...]</literal></entry> + <entry>Any string</entry> + <entry>Arg matches are special and are used for further restricting the + match based on the arguments in the body of a message. As of this time + only string arguments can be matched. An example of an argument match + would be arg3='Foo'. Only argument indexes from 0 to 63 should be + accepted.</entry> + </row> + <row> + <entry><literal>arg[0, 1, 2, 3, ...]path</literal></entry> + <entry>Any string</entry> + <entry>Argument path matches provide a specialised form of wildcard + matching for path-like namespaces. As with normal argument matches, + if the argument is exactly equal to the string given in the match + rule then the rule is satisfied. Additionally, there is also a + match when either the string given in the match rule or the + appropriate message argument ends with '/' and is a prefix of the + other. An example argument path match is arg0path='/aa/bb/'. This + would match messages with first arguments of '/', '/aa/', + '/aa/bb/', '/aa/bb/cc/' and '/aa/bb/cc'. It would not match + messages with first arguments of '/aa/b', '/aa' or even '/aa/bb'.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + </sect3> + </sect2> + <sect2 id="message-bus-starting-services"> + <title>Message Bus Starting Services</title> + <para> + The message bus can start applications on behalf of other applications. + In CORBA terms, this would be called <firstterm>activation</firstterm>. + An application that can be started in this way is called a + <firstterm>service</firstterm>. + </para> + <para> + With D-Bus, starting a service is normally done by name. That is, + applications ask the message bus to start some program that will own a + well-known name, such as <literal>org.freedesktop.TextEditor</literal>. + This implies a contract documented along with the name + <literal>org.freedesktop.TextEditor</literal> for which objects + the owner of that name will provide, and what interfaces those + objects will have. + </para> + <para> + To find an executable corresponding to a particular name, the bus daemon + looks for <firstterm>service description files</firstterm>. Service + description files define a mapping from names to executables. Different + kinds of message bus will look for these files in different places, see + <xref linkend="message-bus-types"/>. + </para> + <para> + [FIXME the file format should be much better specified than "similar to + .desktop entries" esp. since desktop entries are already + badly-specified. ;-)] Service description files have the ".service" file + extension. The message bus will only load service description files + ending with .service; all other files will be ignored. The file format + is similar to that of <ulink + url="http://www.freedesktop.org/standards/desktop-entry-spec/desktop-entry-spec.html">desktop + entries</ulink>. All service description files must be in UTF-8 + encoding. To ensure that there will be no name collisions, service files + must be namespaced using the same mechanism as messages and service + names. + + <figure> + <title>Example service description file</title> + <programlisting> + # Sample service description file + [D-BUS Service] + Names=org.freedesktop.ConfigurationDatabase;org.gnome.GConf; + Exec=/usr/libexec/gconfd-2 + </programlisting> + </figure> + </para> + <para> + When an application asks to start a service by name, the bus daemon tries to + find a service that will own that name. It then tries to spawn the + executable associated with it. If this fails, it will report an + error. [FIXME what happens if two .service files offer the same service; + what kind of error is reported, should we have a way for the client to + choose one?] + </para> + <para> + The executable launched will have the environment variable + <literal>DBUS_STARTER_ADDRESS</literal> set to the address of the + message bus so it can connect and request the appropriate names. + </para> + <para> + The executable being launched may want to know whether the message bus + starting it is one of the well-known message buses (see <xref + linkend="message-bus-types"/>). To facilitate this, the bus must also set + the <literal>DBUS_STARTER_BUS_TYPE</literal> environment variable if it is one + of the well-known buses. The currently-defined values for this variable + are <literal>system</literal> for the systemwide message bus, + and <literal>session</literal> for the per-login-session message + bus. The new executable must still connect to the address given + in <literal>DBUS_STARTER_ADDRESS</literal>, but may assume that the + resulting connection is to the well-known bus. + </para> + <para> + [FIXME there should be a timeout somewhere, either specified + in the .service file, by the client, or just a global value + and if the client being activated fails to connect within that + timeout, an error should be sent back.] + </para> + + <sect3 id="message-bus-starting-services-scope"> + <title>Message Bus Service Scope</title> + <para> + The "scope" of a service is its "per-", such as per-session, + per-machine, per-home-directory, or per-display. The reference + implementation doesn't yet support starting services in a different + scope from the message bus itself. So e.g. if you start a service + on the session bus its scope is per-session. + </para> + <para> + We could add an optional scope to a bus name. For example, for + per-(display,session pair), we could have a unique ID for each display + generated automatically at login and set on screen 0 by executing a + special "set display ID" binary. The ID would be stored in a + <literal>_DBUS_DISPLAY_ID</literal> property and would be a string of + random bytes. This ID would then be used to scope names. + Starting/locating a service could be done by ID-name pair rather than + only by name. + </para> + <para> + Contrast this with a per-display scope. To achieve that, we would + want a single bus spanning all sessions using a given display. + So we might set a <literal>_DBUS_DISPLAY_BUS_ADDRESS</literal> + property on screen 0 of the display, pointing to this bus. + </para> + </sect3> + </sect2> + + <sect2 id="message-bus-types"> + <title>Well-known Message Bus Instances</title> + <para> + Two standard message bus instances are defined here, along with how + to locate them and where their service files live. + </para> + <sect3 id="message-bus-types-login"> + <title>Login session message bus</title> + <para> + Each time a user logs in, a <firstterm>login session message + bus</firstterm> may be started. All applications in the user's login + session may interact with one another using this message bus. + </para> + <para> + The address of the login session message bus is given + in the <literal>DBUS_SESSION_BUS_ADDRESS</literal> environment + variable. If that variable is not set, applications may + also try to read the address from the X Window System root + window property <literal>_DBUS_SESSION_BUS_ADDRESS</literal>. + The root window property must have type <literal>STRING</literal>. + The environment variable should have precedence over the + root window property. + </para> + <para> + [FIXME specify location of .service files, probably using + DESKTOP_DIRS etc. from basedir specification, though login session + bus is not really desktop-specific] + </para> + </sect3> + <sect3 id="message-bus-types-system"> + <title>System message bus</title> + <para> + A computer may have a <firstterm>system message bus</firstterm>, + accessible to all applications on the system. This message bus may be + used to broadcast system events, such as adding new hardware devices, + changes in the printer queue, and so forth. + </para> + <para> + The address of the system message bus is given + in the <literal>DBUS_SYSTEM_BUS_ADDRESS</literal> environment + variable. If that variable is not set, applications should try + to connect to the well-known address + <literal>unix:path=/var/run/dbus/system_bus_socket</literal>. + <footnote> + <para> + The D-Bus reference implementation actually honors the + <literal>$(localstatedir)</literal> configure option + for this address, on both client and server side. + </para> + </footnote> + </para> + <para> + [FIXME specify location of system bus .service files] + </para> + </sect3> + </sect2> + + <sect2 id="message-bus-messages"> + <title>Message Bus Messages</title> + <para> + The special message bus name <literal>org.freedesktop.DBus</literal> + responds to a number of additional messages. + </para> + + <sect3 id="bus-messages-hello"> + <title><literal>org.freedesktop.DBus.Hello</literal></title> + <para> + As a method: + <programlisting> + STRING Hello () + </programlisting> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Unique name assigned to the connection</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + Before an application is able to send messages to other applications + it must send the <literal>org.freedesktop.DBus.Hello</literal> message + to the message bus to obtain a unique name. If an application without + a unique name tries to send a message to another application, or a + message to the message bus itself that isn't the + <literal>org.freedesktop.DBus.Hello</literal> message, it will be + disconnected from the bus. + </para> + <para> + There is no corresponding "disconnect" request; if a client wishes to + disconnect from the bus, it simply closes the socket (or other + communication channel). + </para> + </sect3> + <sect3 id="bus-messages-list-names"> + <title><literal>org.freedesktop.DBus.ListNames</literal></title> + <para> + As a method: + <programlisting> + ARRAY of STRING ListNames () + </programlisting> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>ARRAY of STRING</entry> + <entry>Array of strings where each string is a bus name</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + Returns a list of all currently-owned names on the bus. + </para> + </sect3> + <sect3 id="bus-messages-list-activatable-names"> + <title><literal>org.freedesktop.DBus.ListActivatableNames</literal></title> + <para> + As a method: + <programlisting> + ARRAY of STRING ListActivatableNames () + </programlisting> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>ARRAY of STRING</entry> + <entry>Array of strings where each string is a bus name</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + Returns a list of all names that can be activated on the bus. + </para> + </sect3> + <sect3 id="bus-messages-name-exists"> + <title><literal>org.freedesktop.DBus.NameHasOwner</literal></title> + <para> + As a method: + <programlisting> + BOOLEAN NameHasOwner (in STRING name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name to check</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>BOOLEAN</entry> + <entry>Return value, true if the name exists</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + Checks if the specified name exists (currently has an owner). + </para> + </sect3> + + <sect3 id="bus-messages-name-owner-changed"> + <title><literal>org.freedesktop.DBus.NameOwnerChanged</literal></title> + <para> + This is a signal: + <programlisting> + NameOwnerChanged (STRING name, STRING old_owner, STRING new_owner) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name with a new owner</entry> + </row> + <row> + <entry>1</entry> + <entry>STRING</entry> + <entry>Old owner or empty string if none</entry> + </row> + <row> + <entry>2</entry> + <entry>STRING</entry> + <entry>New owner or empty string if none</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + This signal indicates that the owner of a name has changed. + It's also the signal to use to detect the appearance of + new names on the bus. + </para> + </sect3> + <sect3 id="bus-messages-name-lost"> + <title><literal>org.freedesktop.DBus.NameLost</literal></title> + <para> + This is a signal: + <programlisting> + NameLost (STRING name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name which was lost</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + This signal is sent to a specific application when it loses + ownership of a name. + </para> + </sect3> + + <sect3 id="bus-messages-name-acquired"> + <title><literal>org.freedesktop.DBus.NameAcquired</literal></title> + <para> + This is a signal: + <programlisting> + NameAcquired (STRING name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name which was acquired</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + <para> + This signal is sent to a specific application when it gains + ownership of a name. + </para> + </sect3> + + <sect3 id="bus-messages-start-service-by-name"> + <title><literal>org.freedesktop.DBus.StartServiceByName</literal></title> + <para> + As a method: + <programlisting> + UINT32 StartServiceByName (in STRING name, in UINT32 flags) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name of the service to start</entry> + </row> + <row> + <entry>1</entry> + <entry>UINT32</entry> + <entry>Flags (currently not used)</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>UINT32</entry> + <entry>Return value</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Tries to launch the executable associated with a name. For more information, see <xref linkend="message-bus-starting-services"/>. + + </para> + <para> + The return value can be one of the following values: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Identifier</entry> + <entry>Value</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>DBUS_START_REPLY_SUCCESS</entry> + <entry>1</entry> + <entry>The service was successfully started.</entry> + </row> + <row> + <entry>DBUS_START_REPLY_ALREADY_RUNNING</entry> + <entry>2</entry> + <entry>A connection already owns the given name.</entry> + </row> + </tbody> + </tgroup> + </informaltable> + </para> + + </sect3> + + <sect3 id="bus-messages-update-activation-environment"> + <title><literal>org.freedesktop.DBus.UpdateActivationEnvironment</literal></title> + <para> + As a method: + <programlisting> + UpdateActivationEnvironment (in ARRAY of DICT<STRING,STRING> environment) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>ARRAY of DICT<STRING,STRING></entry> + <entry>Environment to add or update</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Normally, session bus activated services inherit the environment of the bus daemon. This method adds to or modifies that environment when activating services. + </para> + <para> + Some bus instances, such as the standard system bus, may disable access to this method for some or all callers. + </para> + + </sect3> + + <sect3 id="bus-messages-get-name-owner"> + <title><literal>org.freedesktop.DBus.GetNameOwner</literal></title> + <para> + As a method: + <programlisting> + STRING GetNameOwner (in STRING name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name to get the owner of</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Return value, a unique connection name</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Returns the unique connection name of the primary owner of the name + given. If the requested name doesn't have an owner, returns a + <literal>org.freedesktop.DBus.Error.NameHasNoOwner</literal> error. + </para> + </sect3> + + <sect3 id="bus-messages-get-connection-unix-user"> + <title><literal>org.freedesktop.DBus.GetConnectionUnixUser</literal></title> + <para> + As a method: + <programlisting> + UINT32 GetConnectionUnixUser (in STRING connection_name) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Name of the connection to query</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>UINT32</entry> + <entry>unix user id</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Returns the unix uid of the process connected to the server. If unable to + determine it, a <literal>org.freedesktop.DBus.Error.Failed</literal> + error is returned. + </para> + </sect3> + + <sect3 id="bus-messages-add-match"> + <title><literal>org.freedesktop.DBus.AddMatch</literal></title> + <para> + As a method: + <programlisting> + AddMatch (in STRING rule) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Match rule to add to the connection</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Adds a match rule to match messages going through the message bus (see <xref linkend='message-bus-routing-match-rules'/>). + If the bus does not have enough resources the <literal>org.freedesktop.DBus.Error.OOM</literal> + error is returned. + </para> + </sect3> + <sect3 id="bus-messages-remove-match"> + <title><literal>org.freedesktop.DBus.RemoveMatch</literal></title> + <para> + As a method: + <programlisting> + RemoveMatch (in STRING rule) + </programlisting> + Message arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Match rule to remove from the connection</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Removes the first rule that matches (see <xref linkend='message-bus-routing-match-rules'/>). + If the rule is not found the <literal>org.freedesktop.DBus.Error.MatchRuleNotFound</literal> + error is returned. + </para> + </sect3> + + <sect3 id="bus-messages-get-id"> + <title><literal>org.freedesktop.DBus.GetId</literal></title> + <para> + As a method: + <programlisting> + GetId (out STRING id) + </programlisting> + Reply arguments: + <informaltable> + <tgroup cols="3"> + <thead> + <row> + <entry>Argument</entry> + <entry>Type</entry> + <entry>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0</entry> + <entry>STRING</entry> + <entry>Unique ID identifying the bus daemon</entry> + </row> + </tbody> + </tgroup> + </informaltable> + Gets the unique ID of the bus. The unique ID here is shared among all addresses the + bus daemon is listening on (TCP, UNIX domain socket, etc.) and its format is described in + <xref linkend="uuids"/>. Each address the bus is listening on also has its own unique + ID, as described in <xref linkend="addresses"/>. The per-bus and per-address IDs are not related. + There is also a per-machine ID, described in <xref linkend="standard-interfaces-peer"/> and returned + by org.freedesktop.DBus.Peer.GetMachineId(). + For a desktop session bus, the bus ID can be used as a way to uniquely identify a user's session. + </para> + </sect3> + + </sect2> + + </sect1> +<!-- + <appendix id="implementation-notes"> + <title>Implementation notes</title> + <sect1 id="implementation-notes-subsection"> + <title></title> + <para> + </para> + </sect1> + </appendix> +--> + + <glossary><title>Glossary</title> + <para> + This glossary defines some of the terms used in this specification. + </para> + + <glossentry id="term-bus-name"><glossterm>Bus Name</glossterm> + <glossdef> + <para> + The message bus maintains an association between names and + connections. (Normally, there's one connection per application.) A + bus name is simply an identifier used to locate connections. For + example, the hypothetical <literal>com.yoyodyne.Screensaver</literal> + name might be used to send a message to a screensaver from Yoyodyne + Corporation. An application is said to <firstterm>own</firstterm> a + name if the message bus has associated the application's connection + with the name. Names may also have <firstterm>queued + owners</firstterm> (see <xref linkend="term-queued-owner"/>). + The bus assigns a unique name to each connection, + see <xref linkend="term-unique-name"/>. Other names + can be thought of as "well-known names" and are + used to find applications that offer specific functionality. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-message"><glossterm>Message</glossterm> + <glossdef> + <para> + A message is the atomic unit of communication via the D-Bus + protocol. It consists of a <firstterm>header</firstterm> and a + <firstterm>body</firstterm>; the body is made up of + <firstterm>arguments</firstterm>. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-message-bus"><glossterm>Message Bus</glossterm> + <glossdef> + <para> + The message bus is a special application that forwards + or routes messages between a group of applications + connected to the message bus. It also manages + <firstterm>names</firstterm> used for routing + messages. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-name"><glossterm>Name</glossterm> + <glossdef> + <para> + See <xref linkend="term-bus-name"/>. "Name" may + also be used to refer to some of the other names + in D-Bus, such as interface names. + </para> + </glossdef> + </glossentry> + + <glossentry id="namespace"><glossterm>Namespace</glossterm> + <glossdef> + <para> + Used to prevent collisions when defining new interfaces or bus + names. The convention used is the same one Java uses for defining + classes: a reversed domain name. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-object"><glossterm>Object</glossterm> + <glossdef> + <para> + Each application contains <firstterm>objects</firstterm>, which have + <firstterm>interfaces</firstterm> and + <firstterm>methods</firstterm>. Objects are referred to by a name, + called a <firstterm>path</firstterm>. + </para> + </glossdef> + </glossentry> + + <glossentry id="one-to-one"><glossterm>One-to-One</glossterm> + <glossdef> + <para> + An application talking directly to another application, without going + through a message bus. One-to-one connections may be "peer to peer" or + "client to server." The D-Bus protocol has no concept of client + vs. server after a connection has authenticated; the flow of messages + is symmetrical (full duplex). + </para> + </glossdef> + </glossentry> + + <glossentry id="term-path"><glossterm>Path</glossterm> + <glossdef> + <para> + Object references (object names) in D-Bus are organized into a + filesystem-style hierarchy, so each object is named by a path. As in + LDAP, there's no difference between "files" and "directories"; a path + can refer to an object, while still having child objects below it. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-queued-owner"><glossterm>Queued Name Owner</glossterm> + <glossdef> + <para> + Each bus name has a primary owner; messages sent to the name go to the + primary owner. However, certain names also maintain a queue of + secondary owners "waiting in the wings." If the primary owner releases + the name, then the first secondary owner in the queue automatically + becomes the new owner of the name. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-service"><glossterm>Service</glossterm> + <glossdef> + <para> + A service is an executable that can be launched by the bus daemon. + Services normally guarantee some particular features, for example they + may guarantee that they will request a specific name such as + "org.freedesktop.Screensaver", have a singleton object + "/org/freedesktop/Application", and that object will implement the + interface "org.freedesktop.ScreensaverControl". + </para> + </glossdef> + </glossentry> + + <glossentry id="term-service-description-files"><glossterm>Service Description Files</glossterm> + <glossdef> + <para> + ".service files" tell the bus about service applications that can be + launched (see <xref linkend="term-service"/>). Most importantly they + provide a mapping from bus names to services that will request those + names when they start up. + </para> + </glossdef> + </glossentry> + + <glossentry id="term-unique-name"><glossterm>Unique Connection Name</glossterm> + <glossdef> + <para> + The special name automatically assigned to each connection by the + message bus. This name will never change owner, and will be unique + (never reused during the lifetime of the message bus). + It will begin with a ':' character. + </para> + </glossdef> + </glossentry> + + </glossary> +</article> + |