Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: QUIC #282

Merged
merged 28 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
07124ee
feat(net): add `get_socket_option` on `Socket`
AsakuraMizu Jul 31, 2024
c4e9db5
feat(quic): basic endpoint & connection
AsakuraMizu Jul 31, 2024
110011b
fix(quic): blocking
AsakuraMizu Aug 5, 2024
d84891a
feat(quic): datagram
AsakuraMizu Aug 5, 2024
e466fc0
feat(quic): stream
AsakuraMizu Aug 8, 2024
a24f248
feat(quic): 0-rtt
AsakuraMizu Aug 8, 2024
9a58d2f
feat(quic): redesign builders
AsakuraMizu Aug 8, 2024
29ed9f9
test(quic): port from quinn
AsakuraMizu Aug 8, 2024
efa7323
fix(driver,iocp): fix incorrect opcode impl
AsakuraMizu Aug 8, 2024
7fb5067
fix(quic): windows specific bug
AsakuraMizu Aug 9, 2024
afb0539
chore(quic): interaction with tracing
AsakuraMizu Aug 9, 2024
83b928b
feat(quic): add bench
AsakuraMizu Aug 15, 2024
aae6db4
feat(quic): improved close logic
AsakuraMizu Aug 15, 2024
c3cc570
Merge branch 'master' into quic
AsakuraMizu Aug 17, 2024
13fa978
fix(net): mark get/set_socket_option as unsafe
AsakuraMizu Aug 17, 2024
c329a7c
test(net): remove redundant send_msg test
AsakuraMizu Aug 17, 2024
32e07e0
test(quic): ignore echo_dualstack on unsupported platforms
AsakuraMizu Aug 19, 2024
20a3683
feat(quic): remove event-listener
AsakuraMizu Aug 20, 2024
e99bc8d
feat(quic): http3
AsakuraMizu Aug 20, 2024
56bcf29
fix(quic): apply suggestions from code review
AsakuraMizu Aug 24, 2024
aa0ec20
fix(driver, iocp): remove unnecessary field
AsakuraMizu Aug 24, 2024
514b9b7
chore(quic): rustls provider
AsakuraMizu Aug 24, 2024
6590833
bench(quic): various size
AsakuraMizu Aug 24, 2024
fc23e2a
Merge branch 'compio-rs:master' into quic
AsakuraMizu Aug 26, 2024
77f1e23
chore: extract common deps into workspace
AsakuraMizu Aug 26, 2024
b1ed765
chore(quic): simplify check_0rtt
AsakuraMizu Aug 27, 2024
148f3ac
chore(net): add type constraint for get/set_socket_option
AsakuraMizu Aug 27, 2024
ee92ffd
perf(quic): batch recv on channel
AsakuraMizu Aug 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ members = [
"compio-tls",
"compio-log",
"compio-process",
"compio-quic",
]
resolver = "2"

Expand All @@ -36,6 +37,7 @@ compio-dispatcher = { path = "./compio-dispatcher", version = "0.3.0" }
compio-log = { path = "./compio-log", version = "0.1.0" }
compio-tls = { path = "./compio-tls", version = "0.2.0", default-features = false }
compio-process = { path = "./compio-process", version = "0.1.0" }
compio-quic = { path = "./compio-quic", version = "0.1.0" }

flume = "0.11.0"
cfg-if = "1.0.0"
Expand All @@ -49,6 +51,7 @@ nix = "0.29.0"
once_cell = "1.18.0"
os_pipe = "1.1.4"
paste = "1.0.14"
rustls = { version = "0.23.1", default-features = false }
slab = "0.4.9"
socket2 = "0.5.6"
tempfile = "3.8.1"
Expand Down
61 changes: 26 additions & 35 deletions compio-driver/src/iocp/op.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
#[cfg(feature = "once_cell_try")]
use std::sync::OnceLock;
use std::{
io,
marker::PhantomPinned,
net::Shutdown,
os::windows::io::AsRawSocket,
pin::Pin,
ptr::{null, null_mut},
task::Poll,
io, marker::PhantomPinned, net::Shutdown, os::windows::io::AsRawSocket, pin::Pin, ptr::{null, null_mut}, task::Poll
AsakuraMizu marked this conversation as resolved.
Show resolved Hide resolved
};

use aligned_array::{Aligned, A8};
Expand Down Expand Up @@ -781,12 +775,12 @@ static WSA_RECVMSG: OnceLock<LPFN_WSARECVMSG> = OnceLock::new();

/// Receive data and source address with ancillary data into vectored buffer.
pub struct RecvMsg<T: IoVectoredBufMut, C: IoBufMut, S> {
msg: WSAMSG,
addr: SOCKADDR_STORAGE,
addr_len: socklen_t,
fd: SharedFd<S>,
buffer: T,
control: C,
control_len: u32,
slices: Vec<IoSliceMut>,
AsakuraMizu marked this conversation as resolved.
Show resolved Hide resolved
_p: PhantomPinned,
}

Expand All @@ -802,12 +796,12 @@ impl<T: IoVectoredBufMut, C: IoBufMut, S> RecvMsg<T, C, S> {
"misaligned control message buffer"
);
Self {
msg: unsafe { std::mem::zeroed() },
addr: unsafe { std::mem::zeroed() },
addr_len: std::mem::size_of::<SOCKADDR_STORAGE>() as _,
fd,
buffer,
control,
control_len: 0,
slices: vec![],
_p: PhantomPinned,
}
}
Expand All @@ -820,8 +814,8 @@ impl<T: IoVectoredBufMut, C: IoBufMut, S> IntoInner for RecvMsg<T, C, S> {
(
(self.buffer, self.control),
self.addr,
self.addr_len,
self.control_len as _,
self.msg.namelen,
self.msg.Control.len as _,
)
}
}
Expand All @@ -835,26 +829,22 @@ impl<T: IoVectoredBufMut, C: IoBufMut, S: AsRawFd> OpCode for RecvMsg<T, C, S> {
})?;

let this = self.get_unchecked_mut();
let mut slices = this.buffer.io_slices_mut();
let mut msg = WSAMSG {
name: &mut this.addr as *mut _ as _,
namelen: this.addr_len,
lpBuffers: slices.as_mut_ptr() as _,
dwBufferCount: slices.len() as _,
Control: std::mem::transmute::<IoSliceMut, WSABUF>(this.control.as_io_slice_mut()),
dwFlags: 0,
};
this.control_len = 0;

this.slices = this.buffer.io_slices_mut();
this.msg.name = &mut this.addr as *mut _ as _;
this.msg.namelen = std::mem::size_of::<SOCKADDR_STORAGE>() as _;
this.msg.lpBuffers = this.slices.as_mut_ptr() as _;
this.msg.dwBufferCount = this.slices.len() as _;
this.msg.Control = std::mem::transmute::<IoSliceMut, WSABUF>(this.control.as_io_slice_mut());

let mut received = 0;
let res = recvmsg_fn(
this.fd.as_raw_fd() as _,
&mut msg,
&mut this.msg,
&mut received,
optr,
None,
);
this.control_len = msg.Control.len;
winsock_result(res, received)
}

Expand All @@ -866,10 +856,12 @@ impl<T: IoVectoredBufMut, C: IoBufMut, S: AsRawFd> OpCode for RecvMsg<T, C, S> {
/// Send data to specified address accompanied by ancillary data from vectored
/// buffer.
pub struct SendMsg<T: IoVectoredBuf, C: IoBuf, S> {
msg: WSAMSG,
fd: SharedFd<S>,
buffer: T,
control: C,
addr: SockAddr,
pub(crate) slices: Vec<IoSlice>,
AsakuraMizu marked this conversation as resolved.
Show resolved Hide resolved
_p: PhantomPinned,
}

Expand All @@ -885,10 +877,12 @@ impl<T: IoVectoredBuf, C: IoBuf, S> SendMsg<T, C, S> {
"misaligned control message buffer"
);
Self {
msg: unsafe { std::mem::zeroed() },
fd,
buffer,
control,
addr,
slices: vec![],
_p: PhantomPinned,
}
}
Expand All @@ -906,18 +900,15 @@ impl<T: IoVectoredBuf, C: IoBuf, S: AsRawFd> OpCode for SendMsg<T, C, S> {
unsafe fn operate(self: Pin<&mut Self>, optr: *mut OVERLAPPED) -> Poll<io::Result<usize>> {
let this = self.get_unchecked_mut();

let slices = this.buffer.io_slices();
let msg = WSAMSG {
name: this.addr.as_ptr() as _,
namelen: this.addr.len(),
lpBuffers: slices.as_ptr() as _,
dwBufferCount: slices.len() as _,
Control: std::mem::transmute::<IoSlice, WSABUF>(this.control.as_io_slice()),
dwFlags: 0,
};
this.slices = this.buffer.io_slices();
this.msg.name = this.addr.as_ptr() as _;
this.msg.namelen = this.addr.len();
this.msg.lpBuffers = this.slices.as_ptr() as _;
this.msg.dwBufferCount = this.slices.len() as _;
this.msg.Control = std::mem::transmute::<IoSlice, WSABUF>(this.control.as_io_slice());

let mut sent = 0;
let res = WSASendMsg(this.fd.as_raw_fd() as _, &msg, 0, &mut sent, optr, None);
let res = WSASendMsg(this.fd.as_raw_fd() as _, &this.msg, 0, &mut sent, optr, None);
winsock_result(res, sent)
}

Expand Down
45 changes: 44 additions & 1 deletion compio-net/src/socket.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::{future::Future, io, mem::ManuallyDrop};
use std::{
future::Future,
io,
mem::{ManuallyDrop, MaybeUninit},
};

use compio_buf::{BufResult, IntoInner, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut};
#[cfg(unix)]
Expand Down Expand Up @@ -319,6 +323,45 @@ impl Socket {
compio_runtime::submit(op).await.into_inner()
}

#[cfg(unix)]
pub fn get_socket_option<T>(&self, level: i32, name: i32) -> io::Result<T> {
let mut value: MaybeUninit<T> = MaybeUninit::uninit();
AsakuraMizu marked this conversation as resolved.
Show resolved Hide resolved
let mut len = size_of::<T>() as libc::socklen_t;
syscall!(libc::getsockopt(
self.socket.as_raw_fd(),
level,
name,
value.as_mut_ptr() as _,
&mut len
))
.map(|_| {
debug_assert_eq!(len as usize, size_of::<T>());
// SAFETY: The value is initialized by `getsockopt`.
unsafe { value.assume_init() }
})
}

#[cfg(windows)]
pub fn get_socket_option<T>(&self, level: i32, name: i32) -> io::Result<T> {
let mut value: MaybeUninit<T> = MaybeUninit::uninit();
let mut len = size_of::<T>() as i32;
syscall!(
SOCKET,
windows_sys::Win32::Networking::WinSock::getsockopt(
self.socket.as_raw_fd() as _,
level,
name,
value.as_mut_ptr() as _,
&mut len
)
)
.map(|_| {
debug_assert_eq!(len as usize, size_of::<T>());
// SAFETY: The value is initialized by `getsockopt`.
unsafe { value.assume_init() }
})
}

#[cfg(unix)]
pub fn set_socket_option<T>(&self, level: i32, name: i32, value: &T) -> io::Result<()> {
syscall!(libc::setsockopt(
Expand Down
5 changes: 5 additions & 0 deletions compio-net/src/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,11 @@ impl UdpSocket {
.await
}

/// Gets a socket option.
pub fn get_socket_option<T>(&self, level: i32, name: i32) -> io::Result<T> {
self.inner.get_socket_option(level, name)
}

/// Sets a socket option.
pub fn set_socket_option<T>(&self, level: i32, name: i32, value: &T) -> io::Result<()> {
self.inner.set_socket_option(level, name, value)
Expand Down
69 changes: 69 additions & 0 deletions compio-quic/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[package]
name = "compio-quic"
version = "0.1.0"
description = "QUIC for compio"
categories = ["asynchronous", "network-programming"]
keywords = ["async", "net", "quic"]
edition = { workspace = true }
authors = { workspace = true }
readme = { workspace = true }
license = { workspace = true }
repository = { workspace = true }

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
# Workspace dependencies
compio-io = { workspace = true }
compio-buf = { workspace = true }
compio-log = { workspace = true }
compio-net = { workspace = true }
compio-runtime = { workspace = true, features = ["time"] }

quinn-proto = "0.11.3"
rustls = { workspace = true, features = ["ring"] }
AsakuraMizu marked this conversation as resolved.
Show resolved Hide resolved
rustls-platform-verifier = { version = "0.3.3", optional = true }
rustls-native-certs = { version = "0.7.1", optional = true }
webpki-roots = { version = "0.26.3", optional = true }

# Utils
bytes = "1.7.1"
event-listener = "5.3.1"
flume = { workspace = true }
futures-util = { workspace = true }
thiserror = "1.0.63"

# Windows specific dependencies
[target.'cfg(windows)'.dependencies]
windows-sys = { workspace = true, features = ["Win32_Networking_WinSock"] }

[target.'cfg(unix)'.dependencies]
libc = { workspace = true }

[dev-dependencies]
compio-dispatcher = { workspace = true }
compio-driver = { workspace = true }
compio-macros = { workspace = true }
compio-runtime = { workspace = true, features = ["criterion"] }

rand = "0.8.5"
rcgen = "0.13.1"
socket2 = { workspace = true, features = ["all"] }
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }

criterion = { workspace = true, features = ["async_tokio"] }
quinn = "0.11.3"
tokio = { workspace = true, features = ["rt", "macros"] }

[features]
default = []
io-compat = ["futures-util/io"]
platform-verifier = ["dep:rustls-platform-verifier"]
native-certs = ["dep:rustls-native-certs"]
webpki-roots = ["dep:webpki-roots"]

[[bench]]
name = "quic"
harness = false
Loading
Loading