D-Bus bindings for Rust
=======================

[![crates.io](https://img.shields.io/crates/v/dbus.svg)](https://crates.io/crates/dbus)
[![API documentation](https://docs.rs/dbus/badge.svg)](https://docs.rs/dbus)
[![license](https://img.shields.io/crates/l/dbus.svg)](https://crates.io/crates/dbus)
[![Github CI](https://github.com/diwic/dbus-rs/actions/workflows/dbus-rs-github-ci.yml/badge.svg)](https://github.com/diwic/dbus-rs/actions/workflows/dbus-rs-github-ci.yml/badge.svg)

 * Use `blocking::Connection` to connect to the session or system bus. (Or `SyncConnection` / `LocalConnection`)
 * Use `Message` to send and receive messages. Get and append arguments of all types, see the [argument guide](dbus/examples/argument_guide.md) for details.
 * Build method dispatching servers using the `dbus-crossroads` or `dbus-tree` crates.
   Standard D-Bus interfaces (introspection, properties, object manager) are supported.

Breaking changes
----------------

The main dbus crate is fairly mature and the features you need should be all there. Breaking changes can still happen, but not often.

 * In 0.9, the `dbus::tree` module moved to the `dbus-tree` crate (but consider migrating to `dbus-crossroads` instead).
 * If you're currently using 0.6.x of dbus and want to upgrade to later versions, you can read [changes in dbus-rs 0.7](dbus/changes-in-0.7.md).


Additional crates
-----------------

 * [dbus-crossroads](http://crates.io/crates/dbus-crossroads/) for easy building of method
    dispatching servers. [![API documentation](https://docs.rs/dbus-crossroads/badge.svg)](https://docs.rs/dbus-crossroads)
 * [dbus-tokio](http://crates.io/crates/dbus-tokio/) integrates D-Bus with [Tokio](http://tokio.rs). [![API documentation](https://docs.rs/dbus-tokio/badge.svg)](https://docs.rs/dbus-tokio)
 * [dbus-codegen](http://crates.io/crates/dbus-codegen/) installs a binary tool which generates Rust code from D-Bus XML introspection data. The [readme](https://github.com/diwic/dbus-rs/tree/master/dbus-codegen) contains an introduction to how to use it.
 * [libdbus-sys](http://crates.io/crates/libdbus-sys/) contains the raw FFI bindings to libdbus.
 * [dbus-tree](http://crates.io/crates/dbus-tree/) facitilates easy building of method
    dispatching servers (legacy design). [![API documentation](https://docs.rs/dbus-tree/badge.svg)](https://docs.rs/dbus-tree)

Invitation
----------

You are hereby invited to participate in the development of these crates:

 * If you have discovered what you believe is a bug, [file an issue](https://github.com/diwic/dbus-rs/issues).
 * If you have questions or comments that the documentation cannot answer in an easy way, [start a discussion](https://github.com/diwic/dbus-rs/discussions).
 * If you have smaller improvements to code, documentation, examples etc, go ahead and [submit a pull request](https://github.com/diwic/dbus-rs/pulls).
   Larger pieces of work are better off discussed first.

The code is Apache 2.0 / MIT dual licensed. Any code submitted in Pull Requests, discussions or issues is assumed to have this license,
unless explicitly stated otherwise.


Examples
========

Client
------

This example opens a connection to the session bus and asks for a list of all names currently present.

```rust
use dbus::blocking::Connection;
use std::time::Duration;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // First open up a connection to the session bus.
    let conn = Connection::new_session()?;

    // Second, create a wrapper struct around the connection that makes it easy
    // to send method calls to a specific destination and path.
    let proxy = conn.with_proxy("org.freedesktop.DBus", "/", Duration::from_millis(5000));

    // Now make the method call. The ListNames method call takes zero input parameters and
    // one output parameter which is an array of strings.
    // Therefore the input is a zero tuple "()", and the output is a single tuple "(names,)".
    let (names,): (Vec<String>,) = proxy.method_call("org.freedesktop.DBus", "ListNames", ())?;

    // Let's print all the names to stdout.
    for name in names { println!("{}", name); }

    Ok(())
}
```

Examples of client code in the examples directory:

 * [client.rs](https://github.com/diwic/dbus-rs/tree/master/dbus/examples/client.rs) (same as the above)
 * [properties.rs](https://github.com/diwic/dbus-rs/tree/master/dbus/examples/properties.rs)
 * [match_signal.rs](https://github.com/diwic/dbus-rs/tree/master/dbus/examples/match_signal.rs)
 * [rtkit.rs](https://github.com/diwic/dbus-rs/tree/master/dbus/examples/rtkit.rs)
 * [monitor.rs](https://github.com/diwic/dbus-rs/tree/master/dbus/examples/monitor.rs)

Server
------

This example grabs the `com.example.dbustest` bus name, adds the `/hello` path
which implements the `com.example.dbustest` interface, and specifies that this
interface has a `Hello` method.
It then listens for incoming D-Bus method calls on this path and handles them accordingly.

**dbus-crossroads**:

```rust
let c = Connection::new_session()?;
c.request_name("com.example.dbustest", false, true, false)?;
let mut cr = Crossroads::new();
let token = cr.register("com.example.dbustest", |b| {
    b.method("Hello", ("name",), ("reply",), |_, _, (name,): (String,)| {
        Ok(format!("Hello {}!", name))
    });
});
cr.insert("/hello", &[token], ());
cr.serve(&c)?;
```

Examples of server code using `dbus-crossroads` in the examples directory:

 * [server_cr.rs](https://github.com/diwic/dbus-rs/blob/master/dbus-crossroads/examples/server_cr.rs)
 * [tokio_server_cr.rs](https://github.com/diwic/dbus-rs/blob/master/dbus-tokio/examples/tokio_server_cr.rs)
 * [tokio_adv_server_cr.rs](https://github.com/diwic/dbus-rs/blob/master/dbus-tokio/examples/tokio_adv_server_cr.rs)

**dbus-tree**:

```rust
let c = Connection::new_session()?;
c.request_name("com.example.dbustest", false, true, false)?;
let f = Factory::new_fn::<()>();
let tree = f.tree(())
    .add(f.object_path("/hello", ()).introspectable()
        .add(f.interface("com.example.dbustest", ())
            .add_m(f.method("Hello", (), |m| {
                let n: &str = m.msg.read1()?;
                let s = format!("Hello {}!", n);
                Ok(vec!(m.msg.method_return().append1(s)))
            }).inarg::<&str,_>("name")
              .outarg::<&str,_>("reply")
        )
    ).add(f.object_path("/", ()).introspectable());
tree.start_receive(&c);
loop { c.process(Duration::from_millis(1000))?; }
```

Examples of server code using `dbus-tree` in the examples directory:

 * [server.rs](https://github.com/diwic/dbus-rs/tree/master/dbus-tree/examples/server.rs)
 * [adv_server.rs](https://github.com/diwic/dbus-rs/tree/master/dbus-tree/examples/adv_server.rs)

Features
========

The `futures` feature makes `dbus` depend on the `futures` crate. This enables the `nonblock` module (used by the `dbus-tokio` crate).

The `no-string-validation` feature skips an extra check that a specific string (e g a `Path`, `ErrorName` etc) conforms to the D-Bus specification, which might also make things a tiny bit faster. But - if you do so, and then actually send invalid strings to the D-Bus library, you might get a panic instead of a proper error.

Requirements
============

[Libdbus](https://dbus.freedesktop.org/releases/dbus/) 1.6 or higher, and latest stable release of [Rust](https://www.rust-lang.org/). If you run Ubuntu (any maintained version should be okay), this means having the `libdbus-1-dev` and `pkg-config` packages installed while building, and the `libdbus-1-3` package installed while running.

Cross compiling libdbus might be tricky because it binds to a C library, there are some notes [here](https://github.com/diwic/dbus-rs/blob/master/libdbus-sys/cross_compile.md).

Alternatives
============

[zbus](https://gitlab.freedesktop.org/dbus/zbus) and [rustbus](https://github.com/KillingSpark/rustbus) (stalled?) are D-Bus crates
written completely in Rust (i e, no bindings to C libraries).
Some more alternatives are listed [here](https://github.com/KillingSpark/rust-dbus-comparisons), but I'm not sure how usable they are.
