From 3d50ae8907c09eb9be61dd9fad70c1e2f1f232e8 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Wed, 11 Nov 2026 12:40:42 -0500 Subject: [PATCH] bypass initial retry sequence and reset retry backoff for network connection startup; --- src/common/network/Network.cpp | 7 ++++ src/common/network/Network.h | 1 + tests/network/Network_Tests.cpp | 57 +++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/src/common/network/Network.cpp b/src/common/network/Network.cpp index 9435e94b..72494db6 100644 --- a/src/common/network/Network.cpp +++ b/src/common/network/Network.cpp @@ -57,6 +57,7 @@ Network::Network(const std::string& address, uint16_t port, uint16_t localPort, m_radioAliasSyncStreamId(0U), m_salt(nullptr), m_kmfPresharedKey(nullptr), + m_initRetry(true), m_retryTimer(1000U, DEFAULT_RETRY_TIME), m_retryCount(0U), m_maxRetryCount(MAX_RETRY_BEFORE_RECONNECT), @@ -490,6 +491,12 @@ bool Network::open() return false; } + // if this is the initial connection attempt, clock the retry timer with the default retry time + if (m_initRetry) { + m_initRetry = false; + m_retryTimer.clock(DEFAULT_RETRY_TIME * 1000U); + } + return true; } diff --git a/src/common/network/Network.h b/src/common/network/Network.h index b90bb56c..7d800f1a 100644 --- a/src/common/network/Network.h +++ b/src/common/network/Network.h @@ -406,6 +406,7 @@ namespace network uint8_t* m_kmfPresharedKey; + bool m_initRetry; Timer m_retryTimer; uint8_t m_retryCount; uint8_t m_maxRetryCount; diff --git a/tests/network/Network_Tests.cpp b/tests/network/Network_Tests.cpp index 98f6159c..1280dbc8 100644 --- a/tests/network/Network_Tests.cpp +++ b/tests/network/Network_Tests.cpp @@ -87,6 +87,22 @@ public: * @returns uint8_t The current retry count. */ uint32_t getRemotePeerIdForTest() const { return m_remotePeerId; } + + /** + * @brief Checks if the network is ready to attempt a connection based on the retry timer. + * @returns bool True if ready to attempt, false otherwise. + */ + bool readyToAttempt() const { return m_retryTimer.isRunning() && m_retryTimer.hasExpired(); } + /** + * @brief Gets the retry timeout in seconds. + * @returns uint32_t The retry timeout in seconds. + */ + uint32_t retrySeconds() const { return m_retryTimer.getTimeout(); } + /** + * @brief Advances the retry timer by the specified number of milliseconds. + * @param ms The number of milliseconds to advance the retry timer. + */ + void retryClock(uint32_t ms) { m_retryTimer.clock(ms); } }; // --------------------------------------------------------------------------- @@ -852,3 +868,44 @@ TEST_CASE("RTPStreamMultiplex detects lost and out-of-order sequences and resets REQUIRE(mux.verifyStream(0x1234U, RTP_END_OF_CALL_SEQ, NET_FUNC::PROTOCOL, &lastSeq) == MUX_VALID_SUCCESS); REQUIRE_FALSE(mux.hasPktSeq(0x1234U)); } + +TEST_CASE("First FNE connection is immediate and reconnect keeps its backoff", "[network][loopback]") +{ + const uint16_t masterPort = reserveLoopbackPort(); + REQUIRE(masterPort != 0U); + + const uint16_t localPort = reserveLoopbackPort(); + REQUIRE(localPort != 0U); + + TestableNetwork network("127.0.0.1", masterPort, localPort, 9004U, "loopback-password", true, false, true, false, false, false, true, true, true, true, false, false); + network.enable(true); + REQUIRE(network.open()); + + REQUIRE(network.readyToAttempt()); + REQUIRE(network.retrySeconds() == 10U); + network.close(); + REQUIRE(network.open()); + REQUIRE_FALSE(network.readyToAttempt()); + REQUIRE(network.retrySeconds() == 10U); + network.retryClock(9999U); + REQUIRE_FALSE(network.readyToAttempt()); + network.retryClock(1U); + REQUIRE(network.readyToAttempt()); + network.close(); +} + +TEST_CASE("Disabled open does not consume the initial connection", "[network][loopback]") +{ + const uint16_t masterPort = reserveLoopbackPort(); + REQUIRE(masterPort != 0U); + + const uint16_t localPort = reserveLoopbackPort(); + REQUIRE(localPort != 0U); + + TestableNetwork network("127.0.0.1", masterPort, localPort, 9004U, "loopback-password", true, false, true, false, false, false, true, true, true, true, false, false); + network.enable(true); + REQUIRE(network.open()); + + REQUIRE(network.readyToAttempt()); + network.close(); +}