Skip to main content

rust_raknet/
server.rs

1use std::collections::HashMap;
2use std::{net::SocketAddr, sync::Arc};
3use tokio::net::UdpSocket;
4use tokio::sync::mpsc::channel;
5use tokio::sync::mpsc::{Receiver, Sender};
6use tokio::sync::{Mutex, Notify, watch};
7
8use crate::error::{RaknetError, Result};
9use crate::packet::*;
10use crate::utils::*;
11use crate::{raknet_log_debug, raknet_log_error, socket::*};
12
13const SERVER_NAME: &str = "Rust Raknet Server";
14const MAX_CONNECTION: u32 = 99999;
15
16struct SessionSender {
17    sender: Sender<Vec<u8>>,
18    close: Arc<tokio::sync::Semaphore>,
19    guid: u64,
20    mtu: u16,
21}
22
23// The authoritative session map handles handshakes and shutdown. This bounded,
24// direct-mapped cache avoids the shared map on the common dispatch path.
25// A slot collision is only a cache miss: the complete peer address is checked.
26struct SessionDispatchCache {
27    entries: Vec<Option<CachedSession>>,
28}
29
30struct CachedSession {
31    address: SocketAddr,
32    sender: Sender<Vec<u8>>,
33    close: Arc<tokio::sync::Semaphore>,
34}
35
36impl Default for SessionDispatchCache {
37    fn default() -> Self {
38        Self {
39            entries: std::iter::repeat_with(|| None).take(Self::LIMIT).collect(),
40        }
41    }
42}
43
44impl SessionDispatchCache {
45    const LIMIT: usize = 4096;
46
47    fn slot(address: &SocketAddr) -> usize {
48        // Include the IP: many unrelated clients use the same source port.
49        let ip = match address.ip() {
50            std::net::IpAddr::V4(ip) => u64::from(u32::from(ip)),
51            std::net::IpAddr::V6(ip) => {
52                let bits = u128::from(ip);
53                bits as u64 ^ (bits >> 64) as u64
54            }
55        };
56        let mut mixed = ip;
57        mixed ^= mixed >> 33;
58        mixed = mixed.wrapping_mul(0xff51afd7ed558ccd);
59        mixed ^= mixed >> 33;
60        (mixed as usize ^ usize::from(address.port())) & (Self::LIMIT - 1)
61    }
62
63    fn sender(&self, address: &SocketAddr) -> Option<&Sender<Vec<u8>>> {
64        self.entries[Self::slot(address)]
65            .as_ref()
66            .filter(|entry| {
67                entry.address == *address && !entry.close.is_closed() && !entry.sender.is_closed()
68            })
69            .map(|entry| &entry.sender)
70    }
71
72    fn remember(&mut self, address: SocketAddr, session: &SessionSender) {
73        self.entries[Self::slot(&address)] = Some(CachedSession {
74            address,
75            sender: session.sender.clone(),
76            close: session.close.clone(),
77        });
78    }
79
80    fn forget(&mut self, address: &SocketAddr) {
81        let slot = &mut self.entries[Self::slot(address)];
82        if slot.as_ref().is_some_and(|entry| entry.address == *address) {
83            *slot = None;
84        }
85    }
86
87    fn prune(&mut self) {
88        for slot in &mut self.entries {
89            if slot
90                .as_ref()
91                .is_some_and(|entry| entry.close.is_closed() || entry.sender.is_closed())
92            {
93                *slot = None;
94            }
95        }
96    }
97}
98
99/// A RakNet UDP server that accepts incoming connections.
100pub struct RaknetListener {
101    motd: String,
102    shards: Vec<Self>,
103    socket: Option<Arc<UdpSocket>>,
104    guid: u64,
105    listened: bool,
106    maximum_mtu: u16,
107    receive_batching: bool,
108    idle_maintenance: bool,
109    connection_receiver: Receiver<RaknetSocket>,
110    connection_sender: Sender<RaknetSocket>,
111    sessions: Arc<Mutex<HashMap<SocketAddr, SessionSender>>>,
112    close_notifier: Arc<tokio::sync::Semaphore>,
113    all_session_closed_notifier: Arc<Notify>,
114    version_map: Arc<Mutex<HashMap<SocketAddr, u8>>>,
115    motd_receiver: watch::Receiver<String>,
116    motd_sender: watch::Sender<String>,
117}
118
119impl RaknetListener {
120    /// Bind a RakNet listener to the specified UDP address.
121    ///
122    /// Call [`listen`](Self::listen) before accepting connections.
123    pub async fn bind(sockaddr: &SocketAddr) -> Result<Self> {
124        let socket =
125            std::net::UdpSocket::bind(sockaddr).map_err(|_| RaknetError::BindAddressError)?;
126        // A shared listener receives bursts from every connection. This changes
127        // only this socket; the OS may clamp the requested receive buffer.
128        if let Err(error) = socket2::SockRef::from(&socket).set_recv_buffer_size(2 * 1024 * 1024) {
129            raknet_log_debug!("could not enlarge the listener receive buffer: {error}");
130        }
131        Self::from_std(socket).await
132    }
133
134    /// Bind a listener with an explicit maximum nominal MTU in bytes.
135    ///
136    /// The maximum must be between 61 and 1,492 bytes. Offline negotiation
137    /// chooses the smaller of this limit and the client's request. Ordinary
138    /// listeners retain their 1,400-byte maximum.
139    pub async fn bind_with_maximum_mtu(sockaddr: &SocketAddr, maximum_mtu: u16) -> Result<Self> {
140        if !(61..=RAKNET_MAX_MTU).contains(&maximum_mtu) {
141            return Err(RaknetError::PacketSizeExceedMTU);
142        }
143        let mut listener = Self::bind(sockaddr).await?;
144        listener.maximum_mtu = maximum_mtu;
145        Ok(listener)
146    }
147
148    /// Bind a fixed group of UDP receive sockets on Linux.
149    ///
150    /// All shards use the same address, server GUID, MOTD and accept backlog.
151    /// Linux `SO_REUSEPORT` distributes peer flows across the fixed group. Create
152    /// every shard before listening and retain the group for the listener's lifetime.
153    /// The count must be at most 64; one shard uses the ordinary binding path.
154    /// This changes only these sockets and does not alter system network limits.
155    #[cfg(target_os = "linux")]
156    pub async fn bind_with_socket_shards(
157        sockaddr: &SocketAddr,
158        count: std::num::NonZeroUsize,
159    ) -> Result<Self> {
160        if count.get() == 1 {
161            return Self::bind(sockaddr).await;
162        }
163        if count.get() > 64 {
164            return Err(RaknetError::SocketError);
165        }
166        fn bind_socket(address: &SocketAddr) -> Result<std::net::UdpSocket> {
167            let socket = socket2::Socket::new(
168                socket2::Domain::for_address(*address),
169                socket2::Type::DGRAM,
170                Some(socket2::Protocol::UDP),
171            )
172            .map_err(|_| RaknetError::BindAddressError)?;
173            socket
174                .set_reuse_port(true)
175                .map_err(|_| RaknetError::SocketError)?;
176            socket
177                .set_recv_buffer_size(2 * 1024 * 1024)
178                .map_err(|_| RaknetError::SocketError)?;
179            socket
180                .bind(&(*address).into())
181                .map_err(|_| RaknetError::BindAddressError)?;
182            Ok(socket.into())
183        }
184        let mut listener = Self::from_std(bind_socket(sockaddr)?).await?;
185        let address = listener.local_addr()?;
186        for _ in 1..count.get() {
187            let mut shard = Self::from_std(bind_socket(&address)?).await?;
188            shard.guid = listener.guid;
189            shard.connection_sender = listener.connection_sender.clone();
190            shard.motd_sender = listener.motd_sender.clone();
191            shard.motd_receiver = listener.motd_receiver.clone();
192            listener.shards.push(shard);
193        }
194        Ok(listener)
195    }
196
197    /// Bind with a requested per-socket UDP receive buffer size.
198    ///
199    /// The OS may clamp the size to its existing limits. No system limits are
200    /// changed. Unlike [`bind`](Self::bind), a failed buffer request returns an error.
201    /// [`from_std`](Self::from_std) preserves the supplied socket's buffer settings.
202    pub async fn bind_with_receive_buffer_size(
203        sockaddr: &SocketAddr,
204        size: std::num::NonZeroUsize,
205    ) -> Result<Self> {
206        if size.get() > i32::MAX as usize {
207            return Err(RaknetError::SocketError);
208        }
209        let socket =
210            std::net::UdpSocket::bind(sockaddr).map_err(|_| RaknetError::BindAddressError)?;
211        socket2::SockRef::from(&socket)
212            .set_recv_buffer_size(size.get())
213            .map_err(|_| RaknetError::SocketError)?;
214        Self::from_std(socket).await
215    }
216
217    /// Sets the number of connections that may wait for [`accept`](Self::accept).
218    ///
219    /// The default backlog is 128. When it is full, new offline handshakes wait
220    /// for a retried request instead of allocating and immediately closing a session.
221    ///
222    /// # Panics
223    /// Panics if called after [`listen`](Self::listen).
224    pub fn with_accept_backlog(mut self, backlog: std::num::NonZeroUsize) -> Self {
225        assert!(
226            !self.listened,
227            "configure the accept backlog before listening"
228        );
229        let (sender, receiver) = channel(backlog.get());
230        for shard in &mut self.shards {
231            shard.connection_sender = sender.clone();
232        }
233        self.connection_sender = sender;
234        self.connection_receiver = receiver;
235        self
236    }
237
238    /// Enable idle maintenance for newly accepted connections on every shard.
239    ///
240    /// Disabled by default. See [`RaknetSocket::set_idle_maintenance`] for the
241    /// CPU savings and scheduling tradeoff. Configure before listening.
242    ///
243    /// # Panics
244    /// Panics if called after [`listen`](Self::listen).
245    pub fn with_idle_maintenance(mut self, enabled: bool) -> Self {
246        assert!(
247            !self.listened,
248            "configure idle maintenance before listening"
249        );
250        self.idle_maintenance = enabled;
251        for shard in &mut self.shards {
252            shard.idle_maintenance = enabled;
253        }
254        self
255    }
256
257    /// Enable Linux `recvmmsg` batches of up to 16 ready datagrams.
258    ///
259    /// Disabled by default: this can improve busy listeners' throughput but
260    /// costs extra work for sparse traffic. No timer waits to fill a batch.
261    /// The setting applies to every receive socket in a sharded listener.
262    ///
263    /// # Panics
264    /// Panics if called after [`listen`](Self::listen).
265    #[cfg(target_os = "linux")]
266    pub fn with_receive_batching(mut self, enabled: bool) -> Self {
267        assert!(
268            !self.listened,
269            "configure receive batching before listening"
270        );
271        self.receive_batching = enabled;
272        for shard in &mut self.shards {
273            shard.receive_batching = enabled;
274        }
275        self
276    }
277
278    /// Creates a listener from a standard UDP socket.
279    pub async fn from_std(socket: std::net::UdpSocket) -> Result<Self> {
280        socket
281            .set_nonblocking(true)
282            .map_err(|_| RaknetError::SetRaknetRawSocketError)?;
283        let socket =
284            UdpSocket::from_std(socket).map_err(|_| RaknetError::SetRaknetRawSocketError)?;
285        Self::from_udp_socket(socket).await
286    }
287
288    async fn from_udp_socket(socket: UdpSocket) -> Result<Self> {
289        let (connection_sender, connection_receiver) = channel::<RaknetSocket>(128);
290        let (motd_sender, motd_receiver) = watch::channel(String::new());
291        let listener = Self {
292            motd: String::new(),
293            shards: Vec::new(),
294            socket: Some(Arc::new(socket)),
295            guid: rand::random(),
296            listened: false,
297            maximum_mtu: RAKNET_CLIENT_MTU,
298            receive_batching: false,
299            idle_maintenance: false,
300            connection_receiver,
301            connection_sender,
302            sessions: Arc::new(Mutex::new(HashMap::new())),
303            close_notifier: Arc::new(tokio::sync::Semaphore::new(0)),
304            all_session_closed_notifier: Arc::new(Notify::new()),
305            version_map: Arc::new(Mutex::new(HashMap::new())),
306            motd_receiver,
307            motd_sender,
308        };
309
310        Ok(listener)
311    }
312
313    async fn start_session_collect(
314        &self,
315        socket: &Arc<UdpSocket>,
316        sessions: &Arc<Mutex<HashMap<SocketAddr, SessionSender>>>,
317        mut collect_receiver: Receiver<SocketAddr>,
318    ) {
319        let sessions = sessions.clone();
320        let version_map = self.version_map.clone();
321        let socket = socket.clone();
322        let close_notifier = self.close_notifier.clone();
323        let all_session_closed_notifier = self.all_session_closed_notifier.clone();
324        tokio::spawn(async move {
325            loop {
326                let addr: SocketAddr;
327
328                tokio::select! {
329                    a = collect_receiver.recv() => {
330                        match a {
331                            Some(p) => { addr = p },
332                            None => {
333                                raknet_log_debug!("session collector closed");
334                                break;
335                            },
336                        };
337                    },
338                    _ = close_notifier.acquire() => {
339                        raknet_log_debug!("session collector received close notification");
340                        break;
341                    }
342                }
343
344                let mut sessions = sessions.lock().await;
345                // A late collector message from an old peer must not remove
346                // a replacement connection that reused the same address.
347                if sessions
348                    .get(&addr)
349                    .is_some_and(|session| session.close.is_closed())
350                {
351                    match socket.send_to(&[PacketID::Disconnect.to_u8()], addr).await {
352                        Ok(_) => {}
353                        Err(e) => {
354                            raknet_log_error!("udp socket send_to error : {}", e);
355                        }
356                    };
357                    sessions.remove(&addr);
358                    version_map.lock().await.remove(&addr);
359                    raknet_log_debug!("collect socket : {}", addr);
360                }
361            }
362
363            let mut sessions = sessions.lock().await;
364
365            for (addr, session) in sessions.iter() {
366                session.close.close();
367
368                match socket.send_to(&[PacketID::Disconnect.to_u8()], addr).await {
369                    Ok(_) => {}
370                    Err(e) => {
371                        raknet_log_error!("udp socket send_to error : {}", e);
372                    }
373                };
374            }
375
376            while !sessions.is_empty() {
377                let addr = match collect_receiver.recv().await {
378                    Some(p) => p,
379                    None => {
380                        raknet_log_error!(
381                            "failed to clean up sessions; some connections may still be open"
382                        );
383                        break;
384                    }
385                };
386
387                if sessions.contains_key(&addr) {
388                    match socket.send_to(&[PacketID::Disconnect.to_u8()], addr).await {
389                        Ok(_) => {}
390                        Err(e) => {
391                            raknet_log_error!("udp socket send_to error : {}", e);
392                        }
393                    };
394                    sessions.remove(&addr);
395                    version_map.lock().await.remove(&addr);
396                    raknet_log_debug!("collect socket : {}", addr);
397                }
398            }
399
400            sessions.clear();
401            version_map.lock().await.clear();
402            all_session_closed_notifier.notify_one();
403
404            raknet_log_debug!("session collect closed");
405        });
406    }
407
408    /// Start receiving connection requests.
409    ///
410    /// Call this before [`accept`](Self::accept). Repeated calls have no effect.
411    pub async fn listen(&mut self) {
412        if self.close_notifier.is_closed() || self.listened {
413            return;
414        }
415        for shard in &mut self.shards {
416            // Only the parent owns discovery metadata. Prevent a shard from
417            // replacing the shared MOTD with its default during startup.
418            shard.motd = self.motd.clone();
419        }
420        self.listen_single().await;
421        for shard in &mut self.shards {
422            shard.motd = self.motd.clone();
423            shard.listen_single().await;
424        }
425    }
426
427    async fn listen_single(&mut self) {
428        if self.close_notifier.is_closed() || self.listened {
429            return;
430        }
431
432        let Some(socket) = self.socket.as_ref().cloned() else {
433            return;
434        };
435        let local_addr = match socket.local_addr() {
436            Ok(address) => address,
437            Err(error) => {
438                raknet_log_error!("failed to query listener address: {error}");
439                return;
440            }
441        };
442
443        if self.motd.is_empty() {
444            let _ = self
445                .set_motd(
446                    SERVER_NAME,
447                    MAX_CONNECTION,
448                    "486",
449                    "1.18.11",
450                    "Survival",
451                    local_addr.port(),
452                )
453                .await;
454        }
455
456        let guid = self.guid;
457        let maximum_mtu = self.maximum_mtu;
458        let receive_batching = self.receive_batching;
459        let idle_maintenance = self.idle_maintenance;
460        let sessions = self.sessions.clone();
461        let connection_sender = self.connection_sender.clone();
462
463        self.listened = true;
464
465        let (collect_sender, collect_receiver) = channel::<SocketAddr>(10);
466        let collect_sender = Arc::new(Mutex::new(collect_sender));
467        self.start_session_collect(&socket, &sessions, collect_receiver)
468            .await;
469
470        let close_notify = self.close_notifier.clone();
471        let version_map = self.version_map.clone();
472        let mut motd_receiver = self.motd_receiver.clone();
473
474        tokio::spawn(async move {
475            let mut buf = [0u8; 2048];
476            let mut datagrams = crate::udp::DatagramReceiver::new(receive_batching);
477            let mut pending_versions = HashMap::<SocketAddr, (u8, std::time::Instant)>::new();
478            let mut dispatch_cache = SessionDispatchCache::default();
479            let mut cleanup = tokio::time::interval(std::time::Duration::from_secs(30));
480
481            raknet_log_debug!("start listen worker : {}", local_addr);
482
483            loop {
484                let size: usize;
485                let addr: SocketAddr;
486
487                tokio::select! {
488                    a = datagrams.recv_from(&socket, &mut buf) => {
489                        match a {
490                            Ok(p) => {
491                                size = p.0;
492                                addr = p.1;
493                            },
494                            Err(e) => {
495                                raknet_log_debug!("server recv_from error {}" , e);
496                                break;
497                            },
498                        };
499                    },
500                    _ = cleanup.tick() => {
501                        pending_versions.retain(|_, (_, time)| time.elapsed().as_secs() < 60);
502                        dispatch_cache.prune();
503                        continue;
504                    },
505                    changed = motd_receiver.changed() => {
506                        if changed.is_err() {
507                            break;
508                        }
509                        let _ = motd_receiver.borrow_and_update();
510                        continue;
511                    },
512                    _ = close_notify.acquire() => {
513                        raknet_log_debug!("listen close notified");
514                        break;
515                    }
516                }
517
518                if size == 0 {
519                    continue;
520                }
521
522                let cur_status = match PacketID::from(buf[0]) {
523                    Ok(p) => p,
524                    Err(e) => {
525                        raknet_log_debug!("parse packetid faild : {:?}", e);
526                        continue;
527                    }
528                };
529
530                match cur_status {
531                    PacketID::UnconnectedPing1 => {
532                        let _ping = match read_packet_ping(&buf[..size]) {
533                            Ok(p) => p,
534                            Err(_) => continue,
535                        };
536
537                        let packet = crate::packet::PacketUnconnectedPong {
538                            time: cur_timestamp_millis(),
539                            guid,
540                            motd: motd_receiver.borrow_and_update().clone(),
541                        };
542
543                        let pong = match write_packet_pong(&packet) {
544                            Ok(p) => p,
545                            Err(_) => continue,
546                        };
547
548                        match socket.send_to(&pong, addr).await {
549                            Ok(_) => {}
550                            Err(e) => {
551                                raknet_log_error!("udp socket send_to error : {}", e);
552                            }
553                        };
554                        continue;
555                    }
556                    PacketID::UnconnectedPing2 => {
557                        match read_packet_ping(&buf[..size]) {
558                            Ok(p) => p,
559                            Err(_) => continue,
560                        };
561
562                        let packet = crate::packet::PacketUnconnectedPong {
563                            time: cur_timestamp_millis(),
564                            guid,
565                            motd: motd_receiver.borrow_and_update().clone(),
566                        };
567
568                        let pong = match write_packet_pong(&packet) {
569                            Ok(p) => p,
570                            Err(_) => continue,
571                        };
572
573                        match socket.send_to(&pong, addr).await {
574                            Ok(_) => {}
575                            Err(e) => {
576                                raknet_log_error!("udp socket send_to error : {}", e);
577                            }
578                        };
579                        continue;
580                    }
581                    PacketID::OpenConnectionRequest1 => {
582                        let req = match read_packet_connection_open_request_1(&buf[..size]) {
583                            Ok(p) => p,
584                            Err(_) => continue,
585                        };
586
587                        if !RAKNET_PROTOCOL_VERSION_LIST
588                            .as_slice()
589                            .contains(&req.protocol_version)
590                        {
591                            let packet = crate::packet::IncompatibleProtocolVersion {
592                                server_protocol: RAKNET_PROTOCOL_VERSION,
593                                server_guid: guid,
594                            };
595                            let buf = match write_packet_incompatible_protocol_version(&packet) {
596                                Ok(buf) => buf,
597                                Err(error) => {
598                                    raknet_log_error!("failed to encode protocol error: {error}");
599                                    continue;
600                                }
601                            };
602
603                            match socket.send_to(&buf, addr).await {
604                                Ok(_) => {}
605                                Err(e) => {
606                                    raknet_log_error!("udp socket send_to error : {}", e);
607                                }
608                            };
609                            continue;
610                        }
611                        if pending_versions.len() >= 4096 && !pending_versions.contains_key(&addr) {
612                            continue;
613                        }
614                        pending_versions
615                            .insert(addr, (req.protocol_version, std::time::Instant::now()));
616
617                        let packet = crate::packet::OpenConnectionReply1 {
618                            guid,
619                            // Encryption is not negotiated by this implementation.
620                            use_encryption: 0x00,
621                            mtu_size: req.mtu_size.min(maximum_mtu),
622                        };
623
624                        let reply = match write_packet_connection_open_reply_1(&packet) {
625                            Ok(p) => p,
626                            Err(_) => continue,
627                        };
628
629                        match socket.send_to(&reply, addr).await {
630                            Ok(_) => {}
631                            Err(e) => {
632                                raknet_log_error!("udp socket send_to error : {}", e);
633                            }
634                        };
635                        continue;
636                    }
637                    PacketID::OpenConnectionRequest2 => {
638                        dispatch_cache.forget(&addr);
639                        let req = match read_packet_connection_open_request_2(&buf[..size]) {
640                            Ok(p) => p,
641                            Err(_) => continue,
642                        };
643
644                        if !(61..=maximum_mtu).contains(&req.mtu) {
645                            continue;
646                        }
647                        let existing = sessions
648                            .lock()
649                            .await
650                            .get(&addr)
651                            .map(|session| (session.guid, session.mtu));
652                        if let Some((client_guid, mtu)) = existing {
653                            // A lost offline reply causes Request2 retransmission.
654                            // Replay the negotiated response without creating a session.
655                            let reply = if client_guid == req.guid {
656                                write_packet_connection_open_reply_2(&OpenConnectionReply2 {
657                                    guid,
658                                    address: addr,
659                                    mtu,
660                                    encryption_enabled: 0,
661                                })
662                            } else {
663                                write_packet_already_connected(&AlreadyConnected { guid })
664                            };
665                            if let Ok(reply) = reply {
666                                let _ = socket.send_to(&reply, addr).await;
667                            }
668                            continue;
669                        }
670
671                        // Reserve acceptance before acknowledging the offline handshake.
672                        // A full backlog must not create a session only to disconnect it.
673                        let accept_slot = match connection_sender.try_reserve() {
674                            Ok(slot) => slot,
675                            Err(tokio::sync::mpsc::error::TrySendError::Full(_)) => continue,
676                            Err(tokio::sync::mpsc::error::TrySendError::Closed(_)) => break,
677                        };
678
679                        let packet = crate::packet::OpenConnectionReply2 {
680                            guid,
681                            address: addr,
682                            mtu: req.mtu,
683                            encryption_enabled: 0x00,
684                        };
685
686                        let reply = match write_packet_connection_open_reply_2(&packet) {
687                            Ok(p) => p,
688                            Err(_) => continue,
689                        };
690
691                        if let Err(e) = socket.send_to(&reply, addr).await {
692                            raknet_log_error!("udp socket send_to error : {}", e);
693                            continue;
694                        }
695
696                        // Cover the 64-datagram flight window plus control traffic.
697                        let (sender, receiver) = channel::<Vec<u8>>(128);
698                        let raknet_version = pending_versions
699                            .remove(&addr)
700                            .filter(|(_, time)| time.elapsed().as_secs() < 60)
701                            .map(|(version, _)| version)
702                            .unwrap_or(RAKNET_PROTOCOL_VERSION);
703                        version_map.lock().await.insert(addr, raknet_version);
704
705                        let raknet_socket = RaknetSocket::from(
706                            &addr,
707                            &socket,
708                            receiver,
709                            req.mtu,
710                            collect_sender.clone(),
711                            raknet_version,
712                        )
713                        .await;
714                        if idle_maintenance {
715                            raknet_socket.set_idle_maintenance(true);
716                        }
717
718                        sessions.lock().await.insert(
719                            addr,
720                            SessionSender {
721                                sender,
722                                close: raknet_socket.close_signal(),
723                                guid: req.guid,
724                                mtu: req.mtu,
725                            },
726                        );
727
728                        raknet_log_debug!("accept connection : {}", addr);
729                        accept_slot.send(raknet_socket);
730                    }
731                    PacketID::Disconnect => {
732                        dispatch_cache.forget(&addr);
733                        let session_sender = sessions
734                            .lock()
735                            .await
736                            .remove(&addr)
737                            .map(|session| session.close);
738                        if let Some(session_sender) = session_sender {
739                            session_sender.close();
740                            version_map.lock().await.remove(&addr);
741                        }
742                    }
743                    _ => {
744                        let result = if let Some(sender) = dispatch_cache.sender(&addr) {
745                            // Preserve the cooperative budget consumed by the map
746                            // lock on the uncached path. A busy UDP listener must
747                            // still give protocol and application tasks time to run.
748                            tokio::task::consume_budget().await;
749                            Some(sender.try_send(buf[..size].to_vec()))
750                        } else {
751                            dispatch_cache.forget(&addr);
752                            let sessions = sessions.lock().await;
753                            sessions.get(&addr).map(|session| {
754                                let result = session.sender.try_send(buf[..size].to_vec());
755                                dispatch_cache.remember(addr, session);
756                                result
757                            })
758                        };
759                        match result {
760                            Some(Ok(())) | None => {}
761                            Some(Err(tokio::sync::mpsc::error::TrySendError::Full(_))) => {
762                                raknet_log_debug!("session receive queue full for {}", addr);
763                            }
764                            Some(Err(tokio::sync::mpsc::error::TrySendError::Closed(_))) => {
765                                dispatch_cache.forget(&addr);
766                                sessions.lock().await.remove(&addr);
767                                version_map.lock().await.remove(&addr);
768                            }
769                        }
770                    }
771                }
772            }
773            raknet_log_debug!("listen worker closed");
774        });
775    }
776
777    /// Wait for and accept the next incoming RakNet connection.
778    ///
779    /// Call [`listen`](Self::listen) first.
780    ///
781    /// # Example
782    /// ```ignore
783    /// let mut listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
784    /// listener.listen().await;
785    /// let mut socket = listener.accept().await.unwrap();
786    /// ```
787    pub async fn accept(&mut self) -> Result<RaknetSocket> {
788        if !self.listened {
789            Err(RaknetError::NotListen)
790        } else {
791            tokio::select! {
792                a = self.connection_receiver.recv() => {
793                    match a {
794                        Some(p) => Ok(p),
795                        None => {
796                            Err(RaknetError::NotListen)
797                        },
798                    }
799                },
800                _ = self.close_notifier.acquire() => {
801                    raknet_log_debug!("accept close notified");
802                    Err(RaknetError::NotListen)
803                }
804            }
805        }
806    }
807
808    /// Get the GUID, a random number that uniquely identifies the listener instance.
809    pub fn get_guid(&self) -> u64 {
810        self.guid
811    }
812
813    /// Set the server-list MOTD returned in unconnected pong packets.
814    ///
815    /// Future ping responses use the updated value.
816    ///
817    /// # Example
818    /// ```ignore
819    /// let mut listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
820    /// listener.set_motd("Bedrock Server", 20, "protocol", "version", "Survival", 19132).await?;
821    /// ```
822    pub async fn set_motd(
823        &mut self,
824        server_name: &str,
825        max_connection: u32,
826        mc_protocol_version: &str,
827        mc_version: &str,
828        game_type: &str,
829        port: u16,
830    ) -> Result<()> {
831        let motd = format!(
832            "MCPE;{};{};{};0;{};{};Bedrock level;{};1;{};",
833            server_name,
834            mc_protocol_version,
835            mc_version,
836            max_connection,
837            self.guid,
838            game_type,
839            port
840        );
841
842        self.motd = motd.clone();
843        self.motd_sender.send_replace(motd);
844        Ok(())
845    }
846
847    /// Return the MOTD sent in unconnected pong packets.
848    ///
849    /// # Example
850    /// ```ignore
851    /// let listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
852    /// let motd = listener.get_motd().await;
853    /// ```
854    pub async fn get_motd(&self) -> String {
855        self.motd.clone()
856    }
857
858    /// Return the local UDP address used by this listener.
859    ///
860    /// # Example
861    /// ```ignore
862    /// let mut socket = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
863    /// assert_eq!(socket.local_addr().unwrap().ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
864    /// ```
865    pub fn local_addr(&self) -> Result<SocketAddr> {
866        self.socket
867            .as_ref()
868            .ok_or(RaknetError::ConnectionClosed)?
869            .local_addr()
870            .map_err(|_| RaknetError::SocketError)
871    }
872
873    /// Close the listener and all active connections.
874    ///
875    /// # Example
876    /// ```ignore
877    /// let mut socket = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
878    /// socket.close().await;
879    /// ```
880    pub async fn close(&mut self) -> Result<()> {
881        // Signal the whole group before releasing any socket. Active flows must
882        // never be remapped onto a shard that is still accepting new sessions.
883        self.close_notifier.close();
884        for shard in &self.shards {
885            shard.close_notifier.close();
886        }
887        self.close_single().await?;
888        for shard in &mut self.shards {
889            shard.close_single().await?;
890        }
891        Ok(())
892    }
893
894    async fn close_single(&mut self) -> Result<()> {
895        if self.socket.is_none() {
896            return Ok(());
897        }
898        self.close_notifier.close();
899        if self.listened {
900            self.all_session_closed_notifier.notified().await;
901        }
902        if let Some(socket) = self.socket.as_ref() {
903            while Arc::strong_count(socket) != 1 {
904                tokio::task::yield_now().await;
905            }
906        }
907        self.socket = None;
908        self.listened = false;
909        Ok(())
910    }
911
912    /// Set the full MOTD string used by future unconnected pong responses.
913    ///
914    /// # Example
915    /// ```ignore
916    /// let mut listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
917    /// listener.set_full_motd(String::from("motd")).await.unwrap();
918    /// ```
919    pub async fn set_full_motd(&mut self, motd: String) -> Result<()> {
920        self.motd = motd.clone();
921        self.motd_sender.send_replace(motd);
922        Ok(())
923    }
924
925    pub async fn get_peer_raknet_version(&self, peer: &SocketAddr) -> Result<u8> {
926        if let Some(version) = self.version_map.lock().await.get(peer).copied() {
927            return Ok(version);
928        }
929        for shard in &self.shards {
930            if let Some(version) = shard.version_map.lock().await.get(peer).copied() {
931                return Ok(version);
932            }
933        }
934        Ok(RAKNET_PROTOCOL_VERSION)
935    }
936}
937
938impl Drop for RaknetListener {
939    fn drop(&mut self) {
940        self.close_notifier.close();
941    }
942}
943
944#[tokio::test]
945async fn supplied_udp_socket_keeps_its_receive_buffer_configuration() {
946    let socket = std::net::UdpSocket::bind("127.0.0.1:0").unwrap();
947    socket2::SockRef::from(&socket)
948        .set_recv_buffer_size(8192)
949        .unwrap();
950    let before = socket2::SockRef::from(&socket).recv_buffer_size().unwrap();
951    let listener = RaknetListener::from_std(socket).await.unwrap();
952    let socket = listener.socket.as_ref().unwrap();
953    assert_eq!(
954        socket2::SockRef::from(socket.as_ref())
955            .recv_buffer_size()
956            .unwrap(),
957        before
958    );
959}
960
961#[tokio::test]
962async fn custom_receive_buffer_binds_and_rejects_unrepresentable_sizes() {
963    let address = "127.0.0.1:0".parse().unwrap();
964    let listener = RaknetListener::bind_with_receive_buffer_size(
965        &address,
966        std::num::NonZeroUsize::new(8192).unwrap(),
967    )
968    .await
969    .unwrap();
970    assert_ne!(listener.local_addr().unwrap().port(), 0);
971    assert!(matches!(
972        RaknetListener::bind_with_receive_buffer_size(
973            &address,
974            std::num::NonZeroUsize::new(usize::MAX).unwrap(),
975        )
976        .await,
977        Err(RaknetError::SocketError)
978    ));
979}
980
981#[cfg(all(test, target_os = "linux"))]
982mod shard_tests {
983    use super::*;
984    use crate::arq::Reliability;
985    use std::{num::NonZeroUsize, time::Duration};
986    use tokio::{task::JoinSet, time::timeout};
987
988    #[tokio::test(flavor = "multi_thread", worker_threads = 4)]
989    async fn shards_share_discovery_backlog_versions_and_close_all_sessions() {
990        timeout(Duration::from_secs(10), async {
991            let mut listener = RaknetListener::bind_with_socket_shards(
992                &"127.0.0.1:0".parse().unwrap(),
993                NonZeroUsize::new(4).unwrap(),
994            )
995            .await
996            .unwrap()
997            .with_accept_backlog(NonZeroUsize::new(64).unwrap())
998            .with_receive_batching(true);
999            let address = listener.local_addr().unwrap();
1000            let guid = listener.get_guid();
1001            listener
1002                .set_full_motd("shared discovery".into())
1003                .await
1004                .unwrap();
1005            listener.listen().await;
1006            listener
1007                .set_full_motd("updated discovery".into())
1008                .await
1009                .unwrap();
1010            for _ in 0..32 {
1011                let socket = UdpSocket::bind("127.0.0.1:0").await.unwrap();
1012                let packet =
1013                    write_packet_ping(&PacketUnconnectedPing { time: 1, guid: 2 }).unwrap();
1014                socket.send_to(&packet, address).await.unwrap();
1015                let mut buffer = [0; 2048];
1016                let (size, _) = socket.recv_from(&mut buffer).await.unwrap();
1017                let pong = read_packet_pong(&buffer[..size]).unwrap();
1018                assert_eq!(pong.guid, guid);
1019                assert_eq!(pong.motd, "updated discovery");
1020            }
1021            let mut tasks = JoinSet::new();
1022            for index in 0..32 {
1023                tasks.spawn(async move {
1024                    let version = if index % 2 == 0 { 10 } else { 11 };
1025                    RaknetSocket::connect_with_version(&address, version)
1026                        .await
1027                        .unwrap()
1028                });
1029            }
1030            let mut servers = Vec::new();
1031            for _ in 0..32 {
1032                let server = listener.accept().await.unwrap();
1033                assert_eq!(
1034                    listener
1035                        .get_peer_raknet_version(&server.peer_addr().unwrap())
1036                        .await
1037                        .unwrap(),
1038                    server.raknet_version().unwrap()
1039                );
1040                servers.push(server);
1041            }
1042            let mut clients = Vec::new();
1043            while let Some(client) = tasks.join_next().await {
1044                clients.push(client.unwrap());
1045            }
1046            let mut occupied = usize::from(!listener.sessions.lock().await.is_empty());
1047            for shard in &listener.shards {
1048                occupied += usize::from(!shard.sessions.lock().await.is_empty());
1049            }
1050            assert!(occupied > 1, "flows did not reach multiple sockets");
1051            for server in &servers {
1052                server
1053                    .send(&[0xfe, 42], Reliability::ReliableOrdered)
1054                    .await
1055                    .unwrap();
1056            }
1057            for client in &clients {
1058                assert_eq!(client.recv().await.unwrap(), vec![0xfe, 42]);
1059            }
1060            listener.close().await.unwrap();
1061            listener.close().await.unwrap();
1062            assert!(listener.sessions.lock().await.is_empty());
1063            assert!(listener.socket.is_none());
1064            for shard in &listener.shards {
1065                assert!(shard.sessions.lock().await.is_empty());
1066                assert!(shard.socket.is_none());
1067            }
1068            for client in clients {
1069                assert!(client.recv().await.is_err());
1070            }
1071        })
1072        .await
1073        .expect("sharded listener stalled");
1074    }
1075
1076    #[tokio::test]
1077    async fn shard_count_is_bounded_and_one_uses_the_normal_listener() {
1078        let address = "127.0.0.1:0".parse().unwrap();
1079        assert!(
1080            RaknetListener::bind_with_socket_shards(&address, NonZeroUsize::new(65).unwrap(),)
1081                .await
1082                .is_err()
1083        );
1084        let mut listener = RaknetListener::bind_with_socket_shards(&address, NonZeroUsize::MIN)
1085            .await
1086            .unwrap();
1087        assert!(listener.shards.is_empty());
1088        listener.close().await.unwrap();
1089    }
1090}
1091
1092#[cfg(test)]
1093mod dispatch_cache_tests {
1094    use super::*;
1095
1096    fn session() -> (SessionSender, Receiver<Vec<u8>>) {
1097        let (sender, receiver) = channel(2);
1098        (
1099            SessionSender {
1100                sender,
1101                close: Arc::new(tokio::sync::Semaphore::new(0)),
1102                guid: 1,
1103                mtu: 1400,
1104            },
1105            receiver,
1106        )
1107    }
1108
1109    #[test]
1110    fn cache_rejects_closed_sessions_and_replaces_reused_addresses() {
1111        let address = "127.0.0.1:19132".parse().unwrap();
1112        let (first, _first_receiver) = session();
1113        let (second, second_receiver) = session();
1114        let mut cache = SessionDispatchCache::default();
1115        cache.remember(address, &first);
1116        assert!(cache.sender(&address).unwrap().same_channel(&first.sender));
1117        first.close.close();
1118        assert!(cache.sender(&address).is_none());
1119        cache.remember(address, &second);
1120        assert!(cache.sender(&address).unwrap().same_channel(&second.sender));
1121        drop(second_receiver);
1122        assert!(cache.sender(&address).is_none());
1123        cache.prune();
1124        assert!(cache.entries.iter().all(Option::is_none));
1125    }
1126
1127    #[tokio::test]
1128    async fn late_collection_does_not_remove_a_replacement_peer() {
1129        tokio::time::timeout(std::time::Duration::from_secs(2), async {
1130            let mut listener = RaknetListener::bind(&"127.0.0.1:0".parse().unwrap())
1131                .await
1132                .unwrap();
1133            let peer_socket = UdpSocket::bind("127.0.0.1:0").await.unwrap();
1134            let marker_socket = UdpSocket::bind("127.0.0.1:0").await.unwrap();
1135            let peer = peer_socket.local_addr().unwrap();
1136            let marker = marker_socket.local_addr().unwrap();
1137            let (replacement, _replacement_receiver) = session();
1138            let close = replacement.close.clone();
1139            let (old_marker, _marker_receiver) = session();
1140            old_marker.close.close();
1141            listener.sessions.lock().await.insert(peer, replacement);
1142            listener.sessions.lock().await.insert(marker, old_marker);
1143            listener.version_map.lock().await.insert(peer, 11);
1144            let (collect_sender, collect_receiver) = channel(2);
1145            listener
1146                .start_session_collect(
1147                    listener.socket.as_ref().unwrap(),
1148                    &listener.sessions,
1149                    collect_receiver,
1150                )
1151                .await;
1152            collect_sender.send(peer).await.unwrap();
1153            // The marker makes it observable that the earlier notification was processed.
1154            collect_sender.send(marker).await.unwrap();
1155            while listener.sessions.lock().await.contains_key(&marker) {
1156                tokio::task::yield_now().await;
1157            }
1158            assert!(listener.sessions.lock().await.contains_key(&peer));
1159            assert_eq!(listener.version_map.lock().await.get(&peer), Some(&11));
1160            let mut packet = [0; 32];
1161            assert_eq!(
1162                peer_socket.try_recv_from(&mut packet).unwrap_err().kind(),
1163                std::io::ErrorKind::WouldBlock
1164            );
1165            close.close();
1166            collect_sender.send(peer).await.unwrap();
1167            while listener.sessions.lock().await.contains_key(&peer) {
1168                tokio::task::yield_now().await;
1169            }
1170            let (length, _) = peer_socket.recv_from(&mut packet).await.unwrap();
1171            assert_eq!(&packet[..length], &[PacketID::Disconnect.to_u8()]);
1172            drop(collect_sender);
1173            listener.close().await.unwrap();
1174        })
1175        .await
1176        .expect("session collection stalled");
1177    }
1178
1179    #[test]
1180    fn collisions_never_dispatch_to_or_forget_another_peer() {
1181        let (first, _first_receiver) = session();
1182        let (second, _second_receiver) = session();
1183        let first_address = SocketAddr::from(([127, 0, 0, 1], 19132));
1184        let slot = SessionDispatchCache::slot(&first_address);
1185        let mut collisions = (1..=u16::MAX)
1186            .map(|port| SocketAddr::from(([127, 0, 0, 2], port)))
1187            .filter(|address| SessionDispatchCache::slot(address) == slot);
1188        let second_address = collisions.next().unwrap();
1189        let third_address = collisions.next().unwrap();
1190        let mut cache = SessionDispatchCache::default();
1191        cache.remember(first_address, &first);
1192        cache.remember(second_address, &second);
1193        assert!(cache.sender(&first_address).is_none());
1194        assert!(cache.sender(&third_address).is_none());
1195        assert!(
1196            cache
1197                .sender(&second_address)
1198                .unwrap()
1199                .same_channel(&second.sender)
1200        );
1201        cache.forget(&first_address);
1202        assert!(cache.sender(&second_address).is_some());
1203        cache.remember(third_address, &first);
1204        assert!(cache.sender(&second_address).is_none());
1205        assert!(
1206            cache
1207                .sender(&third_address)
1208                .unwrap()
1209                .same_channel(&first.sender)
1210        );
1211        for port in 1..=u16::MAX {
1212            cache.remember(SocketAddr::from(([127, 0, 0, 1], port)), &first);
1213        }
1214        assert_eq!(cache.entries.len(), SessionDispatchCache::LIMIT);
1215        assert_eq!(
1216            cache.entries.iter().filter(|entry| entry.is_some()).count(),
1217            SessionDispatchCache::LIMIT
1218        );
1219    }
1220
1221    #[test]
1222    fn equal_ports_on_different_ips_do_not_all_collide() {
1223        let slots: std::collections::HashSet<_> = (1..=200)
1224            .map(|last| SessionDispatchCache::slot(&SocketAddr::from(([10, 0, 0, last], 19132))))
1225            .collect();
1226        assert!(slots.len() > 180);
1227    }
1228}
1229
1230#[cfg(all(test, target_os = "linux"))]
1231mod receive_batch_configuration_tests {
1232    use super::*;
1233    #[tokio::test]
1234    async fn batching_defaults_off_and_configuration_reaches_every_shard() {
1235        let mut listener = RaknetListener::bind_with_socket_shards(
1236            &"127.0.0.1:0".parse().unwrap(),
1237            std::num::NonZeroUsize::new(4).unwrap(),
1238        )
1239        .await
1240        .unwrap();
1241        assert!(!listener.idle_maintenance);
1242        assert!(listener.shards.iter().all(|shard| !shard.idle_maintenance));
1243        listener = listener.with_idle_maintenance(true);
1244        assert!(listener.idle_maintenance);
1245        assert!(listener.shards.iter().all(|shard| shard.idle_maintenance));
1246        listener = listener.with_idle_maintenance(false);
1247        assert!(listener.shards.iter().all(|shard| !shard.idle_maintenance));
1248        assert!(!listener.receive_batching);
1249        assert!(listener.shards.iter().all(|shard| !shard.receive_batching));
1250        listener = listener.with_receive_batching(true);
1251        assert!(listener.receive_batching);
1252        assert!(listener.shards.iter().all(|shard| shard.receive_batching));
1253        listener = listener.with_receive_batching(false);
1254        assert!(listener.shards.iter().all(|shard| !shard.receive_batching));
1255        listener.close().await.unwrap();
1256    }
1257}