1use renetcode::{
2 ClientAuthentication, ConnectToken, NetcodeClient, NetcodeServer, ServerAuthentication, ServerConfig, ServerResult, NETCODE_KEY_BYTES,
3 NETCODE_MAX_PACKET_BYTES, NETCODE_USER_DATA_BYTES,
4};
5use std::time::Duration;
6use std::{collections::HashMap, thread};
7use std::{
8 net::{SocketAddr, UdpSocket},
9 time::Instant,
10};
11use std::{
12 sync::mpsc::{self, Receiver, TryRecvError},
13 time::{SystemTime, UNIX_EPOCH},
14};
15
16const PROTOCOL_ID: u64 = 123456789;
18
19struct Username(String);
21
22impl Username {
23 fn to_netcode_user_data(&self) -> [u8; NETCODE_USER_DATA_BYTES] {
24 let mut user_data = [0u8; NETCODE_USER_DATA_BYTES];
25 if self.0.len() > NETCODE_USER_DATA_BYTES - 8 {
26 panic!("Username is too big");
27 }
28 user_data[0..8].copy_from_slice(&(self.0.len() as u64).to_le_bytes());
29 user_data[8..self.0.len() + 8].copy_from_slice(self.0.as_bytes());
30
31 user_data
32 }
33
34 fn from_user_data(user_data: &[u8; NETCODE_USER_DATA_BYTES]) -> Self {
35 let mut buffer = [0u8; 8];
36 buffer.copy_from_slice(&user_data[0..8]);
37 let mut len = u64::from_le_bytes(buffer) as usize;
38 len = len.min(NETCODE_USER_DATA_BYTES - 8);
39 let data = user_data[8..len + 8].to_vec();
40 let username = String::from_utf8(data).unwrap();
41 Self(username)
42 }
43}
44
45fn main() {
46 println!("Usage: server [SERVER_PORT] or client [SERVER_PORT] [USER_NAME]");
47 let args: Vec<String> = std::env::args().collect();
48 let private_key = b"an example very very secret key."; let exec_type = &args[1];
51 match exec_type.as_str() {
52 "client" => {
53 let server_addr: SocketAddr = format!("127.0.0.1:{}", args[2]).parse().unwrap();
54 let username = Username(args[3].clone());
55 let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
56 println!("Stating connecting at {:?} with username {}", now, username.0,);
57 let client_id = now.as_millis() as u64;
58 let connect_token = ConnectToken::generate(
59 now,
60 PROTOCOL_ID,
61 300,
62 client_id,
63 15,
64 vec![server_addr],
65 Some(&username.to_netcode_user_data()),
66 private_key,
67 )
68 .unwrap();
69 let auth = ClientAuthentication::Secure { connect_token };
70 client(auth);
71 }
72 "server" => {
73 let server_addr: SocketAddr = format!("127.0.0.1:{}", args[2]).parse().unwrap();
74 server(server_addr, *private_key);
75 }
76 _ => {
77 println!("Invalid argument, first one must be \"client\" or \"server\".");
78 }
79 }
80}
81
82fn handle_server_result(
83 server_result: ServerResult,
84 socket: &UdpSocket,
85 received_messages: &mut Vec<String>,
86 usernames: &mut HashMap<u64, String>,
87) {
88 match server_result {
89 ServerResult::Payload { client_id, payload } => {
90 let text = String::from_utf8(payload.to_vec()).unwrap();
91 let username = usernames.get(&client_id).unwrap();
92 println!("Client {} ({}) sent message {:?}.", username, client_id, text);
93 let text = format!("{}: {}", username, text);
94 received_messages.push(text);
95 }
96 ServerResult::PacketToSend { payload, addr } => {
97 socket.send_to(payload, addr).unwrap();
98 }
99 ServerResult::ClientConnected {
100 client_id,
101 user_data,
102 payload,
103 addr,
104 } => {
105 let username = Username::from_user_data(&user_data);
106 println!("Client {} with id {} connected.", username.0, client_id);
107 usernames.insert(client_id, username.0);
108 socket.send_to(payload, addr).unwrap();
109 }
110 ServerResult::ClientDisconnected { client_id, addr, payload } => {
111 println!("Client {} disconnected.", client_id);
112 usernames.remove_entry(&client_id);
113 if let Some(payload) = payload {
114 socket.send_to(payload, addr).unwrap();
115 }
116 }
117 ServerResult::None => {}
118 }
119}
120
121fn server(addr: SocketAddr, private_key: [u8; NETCODE_KEY_BYTES]) {
122 let current_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
123 let config = ServerConfig {
124 current_time,
125 max_clients: 16,
126 protocol_id: PROTOCOL_ID,
127 public_addresses: vec![addr],
128 authentication: ServerAuthentication::Secure { private_key },
129 };
130 let mut server: NetcodeServer = NetcodeServer::new(config);
131 let udp_socket = UdpSocket::bind(addr).unwrap();
132 udp_socket.set_nonblocking(true).unwrap();
133 let mut received_messages = vec![];
134 let mut last_updated = Instant::now();
135 let mut buffer = [0u8; NETCODE_MAX_PACKET_BYTES];
136 let mut usernames: HashMap<u64, String> = HashMap::new();
137 loop {
138 server.update(Instant::now() - last_updated);
139 received_messages.clear();
140
141 loop {
142 match udp_socket.recv_from(&mut buffer) {
143 Ok((len, addr)) => {
144 let server_result = server.process_packet(addr, &mut buffer[..len]);
146 handle_server_result(server_result, &udp_socket, &mut received_messages, &mut usernames);
147 }
148 Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
149 Err(e) => panic!("Socket error: {}", e),
150 };
151 }
152
153 for text in received_messages.iter() {
154 for client_id in server.clients_id().iter() {
155 let (addr, payload) = server.generate_payload_packet(*client_id, text.as_bytes()).unwrap();
156 udp_socket.send_to(payload, addr).unwrap();
157 }
158 }
159
160 for client_id in server.clients_id().into_iter() {
161 let server_result = server.update_client(client_id);
162 handle_server_result(server_result, &udp_socket, &mut received_messages, &mut usernames);
163 }
164
165 last_updated = Instant::now();
166 thread::sleep(Duration::from_millis(50));
167 }
168}
169
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 continue;
203 }
204 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}
222
223fn spawn_stdin_channel() -> Receiver<String> {
224 let (tx, rx) = mpsc::channel::<String>();
225 thread::spawn(move || loop {
226 let mut buffer = String::new();
227 std::io::stdin().read_line(&mut buffer).unwrap();
228 tx.send(buffer.trim_end().to_string()).unwrap();
229 });
230 rx
231}