2020-10-17 09:36:44 +00:00
|
|
|
use super::super::SysTimer;
|
2020-11-02 18:30:56 +00:00
|
|
|
use crate::{client::Client, metrics::PlayerMetrics, Settings};
|
2020-10-17 09:36:44 +00:00
|
|
|
use common::{
|
|
|
|
event::{EventBus, ServerEvent},
|
2020-12-01 00:28:00 +00:00
|
|
|
resources::Time,
|
2021-03-04 14:00:16 +00:00
|
|
|
vsystem::{Origin, Phase, VJob, VSystem},
|
2020-10-17 09:36:44 +00:00
|
|
|
};
|
2020-12-13 17:11:55 +00:00
|
|
|
use common_net::msg::PingMsg;
|
2021-03-04 14:00:16 +00:00
|
|
|
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write};
|
2020-11-02 18:30:56 +00:00
|
|
|
use std::sync::atomic::Ordering;
|
2020-10-17 09:36:44 +00:00
|
|
|
use tracing::{debug, info};
|
|
|
|
|
|
|
|
impl Sys {
|
2020-11-02 18:30:56 +00:00
|
|
|
fn handle_ping_msg(client: &Client, msg: PingMsg) -> Result<(), crate::error::Error> {
|
2020-10-17 09:36:44 +00:00
|
|
|
match msg {
|
2020-11-02 18:30:56 +00:00
|
|
|
PingMsg::Ping => client.send(PingMsg::Pong)?,
|
2020-10-17 09:36:44 +00:00
|
|
|
PingMsg::Pong => {},
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// This system will handle new messages from clients
|
2021-03-04 14:00:16 +00:00
|
|
|
#[derive(Default)]
|
2020-10-17 09:36:44 +00:00
|
|
|
pub struct Sys;
|
2021-03-04 14:00:16 +00:00
|
|
|
impl<'a> VSystem<'a> for Sys {
|
2020-10-18 22:57:43 +00:00
|
|
|
#[allow(clippy::type_complexity)]
|
2020-10-17 09:36:44 +00:00
|
|
|
type SystemData = (
|
|
|
|
Entities<'a>,
|
|
|
|
Read<'a, EventBus<ServerEvent>>,
|
|
|
|
Read<'a, Time>,
|
|
|
|
ReadExpect<'a, PlayerMetrics>,
|
|
|
|
Write<'a, SysTimer<Self>>,
|
2020-11-02 18:30:56 +00:00
|
|
|
ReadStorage<'a, Client>,
|
2020-10-17 09:36:44 +00:00
|
|
|
Read<'a, Settings>,
|
|
|
|
);
|
|
|
|
|
2021-03-04 14:00:16 +00:00
|
|
|
const NAME: &'static str = "msg::ping";
|
|
|
|
const ORIGIN: Origin = Origin::Server;
|
|
|
|
const PHASE: Phase = Phase::Create;
|
|
|
|
|
2020-10-17 09:36:44 +00:00
|
|
|
fn run(
|
2021-03-04 14:00:16 +00:00
|
|
|
_job: &mut VJob<Self>,
|
2020-10-17 09:36:44 +00:00
|
|
|
(
|
|
|
|
entities,
|
|
|
|
server_event_bus,
|
|
|
|
time,
|
|
|
|
player_metrics,
|
|
|
|
mut timer,
|
2020-11-02 18:30:56 +00:00
|
|
|
clients,
|
2020-10-17 09:36:44 +00:00
|
|
|
settings,
|
|
|
|
): Self::SystemData,
|
|
|
|
) {
|
|
|
|
timer.start();
|
|
|
|
|
|
|
|
let mut server_emitter = server_event_bus.emitter();
|
|
|
|
|
2020-11-02 18:30:56 +00:00
|
|
|
for (entity, client) in (&entities, &clients).join() {
|
|
|
|
let res = super::try_recv_all(client, 4, Self::handle_ping_msg);
|
2020-10-17 09:36:44 +00:00
|
|
|
|
|
|
|
match res {
|
|
|
|
Err(e) => {
|
2020-11-02 18:30:56 +00:00
|
|
|
if !client.terminate_msg_recv.load(Ordering::Relaxed) {
|
2020-10-22 23:45:19 +00:00
|
|
|
debug!(?entity, ?e, "network error with client, disconnecting");
|
2020-10-21 10:23:34 +00:00
|
|
|
player_metrics
|
|
|
|
.clients_disconnected
|
|
|
|
.with_label_values(&["network_error"])
|
|
|
|
.inc();
|
2020-10-22 23:45:19 +00:00
|
|
|
server_emitter.emit(ServerEvent::ClientDisconnect(entity));
|
2020-10-21 10:23:34 +00:00
|
|
|
}
|
2020-10-17 09:36:44 +00:00
|
|
|
},
|
|
|
|
Ok(1_u64..=u64::MAX) => {
|
|
|
|
// Update client ping.
|
2020-11-02 18:30:56 +00:00
|
|
|
*client.last_ping.lock().unwrap() = time.0
|
2020-10-17 09:36:44 +00:00
|
|
|
},
|
|
|
|
Ok(0) => {
|
2020-11-02 18:30:56 +00:00
|
|
|
let last_ping: f64 = *client.last_ping.lock().unwrap();
|
|
|
|
if time.0 - last_ping > settings.client_timeout.as_secs() as f64
|
2020-10-17 09:36:44 +00:00
|
|
|
// Timeout
|
|
|
|
{
|
2020-11-02 18:30:56 +00:00
|
|
|
if !client.terminate_msg_recv.load(Ordering::Relaxed) {
|
2020-10-22 23:45:19 +00:00
|
|
|
info!(?entity, "timeout error with client, disconnecting");
|
2020-10-21 10:23:34 +00:00
|
|
|
player_metrics
|
|
|
|
.clients_disconnected
|
|
|
|
.with_label_values(&["timeout"])
|
|
|
|
.inc();
|
2020-10-22 23:45:19 +00:00
|
|
|
server_emitter.emit(ServerEvent::ClientDisconnect(entity));
|
2020-10-21 10:23:34 +00:00
|
|
|
}
|
2020-11-02 18:30:56 +00:00
|
|
|
} else if time.0 - last_ping > settings.client_timeout.as_secs() as f64 * 0.5 {
|
2020-10-17 09:36:44 +00:00
|
|
|
// Try pinging the client if the timeout is nearing.
|
2020-11-02 18:30:56 +00:00
|
|
|
client.send_fallible(PingMsg::Ping);
|
2020-10-17 09:36:44 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
timer.end()
|
|
|
|
}
|
|
|
|
}
|