use std::{collections::BTreeMap, fmt, sync::Arc};
use anyhow::{ensure, Result};
use serde::{Deserialize, Serialize};
use super::RelayUrl;
use crate::defaults::DEFAULT_STUN_PORT;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RelayMode {
Disabled,
Default,
Staging,
Custom(RelayMap),
}
impl RelayMode {
pub fn relay_map(&self) -> RelayMap {
match self {
RelayMode::Disabled => RelayMap::empty(),
RelayMode::Default => crate::defaults::prod::default_relay_map(),
RelayMode::Staging => crate::defaults::staging::default_relay_map(),
RelayMode::Custom(relay_map) => relay_map.clone(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RelayMap {
nodes: Arc<BTreeMap<RelayUrl, Arc<RelayNode>>>,
}
impl RelayMap {
pub fn urls(&self) -> impl Iterator<Item = &RelayUrl> {
self.nodes.keys()
}
pub fn empty() -> Self {
Self {
nodes: Default::default(),
}
}
pub fn nodes(&self) -> impl Iterator<Item = &Arc<RelayNode>> {
self.nodes.values()
}
pub fn contains_node(&self, url: &RelayUrl) -> bool {
self.nodes.contains_key(url)
}
pub fn get_node(&self, url: &RelayUrl) -> Option<&Arc<RelayNode>> {
self.nodes.get(url)
}
pub fn len(&self) -> usize {
self.nodes.len()
}
pub fn is_empty(&self) -> bool {
self.nodes.is_empty()
}
pub fn default_from_node(url: RelayUrl, stun_port: u16) -> Self {
let mut nodes = BTreeMap::new();
nodes.insert(
url.clone(),
RelayNode {
url,
stun_only: false,
stun_port,
}
.into(),
);
RelayMap {
nodes: Arc::new(nodes),
}
}
pub fn from_url(url: RelayUrl) -> Self {
Self::default_from_node(url, DEFAULT_STUN_PORT)
}
pub fn from_nodes(value: impl IntoIterator<Item = RelayNode>) -> Result<Self> {
let mut map = BTreeMap::new();
for node in value.into_iter() {
ensure!(!map.contains_key(&node.url), "Duplicate node url");
map.insert(node.url.clone(), node.into());
}
Ok(RelayMap { nodes: map.into() })
}
}
impl fmt::Display for RelayMap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self, f)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, PartialOrd, Ord)]
pub struct RelayNode {
pub url: RelayUrl,
pub stun_only: bool,
pub stun_port: u16,
}
impl fmt::Display for RelayNode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.url)
}
}