RepoCloudflare (Workers AI)Cloudflare (Workers AI)published Jan 9, 2025seen 5d

cloudflare/quiche-mallard

Rust

Open original ↗

Captured source

source ↗
published Jan 9, 2025seen 5dcaptured 8hhttp 200method plain

cloudflare/quiche-mallard

Description: quiche fork with congestion & zero-copy patches

Language: Rust

License: BSD-2-Clause

Stars: 1

Forks: 0

Open issues: 0

Created: 2025-01-09T12:01:43Z

Pushed: 2025-06-04T11:57:47Z

Default branch: main

Fork: no

Archived: yes

README: ![quiche](quiche.svg)

![docs.rs](https://docs.rs/quiche-mallard)

_This was a fork of cloudflare/quiche to test new zero-copy and congestion control patches. These have been merged upstream as of quiche 0.24. quiche-mallard is now considered deprecated and archived._

[quiche] is an implementation of the QUIC transport protocol and HTTP/3 as specified by the [IETF]. It provides a low level API for processing QUIC packets and 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 design you can read a [post] on Cloudflare's blog that goes into some more detail.

[quiche]: https://docs.quic.tech/quiche/ [ietf]: https://quicwg.org/ [post]: https://blog.cloudflare.com/enjoy-a-slice-of-quic-and-rust/

Who uses quiche? ----------------

Cloudflare

quiche powers Cloudflare edge network's [HTTP/3 support][cloudflare-http3]. The cloudflare-quic.com website can be used for testing and experimentation.

Android

Android's DNS resolver uses quiche to [implement DNS over HTTP/3][android-http3].

curl

quiche can be [integrated into curl][curl-http3] to provide support for HTTP/3.

NGINX (unofficial)

quiche can be [integrated into NGINX](nginx/) using an unofficial patch to provide support for HTTP/3.

[cloudflare-http3]: https://blog.cloudflare.com/http3-the-past-present-and-future/ [android-http3]: https://security.googleblog.com/2022/07/dns-over-http3-in-android.html [curl-http3]: https://github.com/curl/curl/blob/master/docs/HTTP3.md#quiche-version

Getting Started ---------------

Command-line apps

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

After cloning the project according to the command mentioned in the [building](#building) 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 in production)

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

Configuring connections

The first step in establishing a QUIC connection using quiche is creating a [Config] object:

let mut config = quiche::Config::new(quiche::PROTOCOL_VERSION)?;
config.set_application_protos(&[b"example-proto"]);

// Additional configuration specific to application and use case...

The [Config] object controls important aspects of the QUIC connection such as QUIC version, ALPN IDs, flow control, congestion control, idle timeout and other properties or features.

QUIC is a general-purpose transport protocol and there are several configuration properties where there is no reasonable default value. For example, the permitted number of concurrent streams of any particular type is dependent on the application running over QUIC, and other use-case specific concerns.

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

  • [set_initial_max_streams_bidi()]
  • [set_initial_max_streams_uni()]
  • [set_initial_max_data()]
  • [set_initial_max_stream_data_bidi_local()]
  • [set_initial_max_stream_data_bidi_remote()]
  • [set_initial_max_stream_data_uni()]

[Config] also holds TLS configuration. This can be changed by mutators on the an existing object, or by constructing a TLS context manually and creating a configuration using [with_boring_ssl_ctx_builder()].

A configuration object can be shared among multiple connections.

Connection setup

On the client-side the [connect()] utility function can be used to create a new connection, while [accept()] 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's [recv()] method the application can process incoming 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's [send()] method instead:

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 a timer to react to time-based connection events. The timer expiration can be obtained using the connection's [timeout()] method.

let timeout = conn.timeout();

The application is responsible for providing a timer implementation, which can be specific to the operating system or networking framework used. When a timer expires, the connection's [on_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 applications [pace] sending of outgoing packets to avoid creating packet bursts that could cause short-term congestion and losses in the…

Excerpt shown — open the source for the full document.

Notability

notability 2.0/10

New repo, low traction, likely routine fork