Client and server timeout support#182
Conversation
Dropped this. I think I just had a stale base branch. |
| use crate::common::{IoSession, MidHandshake}; | ||
|
|
||
| /// A `MidHandshake` future bundled with an optional deadline. | ||
| pub(crate) struct HandshakeFuture<IS: IoSession> { |
There was a problem hiding this comment.
Why couldn't we use a tokio::time::Timeout<MindHandshake<IS>> instead of defining this wrapper ourselves?
There was a problem hiding this comment.
I tried that initially after reviewing 178 and having the same thought, but it didn't seem like a good fit to me after I tried it a bit.
- We still end up needing a wrapper enum or similar indirection for whether there is/isn't a
Timeoutunless we do something hacky like always allocating aTimeoutwith max duration. Timeoutis!UnpinbutMidHandshakeand everything else is currentlyUnpin, so we need toPin<Box<...>>it at the cost of a heap allocation and more nesting complexity.- Most importantly, I couldn't figure out a way to maintain
Connect::get_mut()with aPin<Box<Timeout<...>>>or theFallibleConnectimplementation where we need to recover the IO without usingunsafe.
I'm not particularly adept at async rust trickery, but achieving this in a semver compatible way using tokio::time::Timeout without any new deps or unsafe didn't seem tractable, and the implementation as done in this branch (and originally in 178) doesn't seem particularly complex in comparison.
If you think I'm missing something maybe we could land this approach and then refactor it down to a tokio::time::Timeout as follow-up?
|
Thanks for picking this up! |
Matches the client-side implementation. LazyConfigAcceptor/into_stream() paths not yet supported.
Internally store an absolute `Instant` rather than a relative `Duration`, and `sleep_until()` that deadline. The public `new(Option<Duration>)` constructor converts eagerly so existing callers see no behavior change. Add a `from_deadline(Option<Instant>)` constructor for callers that already have an absolute deadline. This is needed so `LazyConfigAcceptor` can establish a deadline in its phase and propagate it through `StartHandshake::into_stream()` to the post-ClientHello Accept, keeping the two phases sharing the same wall-clock deadline.
|
I'm still not sure if this feature belongs in the crate, you don't see something like this in e.g. Moreover, this implementation is not even optimal because we have to box the |
|
I guess my suggestion is to just implement |
|
Thanks for taking a look.
Perhaps, but I'm not sure I'm completely convinced of that yet. I think the linked issues show there's some demand and having each consumer implementing the same things themselves if we can offer it sensibly once via this crate might not be optimal.
I agree on the connect side that there are approaches to doing most of this outside the crate but I do think the
I'm not sure this feedback applies to the code in-branch? It isn't using pin-project, or unsafe, or making any breaking changes.
If you want to open an alternative PR that achieves equivalent support for timeouts across both client/server side internally in a different way, or shows how to achieve it comprehensively from |
Opinions can of course change over time, but part of why I looked at this was an initial signal from Djc in discord that this crate would be an acceptable place to make a change like this. |
I meant that the code in-branch is not (technically) optimal because it boxes the
My questioning is exactly if we should implement this internally or not. Your implementation is perfectly fine given the constraints, and I'm not strongly opposed to merging this PR. |
This takes the client-side timeout work from #178 with some review feedback applied, and extends it to the server-side (both for the simple case, as well as the lazy acceptor machinery).
The review feedback modifications to #178 can be reviewed as unsquashed fixup commits on this branch. In summary:
expect()to anunreachable!()with some commentary (a6d5566)start_paused(4a0b85d)Afterwards I overlaid server support for
TlsAcceptor/FallibleAccept, and then extended it for theLazyConfigAcceptorandinto_stream()bits.