use futures::sync::mpsc::UnboundedSender; use futures::sync::mpsc::SendError; use std::net::SocketAddr; use std::collections::HashMap; use std::sync::{Arc, Mutex}; use user::User; use channel::Channel; use models::IrcMessage; use models::IrcCommand; #[derive(Clone)] pub struct Context { pub hostname: Arc>, pub users: Arc>>, pub channels: Arc>>, } impl Context { pub fn new() -> Context { Context { hostname: Arc::new(Mutex::new("plankircd".to_string())), users: Arc::new(Mutex::new(HashMap::new())), channels: Arc::new(Mutex::new(HashMap::new())), } } pub fn register_user(&mut self, addr: &SocketAddr) -> Result<(), ()> { let mut users = self.users.lock().unwrap(); let cloned = { users.get(addr).cloned() }; match cloned { Some(cloned) => { if !cloned.is_valid() || cloned.is_registered() { return Err(()); } if users.iter().any(|(k, v)| k != addr && v.nickname == cloned.nickname) { return Err(()); } users.get_mut(addr).unwrap().register(); Ok(()) }, None => Err(()) } } pub fn nick_exists(&self, nick: &str) -> bool { self.users.lock().unwrap().values().any(|user| user.nickname == nick) } pub fn send_message_to(&self, addr: &SocketAddr, msg: IrcMessage) -> Result<(), SendError> { if let Some(user) = self.users.lock().unwrap().get(addr) { user.send(msg) } else { Ok(()) } } pub fn is_registered(&self, addr: &SocketAddr) -> bool { if let Some(user) = self.users.lock().unwrap().get(addr) { user.is_registered() } else { false } } pub fn connect(&mut self, addr: SocketAddr, send: UnboundedSender) { self.users.lock().unwrap().insert(addr, User::new(send)); } pub fn disconnect(&mut self, addr: &SocketAddr) { if let Some(user) = self.users.lock().unwrap().remove(addr) { user.send(IrcMessage::new(Some(&self.hostname.lock().unwrap()), IrcCommand::ERROR, vec!["Connection terminated."])); } } }