rust/hedgewars-server/src/handlers.rs
author S.D.
Tue, 27 Sep 2022 14:59:03 +0300
changeset 15900 fc3cb23fd26f
parent 15853 7d0f747afcb8
child 16031 e915ed28726e
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:
15184
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
     1
use std::{
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
     2
    cmp::PartialEq,
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
     3
    collections::HashMap,
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
     4
    fmt::{Formatter, LowerHex},
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
     5
    iter::Iterator,
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
     6
};
12149
44b06731278b Fix handlers module
unc0rr
parents:
diff changeset
     7
15095
c5a6e8566425 shuffle server files
alfadur
parents: 14928
diff changeset
     8
use self::{
c5a6e8566425 shuffle server files
alfadur
parents: 14928
diff changeset
     9
    actions::{Destination, DestinationGroup, PendingMessage},
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
    10
    inanteroom::LoginResult,
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
    11
    strings::*,
14715
25c564f77b7d remove lobby room
alfadur <mail@none>
parents: 14714
diff changeset
    12
};
15826
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15565
diff changeset
    13
use crate::handlers::actions::ToPendingMessage;
14692
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
    14
use crate::{
15095
c5a6e8566425 shuffle server files
alfadur
parents: 14928
diff changeset
    15
    core::{
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
    16
        anteroom::HwAnteroom,
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
    17
        room::RoomSave,
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
    18
        server::HwServer,
15826
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15565
diff changeset
    19
        types::{ClientId, Replay, RoomId},
15095
c5a6e8566425 shuffle server files
alfadur
parents: 14928
diff changeset
    20
    },
15826
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15565
diff changeset
    21
    utils,
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15565
diff changeset
    22
};
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15565
diff changeset
    23
use hedgewars_network_protocol::{
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15565
diff changeset
    24
    messages::{
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
    25
        global_chat, server_chat, HwProtocolMessage, HwProtocolMessage::EngineMessage,
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
    26
        HwServerMessage, HwServerMessage::*,
15095
c5a6e8566425 shuffle server files
alfadur
parents: 14928
diff changeset
    27
    },
15826
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15565
diff changeset
    28
    types::{GameCfg, TeamInfo},
14692
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
    29
};
15826
747278149393 Extract network protocol into a separate crate
unc0rr
parents: 15565
diff changeset
    30
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
    31
use base64::encode;
13810
0463a4221327 cleanup crate imports
alfadur
parents: 13771
diff changeset
    32
use log::*;
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
    33
use rand::{thread_rng, RngCore};
13666
09f4a30e50cc Rust 2018 conversion
alfadur
parents: 13492
diff changeset
    34
15095
c5a6e8566425 shuffle server files
alfadur
parents: 14928
diff changeset
    35
mod actions;
14478
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14436
diff changeset
    36
mod checker;
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14436
diff changeset
    37
mod common;
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
    38
mod inanteroom;
15095
c5a6e8566425 shuffle server files
alfadur
parents: 14928
diff changeset
    39
mod inlobby;
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
    40
mod inroom;
15463
a158ff8f84ef refactor the lobby handler
alfadur
parents: 15237
diff changeset
    41
mod strings;
12149
44b06731278b Fix handlers module
unc0rr
parents:
diff changeset
    42
15123
80ff12edf5e6 handle response from IO result handler
alfadur
parents: 15096
diff changeset
    43
#[derive(PartialEq, Debug)]
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    44
pub struct Sha1Digest([u8; 20]);
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    45
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    46
impl Sha1Digest {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    47
    pub fn new(digest: [u8; 20]) -> Self {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    48
        Self(digest)
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    49
    }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    50
}
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    51
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    52
impl LowerHex for Sha1Digest {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    53
    fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    54
        for byte in &self.0 {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    55
            write!(f, "{:02x}", byte)?;
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    56
        }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    57
        Ok(())
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    58
    }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    59
}
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
    60
15184
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    61
impl PartialEq<&str> for Sha1Digest {
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    62
    fn eq(&self, other: &&str) -> bool {
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    63
        if other.len() != self.0.len() * 2 {
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    64
            false
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    65
        } else {
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    66
            #[inline]
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    67
            fn convert(c: u8) -> u8 {
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    68
                if c > b'9' {
15237
387345a14b3f replace overflowing_sub with wrapping_sub
alfadur
parents: 15197
diff changeset
    69
                    c.wrapping_sub(b'a').saturating_add(10)
15184
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    70
                } else {
15237
387345a14b3f replace overflowing_sub with wrapping_sub
alfadur
parents: 15197
diff changeset
    71
                    c.wrapping_sub(b'0')
15184
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    72
                }
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    73
            }
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    74
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    75
            other
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    76
                .as_bytes()
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    77
                .chunks_exact(2)
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    78
                .zip(&self.0)
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    79
                .all(|(chars, byte)| {
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    80
                    if let [hi, lo] = chars {
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    81
                        convert(*lo) == byte & 0x0f && convert(*hi) == (byte & 0xf0) >> 4
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    82
                    } else {
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    83
                        unreachable!()
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    84
                    }
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    85
                })
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    86
        }
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    87
    }
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    88
}
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
    89
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
    90
pub struct ServerState {
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
    91
    pub server: HwServer,
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
    92
    pub anteroom: HwAnteroom,
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
    93
}
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
    94
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
    95
impl ServerState {
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
    96
    pub fn new(clients_limit: usize, rooms_limit: usize) -> Self {
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
    97
        Self {
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
    98
            server: HwServer::new(clients_limit, rooms_limit),
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
    99
            anteroom: HwAnteroom::new(clients_limit),
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   100
        }
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   101
    }
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   102
}
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   103
15123
80ff12edf5e6 handle response from IO result handler
alfadur
parents: 15096
diff changeset
   104
#[derive(Debug)]
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   105
pub struct AccountInfo {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   106
    pub is_registered: bool,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   107
    pub is_admin: bool,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   108
    pub is_contributor: bool,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   109
    pub server_hash: Sha1Digest,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   110
}
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   111
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   112
pub enum IoTask {
15124
823052e66611 check for account existence before asking passwords
alfadur
parents: 15123
diff changeset
   113
    CheckRegistered {
823052e66611 check for account existence before asking passwords
alfadur
parents: 15123
diff changeset
   114
        nick: String,
823052e66611 check for account existence before asking passwords
alfadur
parents: 15123
diff changeset
   115
    },
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   116
    GetAccount {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   117
        nick: String,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   118
        protocol: u16,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   119
        password_hash: String,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   120
        client_salt: String,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   121
        server_salt: String,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   122
    },
15554
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   123
    GetCheckerAccount {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   124
        nick: String,
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   125
        password: String,
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   126
    },
14806
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   127
    GetReplay {
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   128
        id: u32,
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   129
    },
14801
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   130
    SaveRoom {
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   131
        room_id: RoomId,
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   132
        filename: String,
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   133
        contents: String,
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   134
    },
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   135
    LoadRoom {
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   136
        room_id: RoomId,
14802
01f8ab45f806 fix lobby joining
alfadur
parents: 14801
diff changeset
   137
        filename: String,
01f8ab45f806 fix lobby joining
alfadur
parents: 14801
diff changeset
   138
    },
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   139
}
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   140
15123
80ff12edf5e6 handle response from IO result handler
alfadur
parents: 15096
diff changeset
   141
#[derive(Debug)]
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   142
pub enum IoResult {
15124
823052e66611 check for account existence before asking passwords
alfadur
parents: 15123
diff changeset
   143
    AccountRegistered(bool),
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   144
    Account(Option<AccountInfo>),
15554
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   145
    CheckerAccount { is_registered: bool },
14806
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   146
    Replay(Option<Replay>),
14801
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   147
    SaveRoom(RoomId, bool),
14802
01f8ab45f806 fix lobby joining
alfadur
parents: 14801
diff changeset
   148
    LoadRoom(RoomId, Option<String>),
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   149
}
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   150
14692
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   151
pub struct Response {
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   152
    client_id: ClientId,
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   153
    messages: Vec<PendingMessage>,
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   154
    io_tasks: Vec<IoTask>,
14717
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   155
    removed_clients: Vec<ClientId>,
14692
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   156
}
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   157
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   158
impl Response {
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   159
    pub fn new(client_id: ClientId) -> Self {
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   160
        Self {
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   161
            client_id,
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   162
            messages: vec![],
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   163
            io_tasks: vec![],
14717
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   164
            removed_clients: vec![],
14692
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   165
        }
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   166
    }
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   167
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   168
    #[inline]
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   169
    pub fn is_empty(&self) -> bool {
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   170
        self.messages.is_empty() && self.removed_clients.is_empty() && self.io_tasks.is_empty()
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   171
    }
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   172
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   173
    #[inline]
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   174
    pub fn len(&self) -> usize {
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   175
        self.messages.len()
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   176
    }
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   177
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   178
    #[inline]
14692
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   179
    pub fn client_id(&self) -> ClientId {
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   180
        self.client_id
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   181
    }
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   182
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   183
    #[inline]
14692
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   184
    pub fn add(&mut self, message: PendingMessage) {
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   185
        self.messages.push(message)
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   186
    }
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   187
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   188
    #[inline]
15463
a158ff8f84ef refactor the lobby handler
alfadur
parents: 15237
diff changeset
   189
    pub fn warn(&mut self, message: &str) {
a158ff8f84ef refactor the lobby handler
alfadur
parents: 15237
diff changeset
   190
        self.add(Warning(message.to_string()).send_self());
a158ff8f84ef refactor the lobby handler
alfadur
parents: 15237
diff changeset
   191
    }
a158ff8f84ef refactor the lobby handler
alfadur
parents: 15237
diff changeset
   192
a158ff8f84ef refactor the lobby handler
alfadur
parents: 15237
diff changeset
   193
    #[inline]
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   194
    pub fn error(&mut self, message: &str) {
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   195
        self.add(Error(message.to_string()).send_self());
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   196
    }
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   197
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   198
    #[inline]
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   199
    pub fn request_io(&mut self, task: IoTask) {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   200
        self.io_tasks.push(task)
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   201
    }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   202
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   203
    pub fn extract_messages<'a, 'b: 'a>(
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   204
        &'b mut self,
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   205
        server: &'a HwServer,
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   206
    ) -> impl Iterator<Item = (Vec<ClientId>, HwServerMessage)> + 'a {
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   207
        let client_id = self.client_id;
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   208
        self.messages.drain(..).map(move |m| {
14809
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   209
            let ids = get_recipients(server, client_id, m.destination);
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   210
            (ids, m.message)
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   211
        })
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   212
    }
14717
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   213
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   214
    pub fn remove_client(&mut self, client_id: ClientId) {
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   215
        self.removed_clients.push(client_id);
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   216
    }
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   217
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   218
    pub fn extract_removed_clients(&mut self) -> impl Iterator<Item = ClientId> + '_ {
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   219
        self.removed_clients.drain(..)
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   220
    }
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   221
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   222
    pub fn extract_io_tasks(&mut self) -> impl Iterator<Item = IoTask> + '_ {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   223
        self.io_tasks.drain(..)
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   224
    }
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   225
}
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   226
14708
5122c584804e Server action refactoring part A of N
alfadur <mail@none>
parents: 14694
diff changeset
   227
impl Extend<PendingMessage> for Response {
5122c584804e Server action refactoring part A of N
alfadur <mail@none>
parents: 14694
diff changeset
   228
    fn extend<T: IntoIterator<Item = PendingMessage>>(&mut self, iter: T) {
5122c584804e Server action refactoring part A of N
alfadur <mail@none>
parents: 14694
diff changeset
   229
        for msg in iter {
5122c584804e Server action refactoring part A of N
alfadur <mail@none>
parents: 14694
diff changeset
   230
            self.add(msg)
5122c584804e Server action refactoring part A of N
alfadur <mail@none>
parents: 14694
diff changeset
   231
        }
5122c584804e Server action refactoring part A of N
alfadur <mail@none>
parents: 14694
diff changeset
   232
    }
5122c584804e Server action refactoring part A of N
alfadur <mail@none>
parents: 14694
diff changeset
   233
}
5122c584804e Server action refactoring part A of N
alfadur <mail@none>
parents: 14694
diff changeset
   234
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   235
fn get_recipients(
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   236
    server: &HwServer,
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   237
    client_id: ClientId,
14809
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   238
    destination: Destination,
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   239
) -> Vec<ClientId> {
14809
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   240
    match destination {
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   241
        Destination::ToSelf => vec![client_id],
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   242
        Destination::ToId(id) => vec![id],
14809
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   243
        Destination::ToIds(ids) => ids,
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   244
        Destination::ToAll { group, skip_self } => {
14810
18240b308505 implement stats message
alfadur
parents: 14809
diff changeset
   245
            let mut ids: Vec<_> = match group {
15548
24f692e791d3 disallow mutable rooms outside the server
alfadur <mail@none>
parents: 15545
diff changeset
   246
                DestinationGroup::All => server.iter_client_ids().collect(),
24f692e791d3 disallow mutable rooms outside the server
alfadur <mail@none>
parents: 15545
diff changeset
   247
                DestinationGroup::Lobby => server.lobby_client_ids().collect(),
24f692e791d3 disallow mutable rooms outside the server
alfadur <mail@none>
parents: 15545
diff changeset
   248
                DestinationGroup::Protocol(proto) => server.protocol_client_ids(proto).collect(),
24f692e791d3 disallow mutable rooms outside the server
alfadur <mail@none>
parents: 15545
diff changeset
   249
                DestinationGroup::Room(id) => server.room_client_ids(id).collect(),
14809
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   250
            };
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   251
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   252
            if skip_self {
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   253
                if let Some(index) = ids.iter().position(|id| *id == client_id) {
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   254
                    ids.remove(index);
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   255
                }
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   256
            }
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   257
6dea1ca64992 implement maxteams and teamchat messages
alfadur
parents: 14807
diff changeset
   258
            ids
14693
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   259
        }
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14692
diff changeset
   260
    }
14692
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   261
}
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   262
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   263
pub fn handle(
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   264
    state: &mut ServerState,
14692
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   265
    client_id: ClientId,
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   266
    response: &mut Response,
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   267
    message: HwProtocolMessage,
14692
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   268
) {
12149
44b06731278b Fix handlers module
unc0rr
parents:
diff changeset
   269
    match message {
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   270
        HwProtocolMessage::Ping => response.add(Pong.send_self()),
15134
7d6e519a88c5 consume pongs
alfadur
parents: 15124
diff changeset
   271
        HwProtocolMessage::Pong => (),
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   272
        _ => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   273
            if state.anteroom.clients.contains(client_id) {
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   274
                match inanteroom::handle(state, client_id, response, message) {
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   275
                    LoginResult::Unchanged => (),
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   276
                    LoginResult::Complete => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   277
                        if let Some(client) = state.anteroom.remove_client(client_id) {
15556
bb93e9642b5b send cleared flags on room join
alfadur <mail@none>
parents: 15554
diff changeset
   278
                            let is_checker = client.is_checker;
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   279
                            state.server.add_client(client_id, client);
15556
bb93e9642b5b send cleared flags on room join
alfadur <mail@none>
parents: 15554
diff changeset
   280
                            if !is_checker {
bb93e9642b5b send cleared flags on room join
alfadur <mail@none>
parents: 15554
diff changeset
   281
                                common::get_lobby_join_data(&state.server, response);
bb93e9642b5b send cleared flags on room join
alfadur <mail@none>
parents: 15554
diff changeset
   282
                            }
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   283
                        }
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   284
                    }
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   285
                    LoginResult::Exit => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   286
                        state.anteroom.remove_client(client_id);
14717
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   287
                        response.remove_client(client_id);
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   288
                    }
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   289
                }
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   290
            } else if state.server.has_client(client_id) {
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   291
                match message {
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   292
                    HwProtocolMessage::Quit(Some(msg)) => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   293
                        common::remove_client(
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   294
                            &mut state.server,
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   295
                            response,
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   296
                            "User quit: ".to_string() + &msg,
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   297
                        );
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   298
                    }
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   299
                    HwProtocolMessage::Quit(None) => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   300
                        common::remove_client(&mut state.server, response, "User quit".to_string());
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   301
                    }
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   302
                    HwProtocolMessage::Info(nick) => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   303
                        if let Some(client) = state.server.find_client(&nick) {
14807
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   304
                            let admin_sign = if client.is_admin() { "@" } else { "" };
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   305
                            let master_sign = if client.is_master() { "+" } else { "" };
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   306
                            let room_info = match client.room_id {
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   307
                                Some(room_id) => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   308
                                    let room = state.server.room(room_id);
14807
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   309
                                    let status = match room.game_info {
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   310
                                        Some(_) if client.teams_in_game == 0 => "(spectating)",
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   311
                                        Some(_) => "(playing)",
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   312
                                        None => "",
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   313
                                    };
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   314
                                    format!(
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   315
                                        "[{}{}room {}]{}",
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   316
                                        admin_sign, master_sign, room.name, status
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   317
                                    )
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   318
                                }
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   319
                                None => format!("[{}lobby]", admin_sign),
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   320
                            };
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   321
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   322
                            let info = vec![
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   323
                                client.nick.clone(),
14823
a40139603cde fix info response
alfadur
parents: 14817
diff changeset
   324
                                "[]".to_string(),
14807
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   325
                                utils::protocol_version_string(client.protocol_number).to_string(),
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   326
                                room_info,
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   327
                            ];
14823
a40139603cde fix info response
alfadur
parents: 14817
diff changeset
   328
                            response.add(Info(info).send_self())
14807
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   329
                        } else {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   330
                            response.add(server_chat(USER_OFFLINE.to_string()).send_self())
14807
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   331
                        }
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   332
                    }
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   333
                    HwProtocolMessage::ToggleServerRegisteredOnly => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   334
                        if !state.server.is_admin(client_id) {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   335
                            response.warn(ACCESS_DENIED);
14807
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   336
                        } else {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   337
                            state
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   338
                                .server
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   339
                                .set_is_registered_only(!state.server.is_registered_only());
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   340
                            let msg = if state.server.is_registered_only() {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   341
                                REGISTERED_ONLY_ENABLED
14807
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   342
                            } else {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   343
                                REGISTERED_ONLY_DISABLED
14807
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   344
                            };
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   345
                            response.add(server_chat(msg.to_string()).send_all());
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   346
                        }
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   347
                    }
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   348
                    HwProtocolMessage::Global(msg) => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   349
                        if !state.server.is_admin(client_id) {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   350
                            response.warn(ACCESS_DENIED);
14806
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   351
                        } else {
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   352
                            response.add(global_chat(msg).send_all())
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   353
                        }
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   354
                    }
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   355
                    HwProtocolMessage::SuperPower => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   356
                        if state.server.enable_super_power(client_id) {
15540
e705d30e0f10 some more room handler cleanup
alfadur <mail@none>
parents: 15539
diff changeset
   357
                            response.add(server_chat(SUPER_POWER.to_string()).send_self())
e705d30e0f10 some more room handler cleanup
alfadur <mail@none>
parents: 15539
diff changeset
   358
                        } else {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   359
                            response.warn(ACCESS_DENIED);
14807
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   360
                        }
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   361
                    }
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15832
diff changeset
   362
                    #[allow(unused_variables)]
15096
e935b1ad23f3 normalize type names
alfadur
parents: 15095
diff changeset
   363
                    HwProtocolMessage::Watch(id) => {
14806
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   364
                        #[cfg(feature = "official-server")]
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   365
                        {
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   366
                            response.request_io(IoTask::GetReplay { id })
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   367
                        }
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   368
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   369
                        #[cfg(not(feature = "official-server"))]
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   370
                        {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   371
                            response.warn(REPLAY_NOT_SUPPORTED);
14806
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   372
                        }
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   373
                    }
15545
f4f6060b536c add a separate interface for modifying room state
alfadur <mail@none>
parents: 15544
diff changeset
   374
                    _ => match state.server.get_room_control(client_id) {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   375
                        None => inlobby::handle(&mut state.server, client_id, response, message),
15545
f4f6060b536c add a separate interface for modifying room state
alfadur <mail@none>
parents: 15544
diff changeset
   376
                        Some(control) => inroom::handle(control, response, message),
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   377
                    },
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   378
                }
14692
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14478
diff changeset
   379
            }
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   380
        }
12149
44b06731278b Fix handlers module
unc0rr
parents:
diff changeset
   381
    }
44b06731278b Fix handlers module
unc0rr
parents:
diff changeset
   382
}
14694
08a8605bafaf Server action refactoring part 4 of N
alfadur <mail@none>
parents: 14693
diff changeset
   383
15197
f6115638aa92 enable local admins for non-official servers
alfadur
parents: 15184
diff changeset
   384
pub fn handle_client_accept(
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   385
    state: &mut ServerState,
15197
f6115638aa92 enable local admins for non-official servers
alfadur
parents: 15184
diff changeset
   386
    client_id: ClientId,
f6115638aa92 enable local admins for non-official servers
alfadur
parents: 15184
diff changeset
   387
    response: &mut Response,
15539
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   388
    addr: [u8; 4],
15197
f6115638aa92 enable local admins for non-official servers
alfadur
parents: 15184
diff changeset
   389
    is_local: bool,
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15832
diff changeset
   390
) -> bool {
15539
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   391
    let ban_reason = Some(addr)
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   392
        .filter(|_| !is_local)
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   393
        .and_then(|a| state.anteroom.find_ip_ban(a));
15539
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   394
    if let Some(reason) = ban_reason {
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   395
        response.add(HwServerMessage::Bye(reason).send_self());
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   396
        response.remove_client(client_id);
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15832
diff changeset
   397
        false
15539
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   398
    } else {
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   399
        let mut salt = [0u8; 18];
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   400
        thread_rng().fill_bytes(&mut salt);
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   401
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   402
        state
15539
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   403
            .anteroom
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   404
            .add_client(client_id, encode(&salt), is_local);
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   405
15853
7d0f747afcb8 move server network to tokio
alfadur
parents: 15832
diff changeset
   406
        response.add(
7d0f747afcb8 move server network to tokio
alfadur
parents: 15832
diff changeset
   407
            HwServerMessage::Connected(utils::SERVER_MESSAGE.to_owned(), utils::SERVER_VERSION)
7d0f747afcb8 move server network to tokio
alfadur
parents: 15832
diff changeset
   408
                .send_self(),
7d0f747afcb8 move server network to tokio
alfadur
parents: 15832
diff changeset
   409
        );
7d0f747afcb8 move server network to tokio
alfadur
parents: 15832
diff changeset
   410
        true
15539
abd5eb807166 add ip ban check
alfadur <mail@none>
parents: 15504
diff changeset
   411
    }
14714
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   412
}
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14711
diff changeset
   413
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   414
pub fn handle_client_loss(state: &mut ServerState, client_id: ClientId, response: &mut Response) {
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   415
    if state.anteroom.remove_client(client_id).is_none() {
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   416
        common::remove_client(&mut state.server, response, "Connection reset".to_string());
14717
8a45c90f4580 fix client removal
alfadur
parents: 14715
diff changeset
   417
    }
14694
08a8605bafaf Server action refactoring part 4 of N
alfadur <mail@none>
parents: 14693
diff changeset
   418
}
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   419
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   420
pub fn handle_io_result(
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   421
    state: &mut ServerState,
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   422
    client_id: ClientId,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   423
    response: &mut Response,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   424
    io_result: IoResult,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   425
) {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   426
    match io_result {
15124
823052e66611 check for account existence before asking passwords
alfadur
parents: 15123
diff changeset
   427
        IoResult::AccountRegistered(is_registered) => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   428
            if !is_registered && state.server.is_registered_only() {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   429
                response.add(Bye(REGISTRATION_REQUIRED.to_string()).send_self());
14807
8ecdb5c6bb2a implement info, registered only & super power messages
alfadur
parents: 14806
diff changeset
   430
                response.remove_client(client_id);
15124
823052e66611 check for account existence before asking passwords
alfadur
parents: 15123
diff changeset
   431
            } else if is_registered {
15554
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   432
                let client = &state.anteroom.clients[client_id];
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   433
                response.add(AskPassword(client.server_salt.clone()).send_self());
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   434
            } else if let Some(client) = state.anteroom.remove_client(client_id) {
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   435
                state.server.add_client(client_id, client);
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   436
                common::get_lobby_join_data(&state.server, response);
15124
823052e66611 check for account existence before asking passwords
alfadur
parents: 15123
diff changeset
   437
            }
823052e66611 check for account existence before asking passwords
alfadur
parents: 15123
diff changeset
   438
        }
15554
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   439
        IoResult::Account(None) => {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   440
            response.add(Bye(AUTHENTICATION_FAILED.to_string()).send_self());
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   441
            response.remove_client(client_id);
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   442
        }
15124
823052e66611 check for account existence before asking passwords
alfadur
parents: 15123
diff changeset
   443
        IoResult::Account(Some(info)) => {
823052e66611 check for account existence before asking passwords
alfadur
parents: 15123
diff changeset
   444
            response.add(ServerAuth(format!("{:x}", info.server_hash)).send_self());
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   445
            if let Some(mut client) = state.anteroom.remove_client(client_id) {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   446
                client.is_registered = info.is_registered;
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   447
                client.is_admin = info.is_admin;
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   448
                client.is_contributor = info.is_contributor;
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   449
                state.server.add_client(client_id, client);
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   450
                common::get_lobby_join_data(&state.server, response);
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   451
            }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   452
        }
15554
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   453
        IoResult::CheckerAccount { is_registered } => {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   454
            if is_registered {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   455
                if let Some(client) = state.anteroom.remove_client(client_id) {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   456
                    state.server.add_client(client_id, client);
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   457
                    response.add(LogonPassed.send_self());
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   458
                }
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   459
            } else {
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   460
                response.add(Bye(NO_CHECKER_RIGHTS.to_string()).send_self());
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   461
                response.remove_client(client_id);
f1205f33bf5b complete checker login handling
alfadur <mail@none>
parents: 15548
diff changeset
   462
            }
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   463
        }
14806
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   464
        IoResult::Replay(Some(replay)) => {
15542
fd3a20e9d095 move the anteroom out of the server
alfadur <mail@none>
parents: 15541
diff changeset
   465
            let client = state.server.client(client_id);
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   466
            let protocol = client.protocol_number;
14928
c156273b57de add REPLAY_START support
alfadur
parents: 14823
diff changeset
   467
            let start_msg = if protocol < 58 {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   468
                RoomJoined(vec![client.nick.clone()])
14928
c156273b57de add REPLAY_START support
alfadur
parents: 14823
diff changeset
   469
            } else {
c156273b57de add REPLAY_START support
alfadur
parents: 14823
diff changeset
   470
                ReplayStart
c156273b57de add REPLAY_START support
alfadur
parents: 14823
diff changeset
   471
            };
c156273b57de add REPLAY_START support
alfadur
parents: 14823
diff changeset
   472
            response.add(start_msg.send_self());
c156273b57de add REPLAY_START support
alfadur
parents: 14823
diff changeset
   473
15565
02f648f7cbe1 better response grouping
alfadur <mail@none>
parents: 15556
diff changeset
   474
            common::get_room_config_impl(&replay.config, Destination::ToSelf, response);
02f648f7cbe1 better response grouping
alfadur <mail@none>
parents: 15556
diff changeset
   475
            common::get_teams(replay.teams.iter(), Destination::ToSelf, response);
14806
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   476
            response.add(RunGame.send_self());
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   477
            response.add(ForwardEngineMessage(replay.message_log).send_self());
14928
c156273b57de add REPLAY_START support
alfadur
parents: 14823
diff changeset
   478
c156273b57de add REPLAY_START support
alfadur
parents: 14823
diff changeset
   479
            if protocol < 58 {
c156273b57de add REPLAY_START support
alfadur
parents: 14823
diff changeset
   480
                response.add(Kicked.send_self());
c156273b57de add REPLAY_START support
alfadur
parents: 14823
diff changeset
   481
            }
14806
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   482
        }
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   483
        IoResult::Replay(None) => {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   484
            response.warn(REPLAY_LOAD_FAILED);
14806
a1077e8d26f4 implement watch message apart from replay deserializing
alfadur
parents: 14805
diff changeset
   485
        }
14801
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   486
        IoResult::SaveRoom(_, true) => {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   487
            response.add(server_chat(ROOM_CONFIG_SAVED.to_string()).send_self());
14801
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   488
        }
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   489
        IoResult::SaveRoom(_, false) => {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   490
            response.warn(ROOM_CONFIG_SAVE_FAILED);
14801
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   491
        }
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   492
        IoResult::LoadRoom(room_id, Some(contents)) => {
15548
24f692e791d3 disallow mutable rooms outside the server
alfadur <mail@none>
parents: 15545
diff changeset
   493
            match state.server.set_room_saves(room_id, &contents) {
24f692e791d3 disallow mutable rooms outside the server
alfadur <mail@none>
parents: 15545
diff changeset
   494
                Ok(_) => response.add(server_chat(ROOM_CONFIG_LOADED.to_string()).send_self()),
24f692e791d3 disallow mutable rooms outside the server
alfadur <mail@none>
parents: 15545
diff changeset
   495
                Err(e) => {
24f692e791d3 disallow mutable rooms outside the server
alfadur <mail@none>
parents: 15545
diff changeset
   496
                    warn!("Error while deserializing the room configs: {}", e);
24f692e791d3 disallow mutable rooms outside the server
alfadur <mail@none>
parents: 15545
diff changeset
   497
                    response.warn(ROOM_CONFIG_DESERIALIZE_FAILED);
14801
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   498
                }
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   499
            }
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   500
        }
14802
01f8ab45f806 fix lobby joining
alfadur
parents: 14801
diff changeset
   501
        IoResult::LoadRoom(_, None) => {
15465
61a0bd0bb021 refactor root handler
alfadur
parents: 15463
diff changeset
   502
            response.warn(ROOM_CONFIG_LOAD_FAILED);
14801
65861ba8b4e8 move room saves to IO thread
alfadur
parents: 14800
diff changeset
   503
        }
14800
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   504
    }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14717
diff changeset
   505
}
15184
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   506
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   507
#[cfg(test)]
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   508
mod test {
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   509
    use super::Sha1Digest;
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   510
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   511
    #[test]
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   512
    fn hash_cmp_test() {
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   513
        let hash = Sha1Digest([
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   514
            0x37, 0xC4, 0x9F, 0x5C, 0xC3, 0xC9, 0xDB, 0xFC, 0x54, 0xAC, 0x22, 0x04, 0xF6, 0x12,
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   515
            0x9A, 0xED, 0x69, 0xB1, 0xC4, 0x5C,
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   516
        ]);
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   517
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   518
        assert_eq!(hash, &format!("{:x}", hash)[..]);
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   519
    }
bcb98009ad39 avoid allocation in hash comparison
alfadur
parents: 15134
diff changeset
   520
}