http_request/request/socket/websocket/
impl.rs1use super::*;
2
3impl WebSocket {
4 fn get_url(&self) -> String {
5 self.url.as_ref().clone()
6 }
7
8 fn generate_websocket_key() -> String {
9 let mut key_bytes: [u8; 16] = [0u8; 16];
10 let now: u64 = SystemTime::now()
11 .duration_since(UNIX_EPOCH)
12 .unwrap_or_default()
13 .as_nanos() as u64;
14 let ptr: usize = &key_bytes as *const _ as usize;
15 for (i, byte) in key_bytes.iter_mut().enumerate() {
16 *byte = ((now.wrapping_add(ptr as u64).wrapping_add(i as u64)) % 256) as u8;
17 }
18 base64_encode(&key_bytes)
19 }
20
21 fn get_headers(&self) -> Vec<(String, String)> {
22 let mut headers: Vec<(String, String)> = Vec::new();
23 for (key, value) in self.header.iter() {
24 if let Some(first_value) = value.front() {
25 headers.push((key.clone(), first_value.clone()));
26 }
27 }
28 headers
29 }
30
31 async fn connect_async_internal(&self) -> Result<(), WebSocketError> {
32 if self.connected.load(Ordering::Relaxed) {
33 return Ok(());
34 }
35 let url: String = self.get_url();
36 if url.is_empty() {
37 return Err(WebSocketError::invalid_url("URL is empty"));
38 }
39 let url_obj: HttpUrlComponents = SharedWebSocketBuilder::parse_url(&url)?;
40 if let Ok(mut config) = self.config.write() {
41 config.url_obj = url_obj;
42 }
43 let timeout_duration: Duration = Duration::from_millis(
44 self.config
45 .read()
46 .map(|config| config.timeout)
47 .unwrap_or(DEFAULT_HIGH_SECURITY_READ_TIMEOUT_MS),
48 );
49 let headers: Vec<(String, String)> = self.get_headers();
50 let mut request_builder = Request::builder().uri(&url);
51 for (key, value) in &headers {
52 request_builder = request_builder.header(key, value);
53 }
54 let request: Request = request_builder.body(()).map_err(|error| {
55 WebSocketError::invalid_url(format!("Failed to build request: {error}"))
56 })?;
57 let proxy_config: Option<ProxyConfig> = self
58 .config
59 .read()
60 .ok()
61 .and_then(|config| config.proxy.clone());
62 let ws_stream: WebSocketConnectionType = if let Some(proxy_config) = proxy_config {
63 let url_obj: HttpUrlComponents = self
64 .config
65 .read()
66 .map(|config| config.url_obj.clone())
67 .unwrap_or_default();
68 let target_host: String = url_obj.host.clone().unwrap_or_default();
69 let target_port: u16 = url_obj.port.unwrap_or_default();
70 let proxy_stream: BoxAsyncReadWrite = self
71 .get_proxy_connection_stream_async(target_host.clone(), target_port, &proxy_config)
72 .await?;
73 let proxy_tunnel_stream: WebSocketProxyTunnelStream =
74 WebSocketProxyTunnelStream::new(proxy_stream);
75 let mut proxy_request_builder = Request::builder().uri(&url);
76 proxy_request_builder = proxy_request_builder
77 .header(HOST, format!("{target_host}:{target_port}"))
78 .header(UPGRADE, "websocket")
79 .header(CONNECTION, "Upgrade")
80 .header(SEC_WEBSOCKET_VERSION, "13")
81 .header(SEC_WEBSOCKET_KEY, Self::generate_websocket_key());
82 for (key, value) in &headers {
83 proxy_request_builder = proxy_request_builder.header(key, value);
84 }
85 let protocols: Vec<String> = self
86 .config
87 .read()
88 .map(|config| config.protocols.clone())
89 .unwrap_or_default();
90 if !protocols.is_empty() {
91 proxy_request_builder =
92 proxy_request_builder.header("Sec-WebSocket-String", protocols.join(", "));
93 }
94 let proxy_request: Request = proxy_request_builder.body(()).map_err(|e| {
95 WebSocketError::invalid_url(format!("Failed to build proxy request: {e}"))
96 })?;
97 let connect_future = client_async_with_config(proxy_request, proxy_tunnel_stream, None);
98 let (ws_stream, _) = timeout(timeout_duration, connect_future)
99 .await
100 .map_err(|_| WebSocketError::timeout("Connection timeout"))?
101 .map_err(|e| {
102 let error_msg: String = e.to_string();
103 if error_msg.contains("tls")
104 || error_msg.contains("TLS")
105 || error_msg.contains("ssl")
106 || error_msg.contains("SSL")
107 || error_msg.contains("certificate")
108 || error_msg.contains("handshake")
109 {
110 WebSocketError::tls(error_msg)
111 } else {
112 WebSocketError::connection(error_msg)
113 }
114 })?;
115 WebSocketConnectionType::Proxy(ws_stream)
116 } else {
117 let connect_future = connect_async_with_config(request, None, false);
118 let (ws_stream, _) = timeout(timeout_duration, connect_future)
119 .await
120 .map_err(|_| WebSocketError::timeout("Connection timeout"))?
121 .map_err(|e| {
122 let error_msg: String = e.to_string();
123 if error_msg.contains("tls")
124 || error_msg.contains("TLS")
125 || error_msg.contains("ssl")
126 || error_msg.contains("SSL")
127 || error_msg.contains("certificate")
128 || error_msg.contains("handshake")
129 {
130 WebSocketError::tls(error_msg)
131 } else {
132 WebSocketError::connection(error_msg)
133 }
134 })?;
135 WebSocketConnectionType::Direct(ws_stream)
136 };
137 let mut connection: http_type::tokio::sync::MutexGuard<
138 '_,
139 Option<WebSocketConnectionType>,
140 > = self.connection.lock().await;
141 *connection = Some(ws_stream);
142 self.connected.store(true, Ordering::Relaxed);
143 Ok(())
144 }
145
146 async fn send_message_async(&self, message: Message) -> Result<(), WebSocketError> {
147 if !self.connected.load(Ordering::Relaxed) {
148 self.connect_async_internal().await?;
149 }
150 let mut connection: http_type::tokio::sync::MutexGuard<
151 '_,
152 Option<WebSocketConnectionType>,
153 > = self.connection.lock().await;
154 if let Some(ref mut ws_stream) = *connection {
155 ws_stream
156 .send(message)
157 .await
158 .map_err(|error: tungstenite::Error| WebSocketError::protocol(error.to_string()))?;
159 } else {
160 return Err(WebSocketError::connection("Not connected"));
161 }
162 Ok(())
163 }
164
165 fn send_message_sync(&self, message: Message) -> Result<(), WebSocketError> {
166 let rt: Runtime = Runtime::new()
167 .map_err(|error: std::io::Error| WebSocketError::io(error.to_string()))?;
168 rt.block_on(self.send_message_async(message))
169 }
170
171 async fn receive_message_async(&self) -> Result<WebSocketMessage, WebSocketError> {
172 if !self.connected.load(Ordering::Relaxed) {
173 return Err(WebSocketError::connection("Not connected"));
174 }
175 let timeout_duration: Duration = Duration::from_millis(
176 self.config
177 .read()
178 .map(|config| config.timeout)
179 .unwrap_or(DEFAULT_HIGH_SECURITY_READ_TIMEOUT_MS),
180 );
181 let mut connection: http_type::tokio::sync::MutexGuard<
182 '_,
183 Option<WebSocketConnectionType>,
184 > = self.connection.lock().await;
185 if let Some(ref mut ws_stream) = *connection {
186 let receive_future = ws_stream.next();
187 if let Some(msg_result) = timeout(timeout_duration, receive_future)
188 .await
189 .map_err(|_| WebSocketError::timeout("Receive timeout"))?
190 {
191 let message: Message = msg_result.map_err(|error: tungstenite::Error| {
192 WebSocketError::protocol(error.to_string())
193 })?;
194 return Ok(self.convert_message(message));
195 }
196 }
197 Err(WebSocketError::connection("Connection closed"))
198 }
199
200 fn receive_message_sync(&self) -> Result<WebSocketMessage, WebSocketError> {
201 let rt: Runtime = Runtime::new()
202 .map_err(|error: std::io::Error| WebSocketError::io(error.to_string()))?;
203 rt.block_on(self.receive_message_async())
204 }
205
206 fn convert_message(&self, message: Message) -> WebSocketMessage {
207 match message {
208 Message::Text(text) => WebSocketMessage::Text(text.to_string()),
209 Message::Binary(data) => WebSocketMessage::Binary(data.to_vec()),
210 Message::Ping(data) => WebSocketMessage::Ping(data.to_vec()),
211 Message::Pong(data) => WebSocketMessage::Pong(data.to_vec()),
212 Message::Close(_) => WebSocketMessage::Close,
213 Message::Frame(_) => WebSocketMessage::Close,
214 }
215 }
216
217 async fn close_async_internal(&self) -> Result<(), WebSocketError> {
218 let mut connection: http_type::tokio::sync::MutexGuard<
219 '_,
220 Option<WebSocketConnectionType>,
221 > = self.connection.lock().await;
222 if let Some(ref mut ws_stream) = *connection {
223 ws_stream
224 .send(Message::Close(None))
225 .await
226 .map_err(|error: tungstenite::Error| WebSocketError::protocol(error.to_string()))?;
227 use futures::SinkExt;
228 ws_stream
229 .close()
230 .await
231 .map_err(|error: tungstenite::Error| WebSocketError::protocol(error.to_string()))?;
232 }
233 *connection = None;
234 self.connected.store(false, Ordering::Relaxed);
235 Ok(())
236 }
237
238 fn close_sync(&self) -> Result<(), WebSocketError> {
239 let rt: Runtime = Runtime::new()
240 .map_err(|error: std::io::Error| WebSocketError::io(error.to_string()))?;
241 rt.block_on(self.close_async_internal())
242 }
243
244 async fn get_proxy_connection_stream_async(
245 &self,
246 target_host: String,
247 target_port: u16,
248 proxy_config: &ProxyConfig,
249 ) -> Result<BoxAsyncReadWrite, WebSocketError> {
250 match proxy_config.proxy_type {
251 ProxyType::Http | ProxyType::Https => {
252 self.get_http_proxy_connection_async(target_host, target_port, proxy_config)
253 .await
254 }
255 ProxyType::Socks5 => {
256 self.get_socks5_proxy_connection_async(target_host, target_port, proxy_config)
257 .await
258 }
259 }
260 }
261
262 async fn get_http_proxy_connection_async(
263 &self,
264 target_host: String,
265 target_port: u16,
266 proxy_config: &ProxyConfig,
267 ) -> Result<BoxAsyncReadWrite, WebSocketError> {
268 let proxy_host_port: (String, u16) = (proxy_config.host.clone(), proxy_config.port);
269 let tcp_stream: http_type::tokio::net::TcpStream =
270 http_type::tokio::net::TcpStream::connect(proxy_host_port)
271 .await
272 .map_err(|err| WebSocketError::connection(err.to_string()))?;
273 let mut proxy_stream: BoxAsyncReadWrite = if proxy_config.proxy_type == ProxyType::Https {
274 let roots: RootCertStore = RootCertStore {
275 roots: TLS_SERVER_ROOTS.to_vec(),
276 };
277 let tls_config: ClientConfig = ClientConfig::builder()
278 .with_root_certificates(roots)
279 .with_no_client_auth();
280 let connector: TlsConnector = TlsConnector::from(Arc::new(tls_config));
281 let dns_name: ServerName<'_> = ServerName::try_from(proxy_config.host.clone())
282 .map_err(|err| WebSocketError::tls(err.to_string()))?;
283 let tls_stream: TlsStream<http_type::tokio::net::TcpStream> = connector
284 .connect(dns_name, tcp_stream)
285 .await
286 .map_err(|err| WebSocketError::tls(err.to_string()))?;
287 Box::new(tls_stream)
288 } else {
289 Box::new(tcp_stream)
290 };
291 let connect_request: String = if let (Some(username), Some(password)) =
292 (&proxy_config.username, &proxy_config.password)
293 {
294 let auth: String = format!("{username}:{password}");
295 let auth_encoded: String = base64_encode(auth.as_bytes());
296 format!(
297 "CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\nProxy-Authorization: Basic {auth_encoded}\r\n\r\n"
298 )
299 } else {
300 format!(
301 "CONNECT {target_host}:{target_port} HTTP/1.1\r\nHost: {target_host}:{target_port}\r\n\r\n"
302 )
303 };
304 proxy_stream
305 .write_all(connect_request.as_bytes())
306 .await
307 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
308 proxy_stream
309 .flush()
310 .await
311 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
312 let mut response_buffer: [u8; 1024] = [0u8; 1024];
313 let bytes_read: usize = proxy_stream
314 .read(&mut response_buffer)
315 .await
316 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
317 let response: Cow<'_, str> = String::from_utf8_lossy(&response_buffer[..bytes_read]);
318 if !response.starts_with("HTTP/1.1 200") && !response.starts_with("HTTP/1.0 200") {
319 return Err(WebSocketError::connection(format!(
320 "Proxy connection failed: {}",
321 response.lines().next().unwrap_or("Unknown error")
322 )));
323 }
324 Ok(proxy_stream)
325 }
326
327 async fn get_socks5_proxy_connection_async(
328 &self,
329 target_host: String,
330 target_port: u16,
331 proxy_config: &ProxyConfig,
332 ) -> Result<BoxAsyncReadWrite, WebSocketError> {
333 let proxy_host_port: (String, u16) = (proxy_config.host.clone(), proxy_config.port);
334 let mut tcp_stream: http_type::tokio::net::TcpStream =
335 http_type::tokio::net::TcpStream::connect(proxy_host_port)
336 .await
337 .map_err(|err| WebSocketError::connection(err.to_string()))?;
338 let auth_methods: Vec<u8> =
339 if proxy_config.username.is_some() && proxy_config.password.is_some() {
340 vec![0x05, 0x02, 0x00, 0x02]
341 } else {
342 vec![0x05, 0x01, 0x00]
343 };
344 tcp_stream
345 .write_all(&auth_methods)
346 .await
347 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
348 let mut response: [u8; 2] = [0u8; 2];
349 tcp_stream
350 .read_exact(&mut response)
351 .await
352 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
353 if response[0] != 0x05 {
354 return Err(WebSocketError::protocol("Invalid SOCKS5 response"));
355 }
356 match response[1] {
357 0x00 => {}
358 0x02 => {
359 if let (Some(username), Some(password)) =
360 (&proxy_config.username, &proxy_config.password)
361 {
362 let mut auth_request = vec![0x01];
363 auth_request.push(username.len() as u8);
364 auth_request.extend_from_slice(username.as_bytes());
365 auth_request.push(password.len() as u8);
366 auth_request.extend_from_slice(password.as_bytes());
367
368 tcp_stream
369 .write_all(&auth_request)
370 .await
371 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
372
373 let mut auth_response = [0u8; 2];
374 tcp_stream
375 .read_exact(&mut auth_response)
376 .await
377 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
378
379 if auth_response[1] != 0x00 {
380 return Err(WebSocketError::protocol("SOCKS5 authentication failed"));
381 }
382 } else {
383 return Err(WebSocketError::protocol(
384 "SOCKS5 proxy requires authentication",
385 ));
386 }
387 }
388 0xFF => {
389 return Err(WebSocketError::protocol(
390 "No acceptable SOCKS5 authentication methods",
391 ));
392 }
393 _ => {
394 return Err(WebSocketError::protocol(
395 "Unsupported SOCKS5 authentication method",
396 ));
397 }
398 }
399 let mut connect_request: Vec<u8> = vec![0x05, 0x01, 0x00];
400 if target_host.parse::<Ipv4Addr>().is_ok() {
401 connect_request.push(0x01);
402 let ip: Ipv4Addr = target_host.parse().unwrap();
403 connect_request.extend_from_slice(&ip.octets());
404 } else if target_host.parse::<Ipv6Addr>().is_ok() {
405 connect_request.push(0x04);
406 let ip: Ipv6Addr = target_host.parse().unwrap();
407 connect_request.extend_from_slice(&ip.octets());
408 } else {
409 connect_request.push(0x03);
410 connect_request.push(target_host.len() as u8);
411 connect_request.extend_from_slice(target_host.as_bytes());
412 }
413 connect_request.extend_from_slice(&target_port.to_be_bytes());
414 tcp_stream
415 .write_all(&connect_request)
416 .await
417 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
418
419 let mut connect_response: [u8; 4] = [0u8; 4];
420 tcp_stream
421 .read_exact(&mut connect_response)
422 .await
423 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
424
425 if connect_response[0] != 0x05 || connect_response[1] != 0x00 {
426 return Err(WebSocketError::protocol(format!(
427 "SOCKS5 connection failed with code: {}",
428 connect_response[1]
429 )));
430 }
431 match connect_response[3] {
432 0x01 => {
433 let mut skip: [u8; 6] = [0u8; 6];
434 tcp_stream
435 .read_exact(&mut skip)
436 .await
437 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
438 }
439 0x03 => {
440 let mut len: [u8; 1] = [0u8; 1];
441 tcp_stream
442 .read_exact(&mut len)
443 .await
444 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
445 let mut skip: Vec<u8> = vec![0u8; len[0] as usize + 2];
446 tcp_stream
447 .read_exact(&mut skip)
448 .await
449 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
450 }
451 0x04 => {
452 let mut skip: [u8; 18] = [0u8; 18];
453 tcp_stream
454 .read_exact(&mut skip)
455 .await
456 .map_err(|err: std::io::Error| WebSocketError::protocol(err.to_string()))?;
457 }
458 _ => {
459 return Err(WebSocketError::protocol("Invalid SOCKS5 address type"));
460 }
461 }
462 let proxy_stream: BoxAsyncReadWrite = Box::new(tcp_stream);
463 Ok(proxy_stream)
464 }
465
466 pub fn send_text(&mut self, text: &str) -> WebSocketResult {
476 let message: Message = Message::Text(text.into());
477 self.send_message_sync(message)
478 }
479
480 pub fn send_binary(&mut self, data: &[u8]) -> WebSocketResult {
490 let message: Message = Message::Binary(data.to_vec().into());
491 self.send_message_sync(message)
492 }
493
494 pub fn send_ping(&mut self, data: &[u8]) -> WebSocketResult {
504 let message: Message = Message::Ping(data.to_vec().into());
505 self.send_message_sync(message)
506 }
507
508 pub fn send_pong(&mut self, data: &[u8]) -> WebSocketResult {
518 let message: Message = Message::Pong(data.to_vec().into());
519 self.send_message_sync(message)
520 }
521
522 pub fn receive(&mut self) -> WebSocketMessageResult {
528 self.receive_message_sync()
529 }
530
531 pub fn close(&mut self) -> WebSocketResult {
537 self.close_sync()
538 }
539
540 pub fn is_connected(&self) -> bool {
546 self.connected.load(Ordering::Relaxed)
547 }
548
549 pub async fn send_text_async(&mut self, text: &str) -> WebSocketResult {
559 let message: Message = Message::Text(text.into());
560 self.send_message_async(message).await
561 }
562
563 pub async fn send_binary_async(&mut self, data: &[u8]) -> WebSocketResult {
573 let message: Message = Message::Binary(data.to_vec().into());
574 self.send_message_async(message).await
575 }
576
577 pub async fn send_ping_async(&mut self, data: &[u8]) -> WebSocketResult {
587 let message: Message = Message::Ping(data.to_vec().into());
588 self.send_message_async(message).await
589 }
590
591 pub async fn send_pong_async(&mut self, data: &[u8]) -> WebSocketResult {
601 let message: Message = Message::Pong(data.to_vec().into());
602 self.send_message_async(message).await
603 }
604
605 pub async fn receive_async(&mut self) -> WebSocketMessageResult {
611 self.receive_message_async().await
612 }
613
614 pub async fn close_async_method(&mut self) -> WebSocketResult {
620 self.close_async_internal().await
621 }
622}
623
624impl WebSocketTrait for WebSocket {
632 fn send_text(&mut self, text: &str) -> WebSocketResult {
633 self.send_text(text)
634 }
635
636 fn send_binary(&mut self, data: &[u8]) -> WebSocketResult {
637 self.send_binary(data)
638 }
639
640 fn send_ping(&mut self, data: &[u8]) -> WebSocketResult {
641 self.send_ping(data)
642 }
643
644 fn send_pong(&mut self, data: &[u8]) -> WebSocketResult {
645 self.send_pong(data)
646 }
647
648 fn receive(&mut self) -> WebSocketMessageResult {
649 self.receive()
650 }
651
652 fn close(&mut self) -> WebSocketResult {
653 self.close()
654 }
655
656 fn is_connected(&self) -> bool {
657 self.is_connected()
658 }
659}
660
661impl AsyncWebSocketTrait for WebSocket {
669 fn send_text<'a>(
670 &'a mut self,
671 text: &'a str,
672 ) -> Pin<Box<dyn Future<Output = WebSocketResult> + Send + 'a>> {
673 Box::pin(self.send_text_async(text))
674 }
675
676 fn send_binary<'a>(
677 &'a mut self,
678 data: &'a [u8],
679 ) -> Pin<Box<dyn Future<Output = WebSocketResult> + Send + 'a>> {
680 Box::pin(self.send_binary_async(data))
681 }
682
683 fn send_ping<'a>(
684 &'a mut self,
685 data: &'a [u8],
686 ) -> Pin<Box<dyn Future<Output = WebSocketResult> + Send + 'a>> {
687 Box::pin(self.send_ping_async(data))
688 }
689
690 fn send_pong<'a>(
691 &'a mut self,
692 data: &'a [u8],
693 ) -> Pin<Box<dyn Future<Output = WebSocketResult> + Send + 'a>> {
694 Box::pin(self.send_pong_async(data))
695 }
696
697 fn receive(&mut self) -> Pin<Box<dyn Future<Output = WebSocketMessageResult> + Send + '_>> {
698 Box::pin(self.receive_async())
699 }
700
701 fn close(&mut self) -> Pin<Box<dyn Future<Output = WebSocketResult> + Send + '_>> {
702 Box::pin(self.close_async_method())
703 }
704
705 fn is_connected(&self) -> bool {
706 self.is_connected()
707 }
708}