1#[cfg(feature = "server")]
21pub mod server;
22
23#[cfg(feature = "client")]
24pub mod client;
25
26pub mod voice;
27
28use std::
29{
30 str::FromStr,
31 net::TcpStream,
32 mem::MaybeUninit,
33 io::{ Read, Write },
34 fmt::
35 {
36 self,
37 Display,
38 Formatter,
39 },
40};
41
42use wincode::
43{
44 SchemaWrite,
45 SchemaRead,
46 TypeMeta,
47 WriteResult,
48 ReadResult,
49 error::ReadError,
50 io::
51 {
52 Writer,
53 Reader,
54 },
55};
56
57use colored::Color;
58
59use crate::{ crypto, options };
60
61#[cfg(feature = "server")]
62use std::time::{ Instant, Duration };
63
64#[cfg(feature = "server")]
65use crate::config;
66
67#[derive(SchemaWrite, SchemaRead, PartialEq, Clone)]
69pub enum MessageCode {
71 KeyExchange, Rekey, Welcome, Disconnect, Username, PasswordL, PasswordR, Accept, Join, Leave, List, PrivateMessage, PrivateMessageBack, SpamWarning, RegisterDisabled, Version, Channel, Voice, ChannelJoin, ChannelLeave, VoiceClients, InvalidUsage, InvalidFeature, }
95
96#[derive(Clone)]
97pub struct SerColor(pub Color); #[derive(SchemaWrite, SchemaRead, Clone)]
100pub struct MessageColors {
102 pub username_color: Option<SerColor>, pub message_color: Option<SerColor>, }
105
106#[derive(SchemaWrite, SchemaRead, Clone)]
107pub struct MessagePacket {
109 pub text: Option<String>, pub username: Option<String>, pub id: Option<usize>, pub code: Option<MessageCode>, pub colors: MessageColors, pub seq: usize, }
116
117impl Default for MessagePacket {
120 fn default() -> Self
121 {
122 Self
123 {
124 text: None,
125 username: None,
126 id: None,
127 code: None,
128 colors: MessageColors
129 {
130 username_color: None,
131 message_color: None,
132 },
133 seq: 0,
134 }
135 }
136}
137
138impl Display for SerColor {
140 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
141 {
142 let color_str = match self.0
143 {
144 Color::Black => "black",
145 Color::Red => "red",
146 Color::Green => "green",
147 Color::Yellow => "yellow",
148 Color::Blue => "blue",
149 Color::Magenta => "magenta",
150 Color::Cyan => "cyan",
151 Color::BrightBlack => "bright black",
152 Color::BrightRed => "bright red",
153 Color::BrightGreen => "bright green",
154 Color::BrightYellow => "bright yellow",
155 Color::BrightBlue => "bright blue",
156 Color::BrightMagenta => "bright magenta",
157 Color::BrightCyan => "bright cyan",
158 Color::BrightWhite => "bright white",
159
160 _ => "white",
161 };
162
163 write!(f, "{color_str}")
164 }
165}
166
167impl FromStr for SerColor {
169 type Err = ReadError;
170
171 fn from_str(s: &str) -> Result<Self, Self::Err> {
172 Color::from_str(s)
173 .map(SerColor)
174 .map_err(|_| ReadError::Custom("Invalid color string"))
175 }
176}
177
178impl SchemaWrite for SerColor
180{
181 type Src = Self;
182 const TYPE_META: TypeMeta = TypeMeta::Dynamic;
183
184 fn size_of(src: &Self::Src) -> WriteResult<usize>
185 {
186 <String as SchemaWrite>::size_of(&src.to_string())
187 }
188
189 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()>
190 {
191 <String as SchemaWrite>::write(writer, &src.to_string())
192 }
193}
194
195impl<'de> SchemaRead<'de> for SerColor
197{
198 type Dst = Self;
199 const TYPE_META: TypeMeta = TypeMeta::Dynamic;
200
201 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()>
202 {
203 dst.write(<String as SchemaRead>::get(reader)?.parse::<SerColor>()?);
204 Ok(())
205 }
206}
207
208fn obfuscate_data(data: &[u8]) -> Vec<u8> {
212 let mut obfuscated = data.to_vec();
213 for (i, byte) in obfuscated.iter_mut().enumerate()
214 {
215 *byte ^= options::OBFUSCATION_KEY[i % options::OBFUSCATION_KEY.len()];
217 }
218
219 obfuscated
220}
221
222pub fn send(stream: &mut TcpStream, mut packet: MessagePacket, keys: Option<&options::SharedKeys>) {
225 #[cfg(feature = "client")]
227 {
228 packet.seq = options::get_seq() + 1;
229 options::set_seq(packet.seq);
230 }
231
232 #[cfg(feature = "server")]
234 {
235 let peer_addr = stream.peer_addr().ok();
236 if peer_addr.is_some() && let Some(mut conn) = server::CONNECTIONS.get_mut(&peer_addr.unwrap())
237 {
238 if conn.is_authenticated()
239 {
240 packet.seq = conn.server_seq().unwrap() + 1;
241 *conn.server_seq_mut().unwrap() = packet.seq;
242 }
243 }
244 }
245
246 let packet_bytes = wincode::serialize(&packet).expect("Encoding packet failed");
248
249 let mut final_bytes = if let Some(keys) = keys
250 {
251 crypto::encrypt_packet(packet_bytes, keys)
252 } else
253 {
254 obfuscate_data(&packet_bytes) };
256
257 let packet_len = final_bytes.len();
259 let mut transmission_packet = Vec::with_capacity(4 + packet_len);
260 transmission_packet.extend_from_slice(&(packet_len as u32).to_be_bytes());
261 transmission_packet.append(&mut final_bytes);
262
263 let _ = stream.write_all(&transmission_packet);
265 stream.flush().expect("Flushing stream failed");
266}
267
268pub fn receive(stream: &mut TcpStream, keys: Option<&options::SharedKeys>) -> Option<MessagePacket>
269{
270 #[cfg(feature = "server")]
272 let max_packet_size: usize;
273
274 #[cfg(feature = "server")]
276 let spam_protection = config::server_config::<bool>("spam_protection");
277
278 #[cfg(feature = "server")]
279 let peer_addr = stream.peer_addr().ok()?; #[cfg(feature = "server")]
283 {
284 let authenticated = server::CONNECTIONS.get(&peer_addr)
286 .map(|conn| conn.is_authenticated())
287 .unwrap_or(false);
288
289 max_packet_size = if !spam_protection && authenticated
291 {
292 usize::MAX
293 } else {
295 config::server_config("max_packet_size")
296 };
297 }
298
299 let mut len_buf = [0u8; 4];
301 if stream.read_exact(&mut len_buf).is_err() { return None; } let len = u32::from_be_bytes(len_buf) as usize;
303
304 #[cfg(feature = "server")]
306 if len > max_packet_size
307 {
308 server::remove_connection(&peer_addr, true);
309 return None;
310 }
311
312 let mut decoded_packet = vec![0u8; len];
314 if stream.read_exact(&mut decoded_packet).is_err() { return None; } if let Some(keys) = keys
318 {
319 decoded_packet = match crypto::decrypt_packet(decoded_packet, keys)
320 {
321 Some(d) => d,
322 None => {
324 #[cfg(feature = "server")]
326 log::warn!("HMAC verification failed: {}", peer_addr);
327
328 return None;
329 }
330 }
331 } else
332 {
333 decoded_packet = obfuscate_data(&decoded_packet); }
335
336 #[cfg(feature = "server")]
338 {
339 let mut spam_warning = false;
340 let mut shared_key = None;
341 let mut disconnect = false;
342
343 if let Some(mut conn) = server::CONNECTIONS.get_mut(&peer_addr)
345 {
346 if config::server_config("spam_protection") && conn.is_authenticated() &&
348 Instant::now().duration_since(*conn.last_activity()) <
349 Duration::from_millis(config::server_config::<u64>("min_message_delay"))
350 {
351 *conn.spam_violations_mut().unwrap() += 1;
353
354 spam_warning = true;
356 shared_key = conn.keys().cloned();
357
358 disconnect = *conn.spam_violations().unwrap() > config::server_config::<usize>("max_message_delay_violations");
360 }
361
362 *conn.last_activity_mut() = Instant::now(); }
364
365 if spam_warning
367 {
368 server::send_code(stream, None, MessageCode::SpamWarning, shared_key.as_ref());
369 }
370
371 if disconnect
373 {
374 server::remove_connection(&peer_addr, true);
375 return None;
376 }
377 }
378
379 match wincode::deserialize::<MessagePacket>(&decoded_packet)
381 {
382 Ok(packet) =>
383 {
384 #[cfg(feature = "server")] {
387 if let Some(mut conn) = server::CONNECTIONS.get_mut(&peer_addr)
388 {
389 if packet.seq > *conn.seq() {
391 *conn.seq_mut() = packet.seq;
393 } else
394 {
395 drop(conn); log::warn!("SEQ verification failed: {}", &peer_addr);
398 server::remove_connection(&peer_addr, false);
399 }
400 }
401 }
402
403 #[cfg(feature = "client")] {
406 if packet.seq > options::get_server_seq() || options::get_server_seq() == 0 || packet.code == Some(MessageCode::Disconnect) {
408 options::set_server_seq(packet.seq);
410 } else {
412 return None;
413 }
414 }
415
416 return Some(packet);
417 },
418
419 Err(_) =>
420 {
421 #[cfg(feature = "server")]
423 server::remove_connection(&peer_addr, false);
424
425 return None;
426 }
427 }
428}