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