2 * Copyright (c) 2007 The FFmpeg Project
4 * This file is part of FFmpeg.
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.
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.
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
22 #include "config_components.h"
24 #if CONFIG_TLS_PROTOCOL && CONFIG_OPENSSL
25 #include <openssl/opensslv.h>
32 #include "libavutil/avassert.h"
33 #include "libavutil/mem.h"
34 #include "libavutil/time.h"
38 #if CONFIG_TLS_PROTOCOL
46 void ff_tls_deinit(void)
48 #if CONFIG_TLS_PROTOCOL
55 int ff_network_init(void)
60 if (WSAStartup(MAKEWORD(1,1), &wsaData
))
66 int ff_network_wait_fd(int fd
, int write
)
68 int ev
= write
? POLLOUT
: POLLIN
;
69 struct pollfd p
= { .fd
= fd
, .events
= ev
, .revents
= 0 };
71 ret
= poll(&p
, 1, POLLING_TIME
);
72 return ret
< 0 ? ff_neterrno() : p
.revents
& (ev
| POLLERR
| POLLHUP
) ? 0 : AVERROR(EAGAIN
);
75 int ff_network_wait_fd_timeout(int fd
, int write
, int64_t timeout
, AVIOInterruptCB
*int_cb
)
78 int64_t wait_start
= 0;
81 if (ff_check_interrupt(int_cb
))
83 ret
= ff_network_wait_fd(fd
, write
);
84 if (ret
!= AVERROR(EAGAIN
))
88 wait_start
= av_gettime_relative();
89 else if (av_gettime_relative() - wait_start
> timeout
)
90 return AVERROR(ETIMEDOUT
);
95 int ff_network_sleep_interruptible(int64_t timeout
, AVIOInterruptCB
*int_cb
)
97 int64_t wait_start
= av_gettime_relative();
102 if (ff_check_interrupt(int_cb
))
105 time_left
= timeout
- (av_gettime_relative() - wait_start
);
107 return AVERROR(ETIMEDOUT
);
109 av_usleep(FFMIN(time_left
, POLLING_TIME
* 1000));
113 void ff_network_close(void)
121 int ff_neterrno(void)
123 int err
= WSAGetLastError();
126 return AVERROR(EAGAIN
);
128 return AVERROR(EINTR
);
129 case WSAEPROTONOSUPPORT
:
130 return AVERROR(EPROTONOSUPPORT
);
132 return AVERROR(ETIMEDOUT
);
133 case WSAECONNREFUSED
:
134 return AVERROR(ECONNREFUSED
);
136 return AVERROR(EINPROGRESS
);
142 int ff_is_multicast_address(struct sockaddr
*addr
)
144 if (addr
->sa_family
== AF_INET
) {
145 return IN_MULTICAST(ntohl(((struct sockaddr_in
*)addr
)->sin_addr
.s_addr
));
147 #if HAVE_STRUCT_SOCKADDR_IN6
148 if (addr
->sa_family
== AF_INET6
) {
149 return IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6
*)addr
)->sin6_addr
);
156 static int ff_poll_interrupt(struct pollfd
*p
, nfds_t nfds
, int timeout
,
159 int runs
= timeout
/ POLLING_TIME
;
163 if (ff_check_interrupt(cb
))
165 ret
= poll(p
, nfds
, POLLING_TIME
);
169 if (ret
== AVERROR(EINTR
))
173 } while (timeout
<= 0 || runs
-- > 0);
176 return AVERROR(ETIMEDOUT
);
180 int ff_socket(int af
, int type
, int proto
, void *logctx
)
185 fd
= socket(af
, type
| SOCK_CLOEXEC
, proto
);
186 if (fd
== -1 && errno
== EINVAL
)
189 fd
= socket(af
, type
, proto
);
192 if (fcntl(fd
, F_SETFD
, FD_CLOEXEC
) == -1)
193 av_log(logctx
, AV_LOG_DEBUG
, "Failed to set close on exec\n");
199 if (setsockopt(fd
, SOL_SOCKET
, SO_NOSIGPIPE
, &(int){1}, sizeof(int))) {
200 av_log(logctx
, AV_LOG_WARNING
, "setsockopt(SO_NOSIGPIPE) failed\n");
207 int ff_listen(int fd
, const struct sockaddr
*addr
,
208 socklen_t addrlen
, void *logctx
)
212 if (setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &reuse
, sizeof(reuse
))) {
213 av_log(logctx
, AV_LOG_WARNING
, "setsockopt(SO_REUSEADDR) failed\n");
215 ret
= bind(fd
, addr
, addrlen
);
217 return ff_neterrno();
221 return ff_neterrno();
225 int ff_accept(int fd
, int timeout
, URLContext
*h
)
228 struct pollfd lp
= { fd
, POLLIN
, 0 };
230 ret
= ff_poll_interrupt(&lp
, 1, timeout
, &h
->interrupt_callback
);
234 ret
= accept(fd
, NULL
, NULL
);
236 return ff_neterrno();
237 if (ff_socket_nonblock(ret
, 1) < 0)
238 av_log(h
, AV_LOG_DEBUG
, "ff_socket_nonblock failed\n");
243 int ff_listen_bind(int fd
, const struct sockaddr
*addr
,
244 socklen_t addrlen
, int timeout
, URLContext
*h
)
247 if ((ret
= ff_listen(fd
, addr
, addrlen
, h
)) < 0)
249 if ((ret
= ff_accept(fd
, timeout
, h
)) < 0)
255 int ff_listen_connect(int fd
, const struct sockaddr
*addr
,
256 socklen_t addrlen
, int timeout
, URLContext
*h
,
259 struct pollfd p
= {fd
, POLLOUT
, 0};
263 if (ff_socket_nonblock(fd
, 1) < 0)
264 av_log(h
, AV_LOG_DEBUG
, "ff_socket_nonblock failed\n");
266 while ((ret
= connect(fd
, addr
, addrlen
))) {
270 if (ff_check_interrupt(&h
->interrupt_callback
))
273 case AVERROR(EINPROGRESS
):
274 case AVERROR(EAGAIN
):
275 ret
= ff_poll_interrupt(&p
, 1, timeout
, &h
->interrupt_callback
);
278 optlen
= sizeof(ret
);
279 if (getsockopt (fd
, SOL_SOCKET
, SO_ERROR
, &ret
, &optlen
))
280 ret
= AVUNERROR(ff_neterrno());
284 av_log(h
, AV_LOG_WARNING
,
285 "Connection to %s failed (%s), trying next address\n",
286 h
->filename
, av_err2str(ret
));
288 av_log(h
, AV_LOG_ERROR
, "Connection to %s failed: %s\n",
289 h
->filename
, av_err2str(ret
));
298 static void interleave_addrinfo(struct addrinfo
*base
)
300 struct addrinfo
**next
= &base
->ai_next
;
302 struct addrinfo
*cur
= *next
;
303 // Iterate forward until we find an entry of a different family.
304 if (cur
->ai_family
== base
->ai_family
) {
305 next
= &cur
->ai_next
;
308 if (cur
== base
->ai_next
) {
309 // If the first one following base is of a different family, just
310 // move base forward one step and continue.
312 next
= &base
->ai_next
;
315 // Unchain cur from the rest of the list from its current spot.
316 *next
= cur
->ai_next
;
317 // Hook in cur directly after base.
318 cur
->ai_next
= base
->ai_next
;
320 // Restart with a new base. We know that before moving the cur element,
321 // everything between the previous base and cur had the same family,
322 // different from cur->ai_family. Therefore, we can keep next pointing
323 // where it was, and continue from there with base at the one after
329 static void print_address_list(void *ctx
, const struct addrinfo
*addr
,
332 char hostbuf
[100], portbuf
[20];
333 av_log(ctx
, AV_LOG_DEBUG
, "%s:\n", title
);
335 getnameinfo(addr
->ai_addr
, addr
->ai_addrlen
,
336 hostbuf
, sizeof(hostbuf
), portbuf
, sizeof(portbuf
),
337 NI_NUMERICHOST
| NI_NUMERICSERV
);
338 av_log(ctx
, AV_LOG_DEBUG
, "Address %s port %s\n", hostbuf
, portbuf
);
339 addr
= addr
->ai_next
;
343 struct ConnectionAttempt
{
346 struct addrinfo
*addr
;
349 // Returns < 0 on error, 0 on successfully started connection attempt,
350 // > 0 for a connection that succeeded already.
351 static int start_connect_attempt(struct ConnectionAttempt
*attempt
,
352 struct addrinfo
**ptr
, int timeout_ms
,
354 int (*customize_fd
)(void *, int, int), void *customize_ctx
)
356 struct addrinfo
*ai
= *ptr
;
361 attempt
->fd
= ff_socket(ai
->ai_family
, ai
->ai_socktype
, ai
->ai_protocol
, h
);
363 return ff_neterrno();
364 attempt
->deadline_us
= av_gettime_relative() + timeout_ms
* 1000;
367 ff_socket_nonblock(attempt
->fd
, 1);
370 ret
= customize_fd(customize_ctx
, attempt
->fd
, ai
->ai_family
);
372 closesocket(attempt
->fd
);
378 while ((ret
= connect(attempt
->fd
, ai
->ai_addr
, ai
->ai_addrlen
))) {
382 if (ff_check_interrupt(&h
->interrupt_callback
)) {
383 closesocket(attempt
->fd
);
388 case AVERROR(EINPROGRESS
):
389 case AVERROR(EAGAIN
):
392 closesocket(attempt
->fd
);
400 // Try a new connection to another address after 200 ms, as suggested in
401 // RFC 8305 (or sooner if an earlier attempt fails).
402 #define NEXT_ATTEMPT_DELAY_MS 200
404 int ff_connect_parallel(struct addrinfo
*addrs
, int timeout_ms_per_address
,
405 int parallel
, URLContext
*h
, int *fd
,
406 int (*customize_fd
)(void *, int, int), void *customize_ctx
)
408 struct ConnectionAttempt attempts
[3];
409 struct pollfd pfd
[3];
410 int nb_attempts
= 0, i
, j
;
411 int64_t next_attempt_us
= av_gettime_relative(), next_deadline_us
;
412 int last_err
= AVERROR(EIO
);
414 char hostbuf
[100], portbuf
[20];
416 if (parallel
> FF_ARRAY_ELEMS(attempts
))
417 parallel
= FF_ARRAY_ELEMS(attempts
);
419 print_address_list(h
, addrs
, "Original list of addresses");
420 // This mutates the list, but the head of the list is still the same
421 // element, so the caller, who owns the list, doesn't need to get
422 // an updated pointer.
423 interleave_addrinfo(addrs
);
424 print_address_list(h
, addrs
, "Interleaved list of addresses");
426 while (nb_attempts
> 0 || addrs
) {
427 // Start a new connection attempt, if possible.
428 if (nb_attempts
< parallel
&& addrs
) {
429 getnameinfo(addrs
->ai_addr
, addrs
->ai_addrlen
,
430 hostbuf
, sizeof(hostbuf
), portbuf
, sizeof(portbuf
),
431 NI_NUMERICHOST
| NI_NUMERICSERV
);
432 av_log(h
, AV_LOG_VERBOSE
, "Starting connection attempt to %s port %s\n",
434 last_err
= start_connect_attempt(&attempts
[nb_attempts
], &addrs
,
435 timeout_ms_per_address
, h
,
436 customize_fd
, customize_ctx
);
438 av_log(h
, AV_LOG_VERBOSE
, "Connected attempt failed: %s\n",
439 av_err2str(last_err
));
443 for (i
= 0; i
< nb_attempts
; i
++)
444 closesocket(attempts
[i
].fd
);
445 *fd
= attempts
[nb_attempts
].fd
;
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;
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
))
467 // Check the status from the poll output.
468 for (i
= 0; i
< nb_attempts
; i
++) {
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
);
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
++)
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",
493 if (attempts
[i
].deadline_us
< av_gettime_relative() && !last_err
)
494 last_err
= AVERROR(ETIMEDOUT
);
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
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_log(h
, AV_LOG_VERBOSE
, "Connection attempt to %s port %s "
504 "failed: %s\n", hostbuf
, portbuf
, av_err2str(last_err
));
505 closesocket(attempts
[i
].fd
);
506 memmove(&attempts
[i
], &attempts
[i
+ 1],
507 (nb_attempts
- i
- 1) * sizeof(*attempts
));
508 memmove(&pfd
[i
], &pfd
[i
+ 1],
509 (nb_attempts
- i
- 1) * sizeof(*pfd
));
514 for (i
= 0; i
< nb_attempts
; i
++)
515 closesocket(attempts
[i
].fd
);
517 last_err
= AVERROR(ECONNREFUSED
);
518 if (last_err
!= AVERROR_EXIT
) {
519 av_log(h
, AV_LOG_ERROR
, "Connection to %s failed: %s\n",
520 h
->filename
, av_err2str(last_err
));
525 static int match_host_pattern(const char *pattern
, const char *hostname
)
528 if (!strcmp(pattern
, "*"))
530 // Skip a possible *. at the start of the pattern
531 if (pattern
[0] == '*')
533 if (pattern
[0] == '.')
535 len_p
= strlen(pattern
);
536 len_h
= strlen(hostname
);
539 // Simply check if the end of hostname is equal to 'pattern'
540 if (!strcmp(pattern
, &hostname
[len_h
- len_p
])) {
542 return 1; // Exact match
543 if (hostname
[len_h
- len_p
- 1] == '.')
544 return 1; // The matched substring is a domain and not just a substring of a domain
549 int ff_http_match_no_proxy(const char *no_proxy
, const char *hostname
)
557 buf
= av_strdup(no_proxy
);
562 char *sep
, *next
= NULL
;
563 start
+= strspn(start
, " ,");
564 sep
= start
+ strcspn(start
, " ,");
569 if (match_host_pattern(start
, hostname
)) {
579 void ff_log_net_error(void *ctx
, int level
, const char* prefix
)
581 av_log(ctx
, level
, "%s: %s\n", prefix
, av_err2str(ff_neterrno()));