| .. image:: quiche.svg |
| |
| .. image:: https://travis-ci.com/cloudflare/quiche.svg?branch=master |
| :target: https://travis-ci.com/cloudflare/quiche |
| |
| quiche_ is an implementation of the QUIC transport protocol as specified by |
| the IETF_. It provides a low level API for processing QUIC packets and |
| handling connection state. The application is responsible for providing I/O |
| (e.g. sockets handling) as well as an event loop with support for timers. |
| |
| A live QUIC server based on quiche is available at ``https://quic.tech:4433/`` |
| to be used for experimentation. |
| |
| Note that it is very experimental and unstable software, and many features are |
| still in development. |
| |
| For more information on how quiche came about and some insights into its design |
| you can read a post_ on Cloudflare's (where this library is used in production) |
| blog that goes into some more detail. |
| |
| .. _quiche: https://docs.quic.tech/quiche/ |
| .. _ietf: https://quicwg.org/ |
| .. _post: https://blog.cloudflare.com/enjoy-a-slice-of-quic-and-rust/ |
| |
| Status |
| ------ |
| |
| * [x] QUIC draft-17 |
| * [x] Version Negotiation |
| * [x] TLS 1.3 handshake (using BoringSSL) |
| * [x] Stream API |
| * [x] Flow control |
| * [x] Connection close |
| * [x] Loss detection and recovery |
| * [x] Congestion control |
| * [ ] Key update |
| * [x] Stateless retry |
| * [x] Unidirectional streams |
| * [ ] Session resumption |
| * [ ] 0-RTT |
| * [ ] Stateless reset |
| * [ ] Connection migration |
| |
| Getting Started |
| --------------- |
| |
| The first step in establishing a QUIC connection using quiche, is creating a |
| configuration object: |
| |
| .. code-block:: rust |
| |
| let mut config = quiche::Config::new(quiche::VERSION_DRAFT17).unwrap(); |
| |
| This is shared among multiple connections and can be used to configure a QUIC |
| endpoint. |
| |
| Now a connection can be created, for clients the ``quiche::connect()`` utility |
| function can be used, while ``quiche::accept()`` is for servers: |
| |
| .. code-block:: rust |
| |
| // Client connection. |
| let mut conn = quiche::connect(Some(&server_name), &scid, &mut config).unwrap(); |
| |
| // Server connection. |
| let mut conn = quiche::accept(&scid, None, &mut config).unwrap(); |
| |
| Using the connection's ``recv()`` method the application can process incoming |
| packets from the network that belong to that connection: |
| |
| .. code-block:: rust |
| |
| let read = socket.recv(&mut buf).unwrap(); |
| |
| let read = match conn.recv(&mut buf[..read]) { |
| Ok(v) => v, |
| |
| Err(quiche::Error::Done) => { |
| // Done reading. |
| }, |
| |
| Err(e) => { |
| // An error occurred, handle it. |
| }, |
| }; |
| |
| Outgoing packet are generated using the connection's ``send()`` method instead: |
| |
| .. code-block:: rust |
| |
| let write = match conn.send(&mut out) { |
| Ok(v) => v, |
| |
| Err(quiche::Error::Done) => { |
| // Done writing. |
| }, |
| |
| Err(e) => { |
| // An error occurred, handle it. |
| }, |
| }; |
| |
| socket.send(&out[..write]).unwrap(); |
| |
| When packets are sent, the application is responsible for maintainig a timer |
| to react to time-based connection events. The timer expiration can be obtained |
| using the connection's ``timeout()`` method. |
| |
| .. code-block:: rust |
| |
| let timeout = conn.timeout(); |
| timer.set(timeout); // This needs to be implemented by the application. |
| |
| The application is responsible for providing a timer implementation, which can |
| be specific to the operating system or networking framework used. When a timer |
| expires, the connection's ``on_timeout()`` method should be called, after which |
| additional packets might need to be sent on the network: |
| |
| .. code-block:: rust |
| |
| // Timeout expired, do something. |
| conn.on_timeout(); |
| |
| // Send additional packets on the network. |
| let write = match conn.send(&mut out) { |
| Ok(v) => v, |
| |
| Err(quiche::Error::Done) => { |
| // Done writing. |
| }, |
| |
| Err(e) => { |
| // An error occurred, handle it. |
| }, |
| }; |
| |
| socket.send(&out[..write]).unwrap(); |
| |
| After some back and forth, the connection will complete its handshake and will |
| be ready for sending or receiving application data: |
| |
| .. code-block:: rust |
| |
| if conn.is_established() { |
| // Handshake completed, send some data on stream 0. |
| conn.stream_send(0, b"hello", true); |
| } |
| |
| Have a look at the examples_ directory for more complete examples on how to use |
| the quiche API, including examples on how to use quiche in C/C++ applications |
| (see below for more information). |
| |
| .. _examples: examples/ |
| |
| Calling quiche from C/C++ |
| ------------------------- |
| |
| quiche exposes a `thin C API`_ on top of the Rust API that can be used to more |
| easily integrate quiche into C/C++ applications (as well as in other languages |
| that allow calling C APIs via some form of FFI). The C API follows the same |
| design of the Rust one, modulo the constraints imposed by the C language itself. |
| |
| When running ``cargo build``, a static library called ``libquiche.a`` will be |
| built automatically alongside the Rust one. This is fully stand-alone and can |
| be linked directly into C/C++ applications. |
| |
| .. _thin C API: https://github.com/cloudflare/quiche/blob/master/include/quiche.h |
| |
| Building |
| -------- |
| |
| The first step after cloning the git repo is updating the git submodules: |
| |
| .. code-block:: bash |
| |
| $ git submodule update --init |
| |
| You can now build quiche using cargo: |
| |
| .. code-block:: bash |
| |
| $ cargo build --examples |
| |
| As well as run its tests: |
| |
| .. code-block:: bash |
| |
| $ cargo test |
| |
| Note that BoringSSL_, used to implement QUIC's cryptographic handshake based on |
| TLS, needs to be built and linked to quiche. This is done automatically when |
| building quiche using cargo, but requires the `cmake` and `go` commands to be |
| available during the build process. |
| |
| In alternative you can use your own custom build of BoringSSL by configuring |
| the BoringSSL directory with the ``QUICHE_BSSL_PATH`` environment variable: |
| |
| .. code-block:: bash |
| |
| $ QUICHE_BSSL_PATH="/path/to/boringssl" cargo build --examples |
| |
| .. _BoringSSL: https://boringssl.googlesource.com/boringssl/ |
| |
| Copyright |
| --------- |
| |
| Copyright (C) 2018, Cloudflare, Inc. |
| |
| Copyright (C) 2018, Alessandro Ghedini |
| |
| See COPYING_ for the license. |
| |
| .. _COPYING: https://github.com/cloudflare/quiche/tree/master/COPYING |