-
Notifications
You must be signed in to change notification settings - Fork 133
/
Copy pathmonitor.rs
80 lines (69 loc) · 2.9 KB
/
monitor.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use std::time::Duration;
use dbus::blocking::Connection;
use dbus::channel::MatchingReceiver;
use dbus::message::MatchRule;
use dbus::Message;
// This programs implements the equivalent of running the "dbus-monitor" tool
fn main() {
// Very simple argument parsing.
let use_system_bus = std::env::args().into_iter().any(|a| a == "--system");
// First open up a connection to the desired bus.
let conn = (if use_system_bus { Connection::new_system() } else { Connection::new_session() }).expect("D-Bus connection failed");
// Second create a rule to match messages we want to receive; in this example we add no
// further requirements, so all messages will match
let rule = MatchRule::new();
// Try matching using new scheme
let proxy = conn.with_proxy("org.freedesktop.DBus", "/org/freedesktop/DBus", Duration::from_millis(5000));
let result: Result<(), dbus::Error> =
proxy.method_call("org.freedesktop.DBus.Monitoring", "BecomeMonitor", (vec![rule.match_str()], 0u32));
match result {
// BecomeMonitor was successful, start listening for messages
Ok(_) => {
conn.start_receive(
rule,
Box::new(|msg, _| {
handle_message(&msg);
true
}),
);
}
// BecomeMonitor failed, fallback to using the old scheme
Err(e) => {
eprintln!("Failed to BecomeMonitor: '{}', falling back to eavesdrop", e);
// First, we'll try "eavesdrop", which as the name implies lets us receive
// *all* messages, not just ours.
let rule_with_eavesdrop = {
let mut rule = rule.clone();
rule.eavesdrop = true;
rule
};
let result = conn.add_match(rule_with_eavesdrop, |_: (), _, msg| {
handle_message(&msg);
true
});
match result {
Ok(_) => {
// success, we're now listening
}
// This can sometimes fail, for example when listening to the system bus as a non-root user.
// So, just like `dbus-monitor`, we attempt to fallback without `eavesdrop=true`:
Err(e) => {
eprintln!("Failed to eavesdrop: '{}', trying without it", e);
conn.add_match(rule, |_: (), _, msg| {
handle_message(&msg);
true
})
.expect("add_match failed");
}
}
}
}
// Loop and print out all messages received (using handle_message()) as they come.
// Some can be quite large, e.g. if they contain embedded images..
loop {
conn.process(Duration::from_millis(1000)).unwrap();
}
}
fn handle_message(msg: &Message) {
println!("Got message: {:?}", msg);
}