You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
2.0 KiB
69 lines
2.0 KiB
use crate::chat_error::ChatError;
|
|
use crate::chat_user::ChatUser;
|
|
use crate::config::ConfigArgs;
|
|
use chrono::{DateTime, Utc};
|
|
use std::collections::BTreeMap;
|
|
use std::io::Write;
|
|
use std::net::TcpStream;
|
|
|
|
pub struct ChatServer {
|
|
pub config: ConfigArgs,
|
|
user_map: BTreeMap<u64, ChatUser>,
|
|
user_id_counter: u64,
|
|
}
|
|
|
|
impl ChatServer {
|
|
pub fn new(config: ConfigArgs) -> Self {
|
|
Self {
|
|
config,
|
|
user_map: BTreeMap::new(),
|
|
user_id_counter: 1,
|
|
}
|
|
}
|
|
|
|
pub fn get_user_count(&self) -> usize {
|
|
self.user_map.len()
|
|
}
|
|
|
|
/// register a client by creating a ChatUser for it and assigning it a user id
|
|
pub fn register(&mut self, name: String, socket: TcpStream) -> u64 {
|
|
let chat_user = ChatUser::new(self.user_id_counter, name, socket);
|
|
let client_id = chat_user.id;
|
|
self.user_map.insert(chat_user.id, chat_user);
|
|
self.user_id_counter += 1;
|
|
|
|
client_id
|
|
}
|
|
|
|
pub fn deregister(&mut self, client_id: u64) -> Option<ChatUser> {
|
|
self.user_map.remove(&client_id)
|
|
}
|
|
|
|
pub fn send_to_all(&mut self, msg: &str) -> Result<(), ChatError> {
|
|
let now: DateTime<Utc> = Utc::now();
|
|
let time_msg = format!("[{}] {}", now.format("%H:%M:%S"), msg);
|
|
let mut broken_clients = vec![];
|
|
for (user_id, user) in self.user_map.iter_mut() {
|
|
if write!(user.socket, "{}\n", time_msg).is_err() {
|
|
broken_clients.push((*user_id, user.name.clone()));
|
|
}
|
|
}
|
|
|
|
// remove users from map
|
|
for (user_id, _) in broken_clients.iter() {
|
|
self.deregister(*user_id);
|
|
}
|
|
|
|
// send out the news
|
|
for (_, name) in broken_clients.iter() {
|
|
self.send_to_all(&format!("* {} has left the chat (broken pipe)", name))?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn is_nick_in_use(&self, name: &str) -> bool {
|
|
self.user_map.values().any(|client| client.name == name)
|
|
}
|
|
}
|