gameServer2/src/server/network.rs
author Wuzzy <Wuzzy2@mail.ru>
Mon, 17 Sep 2018 22:37:47 +0200
changeset 13790 4ed202f0428e
parent 13671 09f4a30e50cc
child 13804 c8fd12db6215
permissions -rw-r--r--
Easier back jumps in Basic Movement Training (fixes bug #692) The explanation of Back Jumping (2/2) has been simplified and the "hard" part has been made easier by lowering the girders. The original idea was that I wanted to force players to learn how to jump higher by delaying the 2nd backspace keypress. But this turned out that this section was too unfair and we have lost at least one player due to rage-quitting, according to feedback.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
     1
extern crate slab;
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
     2
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
     3
use std::{
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
     4
    io, io::{Error, ErrorKind, Write},
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
     5
    net::{SocketAddr, IpAddr, Ipv4Addr},
13420
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
     6
    collections::HashSet,
13483
d79795acaa73 Mostly implement voting
alfadur
parents: 13424
diff changeset
     7
    mem::{swap, replace}
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
     8
};
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
     9
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    10
use mio::{
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    11
    net::{TcpStream, TcpListener},
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    12
    Poll, PollOpt, Ready, Token
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    13
};
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    14
use netbuf;
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    15
use slab::Slab;
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    16
13671
09f4a30e50cc Rust 2018 conversion
alfadur
parents: 13529
diff changeset
    17
use crate::{
09f4a30e50cc Rust 2018 conversion
alfadur
parents: 13529
diff changeset
    18
    utils,
09f4a30e50cc Rust 2018 conversion
alfadur
parents: 13529
diff changeset
    19
    protocol::{ProtocolDecoder, messages::*}
09f4a30e50cc Rust 2018 conversion
alfadur
parents: 13529
diff changeset
    20
};
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    21
use super::{
13424
81e0ed105f5d implementation of team related messages
alfadur
parents: 13421
diff changeset
    22
    server::{HWServer},
13483
d79795acaa73 Mostly implement voting
alfadur
parents: 13424
diff changeset
    23
    coretypes::ClientId
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    24
};
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    25
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    26
const MAX_BYTES_PER_READ: usize = 2048;
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    27
13420
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
    28
#[derive(Hash, Eq, PartialEq, Copy, Clone)]
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    29
pub enum NetworkClientState {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    30
    Idle,
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    31
    NeedsWrite,
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    32
    NeedsRead,
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    33
    Closed,
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    34
}
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    35
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    36
type NetworkResult<T> = io::Result<(T, NetworkClientState)>;
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    37
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    38
pub struct NetworkClient {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    39
    id: ClientId,
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    40
    socket: TcpStream,
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    41
    peer_addr: SocketAddr,
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    42
    decoder: ProtocolDecoder,
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    43
    buf_out: netbuf::Buf
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    44
}
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    45
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    46
impl NetworkClient {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    47
    pub fn new(id: ClientId, socket: TcpStream, peer_addr: SocketAddr) -> NetworkClient {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    48
        NetworkClient {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    49
            id, socket, peer_addr,
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    50
            decoder: ProtocolDecoder::new(),
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    51
            buf_out: netbuf::Buf::new()
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    52
        }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    53
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    54
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    55
    pub fn read_messages(&mut self) -> NetworkResult<Vec<HWProtocolMessage>> {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    56
        let mut bytes_read = 0;
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    57
        let result = loop {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    58
            match self.decoder.read_from(&mut self.socket) {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    59
                Ok(bytes) => {
13421
cdf69667593b partial room implementation
alfadur
parents: 13420
diff changeset
    60
                    debug!("Client {}: read {} bytes", self.id, bytes);
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    61
                    bytes_read += bytes;
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    62
                    if bytes == 0 {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    63
                        let result = if bytes_read == 0 {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    64
                            info!("EOF for client {} ({})", self.id, self.peer_addr);
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    65
                            (Vec::new(), NetworkClientState::Closed)
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    66
                        } else {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    67
                            (self.decoder.extract_messages(), NetworkClientState::NeedsRead)
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    68
                        };
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    69
                        break Ok(result);
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    70
                    }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    71
                    else if bytes_read >= MAX_BYTES_PER_READ {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    72
                        break Ok((self.decoder.extract_messages(), NetworkClientState::NeedsRead))
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    73
                    }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    74
                }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    75
                Err(ref error) if error.kind() == ErrorKind::WouldBlock => {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    76
                    let messages =  if bytes_read == 0 {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    77
                        Vec::new()
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    78
                    } else {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    79
                        self.decoder.extract_messages()
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    80
                    };
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    81
                    break Ok((messages, NetworkClientState::Idle));
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    82
                }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    83
                Err(error) =>
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    84
                    break Err(error)
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    85
            }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    86
        };
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    87
        self.decoder.sweep();
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    88
        result
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    89
    }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    90
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    91
    pub fn flush(&mut self) -> NetworkResult<()> {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    92
        let result = loop {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    93
            match self.buf_out.write_to(&mut self.socket) {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    94
                Ok(bytes) if self.buf_out.is_empty() || bytes == 0 =>
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    95
                    break Ok(((), NetworkClientState::Idle)),
13420
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
    96
                Ok(_) => (),
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    97
                Err(ref error) if error.kind() == ErrorKind::Interrupted
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    98
                    || error.kind() == ErrorKind::WouldBlock => {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
    99
                    break Ok(((), NetworkClientState::NeedsWrite));
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   100
                },
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   101
                Err(error) =>
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   102
                    break Err(error)
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   103
            }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   104
        };
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   105
        self.socket.flush()?;
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   106
        result
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   107
    }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   108
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   109
    pub fn send_raw_msg(&mut self, msg: &[u8]) {
13529
5359ff75da3a indulge clippy
alfadur
parents: 13483
diff changeset
   110
        self.buf_out.write_all(msg).unwrap();
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   111
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   112
13529
5359ff75da3a indulge clippy
alfadur
parents: 13483
diff changeset
   113
    pub fn send_string(&mut self, msg: &str) {
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   114
        self.send_raw_msg(&msg.as_bytes());
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   115
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   116
13529
5359ff75da3a indulge clippy
alfadur
parents: 13483
diff changeset
   117
    pub fn send_msg(&mut self, msg: &HWServerMessage) {
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   118
        self.send_string(&msg.to_raw_protocol());
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   119
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   120
}
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   121
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   122
pub struct NetworkLayer {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   123
    listener: TcpListener,
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   124
    server: HWServer,
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   125
    clients: Slab<NetworkClient>,
13420
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   126
    pending: HashSet<(ClientId, NetworkClientState)>,
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   127
    pending_cache: Vec<(ClientId, NetworkClientState)>
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   128
}
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   129
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   130
impl NetworkLayer {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   131
    pub fn new(listener: TcpListener, clients_limit: usize, rooms_limit: usize) -> NetworkLayer {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   132
        let server = HWServer::new(clients_limit, rooms_limit);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   133
        let clients = Slab::with_capacity(clients_limit);
13420
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   134
        let pending = HashSet::with_capacity(2 * clients_limit);
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   135
        let pending_cache = Vec::with_capacity(2 * clients_limit);
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   136
        NetworkLayer {listener, server, clients, pending, pending_cache}
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   137
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   138
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   139
    pub fn register_server(&self, poll: &Poll) -> io::Result<()> {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   140
        poll.register(&self.listener, utils::SERVER, Ready::readable(),
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   141
                      PollOpt::edge())
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   142
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   143
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   144
    fn deregister_client(&mut self, poll: &Poll, id: ClientId) {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   145
        let mut client_exists = false;
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   146
        if let Some(ref client) = self.clients.get(id) {
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   147
            poll.deregister(&client.socket)
13529
5359ff75da3a indulge clippy
alfadur
parents: 13483
diff changeset
   148
                .expect("could not deregister socket");
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   149
            info!("client {} ({}) removed", client.id, client.peer_addr);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   150
            client_exists = true;
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   151
        }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   152
        if client_exists {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   153
            self.clients.remove(id);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   154
        }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   155
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   156
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   157
    fn register_client(&mut self, poll: &Poll, id: ClientId, client_socket: TcpStream, addr: SocketAddr) {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   158
        poll.register(&client_socket, Token(id),
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   159
                      Ready::readable() | Ready::writable(),
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   160
                      PollOpt::edge())
13529
5359ff75da3a indulge clippy
alfadur
parents: 13483
diff changeset
   161
            .expect("could not register socket with event loop");
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   162
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   163
        let entry = self.clients.vacant_entry();
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   164
        let client = NetworkClient::new(id, client_socket, addr);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   165
        info!("client {} ({}) added", client.id, client.peer_addr);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   166
        entry.insert(client);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   167
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   168
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   169
    fn flush_server_messages(&mut self) {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   170
        debug!("{} pending server messages", self.server.output.len());
13424
81e0ed105f5d implementation of team related messages
alfadur
parents: 13421
diff changeset
   171
        for (clients, message) in self.server.output.drain(..) {
81e0ed105f5d implementation of team related messages
alfadur
parents: 13421
diff changeset
   172
            debug!("Message {:?} to {:?}", message, clients);
81e0ed105f5d implementation of team related messages
alfadur
parents: 13421
diff changeset
   173
            let msg_string = message.to_raw_protocol();
81e0ed105f5d implementation of team related messages
alfadur
parents: 13421
diff changeset
   174
            for client_id in clients {
81e0ed105f5d implementation of team related messages
alfadur
parents: 13421
diff changeset
   175
                if let Some(client) = self.clients.get_mut(client_id) {
81e0ed105f5d implementation of team related messages
alfadur
parents: 13421
diff changeset
   176
                    client.send_string(&msg_string);
81e0ed105f5d implementation of team related messages
alfadur
parents: 13421
diff changeset
   177
                    self.pending.insert((client_id, NetworkClientState::NeedsWrite));
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   178
                }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   179
            }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   180
        }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   181
    }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   182
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   183
    pub fn accept_client(&mut self, poll: &Poll) -> io::Result<()> {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   184
        let (client_socket, addr) = self.listener.accept()?;
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   185
        info!("Connected: {}", addr);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   186
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   187
        let client_id = self.server.add_client();
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   188
        self.register_client(poll, client_id, client_socket, addr);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   189
        self.flush_server_messages();
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   190
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   191
        Ok(())
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   192
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   193
13529
5359ff75da3a indulge clippy
alfadur
parents: 13483
diff changeset
   194
    fn operation_failed(&mut self, poll: &Poll, client_id: ClientId, error: &Error, msg: &str) -> io::Result<()> {
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   195
        let addr = if let Some(ref mut client) = self.clients.get_mut(client_id) {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   196
            client.peer_addr
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   197
        } else {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   198
            SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0)
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   199
        };
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   200
        debug!("{}({}): {}", msg, addr, error);
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   201
        self.client_error(poll, client_id)
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   202
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   203
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   204
    pub fn client_readable(&mut self, poll: &Poll,
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   205
                           client_id: ClientId) -> io::Result<()> {
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   206
        let messages =
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   207
            if let Some(ref mut client) = self.clients.get_mut(client_id) {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   208
                client.read_messages()
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   209
            } else {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   210
                warn!("invalid readable client: {}", client_id);
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   211
                Ok((Vec::new(), NetworkClientState::Idle))
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   212
            };
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   213
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   214
        match messages {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   215
            Ok((messages, state)) => {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   216
                for message in messages {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   217
                    self.server.handle_msg(client_id, message);
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   218
                }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   219
                match state {
13420
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   220
                    NetworkClientState::NeedsRead => {
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   221
                        self.pending.insert((client_id, state));
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   222
                    },
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   223
                    NetworkClientState::Closed =>
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   224
                        self.client_error(&poll, client_id)?,
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   225
                    _ => {}
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   226
                };
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   227
            }
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   228
            Err(e) => self.operation_failed(
13529
5359ff75da3a indulge clippy
alfadur
parents: 13483
diff changeset
   229
                poll, client_id, &e,
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   230
                "Error while reading from client socket")?
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   231
        }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   232
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   233
        self.flush_server_messages();
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   234
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   235
        if !self.server.removed_clients.is_empty() {
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   236
            let ids: Vec<_> = self.server.removed_clients.drain(..).collect();
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   237
            for client_id in ids {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   238
                self.deregister_client(poll, client_id);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   239
            }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   240
        }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   241
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   242
        Ok(())
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   243
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   244
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   245
    pub fn client_writable(&mut self, poll: &Poll,
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   246
                           client_id: ClientId) -> io::Result<()> {
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   247
        let result =
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   248
            if let Some(ref mut client) = self.clients.get_mut(client_id) {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   249
                client.flush()
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   250
            } else {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   251
                warn!("invalid writable client: {}", client_id);
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   252
                Ok(((), NetworkClientState::Idle))
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   253
            };
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   254
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   255
        match result {
13420
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   256
            Ok(((), state)) if state == NetworkClientState::NeedsWrite => {
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   257
                self.pending.insert((client_id, state));
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   258
            },
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   259
            Ok(_) => {}
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   260
            Err(e) => self.operation_failed(
13529
5359ff75da3a indulge clippy
alfadur
parents: 13483
diff changeset
   261
                poll, client_id, &e,
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   262
                "Error while writing to client socket")?
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   263
        }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   264
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   265
        Ok(())
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   266
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   267
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   268
    pub fn client_error(&mut self, poll: &Poll,
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   269
                        client_id: ClientId) -> io::Result<()> {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   270
        self.deregister_client(poll, client_id);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   271
        self.server.client_lost(client_id);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   272
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   273
        Ok(())
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   274
    }
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   275
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   276
    pub fn has_pending_operations(&self) -> bool {
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   277
        !self.pending.is_empty()
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   278
    }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   279
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   280
    pub fn on_idle(&mut self, poll: &Poll) -> io::Result<()> {
13420
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   281
        if self.has_pending_operations() {
13483
d79795acaa73 Mostly implement voting
alfadur
parents: 13424
diff changeset
   282
            let mut cache = replace(&mut self.pending_cache, Vec::new());
13420
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   283
            cache.extend(self.pending.drain());
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   284
            for (id, state) in cache.drain(..) {
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   285
                match state {
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   286
                    NetworkClientState::NeedsRead =>
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   287
                        self.client_readable(poll, id)?,
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   288
                    NetworkClientState::NeedsWrite =>
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   289
                        self.client_writable(poll, id)?,
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   290
                    _ => {}
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   291
                }
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   292
            }
13420
0eedc17055a0 rework of prior
alfadur
parents: 13419
diff changeset
   293
            swap(&mut cache, &mut self.pending_cache);
13419
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   294
        }
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   295
        Ok(())
28b314ad566d handle edge polling properly
alfadur
parents: 13124
diff changeset
   296
    }
13124
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   297
}