use std::time::Duration;
use crate::path::metadata::{link::LinkMeta, path_interface::PathInterface};
#[derive(Debug, Clone, PartialEq)]
pub struct PathMetadata {
pub expiration: u64,
pub mtu: u16,
pub interfaces: Option<Vec<InterfaceMetadata>>,
pub epic_auth: Option<epic::EpicAuths>,
pub notes: Option<Vec<String>>,
}
impl PathMetadata {
#[inline]
pub fn new_minimal(expiration: u64, mtu: u16, interfaces: Vec<PathInterface>) -> Self {
Self {
expiration,
mtu,
interfaces: Some(
interfaces
.into_iter()
.map(InterfaceMetadata::new_without_metadata)
.collect(),
),
epic_auth: None,
notes: None,
}
}
#[inline]
pub fn reverse(&mut self) {
if let Some(interfaces) = &mut self.interfaces {
interfaces.reverse();
}
self.epic_auth = None;
if let Some(notes) = &mut self.notes {
notes.reverse();
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct InterfaceMetadata {
pub interface: PathInterface,
pub geo_info: Option<geo::GeoCoordinates>,
pub latency: Option<Duration>,
pub bandwidth: Option<u64>,
pub link: Option<LinkMeta>,
}
impl InterfaceMetadata {
#[inline]
pub const fn new_without_metadata(interface: PathInterface) -> Self {
Self {
interface,
geo_info: None,
latency: None,
bandwidth: None,
link: None,
}
}
}
pub mod epic {
use crate::core::macros::impl_from;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct EpicAuths {
pub phop_authenticator: Vec<u8>,
pub lhop_authenticator: Vec<u8>,
}
impl EpicAuths {
#[inline]
pub const fn new(p_hop_validation_key: Vec<u8>, last_hop_validation_key: Vec<u8>) -> Self {
Self {
phop_authenticator: p_hop_validation_key,
lhop_authenticator: last_hop_validation_key,
}
}
#[inline]
pub fn from_rpc(value: scion_protobuf::daemon::v1::EpicAuths) -> Self {
Self {
phop_authenticator: value.auth_phvf,
lhop_authenticator: value.auth_lhvf,
}
}
#[inline]
pub fn to_rpc(&self) -> scion_protobuf::daemon::v1::EpicAuths {
scion_protobuf::daemon::v1::EpicAuths {
auth_phvf: self.phop_authenticator.clone(),
auth_lhvf: self.lhop_authenticator.clone(),
}
}
}
impl_from!(scion_protobuf::daemon::v1::EpicAuths, EpicAuths, |v| {
EpicAuths::from_rpc(v)
});
impl_from!(EpicAuths, scion_protobuf::daemon::v1::EpicAuths, |v| {
v.to_rpc()
});
}
pub mod geo {
use crate::core::macros::impl_from;
#[derive(Debug, Clone, PartialEq)]
pub struct GeoCoordinates {
pub latitude: f32,
pub longitude: f32,
pub address: Option<String>,
}
impl GeoCoordinates {
#[inline]
pub const fn new(latitude: f32, longitude: f32, address: Option<String>) -> Self {
Self {
latitude,
longitude,
address,
}
}
#[inline]
pub fn try_from_rpc(value: scion_protobuf::daemon::v1::GeoCoordinates) -> Option<Self> {
if value.latitude == 0.0 && value.longitude == 0.0 && value.address.is_empty() {
return None;
}
let address = match value.address.is_empty() {
false => Some(value.address),
true => None,
};
Some(Self {
latitude: value.latitude,
longitude: value.longitude,
address,
})
}
#[inline]
pub fn to_rpc(&self) -> scion_protobuf::daemon::v1::GeoCoordinates {
scion_protobuf::daemon::v1::GeoCoordinates {
latitude: self.latitude,
longitude: self.longitude,
address: self.address.clone().unwrap_or_default(),
}
}
}
impl_from!(
GeoCoordinates,
scion_protobuf::daemon::v1::GeoCoordinates,
|v| v.to_rpc()
);
}
pub mod path_interface {
use std::fmt::Display;
use crate::{core::macros::impl_from, identifier::isd_asn::IsdAsn, rpc::FromRpcError};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PathInterface {
pub isd_asn: IsdAsn,
pub id: u16,
}
impl PathInterface {
#[inline]
pub const fn new(isd_asn: IsdAsn, interface_id: u16) -> Self {
Self {
isd_asn,
id: interface_id,
}
}
#[inline]
pub fn try_from_rpc(
value: scion_protobuf::daemon::v1::PathInterface,
) -> Result<Self, FromRpcError> {
Ok(Self {
isd_asn: value.isd_as.into(),
id: value
.id
.try_into()
.map_err(|_| "interface_id exceeds u16 range")?,
})
}
#[inline]
pub fn to_rpc(&self) -> scion_protobuf::daemon::v1::PathInterface {
scion_protobuf::daemon::v1::PathInterface {
isd_as: self.isd_asn.into(),
id: self.id as u64,
}
}
}
impl Display for PathInterface {
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}#{}", self.isd_asn, self.id)
}
}
impl_from!(
PathInterface,
scion_protobuf::daemon::v1::PathInterface,
|v| v.to_rpc()
);
impl TryFrom<scion_protobuf::daemon::v1::PathInterface> for PathInterface {
type Error = FromRpcError;
#[inline]
fn try_from(value: scion_protobuf::daemon::v1::PathInterface) -> Result<Self, Self::Error> {
Self::try_from_rpc(value)
}
}
}
pub mod link {
use crate::core::macros::impl_from;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LinkMeta {
Ingress {
internal_hop_count: u32,
},
Egress(LinkType),
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[repr(i32)]
pub enum LinkType {
#[default]
Unset = 0,
Direct = 1,
MultiHop = 2,
OpenNet = 3,
Unknown(u8),
}
impl LinkType {
#[inline]
pub const fn from_i32(value: i32) -> Self {
match value {
0 => Self::Unset,
1 => Self::Direct,
2 => Self::MultiHop,
3 => Self::OpenNet,
_ => Self::Unknown(value as u8),
}
}
#[inline]
pub const fn to_i32(&self) -> i32 {
match self {
Self::Unset => 0,
Self::Direct => 1,
Self::MultiHop => 2,
Self::OpenNet => 3,
Self::Unknown(v) => *v as i32,
}
}
}
impl_from!(i32, LinkType, |v| LinkType::from_i32(v));
impl_from!(LinkType, i32, |v| v.to_i32());
}