Connecting to a TLS 1.3 wss server (e.g. behind Cloudflare/nginx) fails on the first response read with Failed reading HTTP status line. Windows/mbedtls backend, mbedtls 3.6+ (TLS 1.3 on by default).
Cause: In TLS 1.3 the server sends NewSessionTicket after the handshake. mbedtls_ssl_read then returns MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET (-0x7B00), a non-fatal "read again" code.
SocketMbedTLS::recv treats it as fatal and readByte aborts. Same for MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA.
Secondary (Windows only): on WANT_READ, recv/send set the CRT errno, but Socket::getErrno() reads WSAGetLastError().
The value is invisible, so isWaitNeeded() aborts a legitimate would-block.
Fix? (IXSocketMbedTLS.cpp, recv, the while(true) already allows the retry):
if (res > 0) return res;
// TLS 1.3: swallow post-handshake NewSessionTicket / early-data (non-fatal).
#if defined(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET)
if (res == MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET) continue;
#endif
#if defined(MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA)
if (res == MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA) continue;
#endif
if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE) {
errno = EWOULDBLOCK;
#ifdef _WIN32
WSASetLastError(WSAEWOULDBLOCK); // getErrno() reads WSAGetLastError() on Windows
#endif
}
return -1;
Maybe also WSASetLastError(WSAEWOULDBLOCK) to send's want-read/write branch
See: Mbed-TLS/mbedtls#9223, Mbed-TLS/mbedtls#8749.
Connecting to a TLS 1.3 wss server (e.g. behind Cloudflare/nginx) fails on the first response read with
Failed reading HTTP status line. Windows/mbedtls backend, mbedtls 3.6+ (TLS 1.3 on by default).Cause: In TLS 1.3 the server sends
NewSessionTicketafter the handshake.mbedtls_ssl_readthen returnsMBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET(-0x7B00), a non-fatal "read again" code.SocketMbedTLS::recvtreats it as fatal andreadByteaborts. Same forMBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA.Secondary (Windows only): on
WANT_READ, recv/send set the CRT errno, butSocket::getErrno()readsWSAGetLastError().The value is invisible, so
isWaitNeeded()aborts a legitimate would-block.Fix? (
IXSocketMbedTLS.cpp,recv, thewhile(true)already allows the retry):Maybe also
WSASetLastError(WSAEWOULDBLOCK)to send's want-read/write branchSee: Mbed-TLS/mbedtls#9223, Mbed-TLS/mbedtls#8749.