diff --git a/libavformat/tcp.c b/libavformat/tcp.c index 8bff9a3867..ea41f2e986 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -70,6 +70,27 @@ static const AVClass tcp_class = { .version = LIBAVUTIL_VERSION_INT, }; +static void customize_fd(void *ctx, int fd) +{ + TCPContext *s = ctx; + /* Set the socket's send or receive buffer sizes, if specified. + If unspecified or setting fails, system default is used. */ + if (s->recv_buffer_size > 0) { + setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &s->recv_buffer_size, sizeof (s->recv_buffer_size)); + } + if (s->send_buffer_size > 0) { + setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size)); + } + if (s->tcp_nodelay > 0) { + setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &s->tcp_nodelay, sizeof (s->tcp_nodelay)); + } +#if !HAVE_WINSOCK2_H + if (s->tcp_mss > 0) { + setsockopt (fd, IPPROTO_TCP, TCP_MAXSEG, &s->tcp_mss, sizeof (s->tcp_mss)); + } +#endif /* !HAVE_WINSOCK2_H */ +} + /* return non zero if error */ static int tcp_open(URLContext *h, const char *uri, int flags) { @@ -129,7 +150,6 @@ static int tcp_open(URLContext *h, const char *uri, int flags) cur_ai = ai; - restart: #if HAVE_STRUCT_SOCKADDR_IN6 // workaround for IOS9 getaddrinfo in IPv6 only network use hardcode IPv4 address can not resolve port number. if (cur_ai->ai_family == AF_INET6){ @@ -140,38 +160,20 @@ static int tcp_open(URLContext *h, const char *uri, int flags) } #endif - fd = ff_socket(cur_ai->ai_family, - cur_ai->ai_socktype, - cur_ai->ai_protocol); - if (fd < 0) { - ret = ff_neterrno(); - goto fail; - } - - /* Set the socket's send or receive buffer sizes, if specified. - If unspecified or setting fails, system default is used. */ - if (s->recv_buffer_size > 0) { - if (setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &s->recv_buffer_size, sizeof (s->recv_buffer_size))) { - ff_log_net_error(h, AV_LOG_WARNING, "setsockopt(SO_RCVBUF)"); + if (s->listen > 0) { + while (cur_ai && fd < 0) { + fd = ff_socket(cur_ai->ai_family, + cur_ai->ai_socktype, + cur_ai->ai_protocol); + if (fd < 0) { + ret = ff_neterrno(); + cur_ai = cur_ai->ai_next; + } } + if (fd < 0) + goto fail1; + customize_fd(s, fd); } - if (s->send_buffer_size > 0) { - if (setsockopt (fd, SOL_SOCKET, SO_SNDBUF, &s->send_buffer_size, sizeof (s->send_buffer_size))) { - ff_log_net_error(h, AV_LOG_WARNING, "setsockopt(SO_SNDBUF)"); - } - } - if (s->tcp_nodelay > 0) { - if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &s->tcp_nodelay, sizeof (s->tcp_nodelay))) { - ff_log_net_error(h, AV_LOG_WARNING, "setsockopt(TCP_NODELAY)"); - } - } -#if !HAVE_WINSOCK2_H - if (s->tcp_mss > 0) { - if (setsockopt (fd, IPPROTO_TCP, TCP_MAXSEG, &s->tcp_mss, sizeof (s->tcp_mss))) { - ff_log_net_error(h, AV_LOG_WARNING, "setsockopt(TCP_MAXSEG)"); - } - } -#endif /* !HAVE_WINSOCK2_H */ if (s->listen == 2) { // multi-client @@ -185,14 +187,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) // Socket descriptor already closed here. Safe to overwrite to client one. fd = ret; } else { - if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, - s->open_timeout / 1000, h, !!cur_ai->ai_next)) < 0) { - - if (ret == AVERROR_EXIT) - goto fail1; - else - goto fail; - } + ret = ff_connect_parallel(ai, s->open_timeout / 1000, 3, h, &fd, customize_fd, s); + if (ret < 0) + goto fail1; } h->is_streamed = 1; @@ -201,15 +198,6 @@ static int tcp_open(URLContext *h, const char *uri, int flags) freeaddrinfo(ai); return 0; - fail: - if (cur_ai->ai_next) { - /* Retry with the next sockaddr */ - cur_ai = cur_ai->ai_next; - if (fd >= 0) - closesocket(fd); - ret = 0; - goto restart; - } fail1: if (fd >= 0) closesocket(fd);