internal: propagate WANT_WRITE from the DTLS 1.3 receive timeout - #11396
internal: propagate WANT_WRITE from the DTLS 1.3 receive timeout#11396yosuke-wolfssl wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
wolfSSLReceive() returns raw WANT_WRITE instead of WC_NO_ERR_TRACE(WANT_WRITE), which can break propagation under error-trace builds and undermine the fix.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR fixes DTLS 1.3 non-blocking behavior by correctly propagating WANT_WRITE when a receive timeout triggers an ACK/retransmit that cannot be sent immediately, aligning wolfSSLReceive()’s timeout path with existing DTLS timeout handling and adding regression tests.
Changes:
- Update
wolfSSLReceive()to returnWANT_WRITE(and setdtls13SendingAckOrRtx) whenDtls13RtxTimeout()cannot write on a non-blocking transport. - Update
GetInputData_ex()to passWANT_WRITEthrough instead of folding it intoSOCKET_ERROR_E(DTLS 1.3 builds). - Add two DTLS 1.3 API tests covering
WANT_WRITEpropagation on timeout during handshake and post-handshake read.
File summaries
| File | Description |
|---|---|
| tests/api/test_dtls13.h | Registers the two new DTLS 1.3 timeout/WANT_WRITE tests in the DTLS 1.3 test group. |
| tests/api/test_dtls13.c | Adds two manual-memio tests validating WANT_WRITE propagation and scheduled-work flushing after timeout-triggered retransmit/ACK. |
| src/internal.c | Implements WANT_WRITE propagation for DTLS 1.3 timeout-driven ACK/retransmit and ensures the read path preserves WANT_WRITE. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- wolfSSLReceive() captures Dtls13RtxTimeout()'s result. On WANT_WRITE it sets dtls13SendingAckOrRtx and returns WANT_WRITE; a negative result still returns WOLFSSL_FATAL_ERROR. - GetInputData_ex() returns WANT_WRITE to its caller instead of rewriting it to SOCKET_ERROR_E, under WOLFSSL_DTLS13. - wolfSSLReceive()'s comment names WANT_READ and WANT_WRITE among the values it returns. - tests: test_dtls13_rtx_timeout_want_write and test_dtls13_rtx_timeout_want_write_read cover the handshake and read paths, with a receive callback that reports a set number of timeouts. Issue: F-13343
7880bf8 to
2aa4f8a
Compare
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #11396
Scan targets checked: wolfcrypt-rs-bugs, wolfssl-bugs, wolfssl-src
Fenrir result: Approved ✅
No new issues found in the changed files.
Advisory only — this automated result does not count as a GitHub approval.
Problem
wolfSSLReceive()answers aWOLFSSL_CBIO_ERR_TIMEOUTby callingDtls13RtxTimeout(), which sends a DTLS 1.3 ACK or retransmits the last flight.On a non-blocking transport that send can return
WANT_WRITE, but the branchtested only
< 0and returnedWOLFSSL_FATAL_ERROR— the application saw a deadconnection where it should have seen "wait for writability and call again". The
source carried
/* TODO: support WANT_WRITE here */from the commit that addedthe branch.
wolfSSL_dtls_got_timeout()already handled the identical return correctly, sothe two ways of driving a DTLS 1.3 timeout disagreed.
Reachable through both supported IO paths: a custom recv callback returning
WOLFSSL_CBIO_ERR_TIMEOUTpaired with a send callback returningWOLFSSL_CBIO_ERR_WANT_WRITE, and the built-inEmbedReceiveFrom()timeoutpaths (
dtls_timeoutaccounting,SO_RCVTIMEO).Closes f-13343.
Fix (
src/internal.c)wolfSSLReceive()captures the result.WANT_WRITEsetsdtls13SendingAckOrRtx, marking the record as still owing a write, andreturns
WANT_WRITE; a genuine failure still returnsWOLFSSL_FATAL_ERROR.GetInputData_ex()passesWANT_WRITEthrough rather than folding it intoSOCKET_ERROR_E, under#ifdef WOLFSSL_DTLS13.Both are required:
WANT_WRITEis-327, so without the second hunk the firstis rewritten to
SOCKET_ERROR_Ein the next frame.Nothing above needed changing.
DoProcessReplyEx()already permitsWANT_WRITEas a retry state,
ReceiveData()already exempts it from its error-state guard,and the connect/accept flush and
wolfSSL_dtls13_do_scheduled_work()alreadysettle the owed record off
dtls13SendingAckOrRtx.Tests
test_dtls13_rtx_timeout_want_writewolfSSL_connect()reportsWANT_WRITE; the retry sends the retransmissiontest_dtls13_rtx_timeout_want_write_readwolfSSL_read()reports it,wolfSSL_dtls13_pending_work()reports the debt, the pump sends itVerification
dtls1322/22,dtls82/82, full API 676 passed / 0 failed,make check0 failed.--disable-dtlsand--enable-dtls --disable-dtls13; the newtests skip rather than fail there.
Not in this PR
Two sites mishandle the widened return only on record-spanning transports (SCTP
or
WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS), unreachable on plain UDP:GetDtlsRecordHeader()foldsWANT_WRITEintoLENGTH_ERROR, andDtlsShouldDrop()drops it post-handshake. That filter already foldsWANT_READthe same way, so all three belong together in a follow-up.