1use std::{
2 collections::{HashMap, VecDeque},
3 time::{Duration, Instant},
4};
5
6use wrym_transport::{ReliableTransport, Transport};
7
8use crate::Opcode;
9
10pub struct ServerConfig {
11 pub client_timeout: Duration,
12}
13
14impl Default for ServerConfig {
15 fn default() -> Self {
16 Self {
17 client_timeout: Duration::from_secs(60),
18 }
19 }
20}
21
22pub struct ClientData {
23 last_activity: Instant,
24}
25
26pub enum ServerEvent {
27 ClientConnected(String),
28 ClientDisconnected(String),
29 MessageReceived(String, Vec<u8>),
30}
31
32pub struct Server<T: Transport> {
33 transport: T,
34 config: ServerConfig,
35 clients: HashMap<String, ClientData>,
36 events: VecDeque<ServerEvent>,
37}
38
39impl<T: Transport> Server<T> {
40 pub fn new(transport: T, config: ServerConfig) -> Self {
41 Self {
42 transport,
43 config,
44 clients: HashMap::new(),
45 events: VecDeque::new(),
46 }
47 }
48
49 fn add_client(&mut self, addr: &str) {
50 if self
51 .clients
52 .insert(
53 addr.to_string(),
54 ClientData {
55 last_activity: Instant::now(),
56 },
57 )
58 .is_none()
59 {
60 self.transport
61 .send_to(&addr, &[Opcode::ClientConnected as u8]);
62 self.events
63 .push_back(ServerEvent::ClientConnected(addr.to_string()));
64 }
65 }
66
67 fn drop_client(&mut self, addr: &str) {
68 if self.clients.remove(addr).is_some() {
69 self.transport
70 .send_to(&addr, &[Opcode::ClientDisconnected as u8]);
71 self.events
72 .push_back(ServerEvent::ClientDisconnected(addr.to_string()));
73 }
74 }
75
76 fn drop_inactive_clients(&mut self, timeout: Duration) {
77 let to_disconnect: Vec<String> = self
78 .clients
79 .iter()
80 .filter_map(|(addr, data)| {
81 if Instant::now().duration_since(data.last_activity) > timeout {
82 Some(addr.to_owned())
83 } else {
84 None
85 }
86 })
87 .collect();
88
89 for addr in to_disconnect {
90 self.drop_client(&addr);
91 }
92 }
93
94 pub fn poll(&mut self) {
95 self.drop_inactive_clients(self.config.client_timeout);
96
97 if let Some((addr, mut bytes)) = self.transport.recv() {
98 if bytes.is_empty() {
99 return;
100 }
101
102 if let Some(data) = self.clients.get_mut(&addr) {
103 data.last_activity = Instant::now();
104 }
105
106 match bytes.remove(0).into() {
107 Opcode::ClientConnected => self.add_client(&addr),
108 Opcode::ClientDisconnected => self.drop_client(&addr),
109 Opcode::Message => {
110 self.events
111 .push_back(ServerEvent::MessageReceived(addr, bytes));
112 }
113 }
114 }
115 }
116
117 pub fn recv_event(&mut self) -> Option<ServerEvent> {
118 self.events.pop_front()
119 }
120
121 pub fn send_to(&self, addr: &str, bytes: &[u8]) {
122 self.transport
123 .send_to(addr, &Opcode::Message.with_bytes(bytes));
124 }
125
126 pub fn broadcast(&self, bytes: &[u8]) {
127 let msg = Opcode::Message.with_bytes(bytes);
128
129 for addr in self.clients.keys() {
130 self.transport.send_to(addr, &msg);
131 }
132 }
133}
134
135impl<T: Transport + ReliableTransport> Server<T> {
136 pub fn send_reliable_to(&self, addr: &str, bytes: &[u8], ordered: bool) {
137 self.transport
138 .send_reliable_to(addr, &Opcode::Message.with_bytes(bytes), ordered);
139 }
140
141 pub fn broadcast_reliable(&self, bytes: &[u8], ordered: bool) {
142 let msg = Opcode::Message.with_bytes(bytes);
143
144 for addr in self.clients.keys() {
145 self.transport.send_reliable_to(addr, &msg, ordered)
146 }
147 }
148}