1use std::{io, net::SocketAddr, time::Duration};
2
3use renetcode2::{NetcodeServer, ServerConfig, ServerResult, NETCODE_MAX_PACKET_BYTES, NETCODE_USER_DATA_BYTES};
4use renetcode2::{ServerAuthentication, ServerSocketConfig};
5
6use renet2::{ClientId, Payload, RenetServer};
7
8use super::{NetcodeTransportError, ServerSocket};
9
10pub struct ServerSetupConfig {
14 pub current_time: Duration,
15 pub max_clients: usize,
17 pub protocol_id: u64,
21 pub socket_addresses: Vec<Vec<SocketAddr>>,
23 pub authentication: ServerAuthentication,
25}
26
27pub struct BoxedSocket(Box<dyn ServerSocket>);
31
32impl BoxedSocket {
33 pub fn new(socket: impl ServerSocket) -> Self {
35 Self(Box::new(socket))
36 }
37}
38
39#[derive(Debug)]
40#[cfg_attr(feature = "bevy", derive(bevy_ecs::resource::Resource))]
41pub struct NetcodeServerTransport {
42 sockets: Vec<Box<dyn ServerSocket>>,
43 netcode_server: NetcodeServer,
44 buffer: [u8; NETCODE_MAX_PACKET_BYTES],
45}
46
47impl NetcodeServerTransport {
48 pub fn new(server_config: ServerSetupConfig, socket: impl ServerSocket) -> Result<Self, std::io::Error> {
50 Self::new_with_sockets(server_config, vec![BoxedSocket::new(socket)])
51 }
52
53 pub fn new_with_sockets(mut server_config: ServerSetupConfig, mut boxed: Vec<BoxedSocket>) -> Result<Self, std::io::Error> {
58 if server_config.socket_addresses.is_empty() {
59 panic!("netcode server transport must have at least 1 socket");
60 }
61 if server_config.socket_addresses.len() != boxed.len() {
62 panic!("server config does not match the number of sockets");
63 }
64
65 let mut sockets = Vec::with_capacity(boxed.len());
67 for socket in boxed.drain(..) {
68 sockets.push(socket.0);
69 }
70
71 let mut socket_configs = Vec::with_capacity(sockets.len());
73 let mut socket_addresses = std::mem::take(&mut server_config.socket_addresses);
74 for (addrs, socket) in socket_addresses.drain(..).zip(sockets.iter()) {
75 socket_configs.push(ServerSocketConfig {
76 needs_encryption: !socket.is_encrypted(),
77 public_addresses: addrs,
78 });
79 }
80
81 let server_config = ServerConfig {
82 current_time: server_config.current_time,
83 max_clients: server_config.max_clients,
84 protocol_id: server_config.protocol_id,
85 sockets: socket_configs,
86 authentication: server_config.authentication,
87 };
88
89 Ok(Self {
90 sockets,
91 netcode_server: NetcodeServer::new(server_config),
92 buffer: [0; NETCODE_MAX_PACKET_BYTES],
93 })
94 }
95
96 pub fn addresses(&self) -> Vec<SocketAddr> {
98 self.get_addresses(0).unwrap()
99 }
100
101 pub fn get_addresses(&self, socket_id: usize) -> Option<Vec<SocketAddr>> {
103 if socket_id >= self.sockets.len() {
104 return None;
105 }
106 Some(self.netcode_server.addresses(socket_id))
107 }
108
109 pub fn max_clients(&self) -> usize {
111 self.netcode_server.max_clients()
112 }
113
114 pub fn set_max_clients(&mut self, max_clients: usize) {
120 self.netcode_server.set_max_clients(max_clients);
121 }
122
123 pub fn connected_clients(&self) -> usize {
125 self.netcode_server.connected_clients()
126 }
127
128 pub fn user_data(&self, client_id: ClientId) -> Option<[u8; NETCODE_USER_DATA_BYTES]> {
130 self.netcode_server.user_data(client_id)
131 }
132
133 pub fn client_addr(&self, client_id: ClientId) -> Option<(usize, SocketAddr)> {
135 self.netcode_server.client_addr(client_id)
136 }
137
138 pub fn disconnect_all(&mut self, server: &mut RenetServer) {
143 for client_id in self.netcode_server.clients_id() {
144 let server_result = self.netcode_server.disconnect(client_id);
145 handle_server_result(server_result, &mut self.sockets, server);
146 }
147 }
148
149 pub fn time_since_last_received_packet(&self, client_id: ClientId) -> Option<Duration> {
153 self.netcode_server.time_since_last_received_packet(client_id)
154 }
155
156 pub fn update(&mut self, duration: Duration, server: &mut RenetServer) -> Result<(), Vec<NetcodeTransportError>> {
158 self.netcode_server.update(duration);
159
160 let mut transport_errors = Vec::default();
161 for socket_id in 0..self.sockets.len() {
162 self.sockets[socket_id].preupdate();
163
164 loop {
165 match self.sockets[socket_id].try_recv(&mut self.buffer) {
166 Ok((len, addr)) => {
167 let server_result = self.netcode_server.process_packet(socket_id, addr, &mut self.buffer[..len]);
168 handle_server_result(server_result, &mut self.sockets, server);
169 }
170 Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => break,
171 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => break,
172 Err(ref e) if e.kind() == io::ErrorKind::ConnectionReset => continue,
173 Err(e) => {
174 transport_errors.push(e.into());
175 }
176 };
177 }
178 }
179
180 for client_id in self.netcode_server.clients_id() {
181 let server_result = self.netcode_server.update_client(client_id);
182 handle_server_result(server_result, &mut self.sockets, server);
183 }
184
185 for disconnection_id in server.disconnections_id() {
186 let server_result = self.netcode_server.disconnect(disconnection_id);
187 handle_server_result(server_result, &mut self.sockets, server);
188 }
189
190 for socket in self.sockets.iter_mut() {
191 socket.postupdate();
192 }
193
194 if !transport_errors.is_empty() {
195 return Err(transport_errors);
196 }
197
198 Ok(())
199 }
200
201 pub fn send_packets(&mut self, server: &mut RenetServer) {
203 for client_id in server.clients_id() {
206 let packets = server.get_packets_to_send(client_id).unwrap();
207 for packet in packets {
208 if !send_packet_to_client(&mut self.sockets, &mut self.netcode_server, server, &packet, client_id) {
209 break;
210 }
211 }
212 }
213 }
214}
215
216fn send_packet_to_client(
220 sockets: &mut [Box<dyn ServerSocket>],
221 netcode_server: &mut NetcodeServer,
222 reliable_server: &mut RenetServer,
223 packet: &Payload,
224 client_id: ClientId,
225) -> bool {
226 let (send_result, socket_id, addr) = match netcode_server.generate_payload_packet(client_id, packet) {
227 Ok((socket_id, addr, payload)) => (sockets[socket_id].send(addr, payload), socket_id, addr),
228 Err(e) => {
229 log::error!("Failed to encrypt payload packet for client {client_id}: {e}");
230 return false;
231 }
232 };
233
234 match send_result {
235 Ok(()) => true,
236 Err(NetcodeTransportError::IO(ref e)) if e.kind() == io::ErrorKind::ConnectionAborted => {
237 reliable_server.remove_connection(client_id);
239 let _ = netcode_server.disconnect(client_id);
241
242 false
243 }
244 Err(e) => {
245 log::error!("Failed to send packet to client {client_id} ({socket_id}/{addr}): {e}");
246 false
247 }
248 }
249}
250
251fn handle_server_result(server_result: ServerResult, sockets: &mut [Box<dyn ServerSocket>], reliable_server: &mut RenetServer) {
252 let send_packet = |sockets: &mut [Box<dyn ServerSocket>], packet: &[u8], socket_id: usize, addr: SocketAddr| {
253 if let Err(err) = sockets[socket_id].send(addr, packet) {
254 log::trace!("Failed to send packet to {socket_id}/{addr}: {err}");
255 }
256 };
257
258 match server_result {
259 ServerResult::None => {}
260 ServerResult::Error { addr, socket_id } => {
261 sockets[socket_id].disconnect(addr);
262 }
263 ServerResult::ConnectionDenied { addr, socket_id, payload } => {
264 if let Some(payload) = payload {
265 send_packet(sockets, payload, socket_id, addr);
266 }
267 sockets[socket_id].connection_denied(addr);
268 }
269 ServerResult::ConnectionAccepted {
270 client_id,
271 addr,
272 socket_id,
273 payload,
274 } => {
275 sockets[socket_id].connection_accepted(client_id, addr);
276 send_packet(sockets, payload, socket_id, addr);
277 }
278 ServerResult::PacketToSend { payload, addr, socket_id } => {
279 send_packet(sockets, payload, socket_id, addr);
280 }
281 ServerResult::Payload { client_id, payload } => {
282 if let Err(e) = reliable_server.process_packet_from(payload, client_id) {
283 log::error!("Error while processing payload for {}: {}", client_id, e);
284 }
285 }
286 ServerResult::ClientConnected {
287 client_id,
288 user_data: _,
289 addr,
290 payload,
291 socket_id,
292 } => {
293 reliable_server.add_connection(client_id, sockets[socket_id].is_reliable());
294 send_packet(sockets, payload, socket_id, addr);
295 }
296 ServerResult::ClientDisconnected {
297 client_id,
298 addr,
299 payload,
300 socket_id,
301 } => {
302 reliable_server.remove_connection(client_id);
303 if let Some(payload) = payload {
304 send_packet(sockets, payload, socket_id, addr);
305 }
306 sockets[socket_id].disconnect(addr);
307 }
308 }
309}