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 connections: Arc>>>, pub unregistered_users: Arc>>, pub users: Arc>>, pub channels: Arc>>, } impl Context { pub fn new() -> Context { Context { connections: Arc::new(Mutex::new(HashMap::new())), unregistered_users: Arc::new(Mutex::new(HashMap::new())), 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 mut unreg = self.unregistered_users.lock().unwrap(); let remove = unreg.remove(addr); match remove { Some(user) => { if users.contains_key(&user.nickname) { self.send_string_to(&addr, format!(":plankircd 433 {} :Nickname is already in use", user.nickname)); unreg.insert(*addr, user); return Err(()); } let mut msg = format!(":plankircd 001 {} :Welcome to IRC!\r\n", user.nickname); msg += &format!(":plankircd 002 {} :Your host is plankircd, running version 0.0.1\r\n", user.nickname); msg += &format!(":plankircd 003 {} :This server was created tomorrow\r\n", user.nickname); msg += &format!(":plankircd 004 {} plankircd plankircd-0.0.1 o o\r\n", user.nickname); msg += &format!(":plankircd 422 {} :MOTD File is missing\r\n", user.nickname); let res = self.send_string_to(&addr, msg); println!("{:?}",res); users.insert(user.nickname.clone(), user); Ok(()) }, None => Err(()) } } pub fn disconnect(&mut self, addr: &SocketAddr) { self.send_message_to(addr, IrcMessage::new(Some("plankircd"), IrcCommand::ERROR, vec!["Connection terminated."])); self.connections.lock().unwrap().remove(addr); self.unregistered_users.lock().unwrap().remove(addr); self.users.lock().unwrap().retain(|_, u| u.address != *addr); } pub fn is_unreg(&self, addr: &SocketAddr) -> bool { self.unregistered_users.lock().unwrap().contains_key(addr) } pub fn send_string_to(&self, to: &SocketAddr, string: String) -> Result<(),SendError> { match self.connections.lock().unwrap().get(to) { Some(tx) => tx.unbounded_send(string), None => Ok(()), // TODO: proper error } } pub fn send_message_to(&self, to: &SocketAddr, message: IrcMessage) -> Result<(),SendError> { self.send_string_to(to, message.to_string()) } }