1use std::future::Future;
2use std::net::{IpAddr, SocketAddr};
3use std::pin::Pin;
4use std::str::FromStr;
5use std::sync::{Arc, Weak};
6
7use futures_util::stream::{SplitSink, SplitStream};
8use futures_util::{SinkExt, StreamExt};
9use log::{debug, error, info};
10use serde::Deserialize;
11use tokio::fs::File;
12use tokio::io::AsyncReadExt;
13use tokio::net::{TcpStream, UdpSocket};
14use tokio::process::Command;
15use tokio::sync::Mutex;
16use tokio::time::{Duration, sleep, timeout};
17use tokio_tungstenite::tungstenite::protocol::Message;
18use tokio_tungstenite::{MaybeTlsStream, WebSocketStream, connect_async};
19use uuid::Uuid;
20
21use crate::protocol::*;
22use crate::utils::{AnyError, resolve_host};
23
24#[derive(Default, Deserialize, Clone)]
25#[serde(rename_all = "camelCase")]
26pub struct Status {
27 pub battery_percentage: Option<i32>,
28}
29
30pub type GetStatusClosure =
31 Box<dyn Fn() -> Pin<Box<dyn Future<Output = Status> + Send + Sync>> + Send + Sync>;
32
33struct RelayInner {
34 me: Weak<Mutex<Self>>,
35 bind_address: String,
37 relay_id: Uuid,
38 streamer_url: String,
39 password: String,
40 name: String,
41 on_status_updated: Option<Box<dyn Fn(String) + Send + Sync>>,
42 get_status: Option<Arc<GetStatusClosure>>,
43 ws_writer: Option<SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, Message>>,
44 started: bool,
45 connected: bool,
46 wrong_password: bool,
47 reconnect_on_tunnel_error: Arc<Mutex<bool>>,
48 start_on_reconnect_soon: Arc<Mutex<bool>>,
49 relay_to_destination: Option<tokio::task::JoinHandle<Result<(), AnyError>>>,
50 relay_to_streamer: Arc<Mutex<Option<tokio::task::AbortHandle>>>,
51}
52
53impl RelayInner {
54 fn new() -> Arc<Mutex<Self>> {
55 Arc::new_cyclic(|me| {
56 Mutex::new(Self {
57 me: me.clone(),
58 bind_address: Self::get_default_bind_address(),
59 relay_id: Uuid::new_v4(),
60 streamer_url: "".to_string(),
61 password: "".to_string(),
62 name: "".to_string(),
63 on_status_updated: None,
64 get_status: None,
65 ws_writer: None,
66 started: false,
67 connected: false,
68 wrong_password: false,
69 reconnect_on_tunnel_error: Arc::new(Mutex::new(false)),
70 start_on_reconnect_soon: Arc::new(Mutex::new(false)),
71 relay_to_destination: None,
72 relay_to_streamer: Arc::new(Mutex::new(None)),
73 })
74 })
75 }
76
77 fn set_bind_address(&mut self, address: String) {
78 self.bind_address = address;
79 }
80
81 async fn setup<F>(
82 &mut self,
83 streamer_url: String,
84 password: String,
85 relay_id: Uuid,
86 name: String,
87 on_status_updated: F,
88 get_status: Option<GetStatusClosure>,
89 ) where
90 F: Fn(String) + Send + Sync + 'static,
91 {
92 self.on_status_updated = Some(Box::new(on_status_updated));
93 self.get_status = get_status.map(Arc::new);
94 self.relay_id = relay_id;
95 self.streamer_url = streamer_url;
96 self.password = password;
97 self.name = name;
98 }
99
100 fn is_started(&self) -> bool {
101 self.started
102 }
103
104 async fn start(&mut self) {
105 if !self.started {
106 self.started = true;
107 self.start_internal().await;
108 }
109 }
110
111 async fn stop(&mut self) {
112 if self.started {
113 self.started = false;
114 self.stop_internal().await;
115 }
116 }
117
118 fn get_default_bind_address() -> String {
119 let interfaces = pnet::datalink::interfaces();
121 let interface = interfaces.iter().find(|interface| {
122 interface.is_up() && !interface.is_loopback() && !interface.ips.is_empty()
123 });
124
125 let ipv4_addresses: Vec<String> = interface
127 .expect("No available network interfaces found")
128 .ips
129 .iter()
130 .filter_map(|ip| {
131 let ip = ip.ip();
132 ip.is_ipv4().then(|| ip.to_string())
133 })
134 .collect();
135
136 ipv4_addresses
138 .first()
139 .cloned()
140 .unwrap_or("0.0.0.0:0".to_string())
141 }
142
143 async fn start_internal(&mut self) {
144 if !self.started {
145 self.stop_internal().await;
146 return;
147 }
148
149 let request = match url::Url::parse(&self.streamer_url) {
150 Ok(url) => url,
151 Err(e) => {
152 error!("Failed to parse URL: {}", e);
153 return;
154 }
155 };
156
157 match timeout(Duration::from_secs(10), connect_async(request.to_string())).await {
158 Ok(Ok((ws_stream, _))) => {
159 debug!("Connected to {}", self.streamer_url);
160 let (writer, reader) = ws_stream.split();
161 self.ws_writer = Some(writer);
162 self.start_websocket_receiver(reader);
163 }
164 Ok(Err(error)) => {
165 debug!(
166 "Failed to connect to {} with error: {}",
167 self.streamer_url, error
168 );
169 self.reconnect_soon().await;
170 }
171 Err(_elapsed) => {
172 debug!(
173 "Failed to connect to {} within 10 seconds",
174 self.streamer_url
175 );
176 self.reconnect_soon().await;
177 }
178 }
179 }
180
181 fn start_websocket_receiver(
182 &mut self,
183 mut reader: SplitStream<WebSocketStream<MaybeTlsStream<TcpStream>>>,
184 ) {
185 let relay = self.me.clone();
187
188 tokio::spawn(async move {
189 let Some(relay_arc) = relay.upgrade() else {
190 return;
191 };
192
193 while let Some(result) = reader.next().await {
194 let mut relay = relay_arc.lock().await;
195 match result {
196 Ok(message) => match message {
197 Message::Text(text) => {
198 match serde_json::from_str::<MessageToRelay>(&text) {
199 Ok(message) => {
200 if let Err(error) = relay.handle_message(message).await {
201 error!("Message handling failed with error: {}", error);
202 relay.reconnect_soon().await;
203 break;
204 }
205 }
206 _ => {
207 error!("Failed to deserialize message: {}", text);
208 }
209 }
210 }
211 Message::Binary(data) => {
212 debug!("Received binary message of length: {}", data.len());
213 }
214 Message::Ping(data) => {
215 relay.send_message(Message::Pong(data)).await.ok();
216 }
217 Message::Pong(_) => {
218 debug!("Received pong message");
219 }
220 Message::Close(frame) => {
221 info!("Received close message: {:?}", frame);
222 relay.reconnect_soon().await;
223 break;
224 }
225 Message::Frame(_) => {
226 unreachable!("This is never used")
227 }
228 },
229 Err(e) => {
230 debug!("Error processing message: {}", e);
231 if e.to_string()
233 .contains("Connection reset without closing handshake")
234 {
235 relay.reconnect_soon().await;
236 }
237 break;
238 }
239 }
240 }
241 });
242 }
243
244 async fn stop_internal(&mut self) {
245 if let Some(mut ws_writer) = self.ws_writer.take() {
246 match ws_writer.close().await {
247 Err(e) => {
248 error!("Error closing WebSocket: {}", e);
249 }
250 _ => {
251 debug!("WebSocket closed successfully");
252 }
253 }
254 }
255 self.connected = false;
256 self.wrong_password = false;
257 *self.start_on_reconnect_soon.lock().await = false;
258 self.stop_tunnel().await;
259 self.update_status();
260 }
261
262 async fn stop_tunnel(&mut self) {
267 *self.reconnect_on_tunnel_error.lock().await = false;
268 if let Some(relay_to_destination) = self.relay_to_destination.take() {
269 relay_to_destination.abort();
270 relay_to_destination.await.ok();
271 }
272 if let Some(relay_to_streamer) = self.relay_to_streamer.lock().await.take() {
274 relay_to_streamer.abort();
275 }
276 }
277
278 fn update_status(&self) {
279 let Some(on_status_updated) = &self.on_status_updated else {
280 return;
281 };
282 let status = if self.connected {
283 "Connected to streamer"
284 } else if self.wrong_password {
285 "Wrong password"
286 } else if self.started {
287 "Connecting to streamer"
288 } else {
289 "Disconnected from streamer"
290 };
291 on_status_updated(status.to_string());
292 }
293
294 async fn reconnect_soon(&mut self) {
295 self.stop_internal().await;
296 *self.start_on_reconnect_soon.lock().await = false;
297 let start_on_reconnect_soon = Arc::new(Mutex::new(true));
298 self.start_on_reconnect_soon = start_on_reconnect_soon.clone();
299 self.start_soon(start_on_reconnect_soon);
300 }
301
302 fn start_soon(&mut self, start_on_reconnect_soon: Arc<Mutex<bool>>) {
303 let relay = self.me.clone();
304
305 tokio::spawn(async move {
306 sleep(Duration::from_secs(5)).await;
307
308 if *start_on_reconnect_soon.lock().await {
309 debug!("Reconnecting...");
310 if let Some(relay) = relay.upgrade() {
311 relay.lock().await.start_internal().await;
312 }
313 }
314 });
315 }
316
317 async fn handle_message(&mut self, message: MessageToRelay) -> Result<(), AnyError> {
318 match message {
319 MessageToRelay::Hello(hello) => self.handle_message_hello(hello).await,
320 MessageToRelay::Identified(identified) => {
321 self.handle_message_identified(identified).await
322 }
323 MessageToRelay::Request(request) => self.handle_message_request(request).await,
324 }
325 }
326
327 async fn handle_message_hello(&mut self, hello: Hello) -> Result<(), AnyError> {
328 let authentication = calculate_authentication(
329 &self.password,
330 &hello.authentication.salt,
331 &hello.authentication.challenge,
332 );
333 let identify = Identify {
334 id: self.relay_id,
335 name: self.name.clone(),
336 authentication,
337 };
338 self.send(MessageToStreamer::Identify(identify)).await
339 }
340
341 async fn handle_message_identified(&mut self, identified: Identified) -> Result<(), AnyError> {
342 match identified.result {
343 MoblinkResult::Ok(_) => {
344 self.connected = true;
345 }
346 MoblinkResult::WrongPassword(_) => {
347 self.wrong_password = true;
348 }
349 }
350 self.update_status();
351 Ok(())
352 }
353
354 async fn handle_message_request(&mut self, request: MessageRequest) -> Result<(), AnyError> {
355 match &request.data {
356 MessageRequestData::StartTunnel(start_tunnel) => {
357 self.handle_message_request_start_tunnel(&request, start_tunnel)
358 .await
359 }
360 MessageRequestData::Status(_) => self.handle_message_request_status(request).await,
361 }
362 }
363
364 async fn handle_message_request_start_tunnel(
365 &mut self,
366 request: &MessageRequest,
367 start_tunnel: &StartTunnelRequest,
368 ) -> Result<(), AnyError> {
369 self.stop_tunnel().await;
370
371 let local_bind_addr_for_streamer = parse_socket_addr("0.0.0.0")?;
373 let local_bind_addr_for_destination = parse_socket_addr(&self.bind_address)?;
374
375 debug!(
376 "Binding streamer socket on: {}, destination socket on: {}",
377 local_bind_addr_for_streamer, local_bind_addr_for_destination
378 );
379 let streamer_socket = create_dual_stack_udp_socket(local_bind_addr_for_streamer).await?;
382 let streamer_port = streamer_socket.local_addr()?.port();
383 let streamer_socket = Arc::new(streamer_socket);
384
385 let data = ResponseData::StartTunnel(StartTunnelResponseData {
387 port: streamer_port,
388 });
389 let response = request.to_ok_response(data);
390 self.send(MessageToStreamer::Response(response)).await?;
391
392 let destination_socket =
395 create_dual_stack_udp_socket(local_bind_addr_for_destination).await?;
396
397 let destination_socket = Arc::new(destination_socket);
398 let destination_address = resolve_host(&start_tunnel.address).await?;
399 let destination_address = match IpAddr::from_str(&destination_address)? {
400 IpAddr::V4(v4) => IpAddr::V4(v4),
401 IpAddr::V6(v6) => {
402 if let Some(mapped_v4) = v6.to_ipv4() {
404 IpAddr::V4(mapped_v4)
405 } else {
406 IpAddr::V6(v6)
408 }
409 }
410 };
411
412 let destination_address = SocketAddr::new(destination_address, start_tunnel.port);
413 info!("Destination address: {}", destination_address);
414
415 self.relay_to_destination = Some(
416 self.start_relay_from_streamer_to_destination(
417 streamer_socket,
418 destination_socket,
419 destination_address,
420 )
421 .await,
422 );
423
424 Ok(())
425 }
426
427 async fn start_relay_from_streamer_to_destination(
428 &mut self,
429 streamer_socket: Arc<UdpSocket>,
430 destination_socket: Arc<UdpSocket>,
431 destination_addr: SocketAddr,
432 ) -> tokio::task::JoinHandle<Result<(), AnyError>> {
433 let reconnect_on_tunnel_error = Arc::new(Mutex::new(true));
434 self.reconnect_on_tunnel_error = reconnect_on_tunnel_error.clone();
435 let relay_to_streamer = Arc::new(Mutex::new(None));
436 self.relay_to_streamer = relay_to_streamer.clone();
437 let relay = self.me.clone();
438
439 tokio::spawn(async move {
440 let streamer_address = Arc::new(Mutex::new(None));
441 let mut relay_to_streamer_started = false;
442 let mut buf = [0; 2048];
443
444 loop {
445 let (size, remote_addr) = streamer_socket.recv_from(&mut buf).await?;
446 destination_socket
447 .send_to(&buf[..size], &destination_addr)
448 .await?;
449 streamer_address.lock().await.replace(remote_addr);
450
451 if !relay_to_streamer_started {
452 let task = start_relay_from_destination_to_streamer(
453 relay.clone(),
454 streamer_socket.clone(),
455 destination_socket.clone(),
456 streamer_address.clone(),
457 reconnect_on_tunnel_error.clone(),
458 );
459 relay_to_streamer.lock().await.replace(task);
460 relay_to_streamer_started = true;
461 }
462 }
463 })
464 }
465
466 async fn handle_message_request_status(
467 &mut self,
468 request: MessageRequest,
469 ) -> Result<(), AnyError> {
470 let mut battery_percentage = None;
471 if let Some(get_status) = self.get_status.as_ref() {
472 battery_percentage = get_status().await.battery_percentage;
473 }
474 let data = ResponseData::Status(StatusResponseData { battery_percentage });
475 let response = request.to_ok_response(data);
476 self.send(MessageToStreamer::Response(response)).await
477 }
478
479 async fn send(&mut self, message: MessageToStreamer) -> Result<(), AnyError> {
480 let text = serde_json::to_string(&message)?;
481 self.send_message(Message::Text(text.into())).await
482 }
483
484 async fn send_message(&mut self, message: Message) -> Result<(), AnyError> {
485 let Some(writer) = self.ws_writer.as_mut() else {
486 return Err("No websocket writer".into());
487 };
488 writer.send(message).await?;
489 Ok(())
490 }
491}
492
493pub struct Relay {
494 inner: Arc<Mutex<RelayInner>>,
495}
496
497impl Default for Relay {
498 fn default() -> Self {
499 Self::new()
500 }
501}
502
503impl Relay {
504 pub fn new() -> Self {
505 Self {
506 inner: RelayInner::new(),
507 }
508 }
509
510 pub async fn set_bind_address(&self, address: String) {
511 self.inner.lock().await.set_bind_address(address);
512 }
513
514 pub async fn setup<F>(
515 &self,
516 streamer_url: String,
517 password: String,
518 relay_id: Uuid,
519 name: String,
520 on_status_updated: F,
521 get_status: Option<GetStatusClosure>,
522 ) where
523 F: Fn(String) + Send + Sync + 'static,
524 {
525 self.inner
526 .lock()
527 .await
528 .setup(
529 streamer_url,
530 password,
531 relay_id,
532 name,
533 on_status_updated,
534 get_status,
535 )
536 .await;
537 }
538
539 pub async fn is_started(&self) -> bool {
540 self.inner.lock().await.is_started()
541 }
542
543 pub async fn start(&self) {
544 self.inner.lock().await.start().await;
545 }
546
547 pub async fn stop(&self) {
548 self.inner.lock().await.stop().await;
549 }
550}
551
552fn start_relay_from_destination_to_streamer(
553 relay: Weak<Mutex<RelayInner>>,
554 streamer_socket: Arc<UdpSocket>,
555 destination_socket: Arc<UdpSocket>,
556 streamer_address: Arc<Mutex<Option<SocketAddr>>>,
557 reconnect_on_tunnel_error: Arc<Mutex<bool>>,
558) -> tokio::task::AbortHandle {
559 tokio::spawn(async move {
560 loop {
561 if let Err(error) = relay_one_packet_from_destination_to_streamer(
562 &streamer_socket,
563 &destination_socket,
564 &streamer_address,
565 )
566 .await
567 {
568 info!("(relay_to_streamer) Failed with error: {}", error);
569 break;
570 }
571 }
572
573 if *reconnect_on_tunnel_error.lock().await {
574 if let Some(relay) = relay.upgrade() {
575 tokio::spawn(async move {
578 relay.lock().await.reconnect_soon().await;
579 });
580 }
581 } else {
582 info!("Not reconnecting after tunnel error");
583 }
584 })
585 .abort_handle()
586}
587
588async fn relay_one_packet_from_destination_to_streamer(
589 streamer_socket: &Arc<UdpSocket>,
590 destination_socket: &Arc<UdpSocket>,
591 streamer_address: &Arc<Mutex<Option<SocketAddr>>>,
592) -> Result<(), AnyError> {
593 let mut buf = [0; 2048];
594 let size = timeout(Duration::from_secs(30), destination_socket.recv(&mut buf)).await??;
595 let streamer_addr = streamer_address
596 .lock()
597 .await
598 .ok_or("Failed to get address lock")?;
599 streamer_socket
600 .send_to(&buf[..size], &streamer_addr)
601 .await?;
602 Ok(())
603}
604
605async fn create_dual_stack_udp_socket(
606 addr: SocketAddr,
607) -> Result<tokio::net::UdpSocket, std::io::Error> {
608 let socket = match addr.is_ipv4() {
609 true => {
610 tokio::net::UdpSocket::bind(addr).await?
612 }
613 false => {
614 let socket = socket2::Socket::new(
616 socket2::Domain::IPV6,
617 socket2::Type::DGRAM,
618 Some(socket2::Protocol::UDP),
619 )?;
620
621 socket.set_only_v6(false)?;
623
624 socket.bind(&socket2::SockAddr::from(addr))?;
626
627 tokio::net::UdpSocket::from_std(socket.into())?
629 }
630 };
631
632 Ok(socket)
633}
634
635fn parse_socket_addr(addr_str: &str) -> Result<SocketAddr, std::io::Error> {
638 if let Ok(socket_addr) = SocketAddr::from_str(addr_str) {
640 return Ok(socket_addr);
641 }
642
643 if let Ok(ip_addr) = IpAddr::from_str(addr_str) {
646 return Ok(SocketAddr::new(ip_addr, 0));
648 }
649
650 Err(std::io::Error::new(
652 std::io::ErrorKind::InvalidInput,
653 "Invalid socket address syntax. Expected 'IP:port' or 'IP'.",
654 ))
655}
656
657pub fn create_get_status_closure(
658 status_executable: &Option<String>,
659 status_file: &Option<String>,
660) -> Option<GetStatusClosure> {
661 let status_executable = status_executable.clone();
662 let status_file = status_file.clone();
663 Some(Box::new(move || {
664 let status_executable = status_executable.clone();
665 let status_file = status_file.clone();
666 Box::pin(async move {
667 let output = if let Some(status_executable) = &status_executable {
668 let Ok(output) = Command::new(status_executable).output().await else {
669 return Default::default();
670 };
671 output.stdout
672 } else if let Some(status_file) = &status_file {
673 let Ok(mut file) = File::open(status_file).await else {
674 return Default::default();
675 };
676 let mut contents = vec![];
677 if file.read_to_end(&mut contents).await.is_err() {
678 return Default::default();
679 }
680 contents
681 } else {
682 return Default::default();
683 };
684 let output = String::from_utf8(output).unwrap_or_default();
685 match serde_json::from_str(&output) {
686 Ok(status) => status,
687 Err(e) => {
688 error!("Failed to decode status with error: {e}");
689 Default::default()
690 }
691 }
692 })
693 }))
694}