mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-17 12:01:23 +00:00
connection_reuse: drop dead connections. (#178)
Currently, connection substreams are added to `connection_reuse::Shared::active_connections`, but never removed. This is not least because the `StreamMuxer` trait defines its inbound and outbound substream futures to always yield a substream and contains no provision to signal that no more substreams can be created, which would allow client code (e.g. `ConnectionReuse`) to detect this and purge its caches. This PR defines the `StreamMuxer` trait to optionally yield inbound/outbound substreams and changes `libp2p-mplex` to handle stream EOFs by marking the underlying resource as closed. `ConnectionReuse` will remove stream muxers from its active connections cache if a `None` substream is returned.
This commit is contained in:
committed by
Pierre Krieger
parent
11f655dd6a
commit
4382adcbde
@ -172,7 +172,7 @@ pub struct InboundFuture<T, Buf: Array> {
|
||||
}
|
||||
|
||||
impl<T: AsyncRead, Buf: Array<Item = u8>> Future for InboundFuture<T, Buf> {
|
||||
type Item = Substream<T, Buf>;
|
||||
type Item = Option<Substream<T, Buf>>;
|
||||
type Error = io::Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
@ -181,6 +181,10 @@ impl<T: AsyncRead, Buf: Array<Item = u8>> Future for InboundFuture<T, Buf> {
|
||||
Async::NotReady => return Ok(Async::NotReady),
|
||||
};
|
||||
|
||||
if lock.is_closed() {
|
||||
return Ok(Async::Ready(None));
|
||||
}
|
||||
|
||||
// Attempt to make progress, but don't block if we can't
|
||||
match read_stream(&mut lock, None) {
|
||||
Ok(_) => {}
|
||||
@ -200,12 +204,12 @@ impl<T: AsyncRead, Buf: Array<Item = u8>> Future for InboundFuture<T, Buf> {
|
||||
|
||||
lock.open_stream(id);
|
||||
|
||||
Ok(Async::Ready(Substream::new(
|
||||
Ok(Async::Ready(Some(Substream::new(
|
||||
id,
|
||||
self.end,
|
||||
name,
|
||||
Arc::clone(&self.state),
|
||||
)))
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,7 +234,7 @@ fn nonce_to_id(id: usize, end: Endpoint) -> u32 {
|
||||
}
|
||||
|
||||
impl<T: AsyncWrite, Buf: Array> Future for OutboundFuture<T, Buf> {
|
||||
type Item = Substream<T, Buf>;
|
||||
type Item = Option<Substream<T, Buf>>;
|
||||
type Error = io::Error;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
|
||||
@ -239,6 +243,10 @@ impl<T: AsyncWrite, Buf: Array> Future for OutboundFuture<T, Buf> {
|
||||
Async::NotReady => return Ok(Async::NotReady),
|
||||
};
|
||||
|
||||
if lock.is_closed() {
|
||||
return Ok(Async::Ready(None));
|
||||
}
|
||||
|
||||
loop {
|
||||
let (mut id_str, id) = self.current_id.take().unwrap_or_else(|| {
|
||||
let next = nonce_to_id(
|
||||
@ -260,12 +268,12 @@ impl<T: AsyncWrite, Buf: Array> Future for OutboundFuture<T, Buf> {
|
||||
debug_assert!(id_str.position() <= id_str.get_ref().len() as u64);
|
||||
if id_str.position() == id_str.get_ref().len() as u64 {
|
||||
if lock.open_stream(id) {
|
||||
return Ok(Async::Ready(Substream::new(
|
||||
return Ok(Async::Ready(Some(Substream::new(
|
||||
id,
|
||||
self.meta.end,
|
||||
Bytes::from(&id_str.get_ref()[..]),
|
||||
Arc::clone(&self.state),
|
||||
)));
|
||||
))));
|
||||
}
|
||||
} else {
|
||||
self.current_id = Some((id_str, id));
|
||||
@ -393,7 +401,12 @@ mod tests {
|
||||
|
||||
let mplex = Multiplex::dial(stream);
|
||||
|
||||
let mut substream = mplex.clone().outbound().wait().unwrap();
|
||||
let mut substream = mplex
|
||||
.clone()
|
||||
.outbound()
|
||||
.wait()
|
||||
.unwrap()
|
||||
.expect("outbound substream");
|
||||
|
||||
assert!(tokio::write_all(&mut substream, message).wait().is_ok());
|
||||
|
||||
@ -410,7 +423,7 @@ mod tests {
|
||||
|
||||
let mplex = Multiplex::listen(stream);
|
||||
|
||||
let mut substream = mplex.inbound().wait().unwrap();
|
||||
let mut substream = mplex.inbound().wait().unwrap().expect("inbound substream");
|
||||
|
||||
assert_eq!(id, substream.id());
|
||||
assert_eq!(
|
||||
@ -435,7 +448,14 @@ mod tests {
|
||||
let mut outbound: Vec<Substream<_>> = vec![];
|
||||
|
||||
for _ in 0..5 {
|
||||
outbound.push(mplex.clone().outbound().wait().unwrap());
|
||||
outbound.push(
|
||||
mplex
|
||||
.clone()
|
||||
.outbound()
|
||||
.wait()
|
||||
.unwrap()
|
||||
.expect("outbound substream"),
|
||||
);
|
||||
}
|
||||
|
||||
outbound.sort_by_key(|a| a.id());
|
||||
@ -455,7 +475,14 @@ mod tests {
|
||||
let mut inbound: Vec<Substream<_>> = vec![];
|
||||
|
||||
for _ in 0..5 {
|
||||
inbound.push(mplex.clone().inbound().wait().unwrap());
|
||||
inbound.push(
|
||||
mplex
|
||||
.clone()
|
||||
.inbound()
|
||||
.wait()
|
||||
.unwrap()
|
||||
.expect("inbound substream"),
|
||||
);
|
||||
}
|
||||
|
||||
inbound.sort_by_key(|a| a.id());
|
||||
@ -515,7 +542,7 @@ mod tests {
|
||||
|
||||
let mplex = Multiplex::listen(io::Cursor::new(input));
|
||||
|
||||
let mut substream = mplex.inbound().wait().unwrap();
|
||||
let mut substream = mplex.inbound().wait().unwrap().expect("inbound substream");
|
||||
|
||||
assert_eq!(substream.id(), 0);
|
||||
assert_eq!(substream.name(), None);
|
||||
@ -567,7 +594,7 @@ mod tests {
|
||||
|
||||
let mplex = Multiplex::listen(io::Cursor::new(input));
|
||||
|
||||
let mut substream = mplex.inbound().wait().unwrap();
|
||||
let mut substream = mplex.inbound().wait().unwrap().expect("inbound substream");
|
||||
|
||||
assert_eq!(substream.id(), 0);
|
||||
assert_eq!(substream.name(), None);
|
||||
@ -615,7 +642,7 @@ mod tests {
|
||||
|
||||
let mplex = Multiplex::listen(io::Cursor::new(data));
|
||||
|
||||
let mut substream = mplex.inbound().wait().unwrap();
|
||||
let mut substream = mplex.inbound().wait().unwrap().expect("inbound substream");
|
||||
|
||||
assert_eq!(substream.id(), 1);
|
||||
|
||||
@ -650,7 +677,14 @@ mod tests {
|
||||
let mut outbound: Vec<Substream<_, Buffer>> = vec![];
|
||||
|
||||
for _ in 0..5 {
|
||||
outbound.push(mplex.clone().outbound().wait().unwrap());
|
||||
outbound.push(
|
||||
mplex
|
||||
.clone()
|
||||
.outbound()
|
||||
.wait()
|
||||
.unwrap()
|
||||
.expect("outbound substream"),
|
||||
);
|
||||
}
|
||||
|
||||
outbound.sort_by_key(|a| a.id());
|
||||
@ -670,7 +704,12 @@ mod tests {
|
||||
let mut inbound: Vec<Substream<_, Buffer>> = vec![];
|
||||
|
||||
for _ in 0..5 {
|
||||
let inb: Substream<_, Buffer> = mplex.clone().inbound().wait().unwrap();
|
||||
let inb: Substream<_, Buffer> = mplex
|
||||
.clone()
|
||||
.inbound()
|
||||
.wait()
|
||||
.unwrap()
|
||||
.expect("inbound substream");
|
||||
inbound.push(inb);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user