• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "config_components.h"
22 
23 #include <fcntl.h>
24 #include "network.h"
25 #include "tls.h"
26 #include "url.h"
27 #include "libavutil/avassert.h"
28 #include "libavutil/mem.h"
29 #include "libavutil/time.h"
30 
ff_tls_init(void)31 int ff_tls_init(void)
32 {
33 #if CONFIG_TLS_PROTOCOL
34 #if CONFIG_OPENSSL
35     int ret;
36     if ((ret = ff_openssl_init()) < 0)
37         return ret;
38 #endif
39 #if CONFIG_GNUTLS
40     ff_gnutls_init();
41 #endif
42 #endif
43     return 0;
44 }
45 
ff_tls_deinit(void)46 void ff_tls_deinit(void)
47 {
48 #if CONFIG_TLS_PROTOCOL
49 #if CONFIG_OPENSSL
50     ff_openssl_deinit();
51 #endif
52 #if CONFIG_GNUTLS
53     ff_gnutls_deinit();
54 #endif
55 #endif
56 }
57 
ff_network_init(void)58 int ff_network_init(void)
59 {
60 #if HAVE_WINSOCK2_H
61     WSADATA wsaData;
62 
63     if (WSAStartup(MAKEWORD(1,1), &wsaData))
64         return 0;
65 #endif
66     return 1;
67 }
68 
ff_network_wait_fd(int fd,int write)69 int ff_network_wait_fd(int fd, int write)
70 {
71     int ev = write ? POLLOUT : POLLIN;
72     struct pollfd p = { .fd = fd, .events = ev, .revents = 0 };
73     int ret;
74     ret = poll(&p, 1, POLLING_TIME);
75     return ret < 0 ? ff_neterrno() : p.revents & (ev | POLLERR | POLLHUP) ? 0 : AVERROR(EAGAIN);
76 }
77 
ff_network_wait_fd_timeout(int fd,int write,int64_t timeout,AVIOInterruptCB * int_cb)78 int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb)
79 {
80     int ret;
81     int64_t wait_start = 0;
82 
83     while (1) {
84         if (ff_check_interrupt(int_cb))
85             return AVERROR_EXIT;
86         ret = ff_network_wait_fd(fd, write);
87         if (ret != AVERROR(EAGAIN))
88             return ret;
89         if (timeout > 0) {
90             if (!wait_start)
91                 wait_start = av_gettime_relative();
92             else if (av_gettime_relative() - wait_start > timeout)
93                 return AVERROR(ETIMEDOUT);
94         }
95     }
96 }
97 
ff_network_sleep_interruptible(int64_t timeout,AVIOInterruptCB * int_cb)98 int ff_network_sleep_interruptible(int64_t timeout, AVIOInterruptCB *int_cb)
99 {
100     int64_t wait_start = av_gettime_relative();
101 
102     while (1) {
103         int64_t time_left;
104 
105         if (ff_check_interrupt(int_cb))
106             return AVERROR_EXIT;
107 
108         time_left = timeout - (av_gettime_relative() - wait_start);
109         if (time_left <= 0)
110             return AVERROR(ETIMEDOUT);
111 
112         av_usleep(FFMIN(time_left, POLLING_TIME * 1000));
113     }
114 }
115 
ff_network_close(void)116 void ff_network_close(void)
117 {
118 #if HAVE_WINSOCK2_H
119     WSACleanup();
120 #endif
121 }
122 
123 #if HAVE_WINSOCK2_H
ff_neterrno(void)124 int ff_neterrno(void)
125 {
126     int err = WSAGetLastError();
127     switch (err) {
128     case WSAEWOULDBLOCK:
129         return AVERROR(EAGAIN);
130     case WSAEINTR:
131         return AVERROR(EINTR);
132     case WSAEPROTONOSUPPORT:
133         return AVERROR(EPROTONOSUPPORT);
134     case WSAETIMEDOUT:
135         return AVERROR(ETIMEDOUT);
136     case WSAECONNREFUSED:
137         return AVERROR(ECONNREFUSED);
138     case WSAEINPROGRESS:
139         return AVERROR(EINPROGRESS);
140     }
141     return -err;
142 }
143 #endif
144 
ff_is_multicast_address(struct sockaddr * addr)145 int ff_is_multicast_address(struct sockaddr *addr)
146 {
147     if (addr->sa_family == AF_INET) {
148         return IN_MULTICAST(ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr));
149     }
150 #if HAVE_STRUCT_SOCKADDR_IN6
151     if (addr->sa_family == AF_INET6) {
152         return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *)addr)->sin6_addr);
153     }
154 #endif
155 
156     return 0;
157 }
158 
ff_poll_interrupt(struct pollfd * p,nfds_t nfds,int timeout,AVIOInterruptCB * cb)159 static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout,
160                              AVIOInterruptCB *cb)
161 {
162     int runs = timeout / POLLING_TIME;
163     int ret = 0;
164 
165     do {
166         if (ff_check_interrupt(cb))
167             return AVERROR_EXIT;
168         ret = poll(p, nfds, POLLING_TIME);
169         if (ret != 0) {
170             if (ret < 0)
171                 ret = ff_neterrno();
172             if (ret == AVERROR(EINTR))
173                 continue;
174             break;
175         }
176     } while (timeout <= 0 || runs-- > 0);
177 
178     if (!ret)
179         return AVERROR(ETIMEDOUT);
180     return ret;
181 }
182 
ff_socket(int af,int type,int proto,void * logctx)183 int ff_socket(int af, int type, int proto, void *logctx)
184 {
185     int fd;
186 
187 #ifdef SOCK_CLOEXEC
188     fd = socket(af, type | SOCK_CLOEXEC, proto);
189     if (fd == -1 && errno == EINVAL)
190 #endif
191     {
192         fd = socket(af, type, proto);
193 #if HAVE_FCNTL
194         if (fd != -1) {
195             if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
196                 av_log(logctx, AV_LOG_DEBUG, "Failed to set close on exec\n");
197         }
198 #endif
199     }
200 #ifdef SO_NOSIGPIPE
201     if (fd != -1) {
202         if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &(int){1}, sizeof(int))) {
203              av_log(logctx, AV_LOG_WARNING, "setsockopt(SO_NOSIGPIPE) failed\n");
204         }
205     }
206 #endif
207     return fd;
208 }
209 
ff_listen(int fd,const struct sockaddr * addr,socklen_t addrlen,void * logctx)210 int ff_listen(int fd, const struct sockaddr *addr,
211               socklen_t addrlen, void *logctx)
212 {
213     int ret;
214     int reuse = 1;
215     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) {
216         av_log(logctx, AV_LOG_WARNING, "setsockopt(SO_REUSEADDR) failed\n");
217     }
218     ret = bind(fd, addr, addrlen);
219     if (ret)
220         return ff_neterrno();
221 
222     ret = listen(fd, 1);
223     if (ret)
224         return ff_neterrno();
225     return ret;
226 }
227 
ff_accept(int fd,int timeout,URLContext * h)228 int ff_accept(int fd, int timeout, URLContext *h)
229 {
230     int ret;
231     struct pollfd lp = { fd, POLLIN, 0 };
232 
233     ret = ff_poll_interrupt(&lp, 1, timeout, &h->interrupt_callback);
234     if (ret < 0)
235         return ret;
236 
237     ret = accept(fd, NULL, NULL);
238     if (ret < 0)
239         return ff_neterrno();
240     if (ff_socket_nonblock(ret, 1) < 0)
241         av_log(h, AV_LOG_DEBUG, "ff_socket_nonblock failed\n");
242 
243     return ret;
244 }
245 
ff_listen_bind(int fd,const struct sockaddr * addr,socklen_t addrlen,int timeout,URLContext * h)246 int ff_listen_bind(int fd, const struct sockaddr *addr,
247                    socklen_t addrlen, int timeout, URLContext *h)
248 {
249     int ret;
250     if ((ret = ff_listen(fd, addr, addrlen, h)) < 0)
251         return ret;
252     if ((ret = ff_accept(fd, timeout, h)) < 0)
253         return ret;
254     closesocket(fd);
255     return ret;
256 }
257 
ff_listen_connect(int fd,const struct sockaddr * addr,socklen_t addrlen,int timeout,URLContext * h,int will_try_next)258 int ff_listen_connect(int fd, const struct sockaddr *addr,
259                       socklen_t addrlen, int timeout, URLContext *h,
260                       int will_try_next)
261 {
262     struct pollfd p = {fd, POLLOUT, 0};
263     int ret;
264     socklen_t optlen;
265 
266     if (ff_socket_nonblock(fd, 1) < 0)
267         av_log(h, AV_LOG_DEBUG, "ff_socket_nonblock failed\n");
268 
269     while ((ret = connect(fd, addr, addrlen))) {
270         ret = ff_neterrno();
271         switch (ret) {
272         case AVERROR(EINTR):
273             if (ff_check_interrupt(&h->interrupt_callback))
274                 return AVERROR_EXIT;
275             continue;
276         case AVERROR(EINPROGRESS):
277         case AVERROR(EAGAIN):
278             ret = ff_poll_interrupt(&p, 1, timeout, &h->interrupt_callback);
279             if (ret < 0)
280                 return ret;
281             optlen = sizeof(ret);
282             if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen))
283                 ret = AVUNERROR(ff_neterrno());
284             if (ret != 0) {
285                 char errbuf[100];
286                 ret = AVERROR(ret);
287                 av_strerror(ret, errbuf, sizeof(errbuf));
288                 if (will_try_next)
289                     av_log(h, AV_LOG_WARNING,
290                            "Connection to %s failed (%s), trying next address\n",
291                            h->filename, errbuf);
292                 else
293                     av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n",
294                            h->filename, errbuf);
295             }
296         default:
297             return ret;
298         }
299     }
300     return ret;
301 }
302 
interleave_addrinfo(struct addrinfo * base)303 static void interleave_addrinfo(struct addrinfo *base)
304 {
305     struct addrinfo **next = &base->ai_next;
306     while (*next) {
307         struct addrinfo *cur = *next;
308         // Iterate forward until we find an entry of a different family.
309         if (cur->ai_family == base->ai_family) {
310             next = &cur->ai_next;
311             continue;
312         }
313         if (cur == base->ai_next) {
314             // If the first one following base is of a different family, just
315             // move base forward one step and continue.
316             base = cur;
317             next = &base->ai_next;
318             continue;
319         }
320         // Unchain cur from the rest of the list from its current spot.
321         *next = cur->ai_next;
322         // Hook in cur directly after base.
323         cur->ai_next = base->ai_next;
324         base->ai_next = cur;
325         // Restart with a new base. We know that before moving the cur element,
326         // everything between the previous base and cur had the same family,
327         // different from cur->ai_family. Therefore, we can keep next pointing
328         // where it was, and continue from there with base at the one after
329         // cur.
330         base = cur->ai_next;
331     }
332 }
333 
print_address_list(void * ctx,const struct addrinfo * addr,const char * title)334 static void print_address_list(void *ctx, const struct addrinfo *addr,
335                                const char *title)
336 {
337     char hostbuf[100], portbuf[20];
338     av_log(ctx, AV_LOG_DEBUG, "%s:\n", title);
339     while (addr) {
340         getnameinfo(addr->ai_addr, addr->ai_addrlen,
341                     hostbuf, sizeof(hostbuf), portbuf, sizeof(portbuf),
342                     NI_NUMERICHOST | NI_NUMERICSERV);
343         av_log(ctx, AV_LOG_DEBUG, "Address %s port %s\n", hostbuf, portbuf);
344         addr = addr->ai_next;
345     }
346 }
347 
348 struct ConnectionAttempt {
349     int fd;
350     int64_t deadline_us;
351     struct addrinfo *addr;
352 };
353 
354 // Returns < 0 on error, 0 on successfully started connection attempt,
355 // > 0 for a connection that succeeded already.
start_connect_attempt(struct ConnectionAttempt * attempt,struct addrinfo ** ptr,int timeout_ms,URLContext * h,void (* customize_fd)(void *,int),void * customize_ctx)356 static int start_connect_attempt(struct ConnectionAttempt *attempt,
357                                  struct addrinfo **ptr, int timeout_ms,
358                                  URLContext *h,
359                                  void (*customize_fd)(void *, int), void *customize_ctx)
360 {
361     struct addrinfo *ai = *ptr;
362     int ret;
363 
364     *ptr = ai->ai_next;
365 
366     attempt->fd = ff_socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol, h);
367     if (attempt->fd < 0)
368         return ff_neterrno();
369     attempt->deadline_us = av_gettime_relative() + timeout_ms * 1000;
370     attempt->addr = ai;
371 
372     ff_socket_nonblock(attempt->fd, 1);
373 
374     if (customize_fd)
375         customize_fd(customize_ctx, attempt->fd);
376 
377     while ((ret = connect(attempt->fd, ai->ai_addr, ai->ai_addrlen))) {
378         ret = ff_neterrno();
379         switch (ret) {
380         case AVERROR(EINTR):
381             if (ff_check_interrupt(&h->interrupt_callback)) {
382                 closesocket(attempt->fd);
383                 attempt->fd = -1;
384                 return AVERROR_EXIT;
385             }
386             continue;
387         case AVERROR(EINPROGRESS):
388         case AVERROR(EAGAIN):
389             return 0;
390         default:
391             closesocket(attempt->fd);
392             attempt->fd = -1;
393             return ret;
394         }
395     }
396     return 1;
397 }
398 
399 // Try a new connection to another address after 200 ms, as suggested in
400 // RFC 8305 (or sooner if an earlier attempt fails).
401 #define NEXT_ATTEMPT_DELAY_MS 200
402 
ff_connect_parallel(struct addrinfo * addrs,int timeout_ms_per_address,int parallel,URLContext * h,int * fd,void (* customize_fd)(void *,int),void * customize_ctx)403 int ff_connect_parallel(struct addrinfo *addrs, int timeout_ms_per_address,
404                         int parallel, URLContext *h, int *fd,
405                         void (*customize_fd)(void *, int), void *customize_ctx)
406 {
407     struct ConnectionAttempt attempts[3];
408     struct pollfd pfd[3];
409     int nb_attempts = 0, i, j;
410     int64_t next_attempt_us = av_gettime_relative(), next_deadline_us;
411     int last_err = AVERROR(EIO);
412     socklen_t optlen;
413     char errbuf[100], hostbuf[100], portbuf[20];
414 
415     if (parallel > FF_ARRAY_ELEMS(attempts))
416         parallel = FF_ARRAY_ELEMS(attempts);
417 
418     print_address_list(h, addrs, "Original list of addresses");
419     // This mutates the list, but the head of the list is still the same
420     // element, so the caller, who owns the list, doesn't need to get
421     // an updated pointer.
422     interleave_addrinfo(addrs);
423     print_address_list(h, addrs, "Interleaved list of addresses");
424 
425     while (nb_attempts > 0 || addrs) {
426         // Start a new connection attempt, if possible.
427         if (nb_attempts < parallel && addrs) {
428             getnameinfo(addrs->ai_addr, addrs->ai_addrlen,
429                         hostbuf, sizeof(hostbuf), portbuf, sizeof(portbuf),
430                         NI_NUMERICHOST | NI_NUMERICSERV);
431             av_log(h, AV_LOG_VERBOSE, "Starting connection attempt to %s port %s\n",
432                                       hostbuf, portbuf);
433             last_err = start_connect_attempt(&attempts[nb_attempts], &addrs,
434                                              timeout_ms_per_address, h,
435                                              customize_fd, customize_ctx);
436             if (last_err < 0) {
437                 av_strerror(last_err, errbuf, sizeof(errbuf));
438                 av_log(h, AV_LOG_VERBOSE, "Connected attempt failed: %s\n",
439                                           errbuf);
440                 continue;
441             }
442             if (last_err > 0) {
443                 for (i = 0; i < nb_attempts; i++)
444                     closesocket(attempts[i].fd);
445                 *fd = attempts[nb_attempts].fd;
446                 return 0;
447             }
448             pfd[nb_attempts].fd = attempts[nb_attempts].fd;
449             pfd[nb_attempts].events = POLLOUT;
450             next_attempt_us = av_gettime_relative() + NEXT_ATTEMPT_DELAY_MS * 1000;
451             nb_attempts++;
452         }
453 
454         av_assert0(nb_attempts > 0);
455         // The connection attempts are sorted from oldest to newest, so the
456         // first one will have the earliest deadline.
457         next_deadline_us = attempts[0].deadline_us;
458         // If we can start another attempt in parallel, wait until that time.
459         if (nb_attempts < parallel && addrs)
460             next_deadline_us = FFMIN(next_deadline_us, next_attempt_us);
461         last_err = ff_poll_interrupt(pfd, nb_attempts,
462                                      (next_deadline_us - av_gettime_relative())/1000,
463                                      &h->interrupt_callback);
464         if (last_err < 0 && last_err != AVERROR(ETIMEDOUT))
465             break;
466 
467         // Check the status from the poll output.
468         for (i = 0; i < nb_attempts; i++) {
469             last_err = 0;
470             if (pfd[i].revents) {
471                 // Some sort of action for this socket, check its status (either
472                 // a successful connection or an error).
473                 optlen = sizeof(last_err);
474                 if (getsockopt(attempts[i].fd, SOL_SOCKET, SO_ERROR, &last_err, &optlen))
475                     last_err = ff_neterrno();
476                 else if (last_err != 0)
477                     last_err = AVERROR(last_err);
478                 if (last_err == 0) {
479                     // Everything is ok, we seem to have a successful
480                     // connection. Close other sockets and return this one.
481                     for (j = 0; j < nb_attempts; j++)
482                         if (j != i)
483                             closesocket(attempts[j].fd);
484                     *fd = attempts[i].fd;
485                     getnameinfo(attempts[i].addr->ai_addr, attempts[i].addr->ai_addrlen,
486                                 hostbuf, sizeof(hostbuf), portbuf, sizeof(portbuf),
487                                 NI_NUMERICHOST | NI_NUMERICSERV);
488                     av_log(h, AV_LOG_VERBOSE, "Successfully connected to %s port %s\n",
489                                               hostbuf, portbuf);
490                     return 0;
491                 }
492             }
493             if (attempts[i].deadline_us < av_gettime_relative() && !last_err)
494                 last_err = AVERROR(ETIMEDOUT);
495             if (!last_err)
496                 continue;
497             // Error (or timeout) for this socket; close the socket and remove
498             // it from the attempts/pfd arrays, to let a new attempt start
499             // directly.
500             getnameinfo(attempts[i].addr->ai_addr, attempts[i].addr->ai_addrlen,
501                         hostbuf, sizeof(hostbuf), portbuf, sizeof(portbuf),
502                         NI_NUMERICHOST | NI_NUMERICSERV);
503             av_strerror(last_err, errbuf, sizeof(errbuf));
504             av_log(h, AV_LOG_VERBOSE, "Connection attempt to %s port %s "
505                                       "failed: %s\n", hostbuf, portbuf, errbuf);
506             closesocket(attempts[i].fd);
507             memmove(&attempts[i], &attempts[i + 1],
508                     (nb_attempts - i - 1) * sizeof(*attempts));
509             memmove(&pfd[i], &pfd[i + 1],
510                     (nb_attempts - i - 1) * sizeof(*pfd));
511             i--;
512             nb_attempts--;
513         }
514     }
515     for (i = 0; i < nb_attempts; i++)
516         closesocket(attempts[i].fd);
517     if (last_err >= 0)
518         last_err = AVERROR(ECONNREFUSED);
519     if (last_err != AVERROR_EXIT) {
520         av_strerror(last_err, errbuf, sizeof(errbuf));
521         av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n",
522                h->filename, errbuf);
523     }
524     return last_err;
525 }
526 
match_host_pattern(const char * pattern,const char * hostname)527 static int match_host_pattern(const char *pattern, const char *hostname)
528 {
529     int len_p, len_h;
530     if (!strcmp(pattern, "*"))
531         return 1;
532     // Skip a possible *. at the start of the pattern
533     if (pattern[0] == '*')
534         pattern++;
535     if (pattern[0] == '.')
536         pattern++;
537     len_p = strlen(pattern);
538     len_h = strlen(hostname);
539     if (len_p > len_h)
540         return 0;
541     // Simply check if the end of hostname is equal to 'pattern'
542     if (!strcmp(pattern, &hostname[len_h - len_p])) {
543         if (len_h == len_p)
544             return 1; // Exact match
545         if (hostname[len_h - len_p - 1] == '.')
546             return 1; // The matched substring is a domain and not just a substring of a domain
547     }
548     return 0;
549 }
550 
ff_http_match_no_proxy(const char * no_proxy,const char * hostname)551 int ff_http_match_no_proxy(const char *no_proxy, const char *hostname)
552 {
553     char *buf, *start;
554     int ret = 0;
555     if (!no_proxy)
556         return 0;
557     if (!hostname)
558         return 0;
559     buf = av_strdup(no_proxy);
560     if (!buf)
561         return 0;
562     start = buf;
563     while (start) {
564         char *sep, *next = NULL;
565         start += strspn(start, " ,");
566         sep = start + strcspn(start, " ,");
567         if (*sep) {
568             next = sep + 1;
569             *sep = '\0';
570         }
571         if (match_host_pattern(start, hostname)) {
572             ret = 1;
573             break;
574         }
575         start = next;
576     }
577     av_free(buf);
578     return ret;
579 }
580 
ff_log_net_error(void * ctx,int level,const char * prefix)581 void ff_log_net_error(void *ctx, int level, const char* prefix)
582 {
583     char errbuf[100];
584     av_strerror(ff_neterrno(), errbuf, sizeof(errbuf));
585     av_log(ctx, level, "%s: %s\n", prefix, errbuf);
586 }
587