KillingSpark / rustbus

Dbus transport in pure rust
MIT License
57 stars 15 forks source link

Status of Project #124

Open ifazk opened 1 month ago

ifazk commented 1 month ago

Hi,

What's the status of the project? Are signals working?

I have been trying to use the project, but I've been running into issues with signals. Do signals work? I couldn't even get the basic example to work:

fn main() -> Result<(), rustbus::connection::Error> {
    // To get a connection going you need to connect to a bus.
    // You will likely use either the session or the system bus.
    let session_path = nix::sys::socket::UnixAddr::new(DBUS_SOCKET_PATH)?;
    let mut con = DuplexConn::connect_to_bus(session_path, true)?;
    // Dont forget to send the obligatory hello message.
    // send_hello wraps the call and parses the response for convenience.
    let _unique_name = con.send_hello(Timeout::Infinite)?;

    // Or use the more higher level abstraction of a RpcConn.
    // This builds the connection and sends the hello for you
    //let mut rpc_con = RpcConn::session_conn(Timeout::Infinite).unwrap();

    // Next you will probably want to create a new message to send out to the world
    let mut sig = MessageBuilder::new()
        .signal(
            "io.killing.spark",
            "TestSignal",
            "/io/killing/spark",
        )
        .build();

    // To put parameters into that message you use the sig.body.push_param functions.
    // These accept anything that can be marshalled into a dbus parameter
    // You can derive or manually implement that trait for your own types if you need that.
    sig.body.push_param("My cool new Signal!").unwrap();

    // Now send you signal to all that want to hear it!
    con.send.send_message(&sig)?.write_all().map_err(force_finish_on_error)?;

    con.recv.read_once(Timeout::Nonblock)?;

    // To receive messages sent to you you can call the various functions on the RecvConn.
    // The simplest is this:
    while let Ok(message) = con.recv.get_next_message(Timeout::Duration(Duration::from_secs(10))) {
        // Now you can inspect the message.dynheader for all the metadata on the message
        println!("The messages dynamic header: {:?}", message.dynheader);

        // After inspecting that dynheader you should know which content the message should contain
        let cool_string = message.body.parser().get::<&str>().unwrap();
        println!("Received a cool string: {}", cool_string);
        match con.recv.read_once(Timeout::Nonblock) {
            Err(rustbus::connection::Error::TimedOut) => continue,
            otherwise => otherwise?,
        }
    }
    Ok(())
}

Simply returns:

The messages dynamic header: DynamicHeader { interface: Some("org.freedesktop.DBus"), member: Some("NameAcquired"), object: Some("/org/freedesktop/DBus"), destination: Some(":1.1453"), serial: Some(2), sender: Some("org.freedesktop.DBus"), signature: Some("s"), error_name: None, response_serial: None, num_fds: None }
Received a cool string: :1.1453

But dbus-monitor shows the signal:

signal time=1726236157.154575 sender=:1.1453 -> destination=(null destination) serial=2 path=/io/killing/spark; interface=io.killing.spark; member=TestSignal
   string "My cool new Signal!"
signal time=1726236167.152735 sender=org.freedesktop.DBus -> destination=(null destination) serial=2447 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
   string ":1.1453"
   string ":1.1453"
   string ""
signal time=1726236232.285846 sender=org.freedesktop.DBus -> destination=(null destination) serial=2448 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameOwnerChanged
   string ":1.1454"
   string ""
   string ":1.1454"
KillingSpark commented 1 month ago

Hi!

Signals are working, but they do require a little more work than that example. This example just sends out a signal (as the monitor shows) but it does not set up any match rules to receive signals.

See here: https://dbus.freedesktop.org/doc/dbus-specification.html the section for match rules

This example is able to receive messages that are directed at its unique bus name (which it conveniently prints out ;)) with e.g. dbus-send

Note that this crate is meant to be relatively low level to allow for a lot of flexibility and careful resource management but it is not the most convenient crate out there

ifazk commented 1 month ago

That helped a lot. Can you add the needed rustbus::standard_messages::add_match("type='signal'") to the signal example in the README?

KillingSpark commented 1 month ago

That's probably a good idea