diff --git a/ntcore/src/main/native/cpp/net/ClientImpl.cpp b/ntcore/src/main/native/cpp/net/ClientImpl.cpp index 1852b6646e..ed9e2d04ca 100644 --- a/ntcore/src/main/native/cpp/net/ClientImpl.cpp +++ b/ntcore/src/main/native/cpp/net/ClientImpl.cpp @@ -32,7 +32,7 @@ static constexpr uint32_t kMinPeriodMs = 5; // maximum amount of time the wire can be not ready to send another // transmission before we close the connection -static constexpr uint32_t kWireMaxNotReadyMs = 1000; +static constexpr uint32_t kWireMaxNotReadyUs = 1000000; namespace { @@ -313,7 +313,9 @@ void CImpl::SendInitialValues() { bool CImpl::CheckNetworkReady(uint64_t curTimeMs) { if (!m_wire.Ready()) { - if (m_lastSendMs != 0 && curTimeMs > (m_lastSendMs + kWireMaxNotReadyMs)) { + uint64_t lastFlushTime = m_wire.GetLastFlushTime(); + uint64_t now = wpi::Now(); + if (lastFlushTime != 0 && now > (lastFlushTime + kWireMaxNotReadyUs)) { m_wire.Disconnect("transmit stalled"); } return false; diff --git a/ntcore/src/main/native/cpp/net/ServerImpl.cpp b/ntcore/src/main/native/cpp/net/ServerImpl.cpp index ecfa4f03db..b2e82fad92 100644 --- a/ntcore/src/main/native/cpp/net/ServerImpl.cpp +++ b/ntcore/src/main/native/cpp/net/ServerImpl.cpp @@ -50,7 +50,7 @@ static constexpr uint32_t kMinPeriodMs = 5; // maximum amount of time the wire can be not ready to send another // transmission before we close the connection -static constexpr uint32_t kWireMaxNotReadyMs = 1000; +static constexpr uint32_t kWireMaxNotReadyUs = 1000000; namespace { @@ -952,7 +952,9 @@ void ClientData4::SendOutgoing(uint64_t curTimeMs) { } if (!m_wire.Ready()) { - if (m_lastSendMs != 0 && curTimeMs > (m_lastSendMs + kWireMaxNotReadyMs)) { + uint64_t lastFlushTime = m_wire.GetLastFlushTime(); + uint64_t now = wpi::Now(); + if (lastFlushTime != 0 && now > (lastFlushTime + kWireMaxNotReadyUs)) { m_wire.Disconnect("transmit stalled"); } return; @@ -1123,7 +1125,9 @@ void ClientData3::SendOutgoing(uint64_t curTimeMs) { } if (!m_wire.Ready()) { - if (m_lastSendMs != 0 && curTimeMs > (m_lastSendMs + kWireMaxNotReadyMs)) { + uint64_t lastFlushTime = m_wire.GetLastFlushTime(); + uint64_t now = wpi::Now(); + if (lastFlushTime != 0 && now > (lastFlushTime + kWireMaxNotReadyUs)) { m_wire.Disconnect("transmit stalled"); } return; diff --git a/ntcore/src/main/native/cpp/net/WebSocketConnection.cpp b/ntcore/src/main/native/cpp/net/WebSocketConnection.cpp index 682a75e62c..2a30e4299b 100644 --- a/ntcore/src/main/native/cpp/net/WebSocketConnection.cpp +++ b/ntcore/src/main/native/cpp/net/WebSocketConnection.cpp @@ -7,6 +7,7 @@ #include #include +#include #include using namespace nt; @@ -67,6 +68,7 @@ void WebSocketConnection::Flush() { m_binary_buffers.clear(); m_text_pos = 0; m_binary_pos = 0; + m_lastFlushTime = wpi::Now(); } void WebSocketConnection::Disconnect(std::string_view reason) { diff --git a/ntcore/src/main/native/cpp/net/WebSocketConnection.h b/ntcore/src/main/native/cpp/net/WebSocketConnection.h index 40aadb467d..8a1d243f42 100644 --- a/ntcore/src/main/native/cpp/net/WebSocketConnection.h +++ b/ntcore/src/main/native/cpp/net/WebSocketConnection.h @@ -34,6 +34,8 @@ class WebSocketConnection final void Flush() final; + uint64_t GetLastFlushTime() const final { return m_lastFlushTime; } + void Disconnect(std::string_view reason) final; std::string_view GetDisconnectReason() const { return m_reason; } @@ -69,6 +71,7 @@ class WebSocketConnection final bool m_in_text = false; int m_sendsActive = 0; std::string m_reason; + uint64_t m_lastFlushTime = 0; }; } // namespace nt::net diff --git a/ntcore/src/main/native/cpp/net/WireConnection.h b/ntcore/src/main/native/cpp/net/WireConnection.h index 2a79a12adf..e4571b99ca 100644 --- a/ntcore/src/main/native/cpp/net/WireConnection.h +++ b/ntcore/src/main/native/cpp/net/WireConnection.h @@ -30,6 +30,8 @@ class WireConnection { virtual void Flush() = 0; + virtual uint64_t GetLastFlushTime() const = 0; // in microseconds + virtual void Disconnect(std::string_view reason) = 0; protected: diff --git a/ntcore/src/main/native/cpp/net3/ClientImpl3.cpp b/ntcore/src/main/native/cpp/net3/ClientImpl3.cpp index 305fc9bab7..064a1d358b 100644 --- a/ntcore/src/main/native/cpp/net3/ClientImpl3.cpp +++ b/ntcore/src/main/native/cpp/net3/ClientImpl3.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include "Handle.h" #include "Log.h" @@ -33,7 +34,7 @@ static constexpr uint32_t kMinPeriodMs = 5; // maximum amount of time the wire can be not ready to send another // transmission before we close the connection -static constexpr uint32_t kWireMaxNotReadyMs = 1000; +static constexpr uint32_t kWireMaxNotReadyUs = 1000000; namespace { @@ -303,7 +304,9 @@ void CImpl::SendValue(Writer& out, Entry* entry, const Value& value) { bool CImpl::CheckNetworkReady(uint64_t curTimeMs) { if (!m_wire.Ready()) { - if (m_lastSendMs != 0 && curTimeMs > (m_lastSendMs + kWireMaxNotReadyMs)) { + uint64_t lastFlushTime = m_wire.GetLastFlushTime(); + uint64_t now = wpi::Now(); + if (lastFlushTime != 0 && now > (lastFlushTime + kWireMaxNotReadyUs)) { m_wire.Disconnect("transmit stalled"); } return false; diff --git a/ntcore/src/main/native/cpp/net3/UvStreamConnection3.cpp b/ntcore/src/main/native/cpp/net3/UvStreamConnection3.cpp index 93af7007c9..835950fd70 100644 --- a/ntcore/src/main/native/cpp/net3/UvStreamConnection3.cpp +++ b/ntcore/src/main/native/cpp/net3/UvStreamConnection3.cpp @@ -4,6 +4,7 @@ #include "UvStreamConnection3.h" +#include #include using namespace nt; @@ -33,6 +34,7 @@ void UvStreamConnection3::Flush() { }); m_buffers.clear(); m_os.reset(); + m_lastFlushTime = wpi::Now(); } void UvStreamConnection3::Disconnect(std::string_view reason) { diff --git a/ntcore/src/main/native/cpp/net3/UvStreamConnection3.h b/ntcore/src/main/native/cpp/net3/UvStreamConnection3.h index f94c4a3fca..35eef02fd5 100644 --- a/ntcore/src/main/native/cpp/net3/UvStreamConnection3.h +++ b/ntcore/src/main/native/cpp/net3/UvStreamConnection3.h @@ -38,6 +38,8 @@ class UvStreamConnection3 final void Flush() final; + uint64_t GetLastFlushTime() const final { return m_lastFlushTime; } + void Disconnect(std::string_view reason) final; std::string_view GetDisconnectReason() const { return m_reason; } @@ -54,6 +56,7 @@ class UvStreamConnection3 final std::vector m_buf_pool; wpi::raw_uv_ostream m_os; std::string m_reason; + uint64_t m_lastFlushTime = 0; int m_sendsActive = 0; }; diff --git a/ntcore/src/main/native/cpp/net3/WireConnection3.h b/ntcore/src/main/native/cpp/net3/WireConnection3.h index 85453d77b6..a3a2d81ceb 100644 --- a/ntcore/src/main/native/cpp/net3/WireConnection3.h +++ b/ntcore/src/main/native/cpp/net3/WireConnection3.h @@ -26,6 +26,8 @@ class WireConnection3 { virtual void Flush() = 0; + virtual uint64_t GetLastFlushTime() const = 0; // in microseconds + virtual void Disconnect(std::string_view reason) = 0; protected: diff --git a/ntcore/src/test/native/cpp/net/MockWireConnection.h b/ntcore/src/test/native/cpp/net/MockWireConnection.h index 3909cabdd8..578bee0c3b 100644 --- a/ntcore/src/test/native/cpp/net/MockWireConnection.h +++ b/ntcore/src/test/native/cpp/net/MockWireConnection.h @@ -32,6 +32,8 @@ class MockWireConnection : public WireConnection { MOCK_METHOD(void, Flush, (), (override)); + MOCK_METHOD(uint64_t, GetLastFlushTime, (), (const, override)); + MOCK_METHOD(void, Disconnect, (std::string_view reason), (override)); protected: diff --git a/ntcore/src/test/native/cpp/net3/MockWireConnection3.h b/ntcore/src/test/native/cpp/net3/MockWireConnection3.h index b7c785f9fa..50fc80cbbb 100644 --- a/ntcore/src/test/native/cpp/net3/MockWireConnection3.h +++ b/ntcore/src/test/native/cpp/net3/MockWireConnection3.h @@ -28,6 +28,8 @@ class MockWireConnection3 : public WireConnection3 { MOCK_METHOD(void, Flush, (), (override)); + MOCK_METHOD(uint64_t, GetLastFlushTime, (), (const, override)); + MOCK_METHOD(void, Disconnect, (std::string_view reason), (override)); protected: