From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 6A0764EE63 for ; Tue, 17 Feb 2026 22:50:43 +0000 (UTC) Authentication-Results: ffbox; dkim=fail (body hash mismatch (got b'WINRCQNKHeJ4blRNl6jftY9194u/mHymckielKljKRU=', expected b'B+xArKTx5Dec4OL/hxO1b+sYr9IZqWMzBDsPEzFskgI=')) header.d=ffmpeg.org header.i=@ffmpeg.org header.a=rsa-sha256 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1771368626; h=mime-version : to : date : message-id : reply-to : subject : list-id : list-archive : list-archive : list-help : list-owner : list-post : list-subscribe : list-unsubscribe : from : cc : content-type : content-transfer-encoding : from; bh=WINRCQNKHeJ4blRNl6jftY9194u/mHymckielKljKRU=; b=NwLr4CCyj2qZCcVJ5au7vTkRz81C3bR+tcmpohJRfJys44zohXT1+bKaxwAKd6LatFIc/ ihS18QEHEIRqDc9zM8EiIpmWl8hFwspWYLcKeI93ddLfxKYpbUvEeF6m9GzTJ5WqfxReVXJ hCroci/waWcHRN+4+HcM/vykCX+4l9upjHAtf4AVwxttHwMb2SEB2a0fiaCPa9xOwq368MP mI5jDYNYfQqKzobHHVEDgppFzgvNoKYEUTrJ260Cxrund6QQ4s6JIcyQL2sGmb3h0/cf3SN T3muc/oVH8dTbCCiY5hcpPRGKza2b4zhozWtl1MLAW0I6aDYnwkrl4WQCIxw== Received: from [172.18.0.3] (unknown [172.18.0.3]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id 52D3D6911AD; Wed, 18 Feb 2026 00:50:26 +0200 (EET) ARC-Seal: i=1; cv=none; a=rsa-sha256; d=ffmpeg.org; s=arc; t=1771368611; b=FE3q3hhgYCxwrHYcFl2jKDkVlZ7oeyYGmWF9W79tj8NvrTxeh+avxoh5vGQBC4b4sEWVU RgOwaVGEuIEwm71Yx2/Y46I8y22ntKUJaiuMhj04iF5F8aUUzYqRgouGX8rm/YX1W+pt4Zc ++Qrm2jxno1FedAi6Ip4K92cTNF+U7NBDYJyZ1VUSApPlBOqO2p6Qx21+NuKNWBHaqJ1tr6 E7Lttfjnxi6d9DQFH2cuk84E33spfzYygPnhiXAysClb/c+em2HpYq/oak2YxXNGGdv4EJ8 2DKuM4RUwu3hpmIUEO7Y/vPU+ZhA/4m/uCvi9nhu/W6rFVlFmgikdf5C3TOw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=ffmpeg.org; s=arc; t=1771368611; h=from : sender : reply-to : subject : date : message-id : to : cc : mime-version : content-type : content-transfer-encoding : content-id : content-description : resent-date : resent-from : resent-sender : resent-to : resent-cc : resent-message-id : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; bh=ZXpoqUq6hjGT5eZja+lrvPIK1YOQN5hNB6aweGQow74=; b=fN4CPWO54oLkm49P9Xs0TUimThgcbCHgDgmeefEANBgZSR02FgBqkZJtM0YxgOJNxxk+a gq0vUKez9dHr0p74nwYdaEAK7l0Y4++OBGHckGslsp6S1/VjzW3A0BHcmgkqiwDTmL//Bxc sK2bENGEbFVCSftLywRh7dVR3VnEyi2e8n0ROsrob7eC5Aow0iDeUnVPtJwDZ5S5RZ68jiO ZLzajk7mc//8lo5THLiLdCkB6ZFwHPHVpqx1SByLPQOJ95pV9VfoKWpjtBRAWVu6Vkr0ZL0 iXWh0b00JYYPjFfEj/IU1GbNEfOSOYQrPdpo4h6OAHRXjg/y2uQ4sN9XGy8A== ARC-Authentication-Results: i=1; ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none; dmarc=pass header.from=ffmpeg.org policy.dmarc=quarantine Authentication-Results: ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none (Message is not ARC signed); dmarc=pass (Used From Domain Record) header.from=ffmpeg.org policy.dmarc=quarantine DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1771368602; h=content-type : mime-version : content-transfer-encoding : from : to : reply-to : subject : date : from; bh=B+xArKTx5Dec4OL/hxO1b+sYr9IZqWMzBDsPEzFskgI=; b=Xc+oTID8CoRkp3LASvnjP+Tu8hMMF/5eazrM7EBBHaNtsklposirOiV2OiPi6dLM68KqK wxvwysI64YUQAvT8ycC+4jAz3+9gaUFaHRbGExWTXR9WPEUlfX6ZLRB6pfj37kUQxNMsCOp ahcrtflJkm0Bub5nz9zOojGyQy6LsEkYWawPxCyLFq6s4eGH5GKlio8AlI5RA9SAOoLhbMD lk2HJc0HFQuE6hq2toHTBknDQ8NxmnrujB6lTZLFmStBq7jczmc46csvIZR9CyAI73FceXg 0J8czVSx8vqZl6YYpBPC3KbBJ9eUnPuGIVZ4S8CUTx0x4zjJymVZPVnkcjOQ== Received: from c8d966988b92 (code.ffmpeg.org [188.245.149.3]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id CA9B7691187 for ; Wed, 18 Feb 2026 00:50:02 +0200 (EET) MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Date: Tue, 17 Feb 2026 22:50:02 -0000 Message-ID: <177136860293.25.1074522917323863801@29965ddac10e> Message-ID-Hash: SVXAMTJTAIMBSCQILMFNJPI5MIXNAAGJ X-Message-ID-Hash: SVXAMTJTAIMBSCQILMFNJPI5MIXNAAGJ X-MailFrom: code@ffmpeg.org X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-ffmpeg-devel.ffmpeg.org-0; header-match-ffmpeg-devel.ffmpeg.org-1; header-match-ffmpeg-devel.ffmpeg.org-2; header-match-ffmpeg-devel.ffmpeg.org-3; emergency; member-moderation X-Mailman-Version: 3.3.10 Precedence: list Reply-To: FFmpeg development discussions and patches Subject: [FFmpeg-devel] [PR] avformat/tls_openssl: fix DTLS handshake retransmission in non-blocking mode (PR #21777) List-Id: FFmpeg development discussions and patches Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Nariman-Sayed via ffmpeg-devel Cc: Nariman-Sayed Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Archived-At: List-Archive: List-Post: PR #21777 opened by Nariman-Sayed URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21777 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21777.patch Switch from blocking to non-blocking mode to properly handle DTLS handshake retransmissions when packets are lost. Key changes: - Enable AVIO_FLAG_NONBLOCK on UDP socket for DTLS connections - Implement retry loop with poll() to wait for socket readiness - Use DTLSv1_get_timeout() to get proper timeout from OpenSSL - Call DTLSv1_handle_timeout() to trigger retransmissions on timeout - Handle SSL_ERROR_WANT_READ/WRITE correctly in non-blocking mode >>From 9144a430e6ea89ad5199b679faf0b8ef1155145f Mon Sep 17 00:00:00 2001 From: Nariman-Sayed Date: Wed, 11 Feb 2026 23:20:08 +0000 Subject: [PATCH 1/3] avformat/tls_openssl: Improve DTLS handshake retry logic This PR implements a proper retry loop for the DTLS handshake using `poll()` to handle timeouts and retransmissions correctly. Key changes: * Added a `while (1)` loop around `SSL_do_handshake` for DTLS connections. * Integrated `poll()` with a 100ms timeout to wait for socket readiness before retrying. * Correctly handles `SSL_ERROR_WANT_READ` and `SSL_ERROR_WANT_WRITE`. * Preserved all original file formatting, headers, and labels (such as `end:`) to avoid unnecessary changes. This version supersedes my previous PR and addresses all formatting feedback provided by @JackLau. Signed-off-by: Nariman-Sayed --- libavformat/tls_openssl.c | 58 ++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c index c7d6ff6cf4..aa7a7a3f95 100644 --- a/libavformat/tls_openssl.c +++ b/libavformat/tls_openssl.c @@ -33,6 +33,13 @@ #include #include +#include "libavformat/network.h" +#include "libavformat/url.h" +#include "libavutil/time.h" +#include +#if HAVE_POLL_H +#include +#endif /** * Convert an EVP_PKEY to a PEM string. */ @@ -630,24 +637,61 @@ static int dtls_handshake(URLContext *h) c->tls_shared.udp->flags &= ~AVIO_FLAG_NONBLOCK; - r0 = SSL_do_handshake(c->ssl); - if (r0 <= 0) { + while (1) { + r0 = SSL_do_handshake(c->ssl); + if (r0 > 0) { + av_log(c, AV_LOG_TRACE, "Handshake success, r0=%d\n", r0); + break; + } + r1 = SSL_get_error(c->ssl, r0); - if (r1 != SSL_ERROR_WANT_READ && r1 != SSL_ERROR_WANT_WRITE && r1 != SSL_ERROR_ZERO_RETURN) { + if (r1 == SSL_ERROR_WANT_READ || r1 == SSL_ERROR_WANT_WRITE) { +#if HAVE_POLL_H + struct pollfd p; + struct timeval tv; + int timeout_ms = 100; + int fd = ffurl_get_file_handle(c->tls_shared.udp); + int r; + + if (DTLSv1_get_timeout(c->ssl, &tv)) + timeout_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000; + + if (timeout_ms <= 0) + timeout_ms = 100; + + p.fd = fd; + p.events = (r1 == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT; + + r = poll(&p, 1, timeout_ms); + if (r == 0) { + DTLSv1_handle_timeout(c->ssl); + continue; + } + else if (r < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + ret = AVERROR(errno); + goto end; + } + continue; +#else + goto end; +#endif + } + + if (r1 != SSL_ERROR_ZERO_RETURN) { av_log(c, AV_LOG_ERROR, "Handshake failed, r0=%d, r1=%d\n", r0, r1); ret = print_ssl_error(h, r0); - goto end; } - } else { - av_log(c, AV_LOG_TRACE, "Handshake success, r0=%d\n", r0); + goto end; } - /* Check whether the handshake is completed. */ if (SSL_is_init_finished(c->ssl) != TLS_ST_OK) goto end; ret = 0; + end: return ret; } -- 2.52.0 >>From ff8702405d2133639737d187b4691493471f6616 Mon Sep 17 00:00:00 2001 From: Nariman-Sayed Date: Thu, 12 Feb 2026 03:41:04 +0000 Subject: [PATCH 2/3] avformat/tls_openssl: fix DTLS handshake timeout handling The DTLS handshake could fail or hang indefinitely when packets are lost or delayed, as there was no proper retry mechanism with timeout handling. This commit implements a proper retry loop using poll() to handle timeouts and retransmissions correctly. Key changes: - Added a while(1) loop around SSL_do_handshake for DTLS connections - Integrated poll() with timeout to wait for socket readiness - Properly handles SSL_ERROR_WANT_READ and SSL_ERROR_WANT_WRITE - Calls DTLSv1_handle_timeout() when poll() times out Addresses review feedback from @JackLau. Signed-off-by: Nariman-Sayed --- libavformat/tls_openssl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c index aa7a7a3f95..ee84e87f33 100644 --- a/libavformat/tls_openssl.c +++ b/libavformat/tls_openssl.c @@ -643,7 +643,7 @@ static int dtls_handshake(URLContext *h) av_log(c, AV_LOG_TRACE, "Handshake success, r0=%d\n", r0); break; } - + /* Check whether the handshake is completed. */ r1 = SSL_get_error(c->ssl, r0); if (r1 == SSL_ERROR_WANT_READ || r1 == SSL_ERROR_WANT_WRITE) { @@ -691,7 +691,6 @@ static int dtls_handshake(URLContext *h) goto end; ret = 0; - end: return ret; } -- 2.52.0 >>From ba29586e0e72f7f64ed3605ae1e1eb783b65eed3 Mon Sep 17 00:00:00 2001 From: Nariman-Sayed Date: Sun, 15 Feb 2026 12:53:56 +0000 Subject: [PATCH 3/3] avformat/tls_openssl: Use non-blocking mode for DTLS handshake retry Switch from blocking to non-blocking mode to properly handle DTLS handshake retransmissions when packets are lost. Key changes: - Enable AVIO_FLAG_NONBLOCK on UDP socket for DTLS connections - Implement retry loop with poll() to wait for socket readiness - Use DTLSv1_get_timeout() to get proper timeout from OpenSSL - Call DTLSv1_handle_timeout() to trigger retransmissions on timeout - Handle SSL_ERROR_WANT_READ/WRITE correctly in non-blocking mode Signed-off-by: Nariman-Sayed --- libavformat/tls_openssl.c | 77 +++++++++++++++------------------------ 1 file changed, 29 insertions(+), 48 deletions(-) diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c index ee84e87f33..bbc01c7d75 100644 --- a/libavformat/tls_openssl.c +++ b/libavformat/tls_openssl.c @@ -632,67 +632,48 @@ static void openssl_info_callback(const SSL *ssl, int where, int ret) { static int dtls_handshake(URLContext *h) { - int ret = 1, r0, r1; TLSContext *c = h->priv_data; + int ret, err; - c->tls_shared.udp->flags &= ~AVIO_FLAG_NONBLOCK; + struct pollfd pfd; + pfd.fd = ffurl_get_file_handle(c->tls_shared.udp); + pfd.events = POLLIN; + pfd.revents = 0; - while (1) { - r0 = SSL_do_handshake(c->ssl); - if (r0 > 0) { - av_log(c, AV_LOG_TRACE, "Handshake success, r0=%d\n", r0); - break; - } - /* Check whether the handshake is completed. */ - r1 = SSL_get_error(c->ssl, r0); + /* use nonblocking mode for DTLS retransmission */ + c->tls_shared.udp->flags |= AVIO_FLAG_NONBLOCK; - if (r1 == SSL_ERROR_WANT_READ || r1 == SSL_ERROR_WANT_WRITE) { -#if HAVE_POLL_H - struct pollfd p; - struct timeval tv; - int timeout_ms = 100; - int fd = ffurl_get_file_handle(c->tls_shared.udp); - int r; + for (;;) { + ret = SSL_do_handshake(c->ssl); + if (ret == 1) + return 0; - if (DTLSv1_get_timeout(c->ssl, &tv)) - timeout_ms = tv.tv_sec * 1000 + tv.tv_usec / 1000; + err = SSL_get_error(c->ssl, ret); - if (timeout_ms <= 0) - timeout_ms = 100; + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) { + struct timeval timeout; + int timeout_ms = 1000; - p.fd = fd; - p.events = (r1 == SSL_ERROR_WANT_READ) ? POLLIN : POLLOUT; + if (DTLSv1_get_timeout(c->ssl, &timeout)) + timeout_ms = timeout.tv_sec * 1000 + + timeout.tv_usec / 1000; - r = poll(&p, 1, timeout_ms); - if (r == 0) { - DTLSv1_handle_timeout(c->ssl); + ret = poll(&pfd, 1, timeout_ms); + if (ret > 0) { + if (pfd.revents & (POLLERR | POLLHUP)) + return AVERROR(EIO); continue; + } else if (ret == 0) { + if (DTLSv1_handle_timeout(c->ssl) < 0) + return AVERROR(EIO); + continue; + } else { + return AVERROR(errno); } - else if (r < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - ret = AVERROR(errno); - goto end; - } - continue; -#else - goto end; -#endif } - if (r1 != SSL_ERROR_ZERO_RETURN) { - av_log(c, AV_LOG_ERROR, "Handshake failed, r0=%d, r1=%d\n", r0, r1); - ret = print_ssl_error(h, r0); - } - goto end; + return AVERROR(EIO); } - - if (SSL_is_init_finished(c->ssl) != TLS_ST_OK) - goto end; - - ret = 0; -end: - return ret; } static av_cold int openssl_init_ca_key_cert(URLContext *h) -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org