3 * Copyright (c) 2011 Martin Storsjo
4 * Copyright (c) 2017 sfan5 <sfan5@live.de>
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
28 #include "libavcodec/internal.h"
29 #include "libavutil/avutil.h"
30 #include "libavutil/opt.h"
34 typedef struct TLSContext {
40 static int ff_tls_close(URLContext *h)
42 TLSContext *p = h->priv_data;
47 ffurl_closep(&p->tls_shared.tcp);
51 static ssize_t tls_read_callback(struct tls *ctx, void *buf, size_t buflen, void *cb_arg)
53 URLContext *h = (URLContext*) cb_arg;
54 int ret = ffurl_read(h, buf, buflen);
55 if (ret == AVERROR(EAGAIN))
56 return TLS_WANT_POLLIN;
57 else if (ret == AVERROR_EXIT)
59 return ret >= 0 ? ret : -1;
62 static ssize_t tls_write_callback(struct tls *ctx, const void *buf, size_t buflen, void *cb_arg)
64 URLContext *h = (URLContext*) cb_arg;
65 int ret = ffurl_write(h, buf, buflen);
66 if (ret == AVERROR(EAGAIN))
67 return TLS_WANT_POLLOUT;
68 else if (ret == AVERROR_EXIT)
70 return ret >= 0 ? ret : -1;
73 static int ff_tls_open(URLContext *h, const char *uri, int flags, AVDictionary **options)
75 TLSContext *p = h->priv_data;
76 TLSShared *c = &p->tls_shared;
77 struct tls_config *cfg = NULL;
80 if (tls_init() == -1) {
85 if ((ret = ff_tls_open_underlying(c, h, uri, options)) < 0)
88 p->ctx = !c->listen ? tls_client() : tls_server();
94 cfg = tls_config_new();
99 if (tls_config_set_protocols(cfg, TLS_PROTOCOLS_ALL) == -1)
101 // While TLSv1.0 and TLSv1.1 are already enabled by the above,
102 // we need to be less strict with ciphers so it works in practice.
103 if (tls_config_set_ciphers(cfg, "compat") == -1)
105 if (c->ca_file && tls_config_set_ca_file(cfg, c->ca_file) == -1)
107 if (c->cert_file && tls_config_set_cert_file(cfg, c->cert_file) == -1)
109 if (c->key_file && tls_config_set_key_file(cfg, c->key_file) == -1)
112 tls_config_insecure_noverifycert(cfg);
113 tls_config_insecure_noverifyname(cfg);
114 tls_config_insecure_noverifytime(cfg);
116 if (tls_configure(p->ctx, cfg) == -1)
120 ret = tls_connect_cbs(p->ctx, tls_read_callback, tls_write_callback,
124 ret = tls_accept_cbs(p->ctx, &ctx_new, tls_read_callback,
125 tls_write_callback, c->tcp);
127 // free "server" context and replace by "connection" context
135 tls_config_free(cfg);
138 av_log(h, AV_LOG_ERROR, "%s\n", tls_config_error(cfg));
142 av_log(h, AV_LOG_ERROR, "%s\n", tls_error(p->ctx));
147 tls_config_free(cfg);
152 static int ff_tls_read(URLContext *h, uint8_t *buf, int size)
154 TLSContext *p = h->priv_data;
156 ret = tls_read(p->ctx, buf, size);
161 av_log(h, AV_LOG_ERROR, "%s\n", tls_error(p->ctx));
165 static int ff_tls_write(URLContext *h, const uint8_t *buf, int size)
167 TLSContext *p = h->priv_data;
169 ret = tls_write(p->ctx, buf, size);
174 av_log(h, AV_LOG_ERROR, "%s\n", tls_error(p->ctx));
178 static int tls_get_file_handle(URLContext *h)
180 TLSContext *c = h->priv_data;
181 return ffurl_get_file_handle(c->tls_shared.tcp);
184 static int tls_get_short_seek(URLContext *h)
186 TLSContext *s = h->priv_data;
187 return ffurl_get_short_seek(s->tls_shared.tcp);
190 static const AVOption options[] = {
191 TLS_COMMON_OPTIONS(TLSContext, tls_shared),
195 static const AVClass tls_class = {
197 .item_name = av_default_item_name,
199 .version = LIBAVUTIL_VERSION_INT,
202 const URLProtocol ff_tls_protocol = {
204 .url_open2 = ff_tls_open,
205 .url_read = ff_tls_read,
206 .url_write = ff_tls_write,
207 .url_close = ff_tls_close,
208 .url_get_file_handle = tls_get_file_handle,
209 .url_get_short_seek = tls_get_short_seek,
210 .priv_data_size = sizeof(TLSContext),
211 .flags = URL_PROTOCOL_FLAG_NETWORK,
212 .priv_data_class = &tls_class,