Crate varlink

Source
Expand description

Server and client support for the varlink protocol

§Server

To create a varlink server in rust, place your varlink interface definition file in src/. E.g. src/org.example.ping.varlink:

Then create a build.rs file in your project directory:

extern crate varlink_generator;

fn main() {
    varlink_generator::cargo_build_tosource("src/org.example.ping.varlink",
                                             /* rustfmt */ true);
}

For more code generation functions see the generator functions.

Add to your Cargo.toml:

[package]
build = "build.rs"
[build-dependencies]
varlink_generator = "<version>"

In your main.rs you can then use:

mod org_example_ping;

and then implement the interface:

struct MyOrgExamplePing;

impl VarlinkInterface for MyOrgExamplePing {
    fn ping(&self, call: &mut dyn Call_Ping, ping: String) -> Result<()> {
        return call.reply(ping);
    }
}

to implement the interface methods.

If your varlink method is called TestMethod, the rust method to be implemented is called test_method. The first parameter is of type Call_TestMethod, which has the method reply().

fn test_method(&self, call: &mut dyn Call_TestMethod, /* more arguments */) -> Result<()> {
    /* ... */
return call.reply( /* more arguments */ );
}

A typical server creates a VarlinkService and starts a server via varlink::listen

let args: Vec<_> = std::env::args().collect();
let myorgexampleping = MyOrgExamplePing;
let myorgexampleping_interface = org_example_ping::new(Box::new(myorgexampleping));

let service = varlink::VarlinkService::new(
    "org.varlink",
    "test service",
    "0.1",
    "http://varlink.org",
    vec![
        Box::new(myorgexampleping_interface),
        // more interfaces ...
    ],
);

varlink::listen(service, &args[1],
    &varlink::ListenConfig {
        idle_timeout: 1,
        ..Default::default()
    },
);

where args[1] would follow the varlink address specification.

Currently supported address URIs are:

  • TCP tcp:127.0.0.1:12345 hostname/IP address and port
  • UNIX socket unix:/run/org.example.ftl optional access ;mode=0666 parameter
  • UNIX abstract namespace socket unix:@org.example.ftl (on Linux only)

§Client

Setup your project, just like in the server case with a varlink file and a build.rs file.

In your main.rs you can then use:

mod org_example_ping;
use org_example_ping;
let connection = Connection::with_address("unix:/tmp/org.example.ping").unwrap();
let mut ping_service = org_example_ping::VarlinkClient::new(connection);
let reply = ping_service.ping(String::from("Test")).call()?;
assert_eq!(String::from("Test"), reply.pong);

A connection can be established via the connection builder functions. The org_example_ping::VarlinkClient implements org_example_ping::VarlinkClientInterface, which has all the varlink methods (names converted from camel case to lowercase snake case). The PingString() method would be named ping_string().

To iterate over a more call

for reply in my_more_service.test_more(/* params */).more()? { /*...*/ }

The reply struct is placed in a structure named after the method with _Reply appended. So, the reply to the Ping() method in our example is in a struct called Ping_Reply.

Re-exports§

Modules§

Macros§

Structs§

Enums§

Traits§

  • CallTrait provides convenience methods for the Call struct, which is passed as the first argument to the interface methods.
  • This trait has to be implemented by any varlink interface implementor. All methods are generated by the varlink-rust-generator, so you don’t have to care about them.
  • Marker trait for the rust code generated by the varlink-rust-generator

Functions§

Type Aliases§