2021-12-24 23:02:53 +00:00
|
|
|
#![allow(dead_code)]
|
|
|
|
|
2021-12-14 14:48:33 +00:00
|
|
|
mod debug;
|
2022-06-08 01:31:05 +00:00
|
|
|
mod serialize_helpers;
|
2021-12-14 14:48:33 +00:00
|
|
|
pub use debug::*;
|
2022-06-08 01:31:05 +00:00
|
|
|
pub use serialize_helpers::*;
|
2021-12-14 14:48:33 +00:00
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
use crate::*;
|
|
|
|
|
|
|
|
pub use crate::xx::{
|
|
|
|
IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, SystemPinBoxFuture,
|
|
|
|
ToSocketAddrs,
|
|
|
|
};
|
|
|
|
pub use alloc::string::ToString;
|
2022-02-07 02:18:42 +00:00
|
|
|
pub use attachment_manager::AttachmentManager;
|
2021-11-22 16:28:30 +00:00
|
|
|
pub use core::str::FromStr;
|
2022-05-31 23:54:52 +00:00
|
|
|
pub use dht::Crypto;
|
|
|
|
pub use dht::{generate_secret, sign, verify, DHTKey, DHTKeySecret, DHTSignature};
|
2022-02-07 02:18:42 +00:00
|
|
|
pub use intf::BlockStore;
|
|
|
|
pub use intf::ProtectedStore;
|
|
|
|
pub use intf::TableStore;
|
|
|
|
pub use network_manager::NetworkManager;
|
|
|
|
pub use routing_table::RoutingTable;
|
2022-05-11 01:49:42 +00:00
|
|
|
pub use rpc_processor::StatusAnswer;
|
2022-02-07 02:18:42 +00:00
|
|
|
|
2022-06-08 01:31:05 +00:00
|
|
|
use api_tracing_layer::*;
|
2022-02-07 02:18:42 +00:00
|
|
|
use core::fmt;
|
|
|
|
use core_context::{api_shutdown, VeilidCoreContext};
|
2022-04-21 00:49:16 +00:00
|
|
|
use enumset::*;
|
2022-02-07 02:18:42 +00:00
|
|
|
use rpc_processor::{RPCError, RPCProcessor};
|
|
|
|
use serde::*;
|
|
|
|
use xx::*;
|
2021-11-22 16:28:30 +00:00
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
|
|
|
#[serde(tag = "kind")]
|
2021-12-21 00:12:30 +00:00
|
|
|
pub enum VeilidAPIError {
|
2022-02-07 02:18:42 +00:00
|
|
|
NotInitialized,
|
|
|
|
AlreadyInitialized,
|
2021-12-21 00:12:30 +00:00
|
|
|
Timeout,
|
|
|
|
Shutdown,
|
2022-02-09 14:47:36 +00:00
|
|
|
NodeNotFound {
|
|
|
|
node_id: NodeId,
|
|
|
|
},
|
|
|
|
NoDialInfo {
|
|
|
|
node_id: NodeId,
|
|
|
|
},
|
2022-05-11 01:49:42 +00:00
|
|
|
NoPeerInfo {
|
|
|
|
node_id: NodeId,
|
|
|
|
},
|
2022-02-09 14:47:36 +00:00
|
|
|
Internal {
|
|
|
|
message: String,
|
|
|
|
},
|
|
|
|
Unimplemented {
|
|
|
|
message: String,
|
|
|
|
},
|
2021-12-21 00:12:30 +00:00
|
|
|
ParseError {
|
|
|
|
message: String,
|
|
|
|
value: String,
|
|
|
|
},
|
|
|
|
InvalidArgument {
|
|
|
|
context: String,
|
|
|
|
argument: String,
|
|
|
|
value: String,
|
|
|
|
},
|
|
|
|
MissingArgument {
|
|
|
|
context: String,
|
|
|
|
argument: String,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for VeilidAPIError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
match self {
|
2022-02-07 02:18:42 +00:00
|
|
|
VeilidAPIError::NotInitialized => write!(f, "VeilidAPIError::NotInitialized"),
|
|
|
|
VeilidAPIError::AlreadyInitialized => write!(f, "VeilidAPIError::AlreadyInitialized"),
|
2021-12-21 00:12:30 +00:00
|
|
|
VeilidAPIError::Timeout => write!(f, "VeilidAPIError::Timeout"),
|
|
|
|
VeilidAPIError::Shutdown => write!(f, "VeilidAPIError::Shutdown"),
|
2022-02-09 14:47:36 +00:00
|
|
|
VeilidAPIError::NodeNotFound { node_id } => {
|
|
|
|
write!(f, "VeilidAPIError::NodeNotFound({})", node_id)
|
|
|
|
}
|
|
|
|
VeilidAPIError::NoDialInfo { node_id } => {
|
|
|
|
write!(f, "VeilidAPIError::NoDialInfo({})", node_id)
|
|
|
|
}
|
2022-05-11 01:49:42 +00:00
|
|
|
VeilidAPIError::NoPeerInfo { node_id } => {
|
|
|
|
write!(f, "VeilidAPIError::NoPeerInfo({})", node_id)
|
|
|
|
}
|
2022-02-09 14:47:36 +00:00
|
|
|
VeilidAPIError::Internal { message } => {
|
|
|
|
write!(f, "VeilidAPIError::Internal({})", message)
|
|
|
|
}
|
|
|
|
VeilidAPIError::Unimplemented { message } => {
|
|
|
|
write!(f, "VeilidAPIError::Unimplemented({})", message)
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
VeilidAPIError::ParseError { message, value } => {
|
|
|
|
write!(f, "VeilidAPIError::ParseError({}: {})", message, value)
|
|
|
|
}
|
|
|
|
VeilidAPIError::InvalidArgument {
|
|
|
|
context,
|
|
|
|
argument,
|
|
|
|
value,
|
|
|
|
} => {
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"VeilidAPIError::InvalidArgument({}: {} = {})",
|
|
|
|
context, argument, value
|
|
|
|
)
|
|
|
|
}
|
|
|
|
VeilidAPIError::MissingArgument { context, argument } => {
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"VeilidAPIError::MissingArgument({}: {})",
|
|
|
|
context, argument
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn convert_rpc_error(x: RPCError) -> VeilidAPIError {
|
|
|
|
match x {
|
|
|
|
RPCError::Timeout => VeilidAPIError::Timeout,
|
2022-04-16 15:18:54 +00:00
|
|
|
RPCError::Unreachable(n) => VeilidAPIError::NodeNotFound {
|
|
|
|
node_id: NodeId::new(n),
|
|
|
|
},
|
2022-02-09 14:47:36 +00:00
|
|
|
RPCError::Unimplemented(s) => VeilidAPIError::Unimplemented { message: s },
|
|
|
|
RPCError::Internal(s) => VeilidAPIError::Internal { message: s },
|
|
|
|
RPCError::Protocol(s) => VeilidAPIError::Internal { message: s },
|
2022-05-18 14:17:04 +00:00
|
|
|
RPCError::InvalidFormat(s) => VeilidAPIError::Internal {
|
|
|
|
message: format!("Invalid RPC format: {}", s),
|
2022-02-09 14:47:36 +00:00
|
|
|
},
|
2021-12-21 00:12:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! map_rpc_error {
|
|
|
|
() => {
|
|
|
|
|x| convert_rpc_error(x)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! parse_error {
|
|
|
|
($msg:expr, $val:expr) => {
|
|
|
|
VeilidAPIError::ParseError {
|
|
|
|
message: $msg.to_string(),
|
|
|
|
value: $val.to_string(),
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-06-08 01:31:05 +00:00
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Copy, Serialize, Deserialize)]
|
2022-01-31 15:11:18 +00:00
|
|
|
pub enum VeilidLogLevel {
|
|
|
|
Error = 1,
|
|
|
|
Warn,
|
|
|
|
Info,
|
|
|
|
Debug,
|
|
|
|
Trace,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl VeilidLogLevel {
|
2022-06-08 01:31:05 +00:00
|
|
|
pub fn from_tracing_level(level: tracing::Level) -> VeilidLogLevel {
|
|
|
|
match level {
|
|
|
|
tracing::Level::ERROR => VeilidLogLevel::Error,
|
|
|
|
tracing::Level::WARN => VeilidLogLevel::Warn,
|
|
|
|
tracing::Level::INFO => VeilidLogLevel::Info,
|
|
|
|
tracing::Level::DEBUG => VeilidLogLevel::Debug,
|
|
|
|
tracing::Level::TRACE => VeilidLogLevel::Trace,
|
|
|
|
}
|
|
|
|
}
|
2022-01-31 15:11:18 +00:00
|
|
|
pub fn from_log_level(level: log::Level) -> VeilidLogLevel {
|
|
|
|
match level {
|
2022-06-08 01:31:05 +00:00
|
|
|
log::Level::Error => VeilidLogLevel::Error,
|
|
|
|
log::Level::Warn => VeilidLogLevel::Warn,
|
|
|
|
log::Level::Info => VeilidLogLevel::Info,
|
|
|
|
log::Level::Debug => VeilidLogLevel::Debug,
|
|
|
|
log::Level::Trace => VeilidLogLevel::Trace,
|
2022-01-31 15:11:18 +00:00
|
|
|
}
|
|
|
|
}
|
2022-06-08 15:45:30 +00:00
|
|
|
pub fn to_tracing_level(&self) -> tracing::Level {
|
|
|
|
match self {
|
|
|
|
Self::Error => tracing::Level::ERROR,
|
|
|
|
Self::Warn => tracing::Level::WARN,
|
|
|
|
Self::Info => tracing::Level::INFO,
|
|
|
|
Self::Debug => tracing::Level::DEBUG,
|
|
|
|
Self::Trace => tracing::Level::TRACE,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn to_log_level(&self) -> log::Level {
|
|
|
|
match self {
|
|
|
|
Self::Error => log::Level::Error,
|
|
|
|
Self::Warn => log::Level::Warn,
|
|
|
|
Self::Info => log::Level::Info,
|
|
|
|
Self::Debug => log::Level::Debug,
|
|
|
|
Self::Trace => log::Level::Trace,
|
|
|
|
}
|
|
|
|
}
|
2022-01-31 15:11:18 +00:00
|
|
|
}
|
|
|
|
|
2022-06-08 13:33:41 +00:00
|
|
|
impl fmt::Display for VeilidLogLevel {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
let text = match self {
|
|
|
|
Self::Error => "ERROR",
|
|
|
|
Self::Warn => "WARN",
|
|
|
|
Self::Info => "INFO",
|
|
|
|
Self::Debug => "DEBUG",
|
|
|
|
Self::Trace => "TRACE",
|
|
|
|
};
|
|
|
|
write!(f, "{}", text)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-16 15:52:48 +00:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
pub struct VeilidStateLog {
|
|
|
|
pub log_level: VeilidLogLevel,
|
|
|
|
pub message: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
pub struct VeilidStateAttachment {
|
|
|
|
pub state: AttachmentState,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
pub struct VeilidStateNetwork {
|
|
|
|
pub started: bool,
|
|
|
|
pub bps_down: u64,
|
|
|
|
pub bps_up: u64,
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
|
|
#[serde(tag = "kind")]
|
2022-01-18 17:33:14 +00:00
|
|
|
pub enum VeilidUpdate {
|
2022-05-16 15:52:48 +00:00
|
|
|
Log(VeilidStateLog),
|
|
|
|
Attachment(VeilidStateAttachment),
|
|
|
|
Network(VeilidStateNetwork),
|
2022-02-15 18:40:17 +00:00
|
|
|
Shutdown,
|
2022-01-18 17:33:14 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
2022-01-18 17:33:14 +00:00
|
|
|
pub struct VeilidState {
|
2022-05-16 15:52:48 +00:00
|
|
|
pub attachment: VeilidStateAttachment,
|
|
|
|
pub network: VeilidStateNetwork,
|
2022-01-18 17:33:14 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
///
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct NodeId {
|
|
|
|
pub key: DHTKey,
|
|
|
|
}
|
|
|
|
impl NodeId {
|
|
|
|
pub fn new(key: DHTKey) -> Self {
|
2021-12-21 00:12:30 +00:00
|
|
|
assert!(key.valid);
|
2021-11-27 17:44:21 +00:00
|
|
|
Self { key }
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
impl fmt::Display for NodeId {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
write!(f, "{}", self.key.encode())
|
|
|
|
}
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct ValueKey {
|
|
|
|
pub key: DHTKey,
|
|
|
|
pub subkey: Option<String>,
|
|
|
|
}
|
|
|
|
impl ValueKey {
|
|
|
|
pub fn new(key: DHTKey) -> Self {
|
2021-11-27 17:44:21 +00:00
|
|
|
Self { key, subkey: None }
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
pub fn new_subkey(key: DHTKey, subkey: String) -> Self {
|
|
|
|
Self {
|
2021-11-27 17:44:21 +00:00
|
|
|
key,
|
2021-11-28 00:56:56 +00:00
|
|
|
subkey: if subkey.is_empty() {
|
2021-11-22 16:28:30 +00:00
|
|
|
None
|
|
|
|
} else {
|
|
|
|
Some(subkey)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct BlockId {
|
|
|
|
pub key: DHTKey,
|
|
|
|
}
|
|
|
|
impl BlockId {
|
|
|
|
pub fn new(key: DHTKey) -> Self {
|
2021-11-27 17:44:21 +00:00
|
|
|
Self { key }
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Default, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct SenderInfo {
|
2021-12-22 03:20:55 +00:00
|
|
|
pub socket_address: Option<SocketAddress>,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-04-25 00:16:13 +00:00
|
|
|
// Keep member order appropriate for sorting < preference
|
2022-04-03 16:58:06 +00:00
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
2022-04-24 02:08:02 +00:00
|
|
|
pub enum DialInfoClass {
|
|
|
|
Direct = 0, // D = Directly reachable with public IP and no firewall, with statically configured port
|
|
|
|
Mapped = 1, // M = Directly reachable with via portmap behind any NAT or firewalled with dynamically negotiated port
|
|
|
|
FullConeNAT = 2, // F = Directly reachable device without portmap behind full-cone NAT
|
|
|
|
Blocked = 3, // B = Inbound blocked at firewall but may hole punch with public address
|
|
|
|
AddressRestrictedNAT = 4, // A = Device without portmap behind address-only restricted NAT
|
|
|
|
PortRestrictedNAT = 5, // P = Device without portmap behind address-and-port restricted NAT
|
2022-04-03 16:58:06 +00:00
|
|
|
}
|
|
|
|
|
2022-04-24 02:08:02 +00:00
|
|
|
impl DialInfoClass {
|
2022-04-07 13:55:09 +00:00
|
|
|
// Is a signal required to do an inbound hole-punch?
|
2022-04-24 02:08:02 +00:00
|
|
|
pub fn requires_signal(&self) -> bool {
|
2022-04-07 13:55:09 +00:00
|
|
|
matches!(
|
|
|
|
self,
|
2022-04-24 02:08:02 +00:00
|
|
|
Self::Blocked | Self::AddressRestrictedNAT | Self::PortRestrictedNAT
|
2022-04-07 13:55:09 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-04-24 02:08:02 +00:00
|
|
|
// Does a relay node need to be allocated for this dial info?
|
|
|
|
// For full cone NAT, the relay itself may not be used but the keepalive sent to it
|
|
|
|
// is required to keep the NAT mapping valid in the router state table
|
|
|
|
pub fn requires_relay(&self) -> bool {
|
2022-04-03 16:58:06 +00:00
|
|
|
matches!(
|
|
|
|
self,
|
2022-04-07 13:55:09 +00:00
|
|
|
Self::FullConeNAT
|
2022-04-24 02:08:02 +00:00
|
|
|
| Self::Blocked
|
2022-04-07 13:55:09 +00:00
|
|
|
| Self::AddressRestrictedNAT
|
|
|
|
| Self::PortRestrictedNAT
|
2022-04-03 16:58:06 +00:00
|
|
|
)
|
|
|
|
}
|
2022-04-24 02:08:02 +00:00
|
|
|
}
|
2022-04-07 13:55:09 +00:00
|
|
|
|
2022-04-25 00:16:13 +00:00
|
|
|
// Keep member order appropriate for sorting < preference
|
2022-04-24 02:08:02 +00:00
|
|
|
#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
|
|
|
pub struct DialInfoDetail {
|
|
|
|
pub class: DialInfoClass,
|
2022-04-25 00:16:13 +00:00
|
|
|
pub dial_info: DialInfo,
|
2022-04-24 02:08:02 +00:00
|
|
|
}
|
2022-04-07 13:55:09 +00:00
|
|
|
|
2022-04-24 02:08:02 +00:00
|
|
|
impl MatchesDialInfoFilter for DialInfoDetail {
|
|
|
|
fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
|
|
|
|
self.dial_info.matches_filter(filter)
|
2022-04-03 16:58:06 +00:00
|
|
|
}
|
2022-04-24 02:08:02 +00:00
|
|
|
}
|
2022-04-07 13:55:09 +00:00
|
|
|
|
2022-04-24 02:08:02 +00:00
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
|
|
|
pub enum NetworkClass {
|
|
|
|
InboundCapable = 0, // I = Inbound capable without relay, may require signal
|
|
|
|
OutboundOnly = 1, // O = Outbound only, inbound relay required except with reverse connect signal
|
|
|
|
WebApp = 2, // W = PWA, outbound relay is required in most cases
|
|
|
|
Invalid = 3, // X = Invalid network class, we don't know how to reach this node
|
2022-04-03 16:58:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for NetworkClass {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::Invalid
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-24 02:08:02 +00:00
|
|
|
impl NetworkClass {
|
|
|
|
// Should an outbound relay be kept available?
|
|
|
|
pub fn outbound_wants_relay(&self) -> bool {
|
|
|
|
matches!(self, Self::WebApp)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2022-04-08 14:17:09 +00:00
|
|
|
pub struct NodeStatus {
|
2021-11-22 16:28:30 +00:00
|
|
|
pub will_route: bool,
|
|
|
|
pub will_tunnel: bool,
|
2022-04-03 16:58:06 +00:00
|
|
|
pub will_signal: bool,
|
|
|
|
pub will_relay: bool,
|
2021-11-22 16:28:30 +00:00
|
|
|
pub will_validate_dial_info: bool,
|
|
|
|
}
|
|
|
|
|
2022-05-11 01:49:42 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2022-04-08 14:17:09 +00:00
|
|
|
pub struct NodeInfo {
|
|
|
|
pub network_class: NetworkClass,
|
2022-04-16 15:18:54 +00:00
|
|
|
pub outbound_protocols: ProtocolSet,
|
2022-05-28 14:07:57 +00:00
|
|
|
pub min_version: u8,
|
|
|
|
pub max_version: u8,
|
2022-04-24 02:08:02 +00:00
|
|
|
pub dial_info_detail_list: Vec<DialInfoDetail>,
|
2022-04-16 15:18:54 +00:00
|
|
|
pub relay_peer_info: Option<Box<PeerInfo>>,
|
|
|
|
}
|
|
|
|
|
2022-04-08 14:17:09 +00:00
|
|
|
impl NodeInfo {
|
2022-05-24 21:13:52 +00:00
|
|
|
pub fn is_valid(&self) -> bool {
|
|
|
|
!matches!(self.network_class, NetworkClass::Invalid)
|
|
|
|
}
|
2022-04-24 02:08:02 +00:00
|
|
|
pub fn first_filtered_dial_info_detail<F>(&self, filter: F) -> Option<DialInfoDetail>
|
2022-04-08 14:17:09 +00:00
|
|
|
where
|
2022-04-24 02:08:02 +00:00
|
|
|
F: Fn(&DialInfoDetail) -> bool,
|
2022-04-08 14:17:09 +00:00
|
|
|
{
|
2022-04-24 02:08:02 +00:00
|
|
|
for did in &self.dial_info_detail_list {
|
2022-04-25 15:29:02 +00:00
|
|
|
if filter(did) {
|
2022-04-24 02:08:02 +00:00
|
|
|
return Some(did.clone());
|
2022-04-08 14:17:09 +00:00
|
|
|
}
|
|
|
|
}
|
2022-04-16 15:18:54 +00:00
|
|
|
None
|
2022-04-08 14:17:09 +00:00
|
|
|
}
|
2022-04-16 15:18:54 +00:00
|
|
|
|
2022-04-24 02:08:02 +00:00
|
|
|
pub fn all_filtered_dial_info_details<F>(&self, filter: F) -> Vec<DialInfoDetail>
|
2022-04-08 14:17:09 +00:00
|
|
|
where
|
2022-04-24 02:08:02 +00:00
|
|
|
F: Fn(&DialInfoDetail) -> bool,
|
2022-04-08 14:17:09 +00:00
|
|
|
{
|
2022-04-24 02:08:02 +00:00
|
|
|
let mut dial_info_detail_list = Vec::new();
|
2022-04-08 14:17:09 +00:00
|
|
|
|
2022-04-24 02:08:02 +00:00
|
|
|
for did in &self.dial_info_detail_list {
|
2022-04-25 15:29:02 +00:00
|
|
|
if filter(did) {
|
2022-04-24 02:08:02 +00:00
|
|
|
dial_info_detail_list.push(did.clone());
|
2022-04-08 14:17:09 +00:00
|
|
|
}
|
|
|
|
}
|
2022-04-24 02:08:02 +00:00
|
|
|
dial_info_detail_list
|
2022-04-16 15:18:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn has_any_dial_info(&self) -> bool {
|
2022-04-24 02:08:02 +00:00
|
|
|
!self.dial_info_detail_list.is_empty()
|
2022-04-16 15:18:54 +00:00
|
|
|
|| !self
|
|
|
|
.relay_peer_info
|
2022-04-17 17:28:39 +00:00
|
|
|
.as_ref()
|
2022-05-11 01:49:42 +00:00
|
|
|
.map(|rpi| rpi.signed_node_info.node_info.has_direct_dial_info())
|
2022-04-16 15:18:54 +00:00
|
|
|
.unwrap_or_default()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn has_direct_dial_info(&self) -> bool {
|
2022-04-24 02:08:02 +00:00
|
|
|
!self.dial_info_detail_list.is_empty()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is some relay required either for signal or inbound relay or outbound relay?
|
|
|
|
pub fn requires_relay(&self) -> bool {
|
|
|
|
match self.network_class {
|
|
|
|
NetworkClass::InboundCapable => {
|
|
|
|
for did in &self.dial_info_detail_list {
|
|
|
|
if did.class.requires_relay() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NetworkClass::OutboundOnly => {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
NetworkClass::WebApp => {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
NetworkClass::Invalid => {}
|
|
|
|
}
|
|
|
|
false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Can this node assist with signalling? Yes but only if it doesn't require signalling, itself.
|
|
|
|
pub fn can_signal(&self) -> bool {
|
|
|
|
// Must be inbound capable
|
|
|
|
if !matches!(self.network_class, NetworkClass::InboundCapable) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// Do any of our dial info require signalling? if so, we can't offer signalling
|
|
|
|
for did in &self.dial_info_detail_list {
|
|
|
|
if did.class.requires_signal() {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Can this node relay be an inbound relay?
|
|
|
|
pub fn can_inbound_relay(&self) -> bool {
|
|
|
|
// For now this is the same
|
|
|
|
self.can_signal()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Is this node capable of validating dial info
|
|
|
|
pub fn can_validate_dial_info(&self) -> bool {
|
|
|
|
// For now this is the same
|
|
|
|
self.can_signal()
|
2022-04-08 14:17:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-11 01:49:42 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2022-04-17 17:28:39 +00:00
|
|
|
pub struct LocalNodeInfo {
|
|
|
|
pub dial_info_list: Vec<DialInfo>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LocalNodeInfo {
|
|
|
|
pub fn first_filtered_dial_info<F>(&self, filter: F) -> Option<DialInfo>
|
|
|
|
where
|
|
|
|
F: Fn(&DialInfo) -> bool,
|
|
|
|
{
|
|
|
|
for di in &self.dial_info_list {
|
|
|
|
if filter(di) {
|
|
|
|
return Some(di.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn all_filtered_dial_info<F>(&self, filter: F) -> Vec<DialInfo>
|
|
|
|
where
|
|
|
|
F: Fn(&DialInfo) -> bool,
|
|
|
|
{
|
|
|
|
let mut dial_info_list = Vec::new();
|
|
|
|
|
|
|
|
for di in &self.dial_info_list {
|
|
|
|
if filter(di) {
|
|
|
|
dial_info_list.push(di.clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dial_info_list
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn has_dial_info(&self) -> bool {
|
|
|
|
!self.dial_info_list.is_empty()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-25 15:29:02 +00:00
|
|
|
#[allow(clippy::derive_hash_xor_eq)]
|
2022-04-21 00:49:16 +00:00
|
|
|
#[derive(Debug, PartialOrd, Ord, Hash, Serialize, Deserialize, EnumSetType)]
|
2022-04-25 00:16:13 +00:00
|
|
|
// Keep member order appropriate for sorting < preference
|
2021-12-22 03:20:55 +00:00
|
|
|
// Must match DialInfo order
|
2021-11-22 16:28:30 +00:00
|
|
|
pub enum ProtocolType {
|
|
|
|
UDP,
|
|
|
|
TCP,
|
|
|
|
WS,
|
|
|
|
WSS,
|
|
|
|
}
|
|
|
|
|
2022-04-17 23:10:10 +00:00
|
|
|
impl ProtocolType {
|
|
|
|
pub fn is_connection_oriented(&self) -> bool {
|
|
|
|
matches!(
|
|
|
|
self,
|
|
|
|
ProtocolType::TCP | ProtocolType::WS | ProtocolType::WSS
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-21 00:49:16 +00:00
|
|
|
pub type ProtocolSet = EnumSet<ProtocolType>;
|
2022-04-16 15:18:54 +00:00
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
|
2021-12-22 03:20:55 +00:00
|
|
|
pub enum AddressType {
|
|
|
|
IPV4,
|
|
|
|
IPV6,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub enum Address {
|
|
|
|
IPV4(Ipv4Addr),
|
|
|
|
IPV6(Ipv6Addr),
|
|
|
|
}
|
|
|
|
|
2021-12-21 00:12:30 +00:00
|
|
|
impl Default for Address {
|
|
|
|
fn default() -> Self {
|
|
|
|
Address::IPV4(Ipv4Addr::new(0, 0, 0, 0))
|
2021-12-14 14:48:33 +00:00
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Address {
|
2021-11-22 16:28:30 +00:00
|
|
|
pub fn from_socket_addr(sa: SocketAddr) -> Address {
|
|
|
|
match sa {
|
|
|
|
SocketAddr::V4(v4) => Address::IPV4(*v4.ip()),
|
|
|
|
SocketAddr::V6(v6) => Address::IPV6(*v6.ip()),
|
|
|
|
}
|
|
|
|
}
|
2021-12-22 03:20:55 +00:00
|
|
|
pub fn address_type(&self) -> AddressType {
|
|
|
|
match self {
|
2021-12-24 23:02:53 +00:00
|
|
|
Address::IPV4(_) => AddressType::IPV4,
|
|
|
|
Address::IPV6(_) => AddressType::IPV6,
|
2021-12-22 03:20:55 +00:00
|
|
|
}
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
pub fn address_string(&self) -> String {
|
|
|
|
match self {
|
|
|
|
Address::IPV4(v4) => v4.to_string(),
|
|
|
|
Address::IPV6(v6) => v6.to_string(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn address_string_with_port(&self, port: u16) -> String {
|
|
|
|
match self {
|
2022-03-13 16:45:36 +00:00
|
|
|
Address::IPV4(v4) => format!("{}:{}", v4, port),
|
|
|
|
Address::IPV6(v6) => format!("[{}]:{}", v6, port),
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-22 03:20:55 +00:00
|
|
|
pub fn is_global(&self) -> bool {
|
2021-11-22 16:28:30 +00:00
|
|
|
match self {
|
2022-04-26 13:16:48 +00:00
|
|
|
Address::IPV4(v4) => ipv4addr_is_global(v4) && !ipv4addr_is_multicast(v4),
|
|
|
|
Address::IPV6(v6) => ipv6addr_is_unicast_global(v6),
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-22 03:20:55 +00:00
|
|
|
pub fn is_local(&self) -> bool {
|
2021-11-22 16:28:30 +00:00
|
|
|
match self {
|
2022-04-26 13:16:48 +00:00
|
|
|
Address::IPV4(v4) => ipv4addr_is_private(v4) || ipv4addr_is_link_local(v4),
|
|
|
|
Address::IPV6(v6) => {
|
|
|
|
ipv6addr_is_unicast_site_local(v6)
|
|
|
|
|| ipv6addr_is_unicast_link_local(v6)
|
|
|
|
|| ipv6addr_is_unique_local(v6)
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn to_ip_addr(&self) -> IpAddr {
|
|
|
|
match self {
|
|
|
|
Self::IPV4(a) => IpAddr::V4(*a),
|
|
|
|
Self::IPV6(a) => IpAddr::V6(*a),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn to_socket_addr(&self, port: u16) -> SocketAddr {
|
|
|
|
SocketAddr::new(self.to_ip_addr(), port)
|
|
|
|
}
|
|
|
|
pub fn to_canonical(&self) -> Address {
|
|
|
|
match self {
|
|
|
|
Address::IPV4(v4) => Address::IPV4(*v4),
|
|
|
|
Address::IPV6(v6) => match v6.to_ipv4() {
|
|
|
|
Some(v4) => Address::IPV4(v4),
|
|
|
|
None => Address::IPV6(*v6),
|
|
|
|
},
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-21 00:12:30 +00:00
|
|
|
impl FromStr for Address {
|
|
|
|
type Err = VeilidAPIError;
|
|
|
|
fn from_str(host: &str) -> Result<Address, VeilidAPIError> {
|
2021-11-28 00:56:56 +00:00
|
|
|
if let Ok(addr) = Ipv4Addr::from_str(host) {
|
2021-11-22 16:28:30 +00:00
|
|
|
Ok(Address::IPV4(addr))
|
2021-11-28 00:56:56 +00:00
|
|
|
} else if let Ok(addr) = Ipv6Addr::from_str(host) {
|
2021-11-22 16:28:30 +00:00
|
|
|
Ok(Address::IPV6(addr))
|
|
|
|
} else {
|
2021-12-21 00:12:30 +00:00
|
|
|
Err(parse_error!("Address::from_str failed", host))
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(
|
|
|
|
Copy, Default, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Serialize, Deserialize,
|
|
|
|
)]
|
2021-12-21 00:12:30 +00:00
|
|
|
pub struct SocketAddress {
|
|
|
|
address: Address,
|
|
|
|
port: u16,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SocketAddress {
|
|
|
|
pub fn new(address: Address, port: u16) -> Self {
|
|
|
|
Self { address, port }
|
|
|
|
}
|
|
|
|
pub fn from_socket_addr(sa: SocketAddr) -> SocketAddress {
|
|
|
|
Self {
|
|
|
|
address: Address::from_socket_addr(sa),
|
|
|
|
port: sa.port(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn address(&self) -> Address {
|
|
|
|
self.address
|
|
|
|
}
|
2021-12-22 03:20:55 +00:00
|
|
|
pub fn address_type(&self) -> AddressType {
|
|
|
|
self.address.address_type()
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn port(&self) -> u16 {
|
|
|
|
self.port
|
|
|
|
}
|
|
|
|
pub fn to_canonical(&self) -> SocketAddress {
|
|
|
|
SocketAddress {
|
|
|
|
address: self.address.to_canonical(),
|
|
|
|
port: self.port,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn to_ip_addr(&self) -> IpAddr {
|
|
|
|
self.address.to_ip_addr()
|
|
|
|
}
|
|
|
|
pub fn to_socket_addr(&self) -> SocketAddr {
|
|
|
|
self.address.to_socket_addr(self.port)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for SocketAddress {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
2021-12-24 01:34:52 +00:00
|
|
|
write!(f, "{}", self.to_socket_addr())
|
2021-12-21 00:12:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromStr for SocketAddress {
|
|
|
|
type Err = VeilidAPIError;
|
|
|
|
fn from_str(s: &str) -> Result<SocketAddress, VeilidAPIError> {
|
2021-12-24 01:34:52 +00:00
|
|
|
let sa = SocketAddr::from_str(s)
|
|
|
|
.map_err(|e| parse_error!("Failed to parse SocketAddress", e))?;
|
|
|
|
Ok(SocketAddress::from_socket_addr(sa))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-04-21 00:49:16 +00:00
|
|
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
2021-12-24 01:34:52 +00:00
|
|
|
pub struct DialInfoFilter {
|
|
|
|
pub peer_scope: PeerScope,
|
2022-04-21 00:49:16 +00:00
|
|
|
pub protocol_set: ProtocolSet,
|
2021-12-24 01:34:52 +00:00
|
|
|
pub address_type: Option<AddressType>,
|
|
|
|
}
|
|
|
|
|
2022-04-21 00:49:16 +00:00
|
|
|
impl Default for DialInfoFilter {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
peer_scope: PeerScope::All,
|
|
|
|
protocol_set: ProtocolSet::all(),
|
|
|
|
address_type: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-24 01:34:52 +00:00
|
|
|
impl DialInfoFilter {
|
2021-12-24 23:02:53 +00:00
|
|
|
pub fn all() -> Self {
|
2021-12-24 01:34:52 +00:00
|
|
|
Self {
|
|
|
|
peer_scope: PeerScope::All,
|
2022-04-21 00:49:16 +00:00
|
|
|
protocol_set: ProtocolSet::all(),
|
2021-12-24 01:34:52 +00:00
|
|
|
address_type: None,
|
|
|
|
}
|
|
|
|
}
|
2021-12-24 23:02:53 +00:00
|
|
|
pub fn global() -> Self {
|
2021-12-24 01:34:52 +00:00
|
|
|
Self {
|
2021-12-24 23:02:53 +00:00
|
|
|
peer_scope: PeerScope::Global,
|
2022-04-21 00:49:16 +00:00
|
|
|
protocol_set: ProtocolSet::all(),
|
2021-12-24 01:34:52 +00:00
|
|
|
address_type: None,
|
|
|
|
}
|
|
|
|
}
|
2021-12-24 23:02:53 +00:00
|
|
|
pub fn local() -> Self {
|
2021-12-24 01:34:52 +00:00
|
|
|
Self {
|
2021-12-24 23:02:53 +00:00
|
|
|
peer_scope: PeerScope::Local,
|
2022-04-21 00:49:16 +00:00
|
|
|
protocol_set: ProtocolSet::all(),
|
2021-12-24 23:02:53 +00:00
|
|
|
address_type: None,
|
2021-12-24 01:34:52 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-24 23:02:53 +00:00
|
|
|
pub fn scoped(peer_scope: PeerScope) -> Self {
|
|
|
|
Self {
|
|
|
|
peer_scope,
|
2022-04-21 00:49:16 +00:00
|
|
|
protocol_set: ProtocolSet::all(),
|
2021-12-24 23:02:53 +00:00
|
|
|
address_type: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn with_protocol_type(mut self, protocol_type: ProtocolType) -> Self {
|
2022-04-21 00:49:16 +00:00
|
|
|
self.protocol_set = ProtocolSet::only(protocol_type);
|
2021-12-24 23:02:53 +00:00
|
|
|
self
|
|
|
|
}
|
2022-04-25 00:16:13 +00:00
|
|
|
pub fn with_protocol_set(mut self, protocol_set: ProtocolSet) -> Self {
|
|
|
|
self.protocol_set = protocol_set;
|
|
|
|
self
|
|
|
|
}
|
2021-12-24 23:02:53 +00:00
|
|
|
pub fn with_address_type(mut self, address_type: AddressType) -> Self {
|
|
|
|
self.address_type = Some(address_type);
|
|
|
|
self
|
|
|
|
}
|
2021-12-24 01:34:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for DialInfoFilter {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
let mut out = String::new();
|
|
|
|
out += &format!("{:?}", self.peer_scope);
|
2022-04-21 00:49:16 +00:00
|
|
|
if self.protocol_set != ProtocolSet::all() {
|
|
|
|
out += &format!("+{:?}", self.protocol_set);
|
2021-12-24 01:34:52 +00:00
|
|
|
}
|
|
|
|
if let Some(at) = self.address_type {
|
|
|
|
out += &format!("+{:?}", at);
|
|
|
|
}
|
|
|
|
write!(f, "[{}]", out)
|
2021-12-21 00:12:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-24 23:02:53 +00:00
|
|
|
pub trait MatchesDialInfoFilter {
|
|
|
|
fn matches_filter(&self, filter: &DialInfoFilter) -> bool;
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct DialInfoUDP {
|
2021-12-21 00:12:30 +00:00
|
|
|
pub socket_address: SocketAddress,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct DialInfoTCP {
|
2021-12-21 00:12:30 +00:00
|
|
|
pub socket_address: SocketAddress,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct DialInfoWS {
|
2021-12-21 00:12:30 +00:00
|
|
|
pub socket_address: SocketAddress,
|
|
|
|
pub request: String,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Default, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct DialInfoWSS {
|
2021-12-21 00:12:30 +00:00
|
|
|
pub socket_address: SocketAddress,
|
|
|
|
pub request: String,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Serialize, Deserialize)]
|
|
|
|
#[serde(tag = "kind")]
|
2022-04-25 00:16:13 +00:00
|
|
|
// Keep member order appropriate for sorting < preference
|
2021-12-22 03:20:55 +00:00
|
|
|
// Must match ProtocolType order
|
2021-11-22 16:28:30 +00:00
|
|
|
pub enum DialInfo {
|
|
|
|
UDP(DialInfoUDP),
|
|
|
|
TCP(DialInfoTCP),
|
|
|
|
WS(DialInfoWS),
|
|
|
|
WSS(DialInfoWSS),
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
impl Default for DialInfo {
|
|
|
|
fn default() -> Self {
|
|
|
|
DialInfo::UDP(DialInfoUDP::default())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for DialInfo {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
match self {
|
|
|
|
DialInfo::UDP(di) => write!(f, "udp|{}", di.socket_address),
|
|
|
|
DialInfo::TCP(di) => write!(f, "tcp|{}", di.socket_address),
|
2022-05-16 15:52:48 +00:00
|
|
|
DialInfo::WS(di) => {
|
|
|
|
let url = format!("ws://{}", di.request);
|
|
|
|
let split_url = SplitUrl::from_str(&url).unwrap();
|
|
|
|
match split_url.host {
|
|
|
|
SplitUrlHost::Hostname(_) => {
|
|
|
|
write!(f, "ws|{}|{}", di.socket_address.to_ip_addr(), di.request)
|
|
|
|
}
|
|
|
|
SplitUrlHost::IpAddr(a) => {
|
|
|
|
if di.socket_address.to_ip_addr() == a {
|
|
|
|
write!(f, "ws|{}", di.request)
|
|
|
|
} else {
|
|
|
|
panic!("resolved address does not match url: {}", di.request);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DialInfo::WSS(di) => {
|
|
|
|
let url = format!("wss://{}", di.request);
|
|
|
|
let split_url = SplitUrl::from_str(&url).unwrap();
|
|
|
|
match split_url.host {
|
|
|
|
SplitUrlHost::Hostname(_) => {
|
|
|
|
write!(f, "wss|{}|{}", di.socket_address.to_ip_addr(), di.request)
|
|
|
|
}
|
|
|
|
SplitUrlHost::IpAddr(_) => {
|
|
|
|
panic!(
|
|
|
|
"secure websockets can not use ip address in request: {}",
|
|
|
|
di.request
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl FromStr for DialInfo {
|
|
|
|
type Err = VeilidAPIError;
|
|
|
|
fn from_str(s: &str) -> Result<DialInfo, VeilidAPIError> {
|
2021-12-24 23:02:53 +00:00
|
|
|
let (proto, rest) = s
|
|
|
|
.split_once('|')
|
|
|
|
.ok_or_else(|| parse_error!("DialInfo::from_str missing protocol '|' separator", s))?;
|
2021-12-21 00:12:30 +00:00
|
|
|
match proto {
|
|
|
|
"udp" => {
|
|
|
|
let socket_address = SocketAddress::from_str(rest)?;
|
|
|
|
Ok(DialInfo::udp(socket_address))
|
|
|
|
}
|
|
|
|
"tcp" => {
|
|
|
|
let socket_address = SocketAddress::from_str(rest)?;
|
|
|
|
Ok(DialInfo::tcp(socket_address))
|
|
|
|
}
|
|
|
|
"ws" => {
|
2022-05-16 15:52:48 +00:00
|
|
|
let url = format!("ws://{}", rest);
|
|
|
|
let split_url = SplitUrl::from_str(&url)
|
|
|
|
.map_err(|e| parse_error!(format!("unable to split WS url: {}", e), url))?;
|
|
|
|
if split_url.scheme != "ws" || !url.starts_with("ws://") {
|
|
|
|
return Err(parse_error!("incorrect scheme for WS dialinfo", url));
|
|
|
|
}
|
|
|
|
let url_port = split_url.port.unwrap_or(80u16);
|
|
|
|
|
|
|
|
match rest.split_once('|') {
|
|
|
|
Some((sa, rest)) => {
|
|
|
|
let address = Address::from_str(sa)?;
|
|
|
|
|
|
|
|
DialInfo::try_ws(
|
|
|
|
SocketAddress::new(address, url_port),
|
|
|
|
format!("ws://{}", rest),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
let address = Address::from_str(&split_url.host.to_string())?;
|
|
|
|
DialInfo::try_ws(
|
|
|
|
SocketAddress::new(address, url_port),
|
|
|
|
format!("ws://{}", rest),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
}
|
|
|
|
"wss" => {
|
2022-05-16 15:52:48 +00:00
|
|
|
let url = format!("wss://{}", rest);
|
|
|
|
let split_url = SplitUrl::from_str(&url)
|
|
|
|
.map_err(|e| parse_error!(format!("unable to split WSS url: {}", e), url))?;
|
|
|
|
if split_url.scheme != "wss" || !url.starts_with("wss://") {
|
|
|
|
return Err(parse_error!("incorrect scheme for WSS dialinfo", url));
|
|
|
|
}
|
|
|
|
let url_port = split_url.port.unwrap_or(443u16);
|
|
|
|
|
|
|
|
let (a, rest) = rest.split_once('|').ok_or_else(|| {
|
2021-12-24 23:02:53 +00:00
|
|
|
parse_error!("DialInfo::from_str missing socket address '|' separator", s)
|
2021-12-21 00:12:30 +00:00
|
|
|
})?;
|
2022-05-16 15:52:48 +00:00
|
|
|
|
|
|
|
let address = Address::from_str(a)?;
|
|
|
|
DialInfo::try_wss(
|
|
|
|
SocketAddress::new(address, url_port),
|
|
|
|
format!("wss://{}", rest),
|
|
|
|
)
|
2021-12-21 00:12:30 +00:00
|
|
|
}
|
2021-12-24 23:02:53 +00:00
|
|
|
_ => Err(parse_error!("DialInfo::from_str has invalid scheme", s)),
|
2021-12-21 00:12:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
|
|
|
|
impl DialInfo {
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn udp_from_socketaddr(socket_addr: SocketAddr) -> Self {
|
2021-11-22 16:28:30 +00:00
|
|
|
Self::UDP(DialInfoUDP {
|
2021-12-21 00:12:30 +00:00
|
|
|
socket_address: SocketAddress::from_socket_addr(socket_addr).to_canonical(),
|
2021-11-22 16:28:30 +00:00
|
|
|
})
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn tcp_from_socketaddr(socket_addr: SocketAddr) -> Self {
|
2021-11-22 16:28:30 +00:00
|
|
|
Self::TCP(DialInfoTCP {
|
2021-12-21 00:12:30 +00:00
|
|
|
socket_address: SocketAddress::from_socket_addr(socket_addr).to_canonical(),
|
2021-11-22 16:28:30 +00:00
|
|
|
})
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn udp(socket_address: SocketAddress) -> Self {
|
|
|
|
Self::UDP(DialInfoUDP {
|
|
|
|
socket_address: socket_address.to_canonical(),
|
|
|
|
})
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn tcp(socket_address: SocketAddress) -> Self {
|
|
|
|
Self::TCP(DialInfoTCP {
|
|
|
|
socket_address: socket_address.to_canonical(),
|
|
|
|
})
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn try_ws(socket_address: SocketAddress, url: String) -> Result<Self, VeilidAPIError> {
|
|
|
|
let split_url = SplitUrl::from_str(&url)
|
|
|
|
.map_err(|e| parse_error!(format!("unable to split WS url: {}", e), url))?;
|
|
|
|
if split_url.scheme != "ws" || !url.starts_with("ws://") {
|
|
|
|
return Err(parse_error!("incorrect scheme for WS dialinfo", url));
|
|
|
|
}
|
|
|
|
let url_port = split_url.port.unwrap_or(80u16);
|
|
|
|
if url_port != socket_address.port() {
|
|
|
|
return Err(parse_error!(
|
|
|
|
"socket address port doesn't match url port",
|
|
|
|
url
|
|
|
|
));
|
|
|
|
}
|
2022-05-16 15:52:48 +00:00
|
|
|
if let SplitUrlHost::IpAddr(a) = split_url.host {
|
|
|
|
if socket_address.to_ip_addr() != a {
|
|
|
|
return Err(parse_error!(
|
|
|
|
format!("request address does not match socket address: {}", a),
|
|
|
|
socket_address
|
|
|
|
));
|
|
|
|
}
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
Ok(Self::WS(DialInfoWS {
|
|
|
|
socket_address: socket_address.to_canonical(),
|
|
|
|
request: url[5..].to_string(),
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
pub fn try_wss(socket_address: SocketAddress, url: String) -> Result<Self, VeilidAPIError> {
|
|
|
|
let split_url = SplitUrl::from_str(&url)
|
|
|
|
.map_err(|e| parse_error!(format!("unable to split WSS url: {}", e), url))?;
|
|
|
|
if split_url.scheme != "wss" || !url.starts_with("wss://") {
|
|
|
|
return Err(parse_error!("incorrect scheme for WSS dialinfo", url));
|
|
|
|
}
|
|
|
|
let url_port = split_url.port.unwrap_or(443u16);
|
|
|
|
if url_port != socket_address.port() {
|
|
|
|
return Err(parse_error!(
|
|
|
|
"socket address port doesn't match url port",
|
|
|
|
url
|
|
|
|
));
|
|
|
|
}
|
2022-04-26 13:16:48 +00:00
|
|
|
if !matches!(split_url.host, SplitUrlHost::Hostname(_)) {
|
2021-12-21 00:12:30 +00:00
|
|
|
return Err(parse_error!(
|
|
|
|
"WSS url can not use address format, only hostname format",
|
|
|
|
url
|
|
|
|
));
|
|
|
|
}
|
|
|
|
Ok(Self::WSS(DialInfoWSS {
|
|
|
|
socket_address: socket_address.to_canonical(),
|
|
|
|
request: url[6..].to_string(),
|
|
|
|
}))
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
pub fn protocol_type(&self) -> ProtocolType {
|
|
|
|
match self {
|
|
|
|
Self::UDP(_) => ProtocolType::UDP,
|
|
|
|
Self::TCP(_) => ProtocolType::TCP,
|
|
|
|
Self::WS(_) => ProtocolType::WS,
|
|
|
|
Self::WSS(_) => ProtocolType::WSS,
|
|
|
|
}
|
|
|
|
}
|
2021-12-22 03:20:55 +00:00
|
|
|
pub fn address_type(&self) -> AddressType {
|
|
|
|
self.socket_address().address_type()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn socket_address(&self) -> SocketAddress {
|
2021-11-22 16:28:30 +00:00
|
|
|
match self {
|
2021-12-21 00:12:30 +00:00
|
|
|
Self::UDP(di) => di.socket_address,
|
|
|
|
Self::TCP(di) => di.socket_address,
|
|
|
|
Self::WS(di) => di.socket_address,
|
|
|
|
Self::WSS(di) => di.socket_address,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn to_ip_addr(&self) -> IpAddr {
|
2021-11-22 16:28:30 +00:00
|
|
|
match self {
|
2021-12-21 00:12:30 +00:00
|
|
|
Self::UDP(di) => di.socket_address.to_ip_addr(),
|
|
|
|
Self::TCP(di) => di.socket_address.to_ip_addr(),
|
|
|
|
Self::WS(di) => di.socket_address.to_ip_addr(),
|
|
|
|
Self::WSS(di) => di.socket_address.to_ip_addr(),
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn port(&self) -> u16 {
|
|
|
|
match self {
|
2021-12-21 00:12:30 +00:00
|
|
|
Self::UDP(di) => di.socket_address.port,
|
|
|
|
Self::TCP(di) => di.socket_address.port,
|
|
|
|
Self::WS(di) => di.socket_address.port,
|
|
|
|
Self::WSS(di) => di.socket_address.port,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-01 03:09:30 +00:00
|
|
|
pub fn set_port(&mut self, port: u16) {
|
|
|
|
match self {
|
|
|
|
Self::UDP(di) => di.socket_address.port = port,
|
|
|
|
Self::TCP(di) => di.socket_address.port = port,
|
|
|
|
Self::WS(di) => di.socket_address.port = port,
|
|
|
|
Self::WSS(di) => di.socket_address.port = port,
|
|
|
|
}
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn to_socket_addr(&self) -> SocketAddr {
|
2021-11-22 16:28:30 +00:00
|
|
|
match self {
|
2021-12-21 00:12:30 +00:00
|
|
|
Self::UDP(di) => di.socket_address.to_socket_addr(),
|
|
|
|
Self::TCP(di) => di.socket_address.to_socket_addr(),
|
|
|
|
Self::WS(di) => di.socket_address.to_socket_addr(),
|
|
|
|
Self::WSS(di) => di.socket_address.to_socket_addr(),
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-25 15:58:43 +00:00
|
|
|
pub fn to_peer_address(&self) -> PeerAddress {
|
|
|
|
match self {
|
|
|
|
Self::UDP(di) => PeerAddress::new(di.socket_address, ProtocolType::UDP),
|
|
|
|
Self::TCP(di) => PeerAddress::new(di.socket_address, ProtocolType::TCP),
|
|
|
|
Self::WS(di) => PeerAddress::new(di.socket_address, ProtocolType::WS),
|
|
|
|
Self::WSS(di) => PeerAddress::new(di.socket_address, ProtocolType::WSS),
|
|
|
|
}
|
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn request(&self) -> Option<String> {
|
2021-11-22 16:28:30 +00:00
|
|
|
match self {
|
2021-12-21 00:12:30 +00:00
|
|
|
Self::UDP(_) => None,
|
|
|
|
Self::TCP(_) => None,
|
|
|
|
Self::WS(di) => Some(format!("ws://{}", di.request)),
|
|
|
|
Self::WSS(di) => Some(format!("wss://{}", di.request)),
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
2021-12-22 03:20:55 +00:00
|
|
|
pub fn is_global(&self) -> bool {
|
|
|
|
self.socket_address().address().is_global()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2021-12-22 03:20:55 +00:00
|
|
|
pub fn is_local(&self) -> bool {
|
|
|
|
self.socket_address().address().is_local()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn is_valid(&self) -> bool {
|
|
|
|
let socket_address = self.socket_address();
|
|
|
|
let address = socket_address.address();
|
|
|
|
let port = socket_address.port();
|
2021-12-22 03:20:55 +00:00
|
|
|
(address.is_global() || address.is_local()) && port > 0
|
|
|
|
}
|
|
|
|
pub fn matches_peer_scope(&self, scope: PeerScope) -> bool {
|
|
|
|
match scope {
|
|
|
|
PeerScope::All => true,
|
|
|
|
PeerScope::Global => self.is_global(),
|
|
|
|
PeerScope::Local => self.is_local(),
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2021-12-24 01:34:52 +00:00
|
|
|
pub fn make_filter(&self, scoped: bool) -> DialInfoFilter {
|
|
|
|
DialInfoFilter {
|
|
|
|
peer_scope: if scoped {
|
|
|
|
if self.is_global() {
|
|
|
|
PeerScope::Global
|
|
|
|
} else if self.is_local() {
|
|
|
|
PeerScope::Local
|
|
|
|
} else {
|
|
|
|
PeerScope::All
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PeerScope::All
|
|
|
|
},
|
2022-04-21 00:49:16 +00:00
|
|
|
protocol_set: ProtocolSet::only(self.protocol_type()),
|
2021-12-24 01:34:52 +00:00
|
|
|
address_type: Some(self.address_type()),
|
|
|
|
}
|
|
|
|
}
|
2022-05-17 20:55:53 +00:00
|
|
|
|
2022-05-28 14:07:57 +00:00
|
|
|
pub fn try_vec_from_short<S: AsRef<str>, H: AsRef<str>>(
|
|
|
|
short: S,
|
|
|
|
hostname: H,
|
|
|
|
) -> Result<Vec<Self>, VeilidAPIError> {
|
|
|
|
let short = short.as_ref();
|
|
|
|
let hostname = hostname.as_ref();
|
|
|
|
|
|
|
|
if short.len() < 2 {
|
|
|
|
return Err(parse_error!("invalid short url length", short));
|
|
|
|
}
|
|
|
|
let url = match &short[0..1] {
|
|
|
|
"U" => {
|
|
|
|
format!("udp://{}:{}", hostname, &short[1..])
|
|
|
|
}
|
|
|
|
"T" => {
|
|
|
|
format!("tcp://{}:{}", hostname, &short[1..])
|
|
|
|
}
|
|
|
|
"W" => {
|
|
|
|
format!("ws://{}:{}", hostname, &short[1..])
|
|
|
|
}
|
|
|
|
"S" => {
|
|
|
|
format!("wss://{}:{}", hostname, &short[1..])
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
return Err(parse_error!("invalid short url type", short));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Self::try_vec_from_url(url)
|
|
|
|
}
|
|
|
|
|
2022-05-24 21:13:52 +00:00
|
|
|
pub fn try_vec_from_url<S: AsRef<str>>(url: S) -> Result<Vec<Self>, VeilidAPIError> {
|
|
|
|
let url = url.as_ref();
|
|
|
|
let split_url = SplitUrl::from_str(url)
|
2022-05-17 20:55:53 +00:00
|
|
|
.map_err(|e| parse_error!(format!("unable to split url: {}", e), url))?;
|
|
|
|
|
|
|
|
let port = match split_url.scheme.as_str() {
|
|
|
|
"udp" | "tcp" => split_url
|
|
|
|
.port
|
|
|
|
.ok_or_else(|| parse_error!("Missing port in udp url", url))?,
|
|
|
|
"ws" => split_url.port.unwrap_or(80u16),
|
|
|
|
"wss" => split_url.port.unwrap_or(443u16),
|
|
|
|
_ => {
|
|
|
|
return Err(parse_error!(
|
|
|
|
"Invalid dial info url scheme",
|
|
|
|
split_url.scheme
|
|
|
|
));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2022-06-09 00:07:26 +00:00
|
|
|
let socket_addrs = {
|
|
|
|
// Resolve if possible, WASM doesn't support resolution and doesn't need it to connect to the dialinfo
|
|
|
|
// This will not be used on signed dialinfo, only for bootstrapping, so we don't need to worry about
|
|
|
|
// the '0.0.0.0' address being propagated across the routing table
|
|
|
|
cfg_if::cfg_if! {
|
|
|
|
if #[cfg(target_arch = "wasm32")] {
|
|
|
|
vec![SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0,0,0,0)), port)]
|
|
|
|
} else {
|
|
|
|
match split_url.host {
|
|
|
|
SplitUrlHost::Hostname(_) => split_url
|
|
|
|
.host_port(port)
|
|
|
|
.to_socket_addrs()
|
|
|
|
.map_err(|_| parse_error!("couldn't resolve hostname in url", url))?
|
|
|
|
.collect(),
|
|
|
|
SplitUrlHost::IpAddr(a) => vec![SocketAddr::new(a, port)],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-17 20:55:53 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
let mut out = Vec::new();
|
|
|
|
for sa in socket_addrs {
|
|
|
|
out.push(match split_url.scheme.as_str() {
|
|
|
|
"udp" => Self::udp_from_socketaddr(sa),
|
|
|
|
"tcp" => Self::tcp_from_socketaddr(sa),
|
|
|
|
"ws" => Self::try_ws(
|
|
|
|
SocketAddress::from_socket_addr(sa).to_canonical(),
|
2022-05-24 21:13:52 +00:00
|
|
|
url.to_string(),
|
2022-05-17 20:55:53 +00:00
|
|
|
)?,
|
|
|
|
"wss" => Self::try_wss(
|
|
|
|
SocketAddress::from_socket_addr(sa).to_canonical(),
|
2022-05-24 21:13:52 +00:00
|
|
|
url.to_string(),
|
2022-05-17 20:55:53 +00:00
|
|
|
)?,
|
|
|
|
_ => {
|
|
|
|
unreachable!("Invalid dial info url scheme")
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
Ok(out)
|
|
|
|
}
|
|
|
|
|
2022-05-28 14:07:57 +00:00
|
|
|
pub async fn to_short(&self) -> (String, String) {
|
|
|
|
match self {
|
|
|
|
DialInfo::UDP(di) => (
|
|
|
|
format!("U{}", di.socket_address.port()),
|
|
|
|
intf::ptr_lookup(di.socket_address.to_ip_addr())
|
|
|
|
.await
|
|
|
|
.unwrap_or_else(|_| di.socket_address.to_string()),
|
|
|
|
),
|
|
|
|
DialInfo::TCP(di) => (
|
|
|
|
format!("T{}", di.socket_address.port()),
|
|
|
|
intf::ptr_lookup(di.socket_address.to_ip_addr())
|
|
|
|
.await
|
|
|
|
.unwrap_or_else(|_| di.socket_address.to_string()),
|
|
|
|
),
|
|
|
|
DialInfo::WS(di) => {
|
|
|
|
let mut split_url = SplitUrl::from_str(&format!("ws://{}", di.request)).unwrap();
|
|
|
|
if let SplitUrlHost::IpAddr(a) = split_url.host {
|
|
|
|
if let Ok(host) = intf::ptr_lookup(a).await {
|
|
|
|
split_url.host = SplitUrlHost::Hostname(host);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(
|
|
|
|
format!(
|
|
|
|
"W{}{}",
|
|
|
|
split_url.port.unwrap_or(80),
|
|
|
|
split_url
|
|
|
|
.path
|
|
|
|
.map(|p| format!("/{}", p))
|
|
|
|
.unwrap_or_default()
|
|
|
|
),
|
|
|
|
split_url.host.to_string(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
DialInfo::WSS(di) => {
|
|
|
|
let mut split_url = SplitUrl::from_str(&format!("wss://{}", di.request)).unwrap();
|
|
|
|
if let SplitUrlHost::IpAddr(a) = split_url.host {
|
|
|
|
if let Ok(host) = intf::ptr_lookup(a).await {
|
|
|
|
split_url.host = SplitUrlHost::Hostname(host);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
(
|
|
|
|
format!(
|
|
|
|
"S{}{}",
|
|
|
|
split_url.port.unwrap_or(443),
|
|
|
|
split_url
|
|
|
|
.path
|
|
|
|
.map(|p| format!("/{}", p))
|
|
|
|
.unwrap_or_default()
|
|
|
|
),
|
|
|
|
split_url.host.to_string(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-17 20:55:53 +00:00
|
|
|
pub async fn to_url(&self) -> String {
|
|
|
|
match self {
|
|
|
|
DialInfo::UDP(di) => intf::ptr_lookup(di.socket_address.to_ip_addr())
|
|
|
|
.await
|
|
|
|
.map(|h| format!("udp://{}:{}", h, di.socket_address.port()))
|
|
|
|
.unwrap_or_else(|_| format!("udp://{}", di.socket_address)),
|
|
|
|
DialInfo::TCP(di) => intf::ptr_lookup(di.socket_address.to_ip_addr())
|
|
|
|
.await
|
|
|
|
.map(|h| format!("tcp://{}:{}", h, di.socket_address.port()))
|
|
|
|
.unwrap_or_else(|_| format!("tcp://{}", di.socket_address)),
|
|
|
|
DialInfo::WS(di) => {
|
|
|
|
let mut split_url = SplitUrl::from_str(&format!("ws://{}", di.request)).unwrap();
|
|
|
|
if let SplitUrlHost::IpAddr(a) = split_url.host {
|
|
|
|
if let Ok(host) = intf::ptr_lookup(a).await {
|
|
|
|
split_url.host = SplitUrlHost::Hostname(host);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
split_url.to_string()
|
|
|
|
}
|
|
|
|
DialInfo::WSS(di) => {
|
|
|
|
let mut split_url = SplitUrl::from_str(&format!("wss://{}", di.request)).unwrap();
|
|
|
|
if let SplitUrlHost::IpAddr(a) = split_url.host {
|
|
|
|
if let Ok(host) = intf::ptr_lookup(a).await {
|
|
|
|
split_url.host = SplitUrlHost::Hostname(host);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
split_url.to_string()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2021-12-24 23:02:53 +00:00
|
|
|
impl MatchesDialInfoFilter for DialInfo {
|
|
|
|
fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
|
|
|
|
if !self.matches_peer_scope(filter.peer_scope) {
|
|
|
|
return false;
|
|
|
|
}
|
2022-04-21 00:49:16 +00:00
|
|
|
if !filter.protocol_set.contains(self.protocol_type()) {
|
|
|
|
return false;
|
2021-12-24 23:02:53 +00:00
|
|
|
}
|
|
|
|
if let Some(at) = filter.address_type {
|
|
|
|
if self.address_type() != at {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub enum PeerScope {
|
|
|
|
All,
|
2021-12-08 03:09:45 +00:00
|
|
|
Global,
|
|
|
|
Local,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2021-12-24 01:34:52 +00:00
|
|
|
impl Default for PeerScope {
|
|
|
|
fn default() -> Self {
|
|
|
|
PeerScope::All
|
|
|
|
}
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
|
2022-05-11 01:49:42 +00:00
|
|
|
// Signed NodeInfo that can be passed around amongst peers and verifiable
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
pub struct SignedNodeInfo {
|
|
|
|
pub node_info: NodeInfo,
|
|
|
|
pub signature: DHTSignature,
|
2022-05-11 13:37:54 +00:00
|
|
|
pub timestamp: u64,
|
2022-05-11 01:49:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl SignedNodeInfo {
|
|
|
|
pub fn new(
|
|
|
|
node_info: NodeInfo,
|
|
|
|
node_id: NodeId,
|
|
|
|
signature: DHTSignature,
|
2022-05-11 13:37:54 +00:00
|
|
|
timestamp: u64,
|
2022-05-11 01:49:42 +00:00
|
|
|
) -> Result<Self, String> {
|
2022-05-11 13:37:54 +00:00
|
|
|
let mut node_info_bytes = serde_cbor::to_vec(&node_info).map_err(map_to_string)?;
|
|
|
|
let mut timestamp_bytes = serde_cbor::to_vec(×tamp).map_err(map_to_string)?;
|
|
|
|
|
|
|
|
node_info_bytes.append(&mut timestamp_bytes);
|
|
|
|
|
2022-05-11 01:49:42 +00:00
|
|
|
verify(&node_id.key, &node_info_bytes, &signature)?;
|
|
|
|
Ok(Self {
|
|
|
|
node_info,
|
|
|
|
signature,
|
2022-05-11 13:37:54 +00:00
|
|
|
timestamp,
|
2022-05-11 01:49:42 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_secret(
|
|
|
|
node_info: NodeInfo,
|
|
|
|
node_id: NodeId,
|
|
|
|
secret: &DHTKeySecret,
|
|
|
|
) -> Result<Self, String> {
|
2022-05-11 13:37:54 +00:00
|
|
|
let timestamp = intf::get_timestamp();
|
|
|
|
|
|
|
|
let mut node_info_bytes = serde_cbor::to_vec(&node_info).map_err(map_to_string)?;
|
|
|
|
let mut timestamp_bytes = serde_cbor::to_vec(×tamp).map_err(map_to_string)?;
|
|
|
|
|
|
|
|
node_info_bytes.append(&mut timestamp_bytes);
|
|
|
|
|
2022-05-11 01:49:42 +00:00
|
|
|
let signature = sign(&node_id.key, secret, &node_info_bytes)?;
|
|
|
|
Ok(Self {
|
|
|
|
node_info,
|
|
|
|
signature,
|
2022-05-11 13:37:54 +00:00
|
|
|
timestamp,
|
2022-05-11 01:49:42 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn with_no_signature(node_info: NodeInfo) -> Self {
|
|
|
|
Self {
|
|
|
|
node_info,
|
|
|
|
signature: DHTSignature::default(),
|
2022-05-11 13:37:54 +00:00
|
|
|
timestamp: intf::get_timestamp(),
|
2022-05-11 01:49:42 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-24 21:13:52 +00:00
|
|
|
|
|
|
|
pub fn is_valid(&self) -> bool {
|
|
|
|
self.signature.valid && self.node_info.is_valid()
|
|
|
|
}
|
2022-05-11 01:49:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct PeerInfo {
|
|
|
|
pub node_id: NodeId,
|
2022-05-11 01:49:42 +00:00
|
|
|
pub signed_node_info: SignedNodeInfo,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PeerInfo {
|
|
|
|
pub fn new(node_id: NodeId, signed_node_info: SignedNodeInfo) -> Self {
|
|
|
|
Self {
|
|
|
|
node_id,
|
|
|
|
signed_node_info,
|
|
|
|
}
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct PeerAddress {
|
2022-06-05 17:23:18 +00:00
|
|
|
socket_address: SocketAddress,
|
|
|
|
protocol_type: ProtocolType,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl PeerAddress {
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn new(socket_address: SocketAddress, protocol_type: ProtocolType) -> Self {
|
2021-11-22 16:28:30 +00:00
|
|
|
Self {
|
2021-12-22 03:20:55 +00:00
|
|
|
socket_address: socket_address.to_canonical(),
|
2021-11-27 17:44:21 +00:00
|
|
|
protocol_type,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-05 17:23:18 +00:00
|
|
|
pub fn socket_address(&self) -> &SocketAddress {
|
|
|
|
&self.socket_address
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn protocol_type(&self) -> ProtocolType {
|
|
|
|
self.protocol_type
|
|
|
|
}
|
|
|
|
|
2021-12-21 00:12:30 +00:00
|
|
|
pub fn to_socket_addr(&self) -> SocketAddr {
|
|
|
|
self.socket_address.to_socket_addr()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2021-12-21 00:12:30 +00:00
|
|
|
|
2021-12-22 03:20:55 +00:00
|
|
|
pub fn address_type(&self) -> AddressType {
|
|
|
|
self.socket_address.address_type()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct ConnectionDescriptor {
|
2022-06-05 17:23:18 +00:00
|
|
|
remote: PeerAddress,
|
|
|
|
local: Option<SocketAddress>,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ConnectionDescriptor {
|
2021-12-22 03:20:55 +00:00
|
|
|
pub fn new(remote: PeerAddress, local: SocketAddress) -> Self {
|
2021-11-22 16:28:30 +00:00
|
|
|
Self {
|
2021-11-27 17:44:21 +00:00
|
|
|
remote,
|
2021-11-22 16:28:30 +00:00
|
|
|
local: Some(local),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn new_no_local(remote: PeerAddress) -> Self {
|
|
|
|
Self {
|
2021-11-27 17:44:21 +00:00
|
|
|
remote,
|
2021-11-22 16:28:30 +00:00
|
|
|
local: None,
|
|
|
|
}
|
|
|
|
}
|
2022-06-05 17:23:18 +00:00
|
|
|
pub fn remote(&self) -> PeerAddress {
|
|
|
|
self.remote
|
|
|
|
}
|
|
|
|
pub fn remote_address(&self) -> &SocketAddress {
|
|
|
|
self.remote.socket_address()
|
|
|
|
}
|
|
|
|
pub fn local(&self) -> Option<SocketAddress> {
|
|
|
|
self.local
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
pub fn protocol_type(&self) -> ProtocolType {
|
|
|
|
self.remote.protocol_type
|
|
|
|
}
|
2021-12-22 03:20:55 +00:00
|
|
|
pub fn address_type(&self) -> AddressType {
|
|
|
|
self.remote.address_type()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2021-12-24 01:34:52 +00:00
|
|
|
pub fn matches_peer_scope(&self, scope: PeerScope) -> bool {
|
|
|
|
match scope {
|
|
|
|
PeerScope::All => true,
|
|
|
|
PeerScope::Global => self.remote.socket_address.address().is_global(),
|
|
|
|
PeerScope::Local => self.remote.socket_address.address().is_local(),
|
|
|
|
}
|
|
|
|
}
|
2021-12-24 23:02:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl MatchesDialInfoFilter for ConnectionDescriptor {
|
|
|
|
fn matches_filter(&self, filter: &DialInfoFilter) -> bool {
|
2021-12-24 01:34:52 +00:00
|
|
|
if !self.matches_peer_scope(filter.peer_scope) {
|
|
|
|
return false;
|
|
|
|
}
|
2022-05-24 21:13:52 +00:00
|
|
|
if !filter.protocol_set.contains(self.protocol_type()) {
|
2022-04-21 00:49:16 +00:00
|
|
|
return false;
|
2021-12-24 01:34:52 +00:00
|
|
|
}
|
|
|
|
if let Some(at) = filter.address_type {
|
|
|
|
if self.address_type() != at {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
true
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
|
2022-01-01 03:09:30 +00:00
|
|
|
pub struct NodeDialInfo {
|
2021-11-22 16:28:30 +00:00
|
|
|
pub node_id: NodeId,
|
|
|
|
pub dial_info: DialInfo,
|
|
|
|
}
|
|
|
|
|
2022-01-01 03:09:30 +00:00
|
|
|
impl fmt::Display for NodeDialInfo {
|
2021-12-21 00:12:30 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
|
|
|
write!(f, "{}@{}", self.node_id, self.dial_info)
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-01 03:09:30 +00:00
|
|
|
impl FromStr for NodeDialInfo {
|
2021-12-21 00:12:30 +00:00
|
|
|
type Err = VeilidAPIError;
|
2022-01-01 03:09:30 +00:00
|
|
|
fn from_str(s: &str) -> Result<NodeDialInfo, VeilidAPIError> {
|
2021-12-21 00:12:30 +00:00
|
|
|
// split out node id from the dial info
|
2022-01-01 03:09:30 +00:00
|
|
|
let (node_id_str, rest) = s
|
|
|
|
.split_once('@')
|
|
|
|
.ok_or_else(|| parse_error!("NodeDialInfo::from_str missing @ node id separator", s))?;
|
2021-12-21 00:12:30 +00:00
|
|
|
|
|
|
|
// parse out node id
|
|
|
|
let node_id = NodeId::new(DHTKey::try_decode(node_id_str).map_err(|e| {
|
|
|
|
parse_error!(
|
2022-01-01 03:09:30 +00:00
|
|
|
format!("NodeDialInfo::from_str couldn't parse node id: {}", e),
|
2021-12-21 00:12:30 +00:00
|
|
|
s
|
|
|
|
)
|
|
|
|
})?);
|
|
|
|
// parse out dial info
|
|
|
|
let dial_info = DialInfo::from_str(rest)?;
|
|
|
|
|
2022-01-01 03:09:30 +00:00
|
|
|
// return completed NodeDialInfo
|
|
|
|
Ok(NodeDialInfo { node_id, dial_info })
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct LatencyStats {
|
|
|
|
pub fastest: u64, // fastest latency in the ROLLING_LATENCIES_SIZE last latencies
|
|
|
|
pub average: u64, // average latency over the ROLLING_LATENCIES_SIZE last latencies
|
|
|
|
pub slowest: u64, // slowest latency in the ROLLING_LATENCIES_SIZE last latencies
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct TransferStats {
|
|
|
|
pub total: u64, // total amount transferred ever
|
|
|
|
pub maximum: u64, // maximum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
|
|
|
pub average: u64, // average rate over the ROLLING_TRANSFERS_SIZE last amounts
|
|
|
|
pub minimum: u64, // minimum rate over the ROLLING_TRANSFERS_SIZE last amounts
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2022-03-19 22:19:40 +00:00
|
|
|
pub struct TransferStatsDownUp {
|
|
|
|
pub down: TransferStats,
|
|
|
|
pub up: TransferStats,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2022-04-18 22:49:33 +00:00
|
|
|
pub struct RPCStats {
|
|
|
|
pub messages_sent: u32, // number of rpcs that have been sent in the total_time range
|
|
|
|
pub messages_rcvd: u32, // number of rpcs that have been received in the total_time range
|
|
|
|
pub questions_in_flight: u32, // number of questions issued that have yet to be answered
|
2022-05-24 21:13:52 +00:00
|
|
|
pub last_question: Option<u64>, // when the peer was last questioned (either successfully or not) and we wanted an answer
|
|
|
|
pub last_seen_ts: Option<u64>, // when the peer was last seen for any reason, including when we first attempted to reach out to it
|
|
|
|
pub first_consecutive_seen_ts: Option<u64>, // the timestamp of the first consecutive proof-of-life for this node (an answer or received question)
|
2022-04-18 22:49:33 +00:00
|
|
|
pub recent_lost_answers: u32, // number of answers that have been lost since we lost reliability
|
2022-05-24 21:13:52 +00:00
|
|
|
pub failed_to_send: u32, // number of messages that have failed to send since we last successfully sent one
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct PeerStats {
|
|
|
|
pub time_added: u64, // when the peer was added to the routing table
|
2022-05-24 21:13:52 +00:00
|
|
|
pub rpc_stats: RPCStats, // information about RPCs
|
2021-11-22 16:28:30 +00:00
|
|
|
pub latency: Option<LatencyStats>, // latencies for communications with the peer
|
2021-11-26 14:54:38 +00:00
|
|
|
pub transfer: TransferStatsDownUp, // Stats for communications with the peer
|
2022-05-24 21:13:52 +00:00
|
|
|
pub status: Option<NodeStatus>, // Last known node status
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
cfg_if! {
|
|
|
|
if #[cfg(target_arch = "wasm32")] {
|
|
|
|
pub type ValueChangeCallback =
|
|
|
|
Arc<dyn Fn(ValueKey, Vec<u8>) -> SystemPinBoxFuture<()> + 'static>;
|
|
|
|
} else {
|
|
|
|
pub type ValueChangeCallback =
|
|
|
|
Arc<dyn Fn(ValueKey, Vec<u8>) -> SystemPinBoxFuture<()> + Send + Sync + 'static>;
|
|
|
|
}
|
|
|
|
}
|
2022-04-16 15:18:54 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
|
|
pub enum SignalInfo {
|
|
|
|
HolePunch {
|
|
|
|
// UDP Hole Punch Request
|
2022-05-28 20:11:50 +00:00
|
|
|
receipt: Vec<u8>, // Receipt to be returned after the hole punch
|
|
|
|
peer_info: PeerInfo, // Sender's peer info
|
2022-04-16 15:18:54 +00:00
|
|
|
},
|
|
|
|
ReverseConnect {
|
|
|
|
// Reverse Connection Request
|
2022-05-28 20:11:50 +00:00
|
|
|
receipt: Vec<u8>, // Receipt to be returned by the reverse connection
|
|
|
|
peer_info: PeerInfo, // Sender's peer info
|
2022-04-16 15:18:54 +00:00
|
|
|
},
|
|
|
|
// XXX: WebRTC
|
|
|
|
// XXX: App-level signalling
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
|
2022-04-16 15:18:54 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub enum TunnelMode {
|
|
|
|
Raw,
|
|
|
|
Turn,
|
|
|
|
}
|
|
|
|
|
|
|
|
type TunnelId = u64;
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct TunnelEndpoint {
|
|
|
|
pub node_id: NodeId, // the node id of the tunnel endpoint
|
|
|
|
pub dial_info: Vec<DialInfo>, // multiple ways of how to get to the node
|
|
|
|
pub mode: TunnelMode,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for TunnelEndpoint {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
node_id: NodeId::default(),
|
|
|
|
dial_info: Vec::new(),
|
|
|
|
mode: TunnelMode::Raw,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct FullTunnel {
|
|
|
|
pub id: TunnelId,
|
|
|
|
pub timeout: u64,
|
|
|
|
pub local: TunnelEndpoint,
|
|
|
|
pub remote: TunnelEndpoint,
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct PartialTunnel {
|
|
|
|
pub id: TunnelId,
|
|
|
|
pub timeout: u64,
|
|
|
|
pub local: TunnelEndpoint,
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct RouteHopSpec {
|
2022-01-01 03:09:30 +00:00
|
|
|
pub dial_info: NodeDialInfo,
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct PrivateRouteSpec {
|
|
|
|
//
|
|
|
|
pub public_key: DHTKey,
|
|
|
|
pub secret_key: DHTKeySecret,
|
|
|
|
pub hops: Vec<RouteHopSpec>,
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct SafetyRouteSpec {
|
|
|
|
pub public_key: DHTKey,
|
|
|
|
pub secret_key: DHTKeySecret,
|
|
|
|
pub hops: Vec<RouteHopSpec>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SafetyRouteSpec {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
let (pk, sk) = generate_secret();
|
|
|
|
SafetyRouteSpec {
|
|
|
|
public_key: pk,
|
|
|
|
secret_key: sk,
|
|
|
|
hops: Vec::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-07 02:18:42 +00:00
|
|
|
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct RoutingContextOptions {
|
|
|
|
pub safety_route_spec: Option<SafetyRouteSpec>,
|
|
|
|
pub private_route_spec: Option<PrivateRouteSpec>,
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
pub struct RoutingContextInner {
|
|
|
|
api: VeilidAPI,
|
|
|
|
options: RoutingContextOptions,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for RoutingContextInner {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
// self.api
|
|
|
|
// .borrow_mut()
|
|
|
|
// .routing_contexts
|
|
|
|
// //.remove(&self.id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct RoutingContext {
|
|
|
|
inner: Arc<Mutex<RoutingContextInner>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RoutingContext {
|
|
|
|
fn new(api: VeilidAPI, options: RoutingContextOptions) -> Self {
|
|
|
|
Self {
|
2021-11-27 17:44:21 +00:00
|
|
|
inner: Arc::new(Mutex::new(RoutingContextInner { api, options })),
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn api(&self) -> VeilidAPI {
|
|
|
|
self.inner.lock().api.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////
|
|
|
|
///
|
|
|
|
|
|
|
|
pub async fn get_value(&self, _value_key: ValueKey) -> Result<Vec<u8>, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn set_value(
|
|
|
|
&self,
|
|
|
|
_value_key: ValueKey,
|
|
|
|
_value: Vec<u8>,
|
|
|
|
) -> Result<bool, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn watch_value(
|
|
|
|
&self,
|
|
|
|
_value_key: ValueKey,
|
|
|
|
_callback: ValueChangeCallback,
|
|
|
|
) -> Result<bool, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn cancel_watch_value(&self, _value_key: ValueKey) -> Result<bool, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn find_block(&self, _block_id: BlockId) -> Result<Vec<u8>, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn supply_block(&self, _block_id: BlockId) -> Result<bool, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn signal(&self, _data: Vec<u8>) -> Result<bool, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
struct VeilidAPIInner {
|
2022-02-07 02:18:42 +00:00
|
|
|
context: Option<VeilidCoreContext>,
|
2021-12-08 03:09:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for VeilidAPIInner {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2022-02-07 02:18:42 +00:00
|
|
|
write!(f, "VeilidAPIInner")
|
2021-12-08 03:09:45 +00:00
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for VeilidAPIInner {
|
|
|
|
fn drop(&mut self) {
|
2022-02-07 02:18:42 +00:00
|
|
|
if let Some(context) = self.context.take() {
|
|
|
|
intf::spawn_local(api_shutdown(context)).detach();
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-08 03:09:45 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub struct VeilidAPI {
|
|
|
|
inner: Arc<Mutex<VeilidAPIInner>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl VeilidAPI {
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(skip_all)]
|
2022-02-07 02:18:42 +00:00
|
|
|
pub(crate) fn new(context: VeilidCoreContext) -> Self {
|
2021-11-22 16:28:30 +00:00
|
|
|
Self {
|
2022-02-07 02:18:42 +00:00
|
|
|
inner: Arc::new(Mutex::new(VeilidAPIInner {
|
|
|
|
context: Some(context),
|
|
|
|
})),
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(skip_all)]
|
2022-02-07 02:18:42 +00:00
|
|
|
pub async fn shutdown(self) {
|
|
|
|
let context = { self.inner.lock().context.take() };
|
|
|
|
if let Some(context) = context {
|
|
|
|
api_shutdown(context).await;
|
2021-12-08 03:09:45 +00:00
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
|
|
|
|
pub fn is_shutdown(&self) -> bool {
|
|
|
|
self.inner.lock().context.is_none()
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
// Accessors
|
|
|
|
pub fn config(&self) -> Result<VeilidConfig, VeilidAPIError> {
|
|
|
|
let inner = self.inner.lock();
|
|
|
|
if let Some(context) = &inner.context {
|
|
|
|
return Ok(context.config.clone());
|
|
|
|
}
|
|
|
|
Err(VeilidAPIError::NotInitialized)
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
pub fn crypto(&self) -> Result<Crypto, VeilidAPIError> {
|
|
|
|
let inner = self.inner.lock();
|
|
|
|
if let Some(context) = &inner.context {
|
|
|
|
return Ok(context.crypto.clone());
|
|
|
|
}
|
|
|
|
Err(VeilidAPIError::NotInitialized)
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
pub fn table_store(&self) -> Result<TableStore, VeilidAPIError> {
|
|
|
|
let inner = self.inner.lock();
|
|
|
|
if let Some(context) = &inner.context {
|
|
|
|
return Ok(context.table_store.clone());
|
|
|
|
}
|
|
|
|
Err(VeilidAPIError::NotInitialized)
|
2021-12-08 03:09:45 +00:00
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
pub fn block_store(&self) -> Result<BlockStore, VeilidAPIError> {
|
|
|
|
let inner = self.inner.lock();
|
|
|
|
if let Some(context) = &inner.context {
|
|
|
|
return Ok(context.block_store.clone());
|
|
|
|
}
|
|
|
|
Err(VeilidAPIError::NotInitialized)
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
pub fn protected_store(&self) -> Result<ProtectedStore, VeilidAPIError> {
|
|
|
|
let inner = self.inner.lock();
|
|
|
|
if let Some(context) = &inner.context {
|
|
|
|
return Ok(context.protected_store.clone());
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
Err(VeilidAPIError::NotInitialized)
|
2021-12-08 03:09:45 +00:00
|
|
|
}
|
2022-02-07 02:18:42 +00:00
|
|
|
pub fn attachment_manager(&self) -> Result<AttachmentManager, VeilidAPIError> {
|
|
|
|
let inner = self.inner.lock();
|
|
|
|
if let Some(context) = &inner.context {
|
|
|
|
return Ok(context.attachment_manager.clone());
|
|
|
|
}
|
|
|
|
Err(VeilidAPIError::NotInitialized)
|
|
|
|
}
|
|
|
|
pub fn network_manager(&self) -> Result<NetworkManager, VeilidAPIError> {
|
|
|
|
let inner = self.inner.lock();
|
|
|
|
if let Some(context) = &inner.context {
|
|
|
|
return Ok(context.attachment_manager.network_manager());
|
|
|
|
}
|
|
|
|
Err(VeilidAPIError::NotInitialized)
|
|
|
|
}
|
|
|
|
pub fn rpc_processor(&self) -> Result<RPCProcessor, VeilidAPIError> {
|
|
|
|
let inner = self.inner.lock();
|
|
|
|
if let Some(context) = &inner.context {
|
|
|
|
return Ok(context.attachment_manager.network_manager().rpc_processor());
|
|
|
|
}
|
|
|
|
Err(VeilidAPIError::NotInitialized)
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
// Attach/Detach
|
|
|
|
|
2022-01-18 17:33:14 +00:00
|
|
|
// get a full copy of the current state
|
|
|
|
pub async fn get_state(&self) -> Result<VeilidState, VeilidAPIError> {
|
2021-12-08 03:09:45 +00:00
|
|
|
let attachment_manager = self.attachment_manager()?;
|
2022-05-16 15:52:48 +00:00
|
|
|
let network_manager = attachment_manager.network_manager();
|
|
|
|
|
|
|
|
let attachment = attachment_manager.get_veilid_state();
|
|
|
|
let network = network_manager.get_veilid_state();
|
|
|
|
|
2022-01-18 17:33:14 +00:00
|
|
|
Ok(VeilidState {
|
2022-05-16 15:52:48 +00:00
|
|
|
attachment,
|
|
|
|
network,
|
2022-01-18 17:33:14 +00:00
|
|
|
})
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-05-16 15:52:48 +00:00
|
|
|
// get network connectedness
|
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
// connect to the network
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", err, skip_all)]
|
2021-12-08 03:09:45 +00:00
|
|
|
pub async fn attach(&self) -> Result<(), VeilidAPIError> {
|
|
|
|
let attachment_manager = self.attachment_manager()?;
|
2022-03-09 03:32:12 +00:00
|
|
|
attachment_manager
|
|
|
|
.request_attach()
|
|
|
|
.await
|
|
|
|
.map_err(|e| VeilidAPIError::Internal { message: e })
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// disconnect from the network
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", err, skip_all)]
|
2021-12-08 03:09:45 +00:00
|
|
|
pub async fn detach(&self) -> Result<(), VeilidAPIError> {
|
|
|
|
let attachment_manager = self.attachment_manager()?;
|
2022-03-09 03:32:12 +00:00
|
|
|
attachment_manager
|
|
|
|
.request_detach()
|
|
|
|
.await
|
|
|
|
.map_err(|e| VeilidAPIError::Internal { message: e })
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-02-01 03:47:17 +00:00
|
|
|
// Change api logging level if it is enabled
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(skip(self))]
|
2022-06-08 01:31:05 +00:00
|
|
|
pub async fn change_api_log_level(&self, log_level: VeilidConfigLogLevel) {
|
|
|
|
ApiTracingLayer::change_api_log_level(log_level.to_veilid_log_level());
|
2022-02-01 03:47:17 +00:00
|
|
|
}
|
|
|
|
|
2021-11-22 16:28:30 +00:00
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
// Direct Node Access (pretty much for testing only)
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", err, skip(self))]
|
2022-05-11 01:49:42 +00:00
|
|
|
pub async fn status(&self, node_id: NodeId) -> Result<StatusAnswer, VeilidAPIError> {
|
2021-12-08 03:09:45 +00:00
|
|
|
let rpc = self.rpc_processor()?;
|
2021-11-22 16:28:30 +00:00
|
|
|
let routing_table = rpc.routing_table();
|
|
|
|
let node_ref = match routing_table.lookup_node_ref(node_id.key) {
|
2022-02-09 14:47:36 +00:00
|
|
|
None => return Err(VeilidAPIError::NodeNotFound { node_id }),
|
2021-11-22 16:28:30 +00:00
|
|
|
Some(nr) => nr,
|
|
|
|
};
|
2022-05-11 01:49:42 +00:00
|
|
|
let status_answer = rpc
|
|
|
|
.rpc_call_status(node_ref)
|
2021-11-22 16:28:30 +00:00
|
|
|
.await
|
|
|
|
.map_err(map_rpc_error!())?;
|
2022-05-11 01:49:42 +00:00
|
|
|
Ok(status_answer)
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", err, skip(self))]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn validate_dial_info(
|
|
|
|
&self,
|
|
|
|
node_id: NodeId,
|
|
|
|
dial_info: DialInfo,
|
|
|
|
redirect: bool,
|
|
|
|
) -> Result<bool, VeilidAPIError> {
|
2021-12-08 03:09:45 +00:00
|
|
|
let rpc = self.rpc_processor()?;
|
2021-11-22 16:28:30 +00:00
|
|
|
let routing_table = rpc.routing_table();
|
|
|
|
let node_ref = match routing_table.lookup_node_ref(node_id.key) {
|
2022-02-09 14:47:36 +00:00
|
|
|
None => return Err(VeilidAPIError::NodeNotFound { node_id }),
|
2021-11-22 16:28:30 +00:00
|
|
|
Some(nr) => nr,
|
|
|
|
};
|
2022-05-28 14:07:57 +00:00
|
|
|
rpc.rpc_call_validate_dial_info(node_ref.clone(), dial_info, redirect)
|
2021-11-22 16:28:30 +00:00
|
|
|
.await
|
|
|
|
.map_err(map_rpc_error!())
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", err, skip(self))]
|
2022-04-16 15:18:54 +00:00
|
|
|
pub async fn search_dht(&self, node_id: NodeId) -> Result<PeerInfo, VeilidAPIError> {
|
2021-12-08 03:09:45 +00:00
|
|
|
let rpc_processor = self.rpc_processor()?;
|
|
|
|
let config = self.config()?;
|
2021-11-22 16:28:30 +00:00
|
|
|
let (count, fanout, timeout) = {
|
|
|
|
let c = config.get();
|
|
|
|
(
|
|
|
|
c.network.dht.resolve_node_count,
|
|
|
|
c.network.dht.resolve_node_fanout,
|
2022-01-27 14:53:01 +00:00
|
|
|
c.network.dht.resolve_node_timeout_ms.map(ms_to_us),
|
2021-11-22 16:28:30 +00:00
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
let node_ref = rpc_processor
|
|
|
|
.search_dht_single_key(node_id.key, count, fanout, timeout)
|
|
|
|
.await
|
|
|
|
.map_err(map_rpc_error!())?;
|
|
|
|
|
2022-04-16 15:18:54 +00:00
|
|
|
let answer = node_ref.peer_info();
|
2022-05-11 01:49:42 +00:00
|
|
|
if let Some(answer) = answer {
|
|
|
|
Ok(answer)
|
|
|
|
} else {
|
|
|
|
Err(VeilidAPIError::NoPeerInfo {
|
|
|
|
node_id: NodeId::new(node_ref.node_id()),
|
|
|
|
})
|
|
|
|
}
|
2021-11-22 16:28:30 +00:00
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", err, skip(self))]
|
2022-04-16 15:18:54 +00:00
|
|
|
pub async fn search_dht_multi(&self, node_id: NodeId) -> Result<Vec<PeerInfo>, VeilidAPIError> {
|
2021-12-08 03:09:45 +00:00
|
|
|
let rpc_processor = self.rpc_processor()?;
|
|
|
|
let config = self.config()?;
|
2021-11-22 16:28:30 +00:00
|
|
|
let (count, fanout, timeout) = {
|
|
|
|
let c = config.get();
|
|
|
|
(
|
|
|
|
c.network.dht.resolve_node_count,
|
|
|
|
c.network.dht.resolve_node_fanout,
|
2022-01-27 14:53:01 +00:00
|
|
|
c.network.dht.resolve_node_timeout_ms.map(ms_to_us),
|
2021-11-22 16:28:30 +00:00
|
|
|
)
|
|
|
|
};
|
|
|
|
|
|
|
|
let node_refs = rpc_processor
|
|
|
|
.search_dht_multi_key(node_id.key, count, fanout, timeout)
|
|
|
|
.await
|
|
|
|
.map_err(map_rpc_error!())?;
|
|
|
|
|
2022-05-11 01:49:42 +00:00
|
|
|
let answer = node_refs.iter().filter_map(|x| x.peer_info()).collect();
|
2021-11-22 16:28:30 +00:00
|
|
|
|
|
|
|
Ok(answer)
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
// Safety / Private Route Handling
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", err, skip(self))]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn new_safety_route_spec(
|
|
|
|
&self,
|
|
|
|
_hops: u8,
|
|
|
|
) -> Result<SafetyRouteSpec, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", err, skip(self))]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn new_private_route_spec(
|
|
|
|
&self,
|
|
|
|
_hops: u8,
|
|
|
|
) -> Result<PrivateRouteSpec, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
// Routing Contexts
|
|
|
|
//
|
|
|
|
// Safety route specified here is for _this_ node's anonymity as a sender, used via the 'route' operation
|
|
|
|
// Private route specified here is for _this_ node's anonymity as a receiver, passed out via the 'respond_to' field for replies
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(skip(self))]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn safe_private(
|
|
|
|
&self,
|
|
|
|
safety_route_spec: SafetyRouteSpec,
|
|
|
|
private_route_spec: PrivateRouteSpec,
|
|
|
|
) -> RoutingContext {
|
|
|
|
self.routing_context(RoutingContextOptions {
|
|
|
|
safety_route_spec: Some(safety_route_spec),
|
|
|
|
private_route_spec: Some(private_route_spec),
|
|
|
|
})
|
|
|
|
.await
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", skip(self))]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn safe_public(&self, safety_route_spec: SafetyRouteSpec) -> RoutingContext {
|
|
|
|
self.routing_context(RoutingContextOptions {
|
|
|
|
safety_route_spec: Some(safety_route_spec),
|
|
|
|
private_route_spec: None,
|
|
|
|
})
|
|
|
|
.await
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", skip(self))]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn unsafe_private(&self, private_route_spec: PrivateRouteSpec) -> RoutingContext {
|
|
|
|
self.routing_context(RoutingContextOptions {
|
|
|
|
safety_route_spec: None,
|
|
|
|
private_route_spec: Some(private_route_spec),
|
|
|
|
})
|
|
|
|
.await
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", skip(self))]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn unsafe_public(&self) -> RoutingContext {
|
|
|
|
self.routing_context(RoutingContextOptions {
|
|
|
|
safety_route_spec: None,
|
|
|
|
private_route_spec: None,
|
|
|
|
})
|
|
|
|
.await
|
|
|
|
}
|
2022-06-10 21:07:10 +00:00
|
|
|
|
|
|
|
#[instrument(level = "debug", skip(self))]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn routing_context(&self, options: RoutingContextOptions) -> RoutingContext {
|
|
|
|
RoutingContext::new(self.clone(), options)
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////
|
|
|
|
// Tunnel Building
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", err, skip(self))]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn start_tunnel(
|
|
|
|
&self,
|
|
|
|
_endpoint_mode: TunnelMode,
|
|
|
|
_depth: u8,
|
|
|
|
) -> Result<PartialTunnel, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", err, skip(self))]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn complete_tunnel(
|
|
|
|
&self,
|
|
|
|
_endpoint_mode: TunnelMode,
|
|
|
|
_depth: u8,
|
|
|
|
_partial_tunnel: PartialTunnel,
|
|
|
|
) -> Result<FullTunnel, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
|
2022-06-10 21:07:10 +00:00
|
|
|
#[instrument(level = "debug", err, skip(self))]
|
2021-11-22 16:28:30 +00:00
|
|
|
pub async fn cancel_tunnel(&self, _tunnel_id: TunnelId) -> Result<bool, VeilidAPIError> {
|
|
|
|
panic!("unimplemented");
|
|
|
|
}
|
|
|
|
}
|