Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ x25519-dalek = "2.0.1"
x509-parser = "0.17.0"
yasna = "0.5.0"
zeroize = "1.8.1"
yamux = "0.13.5"
yamux = "0.13.7"

# Websocket related dependencies.
tokio-tungstenite = { version = "0.27.0", features = ["rustls-tls-native-roots", "url"], optional = true }
Expand Down
24 changes: 22 additions & 2 deletions src/yamux/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use std::{
task::{Context, Poll},
};

const LOG_TARGET: &str = "litep2p::yamux::control";

/// A Yamux [`Connection`] controller.
///
/// This presents an alternative API for using a yamux [`Connection`].
Expand Down Expand Up @@ -81,7 +83,25 @@ where
State::Idle(mut connection) => {
match connection.poll_next_inbound(cx) {
Poll::Ready(maybe_stream) => {
self.state = State::Idle(connection);
// Transport layers will close the connection on the first
// substream error. The `connection.poll_next_inbound` should
// not be called again after returning an error. Instead, we
// must close the connection gracefully.
match maybe_stream.as_ref() {
Some(Err(error)) => {
tracing::debug!(target: LOG_TARGET, ?error, "Inbound stream error, closing connection");

self.state = State::Closing {
reply: None,
inner: Closing::DrainingControlCommands { connection },
};
}
other => {
tracing::debug!(target: LOG_TARGET, ?other, "Inbound stream reset state to idle");
self.state = State::Idle(connection)
}
}

return Poll::Ready(maybe_stream);
}
Poll::Pending => {}
Expand Down Expand Up @@ -191,7 +211,7 @@ where
return Poll::Pending;
}
},
State::Poisoned => unreachable!(),
State::Poisoned => return Poll::Pending,
}
}
}
Expand Down
Loading