nomad_protocol/server/
session.rs1use std::net::SocketAddr;
9use std::time::Instant;
10
11use crate::core::SyncState;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub struct ServerSessionId([u8; 6]);
16
17impl ServerSessionId {
18 pub fn new(bytes: [u8; 6]) -> Self {
20 Self(bytes)
21 }
22
23 pub fn generate() -> Self {
25 use std::time::{SystemTime, UNIX_EPOCH};
27
28 let seed = SystemTime::now()
29 .duration_since(UNIX_EPOCH)
30 .unwrap()
31 .as_nanos() as u64;
32
33 let mut id = [0u8; 6];
34 let mut state = seed;
35 for byte in &mut id {
36 state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
37 *byte = (state >> 33) as u8;
38 }
39
40 Self(id)
41 }
42
43 pub fn as_bytes(&self) -> &[u8; 6] {
45 &self.0
46 }
47
48 pub fn to_u64(&self) -> u64 {
50 let mut buf = [0u8; 8];
51 buf[..6].copy_from_slice(&self.0);
52 u64::from_le_bytes(buf)
53 }
54}
55
56impl std::fmt::Display for ServerSessionId {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 write!(f, "{:012x}", self.to_u64())
59 }
60}
61
62impl From<[u8; 6]> for ServerSessionId {
63 fn from(bytes: [u8; 6]) -> Self {
64 Self::new(bytes)
65 }
66}
67
68impl From<ServerSessionId> for [u8; 6] {
69 fn from(id: ServerSessionId) -> [u8; 6] {
70 id.0
71 }
72}
73
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
76pub enum SessionState {
77 Handshaking,
79 Active,
81 Closing,
83 Closed,
85}
86
87#[derive(Debug)]
89pub struct ServerSession<S: SyncState> {
90 id: ServerSessionId,
92
93 client_addr: SocketAddr,
95
96 client_public_key: [u8; 32],
98
99 state: SessionState,
101
102 server_state: S,
104
105 client_state_version: u64,
107
108 server_state_version: u64,
110
111 last_activity: Instant,
113
114 created_at: Instant,
116
117 extensions: Vec<u16>,
119}
120
121impl<S: SyncState> ServerSession<S> {
122 pub fn new(
124 id: ServerSessionId,
125 client_addr: SocketAddr,
126 client_public_key: [u8; 32],
127 initial_state: S,
128 ) -> Self {
129 let now = Instant::now();
130 Self {
131 id,
132 client_addr,
133 client_public_key,
134 state: SessionState::Handshaking,
135 server_state: initial_state,
136 client_state_version: 0,
137 server_state_version: 0,
138 last_activity: now,
139 created_at: now,
140 extensions: Vec::new(),
141 }
142 }
143
144 pub fn id(&self) -> ServerSessionId {
146 self.id
147 }
148
149 pub fn client_addr(&self) -> SocketAddr {
151 self.client_addr
152 }
153
154 pub fn client_public_key(&self) -> &[u8; 32] {
156 &self.client_public_key
157 }
158
159 pub fn state(&self) -> SessionState {
161 self.state
162 }
163
164 pub fn set_state(&mut self, state: SessionState) {
166 self.state = state;
167 }
168
169 pub fn server_state(&self) -> &S {
171 &self.server_state
172 }
173
174 pub fn server_state_mut(&mut self) -> &mut S {
176 &mut self.server_state
177 }
178
179 pub fn update_server_state(&mut self, state: S) {
181 self.server_state = state;
182 self.server_state_version += 1;
183 }
184
185 pub fn client_state_version(&self) -> u64 {
187 self.client_state_version
188 }
189
190 pub fn update_client_state_version(&mut self, version: u64) {
192 self.client_state_version = version;
193 }
194
195 pub fn server_state_version(&self) -> u64 {
197 self.server_state_version
198 }
199
200 pub fn touch(&mut self) {
202 self.last_activity = Instant::now();
203 }
204
205 pub fn idle_time(&self) -> std::time::Duration {
207 self.last_activity.elapsed()
208 }
209
210 pub fn age(&self) -> std::time::Duration {
212 self.created_at.elapsed()
213 }
214
215 pub fn is_active(&self) -> bool {
217 self.state == SessionState::Active
218 }
219
220 pub fn update_client_addr(&mut self, addr: SocketAddr) {
222 self.client_addr = addr;
223 self.touch();
224 }
225
226 pub fn set_extensions(&mut self, extensions: Vec<u16>) {
228 self.extensions = extensions;
229 }
230
231 pub fn extensions(&self) -> &[u16] {
233 &self.extensions
234 }
235
236 pub fn compression_enabled(&self) -> bool {
238 self.extensions.contains(&0x0001)
240 }
241}
242
243#[cfg(test)]
244mod tests {
245 use super::*;
246
247 #[test]
248 fn test_session_id_generate() {
249 let id1 = ServerSessionId::generate();
250 let id2 = ServerSessionId::generate();
251
252 assert_ne!(id1, id2);
254 }
255
256 #[test]
257 fn test_session_id_display() {
258 let id = ServerSessionId::new([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
259 let display = format!("{}", id);
260 assert_eq!(display.len(), 12); }
262}