Skip to content

feat(quinn): Refactor polling & sending to take &mut self #67

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

Open
wants to merge 12 commits into
base: iroh-0.11.x
Choose a base branch
from

Conversation

matheus23
Copy link
Member

No description provided.

@matheus23 matheus23 self-assigned this May 21, 2025
@n0bot n0bot bot added this to iroh May 21, 2025
@github-project-automation github-project-automation bot moved this to 🏗 In progress in iroh May 21, 2025
@matheus23 matheus23 changed the title [WIP] Try implementing a poll_send-based AsyncUdpSocket abstraction feat(quinn): Refactor polling & sending to take &mut self May 22, 2025
@matheus23 matheus23 force-pushed the matheus23/mut-self branch from 871e5c6 to 54043ca Compare May 23, 2025 08:41
@dignifiedquire dignifiedquire marked this pull request as ready for review May 27, 2025 10:15
Copy link
Collaborator

@flub flub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall seems fine, but needs a lot of docs updates.

One main concern is that I'd like to be relatively sure that this isn't creating a performance impact on upstream Quinn. I believe @matheus23 has been working on this already.

The other is what upstream mentioned: this is a breaking change. For us this would be 0.14. I'd also prefer if we managed to move this upstream. I understand they also have concerns about the semvers-incompatible change. We should already start a PR and have it go through review to a "basically accepted" state, at which point I guess it'd be waiting for when they make the next semver-incompatible release. I believe there are already a few such issues queued up, so this will probably happen at some point.

/// If this returns [`io::ErrorKind::WouldBlock`], [`UdpPoller::poll_writable`] must be called
/// to register the calling task to be woken when a send should be attempted again.
fn try_send(&self, transmit: &Transmit) -> io::Result<()>;
fn create_sender(&self) -> Pin<Box<dyn UdpSender>>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc comments here needs updating.

@@ -91,71 +79,119 @@ pub trait AsyncUdpSocket: Send + Sync + Debug + 'static {
///
/// Any number of `UdpPoller`s may exist for a single [`AsyncUdpSocket`]. Each `UdpPoller` is
/// responsible for notifying at most one task when that socket becomes writable.
pub trait UdpPoller: Send + Sync + Debug + 'static {
pub trait UdpSender: Send + Sync + Debug + 'static {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doc comments need updating

/// Helper adapting a function `MakeFut` that constructs a single-use future `Fut` into a
/// [`UdpPoller`] that may be reused indefinitely
struct UdpPollHelper<MakeFut, Fut> {
pub struct UdpSenderHelper<Socket, MakeFut, Fut> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doc comments. I'd like to understand what fut is expected to do here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another TODO here: Do we want this to be pub? I initially turned this from private to pub because I thought it'd be useful to us in net-tools land in the netwatch socket impl, but turns out we can't quite use the helper there.

I generally find the helper... helpful? Usually anytime I implement AsyncUdpSocket, but it wasn't exposed in quinn before.

// obtain an `&mut Fut` after storing it in `self.fut` when `self` is already behind `Pin`,
// and if we didn't store it then we wouldn't be able to keep it alive between
// `poll_writable` calls.
let result = ready!(this.fut.as_mut().as_pin_mut().unwrap().poll(cx));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not sure what fut is expected to be doing when reading this code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed (this is inherited from the previous quinn code). I considered renaming it to WritableFut.
Polling this future tells us if the socket is writable, and wakes us up if so.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WritableFut would be great!


/// TODO(matheus23): Docs
/// Last ditch/best effort of sending a transmit.
/// Used by the endpoint for resets / close frames when dropped, etc.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like more than last-ditch since poll_send itself is implemented as a function of this? Anyway, a plea for better docs :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fact that it's used like that in the implementation of the tokio and async-io sockets is an implementation detail.
The documentation in the trait has to be more general.

}
}

pub trait UdpSenderHelperSocket: Send + Sync + 'static {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs on why this exists would be helpful. Seems like the reason is that it allows calling try_send and max_transmit_segments on the socket by the helper. Maybe the trait can also be called something like that? Like TrySendTransmit or something?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🏗 In progress
Development

Successfully merging this pull request may close these issues.

3 participants