fix: wait for peer close_notify before retrying TLS unwrap - #16
Conversation
Add a real TLS 1.3 loopback oracle proving that ClientTls and RemoterTls preserve application data sent after local unwrap has entered WANT_READ. Complete the typed WANT matrix for TLS receive and send paths so both WANT_READ and WANT_WRITE remain explicitly retryable without losing queued output.
Replace mock-only confidence with socket-pair coverage proving that peer EOF leaves Client transmit available for a late response. Exercise recurrent close ordering and directional shutdown behavior so queued output drains before local write EOF while final peer input remains readable.
Extract the scheduler-like TLS close driver and rename the complex shutdown tests around the contracts they prove, making recurrent completion and version policy visible before reviewers enter each test body. Add concise RFC context and inline phase anchors for close_notify consumption, nonblocking unwrap advancement, plaintext preservation, and independent TCP half-close directions without changing production code.
Keep ClientTls and RemoterTls in receive service after unwrap returns WANT_READ until peer close_notify is actually observed. This prevents racing TLS 1.3 application data from being consumed inside OpenSSL shutdown and misclassified as APPLICATION_DATA_AFTER_CLOSE_NOTIFY. Extend the recurrent-close oracle to prove that a no-progress receive does not retry unwrap, then complete only after a scripted peer close_notify arrives.
|
Upstream prerequisites: the behaviors exercised here must already exist—Client half-close from #9, TLS receive/send classification from #11/#12, raw recurrent close from #13, and recurrent/version-aware TLS shutdown from #14/#15. This PR is not entirely test-only: it also fixes the |
|
Completes the downstream fix for ioflo#176 by preventing premature |
|
Completes the downstream coverage and shutdown mechanics for ioflo#177 by preventing premature |
Production change
Prevent
ClientTlsandRemoterTlsfrom retryingunwrap()after WANT_READ until receive processing records authenticated peer closure. This avoids racing peerclose_notifyand TLS 1.3 application data arriving after local shutdown begins.Coverage added
Why
A scheduler recurrence may service receives without making progress. Retrying
unwrap()immediately can spin or mishandle final plaintext. The production guard preserves close progress until the receive path records the event required for the next shutdown step.Boundary
The production change is a small guard in each TLS endpoint. The remaining changes strengthen regression coverage; they do not introduce another shutdown design.