author | Wuzzy <Wuzzy2@mail.ru> |
Mon, 16 Sep 2019 17:53:19 +0200 | |
changeset 15416 | 2cde69c1c680 |
parent 15125 | febccab419b1 |
permissions | -rw-r--r-- |
use std::{ fs::{File, OpenOptions}, io::{Error, ErrorKind, Read, Result, Write}, sync::mpsc, thread, }; use crate::{ handlers::{IoResult, IoTask}, server::database::Database, }; use log::*; use mio::{Evented, Poll, PollOpt}; use mio_extras::channel; pub type RequestId = u32; pub struct IoThread { core_tx: mpsc::Sender<(RequestId, IoTask)>, core_rx: channel::Receiver<(RequestId, IoResult)>, } impl IoThread { pub fn new() -> Self { let (core_tx, io_rx) = mpsc::channel(); let (io_tx, core_rx) = channel::channel(); let mut db = Database::new(); db.connect("localhost"); thread::spawn(move || { while let Ok((request_id, task)) = io_rx.recv() { let response = match task { IoTask::CheckRegistered { nick } => match db.is_registered(&nick) { Ok(is_registered) => IoResult::AccountRegistered(is_registered), Err(e) => { warn!("Unable to check account's existence: {}", e); IoResult::AccountRegistered(false) } }, IoTask::GetAccount { nick, protocol, password_hash, client_salt, server_salt, } => { match db.get_account( &nick, protocol, &password_hash, &client_salt, &server_salt, ) { Ok(account) => IoResult::Account(account), Err(e) => { warn!("Unable to get account data: {}", e); IoResult::Account(None) } } } IoTask::GetReplay { id } => { let result = match db.get_replay_name(id) { Ok(Some(filename)) => { let filename = format!( "checked/{}", if filename.starts_with("replays/") { &filename[8..] } else { &filename } ); match load_file(&filename) { Ok(contents) => Some(unimplemented!()), Err(e) => { warn!( "Error while writing the room config file \"{}\": {}", filename, e ); None } } } Ok(None) => None, Err(e) => { warn!("Unable to get replay name: {}", e); None } }; IoResult::Replay(result) } IoTask::SaveRoom { room_id, filename, contents, } => { let result = match save_file(&filename, &contents) { Ok(()) => true, Err(e) => { warn!( "Error while writing the room config file \"{}\": {}", filename, e ); false } }; IoResult::SaveRoom(room_id, result) } IoTask::LoadRoom { room_id, filename } => { let result = match load_file(&filename) { Ok(contents) => Some(contents), Err(e) => { warn!( "Error while writing the room config file \"{}\": {}", filename, e ); None } }; IoResult::LoadRoom(room_id, result) } }; io_tx.send((request_id, response)); } }); Self { core_rx, core_tx } } pub fn send(&self, request_id: RequestId, task: IoTask) { self.core_tx.send((request_id, task)).unwrap(); } pub fn try_recv(&self) -> Option<(RequestId, IoResult)> { match self.core_rx.try_recv() { Ok(result) => Some(result), Err(mpsc::TryRecvError::Empty) => None, Err(mpsc::TryRecvError::Disconnected) => unreachable!(), } } pub fn register_rx(&self, poll: &mio::Poll, token: mio::Token) -> Result<()> { self.core_rx .register(poll, token, mio::Ready::readable(), PollOpt::edge()) } } fn save_file(filename: &str, contents: &str) -> Result<()> { let mut writer = OpenOptions::new().create(true).write(true).open(filename)?; writer.write_all(contents.as_bytes()) } fn load_file(filename: &str) -> Result<String> { let mut reader = File::open(filename)?; let mut result = String::new(); reader.read_to_string(&mut result)?; Ok(result) }