Skip to content

Commit

Permalink
Implement optional support for axum 0.8's Listener trait
Browse files Browse the repository at this point in the history
Doing this is required due to how the orphan rule works in Rust

Signed-off-by: kanpov <karpovanton729@gmail.com>
  • Loading branch information
kanpov committed Feb 10, 2025
1 parent 9281018 commit 9d17fd5
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 1 deletion.
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "tokio-vsock"
version = "0.7.0"
version = "0.7.1"
authors = ["fsyncd", "rust-vsock"]
description = "Asynchronous Virtio socket support for Rust"
repository = "https://github.com/rust-vsock/tokio-vsock"
Expand All @@ -25,6 +25,10 @@ tonic09 = { package = "tonic", version = "0.9", optional = true }
tonic010 = { package = "tonic", version = "0.10", optional = true }
tonic011 = { package = "tonic", version = "0.11", optional = true }
tonic012 = { package = "tonic", version = "0.12", optional = true }
axum08 = { package = "axum", version = "0.8", optional = true, default-features = false, features = [
"tokio",
"http1",
] }

[dev-dependencies]
sha2 = "0.10.6"
Expand Down
45 changes: 45 additions & 0 deletions src/axum_support.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#[cfg(feature = "axum08")]
#[cfg_attr(docsrs, doc(cfg(feature = "axum08")))]
impl axum08::serve::Listener for crate::VsockListener {
type Io = crate::VsockStream;

type Addr = vsock::VsockAddr;

async fn accept(&mut self) -> (Self::Io, Self::Addr) {
loop {
match std::future::poll_fn(|cx| self.poll_accept(cx)).await {
Ok(tuple) => return tuple,
Err(err) => handle_accept_error(err).await,
}
}
}

fn local_addr(&self) -> std::io::Result<Self::Addr> {
self.local_addr()
}
}

#[cfg(feature = "axum08")]
async fn handle_accept_error(err: std::io::Error) {
if matches!(
err.kind(),
std::io::ErrorKind::ConnectionRefused
| std::io::ErrorKind::ConnectionAborted
| std::io::ErrorKind::ConnectionReset
) {
return;
}

// [From `hyper::Server` in 0.14](https://github.com/hyperium/hyper/blob/v0.14.27/src/server/tcp.rs#L186)
//
// > A possible scenario is that the process has hit the max open files
// > allowed, and so trying to accept a new connection will fail with
// > `EMFILE`. In some cases, it's preferable to just wait for some time, if
// > the application will likely close some files (or connections), and try
// > to accept the connection again. If this option is `true`, the error
// > will be logged at the `error` level, since it is still a big deal,
// > and then the listener will sleep for 1 second.
//
// hyper allowed customizing this but axum does not.
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#![cfg_attr(docsrs, feature(doc_cfg))]

mod axum_support;
mod listener;
mod split;
mod stream;
Expand Down

0 comments on commit 9d17fd5

Please sign in to comment.