Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

🥧 Savoury implementation of the QUIC transport protocol and HTTP/3

License

NotificationsYou must be signed in to change notification settings

cloudflare/quiche

quiche

crates.iodocs.rslicensebuild

quiche is an implementation of the QUIC transport protocol and HTTP/3 asspecified by theIETF. It provides a low level API for processing QUIC packetsand 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.

For more information on how quiche came about and some insights into its designyou can read apost on Cloudflare's blog that goes into some more detail.

Who uses quiche?

Cloudflare

quiche powers Cloudflare edge network'sHTTP/3 support. Thecloudflare-quic.com website can be used fortesting and experimentation.

Android

Android's DNS resolver uses quiche toimplement DNS over HTTP/3.

curl

quiche can beintegrated into curl to provide support for HTTP/3.

Getting Started

Command-line apps

Before diving into the quiche API, here are a few examples on how to use thequiche tools provided as part of thequiche-apps crate.

After cloning the project according to the command mentioned in thebuilding section, the client can be run as follows:

 $ cargo run --bin quiche-client -- https://cloudflare-quic.com/

while the server can be run as follows:

 $ cargo run --bin quiche-server -- --cert apps/src/bin/cert.crt --key apps/src/bin/cert.key

(note that the certificate provided is self-signed and should not be used inproduction)

Use the--help command-line flag to get a more detailed description of eachtool's options.

Configuring connections

The first step in establishing a QUIC connection using quiche is creating aConfig object:

letmut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;config.set_application_protos(&[b"example-proto"]);// Additional configuration specific to application and use case...

TheConfig object controls important aspects of the QUIC connection suchas QUIC version, ALPN IDs, flow control, congestion control, idle timeoutand other properties or features.

QUIC is a general-purpose transport protocol and there are severalconfiguration properties where there is no reasonable default value. Forexample, the permitted number of concurrent streams of any particular typeis dependent on the application running over QUIC, and other use-casespecific concerns.

quiche defaults several properties to zero, applications most likely needto set these to something else to satisfy their needs using the following:

Config also holds TLS configuration. This can be changed by mutators onthe an existing object, or by constructing a TLS context manually andcreating a configuration usingwith_boring_ssl_ctx_builder().

A configuration object can be shared among multiple connections.

Connection setup

On the client-side theconnect() utility function can be used to createa new connection, whileaccept() is for servers:

// Client connection.let conn = quiche::connect(Some(&server_name),&scid, local, peer,&mut config)?;// Server connection.let conn = quiche::accept(&scid,None, local, peer,&mut config)?;

Handling incoming packets

Using the connection'srecv() method the application can processincoming packets that belong to that connection from the network:

let to = socket.local_addr().unwrap();loop{let(read, from) = socket.recv_from(&mut buf).unwrap();let recv_info = quiche::RecvInfo{ from, to};let read =match conn.recv(&mut buf[..read], recv_info){Ok(v) => v,Err(e) =>{// An error occurred, handle it.break;},};}

Generating outgoing packets

Outgoing packet are generated using the connection'ssend() methodinstead:

loop{let(write, send_info) =match conn.send(&mut out){Ok(v) => v,Err(quiche::Error::Done) =>{// Done writing.break;},Err(e) =>{// An error occurred, handle it.break;},};    socket.send_to(&out[..write],&send_info.to).unwrap();}

When packets are sent, the application is responsible for maintaining atimer to react to time-based connection events. The timer expiration can beobtained using the connection'stimeout() method.

let timeout = conn.timeout();

The application is responsible for providing a timer implementation, whichcan be specific to the operating system or networking framework used. Whena timer expires, the connection'son_timeout() method should be called,after which additional packets might need to be sent on the network:

// Timeout expired, handle it.conn.on_timeout();// Send more packets as needed after timeout.loop{let(write, send_info) =match conn.send(&mut out){Ok(v) => v,Err(quiche::Error::Done) =>{// Done writing.break;},Err(e) =>{// An error occurred, handle it.break;},};    socket.send_to(&out[..write],&send_info.to).unwrap();}

Pacing

It is recommended that applicationspace sending of outgoing packets toavoid creating packet bursts that could cause short-term congestion andlosses in the network.

quiche exposes pacing hints for outgoing packets through the [at] fieldof the [SendInfo] structure that is returned by thesend() method.This field represents the time when a specific packet should be sent intothe network.

Applications can use these hints by artificially delaying the sending ofpackets through platform-specific mechanisms (such as theSO_TXTIMEsocket option on Linux), or custom methods (for example by using user-spacetimers).

Sending and receiving stream data

After some back and forth, the connection will complete its handshake andwill be ready for sending or receiving application data.

Data can be sent on a stream by using thestream_send() method:

if conn.is_established(){// Handshake completed, send some data on stream 0.    conn.stream_send(0,b"hello",true)?;}

The application can check whether there are any readable streams by usingthe connection'sreadable() method, which returns an iterator over allthe streams that have outstanding data to read.

Thestream_recv() method can then be used to retrieve the applicationdata from the readable stream:

if conn.is_established(){// Iterate over readable streams.for stream_idin conn.readable(){// Stream is readable, read until there's no more data.whileletOk((read, fin)) = conn.stream_recv(stream_id,&mut buf){println!("Got {} bytes on stream {}", read, stream_id);}}}

HTTP/3

The quicheHTTP/3 module provides a high level API for sending andreceiving HTTP requests and responses on top of the QUIC transport protocol.

Have a look at the [quiche/examples/] directory for more complete examples onhow to use the quiche API, including examples on how to use quiche in C/C++applications (see below for more information).

Calling quiche from C/C++

quiche exposes athin C API on top of the Rust API that can be used to moreeasily integrate quiche into C/C++ applications (as well as in other languagesthat allow calling C APIs via some form of FFI). The C API follows the samedesign of the Rust one, modulo the constraints imposed by the C language itself.

When runningcargo build, a static library calledlibquiche.a will bebuilt automatically alongside the Rust one. This is fully stand-alone and canbe linked directly into C/C++ applications.

Note that in order to enable the FFI API, theffi feature must be enabled (itis disabled by default), by passing--features ffi tocargo.

Building

quiche requires Rust 1.82 or later to build. The latest stable Rust release canbe installed usingrustup.

Once the Rust build environment is setup, the quiche source code can be fetchedusing git:

 $ git clone --recursive https://github.com/cloudflare/quiche

and then built using cargo:

 $ cargo build --examples

cargo can also be used to run the testsuite:

 $ cargotest

Note thatBoringSSL, which is used to implement QUIC's cryptographic handshakebased on TLS, needs to be built and linked to quiche. This is done automaticallywhen building quiche using cargo, but requires thecmake command to beavailable during the build process. On Windows you also needNASM. Theofficial BoringSSLdocumentation hasmore details.

In alternative you can use your own custom build of BoringSSL by configuringthe BoringSSL directory with theQUICHE_BSSL_PATH environment variable:

 $ QUICHE_BSSL_PATH="/path/to/boringssl" cargo build --examples

Alternatively you can useOpenSSL/quictls. To enable quiche to use this vendortheopenssl feature can be added to the--feature list. Be aware that0-RTT is not supported if this vendor is used.

Building for Android

Building quiche for Android (NDK version 19 or higher, 21 recommended), can bedone usingcargo-ndk (v2.0 or later).

First theAndroid NDK needs to be installed, either using Android Studio ordirectly, and theANDROID_NDK_HOME environment variable needs to be set to theNDK installation path, e.g.:

 $export ANDROID_NDK_HOME=/usr/local/share/android-ndk

Then the Rust toolchain for the Android architectures needed can be installed asfollows:

 $ rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android

Note that the minimum API level is 21 for all target architectures.

cargo-ndk (v2.0 or later) also needs to be installed:

 $ cargo install cargo-ndk

Finally the quiche library can be built using the following procedure. Note thatthe-t <architecture> and-p <NDK version> options are mandatory.

 $ cargo ndk -t arm64-v8a -p 21 -- build --features ffi

Seebuild_android_ndk19.sh for more information.

Building for iOS

To build quiche for iOS, you need the following:

  • Install Xcode command-line tools. You can install them with Xcode or with thefollowing command:
 $ xcode-select --install
  • Install the Rust toolchain for iOS architectures:
 $ rustup target add aarch64-apple-ios x86_64-apple-ios
  • Installcargo-lipo:
 $ cargo install cargo-lipo

To build libquiche, run the following command:

 $ cargo lipo --features ffi

or

 $ cargo lipo --features ffi --release

iOS build is tested in Xcode 10.1 and Xcode 11.2.

Building Docker images

In order to build the Docker images, simply run the following command:

 $ make docker-build

You can find the quiche Docker images on the following Docker Hub repositories:

Thelatest tag will be updated whenever quiche master branch updates.

cloudflare/quiche

Provides a server and client installed in /usr/local/bin.

cloudflare/quiche-qns

Provides the script to test quiche within thequic-interop-runner.

Copyright

Copyright (C) 2018-2019, Cloudflare, Inc.

SeeCOPYING for the license.


[8]ページ先頭

©2009-2025 Movatter.jp