From e657953b8f94cdeabf8a5d71b2a2f2f9aa3c5dec Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Sun, 18 May 2025 11:19:37 -0500 Subject: [PATCH] [Netcode] Resend Logic Adjustments (#4900) * Timeout adjustment * Update daybreak_connection.cpp * Update daybreak_connection.cpp * Update daybreak_connection.cpp * Update daybreak_connection.cpp * Update daybreak_connection.cpp * Update daybreak_connection.cpp * Stuff * Update daybreak_connection.h * Update daybreak_connection.cpp * Update daybreak_connection.cpp * Update daybreak_connection.cpp * Update daybreak_connection.cpp --- common/net/daybreak_connection.cpp | 62 ++++++++++++++++++++++++++---- common/net/daybreak_connection.h | 2 + 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index b33736af1..322107103 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -1127,22 +1127,59 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) auto time_since_first_sent = std::chrono::duration_cast(now - first_packet.first_sent).count(); if (time_since_first_sent >= m_owner->m_options.resend_timeout) { + auto now_ms = std::chrono::duration_cast(now.time_since_epoch()).count(); + auto first_sent_ms = std::chrono::duration_cast(first_packet.first_sent.time_since_epoch()).count(); + LogNetClient( + "Closing connection for m_endpoint [{}] m_port [{}] time_since_first_sent [{}] >= m_owner->m_options.resend_timeout [{}] now [{}] first_packet.first_sent [{}]", + m_endpoint, + m_port, + time_since_first_sent, + m_owner->m_options.resend_timeout, + now_ms, + first_sent_ms + ); Close(); return; } + + if (m_last_ack - now > std::chrono::milliseconds(1000)) { + LogNetClient( + "Resetting m_acked_since_last_resend flag for m_endpoint [{}] m_port [{}]", + m_endpoint, + m_port + ); + m_acked_since_last_resend = true; + } + + // make sure that the first_packet in the list first_sent time is within the resend_delay and now + // if it is not, then we need to resend all packets in the list + if (time_since_first_sent <= first_packet.resend_delay && !m_acked_since_last_resend) { + LogNetClientDetail( + "Not resending packets for m_endpoint [{}] m_port [{}] packets [{}] time_first_sent [{}] resend_delay [{}] m_acked_since_last_resend [{}]", + m_endpoint, + m_port, + s->sent_packets.size(), + time_since_first_sent, + first_packet.resend_delay, + m_acked_since_last_resend + ); + return; + } } - if (LogSys.IsLogEnabled(Logs::Detail, Logs::Netcode)) { + if (LogSys.IsLogEnabled(Logs::General, Logs::NetClient)) { size_t total_size = 0; for (auto &e: s->sent_packets) { total_size += e.second.packet.Length(); } - LogNetClient( - "Resending packets for stream [{}] packet count [{}] total packet size [{}]", - stream, + LogNetClientDetail( + "Resending packets for m_endpoint [{}] m_port [{}] packet count [{}] total packet size [{}] m_acked_since_last_resend [{}]", + m_endpoint, + m_port, s->sent_packets.size(), - total_size + total_size, + m_acked_since_last_resend ); } @@ -1150,9 +1187,12 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) if (m_resend_packets_sent >= MAX_CLIENT_RECV_PACKETS_PER_WINDOW || m_resend_bytes_sent >= MAX_CLIENT_RECV_BYTES_PER_WINDOW) { LogNetClient( - "Stopping resend because we hit thresholds m_resend_packets_sent [{}] max [{}] m_resend_bytes_sent [{}] max [{}]", + "Stopping resend because we hit thresholds for m_endpoint [{}] m_port [{}] m_resend_packets_sent [{}] max [{}] in_queue [{}] m_resend_bytes_sent [{}] max [{}]", + m_endpoint, + m_port, m_resend_packets_sent, MAX_CLIENT_RECV_PACKETS_PER_WINDOW, + s->sent_packets.size(), m_resend_bytes_sent, MAX_CLIENT_RECV_BYTES_PER_WINDOW ); @@ -1187,11 +1227,13 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) m_owner->m_options.resend_delay_max ); } + + m_acked_since_last_resend = false; + m_last_ack = now; } void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) { - auto now = Clock::now(); auto s = &m_streams[stream]; auto iter = s->sent_packets.begin(); @@ -1212,6 +1254,9 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) ++iter; } } + + m_acked_since_last_resend = true; + m_last_ack = now; } void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) @@ -1229,6 +1274,9 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) s->sent_packets.erase(iter); } + + m_acked_since_last_resend = true; + m_last_ack = now; } void EQ::Net::DaybreakConnection::UpdateDataBudget(double budget_add) diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 5dde5739c..1fddc09c9 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -185,6 +185,8 @@ namespace EQ // resend tracking size_t m_resend_packets_sent = 0; size_t m_resend_bytes_sent = 0; + bool m_acked_since_last_resend = false; + Timestamp m_last_ack; struct DaybreakSentPacket {