scion-stack 0.6.1

SCION endhost network stack
Documentation
// Copyright 2025 Anapaya Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{
    future::Future,
    io,
    sync::Arc,
    time::{Duration, SystemTime},
};

use sciparse::{identifier::isd_asn::IsdAsn, path::ScionPath};
use thiserror::Error;

use crate::path::fetcher::traits::PathFetchError;

/// Trait for active path management with async interface.
pub trait PathManager: SyncPathManager {
    /// Returns a path to the destination from the path cache or requests a new path from the
    /// SCION Control Plane.
    fn path_wait(
        &self,
        src: IsdAsn,
        dst: IsdAsn,
        now: SystemTime,
    ) -> impl Future<Output = Result<ScionPath, PathWaitError>> + Send + '_;

    /// Returns a path to the destination from the path cache or requests a new path from the
    /// SCION Control Plane, with a maximum wait time.
    fn path_timeout(
        &self,
        src: IsdAsn,
        dst: IsdAsn,
        now: SystemTime,
        timeout: Duration,
    ) -> impl Future<Output = Result<ScionPath, PathWaitTimeoutError>> + Send + '_ {
        let fut = self.path_wait(src, dst, now);
        async move {
            match tokio::time::timeout(timeout, fut).await {
                Ok(result) => {
                    result.map_err(|e| {
                        match e {
                            PathWaitError::FetchFailed(source) => {
                                PathWaitTimeoutError::FetchFailed(source)
                            }
                            PathWaitError::NoPathFound => PathWaitTimeoutError::NoPathFound,
                        }
                    })
                }
                Err(_) => Err(PathWaitTimeoutError::Timeout),
            }
        }
    }
}

/// Errors returned when waiting for a path to a destination.
#[derive(Debug, Clone, Error)]
#[non_exhaustive]
pub enum PathWaitError {
    /// Fetching a path from the configured segment sources failed.
    ///
    /// The error is shared (`Arc`) because a single fetch failure may be reported to multiple
    /// concurrent waiters.
    #[error("path fetch failed: {0}")]
    FetchFailed(#[source] Arc<PathFetchError>),
    /// No path to the destination was found.
    #[error("no path found")]
    NoPathFound,
}

/// Errors returned when waiting for a path to a destination with a timeout.
#[derive(Debug, Clone, Error)]
#[non_exhaustive]
pub enum PathWaitTimeoutError {
    /// Fetching a path from the configured segment sources failed.
    ///
    /// The error is shared (`Arc`) because a single fetch failure may be reported to multiple
    /// concurrent waiters.
    #[error("path fetch failed: {0}")]
    FetchFailed(#[source] Arc<PathFetchError>),
    /// No path to the destination was found.
    #[error("no path found")]
    NoPathFound,
    /// Waiting for a path timed out.
    #[error("waiting for path timed out")]
    Timeout,
}

/// Trait for active path management with sync interface. Implementors of this trait should be
/// able to be used in sync and async context. The functions must not block.
pub trait SyncPathManager {
    /// Add a path to the path cache. This can be used to register reverse paths.
    fn register_path(&self, src: IsdAsn, dst: IsdAsn, now: SystemTime, path: ScionPath);

    /// Returns a path to the destination from the path cache.
    /// If the path is not in the cache, it returns Ok(None), possibly causing the path to be
    /// fetched in the background. If the cache is locked an io error `WouldBlock` is
    /// returned.
    fn try_cached_path(
        &self,
        src: IsdAsn,
        dst: IsdAsn,
        now: SystemTime,
    ) -> io::Result<Option<ScionPath>>;
}

/// Trait for prefetching paths in the path manager.
pub trait PathPrefetcher {
    /// Prefetch a path for the given source and destination.
    fn prefetch_path(&self, src: IsdAsn, dst: IsdAsn);
}