rust/hedgewars-server/src/server/network.rs
author Wuzzy <Wuzzy2@mail.ru>
Thu, 11 Jul 2019 16:24:09 +0200
changeset 15231 c10e9261ab9c
parent 15176 f6115638aa92
child 15517 abd5eb807166
permissions -rw-r--r--
Make lowest line of Splash image frames transparent to work around scaling issues The Splash image is scaled. Sometimes, the lowest line is repeated on the top, which caused some weird lines to appear above big splashes (e.g. piano). This has been done fully automated with a script. Only the alpha channel was changed. The color information is preserved.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
13119
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
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
     3
use std::{
13415
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
     4
    collections::HashSet,
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
     5
    io,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
     6
    io::{Error, ErrorKind, Read, Write},
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
     7
    mem::{replace, swap},
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
     8
    net::{IpAddr, Ipv4Addr, SocketAddr},
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
     9
};
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    10
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
    11
use log::*;
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    12
use mio::{
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
    13
    net::{TcpListener, TcpStream},
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
    14
    Evented, Poll, PollOpt, Ready, Token,
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    15
};
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
    16
use mio_extras::timer;
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    17
use netbuf;
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    18
use slab::Slab;
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    19
13666
09f4a30e50cc Rust 2018 conversion
alfadur
parents: 13524
diff changeset
    20
use crate::{
15075
e935b1ad23f3 normalize type names
alfadur
parents: 15074
diff changeset
    21
    core::{server::HwServer, types::ClientId},
15074
c5a6e8566425 shuffle server files
alfadur
parents: 14916
diff changeset
    22
    handlers,
15102
80ff12edf5e6 handle response from IO result handler
alfadur
parents: 15098
diff changeset
    23
    handlers::{IoResult, IoTask},
15103
823052e66611 check for account existence before asking passwords
alfadur
parents: 15102
diff changeset
    24
    protocol::{messages::HwServerMessage::Redirect, messages::*, ProtocolDecoder},
13666
09f4a30e50cc Rust 2018 conversion
alfadur
parents: 13524
diff changeset
    25
    utils,
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    26
};
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
    27
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
    28
#[cfg(feature = "official-server")]
15098
9397e07b3086 use blocking recv in IO thread
alfadur
parents: 15075
diff changeset
    29
use super::io::{IoThread, RequestId};
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
    30
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    31
#[cfg(feature = "tls-connections")]
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    32
use openssl::{
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
    33
    error::ErrorStack,
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    34
    ssl::{
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
    35
        HandshakeError, MidHandshakeSslStream, Ssl, SslContext, SslContextBuilder, SslFiletype,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
    36
        SslMethod, SslOptions, SslStream, SslStreamBuilder, SslVerifyMode,
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    37
    },
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    38
};
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
    39
use std::time::Duration;
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    40
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    41
const MAX_BYTES_PER_READ: usize = 2048;
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
    42
const SEND_PING_TIMEOUT: Duration = Duration::from_secs(30);
14807
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
    43
const DROP_CLIENT_TIMEOUT: Duration = Duration::from_secs(30);
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
    44
const PING_PROBES_COUNT: u8 = 2;
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    45
13415
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
    46
#[derive(Hash, Eq, PartialEq, Copy, Clone)]
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    47
pub enum NetworkClientState {
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    48
    Idle,
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    49
    NeedsWrite,
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    50
    NeedsRead,
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    51
    Closed,
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
    52
    #[cfg(feature = "tls-connections")]
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
    53
    Connected,
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    54
}
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    55
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
    56
type NetworkResult<T> = io::Result<(T, NetworkClientState)>;
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    57
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    58
pub enum ClientSocket {
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
    59
    Plain(TcpStream),
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
    60
    #[cfg(feature = "tls-connections")]
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    61
    SslHandshake(Option<MidHandshakeSslStream<TcpStream>>),
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
    62
    #[cfg(feature = "tls-connections")]
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
    63
    SslStream(SslStream<TcpStream>),
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    64
}
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    65
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    66
impl ClientSocket {
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    67
    fn inner(&self) -> &TcpStream {
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    68
        match self {
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    69
            ClientSocket::Plain(stream) => stream,
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
    70
            #[cfg(feature = "tls-connections")]
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    71
            ClientSocket::SslHandshake(Some(builder)) => builder.get_ref(),
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
    72
            #[cfg(feature = "tls-connections")]
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    73
            ClientSocket::SslHandshake(None) => unreachable!(),
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
    74
            #[cfg(feature = "tls-connections")]
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
    75
            ClientSocket::SslStream(ssl_stream) => ssl_stream.get_ref(),
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    76
        }
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    77
    }
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    78
}
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    79
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    80
pub struct NetworkClient {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    81
    id: ClientId,
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
    82
    socket: ClientSocket,
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    83
    peer_addr: SocketAddr,
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    84
    decoder: ProtocolDecoder,
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
    85
    buf_out: netbuf::Buf,
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
    86
    timeout: timer::Timeout,
15174
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
    87
    pending_close: bool,
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    88
}
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    89
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    90
impl NetworkClient {
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
    91
    pub fn new(
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
    92
        id: ClientId,
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
    93
        socket: ClientSocket,
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
    94
        peer_addr: SocketAddr,
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
    95
        timeout: timer::Timeout,
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
    96
    ) -> NetworkClient {
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
    97
        NetworkClient {
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
    98
            id,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
    99
            socket,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   100
            peer_addr,
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   101
            decoder: ProtocolDecoder::new(),
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   102
            buf_out: netbuf::Buf::new(),
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   103
            timeout,
15174
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   104
            pending_close: false,
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   105
        }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   106
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   107
13802
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   108
    #[cfg(feature = "tls-connections")]
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   109
    fn handshake_impl(
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   110
        &mut self,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   111
        handshake: MidHandshakeSslStream<TcpStream>,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   112
    ) -> io::Result<NetworkClientState> {
13802
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   113
        match handshake.handshake() {
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   114
            Ok(stream) => {
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   115
                self.socket = ClientSocket::SslStream(stream);
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   116
                debug!(
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   117
                    "TLS handshake with {} ({}) completed",
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   118
                    self.id, self.peer_addr
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   119
                );
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   120
                Ok(NetworkClientState::Connected)
13802
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   121
            }
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   122
            Err(HandshakeError::WouldBlock(new_handshake)) => {
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   123
                self.socket = ClientSocket::SslHandshake(Some(new_handshake));
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   124
                Ok(NetworkClientState::Idle)
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   125
            }
13803
fea7c23d9c2c rescue the stream on handshake failure
alfadur
parents: 13802
diff changeset
   126
            Err(HandshakeError::Failure(new_handshake)) => {
fea7c23d9c2c rescue the stream on handshake failure
alfadur
parents: 13802
diff changeset
   127
                self.socket = ClientSocket::SslHandshake(Some(new_handshake));
13802
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   128
                debug!("TLS handshake with {} ({}) failed", self.id, self.peer_addr);
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   129
                Err(Error::new(ErrorKind::Other, "Connection failure"))
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   130
            }
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   131
            Err(HandshakeError::SetupFailure(_)) => unreachable!(),
13802
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   132
        }
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   133
    }
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   134
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   135
    fn read_impl<R: Read>(
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   136
        decoder: &mut ProtocolDecoder,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   137
        source: &mut R,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   138
        id: ClientId,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   139
        addr: &SocketAddr,
15075
e935b1ad23f3 normalize type names
alfadur
parents: 15074
diff changeset
   140
    ) -> NetworkResult<Vec<HwProtocolMessage>> {
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   141
        let mut bytes_read = 0;
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   142
        let result = loop {
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   143
            match decoder.read_from(source) {
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   144
                Ok(bytes) => {
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   145
                    debug!("Client {}: read {} bytes", id, bytes);
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   146
                    bytes_read += bytes;
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   147
                    if bytes == 0 {
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   148
                        let result = if bytes_read == 0 {
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   149
                            info!("EOF for client {} ({})", id, addr);
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   150
                            (Vec::new(), NetworkClientState::Closed)
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   151
                        } else {
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   152
                            (decoder.extract_messages(), NetworkClientState::NeedsRead)
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   153
                        };
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   154
                        break Ok(result);
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   155
                    } else if bytes_read >= MAX_BYTES_PER_READ {
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   156
                        break Ok((decoder.extract_messages(), NetworkClientState::NeedsRead));
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   157
                    }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   158
                }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   159
                Err(ref error) if error.kind() == ErrorKind::WouldBlock => {
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   160
                    let messages = if bytes_read == 0 {
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   161
                        Vec::new()
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   162
                    } else {
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   163
                        decoder.extract_messages()
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   164
                    };
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   165
                    break Ok((messages, NetworkClientState::Idle));
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   166
                }
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   167
                Err(error) => break Err(error),
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   168
            }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   169
        };
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   170
        result
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   171
    }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   172
15075
e935b1ad23f3 normalize type names
alfadur
parents: 15074
diff changeset
   173
    pub fn read(&mut self) -> NetworkResult<Vec<HwProtocolMessage>> {
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   174
        match self.socket {
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   175
            ClientSocket::Plain(ref mut stream) => {
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   176
                NetworkClient::read_impl(&mut self.decoder, stream, self.id, &self.peer_addr)
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   177
            }
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   178
            #[cfg(feature = "tls-connections")]
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   179
            ClientSocket::SslHandshake(ref mut handshake_opt) => {
13802
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   180
                let handshake = std::mem::replace(handshake_opt, None).unwrap();
24fe56d3c6a2 improve error handling for TLS handshake
alfadur
parents: 13799
diff changeset
   181
                Ok((Vec::new(), self.handshake_impl(handshake)?))
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   182
            }
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   183
            #[cfg(feature = "tls-connections")]
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   184
            ClientSocket::SslStream(ref mut stream) => {
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   185
                NetworkClient::read_impl(&mut self.decoder, stream, self.id, &self.peer_addr)
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   186
            }
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   187
        }
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   188
    }
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   189
15174
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   190
    fn write_impl<W: Write>(
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   191
        buf_out: &mut netbuf::Buf,
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   192
        destination: &mut W,
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   193
        close_on_empty: bool,
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   194
    ) -> NetworkResult<()> {
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   195
        let result = loop {
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   196
            match buf_out.write_to(destination) {
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   197
                Ok(bytes) if buf_out.is_empty() || bytes == 0 => {
15174
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   198
                    let status = if buf_out.is_empty() && close_on_empty {
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   199
                        NetworkClientState::Closed
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   200
                    } else {
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   201
                        NetworkClientState::Idle
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   202
                    };
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   203
                    break Ok(((), status));
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   204
                }
13415
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   205
                Ok(_) => (),
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   206
                Err(ref error)
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   207
                    if error.kind() == ErrorKind::Interrupted
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   208
                        || error.kind() == ErrorKind::WouldBlock =>
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   209
                {
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   210
                    break Ok(((), NetworkClientState::NeedsWrite));
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   211
                }
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   212
                Err(error) => break Err(error),
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   213
            }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   214
        };
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   215
        result
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   216
    }
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   217
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   218
    pub fn write(&mut self) -> NetworkResult<()> {
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   219
        let result = match self.socket {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   220
            ClientSocket::Plain(ref mut stream) => {
15174
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   221
                NetworkClient::write_impl(&mut self.buf_out, stream, self.pending_close)
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   222
            }
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   223
            #[cfg(feature = "tls-connections")]
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   224
            ClientSocket::SslHandshake(ref mut handshake_opt) => {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   225
                let handshake = std::mem::replace(handshake_opt, None).unwrap();
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   226
                Ok(((), self.handshake_impl(handshake)?))
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   227
            }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   228
            #[cfg(feature = "tls-connections")]
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   229
            ClientSocket::SslStream(ref mut stream) => {
15174
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   230
                NetworkClient::write_impl(&mut self.buf_out, stream, self.pending_close)
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   231
            }
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   232
        };
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   233
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   234
        self.socket.inner().flush()?;
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   235
        result
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   236
    }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   237
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   238
    pub fn send_raw_msg(&mut self, msg: &[u8]) {
13524
5359ff75da3a indulge clippy
alfadur
parents: 13478
diff changeset
   239
        self.buf_out.write_all(msg).unwrap();
13119
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
13524
5359ff75da3a indulge clippy
alfadur
parents: 13478
diff changeset
   242
    pub fn send_string(&mut self, msg: &str) {
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   243
        self.send_raw_msg(&msg.as_bytes());
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   244
    }
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   245
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   246
    pub fn replace_timeout(&mut self, timeout: timer::Timeout) -> timer::Timeout {
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   247
        replace(&mut self.timeout, timeout)
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   248
    }
15174
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   249
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   250
    pub fn has_pending_sends(&self) -> bool {
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   251
        !self.buf_out.is_empty()
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   252
    }
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   253
}
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   254
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   255
#[cfg(feature = "tls-connections")]
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   256
struct ServerSsl {
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   257
    listener: TcpListener,
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   258
    context: SslContext,
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   259
}
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   260
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   261
#[cfg(feature = "official-server")]
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   262
pub struct IoLayer {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   263
    next_request_id: RequestId,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   264
    request_queue: Vec<(RequestId, ClientId)>,
15098
9397e07b3086 use blocking recv in IO thread
alfadur
parents: 15075
diff changeset
   265
    io_thread: IoThread,
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   266
}
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   267
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   268
#[cfg(feature = "official-server")]
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   269
impl IoLayer {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   270
    fn new() -> Self {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   271
        Self {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   272
            next_request_id: 0,
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   273
            request_queue: vec![],
15098
9397e07b3086 use blocking recv in IO thread
alfadur
parents: 15075
diff changeset
   274
            io_thread: IoThread::new(),
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   275
        }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   276
    }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   277
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   278
    fn send(&mut self, client_id: ClientId, task: IoTask) {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   279
        let request_id = self.next_request_id;
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   280
        self.next_request_id += 1;
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   281
        self.request_queue.push((request_id, client_id));
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   282
        self.io_thread.send(request_id, task);
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   283
    }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   284
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   285
    fn try_recv(&mut self) -> Option<(ClientId, IoResult)> {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   286
        let (request_id, result) = self.io_thread.try_recv()?;
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   287
        if let Some(index) = self
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   288
            .request_queue
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   289
            .iter()
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   290
            .position(|(id, _)| *id == request_id)
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   291
        {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   292
            let (_, client_id) = self.request_queue.swap_remove(index);
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   293
            Some((client_id, result))
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   294
        } else {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   295
            None
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   296
        }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   297
    }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   298
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   299
    fn cancel(&mut self, client_id: ClientId) {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   300
        let mut index = 0;
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   301
        while index < self.request_queue.len() {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   302
            if self.request_queue[index].1 == client_id {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   303
                self.request_queue.swap_remove(index);
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   304
            } else {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   305
                index += 1;
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   306
            }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   307
        }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   308
    }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   309
}
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   310
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   311
enum TimeoutEvent {
14807
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   312
    SendPing { probes_count: u8 },
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   313
    DropClient,
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   314
}
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   315
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   316
struct TimerData(TimeoutEvent, ClientId);
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   317
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   318
pub struct NetworkLayer {
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   319
    listener: TcpListener,
15075
e935b1ad23f3 normalize type names
alfadur
parents: 15074
diff changeset
   320
    server: HwServer,
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   321
    clients: Slab<NetworkClient>,
13415
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   322
    pending: HashSet<(ClientId, NetworkClientState)>,
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   323
    pending_cache: Vec<(ClientId, NetworkClientState)>,
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   324
    #[cfg(feature = "tls-connections")]
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   325
    ssl: ServerSsl,
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   326
    #[cfg(feature = "official-server")]
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   327
    io: IoLayer,
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   328
    timer: timer::Timer<TimerData>,
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   329
}
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   330
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   331
fn register_read<E: Evented>(poll: &Poll, evented: &E, token: mio::Token) -> io::Result<()> {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   332
    poll.register(evented, token, Ready::readable(), PollOpt::edge())
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   333
}
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   334
14807
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   335
fn create_ping_timeout(
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   336
    timer: &mut timer::Timer<TimerData>,
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   337
    probes_count: u8,
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   338
    client_id: ClientId,
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   339
) -> timer::Timeout {
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   340
    timer.set_timeout(
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   341
        SEND_PING_TIMEOUT,
14807
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   342
        TimerData(TimeoutEvent::SendPing { probes_count }, client_id),
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   343
    )
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   344
}
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   345
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   346
fn create_drop_timeout(timer: &mut timer::Timer<TimerData>, client_id: ClientId) -> timer::Timeout {
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   347
    timer.set_timeout(
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   348
        DROP_CLIENT_TIMEOUT,
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   349
        TimerData(TimeoutEvent::DropClient, client_id),
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   350
    )
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   351
}
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   352
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   353
impl NetworkLayer {
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   354
    pub fn register(&self, poll: &Poll) -> io::Result<()> {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   355
        register_read(poll, &self.listener, utils::SERVER_TOKEN)?;
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   356
        #[cfg(feature = "tls-connections")]
14835
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   357
        register_read(poll, &self.ssl.listener, utils::SECURE_SERVER_TOKEN)?;
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   358
        register_read(poll, &self.timer, utils::TIMER_TOKEN)?;
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   359
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   360
        #[cfg(feature = "official-server")]
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   361
        self.io.io_thread.register_rx(poll, utils::IO_TOKEN)?;
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   362
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   363
        Ok(())
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   364
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   365
15175
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   366
    fn deregister_client(&mut self, poll: &Poll, id: ClientId, is_error: bool) {
15174
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   367
        if let Some(ref mut client) = self.clients.get_mut(id) {
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   368
            poll.deregister(client.socket.inner())
13524
5359ff75da3a indulge clippy
alfadur
parents: 13478
diff changeset
   369
                .expect("could not deregister socket");
15175
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   370
            if client.has_pending_sends() && !is_error {
15174
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   371
                info!(
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   372
                    "client {} ({}) pending removal",
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   373
                    client.id, client.peer_addr
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   374
                );
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   375
                client.pending_close = true;
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   376
                poll.register(
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   377
                    client.socket.inner(),
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   378
                    Token(id),
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   379
                    Ready::writable(),
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   380
                    PollOpt::edge(),
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   381
                )
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   382
                .unwrap_or_else(|_| {
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   383
                    self.clients.remove(id);
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   384
                });
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   385
            } else {
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   386
                info!("client {} ({}) removed", client.id, client.peer_addr);
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   387
                self.clients.remove(id);
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   388
            }
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   389
            #[cfg(feature = "official-server")]
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   390
            self.io.cancel(id);
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   391
        }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   392
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   393
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   394
    fn register_client(
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   395
        &mut self,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   396
        poll: &Poll,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   397
        client_socket: ClientSocket,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   398
        addr: SocketAddr,
14916
8750530bf7e7 avoid crashing server in the event loop
alfadur
parents: 14907
diff changeset
   399
    ) -> io::Result<ClientId> {
14693
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14673
diff changeset
   400
        let entry = self.clients.vacant_entry();
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14673
diff changeset
   401
        let client_id = entry.key();
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14673
diff changeset
   402
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   403
        poll.register(
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   404
            client_socket.inner(),
14693
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14673
diff changeset
   405
            Token(client_id),
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   406
            Ready::readable() | Ready::writable(),
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   407
            PollOpt::edge(),
14916
8750530bf7e7 avoid crashing server in the event loop
alfadur
parents: 14907
diff changeset
   408
        )?;
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   409
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   410
        let client = NetworkClient::new(
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   411
            client_id,
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   412
            client_socket,
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   413
            addr,
14807
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   414
            create_ping_timeout(&mut self.timer, PING_PROBES_COUNT - 1, client_id),
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   415
        );
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   416
        info!("client {} ({}) added", client.id, client.peer_addr);
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   417
        entry.insert(client);
14693
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14673
diff changeset
   418
14916
8750530bf7e7 avoid crashing server in the event loop
alfadur
parents: 14907
diff changeset
   419
        Ok(client_id)
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   420
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   421
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   422
    fn handle_response(&mut self, mut response: handlers::Response, poll: &Poll) {
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   423
        if response.is_empty() {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   424
            return;
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   425
        }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   426
14672
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14671
diff changeset
   427
        debug!("{} pending server messages", response.len());
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14671
diff changeset
   428
        let output = response.extract_messages(&mut self.server);
6e6632068a33 Server action refactoring part 3 of N
alfadur <mail@none>
parents: 14671
diff changeset
   429
        for (clients, message) in output {
13419
81e0ed105f5d implementation of team related messages
alfadur
parents: 13416
diff changeset
   430
            debug!("Message {:?} to {:?}", message, clients);
81e0ed105f5d implementation of team related messages
alfadur
parents: 13416
diff changeset
   431
            let msg_string = message.to_raw_protocol();
81e0ed105f5d implementation of team related messages
alfadur
parents: 13416
diff changeset
   432
            for client_id in clients {
81e0ed105f5d implementation of team related messages
alfadur
parents: 13416
diff changeset
   433
                if let Some(client) = self.clients.get_mut(client_id) {
81e0ed105f5d implementation of team related messages
alfadur
parents: 13416
diff changeset
   434
                    client.send_string(&msg_string);
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   435
                    self.pending
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   436
                        .insert((client_id, NetworkClientState::NeedsWrite));
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   437
                }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   438
            }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   439
        }
14696
8a45c90f4580 fix client removal
alfadur
parents: 14693
diff changeset
   440
8a45c90f4580 fix client removal
alfadur
parents: 14693
diff changeset
   441
        for client_id in response.extract_removed_clients() {
15175
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   442
            self.deregister_client(poll, client_id, false);
14696
8a45c90f4580 fix client removal
alfadur
parents: 14693
diff changeset
   443
        }
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   444
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   445
        #[cfg(feature = "official-server")]
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   446
        {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   447
            let client_id = response.client_id();
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   448
            for task in response.extract_io_tasks() {
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   449
                self.io.send(client_id, task);
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   450
            }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   451
        }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   452
    }
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   453
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   454
    pub fn handle_timeout(&mut self, poll: &Poll) -> io::Result<()> {
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   455
        while let Some(TimerData(event, client_id)) = self.timer.poll() {
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   456
            match event {
14807
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   457
                TimeoutEvent::SendPing { probes_count } => {
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   458
                    if let Some(ref mut client) = self.clients.get_mut(client_id) {
15075
e935b1ad23f3 normalize type names
alfadur
parents: 15074
diff changeset
   459
                        client.send_string(&HwServerMessage::Ping.to_raw_protocol());
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   460
                        client.write()?;
14807
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   461
                        let timeout = if probes_count != 0 {
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   462
                            create_ping_timeout(&mut self.timer, probes_count - 1, client_id)
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   463
                        } else {
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   464
                            create_drop_timeout(&mut self.timer, client_id)
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   465
                        };
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   466
                        client.replace_timeout(timeout);
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   467
                    }
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   468
                }
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   469
                TimeoutEvent::DropClient => {
15175
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   470
                    if let Some(ref mut client) = self.clients.get_mut(client_id) {
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   471
                        client.send_string(
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   472
                            &HwServerMessage::Bye("Ping timeout".to_string()).to_raw_protocol(),
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   473
                        );
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   474
                        client.write();
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   475
                    }
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   476
                    self.operation_failed(
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   477
                        poll,
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   478
                        client_id,
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   479
                        &ErrorKind::TimedOut.into(),
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   480
                        "No ping response",
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   481
                    )?;
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   482
                }
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   483
            }
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   484
        }
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   485
        Ok(())
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   486
    }
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   487
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   488
    #[cfg(feature = "official-server")]
15102
80ff12edf5e6 handle response from IO result handler
alfadur
parents: 15098
diff changeset
   489
    pub fn handle_io_result(&mut self, poll: &Poll) -> io::Result<()> {
80ff12edf5e6 handle response from IO result handler
alfadur
parents: 15098
diff changeset
   490
        while let Some((client_id, result)) = self.io.try_recv() {
80ff12edf5e6 handle response from IO result handler
alfadur
parents: 15098
diff changeset
   491
            debug!("Handling io result {:?} for client {}", result, client_id);
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   492
            let mut response = handlers::Response::new(client_id);
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   493
            handlers::handle_io_result(&mut self.server, client_id, &mut response, result);
15102
80ff12edf5e6 handle response from IO result handler
alfadur
parents: 15098
diff changeset
   494
            self.handle_response(response, poll);
14779
f43ab2bd76ae add a thread for internal server IO and implement account checking with it
alfadur
parents: 14697
diff changeset
   495
        }
14916
8750530bf7e7 avoid crashing server in the event loop
alfadur
parents: 14907
diff changeset
   496
        Ok(())
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   497
    }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   498
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   499
    fn create_client_socket(&self, socket: TcpStream) -> io::Result<ClientSocket> {
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   500
        Ok(ClientSocket::Plain(socket))
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   501
    }
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   502
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   503
    #[cfg(feature = "tls-connections")]
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   504
    fn create_client_secure_socket(&self, socket: TcpStream) -> io::Result<ClientSocket> {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   505
        let ssl = Ssl::new(&self.ssl.context).unwrap();
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   506
        let mut builder = SslStreamBuilder::new(ssl, socket);
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   507
        builder.set_accept_state();
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   508
        match builder.handshake() {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   509
            Ok(stream) => Ok(ClientSocket::SslStream(stream)),
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   510
            Err(HandshakeError::WouldBlock(stream)) => Ok(ClientSocket::SslHandshake(Some(stream))),
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   511
            Err(e) => {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   512
                debug!("OpenSSL handshake failed: {}", e);
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   513
                Err(Error::new(ErrorKind::Other, "Connection failure"))
13799
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   514
            }
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   515
        }
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   516
    }
c8fd12db6215 Add TLS support
alfadur
parents: 13666
diff changeset
   517
14835
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   518
    fn init_client(&mut self, poll: &Poll, client_id: ClientId) {
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   519
        let mut response = handlers::Response::new(client_id);
14847
eef1f76150fe don't redirect to self
alfadur
parents: 14835
diff changeset
   520
eef1f76150fe don't redirect to self
alfadur
parents: 14835
diff changeset
   521
        if let ClientSocket::Plain(_) = self.clients[client_id].socket {
eef1f76150fe don't redirect to self
alfadur
parents: 14835
diff changeset
   522
            #[cfg(feature = "tls-connections")]
eef1f76150fe don't redirect to self
alfadur
parents: 14835
diff changeset
   523
            response.add(Redirect(self.ssl.listener.local_addr().unwrap().port()).send_self())
eef1f76150fe don't redirect to self
alfadur
parents: 14835
diff changeset
   524
        }
14835
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   525
15176
f6115638aa92 enable local admins for non-official servers
alfadur
parents: 15175
diff changeset
   526
        handlers::handle_client_accept(
f6115638aa92 enable local admins for non-official servers
alfadur
parents: 15175
diff changeset
   527
            &mut self.server,
f6115638aa92 enable local admins for non-official servers
alfadur
parents: 15175
diff changeset
   528
            client_id,
f6115638aa92 enable local admins for non-official servers
alfadur
parents: 15175
diff changeset
   529
            &mut response,
f6115638aa92 enable local admins for non-official servers
alfadur
parents: 15175
diff changeset
   530
            self.clients[client_id].peer_addr.ip().is_loopback(),
f6115638aa92 enable local admins for non-official servers
alfadur
parents: 15175
diff changeset
   531
        );
14835
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   532
        self.handle_response(response, poll);
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   533
    }
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   534
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   535
    pub fn accept_client(&mut self, poll: &Poll, server_token: mio::Token) -> io::Result<()> {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   536
        match server_token {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   537
            utils::SERVER_TOKEN => {
14870
ce98c37826a7 fix accepting on wrong server socket
alfadur
parents: 14847
diff changeset
   538
                let (client_socket, addr) = self.listener.accept()?;
ce98c37826a7 fix accepting on wrong server socket
alfadur
parents: 14847
diff changeset
   539
                info!("Connected(plaintext): {}", addr);
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   540
                let client_id =
14916
8750530bf7e7 avoid crashing server in the event loop
alfadur
parents: 14907
diff changeset
   541
                    self.register_client(poll, self.create_client_socket(client_socket)?, addr)?;
14835
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   542
                self.init_client(poll, client_id);
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   543
            }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   544
            #[cfg(feature = "tls-connections")]
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   545
            utils::SECURE_SERVER_TOKEN => {
14870
ce98c37826a7 fix accepting on wrong server socket
alfadur
parents: 14847
diff changeset
   546
                let (client_socket, addr) = self.ssl.listener.accept()?;
ce98c37826a7 fix accepting on wrong server socket
alfadur
parents: 14847
diff changeset
   547
                info!("Connected(TLS): {}", addr);
14916
8750530bf7e7 avoid crashing server in the event loop
alfadur
parents: 14907
diff changeset
   548
                self.register_client(poll, self.create_client_secure_socket(client_socket)?, addr)?;
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   549
            }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   550
            _ => unreachable!(),
14693
6a2e13e36b7f add server anteroom
alfadur <mail@none>
parents: 14673
diff changeset
   551
        }
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   552
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   553
        Ok(())
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   554
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   555
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   556
    fn operation_failed(
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   557
        &mut self,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   558
        poll: &Poll,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   559
        client_id: ClientId,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   560
        error: &Error,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   561
        msg: &str,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   562
    ) -> io::Result<()> {
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   563
        let addr = if let Some(ref mut client) = self.clients.get_mut(client_id) {
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   564
            client.peer_addr
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   565
        } else {
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   566
            SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0)
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   567
        };
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   568
        debug!("{}({}): {}", msg, addr, error);
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   569
        self.client_error(poll, client_id)
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   570
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   571
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   572
    pub fn client_readable(&mut self, poll: &Poll, client_id: ClientId) -> io::Result<()> {
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   573
        let messages = if let Some(ref mut client) = self.clients.get_mut(client_id) {
14807
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   574
            let timeout = client.replace_timeout(create_ping_timeout(
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   575
                &mut self.timer,
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   576
                PING_PROBES_COUNT - 1,
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   577
                client_id,
b2beb784e4b5 add support for multiple ping probes
alfadur
parents: 14803
diff changeset
   578
            ));
14803
92225a708bda add client timeouts
alfadur
parents: 14796
diff changeset
   579
            self.timer.cancel_timeout(&timeout);
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   580
            client.read()
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   581
        } else {
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   582
            warn!("invalid readable client: {}", client_id);
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   583
            Ok((Vec::new(), NetworkClientState::Idle))
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   584
        };
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   585
14671
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14457
diff changeset
   586
        let mut response = handlers::Response::new(client_id);
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14457
diff changeset
   587
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   588
        match messages {
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   589
            Ok((messages, state)) => {
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   590
                for message in messages {
14671
455865ccd36c Server action refactoring part 2 of N
alfadur <mail@none>
parents: 14457
diff changeset
   591
                    debug!("Handling message {:?} for client {}", message, client_id);
14796
f5d43f007970 start by actually handling client messages
alfadur
parents: 14795
diff changeset
   592
                    handlers::handle(&mut self.server, client_id, &mut response, message);
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   593
                }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   594
                match state {
13415
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   595
                    NetworkClientState::NeedsRead => {
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   596
                        self.pending.insert((client_id, state));
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   597
                    }
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   598
                    NetworkClientState::Closed => self.client_error(&poll, client_id)?,
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   599
                    #[cfg(feature = "tls-connections")]
14835
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   600
                    NetworkClientState::Connected => self.init_client(poll, client_id),
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   601
                    _ => {}
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   602
                };
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   603
            }
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   604
            Err(e) => self.operation_failed(
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   605
                poll,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   606
                client_id,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   607
                &e,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   608
                "Error while reading from client socket",
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   609
            )?,
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   610
        }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   611
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   612
        self.handle_response(response, poll);
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   613
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   614
        Ok(())
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   615
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   616
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   617
    pub fn client_writable(&mut self, poll: &Poll, client_id: ClientId) -> io::Result<()> {
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   618
        let result = if let Some(ref mut client) = self.clients.get_mut(client_id) {
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   619
            client.write()
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   620
        } else {
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   621
            warn!("invalid writable client: {}", client_id);
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   622
            Ok(((), NetworkClientState::Idle))
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   623
        };
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   624
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   625
        match result {
13415
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   626
            Ok(((), state)) if state == NetworkClientState::NeedsWrite => {
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   627
                self.pending.insert((client_id, state));
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   628
            }
15174
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   629
            Ok(((), state)) if state == NetworkClientState::Closed => {
15175
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   630
                self.deregister_client(poll, client_id, false);
15174
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   631
            }
e705ac360785 pin removed clients until the output buffer is flushed
alfadur
parents: 15173
diff changeset
   632
            Ok(_) => (),
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   633
            Err(e) => {
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   634
                self.operation_failed(poll, client_id, &e, "Error while writing to client socket")?
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   635
            }
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   636
        }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   637
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   638
        Ok(())
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   639
    }
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   640
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   641
    pub fn client_error(&mut self, poll: &Poll, client_id: ClientId) -> io::Result<()> {
15175
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   642
        let pending_close = self.clients[client_id].pending_close;
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   643
        self.deregister_client(poll, client_id, true);
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   644
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   645
        if !pending_close {
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   646
            let mut response = handlers::Response::new(client_id);
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   647
            handlers::handle_client_loss(&mut self.server, client_id, &mut response);
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   648
            self.handle_response(response, poll);
f1c2289d40bd break error loop in client removal
alfadur
parents: 15174
diff changeset
   649
        }
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   650
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   651
        Ok(())
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   652
    }
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   653
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   654
    pub fn has_pending_operations(&self) -> bool {
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   655
        !self.pending.is_empty()
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   656
    }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   657
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   658
    pub fn on_idle(&mut self, poll: &Poll) -> io::Result<()> {
13415
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   659
        if self.has_pending_operations() {
13478
d79795acaa73 Mostly implement voting
alfadur
parents: 13419
diff changeset
   660
            let mut cache = replace(&mut self.pending_cache, Vec::new());
13415
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   661
            cache.extend(self.pending.drain());
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   662
            for (id, state) in cache.drain(..) {
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   663
                match state {
14457
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   664
                    NetworkClientState::NeedsRead => self.client_readable(poll, id)?,
98ef2913ec73 Apply rustfmt to all files
unc0rr
parents: 14415
diff changeset
   665
                    NetworkClientState::NeedsWrite => self.client_writable(poll, id)?,
13415
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   666
                    _ => {}
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   667
                }
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   668
            }
13415
0eedc17055a0 rework of prior
alfadur
parents: 13414
diff changeset
   669
            swap(&mut cache, &mut self.pending_cache);
13414
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   670
        }
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   671
        Ok(())
28b314ad566d handle edge polling properly
alfadur
parents: 13119
diff changeset
   672
    }
13119
1e39b8749072 separated the server logic from all the async io mess.
alfadur
parents:
diff changeset
   673
}
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   674
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   675
pub struct NetworkLayerBuilder {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   676
    listener: Option<TcpListener>,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   677
    secure_listener: Option<TcpListener>,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   678
    clients_capacity: usize,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   679
    rooms_capacity: usize,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   680
}
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   681
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   682
impl Default for NetworkLayerBuilder {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   683
    fn default() -> Self {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   684
        Self {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   685
            clients_capacity: 1024,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   686
            rooms_capacity: 512,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   687
            listener: None,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   688
            secure_listener: None,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   689
        }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   690
    }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   691
}
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   692
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   693
impl NetworkLayerBuilder {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   694
    pub fn with_listener(self, listener: TcpListener) -> Self {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   695
        Self {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   696
            listener: Some(listener),
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   697
            ..self
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   698
        }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   699
    }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   700
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   701
    pub fn with_secure_listener(self, listener: TcpListener) -> Self {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   702
        Self {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   703
            secure_listener: Some(listener),
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   704
            ..self
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   705
        }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   706
    }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   707
14835
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   708
    #[cfg(feature = "tls-connections")]
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   709
    fn create_ssl_context(listener: TcpListener) -> ServerSsl {
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   710
        let mut builder = SslContextBuilder::new(SslMethod::tls()).unwrap();
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   711
        builder.set_verify(SslVerifyMode::NONE);
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   712
        builder.set_read_ahead(true);
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   713
        builder
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   714
            .set_certificate_file("ssl/cert.pem", SslFiletype::PEM)
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   715
            .expect("Cannot find certificate file");
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   716
        builder
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   717
            .set_private_key_file("ssl/key.pem", SslFiletype::PEM)
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   718
            .expect("Cannot find private key file");
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   719
        builder.set_options(SslOptions::NO_COMPRESSION);
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   720
        builder.set_cipher_list("DEFAULT:!LOW:!RC4:!EXP").unwrap();
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   721
        ServerSsl {
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   722
            listener,
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   723
            context: builder.build(),
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   724
        }
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   725
    }
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   726
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   727
    pub fn build(self) -> NetworkLayer {
15075
e935b1ad23f3 normalize type names
alfadur
parents: 15074
diff changeset
   728
        let server = HwServer::new(self.clients_capacity, self.rooms_capacity);
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   729
        let clients = Slab::with_capacity(self.clients_capacity);
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   730
        let pending = HashSet::with_capacity(2 * self.clients_capacity);
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   731
        let pending_cache = Vec::with_capacity(2 * self.clients_capacity);
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   732
        let timer = timer::Builder::default().build();
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   733
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   734
        NetworkLayer {
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   735
            listener: self.listener.expect("No listener provided"),
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   736
            server,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   737
            clients,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   738
            pending,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   739
            pending_cache,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   740
            #[cfg(feature = "tls-connections")]
14835
57ed3981db20 add redirect message
alfadur
parents: 14830
diff changeset
   741
            ssl: Self::create_ssl_context(
14830
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   742
                self.secure_listener.expect("No secure listener provided"),
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   743
            ),
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   744
            #[cfg(feature = "official-server")]
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   745
            io: IoLayer::new(),
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   746
            timer,
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   747
        }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   748
    }
8ddb5842fe0b allow running plaintext and tls servers in parallel
alfadur
parents: 14807
diff changeset
   749
}