#future #tokio #quic #protocols

picoquic

Tokio aware picoquic bindings. Picoquic is a minimalist implementation of the QUIC protocol of the IETF.

2 releases

Uses old Rust 2015

0.1.1 Feb 2, 2018
0.1.0 Feb 2, 2018

#155 in #quic

MIT/Apache

4MB
73K SLoC

Bitbake 37K SLoC // 0.0% comments C 29K SLoC // 0.1% comments GNU Style Assembly 2.5K SLoC // 0.0% comments Python 1.5K SLoC // 0.2% comments Visual Studio Project 1.5K SLoC Rust 1.5K SLoC // 0.1% comments C++ 271 SLoC // 0.1% comments Visual Studio Solution 161 SLoC Arduino C++ 66 SLoC // 0.0% comments Perl 32 SLoC Forge Config 11 SLoC

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

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

  • clang
  • openssl
  • cmake

Building is currently only tested on Linux. To build the project, you just need to 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_core;

use picoquic::{Config, Context, SMessage};

use tokio_core::reactor::Core;

use bytes::Bytes;

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

fn main() {
    let mut evt_loop = Core::new().unwrap();

    let config = Config::client();

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

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

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

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

    let answer = evt_loop
        .run(
            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_core;

use picoquic::{CMessage, Config, Context, SMessage};

use tokio_core::reactor::Core;

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

use bytes::Bytes;

fn main() {
    let mut evt_loop = Core::new().unwrap();

    let manifest_dir = env!("CARGO_MANIFEST_DIR");

    let config = Config::server(
        &format!("{}/examples/cert.pem", manifest_dir),
        &format!("{}/examples/key.pem", manifest_dir),
    );

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

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

    let handle = evt_loop.handle();

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

            let handle = handle.clone();
            handle.clone().spawn(c.for_each(move |s| {
                // Let's see what we got
                let s = match s {
                    CMessage::NewStream(s) => s,
                    _ => return Ok(()),
                };

                // 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 to early.
                handle.spawn(
                    s.into_future()
                        .map_err(|_| ())
                        .and_then(|(m, s)| {
                            println!("Got: {:?}", m);
                            s.send(SMessage::Data(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

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

Dependencies

~8–11MB
~198K SLoC