Skip to content

Commit

Permalink
Netcode: allow multiple server addresses and disable host ip check wh…
Browse files Browse the repository at this point in the history
…en unsecure (#102)
  • Loading branch information
lucaspoffo authored Aug 8, 2023
1 parent 6dd55d2 commit 41d6709
Show file tree
Hide file tree
Showing 14 changed files with 207 additions and 182 deletions.
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ let mut server = RenetServer::new(ConnectionConfig::default());
const SERVER_ADDR: SocketAddr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1), 5000));
let socket: UdpSocket = UdpSocket::bind(SERVER_ADDR).unwrap();
let server_config = ServerConfig {
max_clients:64
current_time: SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(),
max_clients: 64
protocol_id: 0,
public_addr: SERVER_ADDR,
public_addresses: vec![SERVER_ADDR],
authentication: ServerAuthentication::Unsecure
};
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let mut transport = NetcodeServerTransport::new(current_time, server_config, socket).unwrap();
let mut transport = NetcodeServerTransport::new(server_config, socket).unwrap();

// Your gameplay loop
loop {
Expand Down Expand Up @@ -151,7 +151,12 @@ loop {

## Demos

You can checkout the [echo example](https://github.com/lucaspoffo/renet/blob/master/renet/examples/echo.rs) for a simple usage of the library. Or you can look into the two demos that have more complex uses of renet:
You can checkout the [echo example](https://github.com/lucaspoffo/renet/blob/master/renet/examples/echo.rs) for a simple usage of the library. Usage:

- Server: `cargo run --example echo -- server 5000`
- Client: `cargo run --example echo -- client 127.0.0.1:5000 CoolNickName`

Or you can look into the two demos that have more complex uses of renet:

<details><summary>Bevy Demo</summary>
<br/>
Expand Down
31 changes: 18 additions & 13 deletions bevy_renet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ app.insert_resource(server);
app.add_plugin(NetcodeServerPlugin);
let server_addr = "127.0.0.1:5000".parse().unwrap();
let socket = UdpSocket::bind(server_addr).unwrap();
const MAX_CLIENTS: usize = 64;
const GAME_PROTOCOL_ID: u64 = 0;
let server_config = ServerConfig::new(MAX_CLIENTS, PROTOCOL_ID, server_addr, ServerAuthentication::Unsecure);
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let transport = NetcodeServerTransport::new(current_time, server_config, socket).unwrap();
let server_config = ServerConfig {
current_time: SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap(),
max_clients: 64,
protocol_id: 0,
server_addresses: vec![server_addr],
ServerAuthentication::Unsecure,
authentication: ServerAuthentication::Unsecure
};
let transport = NetcodeServerTransport::new(server_config, socket).unwrap();
app.insert_resource(transport);

app.add_system(send_message_system);
Expand Down Expand Up @@ -77,16 +81,17 @@ app.insert_resource(client);

// Setup the transport layer
app.add_plugin(NetcodeClientPlugin);
let public_addr = "127.0.0.1:5000".parse().unwrap();
let socket = UdpSocket::bind(public_addr).unwrap();
let server_config = ServerConfig {
max_clients: 64,
protocol_id: PROTOCOL_ID,
public_addr,
authentication: ServerAuthentication::Unsecure,

let authentication = ClientAuthentication::Unsecure {
server_addr: SERVER_ADDR,
client_id: 0,
user_data: None,
protocol_id: 0,
};
let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let transport = NetcodeServerTransport::new(current_time, server_config, socket).unwrap();
let mut transport = NetcodeClientTransport::new(current_time, authentication, socket).unwrap();

app.insert_resource(transport);

app.add_system(send_message_system);
Expand Down
7 changes: 4 additions & 3 deletions bevy_renet/examples/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,16 @@ fn new_renet_server() -> (RenetServer, NetcodeServerTransport) {

let public_addr = "127.0.0.1:5000".parse().unwrap();
let socket = UdpSocket::bind(public_addr).unwrap();
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let server_config = ServerConfig {
current_time,
max_clients: 64,
protocol_id: PROTOCOL_ID,
public_addr,
public_addresses: vec![public_addr],
authentication: ServerAuthentication::Unsecure,
};
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();

let transport = NetcodeServerTransport::new(current_time, server_config, socket).unwrap();
let transport = NetcodeServerTransport::new(server_config, socket).unwrap();

(server, transport)
}
Expand Down
7 changes: 4 additions & 3 deletions demo_bevy/src/bin/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,16 @@ fn new_renet_server() -> (RenetServer, NetcodeServerTransport) {

let public_addr = "127.0.0.1:5000".parse().unwrap();
let socket = UdpSocket::bind(public_addr).unwrap();
let current_time: std::time::Duration = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let server_config = ServerConfig {
current_time,
max_clients: 64,
protocol_id: PROTOCOL_ID,
public_addr,
public_addresses: vec![public_addr],
authentication: ServerAuthentication::Unsecure,
};
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();

let transport = NetcodeServerTransport::new(current_time, server_config, socket).unwrap();
let transport = NetcodeServerTransport::new(server_config, socket).unwrap();

(server, transport)
}
Expand Down
8 changes: 4 additions & 4 deletions demo_chat/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ pub struct ChatServer {
impl ChatServer {
pub fn new(host_username: String) -> Self {
let socket = UdpSocket::bind("127.0.0.1:0").unwrap();
let public_addr = socket.local_addr().unwrap();
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let server_config = ServerConfig {
current_time,
max_clients: 64,
protocol_id: PROTOCOL_ID,
public_addr,
public_addresses: vec![socket.local_addr().unwrap()],
authentication: ServerAuthentication::Unsecure,
};

let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let transport = NetcodeServerTransport::new(current_time, server_config, socket).unwrap();
let transport = NetcodeServerTransport::new(server_config, socket).unwrap();

let server: RenetServer = RenetServer::new(ConnectionConfig::default());

Expand Down
17 changes: 9 additions & 8 deletions demo_chat/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,15 @@ pub fn draw_host_commands(ui: &mut Ui, chat_server: &mut ChatServer) {
});

ui.separator();
ui.horizontal(|ui| {
let server_addr = chat_server.transport.addr();
ui.label(format!("Address: {}", server_addr));
let tooltip = "Click to copy the server address";
if ui.button("📋").on_hover_text(tooltip).clicked() {
ui.output_mut(|output| output.copied_text = server_addr.to_string());
}
});
for server_addr in chat_server.transport.addresses() {
ui.horizontal(|ui| {
ui.label(format!("Address: {}", server_addr));
let tooltip = "Click to copy the server address";
if ui.button("📋").on_hover_text(tooltip).clicked() {
ui.output_mut(|output| output.copied_text = server_addr.to_string());
}
});
}

ui.separator();

Expand Down
16 changes: 9 additions & 7 deletions renet/examples/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,18 @@ impl Username {

fn main() {
env_logger::init();
println!("Usage: server [SERVER_PORT] or client [SERVER_PORT] [USER_NAME]");
println!("Usage: server [SERVER_PORT] or client [SERVER_ADDR] [USER_NAME]");
let args: Vec<String> = std::env::args().collect();

let exec_type = &args[1];
match exec_type.as_str() {
"client" => {
let server_addr: SocketAddr = format!("127.0.0.1:{}", args[2]).parse().unwrap();
let server_addr: SocketAddr = args[2].parse().unwrap();
let username = Username(args[3].clone());
client(server_addr, username);
}
"server" => {
let server_addr: SocketAddr = format!("127.0.0.1:{}", args[2]).parse().unwrap();
let server_addr: SocketAddr = format!("0.0.0.0:{}", args[2]).parse().unwrap();
server(server_addr);
}
_ => {
Expand All @@ -67,15 +67,17 @@ fn server(public_addr: SocketAddr) {
let connection_config = ConnectionConfig::default();
let mut server: RenetServer = RenetServer::new(connection_config);

let socket: UdpSocket = UdpSocket::bind(public_addr).unwrap();
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let server_config = ServerConfig {
current_time,
max_clients: 64,
protocol_id: PROTOCOL_ID,
public_addr,
public_addresses: vec![public_addr],
authentication: ServerAuthentication::Unsecure,
};
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap();
let mut transport = NetcodeServerTransport::new(current_time, server_config, socket).unwrap();
let socket: UdpSocket = UdpSocket::bind(public_addr).unwrap();

let mut transport = NetcodeServerTransport::new(server_config, socket).unwrap();

let mut usernames: HashMap<u64, String> = HashMap::new();
let mut received_messages = vec![];
Expand Down
44 changes: 2 additions & 42 deletions renet/src/transport/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,12 @@ use std::{
time::Duration,
};

use renetcode::{
ConnectToken, DisconnectReason, NetcodeClient, NetcodeError, NETCODE_KEY_BYTES, NETCODE_MAX_PACKET_BYTES, NETCODE_USER_DATA_BYTES,
};
use renetcode::{ClientAuthentication, DisconnectReason, NetcodeClient, NetcodeError, NETCODE_MAX_PACKET_BYTES};

use crate::remote_connection::RenetClient;

use super::NetcodeTransportError;

/// Configuration to establish an secure ou unsecure connection with the server.
#[derive(Debug)]
#[allow(clippy::large_enum_variant)]
pub enum ClientAuthentication {
/// Establishes a safe connection with the server using the [crate::transport::ConnectToken].
///
/// See also [crate::transport::ServerAuthentication::Secure]
Secure { connect_token: ConnectToken },
/// Establishes an unsafe connection with the server, useful for testing and prototyping.
///
/// See also [crate::transport::ServerAuthentication::Unsecure]
Unsecure {
protocol_id: u64,
client_id: u64,
server_addr: SocketAddr,
user_data: Option<[u8; NETCODE_USER_DATA_BYTES]>,
},
}

#[derive(Debug)]
#[cfg_attr(feature = "bevy", derive(bevy_ecs::system::Resource))]
pub struct NetcodeClientTransport {
Expand All @@ -42,26 +21,7 @@ pub struct NetcodeClientTransport {
impl NetcodeClientTransport {
pub fn new(current_time: Duration, authentication: ClientAuthentication, socket: UdpSocket) -> Result<Self, NetcodeError> {
socket.set_nonblocking(true)?;
let connect_token: ConnectToken = match authentication {
ClientAuthentication::Unsecure {
server_addr,
protocol_id,
client_id,
user_data,
} => ConnectToken::generate(
current_time,
protocol_id,
300,
client_id,
15,
vec![server_addr],
user_data.as_ref(),
&[0; NETCODE_KEY_BYTES],
)?,
ClientAuthentication::Secure { connect_token } => connect_token,
};

let netcode_client = NetcodeClient::new(current_time, connect_token);
let netcode_client = NetcodeClient::new(current_time, authentication)?;

Ok(Self {
buffer: [0u8; NETCODE_MAX_PACKET_BYTES],
Expand Down
4 changes: 2 additions & 2 deletions renet/src/transport/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ pub use client::*;
pub use server::*;

pub use renetcode::{
generate_random_bytes, ConnectToken, DisconnectReason as NetcodeDisconnectReason, NetcodeError, TokenGenerationError,
NETCODE_KEY_BYTES, NETCODE_USER_DATA_BYTES,
generate_random_bytes, ClientAuthentication, ConnectToken, DisconnectReason as NetcodeDisconnectReason, NetcodeError,
ServerAuthentication, ServerConfig, TokenGenerationError, NETCODE_KEY_BYTES, NETCODE_USER_DATA_BYTES,
};

#[derive(Debug)]
Expand Down
52 changes: 5 additions & 47 deletions renet/src/transport/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,12 @@ use std::{
time::Duration,
};

use renetcode::{NetcodeServer, ServerResult, NETCODE_KEY_BYTES, NETCODE_MAX_PACKET_BYTES, NETCODE_USER_DATA_BYTES};
use renetcode::{NetcodeServer, ServerConfig, ServerResult, NETCODE_MAX_PACKET_BYTES, NETCODE_USER_DATA_BYTES};

use crate::server::RenetServer;

use super::NetcodeTransportError;

/// Configuration to establish a secure or unsecure connection with the server.
#[derive(Debug)]
pub enum ServerAuthentication {
/// Establishes a safe connection using a private key for encryption. The private key cannot be
/// shared with the client. Connections are stablished using [crate::transport::ConnectToken].
///
/// See also [ClientAuthentication::Secure][crate::transport::ClientAuthentication::Secure]
Secure { private_key: [u8; NETCODE_KEY_BYTES] },
/// Establishes unsafe connections with clients, useful for testing and prototyping.
///
/// See also [ClientAuthentication::Unsecure][crate::transport::ClientAuthentication::Unsecure]
Unsecure,
}

/// Configuration options for the server transport.
#[derive(Debug)]
pub struct ServerConfig {
/// Maximum numbers of clients that can be connected at a time
pub max_clients: usize,
/// Unique identifier to this game/application
/// One could use a hash function with the game current version to generate this value.
/// So old version would be unable to connect to newer versions.
pub protocol_id: u64,
/// Publicly available address that clients will try to connect to. This is
/// the address used to generate the ConnectToken when using the secure authentication.
pub public_addr: SocketAddr,
/// Authentication configuration for the server
pub authentication: ServerAuthentication,
}

#[derive(Debug)]
#[cfg_attr(feature = "bevy", derive(bevy_ecs::system::Resource))]
pub struct NetcodeServerTransport {
Expand All @@ -49,22 +19,10 @@ pub struct NetcodeServerTransport {
}

impl NetcodeServerTransport {
pub fn new(current_time: Duration, server_config: ServerConfig, socket: UdpSocket) -> Result<Self, std::io::Error> {
pub fn new(server_config: ServerConfig, socket: UdpSocket) -> Result<Self, std::io::Error> {
socket.set_nonblocking(true)?;

// For unsecure connections we use an fixed private key.
let private_key = match server_config.authentication {
ServerAuthentication::Unsecure => [0; NETCODE_KEY_BYTES],
ServerAuthentication::Secure { private_key } => private_key,
};

let netcode_server = NetcodeServer::new(
current_time,
server_config.max_clients,
server_config.protocol_id,
server_config.public_addr,
private_key,
);
let netcode_server = NetcodeServer::new(server_config);

Ok(Self {
socket,
Expand All @@ -74,8 +32,8 @@ impl NetcodeServerTransport {
}

/// Returns the server public address
pub fn addr(&self) -> SocketAddr {
self.netcode_server.address()
pub fn addresses(&self) -> Vec<SocketAddr> {
self.netcode_server.addresses()
}

/// Returns the maximum number of clients that can be connected.
Expand Down
Loading

0 comments on commit 41d6709

Please sign in to comment.