X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fnetwork.c;h=2c34b4a14bfac6fbf3ffcd48bfc964a044688b10;hb=972c71e9cb63e24f57ee481e413199c7d88a8813;hp=a80e2a2d691a099a3ca0ce08c5dc258cf7112782;hpb=9835abb6d63fb07613994ae90e72fef758149408;p=ffmpeg diff --git a/libavformat/network.c b/libavformat/network.c index a80e2a2d691..2c34b4a14bf 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -18,103 +18,31 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "network.h" +#include "tls.h" #include "url.h" #include "libavcodec/internal.h" #include "libavutil/mem.h" -#if HAVE_THREADS -#if HAVE_PTHREADS -#include -#else -#include "compat/w32pthreads.h" -#endif -#endif - -#if CONFIG_OPENSSL -#include -static int openssl_init; -#if HAVE_THREADS -#include -#include "libavutil/avutil.h" -pthread_mutex_t *openssl_mutexes; -static void openssl_lock(int mode, int type, const char *file, int line) -{ - if (mode & CRYPTO_LOCK) - pthread_mutex_lock(&openssl_mutexes[type]); - else - pthread_mutex_unlock(&openssl_mutexes[type]); -} -#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 -static unsigned long openssl_thread_id(void) -{ - return (intptr_t) pthread_self(); -} -#endif -#endif -#endif -#if CONFIG_GNUTLS -#include -#if HAVE_THREADS && GNUTLS_VERSION_NUMBER <= 0x020b00 -#include -#include -GCRY_THREAD_OPTION_PTHREAD_IMPL; -#endif -#endif - void ff_tls_init(void) { - avpriv_lock_avformat(); -#if CONFIG_OPENSSL - if (!openssl_init) { - SSL_library_init(); - SSL_load_error_strings(); -#if HAVE_THREADS - if (!CRYPTO_get_locking_callback()) { - int i; - openssl_mutexes = av_malloc(sizeof(pthread_mutex_t) * CRYPTO_num_locks()); - for (i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_init(&openssl_mutexes[i], NULL); - CRYPTO_set_locking_callback(openssl_lock); -#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 - CRYPTO_set_id_callback(openssl_thread_id); -#endif - } -#endif - } - openssl_init++; -#endif -#if CONFIG_GNUTLS -#if HAVE_THREADS && GNUTLS_VERSION_NUMBER < 0x020b00 - if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0) - gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); +#if CONFIG_TLS_OPENSSL_PROTOCOL + ff_openssl_init(); #endif - gnutls_global_init(); +#if CONFIG_TLS_GNUTLS_PROTOCOL + ff_gnutls_init(); #endif - avpriv_unlock_avformat(); } void ff_tls_deinit(void) { - avpriv_lock_avformat(); -#if CONFIG_OPENSSL - openssl_init--; - if (!openssl_init) { -#if HAVE_THREADS - if (CRYPTO_get_locking_callback() == openssl_lock) { - int i; - CRYPTO_set_locking_callback(NULL); - for (i = 0; i < CRYPTO_num_locks(); i++) - pthread_mutex_destroy(&openssl_mutexes[i]); - av_free(openssl_mutexes); - } -#endif - } +#if CONFIG_TLS_OPENSSL_PROTOCOL + ff_openssl_deinit(); #endif -#if CONFIG_GNUTLS - gnutls_global_deinit(); +#if CONFIG_TLS_GNUTLS_PROTOCOL + ff_gnutls_deinit(); #endif - avpriv_unlock_avformat(); } int ff_network_inited_globally; @@ -210,6 +138,28 @@ static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout, return ret; } +int ff_socket(int af, int type, int proto) +{ + int fd; + +#ifdef SOCK_CLOEXEC + fd = socket(af, type | SOCK_CLOEXEC, proto); + if (fd == -1 && errno == EINVAL) +#endif + { + fd = socket(af, type, proto); +#if HAVE_FCNTL + if (fd != -1) + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif + } +#ifdef SO_NOSIGPIPE + if (fd != -1) + setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &(int){1}, sizeof(int)); +#endif + return fd; +} + int ff_listen_bind(int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h) { @@ -240,7 +190,8 @@ int ff_listen_bind(int fd, const struct sockaddr *addr, } int ff_listen_connect(int fd, const struct sockaddr *addr, - socklen_t addrlen, int timeout, URLContext *h) + socklen_t addrlen, int timeout, URLContext *h, + int will_try_next) { struct pollfd p = {fd, POLLOUT, 0}; int ret; @@ -267,9 +218,13 @@ int ff_listen_connect(int fd, const struct sockaddr *addr, char errbuf[100]; ret = AVERROR(ret); av_strerror(ret, errbuf, sizeof(errbuf)); - av_log(h, AV_LOG_ERROR, - "Connection to %s failed: %s\n", - h->filename, errbuf); + if (will_try_next) + av_log(h, AV_LOG_WARNING, + "Connection to %s failed (%s), trying next address\n", + h->filename, errbuf); + else + av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n", + h->filename, errbuf); } default: return ret; @@ -277,3 +232,57 @@ int ff_listen_connect(int fd, const struct sockaddr *addr, } return ret; } + +static int match_host_pattern(const char *pattern, const char *hostname) +{ + int len_p, len_h; + if (!strcmp(pattern, "*")) + return 1; + // Skip a possible *. at the start of the pattern + if (pattern[0] == '*') + pattern++; + if (pattern[0] == '.') + pattern++; + len_p = strlen(pattern); + len_h = strlen(hostname); + if (len_p > len_h) + return 0; + // Simply check if the end of hostname is equal to 'pattern' + if (!strcmp(pattern, &hostname[len_h - len_p])) { + if (len_h == len_p) + return 1; // Exact match + if (hostname[len_h - len_p - 1] == '.') + return 1; // The matched substring is a domain and not just a substring of a domain + } + return 0; +} + +int ff_http_match_no_proxy(const char *no_proxy, const char *hostname) +{ + char *buf, *start; + int ret = 0; + if (!no_proxy) + return 0; + if (!hostname) + return 0; + buf = av_strdup(no_proxy); + if (!buf) + return 0; + start = buf; + while (start) { + char *sep, *next = NULL; + start += strspn(start, " ,"); + sep = start + strcspn(start, " ,"); + if (*sep) { + next = sep + 1; + *sep = '\0'; + } + if (match_host_pattern(start, hostname)) { + ret = 1; + break; + } + start = next; + } + av_free(buf); + return ret; +}