rust/hedgewars-server/src/server/io.rs
author alfadur
Tue, 09 Apr 2019 21:08:35 +0300
changeset 14784 f43ab2bd76ae
parent 14462 98ef2913ec73
child 14785 65861ba8b4e8
permissions -rw-r--r--
add a thread for internal server IO and implement account checking with it

use std::{
    fs::{File, OpenOptions},
    io::{Error, ErrorKind, Read, Result, Write},
    sync::mpsc,
    thread,
};

use crate::server::{
    database::Database,
    handlers::{IoResult, IoTask},
};
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.try_recv() {
                match task {
                    IoTask::GetAccount {
                        nick,
                        protocol,
                        password_hash,
                        client_salt,
                        server_salt,
                    } => {
                        if let Ok(account) = db.get_account(
                            &nick,
                            protocol,
                            &password_hash,
                            &client_salt,
                            &server_salt,
                        ) {
                            io_tx.send((request_id, IoResult::Account(account)));
                        }
                    }
                }
            }
        });

        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())
    }
}