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