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