1use crate::{
2 id::ShortId,
3 multiaddr::Multiaddr,
4 tls::{TlsState, TlsTermination},
5};
6use serde_derive::{Deserialize, Serialize};
7use std::{
8 net::IpAddr,
9 time::{Duration, SystemTime},
10};
11use utoipa::ToSchema;
12
13#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
14#[serde(rename_all = "snake_case")]
15pub enum SocketState {
16 Listening,
17 Inactive,
18 AddressAlreadyInUse,
19 PermissionDenied,
20 AddressNotAvailable,
21 Error,
22 #[default]
23 Unknown,
24}
25
26#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
27pub struct PortStatus {
28 pub state: PortState,
29 #[serde(
30 serialize_with = "serialize_started_at",
31 deserialize_with = "deserialize_started_at"
32 )]
33 #[schema(value_type = Option<u64>)]
34 pub started_at: Option<SystemTime>,
35}
36
37#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
38pub struct PortState {
39 pub socket: SocketState,
40 pub tls: Option<TlsState>,
41}
42
43fn serialize_started_at<S>(
44 started_at: &Option<SystemTime>,
45 serializer: S,
46) -> Result<S::Ok, S::Error>
47where
48 S: serde::Serializer,
49{
50 if let Some(started_at) = started_at {
51 let started_at = started_at
52 .duration_since(SystemTime::UNIX_EPOCH)
53 .unwrap()
54 .as_secs();
55 serializer.serialize_some(&started_at)
56 } else {
57 serializer.serialize_none()
58 }
59}
60
61fn deserialize_started_at<'de, D>(deserializer: D) -> Result<Option<SystemTime>, D::Error>
62where
63 D: serde::Deserializer<'de>,
64{
65 use serde::Deserialize;
66 let started_at = Option::<u64>::deserialize(deserializer)?;
67 if let Some(started_at) = started_at {
68 Ok(Some(
69 SystemTime::UNIX_EPOCH + Duration::from_secs(started_at),
70 ))
71 } else {
72 Ok(None)
73 }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
77pub struct UpstreamServer {
78 #[schema(value_type = String, example = "/dns/example.com/tcp/8080")]
79 pub addr: Multiaddr,
80}
81
82#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
83pub struct PortEntry {
84 pub id: ShortId,
85 #[schema(inline)]
86 #[serde(flatten)]
87 pub port: Port,
88}
89
90impl From<(ShortId, Port)> for PortEntry {
91 fn from((id, port): (ShortId, Port)) -> Self {
92 Self { id, port }
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
97pub struct Port {
98 #[serde(default = "default_active", skip_serializing_if = "is_true")]
99 pub active: bool,
100 #[serde(default, skip_serializing_if = "String::is_empty")]
101 pub name: String,
102 #[schema(value_type = String, example = "/ip4/127.0.0.1/tcp/8080")]
103 pub listen: Multiaddr,
104 #[serde(flatten, default)]
105 pub opts: PortOptions,
106}
107
108fn default_active() -> bool {
109 true
110}
111
112fn is_true(b: &bool) -> bool {
113 *b
114}
115
116impl From<PortEntry> for (ShortId, Port) {
117 fn from(entry: PortEntry) -> Self {
118 (entry.id, entry.port)
119 }
120}
121
122#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
123pub struct PortOptions {
124 #[serde(default, skip_serializing_if = "Option::is_none")]
125 pub tls_termination: Option<TlsTermination>,
126}
127
128#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
129pub struct NetworkInterface {
130 pub name: String,
131 pub addrs: Vec<NetworkAddr>,
132 pub mac: Option<String>,
133}
134
135#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
136pub struct NetworkAddr {
137 #[schema(value_type = String, example = "127.0.0.1")]
138 pub ip: IpAddr,
139 #[schema(value_type = String, example = "255.255.255.0")]
140 pub mask: Option<IpAddr>,
141}