Skip to main content

RaknetListener

Struct RaknetListener 

Source
pub struct RaknetListener { /* private fields */ }
Expand description

A RakNet UDP server that accepts incoming connections.

Implementations§

Source§

impl RaknetListener

Source

pub async fn bind(sockaddr: &SocketAddr) -> Result<Self>

Bind a RakNet listener to the specified UDP address.

Call listen before accepting connections.

Source

pub async fn bind_with_maximum_mtu( sockaddr: &SocketAddr, maximum_mtu: u16, ) -> Result<Self>

Bind a listener with an explicit maximum nominal MTU in bytes.

The maximum must be between 61 and 1,492 bytes. Offline negotiation chooses the smaller of this limit and the client’s request. Ordinary listeners retain their 1,400-byte maximum.

Source

pub async fn bind_with_socket_shards( sockaddr: &SocketAddr, count: NonZeroUsize, ) -> Result<Self>

Bind a fixed group of UDP receive sockets on Linux.

All shards use the same address, server GUID, MOTD and accept backlog. Linux SO_REUSEPORT distributes peer flows across the fixed group. Create every shard before listening and retain the group for the listener’s lifetime. The count must be at most 64; one shard uses the ordinary binding path. This changes only these sockets and does not alter system network limits.

Examples found in repository?
examples/sharded_echo.rs (line 11)
4async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
5    use rust_raknet::{RaknetListener, Reliability};
6    let address = std::env::args().nth(1).ok_or("ADDRESS required")?.parse()?;
7    let count = std::env::args()
8        .nth(2)
9        .unwrap_or_else(|| "4".into())
10        .parse()?;
11    let mut listener = RaknetListener::bind_with_socket_shards(&address, count).await?;
12    let mut batch_messages = false;
13    for option in std::env::args().skip(3) {
14        listener = match option.as_str() {
15            "--receive-batching" => listener.with_receive_batching(true),
16            "--idle-maintenance" => listener.with_idle_maintenance(true),
17            "--batch-messages" => {
18                batch_messages = true;
19                listener
20            }
21            _ => return Err(format!("unknown option: {option}").into()),
22        };
23    }
24    listener.listen().await;
25    println!("Sharded echo listening on {}", listener.local_addr()?);
26    loop {
27        let client = listener.accept().await?;
28        if batch_messages {
29            tokio::spawn(async move {
30                let mut messages = Vec::with_capacity(16);
31                while client.recv_bytes_batch(&mut messages, 16).await.is_ok() {
32                    if client
33                        .send_bytes_batch(&messages, Reliability::ReliableOrdered)
34                        .await
35                        .is_err()
36                    {
37                        break;
38                    }
39                    if messages.len() == 16 {
40                        tokio::task::yield_now().await;
41                    }
42                }
43            });
44        } else {
45            tokio::spawn(async move {
46                while let Ok(payload) = client.recv().await {
47                    if client
48                        .send(&payload, Reliability::ReliableOrdered)
49                        .await
50                        .is_err()
51                    {
52                        break;
53                    }
54                }
55            });
56        }
57    }
58}
Source

pub async fn bind_with_receive_buffer_size( sockaddr: &SocketAddr, size: NonZeroUsize, ) -> Result<Self>

Bind with a requested per-socket UDP receive buffer size.

The OS may clamp the size to its existing limits. No system limits are changed. Unlike bind, a failed buffer request returns an error. from_std preserves the supplied socket’s buffer settings.

Source

pub fn with_accept_backlog(self, backlog: NonZeroUsize) -> Self

Sets the number of connections that may wait for accept.

The default backlog is 128. When it is full, new offline handshakes wait for a retried request instead of allocating and immediately closing a session.

§Panics

Panics if called after listen.

Source

pub fn with_idle_maintenance(self, enabled: bool) -> Self

Enable idle maintenance for newly accepted connections on every shard.

Disabled by default. See RaknetSocket::set_idle_maintenance for the CPU savings and scheduling tradeoff. Configure before listening.

§Panics

Panics if called after listen.

Examples found in repository?
examples/sharded_echo.rs (line 16)
4async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
5    use rust_raknet::{RaknetListener, Reliability};
6    let address = std::env::args().nth(1).ok_or("ADDRESS required")?.parse()?;
7    let count = std::env::args()
8        .nth(2)
9        .unwrap_or_else(|| "4".into())
10        .parse()?;
11    let mut listener = RaknetListener::bind_with_socket_shards(&address, count).await?;
12    let mut batch_messages = false;
13    for option in std::env::args().skip(3) {
14        listener = match option.as_str() {
15            "--receive-batching" => listener.with_receive_batching(true),
16            "--idle-maintenance" => listener.with_idle_maintenance(true),
17            "--batch-messages" => {
18                batch_messages = true;
19                listener
20            }
21            _ => return Err(format!("unknown option: {option}").into()),
22        };
23    }
24    listener.listen().await;
25    println!("Sharded echo listening on {}", listener.local_addr()?);
26    loop {
27        let client = listener.accept().await?;
28        if batch_messages {
29            tokio::spawn(async move {
30                let mut messages = Vec::with_capacity(16);
31                while client.recv_bytes_batch(&mut messages, 16).await.is_ok() {
32                    if client
33                        .send_bytes_batch(&messages, Reliability::ReliableOrdered)
34                        .await
35                        .is_err()
36                    {
37                        break;
38                    }
39                    if messages.len() == 16 {
40                        tokio::task::yield_now().await;
41                    }
42                }
43            });
44        } else {
45            tokio::spawn(async move {
46                while let Ok(payload) = client.recv().await {
47                    if client
48                        .send(&payload, Reliability::ReliableOrdered)
49                        .await
50                        .is_err()
51                    {
52                        break;
53                    }
54                }
55            });
56        }
57    }
58}
Source

pub fn with_receive_batching(self, enabled: bool) -> Self

Enable Linux recvmmsg batches of up to 16 ready datagrams.

Disabled by default: this can improve busy listeners’ throughput but costs extra work for sparse traffic. No timer waits to fill a batch. The setting applies to every receive socket in a sharded listener.

§Panics

Panics if called after listen.

Examples found in repository?
examples/sharded_echo.rs (line 15)
4async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
5    use rust_raknet::{RaknetListener, Reliability};
6    let address = std::env::args().nth(1).ok_or("ADDRESS required")?.parse()?;
7    let count = std::env::args()
8        .nth(2)
9        .unwrap_or_else(|| "4".into())
10        .parse()?;
11    let mut listener = RaknetListener::bind_with_socket_shards(&address, count).await?;
12    let mut batch_messages = false;
13    for option in std::env::args().skip(3) {
14        listener = match option.as_str() {
15            "--receive-batching" => listener.with_receive_batching(true),
16            "--idle-maintenance" => listener.with_idle_maintenance(true),
17            "--batch-messages" => {
18                batch_messages = true;
19                listener
20            }
21            _ => return Err(format!("unknown option: {option}").into()),
22        };
23    }
24    listener.listen().await;
25    println!("Sharded echo listening on {}", listener.local_addr()?);
26    loop {
27        let client = listener.accept().await?;
28        if batch_messages {
29            tokio::spawn(async move {
30                let mut messages = Vec::with_capacity(16);
31                while client.recv_bytes_batch(&mut messages, 16).await.is_ok() {
32                    if client
33                        .send_bytes_batch(&messages, Reliability::ReliableOrdered)
34                        .await
35                        .is_err()
36                    {
37                        break;
38                    }
39                    if messages.len() == 16 {
40                        tokio::task::yield_now().await;
41                    }
42                }
43            });
44        } else {
45            tokio::spawn(async move {
46                while let Ok(payload) = client.recv().await {
47                    if client
48                        .send(&payload, Reliability::ReliableOrdered)
49                        .await
50                        .is_err()
51                    {
52                        break;
53                    }
54                }
55            });
56        }
57    }
58}
Source

pub async fn from_std(socket: UdpSocket) -> Result<Self>

Creates a listener from a standard UDP socket.

Source

pub async fn listen(&mut self)

Start receiving connection requests.

Call this before accept. Repeated calls have no effect.

Examples found in repository?
examples/sharded_echo.rs (line 24)
4async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
5    use rust_raknet::{RaknetListener, Reliability};
6    let address = std::env::args().nth(1).ok_or("ADDRESS required")?.parse()?;
7    let count = std::env::args()
8        .nth(2)
9        .unwrap_or_else(|| "4".into())
10        .parse()?;
11    let mut listener = RaknetListener::bind_with_socket_shards(&address, count).await?;
12    let mut batch_messages = false;
13    for option in std::env::args().skip(3) {
14        listener = match option.as_str() {
15            "--receive-batching" => listener.with_receive_batching(true),
16            "--idle-maintenance" => listener.with_idle_maintenance(true),
17            "--batch-messages" => {
18                batch_messages = true;
19                listener
20            }
21            _ => return Err(format!("unknown option: {option}").into()),
22        };
23    }
24    listener.listen().await;
25    println!("Sharded echo listening on {}", listener.local_addr()?);
26    loop {
27        let client = listener.accept().await?;
28        if batch_messages {
29            tokio::spawn(async move {
30                let mut messages = Vec::with_capacity(16);
31                while client.recv_bytes_batch(&mut messages, 16).await.is_ok() {
32                    if client
33                        .send_bytes_batch(&messages, Reliability::ReliableOrdered)
34                        .await
35                        .is_err()
36                    {
37                        break;
38                    }
39                    if messages.len() == 16 {
40                        tokio::task::yield_now().await;
41                    }
42                }
43            });
44        } else {
45            tokio::spawn(async move {
46                while let Ok(payload) = client.recv().await {
47                    if client
48                        .send(&payload, Reliability::ReliableOrdered)
49                        .await
50                        .is_err()
51                    {
52                        break;
53                    }
54                }
55            });
56        }
57    }
58}
Source

pub async fn accept(&mut self) -> Result<RaknetSocket>

Wait for and accept the next incoming RakNet connection.

Call listen first.

§Example
ⓘ
let mut listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
listener.listen().await;
let mut socket = listener.accept().await.unwrap();
Examples found in repository?
examples/sharded_echo.rs (line 27)
4async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
5    use rust_raknet::{RaknetListener, Reliability};
6    let address = std::env::args().nth(1).ok_or("ADDRESS required")?.parse()?;
7    let count = std::env::args()
8        .nth(2)
9        .unwrap_or_else(|| "4".into())
10        .parse()?;
11    let mut listener = RaknetListener::bind_with_socket_shards(&address, count).await?;
12    let mut batch_messages = false;
13    for option in std::env::args().skip(3) {
14        listener = match option.as_str() {
15            "--receive-batching" => listener.with_receive_batching(true),
16            "--idle-maintenance" => listener.with_idle_maintenance(true),
17            "--batch-messages" => {
18                batch_messages = true;
19                listener
20            }
21            _ => return Err(format!("unknown option: {option}").into()),
22        };
23    }
24    listener.listen().await;
25    println!("Sharded echo listening on {}", listener.local_addr()?);
26    loop {
27        let client = listener.accept().await?;
28        if batch_messages {
29            tokio::spawn(async move {
30                let mut messages = Vec::with_capacity(16);
31                while client.recv_bytes_batch(&mut messages, 16).await.is_ok() {
32                    if client
33                        .send_bytes_batch(&messages, Reliability::ReliableOrdered)
34                        .await
35                        .is_err()
36                    {
37                        break;
38                    }
39                    if messages.len() == 16 {
40                        tokio::task::yield_now().await;
41                    }
42                }
43            });
44        } else {
45            tokio::spawn(async move {
46                while let Ok(payload) = client.recv().await {
47                    if client
48                        .send(&payload, Reliability::ReliableOrdered)
49                        .await
50                        .is_err()
51                    {
52                        break;
53                    }
54                }
55            });
56        }
57    }
58}
Source

pub fn get_guid(&self) -> u64

Get the GUID, a random number that uniquely identifies the listener instance.

Source

pub async fn set_motd( &mut self, server_name: &str, max_connection: u32, mc_protocol_version: &str, mc_version: &str, game_type: &str, port: u16, ) -> Result<()>

Set the server-list MOTD returned in unconnected pong packets.

Future ping responses use the updated value.

§Example
ⓘ
let mut listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
listener.set_motd("Bedrock Server", 20, "protocol", "version", "Survival", 19132).await?;
Source

pub async fn get_motd(&self) -> String

Return the MOTD sent in unconnected pong packets.

§Example
ⓘ
let listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
let motd = listener.get_motd().await;
Source

pub fn local_addr(&self) -> Result<SocketAddr>

Return the local UDP address used by this listener.

§Example
ⓘ
let mut socket = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
assert_eq!(socket.local_addr().unwrap().ip(), IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)));
Examples found in repository?
examples/sharded_echo.rs (line 25)
4async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
5    use rust_raknet::{RaknetListener, Reliability};
6    let address = std::env::args().nth(1).ok_or("ADDRESS required")?.parse()?;
7    let count = std::env::args()
8        .nth(2)
9        .unwrap_or_else(|| "4".into())
10        .parse()?;
11    let mut listener = RaknetListener::bind_with_socket_shards(&address, count).await?;
12    let mut batch_messages = false;
13    for option in std::env::args().skip(3) {
14        listener = match option.as_str() {
15            "--receive-batching" => listener.with_receive_batching(true),
16            "--idle-maintenance" => listener.with_idle_maintenance(true),
17            "--batch-messages" => {
18                batch_messages = true;
19                listener
20            }
21            _ => return Err(format!("unknown option: {option}").into()),
22        };
23    }
24    listener.listen().await;
25    println!("Sharded echo listening on {}", listener.local_addr()?);
26    loop {
27        let client = listener.accept().await?;
28        if batch_messages {
29            tokio::spawn(async move {
30                let mut messages = Vec::with_capacity(16);
31                while client.recv_bytes_batch(&mut messages, 16).await.is_ok() {
32                    if client
33                        .send_bytes_batch(&messages, Reliability::ReliableOrdered)
34                        .await
35                        .is_err()
36                    {
37                        break;
38                    }
39                    if messages.len() == 16 {
40                        tokio::task::yield_now().await;
41                    }
42                }
43            });
44        } else {
45            tokio::spawn(async move {
46                while let Ok(payload) = client.recv().await {
47                    if client
48                        .send(&payload, Reliability::ReliableOrdered)
49                        .await
50                        .is_err()
51                    {
52                        break;
53                    }
54                }
55            });
56        }
57    }
58}
Source

pub async fn close(&mut self) -> Result<()>

Close the listener and all active connections.

§Example
ⓘ
let mut socket = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
socket.close().await;
Source

pub async fn set_full_motd(&mut self, motd: String) -> Result<()>

Set the full MOTD string used by future unconnected pong responses.

§Example
ⓘ
let mut listener = RaknetListener::bind("127.0.0.1:19132".parse().unwrap()).await.unwrap();
listener.set_full_motd(String::from("motd")).await.unwrap();
Source

pub async fn get_peer_raknet_version(&self, peer: &SocketAddr) -> Result<u8>

Trait Implementations§

Source§

impl Drop for RaknetListener

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V