diff --git a/src/hio/core/tcp/serving.py b/src/hio/core/tcp/serving.py index d69256a4..934a9b91 100644 --- a/src/hio/core/tcp/serving.py +++ b/src/hio/core/tcp/serving.py @@ -690,9 +690,10 @@ def close(self): def refresh(self): """ - Restart tymer + Reset idle tymer from current tyme. """ - self.tymer.restart() + if self.tymer.tyme is not None: + self.tymer.start() def receive(self): @@ -965,6 +966,9 @@ def receive(self): if self.wl: # log over the wire rx self.wl.writeRx(data, who=self.cs.getpeername()) + if self.refreshable: + self.refresh() + else: # data empty so connection closed on other end self.cutoff = True @@ -1003,6 +1007,9 @@ def send(self, data): if self.wl: self.wl.writeTx(data[:result], who=self.cs.getpeername()) + if self.refreshable: + self.refresh() + return result diff --git a/tests/core/tcp/test_tcp.py b/tests/core/tcp/test_tcp.py index 19890c6e..975148b9 100644 --- a/tests/core/tcp/test_tcp.py +++ b/tests/core/tcp/test_tcp.py @@ -16,6 +16,48 @@ from hio.base import tyming, doing from hio.core import tcp + +def test_remoter_refresh_resets_idle_tymeout(): + """Test Remoter activity resets its idle tymer from current tyme.""" + tymist = tyming.Tymist() + remoter = tcp.Remoter( + tymth=tymist.tymen(), + ha=("127.0.0.1", 56000), + ca=("127.0.0.1", 56001), + cs=None, + tymeout=1.0, + ) + + assert remoter.tymer.duration == 1.0 + assert remoter.tymer.remaining == 1.0 + + tymist.tick(tock=0.75) + assert remoter.tymer.remaining == 0.25 + + remoter.refresh() + assert remoter.tymer.duration == 1.0 + assert remoter.tymer.remaining == pytest.approx(1.0) + + # Multiple activity notifications at the same tyme must not accumulate + # additional idle-time credit. + remoter.refresh() + assert remoter.tymer.remaining == pytest.approx(1.0) + + tymist.tick(tock=1.25) + assert remoter.tymer.expired + + # Activity after expiration starts a new full idle interval. + remoter.refresh() + assert not remoter.tymer.expired + assert remoter.tymer.duration == 1.0 + assert remoter.tymer.remaining == pytest.approx(1.0) + + # Remoters without an injected tyme base have no idle time to refresh. + unwound = tcp.Remoter(ha=remoter.ha, ca=remoter.ca, cs=None) + unwound.refresh() + assert unwound.tymer.duration == 0.0 + + def test_tcp_basic(): """ Test the tcp connection between client and server @@ -731,6 +773,11 @@ def test_tcp_tls_default_context(): assert ixBeta.ca == beta.ca assert ixBeta.ha == beta.ha + ixBeta.tymeout = 1.0 + ixBeta.tymer.start(duration=ixBeta.tymeout) + tymist.tick(tock=0.75) + assert ixBeta.tymer.remaining == pytest.approx(0.25) + msgOut = b"Beta sends to Server\n" beta.tx(msgOut) while not( not beta.txbs and ixBeta.rxbs): @@ -743,8 +790,12 @@ def test_tcp_tls_default_context(): msgIn = bytes(ixBeta.rxbs) assert msgIn == msgOut + assert ixBeta.tymer.remaining == pytest.approx(1.0) ixBeta.clearRxbs() + tymist.tick(tock=0.75) + assert ixBeta.tymer.remaining == pytest.approx(0.25) + msgOut = b'Server sends to Beta\n' ixBeta.tx(msgOut) while not (not ixBeta.txbs and beta.rxbs): @@ -754,6 +805,7 @@ def test_tcp_tls_default_context(): msgIn = bytes(beta.rxbs) assert msgIn == msgOut + assert ixBeta.tymer.remaining == pytest.approx(1.0) beta.clearRxbs() assert beta.opened == False