|
143 | 143 | #define WHIP_RTCP_PT_START 192
|
144 | 144 | #define WHIP_RTCP_PT_END 223
|
145 | 145 |
|
| 146 | +/** |
| 147 | + * Consent-freshness constants |
| 148 | + */ |
| 149 | +#define WHIP_CONSENT_DEF_INTERVAL 15000 /* ms - RFC 7675 default */ |
| 150 | +#define WHIP_CONSENT_MAX_FAILURES 3 |
| 151 | + |
146 | 152 | /**
|
147 | 153 | * In the case of ICE-LITE, these fields are not used; instead, they are defined
|
148 | 154 | * as constant values.
|
@@ -303,6 +309,11 @@ typedef struct WHIPContext {
|
303 | 309 | /* The certificate and private key used for DTLS handshake. */
|
304 | 310 | char* cert_file;
|
305 | 311 | char* key_file;
|
| 312 | + |
| 313 | + /* Consent-freshness state */ |
| 314 | + int consent_interval; |
| 315 | + int64_t last_consent_tx; |
| 316 | + int consent_failures; |
306 | 317 | } WHIPContext;
|
307 | 318 |
|
308 | 319 | /**
|
@@ -417,6 +428,12 @@ static av_cold int initialize(AVFormatContext *s)
|
417 | 428 | seed = av_get_random_seed();
|
418 | 429 | av_lfg_init(&whip->rnd, seed);
|
419 | 430 |
|
| 431 | + /* Initialise consent-freshness timers */ |
| 432 | + if (whip->consent_interval <= 0) |
| 433 | + whip->consent_interval = WHIP_CONSENT_DEF_INTERVAL; |
| 434 | + whip->last_consent_tx = av_gettime(); |
| 435 | + whip->consent_failures = 0; |
| 436 | + |
420 | 437 | if (whip->pkt_size < ideal_pkt_size)
|
421 | 438 | av_log(whip, AV_LOG_WARNING, "pkt_size=%d(<%d) is too small, may cause packet loss\n",
|
422 | 439 | whip->pkt_size, ideal_pkt_size);
|
@@ -1784,14 +1801,27 @@ static int whip_write_packet(AVFormatContext *s, AVPacket *pkt)
|
1784 | 1801 | AVStream *st = s->streams[pkt->stream_index];
|
1785 | 1802 | AVFormatContext *rtp_ctx = st->priv_data;
|
1786 | 1803 |
|
1787 |
| - /* TODO: Send binding request every 1s as WebRTC heartbeat. */ |
| 1804 | + /* Periodic consent-freshness STUN Binding Request */ |
| 1805 | + int64_t now = av_gettime(); |
| 1806 | + if (now - whip->last_consent_tx >= (int64_t)whip->consent_interval * 1000) { |
| 1807 | + int req_sz; |
| 1808 | + if (ice_create_request(s, whip->buf, sizeof(whip->buf), &req_sz) >= 0 && ffurl_write(whip->udp, whip->buf, req_sz) == req_sz) { |
| 1809 | + whip->consent_failures++; |
| 1810 | + whip->last_consent_tx = now; |
| 1811 | + av_log(whip, AV_LOG_VERBOSE, "WHIP: consent-freshness request %d sent\n", whip->consent_failures); |
| 1812 | + } |
| 1813 | + } |
1788 | 1814 |
|
1789 | 1815 | /**
|
1790 | 1816 | * Receive packets from the server such as ICE binding requests, DTLS messages,
|
1791 | 1817 | * and RTCP like PLI requests, then respond to them.
|
1792 | 1818 | */
|
1793 | 1819 | ret = ffurl_read(whip->udp, whip->buf, sizeof(whip->buf));
|
1794 | 1820 | if (ret > 0) {
|
| 1821 | + if (ice_is_binding_response(whip->buf, ret)) { |
| 1822 | + whip->consent_failures = 0; |
| 1823 | + av_log(whip, AV_LOG_VERBOSE, "WHIP: consent-freshness response received, counter reset\n"); |
| 1824 | + } |
1795 | 1825 | if (is_dtls_packet(whip->buf, ret)) {
|
1796 | 1826 | if ((ret = ffurl_write(whip->dtls_uc, whip->buf, ret)) < 0) {
|
1797 | 1827 | av_log(whip, AV_LOG_ERROR, "Failed to handle DTLS message\n");
|
@@ -1901,6 +1931,7 @@ static const AVOption options[] = {
|
1901 | 1931 | { "authorization", "The optional Bearer token for WHIP Authorization", OFFSET(authorization), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, ENC },
|
1902 | 1932 | { "cert_file", "The optional certificate file path for DTLS", OFFSET(cert_file), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, ENC },
|
1903 | 1933 | { "key_file", "The optional private key file path for DTLS", OFFSET(key_file), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, ENC },
|
| 1934 | + { "consent_interval", "STUN consent refresh interval in ms (RFC 7675)", OFFSET(consent_interval), AV_OPT_TYPE_INT, { .i64 = WHIP_CONSENT_DEF_INTERVAL }, 5000, 30000, ENC }, |
1904 | 1935 | { NULL },
|
1905 | 1936 | };
|
1906 | 1937 |
|
|
0 commit comments