1use std::collections::HashSet;
6
7use serde::{Deserialize, Serialize};
8
9use super::proxy_node::combined::CombinedProxy;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
15pub enum ProxyType {
16 Unknown,
17 Shadowsocks,
18 ShadowsocksR,
19 VMess,
20 Trojan,
21 Snell,
22 HTTP,
23 HTTPS,
24 Socks5,
25 WireGuard,
26 Hysteria,
27 Hysteria2,
28 Vless,
30 AnyTls,
31}
32
33impl ProxyType {
35 pub fn to_string(self) -> &'static str {
36 match self {
37 ProxyType::Shadowsocks => "SS",
38 ProxyType::ShadowsocksR => "SSR",
39 ProxyType::VMess => "VMess",
40 ProxyType::Trojan => "Trojan",
41 ProxyType::Snell => "Snell",
42 ProxyType::HTTP => "HTTP",
43 ProxyType::HTTPS => "HTTPS",
44 ProxyType::Socks5 => "SOCKS5",
45 ProxyType::WireGuard => "WireGuard",
46 ProxyType::Hysteria => "Hysteria",
47 ProxyType::Hysteria2 => "Hysteria2",
48 ProxyType::Vless => "Vless",
49 ProxyType::AnyTls => "AnyTLS",
50 ProxyType::Unknown => "Unknown",
51 }
52 }
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57#[serde(rename_all = "PascalCase")]
58pub struct Proxy {
59 pub proxy_type: ProxyType,
60 #[serde(flatten)]
61 pub combined_proxy: Option<CombinedProxy>,
62 pub id: u32,
63 pub group_id: i32,
64 pub group: String,
65 pub remark: String,
66 pub hostname: String,
67 pub port: u16,
68
69 pub username: Option<String>,
70 pub password: Option<String>,
71 pub encrypt_method: Option<String>,
72 pub plugin: Option<String>,
73 pub plugin_option: Option<String>,
75 pub protocol: Option<String>,
76 pub protocol_param: Option<String>,
77 pub obfs: Option<String>,
78 pub obfs_param: Option<String>,
79 pub user_id: Option<String>,
80 pub alter_id: u16,
81 pub transfer_protocol: Option<String>,
82 pub fake_type: Option<String>,
83 pub tls_secure: bool,
84
85 pub host: Option<String>,
86 pub path: Option<String>,
87 pub edge: Option<String>,
88
89 pub quic_secure: Option<String>,
90 pub quic_secret: Option<String>,
91
92 pub udp: Option<bool>,
93 pub tcp_fast_open: Option<bool>,
94 pub allow_insecure: Option<bool>,
95 pub tls13: Option<bool>,
96
97 pub underlying_proxy: Option<String>,
98
99 pub snell_version: u16,
100 pub server_name: Option<String>,
101
102 pub self_ip: Option<String>,
103 pub self_ipv6: Option<String>,
104 pub public_key: Option<String>,
105 pub private_key: Option<String>,
106 pub pre_shared_key: Option<String>,
107 pub dns_servers: HashSet<String>,
108 pub mtu: u16,
109 pub allowed_ips: String,
110 pub keep_alive: u16,
111 pub test_url: Option<String>,
112 pub client_id: Option<String>,
113
114 pub ports: Option<String>,
115 pub up_speed: u32,
117 pub down_speed: u32,
119 pub auth: Option<String>,
120 pub auth_str: Option<String>,
121 pub sni: Option<String>,
122 pub fingerprint: Option<String>,
123 pub ca: Option<String>,
124 pub ca_str: Option<String>,
125 pub recv_window_conn: u32,
126 pub recv_window: u32,
127 pub disable_mtu_discovery: Option<bool>,
128 pub hop_interval: u32,
129 pub alpn: HashSet<String>,
130
131 pub cwnd: u32,
132}
133
134impl Default for Proxy {
136 fn default() -> Self {
137 Proxy {
138 proxy_type: ProxyType::Unknown,
139 combined_proxy: None,
140 id: 0,
141 group_id: 0,
142 group: String::new(),
143 remark: String::new(),
144 hostname: String::new(),
145 port: 0,
146 username: None,
147 password: None,
148 encrypt_method: None,
149 plugin: None,
150 plugin_option: None,
151 protocol: None,
152 protocol_param: None,
153 obfs: None,
154 obfs_param: None,
155 user_id: None,
156 alter_id: 0,
157 transfer_protocol: None,
158 fake_type: None,
159 tls_secure: false,
160 host: None,
161 path: None,
162 edge: None,
163 quic_secure: None,
164 quic_secret: None,
165 udp: None,
166 tcp_fast_open: None,
167 allow_insecure: None,
168 tls13: None,
169 underlying_proxy: None,
170 snell_version: 0,
171 server_name: None,
172 self_ip: None,
173 self_ipv6: None,
174 public_key: None,
175 private_key: None,
176 pre_shared_key: None,
177 dns_servers: HashSet::new(),
178 mtu: 0,
179 allowed_ips: String::from("0.0.0.0/0, ::/0"),
180 keep_alive: 0,
181 test_url: None,
182 client_id: None,
183 ports: None,
184 up_speed: 0,
185 down_speed: 0,
186 auth: None,
187 auth_str: None,
188 sni: None,
189 fingerprint: None,
190 ca: None,
191 ca_str: None,
192 recv_window_conn: 0,
193 recv_window: 0,
194 disable_mtu_discovery: None,
195 hop_interval: 0,
196 alpn: HashSet::new(),
197 cwnd: 0,
198 }
199 }
200}
201#[cfg(feature = "js-runtime")]
202use rquickjs::{Ctx, IntoJs};
203#[cfg(feature = "js-runtime")]
204impl<'js> IntoJs<'js> for Proxy {
205 fn into_js(self, ctx: &Ctx<'js>) -> Result<rquickjs::Value<'js>, rquickjs::Error> {
206 let value =
207 ctx.json_parse(
208 serde_json::to_string(&self).map_err(|e| rquickjs::Error::IntoJs {
209 from: "Proxy",
210 to: "Json",
211 message: Some(e.to_string()),
212 })?,
213 )?;
214 Ok(value)
215 }
216}
217
218impl Proxy {
219 pub fn is_combined_proxy(&self) -> bool {
220 matches!(
221 self.proxy_type,
222 ProxyType::Vless | ProxyType::Shadowsocks | ProxyType::AnyTls
223 )
224 }
225
226 pub fn with_udp(mut self, udp: Option<bool>) -> Self {
228 if self.udp.is_none() {
229 self.udp = udp;
230 }
231 self
232 }
233
234 pub fn set_udp(mut self, udp: bool) -> Self {
236 self.udp = Some(udp);
237 self
238 }
239
240 pub fn with_tfo(mut self, tfo: Option<bool>) -> Self {
242 if self.tcp_fast_open.is_none() {
243 self.tcp_fast_open = tfo;
244 }
245 self
246 }
247
248 pub fn set_tfo(mut self, tfo: bool) -> Self {
250 self.tcp_fast_open = Some(tfo);
251 self
252 }
253
254 pub fn with_skip_cert_verify(mut self, scv: Option<bool>) -> Self {
256 if self.allow_insecure.is_none() {
257 self.allow_insecure = scv;
258 }
259 self
260 }
261
262 pub fn set_skip_cert_verify(mut self, scv: bool) -> Self {
264 self.allow_insecure = Some(scv);
265 self
266 }
267
268 pub fn set_remark(mut self, remark: String) -> Self {
270 self.remark = remark;
271 self
272 }
273
274 pub fn apply_default_values(
276 mut self,
277 default_udp: Option<bool>,
278 default_tfo: Option<bool>,
279 default_scv: Option<bool>,
280 ) -> Self {
281 if self.udp.is_none() {
282 self.udp = default_udp;
283 }
284
285 if self.tcp_fast_open.is_none() {
286 self.tcp_fast_open = default_tfo;
287 }
288
289 if self.allow_insecure.is_none() {
290 self.allow_insecure = default_scv;
291 }
292
293 self
294 }
295}
296
297pub const SS_DEFAULT_GROUP: &str = "SSProvider";
299pub const SSR_DEFAULT_GROUP: &str = "SSRProvider";
300pub const V2RAY_DEFAULT_GROUP: &str = "V2RayProvider";
301pub const SOCKS_DEFAULT_GROUP: &str = "SocksProvider";
302pub const HTTP_DEFAULT_GROUP: &str = "HTTPProvider";
303pub const TROJAN_DEFAULT_GROUP: &str = "TrojanProvider";
304pub const SNELL_DEFAULT_GROUP: &str = "SnellProvider";
305pub const WG_DEFAULT_GROUP: &str = "WireGuardProvider";
306pub const HYSTERIA_DEFAULT_GROUP: &str = "HysteriaProvider";
307pub const HYSTERIA2_DEFAULT_GROUP: &str = "Hysteria2Provider";