LCOV - code coverage report
Current view: top level - libavformat - network.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 46 157 29.3 %
Date: 2018-05-20 11:54:08 Functions: 6 16 37.5 %

          Line data    Source code
       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 "tls.h"
      24             : #include "url.h"
      25             : #include "libavcodec/internal.h"
      26             : #include "libavutil/avutil.h"
      27             : #include "libavutil/mem.h"
      28             : #include "libavutil/time.h"
      29             : 
      30        5681 : int ff_tls_init(void)
      31             : {
      32             : #if CONFIG_TLS_PROTOCOL
      33             : #if CONFIG_OPENSSL
      34             :     int ret;
      35             :     if ((ret = ff_openssl_init()) < 0)
      36             :         return ret;
      37             : #endif
      38             : #if CONFIG_GNUTLS
      39             :     ff_gnutls_init();
      40             : #endif
      41             : #endif
      42        5681 :     return 0;
      43             : }
      44             : 
      45        5681 : void ff_tls_deinit(void)
      46             : {
      47             : #if CONFIG_TLS_PROTOCOL
      48             : #if CONFIG_OPENSSL
      49             :     ff_openssl_deinit();
      50             : #endif
      51             : #if CONFIG_GNUTLS
      52             :     ff_gnutls_deinit();
      53             : #endif
      54             : #endif
      55        5681 : }
      56             : 
      57        5681 : int ff_network_init(void)
      58             : {
      59             : #if HAVE_WINSOCK2_H
      60             :     WSADATA wsaData;
      61             : 
      62             :     if (WSAStartup(MAKEWORD(1,1), &wsaData))
      63             :         return 0;
      64             : #endif
      65        5681 :     return 1;
      66             : }
      67             : 
      68           0 : int ff_network_wait_fd(int fd, int write)
      69             : {
      70           0 :     int ev = write ? POLLOUT : POLLIN;
      71           0 :     struct pollfd p = { .fd = fd, .events = ev, .revents = 0 };
      72             :     int ret;
      73           0 :     ret = poll(&p, 1, POLLING_TIME);
      74           0 :     return ret < 0 ? ff_neterrno() : p.revents & (ev | POLLERR | POLLHUP) ? 0 : AVERROR(EAGAIN);
      75             : }
      76             : 
      77           0 : int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb)
      78             : {
      79             :     int ret;
      80           0 :     int64_t wait_start = 0;
      81             : 
      82             :     while (1) {
      83           0 :         if (ff_check_interrupt(int_cb))
      84           0 :             return AVERROR_EXIT;
      85           0 :         ret = ff_network_wait_fd(fd, write);
      86           0 :         if (ret != AVERROR(EAGAIN))
      87           0 :             return ret;
      88           0 :         if (timeout > 0) {
      89           0 :             if (!wait_start)
      90           0 :                 wait_start = av_gettime_relative();
      91           0 :             else if (av_gettime_relative() - wait_start > timeout)
      92           0 :                 return AVERROR(ETIMEDOUT);
      93             :         }
      94             :     }
      95             : }
      96             : 
      97           0 : int ff_network_sleep_interruptible(int64_t timeout, AVIOInterruptCB *int_cb)
      98             : {
      99           0 :     int64_t wait_start = av_gettime_relative();
     100             : 
     101           0 :     while (1) {
     102             :         int64_t time_left;
     103             : 
     104           0 :         if (ff_check_interrupt(int_cb))
     105           0 :             return AVERROR_EXIT;
     106             : 
     107           0 :         time_left = timeout - (av_gettime_relative() - wait_start);
     108           0 :         if (time_left <= 0)
     109           0 :             return AVERROR(ETIMEDOUT);
     110             : 
     111           0 :         av_usleep(FFMIN(time_left, POLLING_TIME * 1000));
     112             :     }
     113             : }
     114             : 
     115        5681 : void ff_network_close(void)
     116             : {
     117             : #if HAVE_WINSOCK2_H
     118             :     WSACleanup();
     119             : #endif
     120        5681 : }
     121             : 
     122             : #if HAVE_WINSOCK2_H
     123             : int ff_neterrno(void)
     124             : {
     125             :     int err = WSAGetLastError();
     126             :     switch (err) {
     127             :     case WSAEWOULDBLOCK:
     128             :         return AVERROR(EAGAIN);
     129             :     case WSAEINTR:
     130             :         return AVERROR(EINTR);
     131             :     case WSAEPROTONOSUPPORT:
     132             :         return AVERROR(EPROTONOSUPPORT);
     133             :     case WSAETIMEDOUT:
     134             :         return AVERROR(ETIMEDOUT);
     135             :     case WSAECONNREFUSED:
     136             :         return AVERROR(ECONNREFUSED);
     137             :     case WSAEINPROGRESS:
     138             :         return AVERROR(EINPROGRESS);
     139             :     }
     140             :     return -err;
     141             : }
     142             : #endif
     143             : 
     144           0 : int ff_is_multicast_address(struct sockaddr *addr)
     145             : {
     146           0 :     if (addr->sa_family == AF_INET) {
     147           0 :         return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr));
     148             :     }
     149             : #if HAVE_STRUCT_SOCKADDR_IN6
     150           0 :     if (addr->sa_family == AF_INET6) {
     151           0 :         return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr);
     152             :     }
     153             : #endif
     154             : 
     155           0 :     return 0;
     156             : }
     157             : 
     158           0 : static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout,
     159             :                              AVIOInterruptCB *cb)
     160             : {
     161           0 :     int runs = timeout / POLLING_TIME;
     162           0 :     int ret = 0;
     163             : 
     164             :     do {
     165           0 :         if (ff_check_interrupt(cb))
     166           0 :             return AVERROR_EXIT;
     167           0 :         ret = poll(p, nfds, POLLING_TIME);
     168           0 :         if (ret != 0)
     169           0 :             break;
     170           0 :     } while (timeout <= 0 || runs-- > 0);
     171             : 
     172           0 :     if (!ret)
     173           0 :         return AVERROR(ETIMEDOUT);
     174           0 :     if (ret < 0)
     175           0 :         return ff_neterrno();
     176           0 :     return ret;
     177             : }
     178             : 
     179           0 : int ff_socket(int af, int type, int proto)
     180             : {
     181             :     int fd;
     182             : 
     183             : #ifdef SOCK_CLOEXEC
     184           0 :     fd = socket(af, type | SOCK_CLOEXEC, proto);
     185           0 :     if (fd == -1 && errno == EINVAL)
     186             : #endif
     187             :     {
     188           0 :         fd = socket(af, type, proto);
     189             : #if HAVE_FCNTL
     190           0 :         if (fd != -1) {
     191           0 :             if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
     192           0 :                 av_log(NULL, AV_LOG_DEBUG, "Failed to set close on exec\n");
     193             :         }
     194             : #endif
     195             :     }
     196             : #ifdef SO_NOSIGPIPE
     197             :     if (fd != -1)
     198             :         setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &(int){1}, sizeof(int));
     199             : #endif
     200           0 :     return fd;
     201             : }
     202             : 
     203           0 : int ff_listen(int fd, const struct sockaddr *addr,
     204             :               socklen_t addrlen)
     205             : {
     206             :     int ret;
     207           0 :     int reuse = 1;
     208           0 :     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) {
     209           0 :         av_log(NULL, AV_LOG_WARNING, "setsockopt(SO_REUSEADDR) failed\n");
     210             :     }
     211           0 :     ret = bind(fd, addr, addrlen);
     212           0 :     if (ret)
     213           0 :         return ff_neterrno();
     214             : 
     215           0 :     ret = listen(fd, 1);
     216           0 :     if (ret)
     217           0 :         return ff_neterrno();
     218           0 :     return ret;
     219             : }
     220             : 
     221           0 : int ff_accept(int fd, int timeout, URLContext *h)
     222             : {
     223             :     int ret;
     224           0 :     struct pollfd lp = { fd, POLLIN, 0 };
     225             : 
     226           0 :     ret = ff_poll_interrupt(&lp, 1, timeout, &h->interrupt_callback);
     227           0 :     if (ret < 0)
     228           0 :         return ret;
     229             : 
     230           0 :     ret = accept(fd, NULL, NULL);
     231           0 :     if (ret < 0)
     232           0 :         return ff_neterrno();
     233           0 :     if (ff_socket_nonblock(ret, 1) < 0)
     234           0 :         av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n");
     235             : 
     236           0 :     return ret;
     237             : }
     238             : 
     239           0 : int ff_listen_bind(int fd, const struct sockaddr *addr,
     240             :                    socklen_t addrlen, int timeout, URLContext *h)
     241             : {
     242             :     int ret;
     243           0 :     if ((ret = ff_listen(fd, addr, addrlen)) < 0)
     244           0 :         return ret;
     245           0 :     if ((ret = ff_accept(fd, timeout, h)) < 0)
     246           0 :         return ret;
     247           0 :     closesocket(fd);
     248           0 :     return ret;
     249             : }
     250             : 
     251           0 : int ff_listen_connect(int fd, const struct sockaddr *addr,
     252             :                       socklen_t addrlen, int timeout, URLContext *h,
     253             :                       int will_try_next)
     254             : {
     255           0 :     struct pollfd p = {fd, POLLOUT, 0};
     256             :     int ret;
     257             :     socklen_t optlen;
     258             : 
     259           0 :     if (ff_socket_nonblock(fd, 1) < 0)
     260           0 :         av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n");
     261             : 
     262           0 :     while ((ret = connect(fd, addr, addrlen))) {
     263           0 :         ret = ff_neterrno();
     264           0 :         switch (ret) {
     265           0 :         case AVERROR(EINTR):
     266           0 :             if (ff_check_interrupt(&h->interrupt_callback))
     267           0 :                 return AVERROR_EXIT;
     268           0 :             continue;
     269           0 :         case AVERROR(EINPROGRESS):
     270             :         case AVERROR(EAGAIN):
     271           0 :             ret = ff_poll_interrupt(&p, 1, timeout, &h->interrupt_callback);
     272           0 :             if (ret < 0)
     273           0 :                 return ret;
     274           0 :             optlen = sizeof(ret);
     275           0 :             if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen))
     276           0 :                 ret = AVUNERROR(ff_neterrno());
     277           0 :             if (ret != 0) {
     278             :                 char errbuf[100];
     279           0 :                 ret = AVERROR(ret);
     280           0 :                 av_strerror(ret, errbuf, sizeof(errbuf));
     281           0 :                 if (will_try_next)
     282           0 :                     av_log(h, AV_LOG_WARNING,
     283             :                            "Connection to %s failed (%s), trying next address\n",
     284             :                            h->filename, errbuf);
     285             :                 else
     286           0 :                     av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n",
     287             :                            h->filename, errbuf);
     288             :             }
     289             :         default:
     290           0 :             return ret;
     291             :         }
     292             :     }
     293           0 :     return ret;
     294             : }
     295             : 
     296          15 : static int match_host_pattern(const char *pattern, const char *hostname)
     297             : {
     298             :     int len_p, len_h;
     299          15 :     if (!strcmp(pattern, "*"))
     300           1 :         return 1;
     301             :     // Skip a possible *. at the start of the pattern
     302          14 :     if (pattern[0] == '*')
     303           2 :         pattern++;
     304          14 :     if (pattern[0] == '.')
     305           3 :         pattern++;
     306          14 :     len_p = strlen(pattern);
     307          14 :     len_h = strlen(hostname);
     308          14 :     if (len_p > len_h)
     309           5 :         return 0;
     310             :     // Simply check if the end of hostname is equal to 'pattern'
     311           9 :     if (!strcmp(pattern, &hostname[len_h - len_p])) {
     312           6 :         if (len_h == len_p)
     313           4 :             return 1; // Exact match
     314           2 :         if (hostname[len_h - len_p - 1] == '.')
     315           1 :             return 1; // The matched substring is a domain and not just a substring of a domain
     316             :     }
     317           4 :     return 0;
     318             : }
     319             : 
     320           9 : int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
     321             : {
     322             :     char *buf, *start;
     323           9 :     int ret = 0;
     324           9 :     if (!no_proxy)
     325           1 :         return 0;
     326           8 :     if (!hostname)
     327           0 :         return 0;
     328           8 :     buf = av_strdup(no_proxy);
     329           8 :     if (!buf)
     330           0 :         return 0;
     331           8 :     start = buf;
     332          25 :     while (start) {
     333          15 :         char *sep, *next = NULL;
     334          15 :         start += strspn(start, " ,");
     335          15 :         sep = start + strcspn(start, " ,");
     336          15 :         if (*sep) {
     337           7 :             next = sep + 1;
     338           7 :             *sep = '\0';
     339             :         }
     340          15 :         if (match_host_pattern(start, hostname)) {
     341           6 :             ret = 1;
     342           6 :             break;
     343             :         }
     344           9 :         start = next;
     345             :     }
     346           8 :     av_free(buf);
     347           8 :     return ret;
     348             : }

Generated by: LCOV version 1.13