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

pub fn is_connecting(&self) -> bool

Source

pub fn is_connected(&self) -> bool

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

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.