From 94604ce886262452aec345c6e6af2c0681658759 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Fri, 20 Oct 2023 13:27:58 +0200 Subject: [PATCH] Only verify remote checksums once And fix bugs with checksum interval > 32 --- src/network/protocol.rs | 19 ++++++------------- src/sessions/p2p_session.rs | 29 +++++++++++++++++------------ 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/network/protocol.rs b/src/network/protocol.rs index 5cddbe7..f94594b 100644 --- a/src/network/protocol.rs +++ b/src/network/protocol.rs @@ -175,7 +175,7 @@ where last_recv_time: Instant, // debug desync - checksum_history: HashMap, + pub(crate) pending_checksums: VecDeque<(Frame, u128)>, last_added_checksum_frame: Frame, } @@ -261,7 +261,7 @@ impl UdpProtocol { last_recv_time: Instant::now(), // debug desync - checksum_history: HashMap::new(), + pending_checksums: VecDeque::new(), last_added_checksum_frame: NULL_FRAME, } } @@ -711,13 +711,10 @@ impl UdpProtocol { /// Upon receiving a `ChecksumReport`, add it to the checksum history fn on_checksum_report(&mut self, body: &ChecksumReport) { if self.last_added_checksum_frame < body.frame { - if self.checksum_history.len() > MAX_CHECKSUM_HISTORY_SIZE { - let oldest_frame_to_keep = self.last_added_checksum_frame; - self.checksum_history - .retain(|&frame, _| frame >= oldest_frame_to_keep as i32); - } - self.last_added_checksum_frame = body.frame; - self.checksum_history.insert(body.frame, body.checksum); + self.pending_checksums + .truncate(MAX_CHECKSUM_HISTORY_SIZE - 1); + self.pending_checksums + .push_front((body.frame, body.checksum)); } } @@ -729,10 +726,6 @@ impl UdpProtocol { } } - pub(crate) fn checksum_history(&self) -> &HashMap { - &self.checksum_history - } - pub(crate) fn send_checksum_report(&mut self, frame_to_send: Frame, checksum: u128) { let body = ChecksumReport { frame: frame_to_send, diff --git a/src/sessions/p2p_session.rs b/src/sessions/p2p_session.rs index 082983d..ba8c07b 100644 --- a/src/sessions/p2p_session.rs +++ b/src/sessions/p2p_session.rs @@ -875,20 +875,25 @@ impl P2PSession { fn compare_local_checksums_against_peers(&mut self) { match self.desync_detection { - DesyncDetection::On { interval } => { - if self.current_frame() % interval as i32 != 0 { - return; - } - - for remote in self.player_reg.remotes.values() { - for (remote_frame, remote_checksum) in remote.checksum_history() { - if let Some(local_checksum) = self.local_checksum_history.get(remote_frame) + DesyncDetection::On { .. } => { + for remote in self.player_reg.remotes.values_mut() { + while remote.pending_checksums.len() > 0 { + // todo: clean up when/if a drain filter variant is added for VecDeque + let (remote_frame, _) = remote.pending_checksums.back().unwrap(); + if *remote_frame >= self.sync_layer.last_confirmed_frame() { + break; + } + if let Some(&local_checksum) = + self.local_checksum_history.get(&remote_frame) { - if *local_checksum != *remote_checksum { + let (remote_frame, remote_checksum) = + remote.pending_checksums.pop_back().unwrap(); + + if local_checksum != remote_checksum { self.event_queue.push_back(GGRSEvent::DesyncDetected { - frame: *remote_frame, - local_checksum: *local_checksum, - remote_checksum: *remote_checksum, + frame: remote_frame, + local_checksum, + remote_checksum, addr: remote.peer_addr(), }); }