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/getenv_utf8.h" 30#include "libavutil/opt.h" 31#include "libavutil/parseutils.h" 32 33static void set_options(TLSShared *c, const char *uri) 34{ 35 char buf[1024]; 36 const char *p = strchr(uri, '?'); 37 if (!p) 38 return; 39 40 if (!c->ca_file && av_find_info_tag(buf, sizeof(buf), "cafile", p)) 41 c->ca_file = av_strdup(buf); 42 43 if (!c->verify && av_find_info_tag(buf, sizeof(buf), "verify", p)) { 44 char *endptr = NULL; 45 c->verify = strtol(buf, &endptr, 10); 46 if (buf == endptr) 47 c->verify = 1; 48 } 49 50 if (!c->cert_file && av_find_info_tag(buf, sizeof(buf), "cert", p)) 51 c->cert_file = av_strdup(buf); 52 53 if (!c->key_file && av_find_info_tag(buf, sizeof(buf), "key", p)) 54 c->key_file = av_strdup(buf); 55} 56 57int ff_tls_open_underlying(TLSShared *c, URLContext *parent, const char *uri, AVDictionary **options) 58{ 59 int port; 60 const char *p; 61 char buf[200], opts[50] = ""; 62 struct addrinfo hints = { 0 }, *ai = NULL; 63 const char *proxy_path; 64 char *env_http_proxy, *env_no_proxy; 65 int use_proxy; 66 67 set_options(c, uri); 68 69 if (c->listen) 70 snprintf(opts, sizeof(opts), "?listen=1"); 71 72 av_url_split(NULL, 0, NULL, 0, c->underlying_host, sizeof(c->underlying_host), &port, NULL, 0, uri); 73 74 p = strchr(uri, '?'); 75 76 if (!p) { 77 p = opts; 78 } else { 79 if (av_find_info_tag(opts, sizeof(opts), "listen", p)) 80 c->listen = 1; 81 } 82 83 ff_url_join(buf, sizeof(buf), "tcp", NULL, c->underlying_host, port, "%s", p); 84 85 hints.ai_flags = AI_NUMERICHOST; 86 if (!getaddrinfo(c->underlying_host, NULL, &hints, &ai)) { 87 c->numerichost = 1; 88 freeaddrinfo(ai); 89 } 90 91 if (!c->host && !(c->host = av_strdup(c->underlying_host))) 92 return AVERROR(ENOMEM); 93 94 env_http_proxy = getenv_utf8("http_proxy"); 95 proxy_path = c->http_proxy ? c->http_proxy : env_http_proxy; 96 97 env_no_proxy = getenv_utf8("no_proxy"); 98 use_proxy = !ff_http_match_no_proxy(env_no_proxy, c->underlying_host) && 99 proxy_path && av_strstart(proxy_path, "http://", NULL); 100 freeenv_utf8(env_no_proxy); 101 102 if (use_proxy) { 103 char proxy_host[200], proxy_auth[200], dest[200]; 104 int proxy_port; 105 av_url_split(NULL, 0, proxy_auth, sizeof(proxy_auth), 106 proxy_host, sizeof(proxy_host), &proxy_port, NULL, 0, 107 proxy_path); 108 ff_url_join(dest, sizeof(dest), NULL, NULL, c->underlying_host, port, NULL); 109 ff_url_join(buf, sizeof(buf), "httpproxy", proxy_auth, proxy_host, 110 proxy_port, "/%s", dest); 111 } 112 113 freeenv_utf8(env_http_proxy); 114 return ffurl_open_whitelist(&c->tcp, buf, AVIO_FLAG_READ_WRITE, 115 &parent->interrupt_callback, options, 116 parent->protocol_whitelist, parent->protocol_blacklist, parent); 117} 118