• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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://img.shields.io/github/actions/workflow/status/cloudflare/quiche/stable.yml?branch=master)
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
13For more information on how quiche came about and some insights into its design
14you can read a [post] on Cloudflare's blog that goes into some more detail.
15
16[quiche]: https://docs.quic.tech/quiche/
17[ietf]: https://quicwg.org/
18[post]: https://blog.cloudflare.com/enjoy-a-slice-of-quic-and-rust/
19
20Who uses quiche?
21----------------
22
23### Cloudflare
24
25quiche powers Cloudflare edge network's [HTTP/3 support][cloudflare-http3]. The
26[cloudflare-quic.com](https://cloudflare-quic.com) website can be used for
27testing and experimentation.
28
29### Android
30
31Android's DNS resolver uses quiche to [implement DNS over HTTP/3][android-http3].
32
33### curl
34
35quiche can be [integrated into curl][curl-http3] to provide support for HTTP/3.
36
37### NGINX (unofficial)
38
39quiche can be [integrated into NGINX](nginx/) using an unofficial patch to
40provide support for HTTP/3.
41
42[cloudflare-http3]: https://blog.cloudflare.com/http3-the-past-present-and-future/
43[android-http3]: https://security.googleblog.com/2022/07/dns-over-http3-in-android.html
44[curl-http3]: https://github.com/curl/curl/blob/master/docs/HTTP3.md#quiche-version
45
46Getting Started
47---------------
48
49### Command-line apps
50
51Before diving into the quiche API, here are a few examples on how to use the
52quiche tools provided as part of the [quiche-apps](apps/) crate.
53
54After cloning the project according to the command mentioned in the [building](#building) section, the client can be run as follows:
55
56```bash
57 $ cargo run --bin quiche-client -- https://cloudflare-quic.com/
58```
59
60while the server can be run as follows:
61
62```bash
63 $ cargo run --bin quiche-server -- --cert apps/src/bin/cert.crt --key 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### Configuring connections
73
74The first step in establishing a QUIC connection using quiche is creating a
75[`Config`] object:
76
77```rust
78let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
79config.set_application_protos(&[b"example-proto"]);
80
81// Additional configuration specific to application and use case...
82```
83
84The [`Config`] object controls important aspects of the QUIC connection such
85as QUIC version, ALPN IDs, flow control, congestion control, idle timeout
86and other properties or features.
87
88QUIC is a general-purpose transport protocol and there are several
89configuration properties where there is no reasonable default value. For
90example, the permitted number of concurrent streams of any particular type
91is dependent on the application running over QUIC, and other use-case
92specific concerns.
93
94quiche defaults several properties to zero, applications most likely need
95to set these to something else to satisfy their needs using the following:
96
97- [`set_initial_max_streams_bidi()`]
98- [`set_initial_max_streams_uni()`]
99- [`set_initial_max_data()`]
100- [`set_initial_max_stream_data_bidi_local()`]
101- [`set_initial_max_stream_data_bidi_remote()`]
102- [`set_initial_max_stream_data_uni()`]
103
104[`Config`] also holds TLS configuration. This can be changed by mutators on
105the an existing object, or by constructing a TLS context manually and
106creating a configuration using [`with_boring_ssl_ctx()`].
107
108A configuration object can be shared among multiple connections.
109
110### Connection setup
111
112On the client-side the [`connect()`] utility function can be used to create
113a new connection, while [`accept()`] is for servers:
114
115```rust
116// Client connection.
117let conn = quiche::connect(Some(&server_name), &scid, local, peer, &mut config)?;
118
119// Server connection.
120let conn = quiche::accept(&scid, None, local, peer, &mut config)?;
121```
122
123### Handling incoming packets
124
125Using the connection's [`recv()`] method the application can process
126incoming packets that belong to that connection from the network:
127
128```rust
129let to = socket.local_addr().unwrap();
130
131loop {
132    let (read, from) = socket.recv_from(&mut buf).unwrap();
133
134    let recv_info = quiche::RecvInfo { from, to };
135
136    let read = match conn.recv(&mut buf[..read], recv_info) {
137        Ok(v) => v,
138
139        Err(e) => {
140            // An error occurred, handle it.
141            break;
142        },
143    };
144}
145```
146
147### Generating outgoing packets
148
149Outgoing packet are generated using the connection's [`send()`] method
150instead:
151
152```rust
153loop {
154    let (write, send_info) = match conn.send(&mut out) {
155        Ok(v) => v,
156
157        Err(quiche::Error::Done) => {
158            // Done writing.
159            break;
160        },
161
162        Err(e) => {
163            // An error occurred, handle it.
164            break;
165        },
166    };
167
168    socket.send_to(&out[..write], &send_info.to).unwrap();
169}
170```
171
172When packets are sent, the application is responsible for maintaining a
173timer to react to time-based connection events. The timer expiration can be
174obtained using the connection's [`timeout()`] method.
175
176```rust
177let timeout = conn.timeout();
178```
179
180The application is responsible for providing a timer implementation, which
181can be specific to the operating system or networking framework used. When
182a timer expires, the connection's [`on_timeout()`] method should be called,
183after which additional packets might need to be sent on the network:
184
185```rust
186// Timeout expired, handle it.
187conn.on_timeout();
188
189// Send more packets as needed after timeout.
190loop {
191    let (write, send_info) = match conn.send(&mut out) {
192        Ok(v) => v,
193
194        Err(quiche::Error::Done) => {
195            // Done writing.
196            break;
197        },
198
199        Err(e) => {
200            // An error occurred, handle it.
201            break;
202        },
203    };
204
205    socket.send_to(&out[..write], &send_info.to).unwrap();
206}
207```
208
209#### Pacing
210
211It is recommended that applications [pace] sending of outgoing packets to
212avoid creating packet bursts that could cause short-term congestion and
213losses in the network.
214
215quiche exposes pacing hints for outgoing packets through the [`at`] field
216of the [`SendInfo`] structure that is returned by the [`send()`] method.
217This field represents the time when a specific packet should be sent into
218the network.
219
220Applications can use these hints by artificially delaying the sending of
221packets through platform-specific mechanisms (such as the [`SO_TXTIME`]
222socket option on Linux), or custom methods (for example by using user-space
223timers).
224
225[pace]: https://datatracker.ietf.org/doc/html/rfc9002#section-7.7
226[`SO_TXTIME`]: https://man7.org/linux/man-pages/man8/tc-etf.8.html
227
228### Sending and receiving stream data
229
230After some back and forth, the connection will complete its handshake and
231will be ready for sending or receiving application data.
232
233Data can be sent on a stream by using the [`stream_send()`] method:
234
235```rust
236if conn.is_established() {
237    // Handshake completed, send some data on stream 0.
238    conn.stream_send(0, b"hello", true)?;
239}
240```
241
242The application can check whether there are any readable streams by using
243the connection's [`readable()`] method, which returns an iterator over all
244the streams that have outstanding data to read.
245
246The [`stream_recv()`] method can then be used to retrieve the application
247data from the readable stream:
248
249```rust
250if conn.is_established() {
251    // Iterate over readable streams.
252    for stream_id in conn.readable() {
253        // Stream is readable, read until there's no more data.
254        while let Ok((read, fin)) = conn.stream_recv(stream_id, &mut buf) {
255            println!("Got {} bytes on stream {}", read, stream_id);
256        }
257    }
258}
259```
260
261### HTTP/3
262
263The quiche [HTTP/3 module] provides a high level API for sending and
264receiving HTTP requests and responses on top of the QUIC transport protocol.
265
266[`Config`]: https://docs.quic.tech/quiche/struct.Config.html
267[`set_initial_max_streams_bidi()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_streams_bidi
268[`set_initial_max_streams_uni()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_streams_uni
269[`set_initial_max_data()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_data
270[`set_initial_max_stream_data_bidi_local()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_stream_data_bidi_local
271[`set_initial_max_stream_data_bidi_remote()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_stream_data_bidi_remote
272[`set_initial_max_stream_data_uni()`]: https://docs.rs/quiche/latest/quiche/struct.Config.html#method.set_initial_max_stream_data_uni
273[`with_boring_ssl_ctx()`]: https://docs.quic.tech/quiche/struct.Config.html#method.with_boring_ssl_ctx
274[`connect()`]: https://docs.quic.tech/quiche/fn.connect.html
275[`accept()`]: https://docs.quic.tech/quiche/fn.accept.html
276[`recv()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.recv
277[`send()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.send
278[`timeout()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.timeout
279[`on_timeout()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.on_timeout
280[`stream_send()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.stream_send
281[`readable()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.readable
282[`stream_recv()`]: https://docs.quic.tech/quiche/struct.Connection.html#method.stream_recv
283[HTTP/3 module]: https://docs.quic.tech/quiche/h3/index.html
284
285Have a look at the [quiche/examples/] directory for more complete examples on
286how to use the quiche API, including examples on how to use quiche in C/C++
287applications (see below for more information).
288
289[examples/]: quiche/examples/
290
291Calling quiche from C/C++
292-------------------------
293
294quiche exposes a [thin C API] on top of the Rust API that can be used to more
295easily integrate quiche into C/C++ applications (as well as in other languages
296that allow calling C APIs via some form of FFI). The C API follows the same
297design of the Rust one, modulo the constraints imposed by the C language itself.
298
299When running ``cargo build``, a static library called ``libquiche.a`` will be
300built automatically alongside the Rust one. This is fully stand-alone and can
301be linked directly into C/C++ applications.
302
303Note that in order to enable the FFI API, the ``ffi`` feature must be enabled (it
304is disabled by default), by passing ``--features ffi`` to ``cargo``.
305
306[thin C API]: https://github.com/cloudflare/quiche/blob/master/quiche/include/quiche.h
307
308Building
309--------
310
311quiche requires Rust 1.66 or later to build. The latest stable Rust release can
312be installed using [rustup](https://rustup.rs/).
313
314Once the Rust build environment is setup, the quiche source code can be fetched
315using git:
316
317```bash
318 $ git clone --recursive https://github.com/cloudflare/quiche
319```
320
321and then built using cargo:
322
323```bash
324 $ cargo build --examples
325```
326
327cargo can also be used to run the testsuite:
328
329```bash
330 $ cargo test
331```
332
333Note that [BoringSSL], which is used to implement QUIC's cryptographic handshake
334based on TLS, needs to be built and linked to quiche. This is done automatically
335when building quiche using cargo, but requires the `cmake` command to be
336available during the build process. On Windows you also need
337[NASM](https://www.nasm.us/). The [official BoringSSL
338documentation](https://github.com/google/boringssl/blob/master/BUILDING.md) has
339more details.
340
341In alternative you can use your own custom build of BoringSSL by configuring
342the BoringSSL directory with the ``QUICHE_BSSL_PATH`` environment variable:
343
344```bash
345 $ QUICHE_BSSL_PATH="/path/to/boringssl" cargo build --examples
346```
347
348[BoringSSL]: https://boringssl.googlesource.com/boringssl/
349
350### Building for Android
351
352Building quiche for Android (NDK version 19 or higher, 21 recommended), can be
353done using [cargo-ndk] (v2.0 or later).
354
355First the [Android NDK] needs to be installed, either using Android Studio or
356directly, and the `ANDROID_NDK_HOME` environment variable needs to be set to the
357NDK installation path, e.g.:
358
359```bash
360 $ export ANDROID_NDK_HOME=/usr/local/share/android-ndk
361```
362
363Then the Rust toolchain for the Android architectures needed can be installed as
364follows:
365
366```bash
367 $ rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
368```
369
370Note that the minimum API level is 21 for all target architectures.
371
372[cargo-ndk] (v2.0 or later) also needs to be installed:
373
374```bash
375 $ cargo install cargo-ndk
376```
377
378Finally the quiche library can be built using the following procedure. Note that
379the `-t <architecture>` and `-p <NDK version>` options are mandatory.
380
381```bash
382 $ cargo ndk -t arm64-v8a -p 21 -- build --features ffi
383```
384
385See [build_android_ndk19.sh] for more information.
386
387[Android NDK]: https://developer.android.com/ndk
388[cargo-ndk]: https://docs.rs/crate/cargo-ndk
389[build_android_ndk19.sh]: https://github.com/cloudflare/quiche/blob/master/tools/android/build_android_ndk19.sh
390
391### Building for iOS
392
393To build quiche for iOS, you need the following:
394
395- Install Xcode command-line tools. You can install them with Xcode or with the
396  following command:
397
398```bash
399 $ xcode-select --install
400```
401
402- Install the Rust toolchain for iOS architectures:
403
404```bash
405 $ rustup target add aarch64-apple-ios x86_64-apple-ios
406```
407
408- Install `cargo-lipo`:
409
410```bash
411 $ cargo install cargo-lipo
412```
413
414To build libquiche, run the following command:
415
416```bash
417 $ cargo lipo --features ffi
418```
419
420or
421
422```bash
423 $ cargo lipo --features ffi --release
424```
425
426iOS build is tested in Xcode 10.1 and Xcode 11.2.
427
428### Building Docker images
429
430In order to build the Docker images, simply run the following command:
431
432```bash
433 $ make docker-build
434```
435
436You can find the quiche Docker images on the following Docker Hub repositories:
437
438- [cloudflare/quiche](https://hub.docker.com/repository/docker/cloudflare/quiche)
439- [cloudflare/quiche-qns](https://hub.docker.com/repository/docker/cloudflare/quiche-qns)
440
441The `latest` tag will be updated whenever quiche master branch updates.
442
443**cloudflare/quiche**
444
445Provides a server and client installed in /usr/local/bin.
446
447**cloudflare/quiche-qns**
448
449Provides the script to test quiche within the [quic-interop-runner](https://github.com/marten-seemann/quic-interop-runner).
450
451Copyright
452---------
453
454Copyright (C) 2018-2019, Cloudflare, Inc.
455
456See [COPYING] for the license.
457
458[COPYING]: https://github.com/cloudflare/quiche/tree/master/COPYING
459