1use renetcode2::{
2 ClientAuthentication, ConnectToken, NetcodeClient, NetcodeServer, ServerAuthentication, ServerConfig, ServerResult, ServerSocketConfig,
3 NETCODE_KEY_BYTES, 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 socket_id = 0;
54 let server_addr: SocketAddr = format!("127.0.0.1:{}", args[2]).parse().unwrap();
55 let username = Username(args[3].clone());
56 let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
57 println!("Stating connecting at {:?} with username {}", now, username.0,);
58 let client_id = now.as_millis() as u64;
59 let connect_token = ConnectToken::generate(
60 now,
61 PROTOCOL_ID,
62 300,
63 client_id,
64 15,
65 socket_id,
66 vec![server_addr],
67 Some(&username.to_netcode_user_data()),
68 private_key,
69 )
70 .unwrap();
71 let auth = ClientAuthentication::Secure { connect_token };
72 client(auth);
73 }
74 "server" => {
75 let server_addr: SocketAddr = format!("127.0.0.1:{}", args[2]).parse().unwrap();
76 server(server_addr, *private_key);
77 }
78 _ => {
79 println!("Invalid argument, first one must be \"client\" or \"server\".");
80 }
81 }
82}
83
84fn handle_server_result(
85 server_result: ServerResult,
86 socket: &UdpSocket,
87 received_messages: &mut Vec<String>,
88 usernames: &mut HashMap<u64, String>,
89) {
90 match server_result {
91 ServerResult::Payload { client_id, payload } => {
92 let text = String::from_utf8(payload.to_vec()).unwrap();
93 let username = usernames.get(&client_id).unwrap();
94 println!("Client {} ({}) sent message {:?}.", username, client_id, text);
95 let text = format!("{}: {}", username, text);
96 received_messages.push(text);
97 }
98 ServerResult::ConnectionAccepted { payload, addr, .. } | ServerResult::PacketToSend { payload, addr, .. } => {
99 socket.send_to(payload, addr).unwrap();
100 }
101 ServerResult::ClientConnected {
102 client_id,
103 user_data,
104 payload,
105 addr,
106 ..
107 } => {
108 let username = Username::from_user_data(&user_data);
109 println!("Client {} with id {} connected.", username.0, client_id);
110 usernames.insert(client_id, username.0);
111 socket.send_to(payload, addr).unwrap();
112 }
113 ServerResult::ClientDisconnected {
114 client_id, addr, payload, ..
115 } => {
116 println!("Client {} disconnected.", client_id);
117 usernames.remove_entry(&client_id);
118 if let Some(payload) = payload {
119 socket.send_to(payload, addr).unwrap();
120 }
121 }
122 ServerResult::ConnectionDenied { .. } => {}
123 ServerResult::Error { .. } => {}
124 ServerResult::None => {}
125 }
126}
127
128fn server(addr: SocketAddr, private_key: [u8; NETCODE_KEY_BYTES]) {
129 let current_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
130 let config = ServerConfig {
131 current_time,
132 max_clients: 16,
133 protocol_id: PROTOCOL_ID,
134 sockets: vec![ServerSocketConfig::new(vec![addr])],
135 authentication: ServerAuthentication::Secure { private_key },
136 };
137 let mut server: NetcodeServer = NetcodeServer::new(config);
138 let udp_socket = UdpSocket::bind(addr).unwrap();
139 udp_socket.set_nonblocking(true).unwrap();
140 let mut received_messages = vec![];
141 let mut last_updated = Instant::now();
142 let mut buffer = [0u8; NETCODE_MAX_PACKET_BYTES];
143 let mut usernames: HashMap<u64, String> = HashMap::new();
144 loop {
145 server.update(Instant::now() - last_updated);
146 received_messages.clear();
147
148 loop {
149 match udp_socket.recv_from(&mut buffer) {
150 Ok((len, addr)) => {
151 let server_result = server.process_packet(0, addr, &mut buffer[..len]);
153 handle_server_result(server_result, &udp_socket, &mut received_messages, &mut usernames);
154 }
155 Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => break,
156 Err(e) => panic!("Socket error: {}", e),
157 };
158 }
159
160 for text in received_messages.iter() {
161 for client_id in server.clients_id().iter() {
162 let (_, addr, payload) = server.generate_payload_packet(*client_id, text.as_bytes()).unwrap();
163 udp_socket.send_to(payload, addr).unwrap();
164 }
165 }
166
167 for client_id in server.clients_id().into_iter() {
168 let server_result = server.update_client(client_id);
169 handle_server_result(server_result, &udp_socket, &mut received_messages, &mut usernames);
170 }
171
172 last_updated = Instant::now();
173 thread::sleep(Duration::from_millis(50));
174 }
175}
176
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 continue;
210 }
211 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}
229
230fn spawn_stdin_channel() -> Receiver<String> {
231 let (tx, rx) = mpsc::channel::<String>();
232 thread::spawn(move || loop {
233 let mut buffer = String::new();
234 std::io::stdin().read_line(&mut buffer).unwrap();
235 tx.send(buffer.trim_end().to_string()).unwrap();
236 });
237 rx
238}