rust/hedgewars-server/src/server/io.rs
author alfadur
Tue, 22 Jun 2021 01:41:33 +0300
changeset 15800 6af892a0a4b8
parent 15797 655d0e0d612a
child 15831 7d0f747afcb8
permissions -rw-r--r--
update mio
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
     1
use std::{
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
     2
    fs::{File, OpenOptions},
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
     3
    io::{Error, ErrorKind, Read, Result, Write},
15800
6af892a0a4b8 update mio
alfadur
parents: 15797
diff changeset
     4
    sync::{mpsc, Arc},
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
     5
    thread,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
     6
};
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
     7
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
     8
use crate::{
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
     9
    handlers::{IoResult, IoTask},
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    10
    server::database::Database,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    11
};
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    12
use log::*;
15800
6af892a0a4b8 update mio
alfadur
parents: 15797
diff changeset
    13
use mio::{Poll, Waker};
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    14
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    15
pub type RequestId = u32;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    16
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    17
pub struct IoThread {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    18
    core_tx: mpsc::Sender<(RequestId, IoTask)>,
15800
6af892a0a4b8 update mio
alfadur
parents: 15797
diff changeset
    19
    core_rx: mpsc::Receiver<(RequestId, IoResult)>,
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    20
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    21
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    22
impl IoThread {
15800
6af892a0a4b8 update mio
alfadur
parents: 15797
diff changeset
    23
    pub fn new(waker: Waker) -> Self {
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    24
        let (core_tx, io_rx) = mpsc::channel();
15800
6af892a0a4b8 update mio
alfadur
parents: 15797
diff changeset
    25
        let (io_tx, core_rx) = mpsc::channel();
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    26
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    27
        let mut db = Database::new();
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    28
        db.connect("localhost");
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    29
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    30
        thread::spawn(move || {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    31
            while let Ok((request_id, task)) = io_rx.recv() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    32
                let response = match task {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    33
                    IoTask::CheckRegistered { nick } => match db.is_registered(&nick) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    34
                        Ok(is_registered) => IoResult::AccountRegistered(is_registered),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    35
                        Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    36
                            warn!("Unable to check account's existence: {}", e);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    37
                            IoResult::AccountRegistered(false)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    38
                        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    39
                    },
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    40
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    41
                    IoTask::GetAccount {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    42
                        nick,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    43
                        protocol,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    44
                        password_hash,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    45
                        client_salt,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    46
                        server_salt,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    47
                    } => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    48
                        match db.get_account(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    49
                            &nick,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    50
                            protocol,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    51
                            &password_hash,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    52
                            &client_salt,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    53
                            &server_salt,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    54
                        ) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    55
                            Ok(account) => IoResult::Account(account),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    56
                            Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    57
                                warn!("Unable to get account data: {}", e);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    58
                                IoResult::Account(None)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    59
                            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    60
                        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    61
                    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    62
15532
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    63
                    IoTask::GetCheckerAccount { nick, password } => {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    64
                        match db.get_checker_account(&nick, &password) {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    65
                            Ok(is_registered) => IoResult::CheckerAccount { is_registered },
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    66
                            Err(e) => {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    67
                                warn!("Unable to get checker account data: {}", e);
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    68
                                IoResult::CheckerAccount {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    69
                                    is_registered: false,
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    70
                                }
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    71
                            }
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    72
                        }
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    73
                    }
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    74
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    75
                    IoTask::GetReplay { id } => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    76
                        let result = match db.get_replay_name(id) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    77
                            Ok(Some(filename)) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    78
                                let filename = format!(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    79
                                    "checked/{}",
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    80
                                    if filename.starts_with("replays/") {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    81
                                        &filename[8..]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    82
                                    } else {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    83
                                        &filename
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    84
                                    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    85
                                );
15796
2939d8599418 load haskell directly into Replay
alfadur
parents: 15532
diff changeset
    86
2939d8599418 load haskell directly into Replay
alfadur
parents: 15532
diff changeset
    87
                                match crate::core::types::Replay::load(&filename) {
2939d8599418 load haskell directly into Replay
alfadur
parents: 15532
diff changeset
    88
                                    Ok(replay) => Some(replay),
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    89
                                    Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    90
                                        warn!(
15797
655d0e0d612a fix error string
alfadur
parents: 15796
diff changeset
    91
                                            "Error while reading replay file \"{}\": {}",
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    92
                                            filename, e
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    93
                                        );
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    94
                                        None
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    95
                                    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    96
                                }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    97
                            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    98
                            Ok(None) => None,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    99
                            Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   100
                                warn!("Unable to get replay name: {}", e);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   101
                                None
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   102
                            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   103
                        };
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   104
                        IoResult::Replay(result)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   105
                    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   106
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   107
                    IoTask::SaveRoom {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   108
                        room_id,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   109
                        filename,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   110
                        contents,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   111
                    } => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   112
                        let result = match save_file(&filename, &contents) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   113
                            Ok(()) => true,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   114
                            Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   115
                                warn!(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   116
                                    "Error while writing the room config file \"{}\": {}",
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   117
                                    filename, e
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   118
                                );
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   119
                                false
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   120
                            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   121
                        };
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   122
                        IoResult::SaveRoom(room_id, result)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   123
                    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   124
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   125
                    IoTask::LoadRoom { room_id, filename } => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   126
                        let result = match load_file(&filename) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   127
                            Ok(contents) => Some(contents),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   128
                            Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   129
                                warn!(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   130
                                    "Error while writing the room config file \"{}\": {}",
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   131
                                    filename, e
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   132
                                );
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   133
                                None
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   134
                            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   135
                        };
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   136
                        IoResult::LoadRoom(room_id, result)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   137
                    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   138
                };
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   139
                io_tx.send((request_id, response));
15800
6af892a0a4b8 update mio
alfadur
parents: 15797
diff changeset
   140
                waker.wake();
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   141
            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   142
        });
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   143
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   144
        Self { core_rx, core_tx }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   145
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   146
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   147
    pub fn send(&self, request_id: RequestId, task: IoTask) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   148
        self.core_tx.send((request_id, task)).unwrap();
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   149
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   150
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   151
    pub fn try_recv(&self) -> Option<(RequestId, IoResult)> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   152
        match self.core_rx.try_recv() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   153
            Ok(result) => Some(result),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   154
            Err(mpsc::TryRecvError::Empty) => None,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   155
            Err(mpsc::TryRecvError::Disconnected) => unreachable!(),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   156
        }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   157
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   158
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   159
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   160
fn save_file(filename: &str, contents: &str) -> Result<()> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   161
    let mut writer = OpenOptions::new().create(true).write(true).open(filename)?;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   162
    writer.write_all(contents.as_bytes())
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   163
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   164
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   165
fn load_file(filename: &str) -> Result<String> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   166
    let mut reader = File::open(filename)?;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   167
    let mut result = String::new();
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   168
    reader.read_to_string(&mut result)?;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   169
    Ok(result)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   170
}