mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
107 lines
3.4 KiB
Rust
107 lines
3.4 KiB
Rust
|
use super::super::SysTimer;
|
||
|
use crate::{
|
||
|
client::Client,
|
||
|
metrics::PlayerMetrics,
|
||
|
streams::{GetStream, PingStream},
|
||
|
Settings,
|
||
|
};
|
||
|
use common::{
|
||
|
event::{EventBus, ServerEvent},
|
||
|
msg::PingMsg,
|
||
|
span,
|
||
|
state::Time,
|
||
|
};
|
||
|
use specs::{Entities, Join, Read, ReadExpect, System, Write, WriteStorage};
|
||
|
use tracing::{debug, info};
|
||
|
|
||
|
impl Sys {
|
||
|
fn handle_ping_msg(
|
||
|
ping_stream: &mut PingStream,
|
||
|
msg: PingMsg,
|
||
|
) -> Result<(), crate::error::Error> {
|
||
|
match msg {
|
||
|
PingMsg::Ping => ping_stream.send(PingMsg::Pong)?,
|
||
|
PingMsg::Pong => {},
|
||
|
}
|
||
|
Ok(())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// This system will handle new messages from clients
|
||
|
pub struct Sys;
|
||
|
impl<'a> System<'a> for Sys {
|
||
|
#[allow(clippy::type_complexity)] // TODO: Pending review in #587
|
||
|
type SystemData = (
|
||
|
Entities<'a>,
|
||
|
Read<'a, EventBus<ServerEvent>>,
|
||
|
Read<'a, Time>,
|
||
|
ReadExpect<'a, PlayerMetrics>,
|
||
|
Write<'a, SysTimer<Self>>,
|
||
|
WriteStorage<'a, Client>,
|
||
|
WriteStorage<'a, PingStream>,
|
||
|
Read<'a, Settings>,
|
||
|
);
|
||
|
|
||
|
#[allow(clippy::match_ref_pats)] // TODO: Pending review in #587
|
||
|
#[allow(clippy::single_char_pattern)] // TODO: Pending review in #587
|
||
|
#[allow(clippy::single_match)] // TODO: Pending review in #587
|
||
|
fn run(
|
||
|
&mut self,
|
||
|
(
|
||
|
entities,
|
||
|
server_event_bus,
|
||
|
time,
|
||
|
player_metrics,
|
||
|
mut timer,
|
||
|
mut clients,
|
||
|
mut ping_streams,
|
||
|
settings,
|
||
|
): Self::SystemData,
|
||
|
) {
|
||
|
span!(_guard, "run", "msg::ping::Sys::run");
|
||
|
timer.start();
|
||
|
|
||
|
let mut server_emitter = server_event_bus.emitter();
|
||
|
|
||
|
for (entity, client, ping_stream) in (&entities, &mut clients, &mut ping_streams).join() {
|
||
|
let res = super::try_recv_all(ping_stream, |ping_stream, msg| {
|
||
|
Self::handle_ping_msg(ping_stream, msg)
|
||
|
});
|
||
|
|
||
|
match res {
|
||
|
Err(e) => {
|
||
|
debug!(?entity, ?e, "network error with client, disconnecting");
|
||
|
player_metrics
|
||
|
.clients_disconnected
|
||
|
.with_label_values(&["network_error"])
|
||
|
.inc();
|
||
|
server_emitter.emit(ServerEvent::ClientDisconnect(entity));
|
||
|
},
|
||
|
Ok(1_u64..=u64::MAX) => {
|
||
|
// Update client ping.
|
||
|
client.last_ping = time.0
|
||
|
},
|
||
|
Ok(0) => {
|
||
|
if time.0 - client.last_ping > settings.client_timeout.as_secs() as f64
|
||
|
// Timeout
|
||
|
{
|
||
|
info!(?entity, "timeout error with client, disconnecting");
|
||
|
player_metrics
|
||
|
.clients_disconnected
|
||
|
.with_label_values(&["timeout"])
|
||
|
.inc();
|
||
|
server_emitter.emit(ServerEvent::ClientDisconnect(entity));
|
||
|
} else if time.0 - client.last_ping
|
||
|
> settings.client_timeout.as_secs() as f64 * 0.5
|
||
|
{
|
||
|
// Try pinging the client if the timeout is nearing.
|
||
|
ping_stream.send_unchecked(PingMsg::Ping);
|
||
|
}
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
|
||
|
timer.end()
|
||
|
}
|
||
|
}
|