1use self::{http::HttpPortContext, tcp::TcpPortContext, udp::UdpPortContext};
2use crate::server::cert_list::CertList;
3use once_cell::sync::OnceCell;
4use taxy_api::error::Error;
5use taxy_api::multiaddr::Multiaddr;
6use taxy_api::port::{PortStatus, SocketState};
7use taxy_api::{
8 port::{Port, PortEntry},
9 proxy::ProxyEntry,
10};
11
12pub mod http;
13pub mod tcp;
14pub mod tls;
15pub mod udp;
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub enum PortContextEvent {
19 SocketStateUpdated(SocketState),
20}
21
22#[derive(Debug)]
23pub struct PortContext {
24 pub entry: PortEntry,
25 pub kind: PortContextKind,
26}
27
28impl PortContext {
29 pub fn new(entry: PortEntry) -> Result<Self, Error> {
30 let kind = if entry.port.listen.is_quic() {
31 PortContextKind::Http3(HttpPortContext::new(&entry)?)
32 } else if entry.port.listen.is_udp() {
33 PortContextKind::Udp(UdpPortContext::new(&entry)?)
34 } else if entry.port.listen.is_http() {
35 PortContextKind::Http(HttpPortContext::new(&entry)?)
36 } else {
37 PortContextKind::Tcp(TcpPortContext::new(&entry)?)
38 };
39 Ok(Self { entry, kind })
40 }
41
42 pub fn reserved() -> Self {
43 Self {
44 entry: PortEntry {
45 id: "reserved".parse().unwrap(),
46 port: Port {
47 active: true,
48 name: String::new(),
49 listen: Multiaddr::default(),
50 opts: Default::default(),
51 },
52 },
53 kind: PortContextKind::Reserved,
54 }
55 }
56
57 pub fn entry(&self) -> &PortEntry {
58 &self.entry
59 }
60
61 pub fn kind(&self) -> &PortContextKind {
62 &self.kind
63 }
64
65 pub fn kind_mut(&mut self) -> &mut PortContextKind {
66 &mut self.kind
67 }
68
69 pub async fn setup(
70 &mut self,
71 ports: &[PortEntry],
72 certs: &CertList,
73 proxies: Vec<ProxyEntry>,
74 ) -> Result<(), Error> {
75 match &mut self.kind {
76 PortContextKind::Tcp(ctx) => ctx.setup(certs, proxies).await,
77 PortContextKind::Http(ctx) => ctx.setup(ports, certs, proxies).await,
78 PortContextKind::Udp(ctx) => ctx.setup(proxies).await,
79 PortContextKind::Http3(ctx) => ctx.setup(ports, certs, proxies).await,
80 PortContextKind::Reserved => Ok(()),
81 }
82 }
83
84 pub fn apply(&mut self, new: Self) {
85 match (&mut self.kind, new.kind) {
86 (PortContextKind::Tcp(old), PortContextKind::Tcp(new)) => old.apply(new),
87 (PortContextKind::Udp(old), PortContextKind::Udp(new)) => old.apply(new),
88 (PortContextKind::Http(old), PortContextKind::Http(new)) => old.apply(new),
89 (PortContextKind::Http3(old), PortContextKind::Http3(new)) => old.apply(new),
90 (old, new) => *old = new,
91 }
92 self.entry = new.entry;
93 }
94
95 pub fn event(&mut self, event: PortContextEvent) {
96 match &mut self.kind {
97 PortContextKind::Tcp(ctx) => ctx.event(event),
98 PortContextKind::Udp(ctx) => ctx.event(event),
99 PortContextKind::Http(ctx) => ctx.event(event),
100 PortContextKind::Http3(ctx) => ctx.event(event),
101 PortContextKind::Reserved => (),
102 }
103 }
104
105 pub fn status(&self) -> &PortStatus {
106 match &self.kind {
107 PortContextKind::Tcp(ctx) => ctx.status(),
108 PortContextKind::Udp(ctx) => ctx.status(),
109 PortContextKind::Http(ctx) => ctx.status(),
110 PortContextKind::Http3(ctx) => ctx.status(),
111 PortContextKind::Reserved => {
112 static STATUS: OnceCell<PortStatus> = OnceCell::new();
113 STATUS.get_or_init(PortStatus::default)
114 }
115 }
116 }
117
118 pub fn reset(&mut self) {
119 match &mut self.kind {
120 PortContextKind::Tcp(ctx) => ctx.reset(),
121 PortContextKind::Udp(ctx) => ctx.reset(),
122 PortContextKind::Http(ctx) => ctx.reset(),
123 PortContextKind::Http3(ctx) => ctx.reset(),
124 PortContextKind::Reserved => (),
125 }
126 }
127}
128
129#[derive(Debug)]
130pub enum PortContextKind {
131 Tcp(TcpPortContext),
132 Udp(UdpPortContext),
133 Http(HttpPortContext),
134 Http3(HttpPortContext),
135 Reserved,
136}