Skip to content

Commit

Permalink
feat(gm-quic): reuse connection and documents
Browse files Browse the repository at this point in the history
  • Loading branch information
eareimu committed Jan 21, 2025
1 parent ba7f1a3 commit 08c1be8
Show file tree
Hide file tree
Showing 10 changed files with 179 additions and 174 deletions.
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,21 @@ resolver = "2"
members = [
"qbase",
"qrecovery",
"qconnection",
"qcongestion",
"qudp",
"qinterface",
"qunreliable",
"qconnection",
"gm-quic",
"h3-shim",
"qinterface",
]
default-members = [
"qbase",
"qrecovery",
"qconnection",
"qcongestion",
"qunreliable",
"qinterface",
"qconnection",
"gm-quic",
]

Expand Down
26 changes: 19 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ With these layers in place, it becomes clear that the `Accept Functor` and the `
- **qbase**: Core structure of the QUIC protocol, including variable integer encoding (VarInt), connection ID management, stream ID, various frame and packet type definitions, and asynchronous keys.
- **qrecovery**: The reliable transport part of QUIC, encompassing the state machine evolution of the sender/receiver, and the internal logic interaction between the application layer and the transport layer.
- **qcongestion**: Congestion control in QUIC, which abstracts a unified congestion control interface and implements BBRv1. In the future, it will also implement more transport control algorithms such as Cubic and others.
- **qinterface**: QUIC's packet routing and definition of the underlying IO interface (`QuicInterface`) enable gm-quic to run in various environments. Contains an optional qudp-based `QuicInterface` implementation
- **qconnection**: Encapsulation of QUIC connections, linking the necessary components and tasks within a QUIC connection to ensure smooth operation.
- **gm-quic**: The top-level encapsulation of the QUIC protocol, including interfaces for both the QUIC client and server.
- **qudp**: High-performance UDP encapsulation for QUIC. Ordinary UDP incurs a system call for each packet sent or received, resulting in poor performance.
Expand Down Expand Up @@ -78,15 +79,27 @@ The QUIC client not only offers configuration options specified by the QUIC prot

```rust
let quic_client = QuicClient::builder()
// Allows reusing a connection to the server when there is already one,
// instead of initiating a new connection every time.
.reuse_connection()
// Keep the connection alive when it is idle
.keep_alive(Durnation::from_secs(30))
// The QUIC version negotiation mechanism prioritizes using the earlier versions,
// currently only supporting V1.
.prefer_versions([1u32])
// .with_parameter(&client_parameters) // If not set, the default parameters will be used
// .witl_streams_controller(controller) // Specify the streams controller for the client
// .with_token_sink(token_sink) // Manage Tokens issued by various servers
.with_root_certificates(root_certificates)
// .with_webpki_verifier(verifier) // More advanced ways to verify server certificates
.without_cert() // Generally, clients do not need to set certificates
// Specify how client bind interfaces
// The default interface is the high-performance udp implementation provided by qudp.
// .with_iface_binder(binder)
// Let the client only use the interface on specified address.
// By default, a new interface will be used every time initiates a connection.
// like 0.0.0.0:0 or [::]:0
// .bind(&local_addrs[..])?
.build();

let quic_client_conn = quic_client
Expand All @@ -98,11 +111,9 @@ The QUIC server provides SNI(Server Name Indication) support in TLS, allowing th

```rust
let quic_server = QuicServer::builder()
// Keep the accepted connection alive when it is idle
.keep_alive(Durnation::from_secs(30))
.with_supported_versions([1u32])
// for load balancing
// .with_load_balance(move |initial_packet: &InitialPacket| -> Option<RetryPacket> {
// ...
// })
.without_cert_verifier() // Generally, client identity is not verified
.enable_sni()
.add_host("www.genmeta.net", www_cert, www_key)
Expand All @@ -118,6 +129,8 @@ while let Ok(quic_server_conn) = quic_server.accept().await? {
}
```

For complete examples, please refer to the `examples` folders under the `h3-shim`, `gm-quic` and `qconnection` folders.

There is an asynchronous interface for creating unidirectional or bidirectional QUIC streams from a QUIC Connection, or for listening to incoming streams from the other side of a QUIC Connection. This interface is almost identical to the one in [`hyperium/h3`](https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md#5-quic-transport).

We also implement the interface defined by [`hyperium/h3`](https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md#5-quic-transport) in `h3-shim` crate to facilitate with other crates integrated. We have a frok of `reqwest` that use `gm-quic` as the transport layer, you can find it [here](https://github.com/genmeta/reqwest/tree/gm-quic).
Expand All @@ -126,12 +139,11 @@ As for reading and writing data from a QUIC stream, the tokio's `AsyncRead` and

## Progress

`gm-quic` has entered the final testing phase. Next, we will further improve the documentation and add the qlog module. Stay tuned.
The early version has been released and is still being continuously optimized and improved. Welcome to use it :D

## Documentation

While `gm-quic` is not yet complete, its documentation will not be uploaded to `crate.io`.
Please refer to the documentation within the code for now!
Online documentation released with the release is at docs.rs. You can also view the latest documentation in the code.

## Contribution

Expand Down
24 changes: 17 additions & 7 deletions README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ QUIC协议可谓一个相当复杂的、IO密集型的协议,因此正是适
- **qbase**: QUIC协议的基础结构,包括可变整型编码VarInt、连接ID管理、流ID、各种帧以及包类型定义、异步密钥等
- **qrecovery**: QUIC的可靠传输部分,包括发送端/接收端的状态机演变、应用层与传输层的内部逻辑交互等
- **qcongestion**: QUIC的拥塞控制,抽象了统一的拥塞控制接口,并实现了BBRv1,未来还会实现Cubic、ETC等更多的传输控制算法
- **qinterface**: QUIC的数据包路由和对底层IO接口(`QuicInterface`)的定义,令gm-quic可以运行在各种环境。内含一个可选的基于qudp的`QuicInterface`实现
- **qconnection**: QUIC连接封装,将QUIC连接内部所需的各组件、任务串联起来,最终能够完美运行
- **gm-quic**: QUIC协议的顶层封装,包括QUIC客户端和服务端2部分的接口
- **qudp**: QUIC的高性能UDP封装,普通的UDP每收发一个包就是一次系统调用,性能低下。qudp则使用GSO、GRO等手段极致优化UDP的性能,如发送的压测效果如下:
Expand Down Expand Up @@ -68,14 +69,23 @@ QUIC客户端不仅提供了QUIC协议所规定的Parameters选项配置,也

```rust
let quic_client = QuicClient::builder()
// 允许复用到服务器的连接,而不是每次都发起新连接
.reuse_connection()
.enable_happy_eyeballs()
// 自动在连接空闲时发送数据包保持连接活跃
.keep_alive(Durnation::from_secs(30))
.prefer_versions([1u32]) // QUIC的版本协商机制,会优先使用靠前的版本,目前仅支持V1
// .with_parameter(&client_parameters) // 不设置即为使用默认参数
// .with_token_sink(token_sink) // 管理各服务器颁发的Token
.with_root_certificates(root_certificates)
// .with_webpki_verifier(verifier) // 更高级地验证服务端证书的办法
.without_cert() // 一般客户端不必设置证书
// 指定客户端怎么绑定接口
// 默认的接口为qudp提供的高性能实现
// .with_iface_binder(binder)
// 令client只使用给定的地址
// 默认client每次建立连接时会创建一个新的接口,绑定系统随机分配的地址端口
// 即绑定0.0.0.0:0 或 [::]:0
// .bind(&local_addrs[..])?
.build();

let quic_client_conn = quic_client
Expand All @@ -87,11 +97,9 @@ QUIC服务端支持SNI(Server Name Indication),可以设置多台Server的

```rust
let quic_server = QuicServer::builder()
// 同client
.keep_alive(Durnation::from_secs(30))
.with_supported_versions([1u32])
// 通过重试包进行负载均衡
// .with_load_balance(move |initial_packet: &InitialPacket| -> Option<RetryPacket> {
// ...
// })
.without_cert_verifier() // 一般不验证客户端身份
.enable_sni()
.add_host("www.genmeta.net", www_cert, www_key)
Expand All @@ -107,17 +115,19 @@ while let Ok(quic_server_conn) = quic_server.accept().await? {
}
```

完整用例请翻阅`h3-shim``gm-quic`以及`qconnection`文件夹下的`examples`文件夹。

关于如何从QUIC Connection中创建单向QUIC流,或者双向QUIC流,抑或是从QUIC Connection监听来自对方的流,都有一套异步的接口,这套接口几乎与[`hyperium/h3`](https://github.com/hyperium/h3/blob/master/docs/PROPOSAL.md#5-quic-transport)的接口相同。

至于如何从QUIC流中读写数据,则为QUIC流实现了标准的`AsyncRead``AsyncWrite`接口,可以很方便地使用。

## 进展

`gm-quic`已经进入到最后的测试阶段。接下来,将进一步完善文档,以及补充qlog模块,敬请期待。
早期版本已经发布,目前仍在不断优化改进中,欢迎使用 :D

## 文档

`gm-quic`尚未完成之际,其文档也不会上传托管到`crate.io`。请暂且先查看代码中的文档!
随版本发布的在线文档位于docs.rs,也可查看代码中的最新文档。

## 贡献

Expand Down
1 change: 0 additions & 1 deletion gm-quic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ qcongestion = { workspace = true }
qconnection = { workspace = true }
qrecovery = { workspace = true }
qinterface = { workspace = true }
qudp = { workspace = true }
qunreliable = { workspace = true }
rustls = { workspace = true }
thiserror = { workspace = true }
Expand Down
9 changes: 1 addition & 8 deletions gm-quic/examples/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,9 @@ async fn run(args: Arguments) -> Result<(), Box<dyn std::error::Error>> {
.build();

let quic_conn = client.connect(args.domain, args.addr).unwrap();
let mut counter = 0;
loop {
let mut input = String::new();

if counter == 0 {
input = "/README.md".to_string();
counter += 1;
} else {
let _n = std::io::stdin().read_line(&mut input).unwrap();
}
_ = std::io::stdin().read_line(&mut input).unwrap();

let content = input.trim();
if content.is_empty() {
Expand Down
1 change: 1 addition & 0 deletions gm-quic/examples/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ async fn run(options: Opt) -> Result<(), Box<dyn std::error::Error>> {
let server = QuicServer::builder()
.with_supported_versions([0x00000001u32])
.without_cert_verifier()
// .keep_alive()
.with_single_cert(options.cert, options.key)
.listen(options.bind)?;

Expand Down
Loading

0 comments on commit 08c1be8

Please sign in to comment.