Skip to main content

scion_stack/path/manager/
traits.rs

1// Copyright 2025 Anapaya Systems
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//   http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::{io, time::Duration};
16
17use bytes::Bytes;
18use chrono::{DateTime, Utc};
19use scion_proto::{address::IsdAsn, path::Path};
20use thiserror::Error;
21use tracing::error;
22
23use crate::types::ResFut;
24
25/// Trait for active path management with async interface.
26pub trait PathManager: SyncPathManager {
27    /// Returns a path to the destination from the path cache or requests a new path from the
28    /// SCION Control Plane.
29    fn path_wait(
30        &self,
31        src: IsdAsn,
32        dst: IsdAsn,
33        now: DateTime<Utc>,
34    ) -> impl ResFut<'_, Path<Bytes>, PathWaitError>;
35
36    /// Returns a path to the destination from the path cache or requests a new path from the
37    /// SCION Control Plane, with a maximum wait time.
38    fn path_timeout(
39        &self,
40        src: IsdAsn,
41        dst: IsdAsn,
42        now: DateTime<Utc>,
43        timeout: Duration,
44    ) -> impl ResFut<'_, Path<Bytes>, PathWaitTimeoutError> {
45        let fut = self.path_wait(src, dst, now);
46        async move {
47            match tokio::time::timeout(timeout, fut).await {
48                Ok(result) => {
49                    result.map_err(|e| {
50                        match e {
51                            PathWaitError::FetchFailed(msg) => {
52                                PathWaitTimeoutError::FetchFailed(msg)
53                            }
54                            PathWaitError::NoPathFound => PathWaitTimeoutError::NoPathFound,
55                        }
56                    })
57                }
58                Err(_) => Err(PathWaitTimeoutError::Timeout),
59            }
60        }
61    }
62}
63
64/// Path wait errors.
65#[derive(Debug, Clone, Error)]
66pub enum PathWaitError {
67    /// Path fetch failed.
68    #[error("path fetch failed: {0}")]
69    FetchFailed(String),
70    /// No path found.
71    #[error("no path found")]
72    NoPathFound,
73}
74
75/// Path wait errors.
76#[derive(Debug, Clone, Error)]
77pub enum PathWaitTimeoutError {
78    /// Path fetch failed.
79    #[error("path fetch failed: {0}")]
80    FetchFailed(String),
81    /// No path found.
82    #[error("no path found")]
83    NoPathFound,
84    /// Waiting for path timed out
85    #[error("waiting for path timed out")]
86    Timeout,
87}
88
89/// Trait for active path management with sync interface. Implementors of this trait should be
90/// able to be used in sync and async context. The functions must not block.
91pub trait SyncPathManager {
92    /// Add a path to the path cache. This can be used to register reverse paths.
93    fn register_path(&self, src: IsdAsn, dst: IsdAsn, now: DateTime<Utc>, path: Path<Bytes>);
94
95    /// Returns a path to the destination from the path cache.
96    /// If the path is not in the cache, it returns Ok(None), possibly causing the path to be
97    /// fetched in the background. If the cache is locked an io error WouldBlock is
98    /// returned.
99    fn try_cached_path(
100        &self,
101        src: IsdAsn,
102        dst: IsdAsn,
103        now: DateTime<Utc>,
104    ) -> io::Result<Option<Path<Bytes>>>;
105}
106
107/// Trait for prefetching paths in the path manager.
108pub trait PathPrefetcher {
109    /// Prefetch a paths for the given source and destination.
110    fn prefetch_path(&self, src: IsdAsn, dst: IsdAsn);
111}