-
-
Notifications
You must be signed in to change notification settings - Fork 395
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
quinn_udp: use async_io instead of tokio #1183
Closed
Closed
Changes from 9 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
e6a283d
Mv quinn/src/platform/ -> quinn-udp
kpp 9046b21
Use quinn-udp instead of quinn::platform
kpp 204dea1
Fix repo urls for quinn* crates
kpp 4953932
Add quinn-udp to the list of crates into the main README
kpp 765a9ce
Move quinn-udp from tokio to async_io
dvc94ch 07e59f8
Fix tests
kpp 0022dae
Add examples
dvc94ch f4fddac
Fix only_v6
kpp 78d43b5
Remove SocketType (it was a write-only field)
kpp 8106e68
Restore logging code
kpp 7e07c36
Cargo fmt code
kpp File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ name = "quinn-proto" | |
version = "0.7.0" | ||
authors = ["Benjamin Saunders <[email protected]>", "Dirkjan Ochtman <[email protected]>"] | ||
license = "MIT OR Apache-2.0" | ||
repository = "https://github.com/djc/quinn" | ||
repository = "https://github.com/quinn-rs/quinn" | ||
description = "State machine for the QUIC transport protocol" | ||
keywords = ["quic"] | ||
categories = [ "network-programming", "asynchronous" ] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
[package] | ||
name = "quinn-udp" | ||
version = "0.7.0" | ||
authors = ["Benjamin Saunders <[email protected]>", "Dirkjan Ochtman <[email protected]>", "David Craven <[email protected]>"] | ||
license = "MIT OR Apache-2.0" | ||
repository = "https://github.com/quinn-rs/quinn" | ||
description = "UDP sockets with ECN information for the QUIC transport protocol" | ||
keywords = ["quic"] | ||
categories = [ "network-programming", "asynchronous" ] | ||
workspace = ".." | ||
edition = "2018" | ||
|
||
[package.metadata.docs.rs] | ||
all-features = true | ||
|
||
[badges] | ||
maintenance = { status = "experimental" } | ||
|
||
[dependencies] | ||
async-io = "1.3.1" | ||
futures-lite = "1.11.3" | ||
libc = "0.2.69" | ||
proto = { package = "quinn-proto", path = "../quinn-proto", version = "0.7" } | ||
socket2 = "0.4" | ||
tracing = "0.1.10" | ||
|
||
[target.'cfg(unix)'.dependencies] | ||
lazy_static = "1" | ||
|
||
[dev-dependencies] | ||
anyhow = "1.0.40" | ||
async-global-executor = "2.0.2" | ||
env_logger = "0.8.3" | ||
log = "0.4.14" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
use anyhow::Result; | ||
use std::io::IoSliceMut; | ||
use std::net::Ipv4Addr; | ||
use std::time::Instant; | ||
use proto::{EcnCodepoint, Transmit}; | ||
use quinn_udp::{RecvMeta, UdpSocket, BATCH_SIZE}; | ||
|
||
fn main() -> Result<()> { | ||
env_logger::init(); | ||
let socket1 = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0).into())?; | ||
let socket2 = UdpSocket::bind((Ipv4Addr::LOCALHOST, 0).into())?; | ||
let addr2 = socket2.local_addr()?; | ||
|
||
let mut transmits = Vec::with_capacity(BATCH_SIZE); | ||
for i in 0..BATCH_SIZE { | ||
let contents = (i as u64).to_be_bytes().to_vec(); | ||
transmits.push(Transmit { | ||
destination: addr2, | ||
ecn: Some(EcnCodepoint::Ce), | ||
segment_size: Some(1200), | ||
contents, | ||
src_ip: Some(Ipv4Addr::LOCALHOST.into()), | ||
}); | ||
} | ||
|
||
let task1 = async_global_executor::spawn(async move { | ||
log::debug!("before send"); | ||
socket1.send(&transmits).await.unwrap(); | ||
log::debug!("after send"); | ||
}); | ||
|
||
let task2 = async_global_executor::spawn(async move { | ||
let mut storage = [[0u8; 1200]; BATCH_SIZE]; | ||
let mut buffers = Vec::with_capacity(BATCH_SIZE); | ||
let mut rest = &mut storage[..]; | ||
for _ in 0..BATCH_SIZE { | ||
let (b, r) = rest.split_at_mut(1); | ||
rest = r; | ||
buffers.push(IoSliceMut::new(&mut b[0])); | ||
} | ||
|
||
let mut meta = [RecvMeta::default(); BATCH_SIZE]; | ||
let n = socket2.recv(&mut buffers, &mut meta).await.unwrap(); | ||
for i in 0..n { | ||
log::debug!( | ||
"received {} {:?} {:?}", | ||
i, | ||
&buffers[i][..meta[i].len], | ||
&meta[i] | ||
); | ||
} | ||
}); | ||
|
||
async_global_executor::block_on(async move { | ||
let start = Instant::now(); | ||
task1.await; | ||
task2.await; | ||
println!( | ||
"sent {} packets in {}ms", | ||
BATCH_SIZE, | ||
start.elapsed().as_millis() | ||
); | ||
}); | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
use crate::RecvMeta; | ||
use proto::Transmit; | ||
|
||
use std::io::{IoSliceMut, Result}; | ||
|
||
pub fn init(_socket: &std::net::UdpSocket) -> Result<()> { | ||
// We do nothing with the given socket. | ||
Ok(()) | ||
} | ||
|
||
pub fn send(socket: &std::net::UdpSocket, transmits: &[Transmit]) -> Result<usize> { | ||
let mut sent = 0; | ||
for transmit in transmits { | ||
match socket.send_to(&transmit.contents, &transmit.destination) { | ||
Ok(_) => { | ||
sent += 1; | ||
} | ||
Err(_) if sent != 0 => { | ||
// We need to report that some packets were sent in this case, so we rely on | ||
// errors being either harmlessly transient (in the case of WouldBlock) or | ||
// recurring on the next call. | ||
return Ok(sent); | ||
} | ||
Err(e) => { | ||
return Err(e); | ||
} | ||
} | ||
} | ||
Ok(sent) | ||
} | ||
|
||
pub fn recv( | ||
socket: &std::net::UdpSocket, | ||
buffers: &mut [IoSliceMut<'_>], | ||
meta: &mut [RecvMeta], | ||
) -> Result<usize> { | ||
let (len, addr) = socket.recv_from(&mut buffers[0])?; | ||
meta[0] = RecvMeta { | ||
addr, | ||
len, | ||
ecn: None, | ||
dst_ip: None, | ||
}; | ||
Ok(1) | ||
} | ||
|
||
/// Returns the platforms UDP socket capabilities | ||
pub fn max_gso_segments() -> Result<usize> { | ||
Ok(1) | ||
} | ||
|
||
pub const BATCH_SIZE: usize = 1; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
use proto::{Transmit}; | ||
use crate::{RecvMeta, UdpCapabilities}; | ||
use async_io::Async; | ||
use futures_lite::future::poll_fn; | ||
use std::io::{IoSliceMut, Result}; | ||
use std::net::SocketAddr; | ||
use std::task::{Context, Poll}; | ||
|
||
use crate::platform as platform; | ||
|
||
/// Async-io-compatible UDP socket with some useful specializations. | ||
/// | ||
/// Unlike a standard UDP socket, this allows ECN bits to be read | ||
/// and written on some platforms. | ||
#[derive(Debug)] | ||
pub struct UdpSocket { | ||
inner: Async<std::net::UdpSocket>, | ||
} | ||
|
||
impl UdpSocket { | ||
/// Returns the platforms UDP socket capabilities | ||
pub fn capabilities() -> Result<UdpCapabilities> { | ||
Ok(UdpCapabilities { | ||
max_gso_segments: platform::max_gso_segments()?, | ||
}) | ||
} | ||
|
||
pub fn from_std(socket: std::net::UdpSocket) -> Result<Self> { | ||
platform::init(&socket)?; | ||
Ok(Self { | ||
inner: Async::new(socket)?, | ||
}) | ||
} | ||
|
||
pub fn bind(addr: SocketAddr) -> Result<Self> { | ||
let socket = std::net::UdpSocket::bind(addr)?; | ||
Self::from_std(socket) | ||
} | ||
|
||
pub fn local_addr(&self) -> Result<SocketAddr> { | ||
self.inner.get_ref().local_addr() | ||
} | ||
|
||
pub fn ttl(&self) -> Result<u8> { | ||
let ttl = self.inner.get_ref().ttl()?; | ||
Ok(ttl as u8) | ||
} | ||
|
||
pub fn set_ttl(&self, ttl: u8) -> Result<()> { | ||
self.inner.get_ref().set_ttl(ttl as u32) | ||
} | ||
|
||
pub fn poll_send(&self, cx: &mut Context, transmits: &[Transmit]) -> Poll<Result<usize>> { | ||
match self.inner.poll_writable(cx) { | ||
Poll::Ready(Ok(())) => {} | ||
Poll::Pending => return Poll::Pending, | ||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err)), | ||
} | ||
let socket = self.inner.get_ref(); | ||
match platform::send(socket, transmits) { | ||
Ok(len) => Poll::Ready(Ok(len)), | ||
Err(err) => Poll::Ready(Err(err)), | ||
} | ||
} | ||
|
||
pub fn poll_recv( | ||
&self, | ||
cx: &mut Context, | ||
buffers: &mut [IoSliceMut<'_>], | ||
meta: &mut [RecvMeta], | ||
) -> Poll<Result<usize>> { | ||
match self.inner.poll_readable(cx) { | ||
Poll::Ready(Ok(())) => {} | ||
Poll::Pending => return Poll::Pending, | ||
Poll::Ready(Err(err)) => return Poll::Ready(Err(err)), | ||
} | ||
let socket = self.inner.get_ref(); | ||
Poll::Ready(platform::recv(socket, buffers, meta)) | ||
} | ||
|
||
pub async fn send(&self, transmits: &[Transmit]) -> Result<usize> { | ||
let mut i = 0; | ||
while i < transmits.len() { | ||
i += poll_fn(|cx| self.poll_send(cx, &transmits[i..])).await?; | ||
} | ||
Ok(i) | ||
} | ||
|
||
pub async fn recv( | ||
&self, | ||
buffers: &mut [IoSliceMut<'_>], | ||
meta: &mut [RecvMeta], | ||
) -> Result<usize> { | ||
poll_fn(|cx| self.poll_recv(cx, buffers, meta)).await | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not very happy about this. I guess it would be better to duplicate the definitions and convert it in
quinn
.