[][src]Crate veloren_network

Crate to handle high level networking of messages with different requirements and priorities over a number of protocols

To start with the veloren_network crate you should focus on the 3 elementar structs Network, Participant and Stream.

Say you have an application that wants to communicate with other application over a Network or on the same computer. Now each application instances the struct Network once with a new Pid. The Pid is necessary to identify other Networks over the network protocols (e.g. TCP, UDP)

To connect to another application, you must know it's ProtocolAddr. One side will call connect, the other connected. If successful both applications will now get a Participant.

This Participant represents the connection between those 2 applications. over the respective ProtocolAddr and with it the chosen network protocol. However messages can't be send directly via Participants, instead you must open a Stream on it. Like above, one side has to call open, the other opened. Streams can have a different priority and Promises.

You can now use the Stream to send and recv in both directions. You can send all kind of messages that implement serde. As the receiving side needs to know the format, it sometimes is useful to always send a specific Enum and then handling it with a big match statement This create makes heavily use of async, except for send which returns always directly.

For best practices see the examples folder of this crate containing useful code snippets, a simple client/server below. Of course due to the async nature, no strict client server separation is necessary

Examples

use async_std::task::sleep;
use futures::{executor::block_on, join};
use veloren_network::{Network, Pid, Promises, ProtocolAddr};

// Client
async fn client() -> std::result::Result<(), Box<dyn std::error::Error>> {
    sleep(std::time::Duration::from_secs(1)).await; // `connect` MUST be after `listen`
    let (client_network, f) = Network::new(Pid::new());
    std::thread::spawn(f);
    let server = client_network
        .connect(ProtocolAddr::Tcp("127.0.0.1:12345".parse().unwrap()))
        .await?;
    let mut stream = server
        .open(10, Promises::ORDERED | Promises::CONSISTENCY)
        .await?;
    stream.send("Hello World")?;
    Ok(())
}

// Server
async fn server() -> std::result::Result<(), Box<dyn std::error::Error>> {
    let (server_network, f) = Network::new(Pid::new());
    std::thread::spawn(f);
    server_network
        .listen(ProtocolAddr::Tcp("127.0.0.1:12345".parse().unwrap()))
        .await?;
    let client = server_network.connected().await?;
    let mut stream = client.opened().await?;
    let msg: String = stream.recv().await?;
    println!("Got message: {}", msg);
    assert_eq!(msg, "Hello World");
    Ok(())
}

fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
    block_on(async {
        let (result_c, result_s) = join!(client(), server(),);
        result_c?;
        result_s?;
        Ok(())
    })
}

Modules

api

(cd network/examples/async_recv && RUST_BACKTRACE=1 cargo run)

channel
message
metrics
participant
prios

Priorities are handled the following way. Prios from 0-63 are allowed. all 5 numbers the throughput is halved. E.g. in the same time 100 prio0 messages are send, only 50 prio5, 25 prio10, 12 prio15 or 6 prio20 messages are send. Note: TODO: prio0 will be send immediately when found!

protocols
scheduler
types

Structs

Message

Support struct used for optimising sending the same Message to multiple Stream

Network

Use the Network to create connections to other Participants

Participant

Participants are generated by the Network and represent a connection to a remote Participant. Look at the connect and connected method of Networks on how to generate Participants

Pid

Support struct used for uniquely identifying Participant over the Network.

Promises

use promises to modify the behavior of Streams. see the consts in this struct for

Stream

Streams represents a channel to send n messages with a certain priority and Promises. messages need always to be send between 2 Streams.

Enums

NetworkError

Error type thrown by Networks methods

ParticipantError

Error type thrown by Participants methods

ProtocolAddr

Represents a Tcp or Udp or Mpsc address

StreamError

Error type thrown by Streams methods A Compression Error should only happen if a client sends malicious code. A Deserialize Error probably means you are expecting Type X while you actually got send type Y.