use std::collections::HashMap;
use super::{
errors::ListenAddrErrors,
identifier::derive::{digest::DigestDerivator, KeyDerivator},
};
use config::Value;
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)]
pub struct TapleSettings {
pub network: NetworkSettings,
pub node: NodeSettings,
}
#[derive(Debug, Deserialize, Clone)]
pub struct NetworkSettings {
pub listen_addr: Vec<ListenAddr>,
#[serde(rename = "knownnodes")]
pub known_nodes: Vec<String>,
#[serde(rename = "externaladdress")]
pub external_address: Vec<String>,
}
const DEFAULT_PORT: u32 = 40040;
#[derive(Debug, Deserialize, Clone)]
pub enum ListenAddr {
Memory {
port: Option<u32>,
},
IP4 {
addr: Option<std::net::Ipv4Addr>,
port: Option<u32>,
},
IP6 {
addr: Option<std::net::Ipv6Addr>,
port: Option<u32>,
},
}
impl Default for ListenAddr {
fn default() -> Self {
Self::IP4 {
addr: Some(std::net::Ipv4Addr::new(0, 0, 0, 0)),
port: Some(DEFAULT_PORT),
}
}
}
impl ListenAddr {
pub fn get_port(&self) -> Option<u32> {
match self {
Self::IP4 { port, .. } => port.clone(),
Self::IP6 { port, .. } => port.clone(),
Self::Memory { port } => port.clone(),
}
}
pub fn increment_port(&mut self, offset: u32) {
match self {
Self::IP4 { port, .. } => port.as_mut().map(|p| *p += offset),
Self::IP6 { port, .. } => port.as_mut().map(|p| *p += offset),
Self::Memory { port } => port.as_mut().map(|p| *p += offset),
};
}
pub fn to_string(&self) -> Result<String, ListenAddrErrors> {
let result = match self {
ListenAddr::Memory { port } => {
let mut result = format!("/memory");
if let Some(port) = port {
result.push_str(&format!("/{}", port));
}
result
}
ListenAddr::IP4 { addr, port } => {
let mut result = format!("/ip4");
if let Some(ip) = addr {
result.push_str(&format!(
"/{}/tcp/{}",
ip.to_string(),
port.ok_or(ListenAddrErrors::InvalidCombination)?
));
}
result
}
ListenAddr::IP6 { addr, port } => {
let mut result = format!("/ip6");
if let Some(ip) = addr {
result.push_str(&format!(
"/{}/tcp/{}",
ip.to_string(),
port.ok_or(ListenAddrErrors::InvalidCombination)?
));
}
result
}
};
Ok(result)
}
}
impl TryFrom<String> for ListenAddr {
type Error = ListenAddrErrors;
fn try_from(value: String) -> Result<Self, Self::Error> {
let mut sections = value.split("/");
let Some(data) = sections.next() else {
return Err(ListenAddrErrors::InvalidListenAddr);
};
if !data.is_empty() {
return Err(ListenAddrErrors::InvalidListenAddr);
}
let Some(protocol) = sections.next() else {
return Err(ListenAddrErrors::InvalidListenAddr);
};
match protocol {
"ip4" => {
if let Some(ip) = sections.next() {
let ip = ip
.parse::<std::net::Ipv4Addr>()
.map_err(|_| ListenAddrErrors::InvalidIP4)?;
let Some(tcp) = sections.next() else {
return Err(ListenAddrErrors::NoTransportProtocolSpecified);
};
if tcp != "tcp" {
return Err(ListenAddrErrors::NoTCP);
}
if let Some(port) = sections.next() {
let port = port
.parse::<u32>()
.map_err(|_| ListenAddrErrors::NoU32Port)?;
return Ok(ListenAddr::IP4 {
addr: Some(ip),
port: Some(port),
});
} else {
return Ok(ListenAddr::IP4 {
addr: Some(ip),
port: None,
});
}
} else {
return Ok(ListenAddr::IP4 {
addr: None,
port: None,
});
}
}
"ip6" => {
if let Some(ip) = sections.next() {
let ip = ip
.parse::<std::net::Ipv6Addr>()
.map_err(|_| ListenAddrErrors::InvalidIP6)?;
let Some(tcp) = sections.next() else {
return Err(ListenAddrErrors::NoTransportProtocolSpecified);
};
if tcp != "tcp" {
return Err(ListenAddrErrors::NoTCP);
}
if let Some(port) = sections.next() {
let port = port
.parse::<u32>()
.map_err(|_| ListenAddrErrors::NoU32Port)?;
return Ok(ListenAddr::IP6 {
addr: Some(ip),
port: Some(port),
});
} else {
return Ok(ListenAddr::IP6 {
addr: Some(ip),
port: None,
});
}
} else {
return Ok(ListenAddr::IP6 {
addr: None,
port: None,
});
}
}
"memory" => {
if let Some(port) = sections.next() {
let port = port
.parse::<u32>()
.map_err(|_| ListenAddrErrors::NoU32Port)?;
return Ok(ListenAddr::Memory { port: Some(port) });
} else {
return Ok(ListenAddr::Memory { port: None });
}
}
_ => Err(ListenAddrErrors::InvalidProtocolSpecified),
}
}
}
#[derive(Debug, Deserialize, Clone)]
pub struct AccessPoint {
#[serde(rename = "peer-id")]
pub peer_id: String,
pub addr: String,
}
#[derive(Debug, Deserialize, Clone)]
pub struct NodeSettings {
#[serde(rename = "keyderivator")]
pub key_derivator: KeyDerivator,
#[serde(rename = "secretkey")]
pub secret_key: Option<String>,
#[serde(rename = "digestderivator")]
pub digest_derivator: DigestDerivator,
#[serde(rename = "replicationfactor")]
pub replication_factor: f64,
pub timeout: u32,
#[doc(hidden)]
pub passvotation: u8,
#[cfg(feature = "evaluation")]
pub smartcontracts_directory: String,
}
impl From<AccessPoint> for Value {
fn from(data: AccessPoint) -> Self {
let mut map = HashMap::new();
map.entry("peer_id".to_owned())
.or_insert(Value::new(None, config::ValueKind::String(data.peer_id)));
map.entry("addr".to_owned())
.or_insert(Value::new(None, config::ValueKind::String(data.addr)));
Self::new(None, config::ValueKind::Table(map))
}
}
pub enum VotationType {
Normal,
AlwaysAccept,
AlwaysReject,
}
impl From<u8> for VotationType {
fn from(passvotation: u8) -> Self {
match passvotation {
2 => Self::AlwaysReject,
1 => Self::AlwaysAccept,
_ => Self::Normal,
}
}
}