-
Notifications
You must be signed in to change notification settings - Fork 950
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
Re-design the StreamMuxer
trait
#2722
Comments
I'd like to discuss again the interface of the In the QUIC muxer we need a way of driving the inner
I am in favor of the 3rd option. The pub trait StreamMuxer {
type Substream: AsyncRead + AsyncWrite;
type Error: std::error::Error;
.
fn close(&mut self) -> Result<Self::Substream, Self::Error>;
fn open_outbound(&mut self, open_info: Self::Info) -> Result<SubstreamId, Self::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<SubstreamEvent<Self::Substream>, Self::Error>>;
}
pub enum SubstreamEvent<S> {
Substream {
stream: S,
id: SubstreamId
},
AddressChange {..}
} I am aware that there was already a discussion in #2724 (comment) about this and that it was the continuous decision for the current design (e.g. to also allow backpressuring inbound substreams). Again, sorry for not engaging in that discussion back then.
@thomaseizinger @mxinden what do you think? Are there drawbacks that I did not consider or any other reasons why you prefer to current design? Also happy to hear alternative ideas on how / where to drive our inner connection in Quic. |
Thanks for commenting! I did think about this problem actually but perhaps the trade-offs play out differently then what I thought they would. The problem I see with a single The current API is IMO rather simple because it is flat. It also simplified things quite a bit in Assuming we want to keep the current API, then I think the way to implement this for QUIC is by copying what was done in mplex: Drive the inner connection on every If we want a different API, then I'd suggest the following: pub trait StreamMuxer {
type Substream: AsyncRead + AsyncWrite;
type Error: std::error::Error;
.
fn close(&mut self) -> Result<(), Self::Error>;
fn open_outbound(&mut self) -> Result<SubstreamId, Self::Error>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<SubstreamEvent<Self::Substream>, Self::Error>>;
}
pub enum SubstreamEvent<S> {
OutgoingSubstream {
stream: S,
id: SubstreamId
},
IncomingSubstream(S),
AddressChange {..}
}
What is not to underestimate is the boilerplate that comes with this ID management which has to be duplicated in every muxer implementation. |
I'm quite happy with the current design of |
I believe I should try to move QuicMuxer to a new API to give it a try. |
When discussing the integration of the new interface in quic, @elenaf9 mentioned that one theoretical issue that we currently have is that one of the In practise,
This function can act as a general-purpose "make progress" function and all other |
Sounds good to me. For the record:
See kpp#19 (comment). |
Thank you. I will take a look |
There is now a draft PR of the above idea here: #2797 |
Discussed in libp2p#2722.
Something I stumbled across just now: in the swarm, we never poll rust-libp2p/swarm/src/connection/pool/task.rs Lines 237 to 249 in 8931860
(The above match block is always called when the connection closes, including graceful closing e.g. because of KeepAlive::No ).
Before #2248 the returned future was driven to completion before dropping the connection (code). |
I think there is a confusion here. We close a connection either due to (1) the (1)
|
Ah thanks, I did overlook case Nr (1).
The connection also returns an error |
We could at least try to close it and ignore any |
Example for such "polled after completion": #2598 That said, I think you are right @elenaf9. In the case of the handler, not the actual I/O resource (connection), returning an error (e.g. I wonder whether we should fix this earlier, or first combine |
Imo it's sufficient if we do it after / within the PR that combines |
I am closing this as completed 🥳 |
Very good work! The amount of small pull requests working towards a greater goal is stunning. Thanks for making it easy to review. |
This issue tracks the redesign of the
StreamMuxer
trait which was originally started in #2648.The primary goals are:
AsyncRead
+AsyncWrite
&mut self
for theStreamMuxer
(This may extend toPin<&mut Self>
)PRs related to this issue
StreamMuxer::Error
to io::Error #2664Poll
import #2685StreamMuxer::flush_all
function #2669close
topoll_close
#2666Sync
bounds #2667StreamMuxerBox
#2668Yamux::close
to use?
#2677ConnectionError
in public API withio::Error
rust-yamux#135StreamMuxerEvent::map_inbound_stream
#2691boxed
module #2703AsyncRead
andAsyncWrite
forSubstream
#2706StreamMuxer::Substream
to implementAsync{Read,Write}
#2707Into<io::Error>
bound onStreamMuxer
withstd::error::Error
#2710StreamMuxerEvent::AddressChange
variant #2723StreamMuxer
interface topoll_{inbound,outbound,address_change,close}
#2724Arc
#2763Unpin
requirement fromStreamMuxer::Substream
#2776Sync
requirement forStreamMuxer
onStreamMuxerBox
#2775StreamMuxer
takePin<&mut Self>
#2765StreamMuxer::poll_address_change
topoll
#2797StreamMuxerEvent
toEvent
The text was updated successfully, but these errors were encountered: