rust/hedgewars-server/src/server/io.rs
author S.D.
Tue, 27 Sep 2022 14:59:03 +0300
changeset 15878 fc3cb23fd26f
parent 15831 7d0f747afcb8
child 15937 e514ceb5e7d6
permissions -rw-r--r--
Allow to see rooms of incompatible versions in the lobby For the new clients the room version is shown in a separate column. There is also a hack for previous versions clients: the room vesion specifier is prepended to the room names for rooms of incompatible versions, and the server shows 'incompatible version' error if the client tries to join them.
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::*;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    13
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    14
pub type RequestId = u32;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    15
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    16
pub struct IoThread {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    17
    core_tx: mpsc::Sender<(RequestId, IoTask)>,
15800
6af892a0a4b8 update mio
alfadur
parents: 15797
diff changeset
    18
    core_rx: mpsc::Receiver<(RequestId, IoResult)>,
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    19
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    20
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    21
impl IoThread {
15800
6af892a0a4b8 update mio
alfadur
parents: 15797
diff changeset
    22
    pub fn new(waker: Waker) -> Self {
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    23
        let (core_tx, io_rx) = mpsc::channel();
15800
6af892a0a4b8 update mio
alfadur
parents: 15797
diff changeset
    24
        let (io_tx, core_rx) = mpsc::channel();
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    25
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    26
        let mut db = Database::new();
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    27
        db.connect("localhost");
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    28
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    29
        thread::spawn(move || {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    30
            while let Ok((request_id, task)) = io_rx.recv() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    31
                let response = match task {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    32
                    IoTask::CheckRegistered { nick } => match db.is_registered(&nick) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    33
                        Ok(is_registered) => IoResult::AccountRegistered(is_registered),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    34
                        Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    35
                            warn!("Unable to check account's existence: {}", e);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    36
                            IoResult::AccountRegistered(false)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    37
                        }
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
                    IoTask::GetAccount {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    41
                        nick,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    42
                        protocol,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    43
                        password_hash,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    44
                        client_salt,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    45
                        server_salt,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    46
                    } => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    47
                        match db.get_account(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    48
                            &nick,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    49
                            protocol,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    50
                            &password_hash,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    51
                            &client_salt,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    52
                            &server_salt,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    53
                        ) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    54
                            Ok(account) => IoResult::Account(account),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    55
                            Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    56
                                warn!("Unable to get account data: {}", e);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    57
                                IoResult::Account(None)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    58
                            }
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
15532
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    62
                    IoTask::GetCheckerAccount { nick, password } => {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    63
                        match db.get_checker_account(&nick, &password) {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    64
                            Ok(is_registered) => IoResult::CheckerAccount { is_registered },
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    65
                            Err(e) => {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    66
                                warn!("Unable to get checker account data: {}", e);
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    67
                                IoResult::CheckerAccount {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    68
                                    is_registered: false,
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15120
diff changeset
    69
                                }
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
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    74
                    IoTask::GetReplay { id } => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    75
                        let result = match db.get_replay_name(id) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    76
                            Ok(Some(filename)) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    77
                                let filename = format!(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    78
                                    "checked/{}",
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    79
                                    if filename.starts_with("replays/") {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    80
                                        &filename[8..]
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    81
                                    } else {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    82
                                        &filename
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    83
                                    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    84
                                );
15796
2939d8599418 load haskell directly into Replay
alfadur
parents: 15532
diff changeset
    85
2939d8599418 load haskell directly into Replay
alfadur
parents: 15532
diff changeset
    86
                                match crate::core::types::Replay::load(&filename) {
2939d8599418 load haskell directly into Replay
alfadur
parents: 15532
diff changeset
    87
                                    Ok(replay) => Some(replay),
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    88
                                    Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    89
                                        warn!(
15797
655d0e0d612a fix error string
alfadur
parents: 15796
diff changeset
    90
                                            "Error while reading replay file \"{}\": {}",
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    91
                                            filename, e
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    92
                                        );
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    93
                                        None
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    94
                                    }
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
                            Ok(None) => None,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    98
                            Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
    99
                                warn!("Unable to get replay name: {}", e);
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   100
                                None
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   101
                            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   102
                        };
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   103
                        IoResult::Replay(result)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   104
                    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   105
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   106
                    IoTask::SaveRoom {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   107
                        room_id,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   108
                        filename,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   109
                        contents,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   110
                    } => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   111
                        let result = match save_file(&filename, &contents) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   112
                            Ok(()) => true,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   113
                            Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   114
                                warn!(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   115
                                    "Error while writing the room config file \"{}\": {}",
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   116
                                    filename, e
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   117
                                );
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   118
                                false
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   119
                            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   120
                        };
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   121
                        IoResult::SaveRoom(room_id, result)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   122
                    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   123
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   124
                    IoTask::LoadRoom { room_id, filename } => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   125
                        let result = match load_file(&filename) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   126
                            Ok(contents) => Some(contents),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   127
                            Err(e) => {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   128
                                warn!(
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   129
                                    "Error while writing the room config file \"{}\": {}",
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   130
                                    filename, e
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   131
                                );
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   132
                                None
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   133
                            }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   134
                        };
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   135
                        IoResult::LoadRoom(room_id, result)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   136
                    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   137
                };
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   138
                io_tx.send((request_id, response));
15800
6af892a0a4b8 update mio
alfadur
parents: 15797
diff changeset
   139
                waker.wake();
15120
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   140
            }
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
        Self { core_rx, core_tx }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   144
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   145
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   146
    pub fn send(&self, request_id: RequestId, task: IoTask) {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   147
        self.core_tx.send((request_id, task)).unwrap();
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   148
    }
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   149
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   150
    pub fn try_recv(&self) -> Option<(RequestId, IoResult)> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   151
        match self.core_rx.try_recv() {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   152
            Ok(result) => Some(result),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   153
            Err(mpsc::TryRecvError::Empty) => None,
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   154
            Err(mpsc::TryRecvError::Disconnected) => unreachable!(),
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   155
        }
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
fn save_file(filename: &str, contents: &str) -> Result<()> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   160
    let mut writer = OpenOptions::new().create(true).write(true).open(filename)?;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   161
    writer.write_all(contents.as_bytes())
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   162
}
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   163
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   164
fn load_file(filename: &str) -> Result<String> {
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   165
    let mut reader = File::open(filename)?;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   166
    let mut result = String::new();
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   167
    reader.read_to_string(&mut result)?;
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   168
    Ok(result)
febccab419b1 Apply dos2unix to rust sources
unc0rr
parents: 15103
diff changeset
   169
}