PR #24809 opened by Bruno Bezerra Trigueiro (kobzar) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24809 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24809.patch
# Summary of changes With -prefer_libcurl 1, HLS/DASH/IMF segments are opened with libcurl's defaults for -http_version, -tls_verify and -ca_file, because ffio_copy_url_options() doesn't copy them from the playlist connection. The client certificate (-cert_file/-key_file) is lost the same way. Adding the names to the list, as suggested in the issue, breaks two cases, so http_version is handled separately: - native http has a read-only `http_version` option holding the response version. Copying it makes every segment open fail with `Error setting option http_version to value 1.1`, so plain HLS over native http stops working. - libcurl's `http_version` is an INT and av_opt_get() prints the number, which parses back as a constant name: 1.1 (2) becomes "2" (HTTP/2) and 2 (3) becomes "3" (HTTP/3). It is copied by constant name instead, and only when prefer_libcurl is set, since with a `libcurl:` prefix the segments go through native http. Tested with a local HLS server that logs each request line, over http, https with a private CA, and https requiring a client certificate: - `-prefer_libcurl 1 -http_version 1.0/1.1/2`: segments use the same version as the playlist (1.1 without an h2c upgrade, 2 with one). - `-tls_verify 0`, `-ca_file`, `-cert_file`/`-key_file`: segments open; before they failed. - AES-128 playlist: the key request gets the version too. - plain native HLS and `libcurl:` URLs behave as before. - FATE hls/dash/imf/url tests pass for each commit. This touches the same list as #24565. With both applied, `-tls_verify 0` and `-ca_file` also reach the segments of a native https playlist, which currently fail with `certificate verify failed`. libcurl's default protocol whitelist (`http,https,libcurl`) doesn't include `crypto`, so AES-128 HLS with -prefer_libcurl 1 still fails unless -protocol_whitelist is given. I left that for a separate change. Fixes: #24752 cc @kasper93 @haasn >From d224fff64e65573e3111a98d7d52c2ed00eda447 Mon Sep 17 00:00:00 2001 From: Bruno Trigueiro <[email protected]> Date: Wed, 30 Sep 2026 09:25:51 -0300 Subject: [PATCH 1/2] avformat/aviobuf: copy http_version, tls_verify and ca_file to children HLS, DASH and IMF open their segment connections with the options ffio_copy_url_options() copies from the playlist connection. With -prefer_libcurl 1 the segments used libcurl's default HTTP version and TLS settings, whatever -http_version, -tls_verify or -ca_file were set to. Add tls_verify and ca_file to the list. Native http does not expose the options of its tls child, so nothing changes when the playlist comes from native https. http_version needs more care. Native http has a read-only option of that name holding the response version, and setting it on a segment connection makes the open fail. libcurl's option is an INT whose named constants overlap with its values ("1.1" is 2, which reads back as the "2" constant), so copy it by constant name, and only when prefer_libcurl is set: with an explicit libcurl: prefix the segments are opened by native http. Fixes: #24752 Signed-off-by: Bruno Trigueiro <[email protected]> --- libavformat/aviobuf.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index edbbc5ffd6..3a706b543e 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -950,10 +950,36 @@ void ffio_write_lines(AVIOContext *s, const unsigned char *buf, int size, } } +/* Native http has a read-only option of the same name, so only libcurl children + * get it. The numeric value would parse as another constant ("1.1" is 2). */ +static int copy_http_version(AVIOContext *pb, AVDictionary **avio_opts) +{ + const AVOption *o, *c = NULL; + int64_t prefer_libcurl, version; + void *target; + + o = av_opt_find2(pb, "http_version", NULL, 0, AV_OPT_SEARCH_CHILDREN, &target); + if (!o || !target || o->type != AV_OPT_TYPE_INT || !o->unit || + o->flags & AV_OPT_FLAG_READONLY) + return 0; + if (av_opt_get_int(pb, "prefer_libcurl", AV_OPT_SEARCH_CHILDREN, &prefer_libcurl) < 0 || + !prefer_libcurl || + av_opt_get_int(target, "http_version", 0, &version) < 0) + return 0; + + while ((c = av_opt_next(target, c))) + if (c->type == AV_OPT_TYPE_CONST && c->unit && !strcmp(c->unit, o->unit) && + c->default_val.i64 == version) + return av_dict_set(avio_opts, "http_version", c->name, 0); + + return av_dict_set_int(avio_opts, "http_version", version, 0); +} + int ffio_copy_url_options(AVIOContext* pb, AVDictionary** avio_opts) { const char *opts[] = { - "headers", "user_agent", "cookies", "http_proxy", "referer", "rw_timeout", "icy", "prefer_libcurl", NULL }; + "headers", "user_agent", "cookies", "http_proxy", "referer", "rw_timeout", "icy", "prefer_libcurl", + "tls_verify", "ca_file", NULL }; const char **opt = opts; uint8_t *buf = NULL; int ret = 0; @@ -971,7 +997,7 @@ int ffio_copy_url_options(AVIOContext* pb, AVDictionary** avio_opts) opt++; } - return ret; + return copy_http_version(pb, avio_opts); } static void update_checksum(AVIOContext *s) -- 2.52.0 >From 71a276525d2f324181ec4f7bcea9602efbc8b9ab Mon Sep 17 00:00:00 2001 From: Bruno Trigueiro <[email protected]> Date: Wed, 30 Sep 2026 09:25:51 -0300 Subject: [PATCH 2/2] avformat/aviobuf: copy cert_file and key_file to children With -prefer_libcurl 1 and a server that requires a client certificate, the playlist opened but every segment failed the TLS handshake, since the certificate and key were not passed on. Signed-off-by: Bruno Trigueiro <[email protected]> --- libavformat/aviobuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c index 3a706b543e..4d34819877 100644 --- a/libavformat/aviobuf.c +++ b/libavformat/aviobuf.c @@ -979,7 +979,7 @@ int ffio_copy_url_options(AVIOContext* pb, AVDictionary** avio_opts) { const char *opts[] = { "headers", "user_agent", "cookies", "http_proxy", "referer", "rw_timeout", "icy", "prefer_libcurl", - "tls_verify", "ca_file", NULL }; + "tls_verify", "ca_file", "cert_file", "key_file", NULL }; const char **opt = opts; uint8_t *buf = NULL; int ret = 0; -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
