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::
60{
61 crypto,
62 options as chat_options,
63};
64
65#[cfg(feature = "server")]
66use std::time::{ Instant, Duration };
67
68#[cfg(feature = "server")]
69use crate::config;
70
71#[derive(SchemaWrite, SchemaRead, PartialEq, Clone)]
73pub enum MessageCode {
75 KeyExchange, Rekey, Welcome, Disconnect, Username, PasswordL, PasswordR, Accept, Join, Leave, List, PrivateMessage, PrivateMessageBack, SpamWarning, RegisterDisabled, Version, Channel, Voice, ChannelJoin, ChannelLeave, VoiceClients, InvalidUsage, InvalidFeature, }
99
100#[derive(Clone)]
101pub struct SerColor(pub Color); #[derive(SchemaWrite, SchemaRead, Clone)]
104pub struct MessageColors {
106 pub username_color: Option<SerColor>, pub message_color: Option<SerColor>, }
109
110#[derive(SchemaWrite, SchemaRead, Clone)]
111pub struct MessagePacket {
113 pub text: Option<String>, pub username: Option<String>, pub id: Option<usize>, pub code: Option<MessageCode>, pub colors: MessageColors, pub seq: usize, }
120
121impl Default for MessagePacket {
124 fn default() -> Self
125 {
126 Self
127 {
128 text: None,
129 username: None,
130 id: None,
131 code: None,
132 colors: MessageColors
133 {
134 username_color: None,
135 message_color: None,
136 },
137 seq: 0,
138 }
139 }
140}
141
142impl Display for SerColor {
144 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
145 {
146 let color_str = match self.0
147 {
148 Color::Black => "black",
149 Color::Red => "red",
150 Color::Green => "green",
151 Color::Yellow => "yellow",
152 Color::Blue => "blue",
153 Color::Magenta => "magenta",
154 Color::Cyan => "cyan",
155 Color::BrightBlack => "bright black",
156 Color::BrightRed => "bright red",
157 Color::BrightGreen => "bright green",
158 Color::BrightYellow => "bright yellow",
159 Color::BrightBlue => "bright blue",
160 Color::BrightMagenta => "bright magenta",
161 Color::BrightCyan => "bright cyan",
162 Color::BrightWhite => "bright white",
163
164 _ => "white",
165 };
166
167 write!(f, "{color_str}")
168 }
169}
170
171impl FromStr for SerColor {
173 type Err = ReadError;
174
175 fn from_str(s: &str) -> Result<Self, Self::Err> {
176 Color::from_str(s)
177 .map(SerColor)
178 .map_err(|_| ReadError::Custom("Invalid color string"))
179 }
180}
181
182impl SchemaWrite for SerColor
184{
185 type Src = Self;
186 const TYPE_META: TypeMeta = TypeMeta::Dynamic;
187
188 fn size_of(src: &Self::Src) -> WriteResult<usize>
189 {
190 <String as SchemaWrite>::size_of(&src.to_string())
191 }
192
193 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()>
194 {
195 <String as SchemaWrite>::write(writer, &src.to_string())
196 }
197}
198
199impl<'de> SchemaRead<'de> for SerColor
201{
202 type Dst = Self;
203 const TYPE_META: TypeMeta = TypeMeta::Dynamic;
204
205 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()>
206 {
207 dst.write(<String as SchemaRead>::get(reader)?.parse::<SerColor>()?);
208 Ok(())
209 }
210}
211
212pub fn send(stream: &mut TcpStream, mut packet: MessagePacket, keys: Option<&chat_options::SharedKeys>) {
215 #[cfg(feature = "client")]
217 {
218 packet.seq = chat_options::get_seq() + 1;
219 chat_options::set_seq(packet.seq);
220 }
221
222 #[cfg(feature = "server")]
224 {
225 let peer_addr = stream.peer_addr().ok();
226 if peer_addr.is_some() && let Some(mut conn) = server::CONNECTIONS.get_mut(&peer_addr.unwrap())
227 {
228 if conn.is_authenticated()
229 {
230 packet.seq = conn.server_seq().unwrap() + 1;
231 *conn.server_seq_mut().unwrap() = packet.seq;
232 }
233 }
234 }
235
236 let packet_bytes = wincode::serialize(&packet).expect("Encoding packet failed");
238
239 let mut final_bytes = if let Some(keys) = keys
240 {
241 crypto::encrypt_packet(packet_bytes, keys)
242 } else
243 {
244 packet_bytes };
246
247 let packet_len = final_bytes.len();
249 let mut transmission_packet = Vec::with_capacity(4 + packet_len);
250 transmission_packet.extend_from_slice(&(packet_len as u32).to_be_bytes());
251 transmission_packet.append(&mut final_bytes);
252
253 let _ = stream.write_all(&transmission_packet);
255 stream.flush().expect("Flushing stream failed");
256}
257
258pub fn receive(stream: &mut TcpStream, keys: Option<&chat_options::SharedKeys>) -> Option<MessagePacket>
259{
260 #[cfg(feature = "server")]
262 let max_packet_size: usize;
263
264 #[cfg(feature = "server")]
266 let spam_protection = config::server_config::<bool>("spam_protection");
267
268 #[cfg(feature = "server")]
269 let peer_addr = stream.peer_addr().ok()?; #[cfg(feature = "server")]
273 {
274 let authenticated = server::CONNECTIONS.get(&peer_addr)
276 .map(|conn| conn.is_authenticated())
277 .unwrap_or(false);
278
279 max_packet_size = if !spam_protection && authenticated
281 {
282 usize::MAX
283 } else {
285 config::server_config("max_packet_size")
286 };
287 }
288
289 let mut len_buf = [0u8; 4];
291 if stream.read_exact(&mut len_buf).is_err() { return None; } let len = u32::from_be_bytes(len_buf) as usize;
293
294 #[cfg(feature = "server")]
296 if len > max_packet_size
297 {
298 server::remove_connection(&peer_addr, true);
299 return None;
300 }
301
302 let mut decoded_packet = vec![0u8; len];
304 if stream.read_exact(&mut decoded_packet).is_err() { return None; } if let Some(keys) = keys
308 {
309 decoded_packet = match crypto::decrypt_packet(decoded_packet, keys)
310 {
311 Some(d) => d,
312 None => {
314 #[cfg(feature = "server")]
316 log::warn!("HMAC verification failed: {}", peer_addr);
317
318 return None;
319 }
320 }
321 }
322
323 #[cfg(feature = "server")]
325 {
326 let mut spam_warning = false;
327 let mut shared_key = None;
328 let mut disconnect = false;
329
330 if let Some(mut conn) = server::CONNECTIONS.get_mut(&peer_addr)
332 {
333 if config::server_config("spam_protection") && conn.is_authenticated() &&
335 Instant::now().duration_since(*conn.last_activity()) <
336 Duration::from_millis(config::server_config::<u64>("min_message_delay"))
337 {
338 *conn.spam_violations_mut().unwrap() += 1;
340
341 spam_warning = true;
343 shared_key = conn.keys().cloned();
344
345 disconnect = *conn.spam_violations().unwrap() > config::server_config::<usize>("max_message_delay_violations");
347 }
348
349 *conn.last_activity_mut() = Instant::now(); }
351
352 if spam_warning
354 {
355 server::send_code(stream, None, MessageCode::SpamWarning, shared_key.as_ref());
356 }
357
358 if disconnect
360 {
361 server::remove_connection(&peer_addr, true);
362 return None;
363 }
364 }
365
366 match wincode::deserialize::<MessagePacket>(&decoded_packet)
368 {
369 Ok(packet) =>
370 {
371 #[cfg(feature = "server")] {
374 if let Some(mut conn) = server::CONNECTIONS.get_mut(&peer_addr)
375 {
376 if packet.seq > *conn.seq() {
378 *conn.seq_mut() = packet.seq;
380 } else
381 {
382 drop(conn); log::warn!("SEQ verification failed: {}", &peer_addr);
385 server::remove_connection(&peer_addr, false);
386 }
387 }
388 }
389
390 #[cfg(feature = "client")] {
393 if packet.seq > chat_options::get_server_seq() || chat_options::get_server_seq() == 0 || packet.code == Some(MessageCode::Disconnect) {
395 chat_options::set_server_seq(packet.seq);
397 } else {
399 return None;
400 }
401 }
402
403 return Some(packet);
404 },
405
406 Err(_) =>
407 {
408 #[cfg(feature = "server")]
410 server::remove_connection(&peer_addr, false);
411
412 return None;
413 }
414 }
415}