picoquic-rs icon indicating copy to clipboard operation
picoquic-rs copied to clipboard

Picoquic bindings for rust.

trafficstars

Picoquic-rs - Tokio aware bindings of picoquic

Build Status

Picoquic is a minimalist implementation of the QUIC protocol by the IETF. The protocol is still in development and so the implementation.

  • Building
  • Example
  • Todo
  • License
  • Contribution

Building

For building picoquic-rs, you need the following dependencies:

  • clang
  • openssl Building is currently only tested on Linux. Clone the repo and fetch the submodules:
git submodule init
git submodule update

To build the project, run cargo build. picoquic-sys will also build the picoquic c-library for you (hopefully).

Example

Client

extern crate bytes;
extern crate futures;
extern crate picoquic;
extern crate tokio;

use picoquic::{Config, Context};

use bytes::Bytes;

use futures::{Future, Sink, Stream};

fn main() {
    let mut evt_loop = tokio::runtime::Runtime::new().unwrap();

    let manifest_dir = env!("CARGO_MANIFEST_DIR");

    let mut config = Config::new();
    config.set_root_certificate_filename(format!("{}/examples/ca_cert.pem", manifest_dir));

    let mut client = Context::new(&([0, 0, 0, 0], 0).into(), evt_loop.executor(), config).unwrap();

    let mut con = evt_loop
        .block_on(client.new_connection(([127, 0, 0, 1], 22222).into(), "server.test"))
        .unwrap();

    let stream = evt_loop.block_on(con.new_bidirectional_stream()).unwrap();

    let stream = evt_loop
        .block_on(stream.send(Bytes::from("hello server")))
        .unwrap();

    let answer = evt_loop
        .block_on(
            stream
                .into_future()
                .map(|(m, _)| m.unwrap())
                .map_err(|(e, _)| e),
        )
        .unwrap();

    println!("Got: {:?}", answer);
}

Server

extern crate bytes;
extern crate futures;
extern crate picoquic;
extern crate tokio;

use picoquic::{Config, Context};

use futures::{Future, Sink, Stream};

use bytes::Bytes;

fn main() {
    let evt_loop = tokio::runtime::Runtime::new().unwrap();

    let manifest_dir = env!("CARGO_MANIFEST_DIR");

    let mut config = Config::new();
    config.set_certificate_chain_filename(format!("{}/examples/cert.pem", manifest_dir));
    config.set_private_key_filename(format!("{}/examples/key.pem", manifest_dir));

    let server = Context::new(&([0, 0, 0, 0], 22222).into(), evt_loop.executor(), config).unwrap();

    println!("Server listening on: {}", server.local_addr());

    evt_loop.block_on_all(
        server
            .for_each(|c| {
                println!("New connection from: {}", c.peer_addr());

                tokio::spawn(
                    c.for_each(move |s| {
                        // We print the received message and sent a new one, after that we collect all
                        // remaining messages. The collect is a "hack" that prevents that the `Stream` is
                        // dropped too early.
                        tokio::spawn(
                            s.into_future()
                                .map_err(|_| ())
                                .and_then(|(m, s)| {
                                    println!("Got: {:?}", m);
                                    s.send(Bytes::from("hello client")).map_err(|_| ())
                                })
                                .and_then(|s| s.collect().map_err(|_| ()))
                                .map(|_| ()),
                        );
                        Ok(())
                    })
                    .map_err(|_| ()),
                );

                Ok(())
            })
    ).unwrap();
}

Todo

  • My first crate/project that uses failure and I'm not happy with the current error structure :(
  • Support more configuration options
  • I currently don't check all return codes of the c functions.
  • Remove the TODOs from the source code

License

Licensed under either of

  • Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
  • MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

License: MIT/Apache-2.0