libsubconverter/parser/explodes/
hysteria2.rs1use crate::{models::HYSTERIA2_DEFAULT_GROUP, utils::url_decode, Proxy};
2use url::Url;
3
4pub fn explode_hysteria2(hysteria2: &str, node: &mut Proxy) -> bool {
6 if !hysteria2.starts_with("hysteria2://") && !hysteria2.starts_with("hy2://") {
8 return false;
9 }
10
11 let url = match Url::parse(hysteria2) {
13 Ok(url) => url,
14 Err(_) => return false,
15 };
16
17 let host = url.host_str().unwrap_or("");
19 let port = url.port().unwrap_or(443);
20
21 let password = url.username();
23
24 let mut up_speed = None;
26 let mut down_speed = None;
27 let mut obfs = String::new();
28 let mut obfs_param = String::new();
29 let mut sni = String::new();
30 let mut fingerprint = String::new();
31 let mut ca = String::new();
32 let mut ca_str = String::new();
33 let mut cwnd = None;
34 let mut allow_insecure = None;
35 let mut ports = String::new();
36 let mut alpn = Vec::new();
37
38 for (key, value) in url.query_pairs() {
39 match key.as_ref() {
40 "up" => up_speed = value.parse::<u32>().ok(),
41 "down" => down_speed = value.parse::<u32>().ok(),
42 "obfs" => obfs = url_decode(&value),
43 "obfs-password" => obfs_param = url_decode(&value),
44 "sni" => sni = url_decode(&value),
45 "insecure" => {
46 allow_insecure =
47 Some(value.as_ref() == "1" || value.as_ref().to_lowercase() == "true")
48 }
49 "fingerprint" => fingerprint = url_decode(&value),
50 "ca" => ca = url_decode(&value),
51 "caStr" => ca_str = url_decode(&value),
52 "ports" => ports = url_decode(&value),
53 "mport" => ports = url_decode(&value),
54 "cwnd" => cwnd = value.parse::<u32>().ok(),
55 "alpn" => {
56 for a in url_decode(&value).split(',') {
57 alpn.push(a.to_string());
58 }
59 }
60 _ => {}
61 }
62 }
63
64 let remark = url_decode(url.fragment().unwrap_or(""));
66
67 let remark_str = if remark.is_empty() {
69 format!("{} ({})", host, port)
70 } else {
71 remark.to_string()
72 };
73
74 *node = Proxy::hysteria2_construct(
76 HYSTERIA2_DEFAULT_GROUP.to_string(),
77 remark_str,
78 host.to_string(),
79 port,
80 Some(ports),
81 up_speed,
82 down_speed,
83 password.to_string(),
84 Some(obfs),
85 Some(obfs_param),
86 Some(sni),
87 Some(fingerprint),
88 alpn,
89 Some(ca),
90 Some(ca_str),
91 cwnd,
92 None,
93 allow_insecure,
94 None,
95 );
96
97 true
98}
99
100pub fn explode_std_hysteria2(hysteria2: &str, node: &mut Proxy) -> bool {
102 if !hysteria2.starts_with("hy2://") {
104 return false;
105 }
106
107 let url = match Url::parse(hysteria2) {
109 Ok(url) => url,
110 Err(_) => return false,
111 };
112
113 let host = url.host_str().unwrap_or("");
115 let port = url.port().unwrap_or(443);
116
117 let password = url.username();
119
120 let mut up_speed = None;
122 let mut down_speed = None;
123 let mut obfs = String::new();
124 let mut obfs_param = String::new();
125 let mut sni = String::new();
126 let mut fingerprint = String::new();
127 let mut ca = String::new();
128 let ca_str = String::new();
129 let mut cwnd = None;
130 let mut allow_insecure = None;
131 let mut ports = String::new();
132 let mut alpn = Vec::new();
133
134 for (key, value) in url.query_pairs() {
135 let value_decoded = url_decode(&value);
136 match key.as_ref() {
137 "bandwidth" => {
138 let parts: Vec<&str> = value_decoded.split(',').collect();
139 if parts.len() >= 1 {
140 up_speed = parts[0].parse::<u32>().ok();
141 }
142 if parts.len() >= 2 {
143 down_speed = parts[1].parse::<u32>().ok();
144 }
145 }
146 "obfs" => obfs = value_decoded,
147 "obfs-password" => obfs_param = value_decoded,
148 "sni" => sni = value_decoded,
149 "insecure" => {
150 allow_insecure =
151 Some(value.as_ref() == "1" || value.as_ref().to_lowercase() == "true")
152 }
153 "pinSHA256" => fingerprint = value_decoded,
154 "ca" => ca = value_decoded,
155 "ports" => ports = value_decoded,
156 "cwnd" => cwnd = value.parse::<u32>().ok(),
157 "alpn" => {
158 for a in value_decoded.split(',') {
159 alpn.push(a.to_string());
160 }
161 }
162 _ => {}
163 }
164 }
165
166 let remark = url_decode(url.fragment().unwrap_or(""));
168
169 let remark_str = if remark.is_empty() {
171 format!("{} ({})", host, port)
172 } else {
173 remark.to_string()
174 };
175
176 *node = Proxy::hysteria2_construct(
178 HYSTERIA2_DEFAULT_GROUP.to_string(),
179 remark_str,
180 host.to_string(),
181 port,
182 Some(ports),
183 up_speed,
184 down_speed,
185 password.to_string(),
186 Some(obfs),
187 Some(obfs_param),
188 Some(sni),
189 Some(fingerprint),
190 alpn,
191 Some(ca),
192 Some(ca_str),
193 cwnd,
194 None,
195 allow_insecure,
196 None,
197 );
198
199 true
200}