syncweb_core/bridge/
server.rs1use std::{net::SocketAddr, path::PathBuf, sync::Arc};
2
3use n0_future::split;
4use tokio::sync::broadcast;
5
6use crate::{
7 error::{Result, SyncwebError},
8 node::iroh_node::IrohNode,
9};
10
11use super::{service::BridgeService, session::WsSession};
12
13pub struct WsBridgeServer {
15 node: Arc<IrohNode>,
16 addr: SocketAddr,
17 data_dir: PathBuf,
18}
19
20impl WsBridgeServer {
21 #[must_use]
22 pub const fn new(node: Arc<IrohNode>, addr: SocketAddr, data_dir: PathBuf) -> Self {
23 Self { node, addr, data_dir }
24 }
25
26 pub async fn run(self, shutdown: broadcast::Sender<()>) -> Result<()> {
34 let listener = Self::bind_listener(self.addr).await?;
35
36 tracing::info!("WebSocket bridge listening on {}", self.addr);
37
38 let service = Arc::new(BridgeService::new(self.node, self.data_dir, shutdown.clone())?);
39
40 let mut server_shutdown = shutdown.subscribe();
41
42 loop {
43 tokio::select! {
44 _ = server_shutdown.recv() => {
45 tracing::info!("bridge server shutting down");
46 break Ok(());
47 }
48 accepted = listener.accept() => {
49 Self::handle_accept(accepted, &service, &shutdown);
50 }
51 }
52 }
53 }
54
55 async fn bind_listener(addr: SocketAddr) -> Result<tokio::net::TcpListener> {
56 tokio::net::TcpListener::bind(addr)
57 .await
58 .map_err(|error| SyncwebError::operation(format!("failed to bind bridge server on {addr}"), error))
59 }
60
61 fn handle_accept(
62 accepted: std::io::Result<(tokio::net::TcpStream, SocketAddr)>,
63 service: &Arc<BridgeService>,
64 shutdown: &broadcast::Sender<()>,
65 ) {
66 let (stream, peer_addr) = match accepted {
67 Ok(conn) => conn,
68 Err(error) => {
69 tracing::warn!(%error, "bridge accept failed");
70 return;
71 }
72 };
73 let svc = Arc::clone(service);
74 let shutdown_rx = shutdown.subscribe();
75 tokio::spawn(async move {
76 if let Err(error) = handle_connection(stream, svc, shutdown_rx).await {
77 tracing::warn!(%peer_addr, %error, "bridge session error");
78 }
79 });
80 }
81}
82
83async fn handle_connection(
84 stream: tokio::net::TcpStream,
85 service: Arc<BridgeService>,
86 shutdown: broadcast::Receiver<()>,
87) -> Result<()> {
88 let ws_stream = tokio_tungstenite::accept_async(stream)
89 .await
90 .map_err(|error| SyncwebError::operation("websocket handshake failed", error))?;
91
92 let (sender, mut receiver) = split::split(ws_stream);
93
94 let session = WsSession::new(service, sender, shutdown);
95 session.run(&mut receiver).await
96}