use std::ops::Deref;
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::MutexGuard;
use crate::api::client_address::ClientAddress;
#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct PortForward {
pub id: i32,
pub from: HostPortDefinition,
pub to: HostPortDefinition,
pub state: PortForwardState,
pub checked: bool,
}
#[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)]
pub struct PortForwardState(Arc<Mutex<PortForwardStateImpl>>);
impl PortForwardState {
pub fn lock(&self) -> MutexGuard<'_, PortForwardStateImpl> {
self.0.lock().expect("PortForwardState")
}
}
impl PartialEq for PortForwardState {
fn eq(&self, _other: &Self) -> bool {
true
}
}
impl Eq for PortForwardState {}
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
pub struct PortForwardStateImpl {
pub count: i32,
pub status: PortForwardStatus,
}
#[derive(Debug, Default, serde::Serialize, serde::Deserialize)]
pub enum PortForwardStatus {
#[default]
Pending,
Up,
Offline,
Failed(String),
}
#[derive(Clone, Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(transparent)]
pub struct HostPortDefinition(Arc<HostPortDefinitionImpl>);
#[derive(Debug, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct HostPortDefinitionImpl {
pub forwarded_remote: ClientAddress,
pub host: String,
pub port: u16,
}
impl HostPortDefinition {
pub fn new(forwarded_remote: ClientAddress, host: String, port: u16) -> Self {
Self(Arc::new(HostPortDefinitionImpl {
forwarded_remote,
host,
port,
}))
}
}
impl Deref for HostPortDefinition {
type Target = HostPortDefinitionImpl;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::fmt::Display for HostPortDefinition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let forwarded_remote = self.forwarded_remote();
let host = &self.host;
let port = self.port;
write!(f, "{forwarded_remote}:{host}:{port}")
}
}
#[cfg(feature = "client")]
mod server {
use terrazzo::html;
use terrazzo::prelude::*;
use super::HostPortDefinition;
impl HostPortDefinition {
#[html]
pub fn show(&self) -> XElement {
let forwarded_remote = self.forwarded_remote();
let host = &self.host;
let port = self.port;
span(
span("{forwarded_remote}", class = super::super::ui::TAG),
":",
span("{host}", class = super::super::ui::TAG),
":",
span("{port}", class = super::super::ui::TAG),
)
}
}
}
impl HostPortDefinition {
fn forwarded_remote(&self) -> String {
if self.forwarded_remote.is_empty() {
"Local".to_string()
} else {
self.forwarded_remote.to_string()
}
}
}