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
16type SessionSender = (i64, Sender<Vec<u8>>);
17
18/// A RakNet UDP server that accepts incoming connections.
19pub struct RaknetListener {
20    motd: String,
21    socket: Option<Arc<UdpSocket>>,
22    guid: u64,
23    listened: bool,
24    connection_receiver: Receiver<RaknetSocket>,
25    connection_sender: Sender<RaknetSocket>,
26    sessions: Arc<Mutex<HashMap<SocketAddr, SessionSender>>>,
27    close_notifier: Arc<tokio::sync::Semaphore>,
28    all_session_closed_notifier: Arc<Notify>,
29    drop_notifier: Arc<Notify>,
30    version_map: Arc<Mutex<HashMap<String, u8>>>,
31    motd_receiver: watch::Receiver<String>,
32    motd_sender: watch::Sender<String>,
33}
34
35impl RaknetListener {
36    /// Bind a RakNet listener to the specified UDP address.
37    ///
38    /// Call [`listen`](Self::listen) before accepting connections.
39    pub async fn bind(sockaddr: &SocketAddr) -> Result<Self> {
40        let socket = UdpSocket::bind(sockaddr)
41            .await
42            .map_err(|_| RaknetError::BindAddressError)?;
43        Self::from_udp_socket(socket).await
44    }
45
46    /// Creates a listener from a standard UDP socket.
47    pub async fn from_std(socket: std::net::UdpSocket) -> Result<Self> {
48        socket
49            .set_nonblocking(true)
50            .map_err(|_| RaknetError::SetRaknetRawSocketError)?;
51        let socket =
52            UdpSocket::from_std(socket).map_err(|_| RaknetError::SetRaknetRawSocketError)?;
53        Self::from_udp_socket(socket).await
54    }
55
56    async fn from_udp_socket(socket: UdpSocket) -> Result<Self> {
57        let (connection_sender, connection_receiver) = channel::<RaknetSocket>(10);
58        let (motd_sender, motd_receiver) = watch::channel(String::new());
59        let listener = Self {
60            motd: String::new(),
61            socket: Some(Arc::new(socket)),
62            guid: rand::random(),
63            listened: false,
64            connection_receiver,
65            connection_sender,
66            sessions: Arc::new(Mutex::new(HashMap::new())),
67            close_notifier: Arc::new(tokio::sync::Semaphore::new(0)),
68            all_session_closed_notifier: Arc::new(Notify::new()),
69            drop_notifier: Arc::new(Notify::new()),
70            version_map: Arc::new(Mutex::new(HashMap::new())),
71            motd_receiver,
72            motd_sender,
73        };
74
75        listener.drop_watcher().await;
76        Ok(listener)
77    }
78
79    async fn start_session_collect(
80        &self,
81        socket: &Arc<UdpSocket>,
82        sessions: &Arc<Mutex<HashMap<SocketAddr, SessionSender>>>,
83        mut collect_receiver: Receiver<SocketAddr>,
84    ) {
85        let sessions = sessions.clone();
86        let socket = socket.clone();
87        let close_notifier = self.close_notifier.clone();
88        let all_session_closed_notifier = self.all_session_closed_notifier.clone();
89        tokio::spawn(async move {
90            loop {
91                let addr: SocketAddr;
92
93                tokio::select! {
94                    a = collect_receiver.recv() => {
95                        match a {
96                            Some(p) => { addr = p },
97                            None => {
98                                raknet_log_debug!("session collector closed");
99                                break;
100                            },
101                        };
102                    },
103                    _ = close_notifier.acquire() => {
104                        raknet_log_debug!("session collector received close notification");
105                        break;
106                    }
107                }
108
109                let mut sessions = sessions.lock().await;
110                if sessions.contains_key(&addr) {
111                    match socket.send_to(&[PacketID::Disconnect.to_u8()], addr).await {
112                        Ok(_) => {}
113                        Err(e) => {
114                            raknet_log_error!("udp socket send_to error : {}", e);
115                        }
116                    };
117                    sessions.remove(&addr);
118                    raknet_log_debug!("collect socket : {}", addr);
119                }
120            }
121
122            let mut sessions = sessions.lock().await;
123
124            for (addr, (_, sender)) in sessions.iter() {
125                let _ = sender.send(vec![PacketID::Disconnect.to_u8()]).await;
126
127                match socket.send_to(&[PacketID::Disconnect.to_u8()], addr).await {
128                    Ok(_) => {}
129                    Err(e) => {
130                        raknet_log_error!("udp socket send_to error : {}", e);
131                    }
132                };
133            }
134
135            while !sessions.is_empty() {
136                let addr = match collect_receiver.recv().await {
137                    Some(p) => p,
138                    None => {
139                        raknet_log_error!(
140                            "failed to clean up sessions; some connections may still be open"
141                        );
142                        break;
143                    }
144                };
145
146                if sessions.contains_key(&addr) {
147                    match socket.send_to(&[PacketID::Disconnect.to_u8()], addr).await {
148                        Ok(_) => {}
149                        Err(e) => {
150                            raknet_log_error!("udp socket send_to error : {}", e);
151                        }
152                    };
153                    sessions.remove(&addr);
154                    raknet_log_debug!("collect socket : {}", addr);
155                }
156            }
157
158            sessions.clear();
159            all_session_closed_notifier.notify_one();
160
161            raknet_log_debug!("session collect closed");
162        });
163    }
164
165    /// Start receiving connection requests.
166    ///
167    /// Call this before [`accept`](Self::accept). Repeated calls have no effect.
168    pub async fn listen(&mut self) {
169        if self.close_notifier.is_closed() || self.listened {
170            return;
171        }
172
173        let Some(socket) = self.socket.as_ref().cloned() else {
174            return;
175        };
176        let local_addr = match socket.local_addr() {
177            Ok(address) => address,
178            Err(error) => {
179                raknet_log_error!("failed to query listener address: {error}");
180                return;
181            }
182        };
183
184        if self.motd.is_empty() {
185            let _ = self
186                .set_motd(
187                    SERVER_NAME,
188                    MAX_CONNECTION,
189                    "486",
190                    "1.18.11",
191                    "Survival",
192                    local_addr.port(),
193                )
194                .await;
195        }
196
197        let guid = self.guid;
198        let sessions = self.sessions.clone();
199        let connection_sender = self.connection_sender.clone();
200
201        self.listened = true;
202
203        let (collect_sender, collect_receiver) = channel::<SocketAddr>(10);
204        let collect_sender = Arc::new(Mutex::new(collect_sender));
205        self.start_session_collect(&socket, &sessions, collect_receiver)
206            .await;
207
208        let close_notify = self.close_notifier.clone();
209        let version_map = self.version_map.clone();
210        let mut motd_receiver = self.motd_receiver.clone();
211
212        tokio::spawn(async move {
213            let mut buf = [0u8; 2048];
214
215            raknet_log_debug!("start listen worker : {}", local_addr);
216
217            loop {
218                let size: usize;
219                let addr: SocketAddr;
220
221                tokio::select! {
222                    a = socket.recv_from(&mut buf) => {
223                        match a {
224                            Ok(p) => {
225                                size = p.0;
226                                addr = p.1;
227                            },
228                            Err(e) => {
229                                raknet_log_debug!("server recv_from error {}" , e);
230                                break;
231                            },
232                        };
233                    },
234                    changed = motd_receiver.changed() => {
235                        if changed.is_err() {
236                            break;
237                        }
238                        let _ = motd_receiver.borrow_and_update();
239                        continue;
240                    },
241                    _ = close_notify.acquire() => {
242                        raknet_log_debug!("listen close notified");
243                        break;
244                    }
245                }
246
247                if size == 0 {
248                    continue;
249                }
250
251                let new_motd = motd_receiver.borrow_and_update().clone();
252                let cur_status = match PacketID::from(buf[0]) {
253                    Ok(p) => p,
254                    Err(e) => {
255                        raknet_log_debug!("parse packetid faild : {:?}", e);
256                        continue;
257                    }
258                };
259
260                match cur_status {
261                    PacketID::UnconnectedPing1 => {
262                        let _ping = match read_packet_ping(&buf[..size]) {
263                            Ok(p) => p,
264                            Err(_) => continue,
265                        };
266
267                        let packet = crate::packet::PacketUnconnectedPong {
268                            time: cur_timestamp_millis(),
269                            guid,
270                            motd: new_motd,
271                        };
272
273                        let pong = match write_packet_pong(&packet) {
274                            Ok(p) => p,
275                            Err(_) => continue,
276                        };
277
278                        match socket.send_to(&pong, addr).await {
279                            Ok(_) => {}
280                            Err(e) => {
281                                raknet_log_error!("udp socket send_to error : {}", e);
282                            }
283                        };
284                        continue;
285                    }
286                    PacketID::UnconnectedPing2 => {
287                        match read_packet_ping(&buf[..size]) {
288                            Ok(p) => p,
289                            Err(_) => continue,
290                        };
291
292                        let packet = crate::packet::PacketUnconnectedPong {
293                            time: cur_timestamp_millis(),
294                            guid,
295                            motd: new_motd,
296                        };
297
298                        let pong = match write_packet_pong(&packet) {
299                            Ok(p) => p,
300                            Err(_) => continue,
301                        };
302
303                        match socket.send_to(&pong, addr).await {
304                            Ok(_) => {}
305                            Err(e) => {
306                                raknet_log_error!("udp socket send_to error : {}", e);
307                            }
308                        };
309                        continue;
310                    }
311                    PacketID::OpenConnectionRequest1 => {
312                        let req = match read_packet_connection_open_request_1(&buf[..size]) {
313                            Ok(p) => p,
314                            Err(_) => continue,
315                        };
316
317                        if !RAKNET_PROTOCOL_VERSION_LIST
318                            .as_slice()
319                            .contains(&req.protocol_version)
320                        {
321                            let packet = crate::packet::IncompatibleProtocolVersion {
322                                server_protocol: RAKNET_PROTOCOL_VERSION,
323                                server_guid: guid,
324                            };
325                            let buf = match write_packet_incompatible_protocol_version(&packet) {
326                                Ok(buf) => buf,
327                                Err(error) => {
328                                    raknet_log_error!("failed to encode protocol error: {error}");
329                                    continue;
330                                }
331                            };
332
333                            match socket.send_to(&buf, addr).await {
334                                Ok(_) => {}
335                                Err(e) => {
336                                    raknet_log_error!("udp socket send_to error : {}", e);
337                                }
338                            };
339                            continue;
340                        }
341                        {
342                            let mut version_map = version_map.lock().await;
343                            version_map.insert(addr.to_string(), req.protocol_version);
344                        }
345
346                        let packet = crate::packet::OpenConnectionReply1 {
347                            guid,
348                            // Encryption is not negotiated by this implementation.
349                            use_encryption: 0x00,
350                            mtu_size: RAKNET_CLIENT_MTU,
351                        };
352
353                        let reply = match write_packet_connection_open_reply_1(&packet) {
354                            Ok(p) => p,
355                            Err(_) => continue,
356                        };
357
358                        match socket.send_to(&reply, addr).await {
359                            Ok(_) => {}
360                            Err(e) => {
361                                raknet_log_error!("udp socket send_to error : {}", e);
362                            }
363                        };
364                        continue;
365                    }
366                    PacketID::OpenConnectionRequest2 => {
367                        let req = match read_packet_connection_open_request_2(&buf[..size]) {
368                            Ok(p) => p,
369                            Err(_) => continue,
370                        };
371
372                        let already_connected = { sessions.lock().await.contains_key(&addr) };
373                        if already_connected {
374                            if let Ok(packet) =
375                                write_packet_already_connected(&AlreadyConnected { guid })
376                            {
377                                let _ = socket.send_to(&packet, addr).await;
378                            }
379                            continue;
380                        }
381
382                        let packet = crate::packet::OpenConnectionReply2 {
383                            guid,
384                            address: addr,
385                            mtu: req.mtu,
386                            encryption_enabled: 0x00,
387                        };
388
389                        let reply = match write_packet_connection_open_reply_2(&packet) {
390                            Ok(p) => p,
391                            Err(_) => continue,
392                        };
393
394                        if let Err(e) = socket.send_to(&reply, addr).await {
395                            raknet_log_error!("udp socket send_to error : {}", e);
396                            continue;
397                        }
398
399                        let (sender, receiver) = channel::<Vec<u8>>(10);
400                        let raknet_version = {
401                            let version_map = version_map.lock().await;
402                            *version_map
403                                .get(&addr.to_string())
404                                .unwrap_or(&RAKNET_PROTOCOL_VERSION)
405                        };
406
407                        let raknet_socket = RaknetSocket::from(
408                            &addr,
409                            &socket,
410                            receiver,
411                            req.mtu,
412                            collect_sender.clone(),
413                            raknet_version,
414                        )
415                        .await;
416
417                        sessions
418                            .lock()
419                            .await
420                            .insert(addr, (cur_timestamp_millis(), sender));
421
422                        raknet_log_debug!("accept connection : {}", addr);
423                        if connection_sender.try_send(raknet_socket).is_err() {
424                            sessions.lock().await.remove(&addr);
425                            let _ = socket.send_to(&[PacketID::Disconnect.to_u8()], addr).await;
426                            raknet_log_debug!(
427                                "pending accept queue is full; disconnected {}",
428                                addr
429                            );
430                        }
431                    }
432                    PacketID::Disconnect => {
433                        let session_sender = sessions
434                            .lock()
435                            .await
436                            .remove(&addr)
437                            .map(|(_, sender)| sender);
438                        if let Some(session_sender) = session_sender {
439                            let _ = session_sender.try_send(buf[..size].to_vec());
440                        }
441                    }
442                    _ => {
443                        let session_sender = {
444                            let mut sessions = sessions.lock().await;
445                            sessions.get_mut(&addr).map(|(last_seen, sender)| {
446                                *last_seen = cur_timestamp_millis();
447                                sender.clone()
448                            })
449                        };
450
451                        if let Some(session_sender) = session_sender {
452                            match session_sender.try_send(buf[..size].to_vec()) {
453                                Ok(()) => {}
454                                Err(tokio::sync::mpsc::error::TrySendError::Full(_)) => {
455                                    raknet_log_debug!("session receive queue full for {}", addr);
456                                }
457                                Err(tokio::sync::mpsc::error::TrySendError::Closed(_)) => {
458                                    sessions.lock().await.remove(&addr);
459                                }
460                            }
461                        }
462                    }
463                }
464            }
465            raknet_log_debug!("listen worker closed");
466        });
467    }
468
469    /// Wait for and accept the next incoming RakNet connection.
470    ///
471    /// Call [`listen`](Self::listen) first.
472    ///
473    /// # Example
474    /// ```ignore
475    /// let mut listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
476    /// listener.listen().await;
477    /// let mut socket = listener.accept().await.unwrap();
478    /// ```
479    pub async fn accept(&mut self) -> Result<RaknetSocket> {
480        if !self.listened {
481            Err(RaknetError::NotListen)
482        } else {
483            tokio::select! {
484                a = self.connection_receiver.recv() => {
485                    match a {
486                        Some(p) => Ok(p),
487                        None => {
488                            Err(RaknetError::NotListen)
489                        },
490                    }
491                },
492                _ = self.close_notifier.acquire() => {
493                    raknet_log_debug!("accept close notified");
494                    Err(RaknetError::NotListen)
495                }
496            }
497        }
498    }
499
500    /// Get the GUID, a random number that uniquely identifies the listener instance.
501    pub fn get_guid(&self) -> u64 {
502        self.guid
503    }
504
505    /// Set the server-list MOTD returned in unconnected pong packets.
506    ///
507    /// Future ping responses use the updated value.
508    ///
509    /// # Example
510    /// ```ignore
511    /// let mut listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
512    /// listener.set_motd("Bedrock Server", 20, "protocol", "version", "Survival", 19132).await?;
513    /// ```
514    pub async fn set_motd(
515        &mut self,
516        server_name: &str,
517        max_connection: u32,
518        mc_protocol_version: &str,
519        mc_version: &str,
520        game_type: &str,
521        port: u16,
522    ) -> Result<()> {
523        let motd = format!(
524            "MCPE;{};{};{};0;{};{};Bedrock level;{};1;{};",
525            server_name,
526            mc_protocol_version,
527            mc_version,
528            max_connection,
529            self.guid,
530            game_type,
531            port
532        );
533
534        self.motd = motd.clone();
535        self.motd_sender.send_replace(motd);
536        Ok(())
537    }
538
539    /// Return the MOTD sent in unconnected pong packets.
540    ///
541    /// # Example
542    /// ```ignore
543    /// let listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
544    /// let motd = listener.get_motd().await;
545    /// ```
546    pub async fn get_motd(&self) -> String {
547        self.motd.clone()
548    }
549
550    /// Return the local UDP address used by this listener.
551    ///
552    /// # Example
553    /// ```ignore
554    /// let mut socket = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
555    /// assert_eq!(socket.local_addr().unwrap().ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
556    /// ```
557    pub fn local_addr(&self) -> Result<SocketAddr> {
558        self.socket
559            .as_ref()
560            .ok_or(RaknetError::ConnectionClosed)?
561            .local_addr()
562            .map_err(|_| RaknetError::SocketError)
563    }
564
565    /// Close the listener and all active connections.
566    ///
567    /// # Example
568    /// ```ignore
569    /// let mut socket = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
570    /// socket.close().await;
571    /// ```
572    pub async fn close(&mut self) -> Result<()> {
573        if self.close_notifier.is_closed() {
574            return Ok(());
575        }
576        self.close_notifier.close();
577        if self.listened {
578            self.all_session_closed_notifier.notified().await;
579        }
580
581        if let Some(socket) = self.socket.as_ref() {
582            while Arc::strong_count(socket) != 1 {
583                tokio::task::yield_now().await;
584            }
585        }
586        self.socket = None;
587        self.listened = false;
588
589        Ok(())
590    }
591
592    /// Set the full MOTD string used by future unconnected pong responses.
593    ///
594    /// # Example
595    /// ```ignore
596    /// let mut listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
597    /// listener.set_full_motd(String::from("motd")).await.unwrap();
598    /// ```
599    pub async fn set_full_motd(&mut self, motd: String) -> Result<()> {
600        self.motd = motd.clone();
601        self.motd_sender.send_replace(motd);
602        Ok(())
603    }
604
605    pub async fn get_peer_raknet_version(&self, peer: &SocketAddr) -> Result<u8> {
606        let version_map = self.version_map.lock().await;
607        let ver = version_map.get(&peer.to_string());
608        Ok(*ver.unwrap_or(&RAKNET_PROTOCOL_VERSION))
609    }
610
611    async fn drop_watcher(&self) {
612        let close_notifier = self.close_notifier.clone();
613        let drop_notifier = self.drop_notifier.clone();
614        tokio::spawn(async move {
615            raknet_log_debug!("listener drop watcher start");
616            drop_notifier.notify_one();
617
618            drop_notifier.notified().await;
619
620            if close_notifier.is_closed() {
621                raknet_log_debug!("close notifier closed");
622                return;
623            }
624
625            close_notifier.close();
626
627            raknet_log_debug!("listener drop watcher closed");
628        });
629
630        self.drop_notifier.notified().await;
631    }
632}
633
634impl Drop for RaknetListener {
635    fn drop(&mut self) {
636        self.drop_notifier.notify_one();
637    }
638}