Merge pull request #42 from Moballo-LLC/codex/py-08a1-completed-handshake
fix(protocol): retain completed DTLS handshakes
This commit is contained in:
@@ -57,6 +57,10 @@ retransmissions within that same deadline:
|
||||
sess.connect(timeout=4.0)
|
||||
```
|
||||
|
||||
The deadline stops further setup, retries, and network waits. If OpenSSL
|
||||
reports that the handshake completed at the deadline boundary, the completed
|
||||
session is retained rather than torn down as a timeout.
|
||||
|
||||
Connection attempts can also use a one-way cancellation signal. The signal is
|
||||
backed by a socketpair, so setting it wakes the network wait immediately while
|
||||
OpenSSL retains control of DTLS retransmission timing:
|
||||
|
||||
@@ -34,14 +34,16 @@ def _drive_dtls_handshake(
|
||||
bounded only by its deadline, while the diagnostic probe retains its
|
||||
explicit retry budget.
|
||||
|
||||
Return ``True`` only when the handshake completes before the deadline.
|
||||
TLS and socket failures are left to the caller to classify.
|
||||
Return ``True`` once OpenSSL reports the handshake complete. The deadline
|
||||
prevents another setup, retry, or network-wait iteration; it does not tear
|
||||
down a session that completed while ``do_handshake()`` was running. TLS and
|
||||
socket failures are left to the caller to classify.
|
||||
"""
|
||||
retransmits = 0
|
||||
while time.monotonic() < deadline:
|
||||
try:
|
||||
connection.do_handshake()
|
||||
return time.monotonic() < deadline
|
||||
return True
|
||||
except SSL.WantReadError:
|
||||
pass
|
||||
|
||||
|
||||
@@ -322,13 +322,15 @@ class DtlsCoapSession:
|
||||
timeout: float | None = None,
|
||||
cancel: ConnectCancellation | None = None,
|
||||
):
|
||||
"""Perform a cancellable DTLS handshake within a monotonic deadline.
|
||||
"""Perform a cancellable DTLS handshake using a monotonic deadline.
|
||||
|
||||
``timeout`` overrides ``HANDSHAKE_TIMEOUT_S`` for this call. OpenSSL
|
||||
owns DTLS retransmission timing while every receive is capped by the
|
||||
remaining budget, so wall-clock adjustments cannot change the bound.
|
||||
A ``ConnectCancellation`` wakes the network wait immediately and does
|
||||
not alter an already established session.
|
||||
Once OpenSSL reports completion, that completed session is retained
|
||||
even if the call returns just after the deadline. A
|
||||
``ConnectCancellation`` wakes the network wait immediately and does not
|
||||
alter an already established session.
|
||||
"""
|
||||
handshake_timeout = _validate_handshake_timeout(
|
||||
timeout, self.HANDSHAKE_TIMEOUT_S)
|
||||
|
||||
@@ -323,12 +323,12 @@ def test_connect_services_openssl_retransmit_timer(monkeypatch):
|
||||
|
||||
|
||||
@pytest.mark.parametrize("success_delay", (0.1, 0.2))
|
||||
def test_handshake_success_at_or_after_deadline_is_rejected(
|
||||
def test_handshake_success_at_or_after_deadline_is_retained(
|
||||
monkeypatch,
|
||||
success_delay,
|
||||
):
|
||||
clock = _Clock()
|
||||
connection, sock, _endpoint, _open_calls = _install_handshake(
|
||||
connection, sock, endpoint, _open_calls = _install_handshake(
|
||||
monkeypatch,
|
||||
clock,
|
||||
)
|
||||
@@ -338,7 +338,11 @@ def test_handshake_success_at_or_after_deadline_is_rejected(
|
||||
|
||||
connection.do_handshake = late_success
|
||||
|
||||
with pytest.raises(SessionTimeoutError):
|
||||
_session().connect(timeout=0.1)
|
||||
session = _session()
|
||||
session.connect(timeout=0.1)
|
||||
|
||||
assert sock.closed
|
||||
assert session.conn is connection
|
||||
assert session.sock is sock
|
||||
assert session.endpoint is endpoint
|
||||
assert session.dest == endpoint.sockaddr
|
||||
assert not sock.closed
|
||||
|
||||
Reference in New Issue
Block a user