author | alfadur <mail@none> |
Mon, 04 Feb 2019 20:25:35 +0300 | |
changeset 14678 | 08a8605bafaf |
parent 14677 | 6e6632068a33 |
child 14698 | 6a2e13e36b7f |
permissions | -rw-r--r-- |
13124 | 1 |
extern crate slab; |
2 |
||
13419 | 3 |
use std::{ |
13420 | 4 |
collections::HashSet, |
14462 | 5 |
io, |
6 |
io::{Error, ErrorKind, Read, Write}, |
|
7 |
mem::{replace, swap}, |
|
8 |
net::{IpAddr, Ipv4Addr, SocketAddr}, |
|
13419 | 9 |
}; |
10 |
||
14462 | 11 |
use log::*; |
13419 | 12 |
use mio::{ |
14462 | 13 |
net::{TcpListener, TcpStream}, |
14 |
Poll, PollOpt, Ready, Token, |
|
13419 | 15 |
}; |
16 |
use netbuf; |
|
13124 | 17 |
use slab::Slab; |
18 |
||
14676
455865ccd36c
Server action refactoring part 2 of N
alfadur <mail@none>
parents:
14462
diff
changeset
|
19 |
use super::{core::HWServer, coretypes::ClientId, handlers, io::FileServerIO}; |
13671 | 20 |
use crate::{ |
14462 | 21 |
protocol::{messages::*, ProtocolDecoder}, |
13671 | 22 |
utils, |
13419 | 23 |
}; |
13804 | 24 |
#[cfg(feature = "tls-connections")] |
25 |
use openssl::{ |
|
14462 | 26 |
error::ErrorStack, |
13804 | 27 |
ssl::{ |
14462 | 28 |
HandshakeError, MidHandshakeSslStream, Ssl, SslContext, SslContextBuilder, SslFiletype, |
29 |
SslMethod, SslOptions, SslStream, SslStreamBuilder, SslVerifyMode, |
|
13804 | 30 |
}, |
31 |
}; |
|
13419 | 32 |
|
33 |
const MAX_BYTES_PER_READ: usize = 2048; |
|
13124 | 34 |
|
13420 | 35 |
#[derive(Hash, Eq, PartialEq, Copy, Clone)] |
13419 | 36 |
pub enum NetworkClientState { |
37 |
Idle, |
|
38 |
NeedsWrite, |
|
39 |
NeedsRead, |
|
40 |
Closed, |
|
41 |
} |
|
42 |
||
43 |
type NetworkResult<T> = io::Result<(T, NetworkClientState)>; |
|
13124 | 44 |
|
13804 | 45 |
#[cfg(not(feature = "tls-connections"))] |
46 |
pub enum ClientSocket { |
|
14462 | 47 |
Plain(TcpStream), |
13804 | 48 |
} |
49 |
||
50 |
#[cfg(feature = "tls-connections")] |
|
51 |
pub enum ClientSocket { |
|
52 |
SslHandshake(Option<MidHandshakeSslStream<TcpStream>>), |
|
14462 | 53 |
SslStream(SslStream<TcpStream>), |
13804 | 54 |
} |
55 |
||
56 |
impl ClientSocket { |
|
57 |
fn inner(&self) -> &TcpStream { |
|
58 |
#[cfg(not(feature = "tls-connections"))] |
|
59 |
match self { |
|
60 |
ClientSocket::Plain(stream) => stream, |
|
61 |
} |
|
62 |
||
63 |
#[cfg(feature = "tls-connections")] |
|
64 |
match self { |
|
65 |
ClientSocket::SslHandshake(Some(builder)) => builder.get_ref(), |
|
66 |
ClientSocket::SslHandshake(None) => unreachable!(), |
|
14462 | 67 |
ClientSocket::SslStream(ssl_stream) => ssl_stream.get_ref(), |
13804 | 68 |
} |
69 |
} |
|
70 |
} |
|
71 |
||
13124 | 72 |
pub struct NetworkClient { |
73 |
id: ClientId, |
|
13804 | 74 |
socket: ClientSocket, |
13124 | 75 |
peer_addr: SocketAddr, |
76 |
decoder: ProtocolDecoder, |
|
14462 | 77 |
buf_out: netbuf::Buf, |
13124 | 78 |
} |
79 |
||
80 |
impl NetworkClient { |
|
13804 | 81 |
pub fn new(id: ClientId, socket: ClientSocket, peer_addr: SocketAddr) -> NetworkClient { |
13124 | 82 |
NetworkClient { |
14462 | 83 |
id, |
84 |
socket, |
|
85 |
peer_addr, |
|
13124 | 86 |
decoder: ProtocolDecoder::new(), |
14462 | 87 |
buf_out: netbuf::Buf::new(), |
13124 | 88 |
} |
89 |
} |
|
90 |
||
13807 | 91 |
#[cfg(feature = "tls-connections")] |
14462 | 92 |
fn handshake_impl( |
93 |
&mut self, |
|
94 |
handshake: MidHandshakeSslStream<TcpStream>, |
|
95 |
) -> io::Result<NetworkClientState> { |
|
13807 | 96 |
match handshake.handshake() { |
97 |
Ok(stream) => { |
|
98 |
self.socket = ClientSocket::SslStream(stream); |
|
14462 | 99 |
debug!( |
100 |
"TLS handshake with {} ({}) completed", |
|
101 |
self.id, self.peer_addr |
|
102 |
); |
|
13807 | 103 |
Ok(NetworkClientState::Idle) |
104 |
} |
|
105 |
Err(HandshakeError::WouldBlock(new_handshake)) => { |
|
106 |
self.socket = ClientSocket::SslHandshake(Some(new_handshake)); |
|
107 |
Ok(NetworkClientState::Idle) |
|
108 |
} |
|
13808 | 109 |
Err(HandshakeError::Failure(new_handshake)) => { |
110 |
self.socket = ClientSocket::SslHandshake(Some(new_handshake)); |
|
13807 | 111 |
debug!("TLS handshake with {} ({}) failed", self.id, self.peer_addr); |
112 |
Err(Error::new(ErrorKind::Other, "Connection failure")) |
|
113 |
} |
|
14462 | 114 |
Err(HandshakeError::SetupFailure(_)) => unreachable!(), |
13807 | 115 |
} |
116 |
} |
|
117 |
||
14462 | 118 |
fn read_impl<R: Read>( |
119 |
decoder: &mut ProtocolDecoder, |
|
120 |
source: &mut R, |
|
121 |
id: ClientId, |
|
122 |
addr: &SocketAddr, |
|
123 |
) -> NetworkResult<Vec<HWProtocolMessage>> { |
|
13419 | 124 |
let mut bytes_read = 0; |
125 |
let result = loop { |
|
13804 | 126 |
match decoder.read_from(source) { |
13419 | 127 |
Ok(bytes) => { |
13804 | 128 |
debug!("Client {}: read {} bytes", id, bytes); |
13419 | 129 |
bytes_read += bytes; |
130 |
if bytes == 0 { |
|
131 |
let result = if bytes_read == 0 { |
|
13804 | 132 |
info!("EOF for client {} ({})", id, addr); |
13419 | 133 |
(Vec::new(), NetworkClientState::Closed) |
134 |
} else { |
|
13804 | 135 |
(decoder.extract_messages(), NetworkClientState::NeedsRead) |
13419 | 136 |
}; |
137 |
break Ok(result); |
|
14462 | 138 |
} else if bytes_read >= MAX_BYTES_PER_READ { |
139 |
break Ok((decoder.extract_messages(), NetworkClientState::NeedsRead)); |
|
13419 | 140 |
} |
141 |
} |
|
142 |
Err(ref error) if error.kind() == ErrorKind::WouldBlock => { |
|
14462 | 143 |
let messages = if bytes_read == 0 { |
13419 | 144 |
Vec::new() |
145 |
} else { |
|
13804 | 146 |
decoder.extract_messages() |
13419 | 147 |
}; |
148 |
break Ok((messages, NetworkClientState::Idle)); |
|
149 |
} |
|
14462 | 150 |
Err(error) => break Err(error), |
13419 | 151 |
} |
152 |
}; |
|
13804 | 153 |
decoder.sweep(); |
13419 | 154 |
result |
155 |
} |
|
156 |
||
13804 | 157 |
pub fn read(&mut self) -> NetworkResult<Vec<HWProtocolMessage>> { |
158 |
#[cfg(not(feature = "tls-connections"))] |
|
159 |
match self.socket { |
|
14462 | 160 |
ClientSocket::Plain(ref mut stream) => { |
161 |
NetworkClient::read_impl(&mut self.decoder, stream, self.id, &self.peer_addr) |
|
162 |
} |
|
13804 | 163 |
} |
164 |
||
165 |
#[cfg(feature = "tls-connections")] |
|
166 |
match self.socket { |
|
167 |
ClientSocket::SslHandshake(ref mut handshake_opt) => { |
|
13807 | 168 |
let handshake = std::mem::replace(handshake_opt, None).unwrap(); |
169 |
Ok((Vec::new(), self.handshake_impl(handshake)?)) |
|
14462 | 170 |
} |
171 |
ClientSocket::SslStream(ref mut stream) => { |
|
13804 | 172 |
NetworkClient::read_impl(&mut self.decoder, stream, self.id, &self.peer_addr) |
14462 | 173 |
} |
13804 | 174 |
} |
175 |
} |
|
176 |
||
177 |
fn write_impl<W: Write>(buf_out: &mut netbuf::Buf, destination: &mut W) -> NetworkResult<()> { |
|
13419 | 178 |
let result = loop { |
13804 | 179 |
match buf_out.write_to(destination) { |
14462 | 180 |
Ok(bytes) if buf_out.is_empty() || bytes == 0 => { |
14676
455865ccd36c
Server action refactoring part 2 of N
alfadur <mail@none>
parents:
14462
diff
changeset
|
181 |
break Ok(((), NetworkClientState::Idle)); |
14462 | 182 |
} |
13420 | 183 |
Ok(_) => (), |
14462 | 184 |
Err(ref error) |
185 |
if error.kind() == ErrorKind::Interrupted |
|
186 |
|| error.kind() == ErrorKind::WouldBlock => |
|
187 |
{ |
|
13419 | 188 |
break Ok(((), NetworkClientState::NeedsWrite)); |
14462 | 189 |
} |
190 |
Err(error) => break Err(error), |
|
13419 | 191 |
} |
192 |
}; |
|
13804 | 193 |
result |
194 |
} |
|
195 |
||
196 |
pub fn write(&mut self) -> NetworkResult<()> { |
|
197 |
let result = { |
|
198 |
#[cfg(not(feature = "tls-connections"))] |
|
199 |
match self.socket { |
|
14462 | 200 |
ClientSocket::Plain(ref mut stream) => { |
13804 | 201 |
NetworkClient::write_impl(&mut self.buf_out, stream) |
14462 | 202 |
} |
13804 | 203 |
} |
204 |
||
14462 | 205 |
#[cfg(feature = "tls-connections")] |
206 |
{ |
|
13804 | 207 |
match self.socket { |
13807 | 208 |
ClientSocket::SslHandshake(ref mut handshake_opt) => { |
209 |
let handshake = std::mem::replace(handshake_opt, None).unwrap(); |
|
210 |
Ok(((), self.handshake_impl(handshake)?)) |
|
211 |
} |
|
14462 | 212 |
ClientSocket::SslStream(ref mut stream) => { |
13804 | 213 |
NetworkClient::write_impl(&mut self.buf_out, stream) |
14462 | 214 |
} |
13804 | 215 |
} |
216 |
} |
|
217 |
}; |
|
218 |
||
219 |
self.socket.inner().flush()?; |
|
13419 | 220 |
result |
221 |
} |
|
222 |
||
13124 | 223 |
pub fn send_raw_msg(&mut self, msg: &[u8]) { |
13529 | 224 |
self.buf_out.write_all(msg).unwrap(); |
13124 | 225 |
} |
226 |
||
13529 | 227 |
pub fn send_string(&mut self, msg: &str) { |
13124 | 228 |
self.send_raw_msg(&msg.as_bytes()); |
229 |
} |
|
230 |
||
13529 | 231 |
pub fn send_msg(&mut self, msg: &HWServerMessage) { |
13124 | 232 |
self.send_string(&msg.to_raw_protocol()); |
233 |
} |
|
234 |
} |
|
235 |
||
13804 | 236 |
#[cfg(feature = "tls-connections")] |
237 |
struct ServerSsl { |
|
14462 | 238 |
context: SslContext, |
13804 | 239 |
} |
240 |
||
13124 | 241 |
pub struct NetworkLayer { |
242 |
listener: TcpListener, |
|
243 |
server: HWServer, |
|
13419 | 244 |
clients: Slab<NetworkClient>, |
13420 | 245 |
pending: HashSet<(ClientId, NetworkClientState)>, |
13804 | 246 |
pending_cache: Vec<(ClientId, NetworkClientState)>, |
247 |
#[cfg(feature = "tls-connections")] |
|
14462 | 248 |
ssl: ServerSsl, |
13124 | 249 |
} |
250 |
||
251 |
impl NetworkLayer { |
|
252 |
pub fn new(listener: TcpListener, clients_limit: usize, rooms_limit: usize) -> NetworkLayer { |
|
14397 | 253 |
let server = HWServer::new(clients_limit, rooms_limit, Box::new(FileServerIO::new())); |
13124 | 254 |
let clients = Slab::with_capacity(clients_limit); |
13420 | 255 |
let pending = HashSet::with_capacity(2 * clients_limit); |
256 |
let pending_cache = Vec::with_capacity(2 * clients_limit); |
|
13804 | 257 |
|
258 |
NetworkLayer { |
|
14462 | 259 |
listener, |
260 |
server, |
|
261 |
clients, |
|
262 |
pending, |
|
263 |
pending_cache, |
|
13804 | 264 |
#[cfg(feature = "tls-connections")] |
14462 | 265 |
ssl: NetworkLayer::create_ssl_context(), |
13804 | 266 |
} |
267 |
} |
|
268 |
||
269 |
#[cfg(feature = "tls-connections")] |
|
270 |
fn create_ssl_context() -> ServerSsl { |
|
271 |
let mut builder = SslContextBuilder::new(SslMethod::tls()).unwrap(); |
|
272 |
builder.set_verify(SslVerifyMode::NONE); |
|
273 |
builder.set_read_ahead(true); |
|
14462 | 274 |
builder |
275 |
.set_certificate_file("ssl/cert.pem", SslFiletype::PEM) |
|
276 |
.unwrap(); |
|
277 |
builder |
|
278 |
.set_private_key_file("ssl/key.pem", SslFiletype::PEM) |
|
279 |
.unwrap(); |
|
13804 | 280 |
builder.set_options(SslOptions::NO_COMPRESSION); |
281 |
builder.set_cipher_list("DEFAULT:!LOW:!RC4:!EXP").unwrap(); |
|
14462 | 282 |
ServerSsl { |
283 |
context: builder.build(), |
|
284 |
} |
|
13124 | 285 |
} |
286 |
||
287 |
pub fn register_server(&self, poll: &Poll) -> io::Result<()> { |
|
14462 | 288 |
poll.register( |
289 |
&self.listener, |
|
290 |
utils::SERVER, |
|
291 |
Ready::readable(), |
|
292 |
PollOpt::edge(), |
|
293 |
) |
|
13124 | 294 |
} |
295 |
||
296 |
fn deregister_client(&mut self, poll: &Poll, id: ClientId) { |
|
297 |
let mut client_exists = false; |
|
13419 | 298 |
if let Some(ref client) = self.clients.get(id) { |
13804 | 299 |
poll.deregister(client.socket.inner()) |
13529 | 300 |
.expect("could not deregister socket"); |
13124 | 301 |
info!("client {} ({}) removed", client.id, client.peer_addr); |
302 |
client_exists = true; |
|
303 |
} |
|
304 |
if client_exists { |
|
305 |
self.clients.remove(id); |
|
306 |
} |
|
307 |
} |
|
308 |
||
14462 | 309 |
fn register_client( |
310 |
&mut self, |
|
311 |
poll: &Poll, |
|
312 |
id: ClientId, |
|
313 |
client_socket: ClientSocket, |
|
314 |
addr: SocketAddr, |
|
315 |
) { |
|
316 |
poll.register( |
|
317 |
client_socket.inner(), |
|
318 |
Token(id), |
|
319 |
Ready::readable() | Ready::writable(), |
|
320 |
PollOpt::edge(), |
|
321 |
) |
|
322 |
.expect("could not register socket with event loop"); |
|
13124 | 323 |
|
324 |
let entry = self.clients.vacant_entry(); |
|
325 |
let client = NetworkClient::new(id, client_socket, addr); |
|
326 |
info!("client {} ({}) added", client.id, client.peer_addr); |
|
327 |
entry.insert(client); |
|
328 |
} |
|
329 |
||
14677
6e6632068a33
Server action refactoring part 3 of N
alfadur <mail@none>
parents:
14676
diff
changeset
|
330 |
fn flush_server_messages(&mut self, mut response: handlers::Response) { |
6e6632068a33
Server action refactoring part 3 of N
alfadur <mail@none>
parents:
14676
diff
changeset
|
331 |
debug!("{} pending server messages", response.len()); |
6e6632068a33
Server action refactoring part 3 of N
alfadur <mail@none>
parents:
14676
diff
changeset
|
332 |
let output = response.extract_messages(&mut self.server); |
6e6632068a33
Server action refactoring part 3 of N
alfadur <mail@none>
parents:
14676
diff
changeset
|
333 |
for (clients, message) in output { |
13424 | 334 |
debug!("Message {:?} to {:?}", message, clients); |
335 |
let msg_string = message.to_raw_protocol(); |
|
336 |
for client_id in clients { |
|
337 |
if let Some(client) = self.clients.get_mut(client_id) { |
|
338 |
client.send_string(&msg_string); |
|
14462 | 339 |
self.pending |
340 |
.insert((client_id, NetworkClientState::NeedsWrite)); |
|
13419 | 341 |
} |
342 |
} |
|
343 |
} |
|
344 |
} |
|
345 |
||
13804 | 346 |
fn create_client_socket(&self, socket: TcpStream) -> io::Result<ClientSocket> { |
14462 | 347 |
#[cfg(not(feature = "tls-connections"))] |
348 |
{ |
|
13804 | 349 |
Ok(ClientSocket::Plain(socket)) |
350 |
} |
|
351 |
||
14462 | 352 |
#[cfg(feature = "tls-connections")] |
353 |
{ |
|
13804 | 354 |
let ssl = Ssl::new(&self.ssl.context).unwrap(); |
355 |
let mut builder = SslStreamBuilder::new(ssl, socket); |
|
356 |
builder.set_accept_state(); |
|
357 |
match builder.handshake() { |
|
14462 | 358 |
Ok(stream) => Ok(ClientSocket::SslStream(stream)), |
359 |
Err(HandshakeError::WouldBlock(stream)) => { |
|
360 |
Ok(ClientSocket::SslHandshake(Some(stream))) |
|
361 |
} |
|
13804 | 362 |
Err(e) => { |
363 |
debug!("OpenSSL handshake failed: {}", e); |
|
364 |
Err(Error::new(ErrorKind::Other, "Connection failure")) |
|
365 |
} |
|
366 |
} |
|
367 |
} |
|
368 |
} |
|
369 |
||
13124 | 370 |
pub fn accept_client(&mut self, poll: &Poll) -> io::Result<()> { |
371 |
let (client_socket, addr) = self.listener.accept()?; |
|
372 |
info!("Connected: {}", addr); |
|
373 |
||
374 |
let client_id = self.server.add_client(); |
|
14462 | 375 |
self.register_client( |
376 |
poll, |
|
377 |
client_id, |
|
378 |
self.create_client_socket(client_socket)?, |
|
379 |
addr, |
|
380 |
); |
|
14677
6e6632068a33
Server action refactoring part 3 of N
alfadur <mail@none>
parents:
14676
diff
changeset
|
381 |
//TODO: create response for initial messages |
13124 | 382 |
|
383 |
Ok(()) |
|
384 |
} |
|
385 |
||
14462 | 386 |
fn operation_failed( |
387 |
&mut self, |
|
388 |
poll: &Poll, |
|
389 |
client_id: ClientId, |
|
390 |
error: &Error, |
|
391 |
msg: &str, |
|
392 |
) -> io::Result<()> { |
|
13419 | 393 |
let addr = if let Some(ref mut client) = self.clients.get_mut(client_id) { |
394 |
client.peer_addr |
|
395 |
} else { |
|
396 |
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0) |
|
397 |
}; |
|
398 |
debug!("{}({}): {}", msg, addr, error); |
|
399 |
self.client_error(poll, client_id) |
|
13124 | 400 |
} |
401 |
||
14462 | 402 |
pub fn client_readable(&mut self, poll: &Poll, client_id: ClientId) -> io::Result<()> { |
403 |
let messages = if let Some(ref mut client) = self.clients.get_mut(client_id) { |
|
404 |
client.read() |
|
405 |
} else { |
|
406 |
warn!("invalid readable client: {}", client_id); |
|
407 |
Ok((Vec::new(), NetworkClientState::Idle)) |
|
408 |
}; |
|
13419 | 409 |
|
14676
455865ccd36c
Server action refactoring part 2 of N
alfadur <mail@none>
parents:
14462
diff
changeset
|
410 |
let mut response = handlers::Response::new(client_id); |
455865ccd36c
Server action refactoring part 2 of N
alfadur <mail@none>
parents:
14462
diff
changeset
|
411 |
|
13419 | 412 |
match messages { |
413 |
Ok((messages, state)) => { |
|
414 |
for message in messages { |
|
14676
455865ccd36c
Server action refactoring part 2 of N
alfadur <mail@none>
parents:
14462
diff
changeset
|
415 |
debug!("Handling message {:?} for client {}", message, client_id); |
455865ccd36c
Server action refactoring part 2 of N
alfadur <mail@none>
parents:
14462
diff
changeset
|
416 |
if self.server.clients.contains(client_id) { |
455865ccd36c
Server action refactoring part 2 of N
alfadur <mail@none>
parents:
14462
diff
changeset
|
417 |
handlers::handle(&mut self.server, client_id, &mut response, message); |
455865ccd36c
Server action refactoring part 2 of N
alfadur <mail@none>
parents:
14462
diff
changeset
|
418 |
} |
13419 | 419 |
} |
420 |
match state { |
|
13420 | 421 |
NetworkClientState::NeedsRead => { |
422 |
self.pending.insert((client_id, state)); |
|
14462 | 423 |
} |
424 |
NetworkClientState::Closed => self.client_error(&poll, client_id)?, |
|
13419 | 425 |
_ => {} |
426 |
}; |
|
13124 | 427 |
} |
13419 | 428 |
Err(e) => self.operation_failed( |
14462 | 429 |
poll, |
430 |
client_id, |
|
431 |
&e, |
|
432 |
"Error while reading from client socket", |
|
433 |
)?, |
|
13124 | 434 |
} |
435 |
||
14677
6e6632068a33
Server action refactoring part 3 of N
alfadur <mail@none>
parents:
14676
diff
changeset
|
436 |
if !response.is_empty() { |
6e6632068a33
Server action refactoring part 3 of N
alfadur <mail@none>
parents:
14676
diff
changeset
|
437 |
self.flush_server_messages(response); |
6e6632068a33
Server action refactoring part 3 of N
alfadur <mail@none>
parents:
14676
diff
changeset
|
438 |
} |
13419 | 439 |
|
13124 | 440 |
if !self.server.removed_clients.is_empty() { |
13419 | 441 |
let ids: Vec<_> = self.server.removed_clients.drain(..).collect(); |
13124 | 442 |
for client_id in ids { |
443 |
self.deregister_client(poll, client_id); |
|
444 |
} |
|
445 |
} |
|
446 |
||
447 |
Ok(()) |
|
448 |
} |
|
449 |
||
14462 | 450 |
pub fn client_writable(&mut self, poll: &Poll, client_id: ClientId) -> io::Result<()> { |
451 |
let result = if let Some(ref mut client) = self.clients.get_mut(client_id) { |
|
452 |
client.write() |
|
453 |
} else { |
|
454 |
warn!("invalid writable client: {}", client_id); |
|
455 |
Ok(((), NetworkClientState::Idle)) |
|
456 |
}; |
|
13419 | 457 |
|
458 |
match result { |
|
13420 | 459 |
Ok(((), state)) if state == NetworkClientState::NeedsWrite => { |
460 |
self.pending.insert((client_id, state)); |
|
14462 | 461 |
} |
13420 | 462 |
Ok(_) => {} |
14462 | 463 |
Err(e) => { |
464 |
self.operation_failed(poll, client_id, &e, "Error while writing to client socket")? |
|
465 |
} |
|
13124 | 466 |
} |
467 |
||
468 |
Ok(()) |
|
469 |
} |
|
470 |
||
14462 | 471 |
pub fn client_error(&mut self, poll: &Poll, client_id: ClientId) -> io::Result<()> { |
13124 | 472 |
self.deregister_client(poll, client_id); |
14678
08a8605bafaf
Server action refactoring part 4 of N
alfadur <mail@none>
parents:
14677
diff
changeset
|
473 |
let mut response = handlers::Response::new(client_id); |
08a8605bafaf
Server action refactoring part 4 of N
alfadur <mail@none>
parents:
14677
diff
changeset
|
474 |
handlers::handle_client_loss(&mut self.server, client_id, &mut response); |
08a8605bafaf
Server action refactoring part 4 of N
alfadur <mail@none>
parents:
14677
diff
changeset
|
475 |
self.flush_server_messages(response); |
13124 | 476 |
|
477 |
Ok(()) |
|
478 |
} |
|
13419 | 479 |
|
480 |
pub fn has_pending_operations(&self) -> bool { |
|
481 |
!self.pending.is_empty() |
|
482 |
} |
|
483 |
||
484 |
pub fn on_idle(&mut self, poll: &Poll) -> io::Result<()> { |
|
13420 | 485 |
if self.has_pending_operations() { |
13483 | 486 |
let mut cache = replace(&mut self.pending_cache, Vec::new()); |
13420 | 487 |
cache.extend(self.pending.drain()); |
488 |
for (id, state) in cache.drain(..) { |
|
489 |
match state { |
|
14462 | 490 |
NetworkClientState::NeedsRead => self.client_readable(poll, id)?, |
491 |
NetworkClientState::NeedsWrite => self.client_writable(poll, id)?, |
|
13420 | 492 |
_ => {} |
493 |
} |
|
13419 | 494 |
} |
13420 | 495 |
swap(&mut cache, &mut self.pending_cache); |
13419 | 496 |
} |
497 |
Ok(()) |
|
498 |
} |
|
13124 | 499 |
} |