@@ -41,15 +41,46 @@ impl UdpServer {
4141 let domain = if bind_address. is_ipv4 ( ) { Domain :: IPV4 } else { Domain :: IPV6 } ;
4242 let socket = Socket :: new ( domain, Type :: DGRAM , Some ( Protocol :: UDP ) ) ?;
4343
44- socket. set_recv_buffer_size ( recv_buffer_size) . map_err ( tokio:: io:: Error :: other) ?;
45- socket. set_send_buffer_size ( send_buffer_size) . map_err ( tokio:: io:: Error :: other) ?;
44+ // Aggressive buffer sizing for high throughput
45+ let actual_recv_buffer = recv_buffer_size. max ( 16_777_216 ) ; // Minimum 16MB
46+ let actual_send_buffer = send_buffer_size. max ( 16_777_216 ) ; // Minimum 16MB
47+
48+ socket. set_recv_buffer_size ( actual_recv_buffer) . map_err ( tokio:: io:: Error :: other) ?;
49+ socket. set_send_buffer_size ( actual_send_buffer) . map_err ( tokio:: io:: Error :: other) ?;
4650 socket. set_reuse_address ( reuse_address) . map_err ( tokio:: io:: Error :: other) ?;
51+
52+ // Enable SO_REUSEPORT for better load distribution across threads
53+ #[ cfg( target_os = "linux" ) ]
54+ {
55+ use socket2:: TcpKeepalive ;
56+ let reuse_port = 1i32 ;
57+ unsafe {
58+ let optval = & reuse_port as * const i32 as * const libc:: c_void ;
59+ if libc:: setsockopt (
60+ socket. as_raw_fd ( ) ,
61+ libc:: SOL_SOCKET ,
62+ libc:: SO_REUSEPORT ,
63+ optval,
64+ std:: mem:: size_of :: < i32 > ( ) as libc:: socklen_t ,
65+ ) != 0 {
66+ log:: warn!( "Failed to set SO_REUSEPORT - continuing without it" ) ;
67+ }
68+ }
69+ }
70+
4771 socket. bind ( & bind_address. into ( ) ) . map_err ( tokio:: io:: Error :: other) ?;
4872 socket. set_nonblocking ( true ) . map_err ( tokio:: io:: Error :: other) ?;
4973
74+ // Convert to std::net::UdpSocket, then to tokio::net::UdpSocket
5075 let std_socket: std:: net:: UdpSocket = socket. into ( ) ;
5176 let tokio_socket = UdpSocket :: from_std ( std_socket) ?;
5277
78+ // Log actual buffer sizes
79+ let sock_ref = socket2:: SockRef :: from ( & tokio_socket) ;
80+ let actual_recv = sock_ref. recv_buffer_size ( ) . unwrap_or ( 0 ) ;
81+ let actual_send = sock_ref. send_buffer_size ( ) . unwrap_or ( 0 ) ;
82+ info ! ( "Socket created with buffers - Recv: {} bytes, Send: {} bytes" , actual_recv, actual_send) ;
83+
5384 Ok ( UdpServer {
5485 socket : Arc :: new ( tokio_socket) ,
5586 threads,
@@ -61,32 +92,62 @@ impl UdpServer {
6192 pub async fn start ( & self , rx : tokio:: sync:: watch:: Receiver < bool > )
6293 {
6394 let threads = self . threads ;
64- for _index in 0 ..=threads {
95+ // Create multiple sockets for better performance using SO_REUSEPORT
96+ for thread_id in 0 ..threads {
6597 let socket_clone = self . socket . clone ( ) ;
6698 let tracker = self . tracker . clone ( ) ;
6799 let mut rx = rx. clone ( ) ;
68- let mut data = [ 0 ; 1496 ] ;
100+
69101 tokio:: spawn ( async move {
102+ // Larger buffer to handle burst traffic
103+ let mut data = [ 0 ; 2048 ] ; // Increased from 1496
104+ let mut packet_count = 0u64 ;
105+ let mut last_stats = std:: time:: Instant :: now ( ) ;
106+
70107 loop {
71108 let udp_sock = socket_clone. local_addr ( ) . unwrap ( ) ;
72109 tokio:: select! {
73110 _ = rx. changed( ) => {
74- info!( "Stopping UDP server: {udp_sock}..." ) ;
111+ info!( "Stopping UDP server thread {} : {udp_sock}..." , thread_id ) ;
75112 break ;
76113 }
77- Ok ( ( valid_bytes, remote_addr) ) = socket_clone. recv_from( & mut data) => {
78- let payload = & data[ ..valid_bytes] ;
79-
80- debug!( "Received {} bytes from {}" , payload. len( ) , remote_addr) ;
81- debug!( "{payload:?}" ) ;
82-
83- let tracker_cloned = tracker. clone( ) ;
84- let socket_cloned = socket_clone. clone( ) ;
85- let payload_vec = payload. to_vec( ) ;
86- tokio:: spawn( async move {
87- let response = UdpServer :: handle_packet( remote_addr, payload_vec, tracker_cloned. clone( ) ) . await ;
88- UdpServer :: send_response( tracker_cloned. clone( ) , socket_cloned. clone( ) , remote_addr, response) . await ;
89- } ) ;
114+ result = socket_clone. recv_from( & mut data) => {
115+ match result {
116+ Ok ( ( valid_bytes, remote_addr) ) => {
117+ packet_count += 1 ;
118+
119+ // Log stats every 10k packets per thread
120+ if packet_count % 10000 == 0 {
121+ let elapsed = last_stats. elapsed( ) ;
122+ let rate = 10000.0 / elapsed. as_secs_f64( ) ;
123+ debug!( "Thread {} processed 10k packets in {:?} ({:.1} pps)" ,
124+ thread_id, elapsed, rate) ;
125+ last_stats = std:: time:: Instant :: now( ) ;
126+ }
127+
128+ let payload = & data[ ..valid_bytes] ;
129+ debug!( "Thread {} received {} bytes from {}" , thread_id, payload. len( ) , remote_addr) ;
130+
131+ let tracker_cloned = tracker. clone( ) ;
132+ let socket_cloned = socket_clone. clone( ) ;
133+ let payload_vec = payload. to_vec( ) ;
134+
135+ // Process immediately without extra spawning for better performance
136+ let response = UdpServer :: handle_packet( remote_addr, payload_vec, tracker_cloned. clone( ) ) . await ;
137+ UdpServer :: send_response( tracker_cloned. clone( ) , socket_cloned. clone( ) , remote_addr, response) . await ;
138+ }
139+ Err ( e) => {
140+ match e. kind( ) {
141+ std:: io:: ErrorKind :: WouldBlock => {
142+ // This is normal for non-blocking sockets
143+ tokio:: task:: yield_now( ) . await ;
144+ }
145+ _ => {
146+ log:: error!( "Thread {} recv_from error: {}" , thread_id, e) ;
147+ }
148+ }
149+ }
150+ }
90151 }
91152 }
92153 }
@@ -101,14 +162,16 @@ impl UdpServer {
101162 let sentry = sentry:: TransactionContext :: new ( "udp server" , "send response" ) ;
102163 let transaction = sentry:: start_transaction ( sentry) ;
103164
104- let mut buffer = Vec :: with_capacity ( 512 ) ;
165+ // Pre-allocate buffer with exact capacity instead of MAX_PACKET_SIZE
166+ let mut buffer = Vec :: with_capacity ( 512 ) ; // Most responses are much smaller than MAX_PACKET_SIZE
105167 let mut cursor = Cursor :: new ( & mut buffer) ;
106168
107169 match response. write ( & mut cursor) {
108170 Ok ( _) => {
109171 let position = cursor. position ( ) as usize ;
110172 debug ! ( "Response bytes: {:?}" , & buffer[ ..position] ) ;
111173
174+ // Get batch manager for this socket and queue the response
112175 let batch_manager = ResponseBatchManager :: get_for_socket ( socket) . await ;
113176 batch_manager. queue_response ( remote_addr, buffer[ ..position] . to_vec ( ) ) ;
114177 }
@@ -127,6 +190,7 @@ impl UdpServer {
127190
128191 #[ tracing:: instrument( level = "debug" ) ]
129192 pub async fn send_packet ( socket : Arc < UdpSocket > , remote_addr : & SocketAddr , payload : & [ u8 ] ) {
193+ // This method is kept for compatibility but shouldn't be used in the batched version
130194 let _ = socket. send_to ( payload, remote_addr) . await ;
131195 }
132196
@@ -214,6 +278,7 @@ impl UdpServer {
214278 pub async fn handle_udp_announce ( remote_addr : SocketAddr , request : & AnnounceRequest , tracker : Arc < TorrentTracker > ) -> Result < Response , ServerError > {
215279 let config = tracker. config . tracker_config . clone ( ) ;
216280
281+ // Whitelist/Blacklist checks
217282 if config. whitelist_enabled && !tracker. check_whitelist ( InfoHash ( request. info_hash . 0 ) ) {
218283 debug ! ( "[UDP ERROR] Torrent Not Whitelisted" ) ;
219284 return Err ( ServerError :: TorrentNotWhitelisted ) ;
@@ -223,6 +288,7 @@ impl UdpServer {
223288 return Err ( ServerError :: TorrentBlacklisted ) ;
224289 }
225290
291+ // Key validation
226292 if config. keys_enabled {
227293 if request. path . len ( ) < 50 {
228294 debug ! ( "[UDP ERROR] Unknown Key" ) ;
@@ -246,6 +312,7 @@ impl UdpServer {
246312 }
247313 }
248314
315+ // User key validation
249316 let user_key = if config. users_enabled {
250317 let user_key_path_extract = if request. path . len ( ) >= 91 {
251318 Some ( & request. path [ 51 ..=91 ] )
@@ -278,6 +345,7 @@ impl UdpServer {
278345 return Err ( ServerError :: PeerKeyNotValid ) ;
279346 }
280347
348+ // Handle announce
281349 let torrent = match tracker. handle_announce ( tracker. clone ( ) , AnnounceQueryRequest {
282350 info_hash : InfoHash ( request. info_hash . 0 ) ,
283351 peer_id : PeerId ( request. peer_id . 0 ) ,
@@ -298,13 +366,15 @@ impl UdpServer {
298366 }
299367 } ;
300368
369+ // Get peers efficiently
301370 let torrent_peers = tracker. get_torrent_peers ( request. info_hash , 72 , TorrentPeersType :: All , Some ( remote_addr. ip ( ) ) ) ;
302371
303372 let ( peers, peers6) = if let Some ( torrent_peers_unwrapped) = torrent_peers {
304373 let mut peers = Vec :: with_capacity ( 72 ) ;
305374 let mut peers6 = Vec :: with_capacity ( 72 ) ;
306375 let mut count = 0 ;
307376
377+ // Only collect peers if not completed download
308378 if request. bytes_left . 0 != 0 {
309379 if remote_addr. is_ipv4 ( ) {
310380 for torrent_peer in torrent_peers_unwrapped. seeds_ipv4 . values ( ) . take ( 72 ) {
@@ -325,6 +395,7 @@ impl UdpServer {
325395 }
326396 }
327397
398+ // Collect regular peers
328399 if remote_addr. is_ipv4 ( ) {
329400 for torrent_peer in torrent_peers_unwrapped. peers_ipv4 . values ( ) . take ( 72 - count) {
330401 if let Ok ( ip) = torrent_peer. peer_addr . ip ( ) . to_string ( ) . parse :: < Ipv4Addr > ( ) {
@@ -344,6 +415,7 @@ impl UdpServer {
344415 ( Vec :: new ( ) , Vec :: new ( ) )
345416 } ;
346417
418+ // Create response
347419 let response = if remote_addr. is_ipv6 ( ) {
348420 Response :: from ( AnnounceResponse {
349421 transaction_id : request. transaction_id ,
@@ -362,6 +434,7 @@ impl UdpServer {
362434 } )
363435 } ;
364436
437+ // Update stats
365438 let stats_event = if remote_addr. is_ipv4 ( ) {
366439 StatsEvent :: Udp4AnnouncesHandled
367440 } else {
0 commit comments