FFmpeg
Loading...
Searching...
No Matches
tls.c
Go to the documentation of this file.
1/*
2 * TLS/DTLS/SSL Protocol
3 * Copyright (c) 2011 Martin Storsjo
4 * Copyright (c) 2025 Jack Lau
5 *
6 * This file is part of FFmpeg.
7 *
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.
12 *
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.
17 *
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
21 */
22
23#include "avformat.h"
24#include "internal.h"
25#include "network.h"
26#include "os_support.h"
27#include "url.h"
28#include "tls.h"
29#include "libavutil/avstring.h"
32#include "libavutil/mem.h"
34
35int ff_tls_parse_host(TLSShared *s, char *hostname, int hostname_size, int *port_ptr, const char *uri)
36{
37 struct addrinfo hints = { .ai_flags = AI_NUMERICHOST }, *ai;
38
39 if (!hostname || hostname_size <= 0)
40 return AVERROR(EINVAL);
41
42 av_url_split(NULL, 0, NULL, 0, hostname, hostname_size, port_ptr, NULL, 0, uri);
43 if (!getaddrinfo(hostname, NULL, &hints, &ai)) {
44 s->numerichost = 1;
45 freeaddrinfo(ai);
46 }
47
48 if (!s->host && !(s->host = av_strdup(hostname)))
49 return AVERROR(ENOMEM);
50
51 return 0;
52}
53
55{
56 int port;
57 const char *p;
58 char buf[200], opts[50] = "";
59 const char *proxy_path;
60 char *env_http_proxy, *env_no_proxy;
61 int use_proxy;
62 int ret;
63
64 p = strchr(uri, '?');
65 if (p) {
67 if (ret < 0)
68 return ret;
69 }
70
71 if (c->listen && !c->is_dtls)
72 snprintf(opts, sizeof(opts), "?listen=1");
73
74 ret = ff_tls_parse_host(c, c->underlying_host, sizeof(c->underlying_host), &port, uri);
75 if (ret < 0)
76 return ret;
77
78 if (!p) {
79 p = opts;
80 } else {
81 if (av_find_info_tag(opts, sizeof(opts), "listen", p))
82 c->listen = 1;
83 }
84
85 ff_url_join(buf, sizeof(buf), c->is_dtls ? "udp" : "tcp", NULL, (c->is_dtls && c->listen) ? "" : c->underlying_host, port, "%s", p);
86
87 env_http_proxy = getenv_utf8("http_proxy");
88 proxy_path = c->http_proxy ? c->http_proxy : env_http_proxy;
89
90 env_no_proxy = getenv_utf8("no_proxy");
91 use_proxy = !ff_http_match_no_proxy(env_no_proxy, c->underlying_host) &&
92 proxy_path && av_strstart(proxy_path, "http://", NULL);
93 freeenv_utf8(env_no_proxy);
94
95 if (!c->is_dtls && use_proxy) {
96 char proxy_host[200], proxy_auth[200], dest[200];
97 int proxy_port;
98 av_url_split(NULL, 0, proxy_auth, sizeof(proxy_auth),
99 proxy_host, sizeof(proxy_host), &proxy_port, NULL, 0,
100 proxy_path);
101 ff_url_join(dest, sizeof(dest), NULL, NULL, c->underlying_host, port, NULL);
102 ff_url_join(buf, sizeof(buf), "httpproxy", proxy_auth, proxy_host,
103 proxy_port, "/%s", dest);
104 }
105
106 freeenv_utf8(env_http_proxy);
107 if (c->is_dtls) {
108 if (c->listen) {
109 av_dict_set_int(options, "localport", port, 0);
110 av_dict_set(options, "localaddr", c->underlying_host, 0);
111 } else {
112 av_dict_set_int(options, "localport", 0, 0);
113 av_dict_set_int(options, "connect", 1, 0);
114 }
115 av_dict_set_int(options, "fifo_size", 0, 0);
116 /* Set the max packet size to the buffer size. */
117 av_dict_set_int(options, "pkt_size", c->mtu, 0);
118 }
119 ret = ffurl_open_whitelist(c->is_dtls ? &c->udp : &c->tcp, buf, AVIO_FLAG_READ_WRITE,
120 &parent->interrupt_callback, options,
121 parent->protocol_whitelist, parent->protocol_blacklist, parent);
122 return ret;
123}
124
125/**
126 * Read all data from the given URL url and store it in the given buffer bp.
127 */
128int ff_url_read_all(const char *url, AVBPrint *bp)
129{
130 int ret = 0;
132 URLContext *uc = NULL;
133 char buf[MAX_URL_SIZE];
134
136 if (ret < 0) {
137 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to open url %s\n", url);
138 goto end;
139 }
140
141 while (1) {
142 ret = ffurl_read(uc, buf, sizeof(buf));
143 if (ret == AVERROR_EOF) {
144 /* Reset the error because we read all response as answer util EOF. */
145 ret = 0;
146 break;
147 }
148 if (ret <= 0) {
149 av_log(NULL, AV_LOG_ERROR, "TLS: Failed to read from url=%s, key is %s\n", url, bp->str);
150 goto end;
151 }
152
153 av_bprintf(bp, "%.*s", ret, buf);
154 if (!av_bprint_is_complete(bp)) {
155 av_log(NULL, AV_LOG_ERROR, "TLS: Exceed max size %.*s, %s\n", ret, buf, bp->str);
156 ret = AVERROR(EIO);
157 goto end;
158 }
159 }
160
161end:
162 ffurl_closep(&uc);
164 return ret;
165}
166
167int ff_is_dtls_packet(const uint8_t *buf, int size)
168{
170 uint16_t version = AV_RB16(&buf[1]);
171 return buf[0] >= DTLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC &&
173 }
174 return 0;
175}
Main libavformat public API header.
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist, const char *blacklist, URLContext *parent)
Create an URLContext for accessing to the resource indicated by url, and open it.
Definition avio.c:461
int ffurl_closep(URLContext **hh)
Close the resource accessed by the URLContext h, and free the memory used by it.
Definition avio.c:656
#define AVIO_FLAG_READ
read-only
Definition avio.h:617
#define AVIO_FLAG_READ_WRITE
read-write pseudo flag
Definition avio.h:619
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition bprint.c:122
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
static char * getenv_utf8(const char *varname)
Definition getenv_utf8.h:67
static void freeenv_utf8(char *var)
Definition getenv_utf8.h:72
void av_url_split(char *proto, int proto_size, char *authorization, int authorization_size, char *hostname, int hostname_size, int *port_ptr, char *path, int path_size, const char *url)
Split a URL string into components.
Definition utils.c:361
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition bprint.h:218
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition dict.c:86
int av_dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
Convenience wrapper for av_dict_set() that converts the value to a string and stores it.
Definition dict.c:177
#define AVERROR_EOF
End of file.
Definition error.h:57
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition avstring.c:36
#define AV_RB16(p)
int ff_parse_opts_from_query_string(void *obj, const char *str, int allow_unknown)
Set a list of query string options on an object.
Definition utils.c:643
#define MAX_URL_SIZE
Definition internal.h:30
version
Definition libkvazaar.c:313
Memory handling functions.
int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
Definition network.c:558
#define AI_NUMERICHOST
Definition network.h:187
#define getaddrinfo
Definition network.h:217
#define freeaddrinfo
Definition network.h:218
#define av_strdup(s)
Definition ops_static.c:55
miscellaneous OS support macros and functions.
int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info)
Attempt to find a specific tag in a URL.
Definition parseutils.c:756
misc parsing utilities
#define snprintf
Definition snprintf.h:34
const char * protocol_whitelist
Definition url.h:46
AVIOInterruptCB interrupt_callback
Definition url.h:44
const char * protocol_blacklist
Definition url.h:47
#define av_log(a,...)
static AVDictionary * opts
Definition movenc.c:51
int ff_url_read_all(const char *url, AVBPrint *bp)
Read all data from the given URL url and store it in the given buffer bp.
Definition tls.c:128
int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options)
Definition tls.c:54
int ff_tls_parse_host(TLSShared *s, char *hostname, int hostname_size, int *port_ptr, const char *uri)
Definition tls.c:35
int ff_is_dtls_packet(const uint8_t *buf, int size)
Whether the packet is a DTLS packet, as defined by RFC 5764 Section 5.1.2.
Definition tls.c:167
#define DTLS_VERSION_12
Definition tls.h:54
#define DTLS_RECORD_LAYER_HEADER_LEN
The DTLS record layer header has a total size of 13 bytes, consisting of ContentType (1 byte),...
Definition tls.h:48
#define DTLS_VERSION_10
The DTLS version number, which is 0xfeff for DTLS 1.0, or 0xfefd for DTLS 1.2.
Definition tls.h:53
#define DTLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC
The DTLS content type.
Definition tls.h:41
int size
int ff_url_join(char *str, int size, const char *proto, const char *authorization, const char *hostname, int port, const char *fmt,...)
Definition url.c:40
unbuffered private I/O API
static int ffurl_read(URLContext *h, uint8_t *buf, int size)
Read up to size bytes from the resource accessed by h, and store the read bytes in buf.
Definition url.h:183
static double c[64]