README.md
1![quiche](quiche.svg)
2
3[![crates.io](https://img.shields.io/crates/v/quiche.svg)](https://crates.io/crates/quiche)
4[![docs.rs](https://docs.rs/quiche/badge.svg)](https://docs.rs/quiche)
5[![license](https://img.shields.io/github/license/cloudflare/quiche.svg)](https://opensource.org/licenses/BSD-2-Clause)
6[![build](https://travis-ci.com/cloudflare/quiche.svg?branch=master)](https://travis-ci.com/cloudflare/quiche)
7
8[quiche] is an implementation of the QUIC transport protocol and HTTP/3 as
9specified by the [IETF]. It provides a low level API for processing QUIC packets
10and handling connection state. The application is responsible for providing I/O
11(e.g. sockets handling) as well as an event loop with support for timers.
12
13A live QUIC server based on quiche is available at ``https://quic.tech:4433/``,
14and an HTTP/3 one at ``https://quic.tech:8443/``, that can be used for
15experimentation.
16
17For more information on how quiche came about and some insights into its design
18you can read a [post] on Cloudflare's blog that goes into some more detail.
19
20[quiche]: https://docs.quic.tech/quiche/
21[ietf]: https://quicwg.org/
22[post]: https://blog.cloudflare.com/enjoy-a-slice-of-quic-and-rust/
23
24Who uses quiche?
25----------------
26
27### Cloudflare
28
29quiche powers Cloudflare edge network's [HTTP/3 support][cloudflare-http3].
30
31### curl
32
33quiche can be [integrated into curl][curl-http3] to provide support for HTTP/3.
34
35### NGINX (unofficial)
36
37quiche can be [integrated into NGINX][nginx-http3] using an unofficial patch to
38provide support for HTTP/3.
39
40[cloudflare-http3]: https://blog.cloudflare.com/http3-the-past-present-and-future/
41[curl-http3]: https://github.com/curl/curl/blob/master/docs/HTTP3.md#quiche-version
42[nginx-http3]: https://github.com/cloudflare/quiche/tree/master/extras/nginx
43
44Getting Started
45---------------
46
47### Command-line apps
48
49Before diving into the quiche API, here are a few examples on how to use the
50quiche tools provided as part of the [quiche-apps](tools/apps/) crate.
51
52The client can be run as follows:
53
54```bash
55 $ cargo run --manifest-path=tools/apps/Cargo.toml --bin quiche-client -- https://quic.tech:8443/
56```
57
58while the server can be run as follows:
59
60```bash
61 $ cargo run --manifest-path=tools/apps/Cargo.toml --bin quiche-server -- \
62 --cert tools/apps/src/bin/cert.crt \
63 --key tools/apps/src/bin/cert.key
64```
65
66(note that the certificate provided is self-signed and should not be used in
67production)
68
69Use the `--help` command-line flag to get a more detailed description of each
70tool's options.
71
72### Connection setup
73
74The first step in establishing a QUIC connection using quiche is creating a
75configuration object:
76
77```rust
78let config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
79```
80
81This is shared among multiple connections and can be used to configure a
82QUIC endpoint.
83
84On the client-side the [`connect()`] utility function can be used to create
85a new connection, while [`accept()`] is for servers:
86
87```rust
88// Client connection.
89let conn = quiche::connect(Some(&server_name), &scid, &mut config)?;
90
91// Server connection.
92let conn = quiche::accept(&scid, None, &mut config)?;
93```
94
95### Handling incoming packets
96
97Using the connection's [`recv()`] method the application can process
98incoming packets that belong to that connection from the network:
99
100```rust
101loop {
102 let read = socket.recv(&mut buf).unwrap();
103
104 let read = match conn.recv(&mut buf[..read]) {
105 Ok(v) => v,
106
107 Err(e) => {
108 // An error occurred, handle it.
109 break;
110 },
111 };
112}
113```
114
115### Generating outgoing packets
116
117Outgoing packet are generated using the connection's [`send()`] method
118instead:
119
120```rust
121loop {
122 let write = match conn.send(&mut out) {
123 Ok(v) => v,
124
125 Err(quiche::Error::Done) => {
126 // Done writing.
127 break;
128 },
129
130 Err(e) => {
131 // An error occurred, handle it.
132 break;
133 },
134 };
135
136 socket.send(&out[..write]).unwrap();
137}
138```
139
140When packets are sent, the application is responsible for maintaining a
141timer to react to time-based connection events. The timer expiration can be
142obtained using the connection's [`timeout()`] method.
143
144```rust
145let timeout = conn.timeout();
146```
147
148The application is responsible for providing a timer implementation, which
149can be specific to the operating system or networking framework used. When
150a timer expires, the connection's [`on_timeout()`] method should be called,
151after which additional packets might need to be sent on the network:
152
153```rust
154// Timeout expired, handle it.
155conn.on_timeout();
156
157// Send more packets as needed after timeout.
158loop {
159 let write = match conn.send(&mut out) {
160 Ok(v) => v,
161
162 Err(quiche::Error::Done) => {
163 // Done writing.
164 break;
165 },
166
167 Err(e) => {
168 // An error occurred, handle it.
169 break;
170 },
171 };
172
173 socket.send(&out[..write]).unwrap();
174}
175```
176
177### Sending and receiving stream data
178
179After some back and forth, the connection will complete its handshake and
180will be ready for sending or receiving application data.
181
182Data can be sent on a stream by using the [`stream_send()`] method:
183
184```rust
185if conn.is_established() {
186 // Handshake completed, send some data on stream 0.
187 conn.stream_send(0, b"hello", true)?;
188}
189```
190
191The application can check whether there are any readable streams by using
192the connection's [`readable()`] method, which returns an iterator over all
193the streams that have outstanding data to read.
194
195The [`stream_recv()`] method can then be used to retrieve the application
196data from the readable stream:
197
198```rust
199if conn.is_established() {
200 // Iterate over readable streams.
201 for stream_id in conn.readable() {
202 // Stream is readable, read until there's no more data.
203 while let Ok((read, fin)) = conn.stream_recv(stream_id, &mut buf) {
204 println!("Got {} bytes on stream {}", read, stream_id);
205 }
206 }
207}
208```
209
210### HTTP/3
211
212The quiche [HTTP/3 module] provides a high level API for sending and
213receiving HTTP requests and responses on top of the QUIC transport protocol.
214
215[`connect()`]: https://docs.quic.tech/quiche/fn.connect.html
216[`accept()`]: https://docs.quic.tech/quiche/fn.accept.html
217[`recv()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.recv
218[`send()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.send
219[`timeout()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.timeout
220[`on_timeout()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.on_timeout
221[`stream_send()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.stream_send
222[`readable()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.readable
223[`stream_recv()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.stream_recv
224[HTTP/3 module]: https://docs.quic.tech/quiche/h3/index.html
225
226Have a look at the [examples/] directory for more complete examples on how to use
227the quiche API, including examples on how to use quiche in C/C++ applications
228(see below for more information).
229
230[examples/]: examples/
231
232Calling quiche from C/C++
233-------------------------
234
235quiche exposes a [thin C API] on top of the Rust API that can be used to more
236easily integrate quiche into C/C++ applications (as well as in other languages
237that allow calling C APIs via some form of FFI). The C API follows the same
238design of the Rust one, modulo the constraints imposed by the C language itself.
239
240When running ``cargo build``, a static library called ``libquiche.a`` will be
241built automatically alongside the Rust one. This is fully stand-alone and can
242be linked directly into C/C++ applications.
243
244[thin C API]: https://github.com/cloudflare/quiche/blob/master/include/quiche.h
245
246Building
247--------
248
249quiche requires Rust 1.39 or later to build. The latest stable Rust release can
250be installed using [rustup](https://rustup.rs/).
251
252Once the Rust build environment is setup, the quiche source code can be fetched
253using git:
254
255```bash
256 $ git clone --recursive https://github.com/cloudflare/quiche
257```
258
259and then built using cargo:
260
261```bash
262 $ cargo build --examples
263```
264
265cargo can also be used to run the testsuite:
266
267```bash
268 $ cargo test
269```
270
271Note that [BoringSSL], which is used to implement QUIC's cryptographic handshake
272based on TLS, needs to be built and linked to quiche. This is done automatically
273when building quiche using cargo, but requires the `cmake` command to be
274available during the build process. On Windows you also need
275[NASM](https://www.nasm.us/). The [official BoringSSL
276documentation](https://github.com/google/boringssl/blob/master/BUILDING.md) has
277more details.
278
279In alternative you can use your own custom build of BoringSSL by configuring
280the BoringSSL directory with the ``QUICHE_BSSL_PATH`` environment variable:
281
282```bash
283 $ QUICHE_BSSL_PATH="/path/to/boringssl" cargo build --examples
284```
285
286[BoringSSL]: https://boringssl.googlesource.com/boringssl/
287
288### Building for Android
289
290To build quiche for Android, you need the following:
291
292- Install the [Android NDK] (13b or higher), using Android Studio or directly.
293- Set `ANDROID_NDK_HOME` environment variable to NDK path, e.g.
294
295```bash
296 $ export ANDROID_NDK_HOME=/usr/local/share/android-ndk
297```
298
299- Install the Rust toolchain for Android architectures needed:
300
301```bash
302 $ rustup target add aarch64-linux-android arm-linux-androideabi armv7-linux-androideabi i686-linux-android x86_64-linux-android
303```
304
305Note that the minimum API level is 21 for all target architectures.
306
307Depending on the NDK version used, you can take one of the following procedures:
308
309[Android NDK]: https://developer.android.com/ndk
310
311#### NDK version >= 19
312
313For NDK version 19 or higher (21 recommended), you can build in a simpler
314way using [cargo-ndk]. You need to install [cargo-ndk] first.
315
316```bash
317 $ cargo install cargo-ndk
318```
319
320You can build the quiche library using the following procedure. Note that
321`--target` and `--android-platform` are mandatory.
322
323```bash
324 $ cargo ndk --target aarch64-linux-android --android-platform 21 -- build
325```
326
327See [build_android_ndk19.sh] for more information.
328
329Note that building with NDK version 18 appears to be broken.
330
331[cargo-ndk]: https://docs.rs/crate/cargo-ndk
332[build_android_ndk19.sh]: https://github.com/cloudflare/quiche/blob/master/tools/android/build_android_ndk19.sh
333
334#### NDK version < 18
335
336If you need to use NDK version < 18 (gcc), you can build quiche in the following way.
337
338To prepare the cross-compiling toolchain, run the following command:
339
340```bash
341 $ tools/android/setup_android.sh
342```
343
344It will create a standalone toolchain for arm64/arm/x86 architectures under the
345`$TOOLCHAIN_DIR/arch` directory. If you didn't set `TOOLCHAIN_DIR` environment
346variable, the current directory will be used.
347
348After it run successfully, run the following script to build libquiche:
349
350```bash
351 $ tools/android/build_android.sh --features ndk-old-gcc
352```
353
354It will build binaries for aarch64, armv7 and i686. You can pass parameters to
355this script for cargo build. For example if you want to build a release binary
356with verbose logs, do the following:
357
358```bash
359 $ tools/android/build_android.sh --features ndk-old-gcc --release -vv
360```
361
362### Building for iOS
363
364To build quiche for iOS, you need the following:
365
366- Install Xcode command-line tools. You can install them with Xcode or with the
367 following command:
368
369```bash
370 $ xcode-select --install
371```
372
373- Install the Rust toolchain for iOS architectures:
374
375```bash
376 $ rustup target add aarch64-apple-ios x86_64-apple-ios
377```
378
379- Install `cargo-lipo`:
380
381```bash
382 $ cargo install cargo-lipo
383```
384
385To build libquiche, run the following command:
386
387```bash
388 $ cargo lipo
389```
390
391or
392
393```bash
394 $ cargo lipo --release
395```
396
397iOS build is tested in Xcode 10.1 and Xcode 11.2.
398
399### Building Docker images
400
401In order to build the Docker images, simply run the following command:
402
403```bash
404 $ make docker-build
405```
406
407You can find the quiche Docker images on the following Docker Hub repositories:
408
409- [cloudflare/quiche](https://hub.docker.com/repository/docker/cloudflare/quiche)
410- [cloudflare/quiche-qns](https://hub.docker.com/repository/docker/cloudflare/quiche-qns)
411
412The `latest` tag will be updated whenever quiche master branch updates.
413
414**cloudflare/quiche**
415
416Provides a server and client installed in /usr/local/bin.
417
418**cloudflare/quiche-qns**
419
420Provides the script to test quiche within the [quic-interop-runner](https://github.com/marten-seemann/quic-interop-runner).
421
422Copyright
423---------
424
425Copyright (C) 2018-2019, Cloudflare, Inc.
426
427See [COPYING] for the license.
428
429[COPYING]: https://github.com/cloudflare/quiche/tree/master/COPYING
430