pub mod discovery;
pub mod types;
use std::collections::HashMap;
use std::sync::Mutex;
use tokio::sync::broadcast;
pub use types::*;
use crate::network::{NetworkProvider, ProxyAddParams};
use crate::node::{Node, NodeError};
pub(crate) struct ProxyState {
pub(crate) event_tx: broadcast::Sender<ProxyEvent>,
pub(crate) proxies: Mutex<HashMap<String, ProxyInfo>>,
}
impl ProxyState {
pub(crate) fn new() -> Self {
let (event_tx, _) = broadcast::channel(64);
Self {
event_tx,
proxies: Mutex::new(HashMap::new()),
}
}
#[allow(dead_code)]
pub(crate) fn emit_error(&self, id: String, code: String, message: String) {
let _ = self.event_tx.send(ProxyEvent::Error { id, code, message });
}
}
pub struct Proxy<'a, N: NetworkProvider + 'static> {
#[allow(dead_code)]
node: &'a Node<N>,
}
impl<'a, N: NetworkProvider + 'static> Proxy<'a, N> {
pub(crate) fn new(node: &'a Node<N>) -> Self {
Self { node }
}
fn state(&self) -> &ProxyState {
&self.node.proxy_state
}
pub fn subscribe(&self) -> broadcast::Receiver<ProxyEvent> {
self.state().event_tx.subscribe()
}
pub fn list(&self) -> Vec<ProxyInfo> {
self.state()
.proxies
.lock()
.expect("proxy state poisoned")
.values()
.cloned()
.collect()
}
pub async fn add(&self, config: ProxyConfig) -> Result<ProxyInfo, NodeError> {
let params = ProxyAddParams {
id: config.id.clone(),
name: config.name.clone(),
listen_port: config.listen_port,
target_host: config.target.host.clone(),
target_port: config.target.port,
target_scheme: config.target.scheme.clone(),
};
let result = self.node.network.proxy_add(params).await?;
let info = ProxyInfo {
id: result.id.clone(),
name: config.name,
listen_port: result.listen_port,
target: config.target,
url: result.url.clone(),
status: ProxyStatus::Running,
};
self.state()
.proxies
.lock()
.expect("proxy state poisoned")
.insert(info.id.clone(), info.clone());
let _ = self.state().event_tx.send(ProxyEvent::Started {
id: result.id,
url: result.url,
listen_port: result.listen_port,
});
Ok(info)
}
pub async fn remove(&self, id: &str) -> Result<(), NodeError> {
self.node.network.proxy_remove(id).await?;
self.state()
.proxies
.lock()
.expect("proxy state poisoned")
.remove(id);
let _ = self
.state()
.event_tx
.send(ProxyEvent::Stopped { id: id.to_string() });
Ok(())
}
}