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 CDCA244B0D for ; Fri, 19 Sep 2025 19:08:17 +0000 (UTC) Authentication-Results: ffbox; dkim=fail (body hash mismatch (got b'EjR+/YAXY5MYE6i6HTmGqi9PIPgSXohpZ5OpediIz+Q=', expected b'lkZ//IfJ4drrk3F0zPP+YS7UOXj1G2ini4zm3iskCII=')) 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=1758308887; 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=EjR+/YAXY5MYE6i6HTmGqi9PIPgSXohpZ5OpediIz+Q=; b=JTEDh58bpK5d0W698O6aidtiVkZX/uKsrUnQLDClV7owbYJhRAJUzo29s3NZTwyTDT6Sr gaF6+TwGmWTZRN8UrvJ/d+FMuONkvSgqBm+yTPT8LhbhuDtdx63fNCgTm/rA1aw4g5S2oM2 ECK+1SI209lC7py+MWc5aNzV3vdaS3D8Nz7mWAXX6TwzPnBx7AYUT7FK03XugioogxiupBK cHNUnDoRGTBHVodEXT/SDTC9wZmLxnWz5ZhAiAEL9KpkGe1Zr1xB7lZNzzSMJY5gEfPGByC uRUNl28/jLsfmZxh5sSKJM1J9KisXrhrT0gvLGrZtD7SdBSShrgZZ8DMpC0w== Received: from [172.19.0.4] (unknown [172.19.0.4]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id E3F9868EB5C; Fri, 19 Sep 2025 22:08:07 +0300 (EEST) ARC-Seal: i=1; cv=none; a=rsa-sha256; d=ffmpeg.org; s=arc; t=1758308886; b=grINlIshpnyqUKuFvIYMCKaRPrVIYSQSv+5Aq1lNz3IRQ1Dg+67eRhu5qxzbbb9pdcpLo rxw35D32qBFDc95BxwSJitCOZr7gnuXLrkhFy5cmgs7ykTmKWf3cQTh2ohLWT1NVbadtxh0 nSLz6oqG88kWGFwrSNlUm5D0sPzTOBrouRnJZ1s+LjcOHvJEc3lc8aRyam4FkwAj3F4mahP qIjCIsxaf2FNZUepPeViCJYC4mMJOTHR1TM07IsJIMeC8ddYvOWFGr+gurbLvujjgQO3dz3 AkzAWlxarlvcu5yTytnXSo0O9ODwKCoT62VjUbE0m+IoWmGj9pDeQIMNqe7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=ffmpeg.org; s=arc; t=1758308886; 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=mDn6Z2l3HK4kusBwmFb9cjAc7/rJBQ+Mw5cCG9T3lOY=; b=mljfGDXuBMtjoLFsR4TAnTaHN3B3Bo3J3OVe1YIZUW9gixvbWrdcjB+OKnfxnN9S4E21O XA9hGdK+tNYrtsgjsHZs0lSzHnMRdEDFHppGzfjAX2F+8A0R/r6CQnC6ZjENl6E5fbzVjNF 4mAAJIu95aORyx4WCRHbG5sFAjRUL/TrwNQk4JFk9L5RoLR01u+imHnTqk1nrwlxV89a1es FIUc95jmgJTVPdfnoIJcYynhwgjsBwxUhRT4tR65mrxFPEihofkDGFSWtOuUgk5Y7WXSDRW XJ2eQew2QOVW0ebo+IYJEIQFmMQ96sklE/Y1Vd9enNWxYrmvsCPoC3jAK/lA== ARC-Authentication-Results: i=1; ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none; dmarc=none Authentication-Results: ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none (Message is not ARC signed); dmarc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1758308876; h=content-type : mime-version : content-transfer-encoding : from : to : reply-to : subject : date : from; bh=lkZ//IfJ4drrk3F0zPP+YS7UOXj1G2ini4zm3iskCII=; b=KgdL0GQck5W3tnVN5dJ7QHb/miIPLmoxIJfBzjYmyNWFdZNlEu0EjHMtKGPUuIti68ZsG D6CbL6Z4p33zNmuR604Z2q8eF7P1zSsET7W6T91JBPXDEpKqFSu81Gwgrm9f1qvgDdz4kQT juTnb+03Task8oP5RdUjrbCffO7SFv1nMDFDocsdWtWCgpxxqmZvB+Q2GxqAcxQIkA587k1 3rNSYzBj/n3EVg8hHF/ZevnT7w4tLooXAZeqMdR+LkdLOHJ1uYgsDU+zefyAebpN/Czspyf cso/GVaKjxT8ChBS/6rr80bUkPYXl8sSOWKSZPlapMEJjUKSL7n5bz4J77TQ== Received: from ed19c606a818 (code.ffmpeg.org [188.245.149.3]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id 6F93268EB48 for ; Fri, 19 Sep 2025 22:07:56 +0300 (EEST) MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Date: Fri, 19 Sep 2025 19:07:55 -0000 Message-ID: <175830887666.25.8540859823824875873@463a07221176> Message-ID-Hash: SBKHVJP6ERAZWLQU3ODY6GETV6JNTBR6 X-Message-ID-Hash: SBKHVJP6ERAZWLQU3ODY6GETV6JNTBR6 X-MailFrom: code@ffmpeg.org 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; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list Reply-To: FFmpeg development discussions and patches Subject: [FFmpeg-devel] [PATCH] Use AVOption calls to parse URL options (PR #20555) 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: Marton Balint via ffmpeg-devel Cc: Marton Balint Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Archived-At: List-Archive: List-Post: PR #20555 opened by Marton Balint (cus) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20555 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20555.patch This removes lots of parsing code duplications, unifies parsing rules and also enhances the documentation. Some notable changes, some of them slightly changes behaviour: - unconditional complication of urldecode.c - always doing URL decoding for URL option keys and values, previously URL decoding was only used in a few places - proper rejection of invalid option values - rejection of unknown options for libsrt and sctp. (other protocols might nest each other so unkown options can be OK) - supporting OPT_TYPE_BOOL options with no value (e.g. ?verify instead of ?verify=1), previously only a few boolean options were supported this way - the order of parsing AVOptions / URLOptions is unified, URL options now always override AVOptions, this mostly affects the TLS protocol - previously you could merge multicast sources from AVOptions and URLOptions, from now only one of those is parsed. >>From 016015b8ef97443c1a65617ff5603748abd1a512 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 26 Aug 2025 22:57:40 +0200 Subject: [PATCH 01/10] avformat/urldecode: add ff_urldecode_len function This will be used later to decode partial strings. Signed-off-by: Marton Balint --- libavformat/urldecode.c | 18 ++++++++++++++++++ libavformat/urldecode.h | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/libavformat/urldecode.c b/libavformat/urldecode.c index e7fa27b3fa..fdaa41784f 100644 --- a/libavformat/urldecode.c +++ b/libavformat/urldecode.c @@ -28,6 +28,8 @@ #include +#include "libavutil/error.h" +#include "libavutil/macros.h" #include "libavutil/mem.h" #include "libavutil/avstring.h" #include "urldecode.h" @@ -93,3 +95,19 @@ char *ff_urldecode(const char *url, int decode_plus_sign) return dest; } + +int ff_urldecode_len(char *dest, size_t dest_len, const char *url, size_t url_max_len, int decode_plus_sign) +{ + size_t written_bytes; + size_t url_len = strlen(url); + + url_len = FFMIN(url_len, url_max_len); + + if (dest_len <= url_len) + return AVERROR(EINVAL); + + written_bytes = urldecode(dest, url, url_len, decode_plus_sign); + dest[written_bytes] = '\0'; + + return written_bytes; +} diff --git a/libavformat/urldecode.h b/libavformat/urldecode.h index 80b11c3428..adca3e89a6 100644 --- a/libavformat/urldecode.h +++ b/libavformat/urldecode.h @@ -33,4 +33,20 @@ */ char *ff_urldecode(const char *url, int decode_plus_sign); +/** + * Decodes an URL from its percent-encoded form back into normal + * representation. This function returns the decoded URL in a string. + * The URL to be decoded does not necessarily have to be encoded but + * in that case the original string is duplicated. + * + * @param dest the destination buffer. + * @param dest_len the maximum available space in the destination buffer. + * Must be bigger than FFMIN(strlen(url), url_max_len) to avoid + * an AVERROR(EINVAL) result + * @param url_max_len the maximum number of chars to read from url + * @param decode_plus_sign if nonzero plus sign is decoded to space + * @return the number of written bytes to dest excluding the zero terminator, + * negative on error + */ +int ff_urldecode_len(char *dest, size_t dest_len, const char *url, size_t url_max_len, int decode_plus_sign); #endif /* AVFORMAT_URLDECODE_H */ -- 2.49.1 >>From 717ff1eb3823f88f74b19066a0377dcb167ad91b Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 26 Aug 2025 23:03:40 +0200 Subject: [PATCH 02/10] avformat: compile urldecode unconditionally It will be used by the generic helper function to set options from URLs. Signed-off-by: Marton Balint --- libavformat/Makefile | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/libavformat/Makefile b/libavformat/Makefile index ab5551a735..801a0b0330 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -28,6 +28,7 @@ OBJS = allformats.o \ sdp.o \ seek.o \ url.o \ + urldecode.o \ utils.o \ version.o \ @@ -536,10 +537,8 @@ OBJS-$(CONFIG_RTP_MUXER) += rtp.o \ rtpenc_vp8.o \ rtpenc_vp9.o \ rtpenc_xiph.o -OBJS-$(CONFIG_RTSP_DEMUXER) += rtsp.o rtspdec.o httpauth.o \ - urldecode.o -OBJS-$(CONFIG_RTSP_MUXER) += rtsp.o rtspenc.o httpauth.o \ - urldecode.o +OBJS-$(CONFIG_RTSP_DEMUXER) += rtsp.o rtspdec.o httpauth.o +OBJS-$(CONFIG_RTSP_MUXER) += rtsp.o rtspenc.o httpauth.o OBJS-$(CONFIG_S337M_DEMUXER) += s337m.o spdif.o OBJS-$(CONFIG_SAMI_DEMUXER) += samidec.o subtitles.o OBJS-$(CONFIG_SAP_DEMUXER) += sapdec.o @@ -684,13 +683,13 @@ OBJS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpcrypt.o rtmpdigest.o rtmpdh.o OBJS-$(CONFIG_FFRTMPHTTP_PROTOCOL) += rtmphttp.o OBJS-$(CONFIG_FILE_PROTOCOL) += file.o OBJS-$(CONFIG_FD_PROTOCOL) += file.o -OBJS-$(CONFIG_FTP_PROTOCOL) += ftp.o urldecode.o +OBJS-$(CONFIG_FTP_PROTOCOL) += ftp.o OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o OBJS-$(CONFIG_GOPHERS_PROTOCOL) += gopher.o OBJS-$(CONFIG_HLS_PROTOCOL) += hlsproto.o -OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o urldecode.o -OBJS-$(CONFIG_HTTPPROXY_PROTOCOL) += http.o httpauth.o urldecode.o -OBJS-$(CONFIG_HTTPS_PROTOCOL) += http.o httpauth.o urldecode.o +OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o +OBJS-$(CONFIG_HTTPPROXY_PROTOCOL) += http.o httpauth.o +OBJS-$(CONFIG_HTTPS_PROTOCOL) += http.o httpauth.o OBJS-$(CONFIG_ICECAST_PROTOCOL) += icecast.o OBJS-$(CONFIG_MD5_PROTOCOL) += md5proto.o OBJS-$(CONFIG_MMSH_PROTOCOL) += mmsh.o mms.o asf_tags.o @@ -724,7 +723,7 @@ OBJS-$(CONFIG_UDPLITE_PROTOCOL) += udp.o ip.o OBJS-$(CONFIG_UNIX_PROTOCOL) += unix.o # external library protocols -OBJS-$(CONFIG_LIBAMQP_PROTOCOL) += libamqp.o urldecode.o +OBJS-$(CONFIG_LIBAMQP_PROTOCOL) += libamqp.o OBJS-$(CONFIG_LIBRIST_PROTOCOL) += librist.o OBJS-$(CONFIG_LIBRTMP_PROTOCOL) += librtmp.o OBJS-$(CONFIG_LIBRTMPE_PROTOCOL) += librtmp.o @@ -732,7 +731,7 @@ OBJS-$(CONFIG_LIBRTMPS_PROTOCOL) += librtmp.o OBJS-$(CONFIG_LIBRTMPT_PROTOCOL) += librtmp.o OBJS-$(CONFIG_LIBRTMPTE_PROTOCOL) += librtmp.o OBJS-$(CONFIG_LIBSMBCLIENT_PROTOCOL) += libsmbclient.o -OBJS-$(CONFIG_LIBSRT_PROTOCOL) += libsrt.o urldecode.o +OBJS-$(CONFIG_LIBSRT_PROTOCOL) += libsrt.o OBJS-$(CONFIG_LIBSSH_PROTOCOL) += libssh.o OBJS-$(CONFIG_LIBZMQ_PROTOCOL) += libzmq.o -- 2.49.1 >>From 2c1295d878347a82e3cf4f06fe4462eae88a292a Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 25 Aug 2025 00:54:29 +0200 Subject: [PATCH 03/10] avformat/utils: add helper function to set opts from query string Signed-off-by: Marton Balint --- libavformat/internal.h | 12 ++++++++ libavformat/utils.c | 66 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/libavformat/internal.h b/libavformat/internal.h index 0dfbf02ca0..1a50ba07d3 100644 --- a/libavformat/internal.h +++ b/libavformat/internal.h @@ -649,4 +649,16 @@ int ff_bprint_get_frame_filename(struct AVBPrint *buf, const char *path, int64_t */ int ff_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestamp); +/** + * Set a list of query string options on an object. Only the objects own + * options will be set. + * + * @param obj the object to set options on + * @param str the query string + * @param allow_unknown ignore unknown query string options. This can be OK if + * nested protocols are used. + * @return <0 on error + */ +int ff_parse_opts_from_query_string(void *obj, const char *str, int allow_unkown); + #endif /* AVFORMAT_INTERNAL_H */ diff --git a/libavformat/utils.c b/libavformat/utils.c index 3573aa918e..a1af20cffb 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -25,10 +25,13 @@ #include "config.h" #include "libavutil/avstring.h" +#include "libavutil/avassert.h" #include "libavutil/bprint.h" #include "libavutil/dict.h" #include "libavutil/internal.h" #include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/parseutils.h" #include "libavutil/time.h" #include "libavutil/time_internal.h" @@ -41,6 +44,7 @@ #include "network.h" #endif #include "os_support.h" +#include "urldecode.h" /** * @file @@ -618,3 +622,65 @@ int ff_dict_set_timestamp(AVDictionary **dict, const char *key, int64_t timestam return AVERROR_EXTERNAL; } } + +static const AVOption* find_opt(void *obj, const char *name, size_t len) +{ + char decoded_name[128]; + + if (ff_urldecode_len(decoded_name, sizeof(decoded_name), name, len, 1) < 0) + return NULL; + + return av_opt_find(obj, decoded_name, NULL, 0, 0); +} + +int ff_parse_opts_from_query_string(void *obj, const char *str, int allow_unknown) +{ + const AVOption *opt; + char optval[512]; + int ret; + + if (*str == '?') + str++; + while (*str) { + size_t len = strcspn(str, "=&"); + opt = find_opt(obj, str, len); + if (!opt) { + if (!allow_unknown) { + av_log(obj, AV_LOG_ERROR, "Query string option '%.*s' does not exist\n", (int)len, str); + return AVERROR_OPTION_NOT_FOUND; + } + av_log(obj, AV_LOG_VERBOSE, "Ignoring unknown query string option '%.*s'\n", (int)len, str); + } + str += len; + if (!opt) { + len = strcspn(str, "&"); + str += len; + } else if (*str == '&' || *str == '\0') { + /* Check for bool options without value, e.g. "?verify". + * Unfortunately "listen" is a tri-state INT for some protocols so + * we also have to allow that for backward compatibility. */ + if (opt->type != AV_OPT_TYPE_BOOL && strcmp(opt->name, "listen")) { + av_log(obj, AV_LOG_ERROR, "Non-bool query string option '%s' has no value\n", opt->name); + return AVERROR(EINVAL); + } + ret = av_opt_set_int(obj, opt->name, 1, 0); + if (ret < 0) + return ret; + } else { + av_assert2(*str == '='); + str++; + len = strcspn(str, "&"); + if (ff_urldecode_len(optval, sizeof(optval), str, len, 1) < 0) { + av_log(obj, AV_LOG_ERROR, "Query string option '%s' value is too long\n", opt->name); + return AVERROR(EINVAL); + } + ret = av_opt_set(obj, opt->name, optval, 0); + if (ret < 0) + return ret; + str += len; + } + if (*str) + str++; + } + return 0; +} -- 2.49.1 >>From 6eca18b7a2217c673d7f0f6d4c182791aac02953 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 25 Aug 2025 01:50:13 +0200 Subject: [PATCH 04/10] avformat/libsrt: use ff_parse_opts_from_query_string() to set URL parameters Signed-off-by: Marton Balint --- doc/protocols.texi | 15 ++--- libavformat/libsrt.c | 142 +------------------------------------------ 2 files changed, 8 insertions(+), 149 deletions(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index cd0726cc7a..133574b4db 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1554,18 +1554,13 @@ srt://@var{hostname}:@var{port}[?@var{options}] @end example @var{options} contains a list of &-separated options of the form -@var{key}=@var{val}. +@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for +space) can be used to escape keys and values. -or +Options can also can be specified via command line options (or in code via +@code{AVOption}s). -@example -@var{options} srt://@var{hostname}:@var{port} -@end example - -@var{options} contains a list of '-@var{key} @var{val}' -options. - -This protocol accepts the following options. +The list of supported options follows. @table @option @item connect_timeout=@var{milliseconds} diff --git a/libavformat/libsrt.c b/libavformat/libsrt.c index 9e860abccd..ba04d9f782 100644 --- a/libavformat/libsrt.c +++ b/libavformat/libsrt.c @@ -386,8 +386,6 @@ static int libsrt_setup(URLContext *h, const char *uri, int flags) struct addrinfo hints = { 0 }, *ai, *cur_ai; int port, fd; SRTContext *s = h->priv_data; - const char *p; - char buf[256]; int ret; char hostname[1024],proto[1024],path[1024]; char portstr[10]; @@ -402,15 +400,6 @@ static int libsrt_setup(URLContext *h, const char *uri, int flags) av_log(h, AV_LOG_ERROR, "Port missing in uri\n"); return AVERROR(EINVAL); } - p = strchr(uri, '?'); - if (p) { - if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { - s->rw_timeout = strtoll(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { - s->listen_timeout = strtoll(buf, NULL, 10); - } - } if (s->rw_timeout >= 0) { open_timeout = h->rw_timeout = s->rw_timeout; } @@ -534,7 +523,6 @@ static int libsrt_open(URLContext *h, const char *uri, int flags) { SRTContext *s = h->priv_data; const char * p; - char buf[1024]; int ret = 0; if (srt_startup() < 0) { @@ -544,133 +532,9 @@ static int libsrt_open(URLContext *h, const char *uri, int flags) /* SRT options (srt/srt.h) */ p = strchr(uri, '?'); if (p) { - if (av_find_info_tag(buf, sizeof(buf), "maxbw", p)) { - s->maxbw = strtoll(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "pbkeylen", p)) { - s->pbkeylen = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "passphrase", p)) { - av_freep(&s->passphrase); - s->passphrase = ff_urldecode(buf, 1); - if (!s->passphrase) { - ret = AVERROR(ENOMEM); - goto err; - } - } -#if SRT_VERSION_VALUE >= 0x010302 - if (av_find_info_tag(buf, sizeof(buf), "enforced_encryption", p)) { - s->enforced_encryption = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "kmrefreshrate", p)) { - s->kmrefreshrate = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "kmpreannounce", p)) { - s->kmpreannounce = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "snddropdelay", p)) { - s->snddropdelay = strtoll(buf, NULL, 10); - } -#endif - if (av_find_info_tag(buf, sizeof(buf), "mss", p)) { - s->mss = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "ffs", p)) { - s->ffs = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "ipttl", p)) { - s->ipttl = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "iptos", p)) { - s->iptos = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "inputbw", p)) { - s->inputbw = strtoll(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "oheadbw", p)) { - s->oheadbw = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "latency", p)) { - s->latency = strtoll(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "tsbpddelay", p)) { - s->latency = strtoll(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "rcvlatency", p)) { - s->rcvlatency = strtoll(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "peerlatency", p)) { - s->peerlatency = strtoll(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "tlpktdrop", p)) { - s->tlpktdrop = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "nakreport", p)) { - s->nakreport = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "connect_timeout", p)) { - s->connect_timeout = strtoll(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "payload_size", p) || - av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) { - s->payload_size = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "mode", p)) { - if (!strcmp(buf, "caller")) { - s->mode = SRT_MODE_CALLER; - } else if (!strcmp(buf, "listener")) { - s->mode = SRT_MODE_LISTENER; - } else if (!strcmp(buf, "rendezvous")) { - s->mode = SRT_MODE_RENDEZVOUS; - } else { - ret = AVERROR(EINVAL); - goto err; - } - } - if (av_find_info_tag(buf, sizeof(buf), "sndbuf", p)) { - s->sndbuf = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "rcvbuf", p)) { - s->rcvbuf = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "lossmaxttl", p)) { - s->lossmaxttl = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "minversion", p)) { - s->minversion = strtol(buf, NULL, 0); - } - if (av_find_info_tag(buf, sizeof(buf), "streamid", p)) { - av_freep(&s->streamid); - s->streamid = ff_urldecode(buf, 1); - if (!s->streamid) { - ret = AVERROR(ENOMEM); - goto err; - } - } - if (av_find_info_tag(buf, sizeof(buf), "smoother", p)) { - av_freep(&s->smoother); - s->smoother = ff_urldecode(buf, 1); - if(!s->smoother) { - ret = AVERROR(ENOMEM); - goto err; - } - } - if (av_find_info_tag(buf, sizeof(buf), "messageapi", p)) { - s->messageapi = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "transtype", p)) { - if (!strcmp(buf, "live")) { - s->transtype = SRTT_LIVE; - } else if (!strcmp(buf, "file")) { - s->transtype = SRTT_FILE; - } else { - ret = AVERROR(EINVAL); - goto err; - } - } - if (av_find_info_tag(buf, sizeof(buf), "linger", p)) { - s->linger = strtol(buf, NULL, 10); - } + ret = ff_parse_opts_from_query_string(s, p, 0); + if (ret < 0) + goto err; } ret = libsrt_setup(h, uri, flags); if (ret < 0) -- 2.49.1 >>From bc5c0d24b3224170f898b8fc28e28c6277c1b145 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 25 Aug 2025 01:51:15 +0200 Subject: [PATCH 05/10] avformat/udp: use ff_parse_opts_from_query_string() to set URL parameters Signed-off-by: Marton Balint --- doc/protocols.texi | 7 +++- libavformat/udp.c | 93 +++++++--------------------------------------- 2 files changed, 19 insertions(+), 81 deletions(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index 133574b4db..b4b6c25579 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -2114,7 +2114,12 @@ The required syntax for an UDP URL is: udp://@var{hostname}:@var{port}[?@var{options}] @end example -@var{options} contains a list of &-separated options of the form @var{key}=@var{val}. +@var{options} contains a list of &-separated options of the form +@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for +space) can be used to escape keys and values. + +Options can also can be specified via command line options (or in code via +@code{AVOption}s). In case threading is enabled on the system, a circular buffer is used to store the incoming data, which allows one to reduce loss of data due to diff --git a/libavformat/udp.c b/libavformat/udp.c index e1dec49010..05936fc055 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -36,6 +36,7 @@ #include "libavutil/opt.h" #include "libavutil/log.h" #include "libavutil/time.h" +#include "internal.h" #include "network.h" #include "os_support.h" #include "url.h" @@ -697,7 +698,6 @@ static int udp_open(URLContext *h, const char *uri, int flags) UDPContext *s = h->priv_data; int is_output; const char *p; - char buf[256]; struct sockaddr_storage my_addr; socklen_t len; int ret; @@ -708,87 +708,11 @@ static int udp_open(URLContext *h, const char *uri, int flags) if (s->buffer_size < 0) s->buffer_size = is_output ? UDP_TX_BUF_SIZE : UDP_RX_BUF_SIZE; - if (s->sources) { - if ((ret = ff_ip_parse_sources(h, s->sources, &s->filters)) < 0) - goto fail; - } - - if (s->block) { - if ((ret = ff_ip_parse_blocks(h, s->block, &s->filters)) < 0) - goto fail; - } - p = strchr(uri, '?'); if (p) { - if (av_find_info_tag(buf, sizeof(buf), "reuse", p)) { - char *endptr = NULL; - s->reuse_socket = strtol(buf, &endptr, 10); - /* assume if no digits were found it is a request to enable it */ - if (buf == endptr) - s->reuse_socket = 1; - } - if (av_find_info_tag(buf, sizeof(buf), "overrun_nonfatal", p)) { - char *endptr = NULL; - s->overrun_nonfatal = strtol(buf, &endptr, 10); - /* assume if no digits were found it is a request to enable it */ - if (buf == endptr) - s->overrun_nonfatal = 1; - } - if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { - s->ttl = strtol(buf, NULL, 10); - if (s->ttl < 0 || s->ttl > 255) { - av_log(h, AV_LOG_ERROR, "ttl(%d) should be in range [0,255]\n", s->ttl); - ret = AVERROR(EINVAL); - goto fail; - } - } - if (av_find_info_tag(buf, sizeof(buf), "udplite_coverage", p)) { - s->udplite_coverage = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "localport", p)) { - s->local_port = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) { - s->pkt_size = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "buffer_size", p)) { - s->buffer_size = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { - s->is_connected = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) { - s->dscp = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "fifo_size", p)) { - s->circular_buffer_size = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "bitrate", p)) { - s->bitrate = strtoll(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "burst_bits", p)) { - s->burst_bits = strtoll(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { - av_freep(&s->localaddr); - s->localaddr = av_strdup(buf); - if (!s->localaddr) { - ret = AVERROR(ENOMEM); - goto fail; - } - } - if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { - if ((ret = ff_ip_parse_sources(h, buf, &s->filters)) < 0) - goto fail; - } - if (av_find_info_tag(buf, sizeof(buf), "block", p)) { - if ((ret = ff_ip_parse_blocks(h, buf, &s->filters)) < 0) - goto fail; - } - if (!is_output && av_find_info_tag(buf, sizeof(buf), "timeout", p)) - s->timeout = strtol(buf, NULL, 10); - if (is_output && av_find_info_tag(buf, sizeof(buf), "broadcast", p)) - s->is_broadcast = strtol(buf, NULL, 10); + ret = ff_parse_opts_from_query_string(s, p, 1); + if (ret < 0) + goto fail; } if (!HAVE_PTHREAD_CANCEL) { int64_t optvals[] = {s->overrun_nonfatal, s->bitrate, s->circular_buffer_size}; @@ -800,6 +724,15 @@ static int udp_open(URLContext *h, const char *uri, int flags) "on this build (pthread support is required)\n", optnames[i]); } } + if (s->sources) { + if ((ret = ff_ip_parse_sources(h, s->sources, &s->filters)) < 0) + goto fail; + } + if (s->block) { + if ((ret = ff_ip_parse_blocks(h, s->block, &s->filters)) < 0) + goto fail; + } + /* handling needed to support options picking from both AVOption and URL */ s->circular_buffer_size *= 188; if (flags & AVIO_FLAG_WRITE) { -- 2.49.1 >>From c899a1e142c03ab0c1d418d7fe61cb2d80d1085d Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 25 Aug 2025 01:52:00 +0200 Subject: [PATCH 06/10] avformat/tcp: use ff_parse_opts_from_query_string() to set URL parameters Signed-off-by: Marton Balint --- doc/protocols.texi | 6 +++++- libavformat/tcp.c | 36 ++++-------------------------------- 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index b4b6c25579..a329f59fe3 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1913,7 +1913,11 @@ tcp://@var{hostname}:@var{port}[?@var{options}] @end example @var{options} contains a list of &-separated options of the form -@var{key}=@var{val}. +@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for +space) can be used to escape keys and values. + +Options can also can be specified via command line options (or in code via +@code{AVOption}s). The list of supported options follows. diff --git a/libavformat/tcp.c b/libavformat/tcp.c index c286698d33..ce9f69a50b 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -25,6 +25,7 @@ #include "libavutil/opt.h" #include "libavutil/time.h" +#include "internal.h" #include "network.h" #include "os_support.h" #include "url.h" @@ -151,7 +152,6 @@ static int tcp_open(URLContext *h, const char *uri, int flags) int port, fd = -1; TCPContext *s = h->priv_data; const char *p; - char buf[256]; int ret; char hostname[1024],proto[1024],path[1024]; char portstr[10]; @@ -167,37 +167,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) } p = strchr(uri, '?'); if (p) { - if (av_find_info_tag(buf, sizeof(buf), "listen", p)) { - char *endptr = NULL; - s->listen = strtol(buf, &endptr, 10); - /* assume if no digits were found it is a request to enable it */ - if (buf == endptr) - s->listen = 1; - } - if (av_find_info_tag(buf, sizeof(buf), "local_port", p)) { - av_freep(&s->local_port); - s->local_port = av_strdup(buf); - if (!s->local_port) - return AVERROR(ENOMEM); - } - if (av_find_info_tag(buf, sizeof(buf), "local_addr", p)) { - av_freep(&s->local_addr); - s->local_addr = av_strdup(buf); - if (!s->local_addr) - return AVERROR(ENOMEM); - } - if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { - s->rw_timeout = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "listen_timeout", p)) { - s->listen_timeout = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "tcp_nodelay", p)) { - s->tcp_nodelay = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "tcp_keepalive", p)) { - s->tcp_keepalive = strtol(buf, NULL, 10); - } + int ret = ff_parse_opts_from_query_string(s, p, 1); + if (ret < 0) + return ret; } if (s->rw_timeout >= 0) { s->open_timeout = -- 2.49.1 >>From cf1b430dba68d5854c452cb8af33710cbf0fe474 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 25 Aug 2025 02:09:26 +0200 Subject: [PATCH 07/10] avformat/sctp: use ff_parse_opts_from_query_string() to set URL parameters Signed-off-by: Marton Balint --- doc/protocols.texi | 10 +++++++++- libavformat/sctp.c | 8 +++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index a329f59fe3..563aee6cc7 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1535,7 +1535,15 @@ The accepted URL syntax is: sctp://@var{host}:@var{port}[?@var{options}] @end example -The protocol accepts the following options: +@var{options} contains a list of &-separated options of the form +@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for +space) can be used to escape keys and values. + +Options can also can be specified via command line options (or in code via +@code{AVOption}s). + +The list of supported options follows. + @table @option @item listen If set to any value, listen for an incoming connection. Outgoing connection is done by default. diff --git a/libavformat/sctp.c b/libavformat/sctp.c index 9d9e90097e..4122fbe312 100644 --- a/libavformat/sctp.c +++ b/libavformat/sctp.c @@ -185,7 +185,6 @@ static int sctp_open(URLContext *h, const char *uri, int flags) int fd = -1; SCTPContext *s = h->priv_data; const char *p; - char buf[256]; int ret; char hostname[1024], proto[1024], path[1024]; char portstr[10]; @@ -201,10 +200,9 @@ static int sctp_open(URLContext *h, const char *uri, int flags) p = strchr(uri, '?'); if (p) { - if (av_find_info_tag(buf, sizeof(buf), "listen", p)) - s->listen = 1; - if (av_find_info_tag(buf, sizeof(buf), "max_streams", p)) - s->max_streams = strtol(buf, NULL, 10); + ret = ff_parse_opts_from_query_string(s, p, 0); + if (ret < 0) + return ret; } hints.ai_family = AF_UNSPEC; -- 2.49.1 >>From 3aa50f4a5ec4298bc488cec4c9fcb332ae5ae891 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 25 Aug 2025 21:35:40 +0200 Subject: [PATCH 08/10] avformat/rtpproto: use ff_parse_opts_from_query_string() to set URL parameters Signed-off-by: Marton Balint --- doc/protocols.texi | 8 +++-- libavformat/rtpproto.c | 69 +++++++++--------------------------------- 2 files changed, 21 insertions(+), 56 deletions(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index 563aee6cc7..3d9685ed6d 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1162,9 +1162,13 @@ rtp://@var{hostname}[:@var{port}][?@var{options}] @var{port} specifies the RTP port to use. @var{options} contains a list of &-separated options of the form -@var{key}=@var{val}. +@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for +space) can be used to escape keys and values. -The following options are supported: +Options can also can be specified via command line options (or in code via +@code{AVOption}s). + +The list of supported options follows. @table @option diff --git a/libavformat/rtpproto.c b/libavformat/rtpproto.c index 69879b7fa8..c4309c19e4 100644 --- a/libavformat/rtpproto.c +++ b/libavformat/rtpproto.c @@ -29,6 +29,7 @@ #include "libavutil/avstring.h" #include "libavutil/opt.h" #include "avformat.h" +#include "internal.h" #include "rtp.h" #include "rtpproto.h" #include "url.h" @@ -232,8 +233,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) RTPContext *s = h->priv_data; AVDictionary *fec_opts = NULL; int rtp_port; - char hostname[256], include_sources[1024] = "", exclude_sources[1024] = ""; - char *sources = include_sources, *block = exclude_sources; + char hostname[256]; char *fec_protocol = NULL; char buf[1024]; char path[1024]; @@ -250,58 +250,17 @@ static int rtp_open(URLContext *h, const char *uri, int flags) p = strchr(uri, '?'); if (p) { - if (av_find_info_tag(buf, sizeof(buf), "ttl", p)) { - s->ttl = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) { - s->rtcp_port = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "localport", p)) { - s->local_rtpport = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "localrtpport", p)) { - s->local_rtpport = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "localrtcpport", p)) { - s->local_rtcpport = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) { - s->pkt_size = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { - s->connect = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "write_to_source", p)) { - s->write_to_source = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "dscp", p)) { - s->dscp = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "timeout", p)) { - s->rw_timeout = strtol(buf, NULL, 10); - } - if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { - av_strlcpy(include_sources, buf, sizeof(include_sources)); - ff_ip_parse_sources(h, buf, &s->filters); - } else { - ff_ip_parse_sources(h, s->sources, &s->filters); - sources = s->sources; - } - if (av_find_info_tag(buf, sizeof(buf), "block", p)) { - av_strlcpy(exclude_sources, buf, sizeof(exclude_sources)); - ff_ip_parse_blocks(h, buf, &s->filters); - } else { - ff_ip_parse_blocks(h, s->block, &s->filters); - block = s->block; - } - if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { - av_freep(&s->localaddr); - s->localaddr = av_strdup(buf); - if (!s->localaddr) { - ret = AVERROR(ENOMEM); - goto fail; - } - } + ret = ff_parse_opts_from_query_string(s, p, 1); + if (ret < 0) + goto fail; + } + if (s->sources) { + if ((ret = ff_ip_parse_sources(h, s->sources, &s->filters)) < 0) + goto fail; + } + if (s->block) { + if ((ret = ff_ip_parse_blocks(h, s->block, &s->filters)) < 0) + goto fail; } if (s->rw_timeout >= 0) h->rw_timeout = s->rw_timeout; @@ -334,6 +293,8 @@ static int rtp_open(URLContext *h, const char *uri, int flags) } for (i = 0; i < max_retry_count; i++) { + const char *sources = s->sources ? s->sources : ""; + const char *block = s->block ? s->block : ""; build_udp_url(s, buf, sizeof(buf), hostname, s->localaddr, rtp_port, s->local_rtpport, sources, block); -- 2.49.1 >>From ee7094027e66b8b8d9dbfdd80e8e94da54307712 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 26 Aug 2025 00:23:16 +0200 Subject: [PATCH 09/10] avformat/tls: use ff_parse_opts_from_query_string() to set URL parameters Note that this changes the code to work the same way as other protocols where an URL parameter can override an AVOption. Signed-off-by: Marton Balint --- doc/protocols.texi | 10 +++++++-- libavformat/tls.c | 46 +++++---------------------------------- libavformat/tls_mbedtls.c | 14 ------------ 3 files changed, 14 insertions(+), 56 deletions(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index 3d9685ed6d..9f88f005b9 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -1984,8 +1984,14 @@ The required syntax for a TLS/SSL url is: tls://@var{hostname}:@var{port}[?@var{options}] @end example -The following parameters can be set via command line options -(or in code via @code{AVOption}s): +@var{options} contains a list of &-separated options of the form +@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for +space) can be used to escape keys and values. + +Options can also can be specified via command line options (or in code via +@code{AVOption}s). + +The list of supported options follows. @table @option diff --git a/libavformat/tls.c b/libavformat/tls.c index bd9c05e6dc..2cf0c99a6b 100644 --- a/libavformat/tls.c +++ b/libavformat/tls.c @@ -31,41 +31,6 @@ #include "libavutil/mem.h" #include "libavutil/parseutils.h" -static int set_options(TLSShared *c, const char *uri) -{ - char buf[1024]; - const char *p = strchr(uri, '?'); - if (!p) - return 0; - - if (!c->ca_file && av_find_info_tag(buf, sizeof(buf), "cafile", p)) { - c->ca_file = av_strdup(buf); - if (!c->ca_file) - return AVERROR(ENOMEM); - } - - if (!c->verify && av_find_info_tag(buf, sizeof(buf), "verify", p)) { - char *endptr = NULL; - c->verify = strtol(buf, &endptr, 10); - if (buf == endptr) - c->verify = 1; - } - - if (!c->cert_file && av_find_info_tag(buf, sizeof(buf), "cert", p)) { - c->cert_file = av_strdup(buf); - if (!c->cert_file) - return AVERROR(ENOMEM); - } - - if (!c->key_file && av_find_info_tag(buf, sizeof(buf), "key", p)) { - c->key_file = av_strdup(buf); - if (!c->key_file) - return AVERROR(ENOMEM); - } - - return 0; -} - int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options) { int port; @@ -77,17 +42,18 @@ int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AV int use_proxy; int ret; - ret = set_options(c, uri); - if (ret < 0) - return ret; + p = strchr(uri, '?'); + if (p) { + ret = ff_parse_opts_from_query_string(c, p, 1); + if (ret < 0) + return ret; + } if (c->listen && !c->is_dtls) snprintf(opts, sizeof(opts), "?listen=1"); av_url_split(NULL, 0, NULL, 0, c->underlying_host, sizeof(c->underlying_host), &port, NULL, 0, uri); - p = strchr(uri, '?'); - if (!p) { p = opts; } else { diff --git a/libavformat/tls_mbedtls.c b/libavformat/tls_mbedtls.c index 2bcd3cca63..8aa142b9d2 100644 --- a/libavformat/tls_mbedtls.c +++ b/libavformat/tls_mbedtls.c @@ -174,17 +174,6 @@ static void handle_handshake_error(URLContext *h, int ret) } } -static void parse_options(TLSContext *tls_ctxc, const char *uri) -{ - char buf[1024]; - const char *p = strchr(uri, '?'); - if (!p) - return; - - if (!tls_ctxc->priv_key_pw && av_find_info_tag(buf, sizeof(buf), "key_password", p)) - tls_ctxc->priv_key_pw = av_strdup(buf); -} - static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options) { TLSContext *tls_ctx = h->priv_data; @@ -192,9 +181,6 @@ static int tls_open(URLContext *h, const char *uri, int flags, AVDictionary **op uint32_t verify_res_flags; int ret; - // parse additional options - parse_options(tls_ctx, uri); - if ((ret = ff_tls_open_underlying(shr, h, uri, options)) < 0) goto fail; -- 2.49.1 >>From 594ea1b6017eed768a7de8422a068b87bffa6072 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Wed, 3 Sep 2025 00:55:46 +0200 Subject: [PATCH 10/10] avformat/tls_openssl: initialize underlying protocol early for dtls_start() The same way we do with TLS, so all tls URL options will be properly supported. Signed-off-by: Marton Balint --- doc/protocols.texi | 13 ++++++++++--- libavformat/tls_openssl.c | 15 ++++++++------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index 9f88f005b9..b74383122a 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -2052,12 +2052,19 @@ Datagram Transport Layer Security (DTLS) The required syntax for a DTLS URL is: @example -dtls://@var{hostname}:@var{port} +dtls://@var{hostname}:@var{port}[?@var{options}] @end example +@var{options} contains a list of &-separated options of the form +@var{key}=@var{val}. Standard percent-encoding (and using the plus sign for +space) can be used to escape keys and values. + +Options can also can be specified via command line options (or in code via +@code{AVOption}s). + DTLS shares most options with TLS, but operates over UDP instead of TCP. -The following parameters can be set via command line options -(or in code via @code{AVOption}s): + +The list of supported options follows. @table @option diff --git a/libavformat/tls_openssl.c b/libavformat/tls_openssl.c index edfd657a3f..f724153da1 100644 --- a/libavformat/tls_openssl.c +++ b/libavformat/tls_openssl.c @@ -749,6 +749,13 @@ static int dtls_start(URLContext *h, const char *url, int flags, AVDictionary ** av_assert0(s); s->is_dtls = 1; + if (!c->tls_shared.external_sock) { + if ((ret = ff_tls_open_underlying(&c->tls_shared, h, url, options)) < 0) { + av_log(c, AV_LOG_ERROR, "Failed to connect %s\n", url); + return ret; + } + } + c->ctx = SSL_CTX_new(s->listen ? DTLS_server_method() : DTLS_client_method()); if (!c->ctx) { ret = AVERROR(ENOMEM); @@ -801,13 +808,6 @@ static int dtls_start(URLContext *h, const char *url, int flags, AVDictionary ** DTLS_set_link_mtu(c->ssl, s->mtu); init_bio_method(h); - if (!c->tls_shared.external_sock) { - if ((ret = ff_tls_open_underlying(&c->tls_shared, h, url, options)) < 0) { - av_log(c, AV_LOG_ERROR, "Failed to connect %s\n", url); - return ret; - } - } - /* This seems to be necessary despite explicitly setting client/server method above. */ if (s->listen) SSL_set_accept_state(c->ssl); @@ -838,6 +838,7 @@ static int dtls_start(URLContext *h, const char *url, int flags, AVDictionary ** ret = 0; fail: + tls_close(h); return ret; } -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org