99use std:: sync:: Arc ;
1010use std:: time:: Duration ;
1111
12- use anyhow:: { Context , Result } ;
13- use bytes:: Bytes ;
12+ use anyhow:: Result ;
1413use clap:: Parser ;
15- use tokio:: io:: { AsyncReadExt , AsyncWriteExt } ;
16- use tokio:: net:: TcpStream ;
1714
1815use candy_spoof:: config:: Config ;
1916use candy_spoof:: raw_socket:: { RawReceiver , RawSender } ;
17+ use candy_spoof:: smux:: SmuxServer ;
2018use candy_spoof:: tunnel:: { PeerAddr , TunnelManager } ;
2119
2220#[ derive( Parser , Debug ) ]
@@ -62,6 +60,7 @@ async fn main() -> Result<()> {
6260 is_server : true ,
6361 } ;
6462 let manager = TunnelManager :: new ( sender, peer_addr, cfg. clone ( ) ) ;
63+ let smux = SmuxServer :: new ( cfg. clone ( ) , manager. clone ( ) ) . await ?;
6564
6665 // ── Periodic housekeeping ────────────────────────────────────────────────
6766 let mgr_tick = manager. clone ( ) ;
@@ -93,10 +92,9 @@ async fn main() -> Result<()> {
9392 {
9493 Ok ( Some ( ( syn_pkt, src_ip) ) ) => {
9594 // New tunnel request – accept it and spawn a session handler.
96- let mgr2 = manager. clone ( ) ;
97- let cfg2 = cfg. clone ( ) ;
95+ let smux2 = smux. clone ( ) ;
9896 tokio:: spawn ( async move {
99- if let Err ( e) = handle_new_tunnel ( syn_pkt, src_ip, mgr2 , cfg2 ) . await {
97+ if let Err ( e) = smux2 . attach_syn ( syn_pkt, src_ip) . await {
10098 log:: warn!( "session error: {}" , e) ;
10199 }
102100 } ) ;
@@ -108,94 +106,3 @@ async fn main() -> Result<()> {
108106
109107 Ok ( ( ) )
110108}
111-
112- // ── New-tunnel handler ────────────────────────────────────────────────────────
113-
114- /// Accept a SYN, wait for the first DATA packet containing the CONNECT
115- /// destination, open a TCP connection to that destination, and relay data.
116- async fn handle_new_tunnel (
117- syn : candy_spoof:: packet:: CandyPacket ,
118- src_ip : std:: net:: Ipv4Addr ,
119- manager : TunnelManager ,
120- cfg : Arc < Config > ,
121- ) -> Result < ( ) > {
122- let ( tunnel_id, mut app_rx, net_tx) = manager
123- . accept_syn ( syn, src_ip)
124- . await
125- . context ( "accept_syn" ) ?;
126-
127- // First message from the client is the CONNECT destination.
128- let first_msg = tokio:: time:: timeout ( Duration :: from_secs ( 15 ) , app_rx. recv ( ) )
129- . await
130- . context ( "timeout waiting for CONNECT meta" ) ?
131- . context ( "tunnel closed before CONNECT meta" ) ?;
132-
133- let meta = String :: from_utf8_lossy ( & first_msg) ;
134- let ( target_host, target_port) = parse_connect_meta ( & meta) ?;
135-
136- log:: info!(
137- "tunnel {} forwarding to {}:{}" ,
138- tunnel_id,
139- target_host,
140- target_port
141- ) ;
142-
143- // Open TCP connection to the target.
144- let target_addr = format ! ( "{}:{}" , target_host, target_port) ;
145- let tcp_stream = TcpStream :: connect ( & target_addr)
146- . await
147- . with_context ( || format ! ( "connect to {}" , target_addr) ) ?;
148-
149- let ( mut tcp_r, mut tcp_w) = tcp_stream. into_split ( ) ;
150- let mtu = cfg. mtu ;
151-
152- // Tunnel → TCP
153- let t_to_tcp = tokio:: spawn ( async move {
154- loop {
155- match app_rx. recv ( ) . await {
156- Some ( data) => {
157- if tcp_w. write_all ( & data) . await . is_err ( ) { break ; }
158- }
159- None => break ,
160- }
161- }
162- } ) ;
163-
164- // TCP → tunnel
165- let net_tx2 = net_tx;
166- let tcp_to_t = tokio:: spawn ( async move {
167- let mut buf = vec ! [ 0u8 ; mtu] ;
168- loop {
169- match tcp_r. read ( & mut buf) . await {
170- Ok ( 0 ) | Err ( _) => break ,
171- Ok ( n) => {
172- let chunk = Bytes :: copy_from_slice ( & buf[ ..n] ) ;
173- if net_tx2. send ( chunk) . await . is_err ( ) { break ; }
174- }
175- }
176- }
177- } ) ;
178-
179- tokio:: select! {
180- _ = t_to_tcp => { }
181- _ = tcp_to_t => { }
182- }
183-
184- manager. close_tunnel ( tunnel_id) . await ;
185- Ok ( ( ) )
186- }
187-
188- fn parse_connect_meta ( meta : & str ) -> Result < ( String , u16 ) > {
189- // Expected format: "CONNECT host:port"
190- let rest = meta
191- . strip_prefix ( "CONNECT " )
192- . context ( "missing CONNECT prefix in meta" ) ?;
193- let ( host, port_str) = rest
194- . rsplit_once ( ':' )
195- . context ( "missing ':' in CONNECT meta" ) ?;
196- let port = port_str
197- . trim ( )
198- . parse :: < u16 > ( )
199- . context ( "invalid port in CONNECT meta" ) ?;
200- Ok ( ( host. to_string ( ) , port) )
201- }
0 commit comments