NetcodeClient

Struct NetcodeClient 

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

A client that can generate encrypted packets that be sent to the connected server, or consume encrypted packets from the server. The client is agnostic from the transport layer, only consuming and generating bytes that can be transported in any way desired.

Implementations§

Source§

impl NetcodeClient

Source

pub fn new( current_time: Duration, authentication: ClientAuthentication, ) -> Result<Self, NetcodeError>

Examples found in repository?
examples/echo_netcode.rs (line 181)
177fn client(authentication: ClientAuthentication) {
178    let udp_socket = UdpSocket::bind("127.0.0.1:0").unwrap();
179    udp_socket.set_nonblocking(true).unwrap();
180    let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
181    let mut client = NetcodeClient::new(now, authentication).unwrap();
182    let stdin_channel = spawn_stdin_channel();
183    let mut buffer = [0u8; NETCODE_MAX_PACKET_BYTES];
184
185    let mut last_updated = Instant::now();
186    loop {
187        if let Some(err) = client.disconnect_reason() {
188            panic!("Client error: {:?}", err);
189        }
190
191        match stdin_channel.try_recv() {
192            Ok(text) => {
193                if client.is_connected() {
194                    let (addr, payload) = client.generate_payload_packet(text.as_bytes()).unwrap();
195                    udp_socket.send_to(payload, addr).unwrap();
196                } else {
197                    println!("Client is not yet connected");
198                }
199            }
200            Err(TryRecvError::Empty) => {}
201            Err(TryRecvError::Disconnected) => panic!("Stdin channel disconnected"),
202        }
203
204        loop {
205            match udp_socket.recv_from(&mut buffer) {
206                Ok((len, addr)) => {
207                    if addr != client.server_addr() {
208                        // Ignore packets that are not from the server
209                        continue;
210                    }
211                    // println!("Received decrypted message {:?} from server {}", &buffer[..len], addr);
212                    if let Some(payload) = client.process_packet(&mut buffer[..len]) {
213                        let text = String::from_utf8(payload.to_vec()).unwrap();
214                        println!("Received message from server: {}", text);
215                    }
216                }
217                Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
218                Err(e) => panic!("Socket error: {}", e),
219            };
220        }
221
222        if let Some((packet, addr)) = client.update(Instant::now() - last_updated) {
223            udp_socket.send_to(packet, addr).unwrap();
224        }
225        last_updated = Instant::now();
226        thread::sleep(Duration::from_millis(50));
227    }
228}
Source

pub fn set_encryption_policy(self, policy: bool) -> Self

Sets the clients’s encryption policy.

Packets will not be encrypted nor decrypted if set to false.

Source

pub fn is_connecting(&self) -> bool

Source

pub fn is_connected(&self) -> bool

Examples found in repository?
examples/echo_netcode.rs (line 193)
177fn client(authentication: ClientAuthentication) {
178    let udp_socket = UdpSocket::bind("127.0.0.1:0").unwrap();
179    udp_socket.set_nonblocking(true).unwrap();
180    let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
181    let mut client = NetcodeClient::new(now, authentication).unwrap();
182    let stdin_channel = spawn_stdin_channel();
183    let mut buffer = [0u8; NETCODE_MAX_PACKET_BYTES];
184
185    let mut last_updated = Instant::now();
186    loop {
187        if let Some(err) = client.disconnect_reason() {
188            panic!("Client error: {:?}", err);
189        }
190
191        match stdin_channel.try_recv() {
192            Ok(text) => {
193                if client.is_connected() {
194                    let (addr, payload) = client.generate_payload_packet(text.as_bytes()).unwrap();
195                    udp_socket.send_to(payload, addr).unwrap();
196                } else {
197                    println!("Client is not yet connected");
198                }
199            }
200            Err(TryRecvError::Empty) => {}
201            Err(TryRecvError::Disconnected) => panic!("Stdin channel disconnected"),
202        }
203
204        loop {
205            match udp_socket.recv_from(&mut buffer) {
206                Ok((len, addr)) => {
207                    if addr != client.server_addr() {
208                        // Ignore packets that are not from the server
209                        continue;
210                    }
211                    // println!("Received decrypted message {:?} from server {}", &buffer[..len], addr);
212                    if let Some(payload) = client.process_packet(&mut buffer[..len]) {
213                        let text = String::from_utf8(payload.to_vec()).unwrap();
214                        println!("Received message from server: {}", text);
215                    }
216                }
217                Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
218                Err(e) => panic!("Socket error: {}", e),
219            };
220        }
221
222        if let Some((packet, addr)) = client.update(Instant::now() - last_updated) {
223            udp_socket.send_to(packet, addr).unwrap();
224        }
225        last_updated = Instant::now();
226        thread::sleep(Duration::from_millis(50));
227    }
228}
Source

pub fn is_disconnected(&self) -> bool

Source

pub fn current_time(&self) -> Duration

Source

pub fn client_id(&self) -> u64

Source

pub fn time_since_last_received_packet(&self) -> Duration

Returns the duration since the client last received a packet. Usefull to detect timeouts.

Source

pub fn disconnect_reason(&self) -> Option<DisconnectReason>

Returns the reason that the client was disconnected for.

Examples found in repository?
examples/echo_netcode.rs (line 187)
177fn client(authentication: ClientAuthentication) {
178    let udp_socket = UdpSocket::bind("127.0.0.1:0").unwrap();
179    udp_socket.set_nonblocking(true).unwrap();
180    let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
181    let mut client = NetcodeClient::new(now, authentication).unwrap();
182    let stdin_channel = spawn_stdin_channel();
183    let mut buffer = [0u8; NETCODE_MAX_PACKET_BYTES];
184
185    let mut last_updated = Instant::now();
186    loop {
187        if let Some(err) = client.disconnect_reason() {
188            panic!("Client error: {:?}", err);
189        }
190
191        match stdin_channel.try_recv() {
192            Ok(text) => {
193                if client.is_connected() {
194                    let (addr, payload) = client.generate_payload_packet(text.as_bytes()).unwrap();
195                    udp_socket.send_to(payload, addr).unwrap();
196                } else {
197                    println!("Client is not yet connected");
198                }
199            }
200            Err(TryRecvError::Empty) => {}
201            Err(TryRecvError::Disconnected) => panic!("Stdin channel disconnected"),
202        }
203
204        loop {
205            match udp_socket.recv_from(&mut buffer) {
206                Ok((len, addr)) => {
207                    if addr != client.server_addr() {
208                        // Ignore packets that are not from the server
209                        continue;
210                    }
211                    // println!("Received decrypted message {:?} from server {}", &buffer[..len], addr);
212                    if let Some(payload) = client.process_packet(&mut buffer[..len]) {
213                        let text = String::from_utf8(payload.to_vec()).unwrap();
214                        println!("Received message from server: {}", text);
215                    }
216                }
217                Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
218                Err(e) => panic!("Socket error: {}", e),
219            };
220        }
221
222        if let Some((packet, addr)) = client.update(Instant::now() - last_updated) {
223            udp_socket.send_to(packet, addr).unwrap();
224        }
225        last_updated = Instant::now();
226        thread::sleep(Duration::from_millis(50));
227    }
228}
Source

pub fn server_addr(&self) -> SocketAddr

Returns the current server address the client is connected or trying to connect.

Examples found in repository?
examples/echo_netcode.rs (line 207)
177fn client(authentication: ClientAuthentication) {
178    let udp_socket = UdpSocket::bind("127.0.0.1:0").unwrap();
179    udp_socket.set_nonblocking(true).unwrap();
180    let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
181    let mut client = NetcodeClient::new(now, authentication).unwrap();
182    let stdin_channel = spawn_stdin_channel();
183    let mut buffer = [0u8; NETCODE_MAX_PACKET_BYTES];
184
185    let mut last_updated = Instant::now();
186    loop {
187        if let Some(err) = client.disconnect_reason() {
188            panic!("Client error: {:?}", err);
189        }
190
191        match stdin_channel.try_recv() {
192            Ok(text) => {
193                if client.is_connected() {
194                    let (addr, payload) = client.generate_payload_packet(text.as_bytes()).unwrap();
195                    udp_socket.send_to(payload, addr).unwrap();
196                } else {
197                    println!("Client is not yet connected");
198                }
199            }
200            Err(TryRecvError::Empty) => {}
201            Err(TryRecvError::Disconnected) => panic!("Stdin channel disconnected"),
202        }
203
204        loop {
205            match udp_socket.recv_from(&mut buffer) {
206                Ok((len, addr)) => {
207                    if addr != client.server_addr() {
208                        // Ignore packets that are not from the server
209                        continue;
210                    }
211                    // println!("Received decrypted message {:?} from server {}", &buffer[..len], addr);
212                    if let Some(payload) = client.process_packet(&mut buffer[..len]) {
213                        let text = String::from_utf8(payload.to_vec()).unwrap();
214                        println!("Received message from server: {}", text);
215                    }
216                }
217                Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
218                Err(e) => panic!("Socket error: {}", e),
219            };
220        }
221
222        if let Some((packet, addr)) = client.update(Instant::now() - last_updated) {
223            udp_socket.send_to(packet, addr).unwrap();
224        }
225        last_updated = Instant::now();
226        thread::sleep(Duration::from_millis(50));
227    }
228}
Source

pub fn disconnect(&mut self) -> Result<(SocketAddr, &mut [u8]), NetcodeError>

Disconnect the client from the server. Returns a disconnect packet that should be sent to the server.

Source

pub fn process_packet<'a>(&mut self, buffer: &'a mut [u8]) -> Option<&'a [u8]>

Process any packet received from the server. This function might return a payload sent from the server. If nothing is returned, it was a packet used for the internal protocol or an invalid packet.

Examples found in repository?
examples/echo_netcode.rs (line 212)
177fn client(authentication: ClientAuthentication) {
178    let udp_socket = UdpSocket::bind("127.0.0.1:0").unwrap();
179    udp_socket.set_nonblocking(true).unwrap();
180    let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
181    let mut client = NetcodeClient::new(now, authentication).unwrap();
182    let stdin_channel = spawn_stdin_channel();
183    let mut buffer = [0u8; NETCODE_MAX_PACKET_BYTES];
184
185    let mut last_updated = Instant::now();
186    loop {
187        if let Some(err) = client.disconnect_reason() {
188            panic!("Client error: {:?}", err);
189        }
190
191        match stdin_channel.try_recv() {
192            Ok(text) => {
193                if client.is_connected() {
194                    let (addr, payload) = client.generate_payload_packet(text.as_bytes()).unwrap();
195                    udp_socket.send_to(payload, addr).unwrap();
196                } else {
197                    println!("Client is not yet connected");
198                }
199            }
200            Err(TryRecvError::Empty) => {}
201            Err(TryRecvError::Disconnected) => panic!("Stdin channel disconnected"),
202        }
203
204        loop {
205            match udp_socket.recv_from(&mut buffer) {
206                Ok((len, addr)) => {
207                    if addr != client.server_addr() {
208                        // Ignore packets that are not from the server
209                        continue;
210                    }
211                    // println!("Received decrypted message {:?} from server {}", &buffer[..len], addr);
212                    if let Some(payload) = client.process_packet(&mut buffer[..len]) {
213                        let text = String::from_utf8(payload.to_vec()).unwrap();
214                        println!("Received message from server: {}", text);
215                    }
216                }
217                Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
218                Err(e) => panic!("Socket error: {}", e),
219            };
220        }
221
222        if let Some((packet, addr)) = client.update(Instant::now() - last_updated) {
223            udp_socket.send_to(packet, addr).unwrap();
224        }
225        last_updated = Instant::now();
226        thread::sleep(Duration::from_millis(50));
227    }
228}
Source

pub fn generate_payload_packet( &mut self, payload: &[u8], ) -> Result<(SocketAddr, &mut [u8]), NetcodeError>

Returns the server address and an encrypted payload packet that can be sent to the server.

Examples found in repository?
examples/echo_netcode.rs (line 194)
177fn client(authentication: ClientAuthentication) {
178    let udp_socket = UdpSocket::bind("127.0.0.1:0").unwrap();
179    udp_socket.set_nonblocking(true).unwrap();
180    let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
181    let mut client = NetcodeClient::new(now, authentication).unwrap();
182    let stdin_channel = spawn_stdin_channel();
183    let mut buffer = [0u8; NETCODE_MAX_PACKET_BYTES];
184
185    let mut last_updated = Instant::now();
186    loop {
187        if let Some(err) = client.disconnect_reason() {
188            panic!("Client error: {:?}", err);
189        }
190
191        match stdin_channel.try_recv() {
192            Ok(text) => {
193                if client.is_connected() {
194                    let (addr, payload) = client.generate_payload_packet(text.as_bytes()).unwrap();
195                    udp_socket.send_to(payload, addr).unwrap();
196                } else {
197                    println!("Client is not yet connected");
198                }
199            }
200            Err(TryRecvError::Empty) => {}
201            Err(TryRecvError::Disconnected) => panic!("Stdin channel disconnected"),
202        }
203
204        loop {
205            match udp_socket.recv_from(&mut buffer) {
206                Ok((len, addr)) => {
207                    if addr != client.server_addr() {
208                        // Ignore packets that are not from the server
209                        continue;
210                    }
211                    // println!("Received decrypted message {:?} from server {}", &buffer[..len], addr);
212                    if let Some(payload) = client.process_packet(&mut buffer[..len]) {
213                        let text = String::from_utf8(payload.to_vec()).unwrap();
214                        println!("Received message from server: {}", text);
215                    }
216                }
217                Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
218                Err(e) => panic!("Socket error: {}", e),
219            };
220        }
221
222        if let Some((packet, addr)) = client.update(Instant::now() - last_updated) {
223            udp_socket.send_to(packet, addr).unwrap();
224        }
225        last_updated = Instant::now();
226        thread::sleep(Duration::from_millis(50));
227    }
228}
Source

pub fn update(&mut self, duration: Duration) -> Option<(&mut [u8], SocketAddr)>

Update the internal state of the client, receives the duration since last updated. Might return the serve address and a protocol packet to be sent to the server.

Examples found in repository?
examples/echo_netcode.rs (line 222)
177fn client(authentication: ClientAuthentication) {
178    let udp_socket = UdpSocket::bind("127.0.0.1:0").unwrap();
179    udp_socket.set_nonblocking(true).unwrap();
180    let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
181    let mut client = NetcodeClient::new(now, authentication).unwrap();
182    let stdin_channel = spawn_stdin_channel();
183    let mut buffer = [0u8; NETCODE_MAX_PACKET_BYTES];
184
185    let mut last_updated = Instant::now();
186    loop {
187        if let Some(err) = client.disconnect_reason() {
188            panic!("Client error: {:?}", err);
189        }
190
191        match stdin_channel.try_recv() {
192            Ok(text) => {
193                if client.is_connected() {
194                    let (addr, payload) = client.generate_payload_packet(text.as_bytes()).unwrap();
195                    udp_socket.send_to(payload, addr).unwrap();
196                } else {
197                    println!("Client is not yet connected");
198                }
199            }
200            Err(TryRecvError::Empty) => {}
201            Err(TryRecvError::Disconnected) => panic!("Stdin channel disconnected"),
202        }
203
204        loop {
205            match udp_socket.recv_from(&mut buffer) {
206                Ok((len, addr)) => {
207                    if addr != client.server_addr() {
208                        // Ignore packets that are not from the server
209                        continue;
210                    }
211                    // println!("Received decrypted message {:?} from server {}", &buffer[..len], addr);
212                    if let Some(payload) = client.process_packet(&mut buffer[..len]) {
213                        let text = String::from_utf8(payload.to_vec()).unwrap();
214                        println!("Received message from server: {}", text);
215                    }
216                }
217                Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
218                Err(e) => panic!("Socket error: {}", e),
219            };
220        }
221
222        if let Some((packet, addr)) = client.update(Instant::now() - last_updated) {
223            udp_socket.send_to(packet, addr).unwrap();
224        }
225        last_updated = Instant::now();
226        thread::sleep(Duration::from_millis(50));
227    }
228}

Trait Implementations§

Source§

impl Debug for NetcodeClient

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. 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<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> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.