blob: 10e0792e292c3276c0283744879f632642ed3961
1 | /* |
2 | * TLS/SSL Protocol |
3 | * Copyright (c) 2011 Martin Storsjo |
4 | * |
5 | * This file is part of FFmpeg. |
6 | * |
7 | * FFmpeg is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU Lesser General Public |
9 | * License as published by the Free Software Foundation; either |
10 | * version 2.1 of the License, or (at your option) any later version. |
11 | * |
12 | * FFmpeg is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | * Lesser General Public License for more details. |
16 | * |
17 | * You should have received a copy of the GNU Lesser General Public |
18 | * License along with FFmpeg; if not, write to the Free Software |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | */ |
21 | |
22 | #include "avformat.h" |
23 | #include "internal.h" |
24 | #include "network.h" |
25 | #include "os_support.h" |
26 | #include "url.h" |
27 | #include "tls.h" |
28 | #include "libavutil/avstring.h" |
29 | #include "libavutil/opt.h" |
30 | #include "libavutil/parseutils.h" |
31 | |
32 | static void set_options(TLSShared *c, const char *uri) |
33 | { |
34 | char buf[1024]; |
35 | const char *p = strchr(uri, '?'); |
36 | if (!p) |
37 | return; |
38 | |
39 | if (!c->ca_file && av_find_info_tag(buf, sizeof(buf), "cafile", p)) |
40 | c->ca_file = av_strdup(buf); |
41 | |
42 | if (!c->verify && av_find_info_tag(buf, sizeof(buf), "verify", p)) { |
43 | char *endptr = NULL; |
44 | c->verify = strtol(buf, &endptr, 10); |
45 | if (buf == endptr) |
46 | c->verify = 1; |
47 | } |
48 | |
49 | if (!c->cert_file && av_find_info_tag(buf, sizeof(buf), "cert", p)) |
50 | c->cert_file = av_strdup(buf); |
51 | |
52 | if (!c->key_file && av_find_info_tag(buf, sizeof(buf), "key", p)) |
53 | c->key_file = av_strdup(buf); |
54 | } |
55 | |
56 | int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options) |
57 | { |
58 | int port; |
59 | const char *p; |
60 | char buf[200], opts[50] = ""; |
61 | struct addrinfo hints = { 0 }, *ai = NULL; |
62 | const char *proxy_path; |
63 | int use_proxy; |
64 | |
65 | set_options(c, uri); |
66 | |
67 | if (c->listen) |
68 | snprintf(opts, sizeof(opts), "?listen=1"); |
69 | |
70 | av_url_split(NULL, 0, NULL, 0, c->underlying_host, sizeof(c->underlying_host), &port, NULL, 0, uri); |
71 | |
72 | p = strchr(uri, '?'); |
73 | |
74 | if (!p) { |
75 | p = opts; |
76 | } else { |
77 | if (av_find_info_tag(opts, sizeof(opts), "listen", p)) |
78 | c->listen = 1; |
79 | } |
80 | |
81 | ff_url_join(buf, sizeof(buf), "tcp", NULL, c->underlying_host, port, "%s", p); |
82 | |
83 | hints.ai_flags = AI_NUMERICHOST; |
84 | if (!getaddrinfo(c->underlying_host, NULL, &hints, &ai)) { |
85 | c->numerichost = 1; |
86 | freeaddrinfo(ai); |
87 | } |
88 | |
89 | if (!c->host && !(c->host = av_strdup(c->underlying_host))) |
90 | return AVERROR(ENOMEM); |
91 | |
92 | proxy_path = getenv("http_proxy"); |
93 | use_proxy = !ff_http_match_no_proxy(getenv("no_proxy"), c->underlying_host) && |
94 | proxy_path && av_strstart(proxy_path, "http://", NULL); |
95 | |
96 | if (use_proxy) { |
97 | char proxy_host[200], proxy_auth[200], dest[200]; |
98 | int proxy_port; |
99 | av_url_split(NULL, 0, proxy_auth, sizeof(proxy_auth), |
100 | proxy_host, sizeof(proxy_host), &proxy_port, NULL, 0, |
101 | proxy_path); |
102 | ff_url_join(dest, sizeof(dest), NULL, NULL, c->underlying_host, port, NULL); |
103 | ff_url_join(buf, sizeof(buf), "httpproxy", proxy_auth, proxy_host, |
104 | proxy_port, "/%s", dest); |
105 | } |
106 | |
107 | return ffurl_open_whitelist(&c->tcp, buf, AVIO_FLAG_READ_WRITE, |
108 | &parent->interrupt_callback, options, |
109 | parent->protocol_whitelist, parent->protocol_blacklist, parent); |
110 | } |
111 |