1/* 2 * Copyright (c) 2007 The FFmpeg Project 3 * 4 * This file is part of FFmpeg. 5 * 6 * FFmpeg is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * FFmpeg is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with FFmpeg; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21#include <fcntl.h> 22#include "network.h" 23#include "url.h" 24#include "libavcodec/internal.h" 25#include "libavutil/avutil.h" 26#include "libavutil/mem.h" 27#include "libavutil/time.h" 28 29#if HAVE_THREADS 30#if HAVE_PTHREADS 31#include <pthread.h> 32#elif HAVE_OS2THREADS 33#include "compat/os2threads.h" 34#else 35#include "compat/w32pthreads.h" 36#endif 37#endif 38 39#if CONFIG_OPENSSL 40#include <openssl/ssl.h> 41static int openssl_init; 42#if HAVE_THREADS 43#include <openssl/crypto.h> 44pthread_mutex_t *openssl_mutexes; 45static void openssl_lock(int mode, int type, const char *file, int line) 46{ 47 if (mode & CRYPTO_LOCK) 48 pthread_mutex_lock(&openssl_mutexes[type]); 49 else 50 pthread_mutex_unlock(&openssl_mutexes[type]); 51} 52#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 53static unsigned long openssl_thread_id(void) 54{ 55 return (intptr_t) pthread_self(); 56} 57#endif 58#endif 59#endif 60#if CONFIG_GNUTLS 61#include <gnutls/gnutls.h> 62#if HAVE_THREADS && GNUTLS_VERSION_NUMBER <= 0x020b00 63#include <gcrypt.h> 64#include <errno.h> 65GCRY_THREAD_OPTION_PTHREAD_IMPL; 66#endif 67#endif 68 69void ff_tls_init(void) 70{ 71 avpriv_lock_avformat(); 72#if CONFIG_OPENSSL 73 if (!openssl_init) { 74 SSL_library_init(); 75 SSL_load_error_strings(); 76#if HAVE_THREADS 77 if (!CRYPTO_get_locking_callback()) { 78 int i; 79 openssl_mutexes = av_malloc_array(sizeof(pthread_mutex_t), CRYPTO_num_locks()); 80 for (i = 0; i < CRYPTO_num_locks(); i++) 81 pthread_mutex_init(&openssl_mutexes[i], NULL); 82 CRYPTO_set_locking_callback(openssl_lock); 83#if !defined(WIN32) && OPENSSL_VERSION_NUMBER < 0x10000000 84 CRYPTO_set_id_callback(openssl_thread_id); 85#endif 86 } 87#endif 88 } 89 openssl_init++; 90#endif 91#if CONFIG_GNUTLS 92#if HAVE_THREADS && GNUTLS_VERSION_NUMBER < 0x020b00 93 if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P) == 0) 94 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); 95#endif 96 gnutls_global_init(); 97#endif 98 avpriv_unlock_avformat(); 99} 100 101void ff_tls_deinit(void) 102{ 103 avpriv_lock_avformat(); 104#if CONFIG_OPENSSL 105 openssl_init--; 106 if (!openssl_init) { 107#if HAVE_THREADS 108 if (CRYPTO_get_locking_callback() == openssl_lock) { 109 int i; 110 CRYPTO_set_locking_callback(NULL); 111 for (i = 0; i < CRYPTO_num_locks(); i++) 112 pthread_mutex_destroy(&openssl_mutexes[i]); 113 av_free(openssl_mutexes); 114 } 115#endif 116 } 117#endif 118#if CONFIG_GNUTLS 119 gnutls_global_deinit(); 120#endif 121 avpriv_unlock_avformat(); 122} 123 124int ff_network_inited_globally; 125 126int ff_network_init(void) 127{ 128#if HAVE_WINSOCK2_H 129 WSADATA wsaData; 130#endif 131 132 if (!ff_network_inited_globally) 133 av_log(NULL, AV_LOG_WARNING, "Using network protocols without global " 134 "network initialization. Please use " 135 "avformat_network_init(), this will " 136 "become mandatory later.\n"); 137#if HAVE_WINSOCK2_H 138 if (WSAStartup(MAKEWORD(1,1), &wsaData)) 139 return 0; 140#endif 141 return 1; 142} 143 144int ff_network_wait_fd(int fd, int write) 145{ 146 int ev = write ? POLLOUT : POLLIN; 147 struct pollfd p = { .fd = fd, .events = ev, .revents = 0 }; 148 int ret; 149 ret = poll(&p, 1, 100); 150 return ret < 0 ? ff_neterrno() : p.revents & (ev | POLLERR | POLLHUP) ? 0 : AVERROR(EAGAIN); 151} 152 153int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb) 154{ 155 int ret; 156 int64_t wait_start = 0; 157 158 while (1) { 159 if (ff_check_interrupt(int_cb)) 160 return AVERROR_EXIT; 161 ret = ff_network_wait_fd(fd, write); 162 if (ret != AVERROR(EAGAIN)) 163 return ret; 164 if (timeout > 0) { 165 if (!wait_start) 166 wait_start = av_gettime_relative(); 167 else if (av_gettime_relative() - wait_start > timeout) 168 return AVERROR(ETIMEDOUT); 169 } 170 } 171} 172 173void ff_network_close(void) 174{ 175#if HAVE_WINSOCK2_H 176 WSACleanup(); 177#endif 178} 179 180#if HAVE_WINSOCK2_H 181int ff_neterrno(void) 182{ 183 int err = WSAGetLastError(); 184 switch (err) { 185 case WSAEWOULDBLOCK: 186 return AVERROR(EAGAIN); 187 case WSAEINTR: 188 return AVERROR(EINTR); 189 case WSAEPROTONOSUPPORT: 190 return AVERROR(EPROTONOSUPPORT); 191 case WSAETIMEDOUT: 192 return AVERROR(ETIMEDOUT); 193 case WSAECONNREFUSED: 194 return AVERROR(ECONNREFUSED); 195 case WSAEINPROGRESS: 196 return AVERROR(EINPROGRESS); 197 } 198 return -err; 199} 200#endif 201 202int ff_is_multicast_address(struct sockaddr *addr) 203{ 204 if (addr->sa_family == AF_INET) { 205 return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr)); 206 } 207#if HAVE_STRUCT_SOCKADDR_IN6 208 if (addr->sa_family == AF_INET6) { 209 return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr); 210 } 211#endif 212 213 return 0; 214} 215 216static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout, 217 AVIOInterruptCB *cb) 218{ 219 int runs = timeout / POLLING_TIME; 220 int ret = 0; 221 222 do { 223 if (ff_check_interrupt(cb)) 224 return AVERROR_EXIT; 225 ret = poll(p, nfds, POLLING_TIME); 226 if (ret != 0) 227 break; 228 } while (timeout <= 0 || runs-- > 0); 229 230 if (!ret) 231 return AVERROR(ETIMEDOUT); 232 if (ret < 0) 233 return AVERROR(errno); 234 return ret; 235} 236 237int ff_socket(int af, int type, int proto) 238{ 239 int fd; 240 241#ifdef SOCK_CLOEXEC 242 fd = socket(af, type | SOCK_CLOEXEC, proto); 243 if (fd == -1 && errno == EINVAL) 244#endif 245 { 246 fd = socket(af, type, proto); 247#if HAVE_FCNTL 248 if (fd != -1) { 249 if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) 250 av_log(NULL, AV_LOG_DEBUG, "Failed to set close on exec\n"); 251 } 252#endif 253 } 254 return fd; 255} 256 257int ff_listen_bind(int fd, const struct sockaddr *addr, 258 socklen_t addrlen, int timeout, URLContext *h) 259{ 260 int ret; 261 int reuse = 1; 262 struct pollfd lp = { fd, POLLIN, 0 }; 263 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) { 264 av_log(NULL, AV_LOG_WARNING, "setsockopt(SO_REUSEADDR) failed\n"); 265 } 266 ret = bind(fd, addr, addrlen); 267 if (ret) 268 return ff_neterrno(); 269 270 ret = listen(fd, 1); 271 if (ret) 272 return ff_neterrno(); 273 274 ret = ff_poll_interrupt(&lp, 1, timeout, &h->interrupt_callback); 275 if (ret < 0) 276 return ret; 277 278 ret = accept(fd, NULL, NULL); 279 if (ret < 0) 280 return ff_neterrno(); 281 282 closesocket(fd); 283 284 if (ff_socket_nonblock(ret, 1) < 0) 285 av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n"); 286 287 return ret; 288} 289 290int ff_listen_connect(int fd, const struct sockaddr *addr, 291 socklen_t addrlen, int timeout, URLContext *h, 292 int will_try_next) 293{ 294 struct pollfd p = {fd, POLLOUT, 0}; 295 int ret; 296 socklen_t optlen; 297 298 if (ff_socket_nonblock(fd, 1) < 0) 299 av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n"); 300 301 while ((ret = connect(fd, addr, addrlen))) { 302 ret = ff_neterrno(); 303 switch (ret) { 304 case AVERROR(EINTR): 305 if (ff_check_interrupt(&h->interrupt_callback)) 306 return AVERROR_EXIT; 307 continue; 308 case AVERROR(EINPROGRESS): 309 case AVERROR(EAGAIN): 310 ret = ff_poll_interrupt(&p, 1, timeout, &h->interrupt_callback); 311 if (ret < 0) 312 return ret; 313 optlen = sizeof(ret); 314 if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) 315 ret = AVUNERROR(ff_neterrno()); 316 if (ret != 0) { 317 char errbuf[100]; 318 ret = AVERROR(ret); 319 av_strerror(ret, errbuf, sizeof(errbuf)); 320 if (will_try_next) 321 av_log(h, AV_LOG_WARNING, 322 "Connection to %s failed (%s), trying next address\n", 323 h->filename, errbuf); 324 else 325 av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n", 326 h->filename, errbuf); 327 } 328 default: 329 return ret; 330 } 331 } 332 return ret; 333} 334 335static int match_host_pattern(const char *pattern, const char *hostname) 336{ 337 int len_p, len_h; 338 if (!strcmp(pattern, "*")) 339 return 1; 340 // Skip a possible *. at the start of the pattern 341 if (pattern[0] == '*') 342 pattern++; 343 if (pattern[0] == '.') 344 pattern++; 345 len_p = strlen(pattern); 346 len_h = strlen(hostname); 347 if (len_p > len_h) 348 return 0; 349 // Simply check if the end of hostname is equal to 'pattern' 350 if (!strcmp(pattern, &hostname[len_h - len_p])) { 351 if (len_h == len_p) 352 return 1; // Exact match 353 if (hostname[len_h - len_p - 1] == '.') 354 return 1; // The matched substring is a domain and not just a substring of a domain 355 } 356 return 0; 357} 358 359int ff_http_match_no_proxy(const char *no_proxy, const char *hostname) 360{ 361 char *buf, *start; 362 int ret = 0; 363 if (!no_proxy) 364 return 0; 365 if (!hostname) 366 return 0; 367 buf = av_strdup(no_proxy); 368 if (!buf) 369 return 0; 370 start = buf; 371 while (start) { 372 char *sep, *next = NULL; 373 start += strspn(start, " ,"); 374 sep = start + strcspn(start, " ,"); 375 if (*sep) { 376 next = sep + 1; 377 *sep = '\0'; 378 } 379 if (match_host_pattern(start, hostname)) { 380 ret = 1; 381 break; 382 } 383 start = next; 384 } 385 av_free(buf); 386 return ret; 387} 388