veilid/veilid-core/src/veilid_api.rs

1233 lines
37 KiB
Rust
Raw Normal View History

2021-11-22 16:28:30 +00:00
pub use crate::rpc_processor::InfoAnswer;
use crate::*;
use attachment_manager::AttachmentManager;
2021-12-08 03:09:45 +00:00
use core::fmt;
2021-11-22 16:28:30 +00:00
use network_manager::NetworkManager;
2021-12-11 01:14:33 +00:00
use routing_table::*;
2021-11-22 16:28:30 +00:00
use rpc_processor::{RPCError, RPCProcessor};
use xx::*;
pub use crate::dht::key::{generate_secret, DHTKey, DHTKeySecret};
pub use crate::xx::{
IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, SystemPinBoxFuture,
ToSocketAddrs,
};
pub use alloc::string::ToString;
pub use core::str::FromStr;
/////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord)]
pub struct NodeId {
pub key: DHTKey,
}
impl NodeId {
pub fn new(key: DHTKey) -> Self {
2021-11-27 17:44:21 +00:00
Self { key }
2021-11-22 16:28:30 +00:00
}
}
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord)]
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)
},
}
}
}
#[derive(Clone, Debug, Default, PartialOrd, PartialEq, Eq, Ord)]
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
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
2021-12-04 18:18:44 +00:00
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash, Default)]
2021-11-22 16:28:30 +00:00
pub struct SenderInfo {
pub socket_address: Option<SocketAddr>,
}
#[derive(Clone, Debug, Default)]
pub struct NodeInfo {
pub can_route: bool,
pub will_route: bool,
pub can_tunnel: bool,
pub will_tunnel: bool,
pub can_signal_lease: bool,
pub will_signal_lease: bool,
pub can_relay_lease: bool,
pub will_relay_lease: bool,
pub can_validate_dial_info: bool,
pub will_validate_dial_info: bool,
}
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum ProtocolType {
UDP,
TCP,
WS,
WSS,
}
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum ProtocolAddressType {
UDPv4,
UDPv6,
TCPv4,
TCPv6,
WS,
WSS,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub enum Address {
IPV4(Ipv4Addr),
IPV6(Ipv6Addr),
Hostname(String),
}
impl Address {
pub fn from_socket_addr(sa: SocketAddr) -> Address {
match sa {
SocketAddr::V4(v4) => Address::IPV4(*v4.ip()),
SocketAddr::V6(v6) => Address::IPV6(*v6.ip()),
}
}
pub fn address_string(&self) -> String {
match self {
Address::IPV4(v4) => v4.to_string(),
Address::IPV6(v6) => v6.to_string(),
Address::Hostname(h) => h.clone(),
}
}
pub fn address_string_with_port(&self, port: u16) -> String {
match self {
Address::IPV4(v4) => format!("{}:{}", v4.to_string(), port),
Address::IPV6(v6) => format!("[{}]:{}", v6.to_string(), port),
Address::Hostname(h) => format!("{}:{}", h.clone(), port),
}
}
2021-11-28 00:56:56 +00:00
pub fn resolve(&self) -> Result<IpAddr, String> {
2021-11-22 16:28:30 +00:00
match self {
2021-11-28 00:56:56 +00:00
Self::IPV4(a) => Ok(IpAddr::V4(*a)),
Self::IPV6(a) => Ok(IpAddr::V6(*a)),
Self::Hostname(h) => h
.parse()
.map_err(|e| format!("Failed to parse hostname: {}", e)),
2021-11-22 16:28:30 +00:00
}
}
2021-11-28 00:56:56 +00:00
pub fn address(&self) -> Result<IpAddr, String> {
2021-11-22 16:28:30 +00:00
match self {
2021-11-28 00:56:56 +00:00
Self::IPV4(a) => Ok(IpAddr::V4(*a)),
Self::IPV6(a) => Ok(IpAddr::V6(*a)),
Self::Hostname(h) => Err(format!("Address not available for hostname: {}", h)),
2021-11-22 16:28:30 +00:00
}
}
2021-11-28 00:56:56 +00:00
pub fn to_socket_addr(&self, port: u16) -> Result<SocketAddr, String> {
2021-11-22 16:28:30 +00:00
let addr = self.address()?;
Ok(SocketAddr::new(addr, port))
}
}
impl core::str::FromStr for Address {
2021-11-28 00:56:56 +00:00
type Err = String;
fn from_str(host: &str) -> Result<Address, String> {
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 if !host.is_empty() {
Ok(Address::Hostname(host.to_string()))
} else {
2021-11-28 00:56:56 +00:00
Err("unable to convert address to string".to_owned())
2021-11-22 16:28:30 +00:00
}
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
pub struct DialInfoUDP {
pub address: Address,
pub port: u16,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
pub struct DialInfoTCP {
pub address: Address,
pub port: u16,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
pub struct DialInfoWS {
2021-12-09 21:55:20 +00:00
pub host: String,
2021-11-22 16:28:30 +00:00
pub port: u16,
pub path: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
pub struct DialInfoWSS {
2021-12-09 21:55:20 +00:00
pub host: String,
2021-11-22 16:28:30 +00:00
pub port: u16,
pub path: String,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)]
pub enum DialInfo {
UDP(DialInfoUDP),
TCP(DialInfoTCP),
WS(DialInfoWS),
WSS(DialInfoWSS),
}
impl DialInfo {
pub fn udp_from_socketaddr(socketaddr: SocketAddr) -> Self {
Self::UDP(DialInfoUDP {
address: Address::from_socket_addr(socketaddr),
port: socketaddr.port(),
})
}
pub fn tcp_from_socketaddr(socketaddr: SocketAddr) -> Self {
Self::TCP(DialInfoTCP {
address: Address::from_socket_addr(socketaddr),
port: socketaddr.port(),
})
}
pub fn udp(address: Address, port: u16) -> Self {
if let Address::Hostname(_) = address {
panic!("invalid address type for protocol")
}
2021-11-27 17:44:21 +00:00
Self::UDP(DialInfoUDP { address, port })
2021-11-22 16:28:30 +00:00
}
pub fn tcp(address: Address, port: u16) -> Self {
if let Address::Hostname(_) = address {
panic!("invalid address type for protocol")
}
2021-11-27 17:44:21 +00:00
Self::TCP(DialInfoTCP { address, port })
2021-11-22 16:28:30 +00:00
}
2021-12-09 21:55:20 +00:00
pub fn ws(host: String, port: u16, path: String) -> Self {
Self::WS(DialInfoWS { host, port, path })
2021-11-22 16:28:30 +00:00
}
2021-12-09 21:55:20 +00:00
pub fn wss(host: String, port: u16, path: String) -> Self {
Self::WSS(DialInfoWSS { host, port, path })
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,
}
}
pub fn protocol_address_type(&self) -> ProtocolAddressType {
match self {
Self::UDP(di) => match di.address {
Address::IPV4(_) => ProtocolAddressType::UDPv4,
Address::IPV6(_) => ProtocolAddressType::UDPv6,
Address::Hostname(_) => panic!("invalid address type for protocol"),
},
Self::TCP(di) => match di.address {
Address::IPV4(_) => ProtocolAddressType::TCPv4,
Address::IPV6(_) => ProtocolAddressType::TCPv6,
Address::Hostname(_) => panic!("invalid address type for protocol"),
},
Self::WS(_) => ProtocolAddressType::WS,
Self::WSS(_) => ProtocolAddressType::WSS,
}
}
pub fn try_udp_v4(&self) -> Option<SocketAddrV4> {
match self {
Self::UDP(v) => match v.address.to_socket_addr(v.port).ok() {
2021-11-28 00:56:56 +00:00
Some(SocketAddr::V4(v4)) => Some(v4),
_ => None,
2021-11-22 16:28:30 +00:00
},
_ => None,
}
}
pub fn try_udp_v6(&self) -> Option<SocketAddrV6> {
match self {
Self::UDP(v) => match v.address.to_socket_addr(v.port).ok() {
2021-11-28 00:56:56 +00:00
Some(SocketAddr::V6(v6)) => Some(v6),
_ => None,
2021-11-22 16:28:30 +00:00
},
_ => None,
}
}
pub fn try_tcp_v4(&self) -> Option<SocketAddrV4> {
match self {
Self::TCP(v) => match v.address.to_socket_addr(v.port).ok() {
2021-11-28 00:56:56 +00:00
Some(SocketAddr::V4(v4)) => Some(v4),
_ => None,
2021-11-22 16:28:30 +00:00
},
_ => None,
}
}
pub fn try_tcp_v6(&self) -> Option<SocketAddrV6> {
match self {
Self::TCP(v) => match v.address.to_socket_addr(v.port).ok() {
2021-11-28 00:56:56 +00:00
Some(SocketAddr::V6(v6)) => Some(v6),
_ => None,
2021-11-22 16:28:30 +00:00
},
_ => None,
}
}
pub fn try_ws(&self) -> Option<String> {
match self {
2021-12-09 21:55:20 +00:00
Self::WS(v) => Some(v.host.clone()),
2021-11-22 16:28:30 +00:00
_ => None,
}
}
pub fn try_wss(&self) -> Option<String> {
match self {
2021-12-09 21:55:20 +00:00
Self::WSS(v) => Some(v.host.clone()),
2021-11-22 16:28:30 +00:00
_ => None,
}
}
pub fn address_string(&self) -> String {
match self {
Self::UDP(di) => di.address.address_string(),
Self::TCP(di) => di.address.address_string(),
2021-12-09 21:55:20 +00:00
Self::WS(di) => di.host.clone(),
Self::WSS(di) => di.host.clone(),
2021-11-22 16:28:30 +00:00
}
}
pub fn address_string_with_port(&self) -> String {
match self {
Self::UDP(di) => di.address.address_string_with_port(di.port),
Self::TCP(di) => di.address.address_string_with_port(di.port),
2021-12-09 21:55:20 +00:00
Self::WS(di) => format!("{}:{}", di.host.clone(), di.port),
Self::WSS(di) => format!("{}:{}", di.host.clone(), di.port),
2021-11-22 16:28:30 +00:00
}
}
pub fn all_but_path(&self) -> String {
match self {
Self::UDP(di) => format!("udp://{}", di.address.address_string_with_port(di.port)),
Self::TCP(di) => format!("tcp://{}", di.address.address_string_with_port(di.port)),
2021-12-09 21:55:20 +00:00
Self::WS(di) => format!("ws://{}:{}", di.host.clone(), di.port),
Self::WSS(di) => format!("wss://{}:{}", di.host.clone(), di.port),
2021-11-22 16:28:30 +00:00
}
}
pub fn to_url_string(&self, user: Option<String>) -> String {
let user_string = match user {
Some(u) => format!("{}@", u),
None => "".to_owned(),
};
match self {
Self::UDP(di) => format!(
"udp://{}{}",
user_string,
di.address.address_string_with_port(di.port)
),
Self::TCP(di) => format!(
"tcp://{}{}",
user_string,
di.address.address_string_with_port(di.port)
),
Self::WS(di) => format!(
"ws://{}{}:{}{}",
user_string,
2021-12-09 21:55:20 +00:00
di.host.clone(),
2021-11-22 16:28:30 +00:00
di.port,
prepend_slash(di.path.clone())
),
Self::WSS(di) => format!(
"wss://{}{}:{}{}",
user_string,
2021-12-09 21:55:20 +00:00
di.host.clone(),
2021-11-22 16:28:30 +00:00
di.port,
prepend_slash(di.path.clone())
),
}
}
2021-11-28 00:56:56 +00:00
pub fn resolve(&self) -> Result<IpAddr, String> {
2021-11-22 16:28:30 +00:00
match self {
Self::UDP(di) => {
let addr = di.address.resolve()?;
2021-11-28 00:56:56 +00:00
Ok(addr)
2021-11-22 16:28:30 +00:00
}
Self::TCP(di) => {
let addr = di.address.resolve()?;
2021-11-28 00:56:56 +00:00
Ok(addr)
2021-11-22 16:28:30 +00:00
}
Self::WS(di) => {
2021-11-28 00:56:56 +00:00
let addr: IpAddr = di
2021-12-09 21:55:20 +00:00
.host
2021-11-28 00:56:56 +00:00
.parse()
2021-12-09 21:55:20 +00:00
.map_err(|e| format!("Failed to parse WS host '{}': {}", di.host, e))?;
2021-11-28 00:56:56 +00:00
Ok(addr)
2021-11-22 16:28:30 +00:00
}
Self::WSS(di) => {
2021-11-28 00:56:56 +00:00
let addr: IpAddr = di
2021-12-09 21:55:20 +00:00
.host
2021-11-28 00:56:56 +00:00
.parse()
2021-12-09 21:55:20 +00:00
.map_err(|e| format!("Failed to parse WSS host '{}': {}", di.host, e))?;
2021-11-28 00:56:56 +00:00
Ok(addr)
2021-11-22 16:28:30 +00:00
}
}
}
2021-11-28 00:56:56 +00:00
pub fn address(&self) -> Result<IpAddr, String> {
2021-11-22 16:28:30 +00:00
match self {
Self::UDP(di) => di.address.address(),
Self::TCP(di) => di.address.address(),
2021-11-28 00:56:56 +00:00
Self::WS(_) => Err("Address not available for WS protocol".to_owned()),
Self::WSS(_) => Err("Address not available for WSS protocol".to_owned()),
2021-11-22 16:28:30 +00:00
}
}
pub fn port(&self) -> u16 {
match self {
Self::UDP(di) => di.port,
Self::TCP(di) => di.port,
Self::WS(di) => di.port,
Self::WSS(di) => di.port,
}
}
2021-11-28 00:56:56 +00:00
pub fn path(&self) -> Result<String, String> {
2021-11-22 16:28:30 +00:00
match self {
2021-11-28 00:56:56 +00:00
Self::UDP(_) => Err("path not available for udp protocol".to_owned()),
Self::TCP(_) => Err("path not available for tcp protocol".to_owned()),
2021-11-22 16:28:30 +00:00
Self::WS(di) => Ok(di.path.clone()),
Self::WSS(di) => Ok(di.path.clone()),
}
}
2021-11-28 00:56:56 +00:00
pub fn to_socket_addr(&self) -> Result<SocketAddr, String> {
2021-11-22 16:28:30 +00:00
match self {
Self::UDP(di) => Ok(SocketAddr::new(di.address.address()?, di.port)),
Self::TCP(di) => Ok(SocketAddr::new(di.address.address()?, di.port)),
2021-11-28 00:56:56 +00:00
Self::WS(_) => Err("Can not directly convert WS hostname to socket addr".to_owned()),
Self::WSS(_) => Err("Can not directly convert WSS hostname to socket addr".to_owned()),
2021-11-22 16:28:30 +00:00
}
}
pub fn is_public(&self) -> Result<bool, String> {
let addr = self
.resolve()
.map_err(|_| "failed to resolve address".to_owned())?;
Ok(ipaddr_is_global(&addr))
}
pub fn is_private(&self) -> Result<bool, String> {
let addr = self
.resolve()
.map_err(|_| "failed to resolve address".to_owned())?;
Ok(match addr {
IpAddr::V4(a) => ipv4addr_is_private(&a),
IpAddr::V6(a) => ipv6addr_is_unicast_site_local(&a),
})
}
pub fn is_valid(&self) -> Result<bool, String> {
Ok(self.is_public()? || self.is_private()?)
}
pub fn is_loopback(&self) -> Result<bool, String> {
let addr = self
.resolve()
.map_err(|_| "failed to resolve address".to_owned())?;
Ok(ipaddr_is_loopback(&addr))
}
}
impl ToString for DialInfo {
fn to_string(&self) -> String {
self.to_url_string(None)
}
}
impl Default for DialInfo {
fn default() -> Self {
Self::UDP(DialInfoUDP {
address: Address::IPV4(Ipv4Addr::new(0, 0, 0, 0)),
port: 0u16,
})
}
}
//////////////////////////////////////////////////////////////////////////
#[derive(Clone, Copy, Debug)]
pub enum PeerScope {
All,
2021-12-08 03:09:45 +00:00
Global,
Local,
2021-11-22 16:28:30 +00:00
}
#[derive(Clone, Debug, Default)]
pub struct PeerInfo {
pub node_id: NodeId,
pub dial_infos: Vec<DialInfo>,
}
#[derive(Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct PeerAddress {
pub address: Address,
pub port: u16,
pub protocol_type: ProtocolType,
}
impl PeerAddress {
pub fn new(address: Address, port: u16, protocol_type: ProtocolType) -> Self {
Self {
2021-11-27 17:44:21 +00:00
address,
port,
protocol_type,
2021-11-22 16:28:30 +00:00
}
}
2021-11-28 00:56:56 +00:00
pub fn to_socket_addr(&self) -> Result<SocketAddr, String> {
2021-11-22 16:28:30 +00:00
self.address.to_socket_addr(self.port)
}
pub fn protocol_address_type(&self) -> ProtocolAddressType {
match self.protocol_type {
ProtocolType::UDP => match self.address {
Address::IPV4(_) => ProtocolAddressType::UDPv4,
Address::IPV6(_) => ProtocolAddressType::UDPv6,
Address::Hostname(_) => panic!("invalid address type for protocol"),
},
ProtocolType::TCP => match self.address {
Address::IPV4(_) => ProtocolAddressType::TCPv4,
Address::IPV6(_) => ProtocolAddressType::TCPv6,
Address::Hostname(_) => panic!("invalid address type for protocol"),
},
ProtocolType::WS => ProtocolAddressType::WS,
ProtocolType::WSS => ProtocolAddressType::WSS,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ConnectionDescriptor {
pub remote: PeerAddress,
pub local: Option<SocketAddr>,
}
impl ConnectionDescriptor {
pub fn new(remote: PeerAddress, local: SocketAddr) -> Self {
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,
}
}
pub fn protocol_type(&self) -> ProtocolType {
self.remote.protocol_type
}
pub fn protocol_address_type(&self) -> ProtocolAddressType {
self.remote.protocol_address_type()
}
}
//////////////////////////////////////////////////////////////////////////
#[derive(Clone, Debug, Default)]
pub struct NodeDialInfoSingle {
pub node_id: NodeId,
pub dial_info: DialInfo,
}
impl core::str::FromStr for NodeDialInfoSingle {
2021-11-28 00:56:56 +00:00
type Err = String;
fn from_str(url: &str) -> Result<NodeDialInfoSingle, String> {
2021-11-22 16:28:30 +00:00
let mut cur_url = url;
let proto;
if url.starts_with("udp://") {
cur_url = &cur_url[6..];
proto = ProtocolType::UDP;
} else if url.starts_with("tcp://") {
cur_url = &cur_url[6..];
proto = ProtocolType::TCP;
} else if url.starts_with("ws://") {
cur_url = &cur_url[5..];
proto = ProtocolType::WS;
} else if url.starts_with("wss://") {
cur_url = &cur_url[6..];
proto = ProtocolType::WSS;
} else {
2021-11-28 00:56:56 +00:00
return Err("unknown protocol".to_owned());
2021-11-22 16:28:30 +00:00
}
// parse out node id if we have one
let node_id = match cur_url.find('@') {
Some(x) => {
2021-11-28 00:56:56 +00:00
let n = NodeId::new(DHTKey::try_decode(&cur_url[0..x])?);
2021-11-22 16:28:30 +00:00
cur_url = &cur_url[x + 1..];
n
}
None => {
2021-11-28 00:56:56 +00:00
return Err("NodeDialInfoSingle is missing the node id".to_owned());
2021-11-22 16:28:30 +00:00
}
};
// parse out address
let address = match cur_url.rfind(':') {
Some(x) => {
let mut h = &cur_url[0..x];
cur_url = &cur_url[x + 1..];
match proto {
ProtocolType::WS | ProtocolType::WSS => Address::Hostname(h.to_string()),
_ => {
// peel off square brackets on ipv6 address
if x >= 2 && &h[0..1] == "[" && &h[(h.len() - 1)..] == "]" {
h = &h[1..(h.len() - 1)];
}
Address::from_str(h)?
}
}
}
None => {
2021-11-28 00:56:56 +00:00
return Err("NodeDialInfoSingle is missing the port".to_owned());
2021-11-22 16:28:30 +00:00
}
};
// parse out port
let pathstart = cur_url.find('/').unwrap_or(cur_url.len());
2021-11-28 00:56:56 +00:00
let port =
u16::from_str(&cur_url[0..pathstart]).map_err(|e| format!("port is invalid: {}", e))?;
2021-11-22 16:28:30 +00:00
cur_url = &cur_url[pathstart..];
// build NodeDialInfoSingle
Ok(NodeDialInfoSingle {
2021-11-27 17:44:21 +00:00
node_id,
2021-11-22 16:28:30 +00:00
dial_info: match proto {
ProtocolType::UDP => DialInfo::udp(address, port),
ProtocolType::TCP => DialInfo::tcp(address, port),
ProtocolType::WS => {
DialInfo::ws(address.address_string(), port, cur_url.to_string())
}
ProtocolType::WSS => {
DialInfo::wss(address.address_string(), port, cur_url.to_string())
}
},
})
}
}
impl ToString for NodeDialInfoSingle {
fn to_string(&self) -> String {
self.dial_info
.to_url_string(Some(self.node_id.key.encode()))
}
}
#[derive(Clone, Debug, Default)]
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
}
#[derive(Clone, Debug, Default)]
pub struct TransferStatsDownUp {
pub down: TransferStats,
pub up: TransferStats,
}
2021-11-22 16:28:30 +00:00
#[derive(Clone, Debug, Default)]
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
}
#[derive(Clone, Debug, Default)]
pub struct PingStats {
pub in_flight: u32, // number of pings issued that have yet to be answered
pub total_sent: u32, // number of pings that have been sent in the total_time range
pub total_returned: u32, // number of pings that have been returned by the node in the total_time range
pub consecutive_pongs: u32, // number of pongs that have been received and returned consecutively without a lost ping
pub last_pinged: Option<u64>, // when the peer was last pinged
pub first_consecutive_pong_time: Option<u64>, // the timestamp of the first pong in a series of consecutive pongs
pub recent_lost_pings: u32, // number of pings that have been lost since we lost reliability
}
#[derive(Clone, Debug, Default)]
pub struct PeerStats {
pub time_added: u64, // when the peer was added to the routing table
pub last_seen: Option<u64>, // when the peer was last seen for any reason
pub ping_stats: PingStats, // information about pings
pub latency: Option<LatencyStats>, // latencies for communications with the peer
pub transfer: TransferStatsDownUp, // Stats for communications with the peer
pub node_info: Option<NodeInfo>, // Last known node info
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>;
}
}
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
pub enum VeilidAPIError {
Timeout,
Shutdown,
NodeNotFound(NodeId),
NoDialInfo(NodeId),
Internal(String),
Unimplemented(String),
}
fn convert_rpc_error(x: RPCError) -> VeilidAPIError {
match x {
RPCError::Timeout => VeilidAPIError::Timeout,
RPCError::Unimplemented(s) => VeilidAPIError::Unimplemented(s),
RPCError::Internal(s) => VeilidAPIError::Internal(s),
RPCError::Protocol(s) => VeilidAPIError::Internal(s),
RPCError::InvalidFormat => VeilidAPIError::Internal("Invalid packet format".to_owned()),
}
}
macro_rules! map_rpc_error {
() => {
|x| convert_rpc_error(x)
};
}
#[derive(Clone, Debug, PartialOrd, PartialEq, Eq, Ord)]
pub enum TunnelMode {
Raw,
Turn,
}
type TunnelId = u64;
#[derive(Clone, Debug)]
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,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct FullTunnel {
pub id: TunnelId,
pub timeout: u64,
pub local: TunnelEndpoint,
pub remote: TunnelEndpoint,
}
#[derive(Clone, Debug, Default)]
pub struct PartialTunnel {
pub id: TunnelId,
pub timeout: u64,
pub local: TunnelEndpoint,
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(Clone, Debug, Default)]
pub struct RouteHopSpec {
pub dial_info: NodeDialInfoSingle,
}
#[derive(Clone, Debug, Default)]
pub struct PrivateRouteSpec {
//
pub public_key: DHTKey,
pub secret_key: DHTKeySecret,
pub hops: Vec<RouteHopSpec>,
}
#[derive(Clone, Debug, Default)]
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(),
}
}
}
#[derive(Clone, Debug, Default)]
pub struct RoutingContextOptions {
pub safety_route_spec: Option<SafetyRouteSpec>,
pub private_route_spec: Option<PrivateRouteSpec>,
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(Clone, Debug, Default)]
pub struct SearchDHTAnswer {
pub node_id: NodeId,
pub dial_info: Vec<DialInfo>,
}
/////////////////////////////////////////////////////////////////////////////////////////////////////
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 {
2021-12-08 03:09:45 +00:00
core: Option<VeilidCore>,
}
impl fmt::Debug for VeilidAPIInner {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"VeilidAPIInner: {}",
match self.core {
Some(_) => "active",
None => "shutdown",
}
)
}
2021-11-22 16:28:30 +00:00
}
impl Drop for VeilidAPIInner {
fn drop(&mut self) {
2021-12-08 03:09:45 +00:00
if let Some(core) = self.core.take() {
intf::spawn_local(core.shutdown()).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>>,
}
2021-12-08 03:09:45 +00:00
#[derive(Clone, Debug, Default)]
pub struct VeilidAPIWeak {
inner: Weak<Mutex<VeilidAPIInner>>,
}
impl VeilidAPIWeak {
pub fn upgrade(&self) -> Option<VeilidAPI> {
self.inner.upgrade().map(|v| VeilidAPI { inner: v })
}
}
2021-11-22 16:28:30 +00:00
impl VeilidAPI {
2021-12-08 03:09:45 +00:00
pub(crate) fn new(core: VeilidCore) -> Self {
2021-11-22 16:28:30 +00:00
Self {
2021-12-08 03:09:45 +00:00
inner: Arc::new(Mutex::new(VeilidAPIInner { core: Some(core) })),
2021-11-22 16:28:30 +00:00
}
}
2021-12-08 03:09:45 +00:00
pub fn weak(&self) -> VeilidAPIWeak {
VeilidAPIWeak {
inner: Arc::downgrade(&self.inner),
}
2021-11-22 16:28:30 +00:00
}
2021-12-08 03:09:45 +00:00
fn core(&self) -> Result<VeilidCore, VeilidAPIError> {
Ok(self
.inner
.lock()
.core
.as_ref()
.ok_or(VeilidAPIError::Shutdown)?
.clone())
2021-11-22 16:28:30 +00:00
}
2021-12-08 03:09:45 +00:00
fn config(&self) -> Result<VeilidConfig, VeilidAPIError> {
Ok(self.core()?.config())
2021-11-22 16:28:30 +00:00
}
2021-12-08 03:09:45 +00:00
fn attachment_manager(&self) -> Result<AttachmentManager, VeilidAPIError> {
Ok(self.core()?.attachment_manager())
2021-11-22 16:28:30 +00:00
}
2021-12-08 03:09:45 +00:00
fn network_manager(&self) -> Result<NetworkManager, VeilidAPIError> {
Ok(self.attachment_manager()?.network_manager())
}
fn rpc_processor(&self) -> Result<RPCProcessor, VeilidAPIError> {
Ok(self.network_manager()?.rpc_processor())
2021-11-22 16:28:30 +00:00
}
2021-12-08 03:09:45 +00:00
pub async fn shutdown(self) {
let core = { self.inner.lock().core.take() };
if let Some(core) = core {
core.shutdown().await;
2021-11-22 16:28:30 +00:00
}
2021-12-08 03:09:45 +00:00
}
pub fn is_shutdown(&self) -> bool {
self.inner.lock().core.is_none()
2021-11-22 16:28:30 +00:00
}
2021-12-11 01:14:33 +00:00
////////////////////////////////////////////////////////////////
// Debugging
async fn debug_buckets(&self, mut debug_args: Vec<String>) -> Result<String, VeilidAPIError> {
let min_state = {
if let Some(min_state) = debug_args.pop() {
if min_state == "dead" {
BucketEntryState::Dead
} else if min_state == "reliable" {
BucketEntryState::Reliable
} else {
return Err(VeilidAPIError::Internal(format!(
"Invalid argument '{}'",
min_state
)));
}
} else {
BucketEntryState::Unreliable
}
};
// Dump routing table bucket info
let rpc = self.rpc_processor()?;
let routing_table = rpc.routing_table();
Ok(routing_table.debug_info(min_state))
}
pub async fn debug(&self, what: String) -> Result<String, VeilidAPIError> {
trace!("VeilidCore::debug");
let mut out = String::new();
let mut debug_args: Vec<String> = what
.split_ascii_whitespace()
.map(|s| s.to_owned())
.collect();
if let Some(arg) = debug_args.pop() {
if arg == "buckets" {
out += self.debug_buckets(debug_args).await?.as_str();
} else {
out += ">>> Unknown command\n";
}
} else {
out += ">>> Debug commands:\n buckets [dead|reliable]\n";
}
Ok(out)
}
2021-11-22 16:28:30 +00:00
////////////////////////////////////////////////////////////////
// Attach/Detach
// issue state changed updates for updating clients
2021-12-08 03:09:45 +00:00
pub async fn send_state_update(&self) -> Result<(), VeilidAPIError> {
2021-11-22 16:28:30 +00:00
trace!("VeilidCore::send_state_update");
2021-12-08 03:09:45 +00:00
let attachment_manager = self.attachment_manager()?;
2021-11-22 16:28:30 +00:00
attachment_manager.send_state_update().await;
2021-12-08 03:09:45 +00:00
Ok(())
2021-11-22 16:28:30 +00:00
}
// connect to the network
2021-12-08 03:09:45 +00:00
pub async fn attach(&self) -> Result<(), VeilidAPIError> {
2021-11-22 16:28:30 +00:00
trace!("VeilidCore::attach");
2021-12-08 03:09:45 +00:00
let attachment_manager = self.attachment_manager()?;
2021-11-22 16:28:30 +00:00
attachment_manager.request_attach().await;
2021-12-08 03:09:45 +00:00
Ok(())
2021-11-22 16:28:30 +00:00
}
// disconnect from the network
2021-12-08 03:09:45 +00:00
pub async fn detach(&self) -> Result<(), VeilidAPIError> {
2021-11-22 16:28:30 +00:00
trace!("VeilidCore::detach");
2021-12-08 03:09:45 +00:00
let attachment_manager = self.attachment_manager()?;
2021-11-22 16:28:30 +00:00
attachment_manager.request_detach().await;
2021-12-08 03:09:45 +00:00
Ok(())
2021-11-22 16:28:30 +00:00
}
// wait for state change
// xxx: this should not use 'sleep', perhaps this function should be eliminated anyway
2021-12-08 03:09:45 +00:00
// xxx: it should really only be used for test anyway, and there is probably a better way to do this regardless
// xxx: that doesn't wait forever and can time out
pub async fn wait_for_state(&self, state: VeilidState) -> Result<(), VeilidAPIError> {
2021-11-22 16:28:30 +00:00
loop {
intf::sleep(500).await;
match state {
VeilidState::Attachment(cs) => {
2021-12-08 03:09:45 +00:00
if self.attachment_manager()?.get_state() == cs {
2021-11-22 16:28:30 +00:00
break;
}
}
}
}
2021-12-08 03:09:45 +00:00
Ok(())
2021-11-22 16:28:30 +00:00
}
////////////////////////////////////////////////////////////////
// Direct Node Access (pretty much for testing only)
pub async fn info(&self, node_id: NodeId) -> Result<InfoAnswer, 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) {
None => return Err(VeilidAPIError::NodeNotFound(node_id)),
Some(nr) => nr,
};
let info_answer = rpc
.rpc_call_info(node_ref)
.await
.map_err(map_rpc_error!())?;
Ok(info_answer)
}
pub async fn validate_dial_info(
&self,
node_id: NodeId,
dial_info: DialInfo,
redirect: bool,
alternate_port: 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) {
None => return Err(VeilidAPIError::NodeNotFound(node_id)),
Some(nr) => nr,
};
rpc.rpc_call_validate_dial_info(node_ref.clone(), dial_info, redirect, alternate_port)
.await
.map_err(map_rpc_error!())
}
pub async fn search_dht(&self, node_id: NodeId) -> Result<SearchDHTAnswer, 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,
c.network.dht.resolve_node_timeout,
)
};
let node_ref = rpc_processor
.search_dht_single_key(node_id.key, count, fanout, timeout)
.await
.map_err(map_rpc_error!())?;
let answer = node_ref.operate(|e| SearchDHTAnswer {
node_id: NodeId::new(node_ref.node_id()),
dial_info: e.dial_info(),
});
Ok(answer)
}
pub async fn search_dht_multi(
&self,
node_id: NodeId,
) -> Result<Vec<SearchDHTAnswer>, 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,
c.network.dht.resolve_node_timeout,
)
};
let node_refs = rpc_processor
.search_dht_multi_key(node_id.key, count, fanout, timeout)
.await
.map_err(map_rpc_error!())?;
let mut answer = Vec::<SearchDHTAnswer>::new();
for nr in node_refs {
let a = nr.operate(|e| SearchDHTAnswer {
node_id: NodeId::new(nr.node_id()),
dial_info: e.dial_info(),
});
answer.push(a);
}
Ok(answer)
}
////////////////////////////////////////////////////////////////
// Safety / Private Route Handling
pub async fn new_safety_route_spec(
&self,
_hops: u8,
) -> Result<SafetyRouteSpec, VeilidAPIError> {
panic!("unimplemented");
}
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
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
}
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
}
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
}
pub async fn unsafe_public(&self) -> RoutingContext {
self.routing_context(RoutingContextOptions {
safety_route_spec: None,
private_route_spec: None,
})
.await
}
pub async fn routing_context(&self, options: RoutingContextOptions) -> RoutingContext {
RoutingContext::new(self.clone(), options)
}
////////////////////////////////////////////////////////////////
// Tunnel Building
pub async fn start_tunnel(
&self,
_endpoint_mode: TunnelMode,
_depth: u8,
) -> Result<PartialTunnel, VeilidAPIError> {
panic!("unimplemented");
}
pub async fn complete_tunnel(
&self,
_endpoint_mode: TunnelMode,
_depth: u8,
_partial_tunnel: PartialTunnel,
) -> Result<FullTunnel, VeilidAPIError> {
panic!("unimplemented");
}
pub async fn cancel_tunnel(&self, _tunnel_id: TunnelId) -> Result<bool, VeilidAPIError> {
panic!("unimplemented");
}
}