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