3 个版本 (破坏性)

0.3.0 2024 年 1 月 24 日
0.2.0 2022 年 5 月 24 日
0.1.0 2022 年 4 月 8 日

#740网络编程

Download history 4028/week @ 2024-03-14 4123/week @ 2024-03-21 4663/week @ 2024-03-28 4491/week @ 2024-04-04 3602/week @ 2024-04-11 4324/week @ 2024-04-18 5442/week @ 2024-04-25 5343/week @ 2024-05-02 5430/week @ 2024-05-09 5481/week @ 2024-05-16 5072/week @ 2024-05-23 4622/week @ 2024-05-30 6126/week @ 2024-06-06 6506/week @ 2024-06-13 6387/week @ 2024-06-20 5296/week @ 2024-06-27

每月 25,205 次下载
38 个组件中使用 (5 个直接使用)

BSD-2-Clause

38KB
879

quiche

crates.io docs.rs license build

quiche 是 IETF 规定的 QUIC 传输协议和 HTTP/3 的实现。它提供了处理 QUIC 数据包和处理连接状态的低级 API。应用程序负责提供 I/O(例如套接字处理)以及支持定时器的事件循环。

有关 quiche 的产生及其设计的更多详细信息,您可以阅读 Cloudflare 博客上的文章

谁在使用 quiche?

Cloudflare

quiche 为 Cloudflare 边缘网络的 HTTP/3 支持 提供动力。可以使用 cloudflare-quic.com 网站进行测试和实验。

Android

Android 的 DNS 解析器使用 quiche 来 实现 DNS over HTTP/3

curl

可以将 quiche 集成到 curl 中以提供对 HTTP/3 的支持。查看集成方法

NGINX(非官方)

可以使用非官方补丁将 quiche 集成到 NGINX 中以提供对 HTTP/3 的支持。查看集成方法

入门

命令行应用程序

在深入了解 quiche API 之前,这里有一些使用作为 quiche-apps 组件的一部分提供的 quiche 工具的示例。

根据 构建 部分中提到的命令克隆项目后,客户端可以按照以下方式运行:

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

而服务器可以按照以下方式运行:

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

(请注意,提供的证书是自签名的,不应在生产中使用)

使用 --help 命令行标志可以获得每个工具选项的更详细描述。

配置连接

使用quiche建立QUIC连接的第一步是创建一个Config对象。

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

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

Config对象控制QUIC连接的重要方面,如QUIC版本、ALPN标识、流量控制、拥塞控制、空闲超时以及其他属性或功能。

QUIC是一种通用传输协议,有几个配置属性没有合理的默认值。例如,任何特定类型的并发流数取决于在QUIC上运行的应用程序以及其他特定用例的考虑。

quiche将多个属性默认设置为零,应用程序很可能需要根据以下内容将其设置为其他值以满足其需求:

Config还包含TLS配置。这可以通过对现有对象的突变者进行更改,或者通过手动构建TLS上下文并使用with_boring_ssl_ctx_builder()创建配置来更改。

配置对象可以在多个连接之间共享。

连接设置

在客户端,可以使用connect()实用函数来创建新的连接,而accept()则用于服务器。

// 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)?;

处理传入的数据包

应用程序可以使用连接的recv()方法处理属于该连接的来自网络的传入数据包。

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;
        },
    };
}

生成传出数据包

可以使用连接的send()方法生成传出数据包。

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();
}

发送数据包时,应用程序负责维护计时器以响应基于时间的连接事件。可以使用连接的timeout()方法获取计时器到期时间。

let timeout = conn.timeout();

应用程序负责提供计时器实现,这可能特定于操作系统或使用的网络框架。当计时器到期时,应调用连接的on_timeout()方法,之后可能需要在网络上发送更多数据包。

// 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();
}

节流

建议应用程序节流发送传出数据包,以避免创建可能导致网络短期拥塞和丢失的数据包突发。

quiche通过SendInfo结构体的[at]字段公开传出数据包的节流提示,该结构体由send()方法返回。此字段表示特定数据包应发送到网络中的时间。

应用程序可以通过平台特定的机制(例如Linux上的SO_TXTIME套接字选项)或自定义方法(例如使用用户空间定时器)人为地延迟发送数据包来使用这些提示。

发送和接收流数据

经过一番来回后,连接将完成握手并准备好发送或接收应用程序数据。

可以通过使用stream_send()方法在流上发送数据

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

应用程序可以使用连接的readable()方法检查是否有任何可读的流,该方法返回一个遍历所有待读取数据的流的迭代器。

然后可以使用stream_recv()方法从可读流中检索应用程序数据

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

HTTP/3

quiche HTTP/3模块为在QUIC传输协议之上发送和接收HTTP请求和响应提供了一个高级API。

请参阅quiche/examples/目录,了解更多如何使用quiche API的完整示例,包括如何在C/C++应用程序中使用quiche的示例(以下提供更多信息)。

从C/C++调用quiche

quiche在Rust API之上公开了一个精简的C API,可以更轻松地将quiche集成到C/C++应用程序中(以及允许通过某些形式的FFI调用C API的其他语言)。C API遵循与Rust相同的结构,但受到C语言本身的约束。

在运行cargo build时,将与Rust版本一起自动构建一个名为libquiche.a的静态库。这是一个完全独立的库,可以直接链接到C/C++应用程序中。

请注意,为了启用FFI API,必须启用ffi功能(默认情况下是禁用的),通过向cargo传递--features ffi来实现。

构建

quiche需要Rust 1.66或更高版本来构建。可以使用rustup安装最新的稳定版Rust。

设置好Rust构建环境后,可以使用git获取quiche源代码

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

然后使用cargo进行构建

 $ cargo build --examples

cargo还可以用于运行测试套件

 $ cargo test

请注意,用于实现基于TLS的QUIC的加密握手的BoringSSL需要构建并链接到quiche。当使用cargo构建quiche时,这会自动完成,但需要在构建过程中提供cmake命令。在Windows上,还需要NASM。有关详细信息,请参阅官方BoringSSL文档

作为替代,您可以使用自己的自定义构建的BoringSSL,通过使用QUICHE_BSSL_PATH环境变量配置BoringSSL目录来实现。

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

或者您可以使用 OpenSSL/quictls。要启用 quiche 使用此供应商,可以将 openssl 功能添加到 --feature 列表中。请注意,如果使用此供应商,则不支持 0-RTT

为 Android 构建

使用 NDK 版本 19 或更高版本(建议使用 21),可以使用 cargo-ndk(v2.0 或更高版本)为 Android 构建 quiche。

首先需要安装 Android NDK,可以使用 Android Studio 或直接安装,并将环境变量 ANDROID_NDK_HOME 设置为 NDK 安装路径,例如:

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

然后,可以按照以下方式安装所需的 Android 架构的 Rust 工具链:

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

请注意,所有目标架构的最小 API 级别为 21。

还需要安装 cargo-ndk(v2.0 或更高版本)

 $ cargo install cargo-ndk

最后,可以使用以下步骤构建 quiche 库。请注意,-t <架构>-p <NDK 版本> 选项是必需的。

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

有关更多信息,请参阅 build_android_ndk19.sh

为 iOS 构建

要为 iOS 构建 quiche,您需要以下内容:

  • 安装 Xcode 命令行工具。您可以使用 Xcode 安装它们,或者使用以下命令安装:
 $ xcode-select --install
  • 安装 iOS 架构的 Rust 工具链
 $ rustup target add aarch64-apple-ios x86_64-apple-ios
  • 安装 cargo-lipo
 $ cargo install cargo-lipo

要构建 libquiche,请运行以下命令:

 $ cargo lipo --features ffi

 $ cargo lipo --features ffi --release

iOS 构建已在 Xcode 10.1 和 Xcode 11.2 中测试。

构建 Docker 镜像

为了构建 Docker 镜像,只需运行以下命令:

 $ make docker-build

您可以在以下 Docker Hub 仓库找到 quiche Docker 镜像:

每当 quiche master 分支更新时,将更新 latest 标签。

cloudflare/quiche

提供安装在 /usr/local/bin 中的服务器和客户端。

cloudflare/quiche-qns

提供在 quic-interop-runner 中测试 quiche 的脚本。

版权(C)2018-2019,Cloudflare,Inc。

有关许可信息,请参阅 COPYING

无运行时依赖