server/
server.rs

1/* This example creates a D-Bus server with the following functionality:
2   It registers the "com.example.dbustest" name, creates a "/hello" object path,
3   which has an "com.example.dbustest" interface.
4
5   The interface has a "Hello" method (which takes no arguments and returns a string),
6   and a "HelloHappened" signal (with a string argument) which is sent every time
7   someone calls the "Hello" method.
8*/
9
10use std::sync::Arc;
11use dbus::blocking::LocalConnection;
12use dbus_tree::Factory;
13use std::error::Error;
14use std::time::Duration;
15
16fn main() -> Result<(), Box<dyn Error>> {
17    // Let's start by starting up a connection to the session bus and request a name.
18    let c = LocalConnection::new_session()?;
19    c.request_name("com.example.dbustest", false, true, false)?;
20
21    // The choice of factory tells us what type of tree we want,
22    // and if we want any extra data inside. We pick the simplest variant.
23    let f = Factory::new_fn::<()>();
24
25    // We create the signal first, since we'll need it in both inside the method callback
26    // and when creating the tree.
27    let signal = Arc::new(f.signal("HelloHappened", ()).sarg::<&str,_>("sender"));
28    let signal2 = signal.clone();
29
30    // We create a tree with one object path inside and make that path introspectable.
31    let tree = f.tree(()).add(f.object_path("/hello", ()).introspectable().add(
32
33        // We add an interface to the object path...
34        f.interface("com.example.dbustest", ()).add_m(
35
36            // ...and a method inside the interface.
37            f.method("Hello", (), move |m| {
38
39                // This is the callback that will be called when another peer on the bus calls our method.
40                // the callback receives "MethodInfo" struct and can return either an error, or a list of
41                // messages to send back.
42
43                let name: &str = m.msg.read1()?;
44                let s = format!("Hello {}!", name);
45                let mret = m.msg.method_return().append1(s);
46
47                let sig = signal.msg(m.path.get_name(), m.iface.get_name())
48                    .append1(&*name);
49
50                // Two messages will be returned - one is the method return (and should always be there),
51                // and in our case we also have a signal we want to send at the same time.
52                Ok(vec!(mret, sig))
53
54            // Our method has one output argument and one input argument.
55            }).outarg::<&str,_>("reply")
56            .inarg::<&str,_>("name")
57
58        // We also add the signal to the interface. This is mainly for introspection.
59        ).add_s(signal2)
60
61    // Also add the root path, to help introspection from debugging tools.
62    )).add(f.object_path("/", ()).introspectable());
63
64    // We add the tree to the connection so that incoming method calls will be handled.
65    tree.start_receive(&c);
66
67    // Serve clients forever.
68    loop { c.process(Duration::from_millis(1000))?; }
69}