Module strymon_communication::rpc [] [src]

Asynchronous remote procedure calls.

This implements a small framework for receiving and sending requests and responses between two connected peers. During set-up, one of the peers acts as a server, listening on a server socket to accept new incoming clients. Clients connect to a server using the socket address.

Once a connection between two peers is established, their initial role as server and client becomes irrelevant, as they take on the role of either being a sender or receiver (or both) of requests.

1. Defining a custom protocol

In order to use this framework, client code must first define the types to be used for a request-response protocol. It is not using a custom interface description language (IDL) but rather is based on implementing certain Rust traits. Different types of requests must be distinguished from each other through a value called the name (i.e. the name of the remote procedure). Since the name is typically used for dispatching on the receiver-side, it is recommended to use an enum for it.

The name, argument and return types of a method are defined by implementing the Request type. Each invocation can either return successfully with the type specified in Request::Success or fail with an application-specific error defined in Request::Error.

2. Connection set-up

During connection set-up, one peer needs to act as a server. To instantiate a server, invoke Network::server() to obtain a handle for new incoming clients.

The client is expected to call Network::client() with the corresponding socket address to connect to the server. Both peers will obtain a pair of (Incoming, Outgoing) queue handles. These are used to either receive incoming requests, or send out outgoing requests.

3. Handling requests & responses

Once connected, a peer might decide to send requests by invoking Outgoing::request() with an argument implementing the Request trait. The remote peer will receive this request on its Incoming queue in the form of an encoded RequestBuf object. To decode this object, it is common to match on the method name returned by RequestBuf::name() and then decode the request payload using RequestBuf::decode(). Decoding a request successfully returns the decoded payload, as well as a Responder object which is used to send back the response to the origin.

Once the response arrives back at the original sender, the Response future will resolve to the decoded response.

Examples:

Please refer to tests/calc.rs for a complete example of how to use this module.

Structs

Incoming

Receiver-side queue of incoming requests.

Outgoing

Sender-side queue for sending out requests.

RequestBuf

Receiver-side buffer containing an incoming request.

Responder

Receiver-side handle for responding to a given request.

Response

Sender-side future eventually yielding the response for a request.

Server

Handle for queue of newly connected peers.

Traits

Name

A trait to distinguish remote procedure calls.

Request

A trait for defining the signature of a remote procedure.