use std::{io, time::Duration};
use bytes::Bytes;
use chrono::{DateTime, Utc};
use scion_proto::{address::IsdAsn, path::Path};
use thiserror::Error;
use crate::types::ResFut;
pub trait PathManager: SyncPathManager {
fn path_wait(
&self,
src: IsdAsn,
dst: IsdAsn,
now: DateTime<Utc>,
) -> impl ResFut<'_, Path<Bytes>, PathWaitError>;
fn path_timeout(
&self,
src: IsdAsn,
dst: IsdAsn,
now: DateTime<Utc>,
timeout: Duration,
) -> impl ResFut<'_, Path<Bytes>, PathWaitTimeoutError> {
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(msg) => {
PathWaitTimeoutError::FetchFailed(msg)
}
PathWaitError::NoPathFound => PathWaitTimeoutError::NoPathFound,
}
})
}
Err(_) => Err(PathWaitTimeoutError::Timeout),
}
}
}
}
#[derive(Debug, Clone, Error)]
pub enum PathWaitError {
#[error("path fetch failed: {0}")]
FetchFailed(String),
#[error("no path found")]
NoPathFound,
}
#[derive(Debug, Clone, Error)]
pub enum PathWaitTimeoutError {
#[error("path fetch failed: {0}")]
FetchFailed(String),
#[error("no path found")]
NoPathFound,
#[error("waiting for path timed out")]
Timeout,
}
pub trait SyncPathManager {
fn register_path(&self, src: IsdAsn, dst: IsdAsn, now: DateTime<Utc>, path: Path<Bytes>);
fn try_cached_path(
&self,
src: IsdAsn,
dst: IsdAsn,
now: DateTime<Utc>,
) -> io::Result<Option<Path<Bytes>>>;
}
pub trait PathPrefetcher {
fn prefetch_path(&self, src: IsdAsn, dst: IsdAsn);
}