Skip to content

Commit

Permalink
do not enable app to abandon last active path
Browse files Browse the repository at this point in the history
  • Loading branch information
qdeconinck committed Nov 7, 2024
1 parent 2deb762 commit 7f42ecd
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 1 deletion.
7 changes: 7 additions & 0 deletions quiche/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -594,6 +594,9 @@ pub enum Error {

/// No spare Path Identifier to perform the operation in multipath.
OutOfPathId,

/// There is no more path available on the connection.
NoMorePath,
}

/// QUIC error codes sent on the wire.
Expand Down Expand Up @@ -708,6 +711,7 @@ impl Error {
Error::UnavailablePath => -21,
Error::PathIdViolation => -22,
Error::OutOfPathId => -23,
Error::NoMorePath => -24,
}
}
}
Expand Down Expand Up @@ -6572,8 +6576,11 @@ impl Connection {
/// If the path specified by the 4-tuple does not exist, returns an
/// [`Done`].
///
/// If the path to abandon is the only active one, returns a [`NoMorePath`].
///
/// [`InvalidState`]: enum.Error.html#InvalidState
/// [`Done`]: enum.Error.html#Done
/// [`NoMorePath`]: enum.Error.html#NoMorePath
pub fn abandon_path(
&mut self, local: SocketAddr, peer: SocketAddr, err_code: u64,
) -> Result<()> {
Expand Down
18 changes: 17 additions & 1 deletion quiche/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1120,23 +1120,39 @@ impl PathMap {
self.multipath = v;
}

/// Returns the number of active paths.
fn count_active_paths(&self) -> usize {
self.paths.iter().filter(|p| p.1.active()).count()
}

/// Changes the state of the path with the identifier `path_id` according to
/// the provided `PathRequest`.
///
/// This API is only usable when multipath extensions are enabled.
/// Otherwise, it raises an [`InvalidState`].
///
/// In case the request closes the last active path, returns a
/// [`NoMorePath`].
///
/// In case the request is invalid, returns an [`InvalidState`].
///
/// [`InvalidState`]: enum.Error.html#variant.InvalidState
/// [`NoMorePath`]: enum.Error.html#variant.NoMorePath
pub fn request(
&mut self, path_id: usize, request: PathRequest,
) -> Result<()> {
if !self.multipath {
return Err(Error::InvalidState);
}
let path = self.get_mut(path_id)?;
let requested_state = request.requested_state();
if let PathState::Closing(_) = requested_state {
if self.count_active_paths() == 1 &&
path_id == self.get_active_path_id()?
{
return Err(Error::NoMorePath);
}
}
let path = self.get_mut(path_id)?;
path.set_state(requested_state)?;
if path.is_closing() {
self.mark_path_abandon(path_id, true);
Expand Down

0 comments on commit 7f42ecd

Please sign in to comment.