2 * TLS/DTLS/SSL Protocol
3 * Copyright (c) 2011 Martin Storsjo
4 * Copyright (c) 2025 Jack Lau
6 * This file is part of FFmpeg.
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "os_support.h"
29 #include "libavutil/avstring.h"
30 #include "libavutil/getenv_utf8.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/parseutils.h"
34 int ff_tls_open_underlying(TLSShared
*c
, URLContext
*parent
, const char *uri
, AVDictionary
**options
)
38 char buf
[200], opts
[50] = "";
39 struct addrinfo hints
= { 0 }, *ai
= NULL
;
40 const char *proxy_path
;
41 char *env_http_proxy
, *env_no_proxy
;
47 ret
= ff_parse_opts_from_query_string(c
, p
, 1);
52 if (c
->listen
&& !c
->is_dtls
)
53 snprintf(opts
, sizeof(opts
), "?listen=1");
55 av_url_split(NULL
, 0, NULL
, 0, c
->underlying_host
, sizeof(c
->underlying_host
), &port
, NULL
, 0, uri
);
60 if (av_find_info_tag(opts
, sizeof(opts
), "listen", p
))
64 ff_url_join(buf
, sizeof(buf
), c
->is_dtls
? "udp" : "tcp", NULL
, (c
->is_dtls
&& c
->listen
) ? "" : c
->underlying_host
, port
, "%s", p
);
66 hints
.ai_flags
= AI_NUMERICHOST
;
67 if (!getaddrinfo(c
->underlying_host
, NULL
, &hints
, &ai
)) {
72 if (!c
->host
&& !(c
->host
= av_strdup(c
->underlying_host
)))
73 return AVERROR(ENOMEM
);
75 env_http_proxy
= getenv_utf8("http_proxy");
76 proxy_path
= c
->http_proxy
? c
->http_proxy
: env_http_proxy
;
78 env_no_proxy
= getenv_utf8("no_proxy");
79 use_proxy
= !ff_http_match_no_proxy(env_no_proxy
, c
->underlying_host
) &&
80 proxy_path
&& av_strstart(proxy_path
, "http://", NULL
);
81 freeenv_utf8(env_no_proxy
);
83 if (!c
->is_dtls
&& use_proxy
) {
84 char proxy_host
[200], proxy_auth
[200], dest
[200];
86 av_url_split(NULL
, 0, proxy_auth
, sizeof(proxy_auth
),
87 proxy_host
, sizeof(proxy_host
), &proxy_port
, NULL
, 0,
89 ff_url_join(dest
, sizeof(dest
), NULL
, NULL
, c
->underlying_host
, port
, NULL
);
90 ff_url_join(buf
, sizeof(buf
), "httpproxy", proxy_auth
, proxy_host
,
91 proxy_port
, "/%s", dest
);
94 freeenv_utf8(env_http_proxy
);
97 av_dict_set_int(options
, "localport", port
, 0);
98 av_dict_set(options
, "localaddr", c
->underlying_host
, 0);
100 av_dict_set_int(options
, "localport", 0, 0);
101 av_dict_set_int(options
, "connect", 1, 0);
103 av_dict_set_int(options
, "fifo_size", 0, 0);
104 /* Set the max packet size to the buffer size. */
105 av_dict_set_int(options
, "pkt_size", c
->mtu
, 0);
107 ret
= ffurl_open_whitelist(c
->is_dtls
? &c
->udp
: &c
->tcp
, buf
, AVIO_FLAG_READ_WRITE
,
108 &parent
->interrupt_callback
, options
,
109 parent
->protocol_whitelist
, parent
->protocol_blacklist
, parent
);
114 * Read all data from the given URL url and store it in the given buffer bp.
116 int ff_url_read_all(const char *url
, AVBPrint
*bp
)
119 AVDictionary
*opts
= NULL
;
120 URLContext
*uc
= NULL
;
121 char buf
[MAX_URL_SIZE
];
123 ret
= ffurl_open_whitelist(&uc
, url
, AVIO_FLAG_READ
, NULL
, &opts
, NULL
, NULL
, NULL
);
125 av_log(NULL
, AV_LOG_ERROR
, "TLS: Failed to open url %s\n", url
);
130 ret
= ffurl_read(uc
, buf
, sizeof(buf
));
131 if (ret
== AVERROR_EOF
) {
132 /* Reset the error because we read all response as answer util EOF. */
137 av_log(NULL
, AV_LOG_ERROR
, "TLS: Failed to read from url=%s, key is %s\n", url
, bp
->str
);
141 av_bprintf(bp
, "%.*s", ret
, buf
);
142 if (!av_bprint_is_complete(bp
)) {
143 av_log(NULL
, AV_LOG_ERROR
, "TLS: Exceed max size %.*s, %s\n", ret
, buf
, bp
->str
);