* [FFmpeg-devel] [PATCH] avformat/whip: add ICE consent freshness support (PR #20482)
@ 2025-09-10 8:08 Jack Lau via ffmpeg-devel
0 siblings, 0 replies; only message in thread
From: Jack Lau via ffmpeg-devel @ 2025-09-10 8:08 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Jack Lau
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
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2025-09-10 8:08 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-10 8:08 [FFmpeg-devel] [PATCH] avformat/whip: add ICE consent freshness support (PR #20482) Jack Lau via ffmpeg-devel
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