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
23struct 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 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
99pub 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 pub async fn bind(sockaddr: &SocketAddr) -> Result<Self> {
124 let socket =
125 std::net::UdpSocket::bind(sockaddr).map_err(|_| RaknetError::BindAddressError)?;
126 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 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 #[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 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 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 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 #[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 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 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 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 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 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 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 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 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 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 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 pub fn get_guid(&self) -> u64 {
810 self.guid
811 }
812
813 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 pub async fn get_motd(&self) -> String {
855 self.motd.clone()
856 }
857
858 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 pub async fn close(&mut self) -> Result<()> {
881 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 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 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}