Crate picoquic [] [src]

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

Be careful when using this code, it's not being tested!
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

Be careful when using this code, it's not being tested!
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.

Structs

Config

Configuration used by Context to setup Picoquic.

Connection

Represents a connection to a peer.

Context

The Picoquic context. It setups and controls the UdpSocket. Every incoming Connection can be obtained by polling this context.

NewConnectionFuture
NewConnectionHandle
NewStreamFuture

A future that resolves to a Stream. This future is created by the NewStreamHandle.

NewStreamHandle

A handle to create new Streams for a connection.

Stream

A Stream is part of a Connection. A Connection can consists of multiple Streams. Each Stream is a new channel over the Connection to the Peer. All traffic of a Stream is always unique for each Stream. The Stream needs to be polled, to get notified about a new Message.

Enums

CMessage
SMessage

A Message is used by the Stream to propagate information from the peer or to send information to the peer.

SType

A Stream can either be unidirectional or bidirectional.