From: Jack Lau via ffmpeg-devel <ffmpeg-devel@ffmpeg.org> To: ffmpeg-devel@ffmpeg.org Cc: Jack Lau <code@ffmpeg.org> Subject: [FFmpeg-devel] [PATCH] avformat/whip: add ICE consent freshness support (PR #20482) Date: Wed, 10 Sep 2025 08:08:09 -0000 Message-ID: <175749169039.25.1792615083287656948@463a07221176> (raw) PR #20482 opened by Jack Lau (JackLau) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20482 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20482.patch Refer to RFC 9725 4.2, "Once a session is set up, consent freshness as per [RFC7675] SHALL be used to detect non-graceful disconnection by full ICE implementations and DTLS teardown for session termination by either side" Refer to RFC 7675, send STUN Binding request every 5s, expire consent after 30s without response, terminate session when the consent expired. TODO: Random consent check interval (4-6s) will be added later. Co-authored-by: Sergio Garcia Murillo <sergio.garcia.murillo@gmail.com> Signed-off-by: Jack Lau <jacklau1222@qq.com> >From 456f08ce82d1a1af3e03d9296f48e9b88a133a57 Mon Sep 17 00:00:00 2001 From: Jack Lau <jacklau1222@qq.com> Date: Wed, 10 Sep 2025 15:53:25 +0800 Subject: [PATCH 1/2] avformat/whip: add WHIP_US_PER_MS macro to replace 1000 Signed-off-by: Jack Lau <jacklau1222@qq.com> --- libavformat/whip.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/whip.c b/libavformat/whip.c index 20db03a239..ef5890fc7d 100644 --- a/libavformat/whip.c +++ b/libavformat/whip.c @@ -66,6 +66,8 @@ */ #define DTLS_SRTP_CHECKSUM_LEN 16 +#define WHIP_US_PER_MS 1000 + /** * When sending ICE or DTLS messages, responses are received via UDP. However, the peer * may not be ready and return EAGAIN, in which case we should wait for a short duration @@ -1251,7 +1253,7 @@ next_packet: break; now = av_gettime_relative(); - if (now - starttime >= whip->handshake_timeout * 1000) { + if (now - starttime >= whip->handshake_timeout * WHIP_US_PER_MS) { av_log(whip, AV_LOG_ERROR, "DTLS handshake timeout=%dms, cost=%.2fms, elapsed=%.2fms, state=%d\n", whip->handshake_timeout, ELAPSED(starttime, now), ELAPSED(whip->whip_starttime, now), whip->state); ret = AVERROR(ETIMEDOUT); @@ -1264,7 +1266,7 @@ next_packet: if (ret > 0) break; if (ret == AVERROR(EAGAIN)) { - av_usleep(5 * 1000); + av_usleep(5 * WHIP_US_PER_MS); continue; } av_log(whip, AV_LOG_ERROR, "Failed to read message\n"); -- 2.49.1 >From f84805f59cb1d515a8492d64b5c15c02bc39263b Mon Sep 17 00:00:00 2001 From: Jack Lau <jacklau1222@qq.com> Date: Wed, 10 Sep 2025 15:26:22 +0800 Subject: [PATCH 2/2] avformat/whip: add ICE consent freshness support Refer to RFC 9725 4.2, "Once a session is set up, consent freshness as per [RFC7675] SHALL be used to detect non-graceful disconnection by full ICE implementations and DTLS teardown for session termination by either side" Refer to RFC 7675, send STUN Binding request every 5s, expire consent after 30s without response, terminate session when the consent expired. TODO: Random consent check interval (4-6s) will be added later. Co-authored-by: Sergio Garcia Murillo <sergio.garcia.murillo@gmail.com> Signed-off-by: Jack Lau <jacklau1222@qq.com> --- libavformat/whip.c | 49 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/libavformat/whip.c b/libavformat/whip.c index ef5890fc7d..e10c3cacd1 100644 --- a/libavformat/whip.c +++ b/libavformat/whip.c @@ -159,6 +159,17 @@ #define WHIP_SDP_SESSION_ID "4489045141692799359" #define WHIP_SDP_CREATOR_IP "127.0.0.1" +/** + * Refer to RFC 7675 5.1, + * + * To prevent expiry of consent, a STUN binding request can be sent periodically. + * Implementations SHOULD set a default interval of 5 seconds(5000ms). + * + * Consent expires after 30 seconds(30000ms). + */ +#define WHIP_ICE_CONSENT_CHECK_INTERVAL 5000 +#define WHIP_ICE_CONSENT_EXPIRED_TIMER 30000 + /* Calculate the elapsed time from starttime to endtime in milliseconds. */ #define ELAPSED(starttime, endtime) ((float)(endtime - starttime) / 1000) @@ -269,6 +280,8 @@ typedef struct WHIPContext { int64_t whip_ice_time; int64_t whip_dtls_time; int64_t whip_srtp_time; + int64_t whip_last_consent_tx_time; + int64_t whip_last_consent_rx_time; /* The certificate and private key content used for DTLS handshake */ char cert_buf[MAX_CERTIFICATE_SIZE]; @@ -1320,6 +1333,8 @@ next_packet: /* If got any DTLS messages, handle it. */ if (is_dtls_packet(whip->buf, ret) && whip->state >= WHIP_STATE_ICE_CONNECTED || whip->state == WHIP_STATE_DTLS_CONNECTING) { + /* Start consent timer when ICE selected */ + whip->whip_last_consent_tx_time = whip->whip_last_consent_rx_time = av_gettime_relative(); whip->state = WHIP_STATE_DTLS_CONNECTING; ret = ffurl_handshake(whip->dtls_uc); if (ret < 0) { @@ -1787,8 +1802,26 @@ static int whip_write_packet(AVFormatContext *s, AVPacket *pkt) WHIPContext *whip = s->priv_data; AVStream *st = s->streams[pkt->stream_index]; AVFormatContext *rtp_ctx = st->priv_data; - - /* TODO: Send binding request every 1s as WebRTC heartbeat. */ + int64_t now = av_gettime_relative(); + /** + * Refer to RFC 7675 + * Periodically send Consent Freshness STUN Binding Request + */ + if (now - whip->whip_last_consent_tx_time > WHIP_ICE_CONSENT_CHECK_INTERVAL * WHIP_US_PER_MS) { + int size; + ret = ice_create_request(s, whip->buf, sizeof(whip->buf), &size); + if (ret < 0) { + av_log(whip, AV_LOG_ERROR, "Failed to create STUN binding request, size=%d\n", size); + goto end; + } + ret = ffurl_write(whip->udp, whip->buf, size); + if (ret < 0) { + av_log(whip, AV_LOG_ERROR, "Failed to send STUN binding request, size=%d\n", size); + goto end; + } + whip->whip_last_consent_tx_time = now; + av_log(whip, AV_LOG_DEBUG, "Consent Freshness check sent\n"); + } /** * Receive packets from the server such as ICE binding requests, DTLS messages, @@ -1805,6 +1838,10 @@ static int whip_write_packet(AVFormatContext *s, AVPacket *pkt) av_log(whip, AV_LOG_ERROR, "Receive EOF from UDP socket\n"); goto end; } + if (ice_is_binding_response(whip->buf, ret)) { + whip->whip_last_consent_rx_time = av_gettime_relative(); + av_log(whip, AV_LOG_DEBUG, "Consent Freshness check received\n"); + } if (is_dtls_packet(whip->buf, ret)) { if ((ret = ffurl_write(whip->dtls_uc, whip->buf, ret)) < 0) { av_log(whip, AV_LOG_ERROR, "Failed to handle DTLS message\n"); @@ -1812,6 +1849,14 @@ static int whip_write_packet(AVFormatContext *s, AVPacket *pkt) } } write_packet: + now = av_gettime_relative(); + if (now - whip->whip_last_consent_rx_time > WHIP_ICE_CONSENT_EXPIRED_TIMER * WHIP_US_PER_MS) { + av_log(whip, AV_LOG_ERROR, + "Consent Freshness expired after %.2fms (limted %dms), terminate session\n", + ELAPSED(now, whip->whip_last_consent_rx_time), WHIP_ICE_CONSENT_EXPIRED_TIMER); + ret = AVERROR(ETIMEDOUT); + goto end; + } if (whip->h264_annexb_insert_sps_pps && st->codecpar->codec_id == AV_CODEC_ID_H264) { if ((ret = h264_annexb_insert_sps_pps(s, pkt)) < 0) { av_log(whip, AV_LOG_ERROR, "Failed to insert SPS/PPS before IDR\n"); -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org
reply other threads:[~2025-09-10 8:08 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=175749169039.25.1792615083287656948@463a07221176 \ --to=ffmpeg-devel@ffmpeg.org \ --cc=code@ffmpeg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git