* qatar/master: network: factor out connect-listening code Conflicts: libavformat/network.h libavformat/tcp.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n2.0
| @@ -20,6 +20,7 @@ | |||
| #include "libavutil/avutil.h" | |||
| #include "network.h" | |||
| #include "url.h" | |||
| #include "libavcodec/internal.h" | |||
| #include "libavutil/mem.h" | |||
| #include "url.h" | |||
| @@ -241,3 +242,50 @@ int ff_listen_bind(int fd, const struct sockaddr *addr, | |||
| ff_socket_nonblock(ret, 1); | |||
| return ret; | |||
| } | |||
| int ff_listen_connect(int fd, const struct sockaddr *addr, | |||
| socklen_t addrlen, int rw_timeout, URLContext *h) | |||
| { | |||
| struct pollfd p = {fd, POLLOUT, 0}; | |||
| int64_t wait_started; | |||
| int ret; | |||
| socklen_t optlen; | |||
| ff_socket_nonblock(fd, 1); | |||
| while ((ret = connect(fd, addr, addrlen))) { | |||
| ret = ff_neterrno(); | |||
| switch (ret) { | |||
| case AVERROR(EINTR): | |||
| if (ff_check_interrupt(&h->interrupt_callback)) | |||
| return AVERROR_EXIT; | |||
| continue; | |||
| case AVERROR(EINPROGRESS): | |||
| case AVERROR(EAGAIN): | |||
| wait_started = av_gettime(); | |||
| do { | |||
| if (ff_check_interrupt(&h->interrupt_callback)) | |||
| return AVERROR_EXIT; | |||
| ret = poll(&p, 1, 100); | |||
| if (ret > 0) | |||
| break; | |||
| } while (!rw_timeout || (av_gettime() - wait_started < rw_timeout)); | |||
| if (ret <= 0) | |||
| return AVERROR(ETIMEDOUT); | |||
| optlen = sizeof(ret); | |||
| if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) | |||
| ret = AVUNERROR(ff_neterrno()); | |||
| if (ret != 0) { | |||
| char errbuf[100]; | |||
| ret = AVERROR(ret); | |||
| av_strerror(ret, errbuf, sizeof(errbuf)); | |||
| av_log(h, AV_LOG_ERROR, | |||
| "Connection to %s failed: %s\n", | |||
| h->filename, errbuf); | |||
| } | |||
| default: | |||
| return ret; | |||
| } | |||
| } | |||
| return ret; | |||
| } | |||
| @@ -28,6 +28,7 @@ | |||
| #include "libavutil/error.h" | |||
| #include "os_support.h" | |||
| #include "avio.h" | |||
| #include "url.h" | |||
| #if HAVE_UNISTD_H | |||
| #include <unistd.h> | |||
| @@ -224,5 +225,7 @@ int ff_is_multicast_address(struct sockaddr *addr); | |||
| int ff_listen_bind(int fd, const struct sockaddr *addr, | |||
| socklen_t addrlen, int timeout); | |||
| int ff_listen_connect(int fd, const struct sockaddr *addr, | |||
| socklen_t addrlen, int timeout, | |||
| URLContext *h); | |||
| #endif /* AVFORMAT_NETWORK_H */ | |||
| @@ -64,7 +64,6 @@ static int tcp_open(URLContext *h, const char *uri, int flags) | |||
| const char *p; | |||
| char buf[256]; | |||
| int ret; | |||
| socklen_t optlen; | |||
| char hostname[1024],proto[1024],path[1024]; | |||
| char portstr[10]; | |||
| h->rw_timeout = 5000000; | |||
| @@ -121,55 +120,16 @@ static int tcp_open(URLContext *h, const char *uri, int flags) | |||
| goto fail1; | |||
| } | |||
| } else { | |||
| redo: | |||
| ff_socket_nonblock(fd, 1); | |||
| ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); | |||
| } | |||
| if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, | |||
| h->rw_timeout, h)) < 0) { | |||
| if (ret < 0) { | |||
| struct pollfd p = {fd, POLLOUT, 0}; | |||
| int64_t wait_started; | |||
| ret = ff_neterrno(); | |||
| if (ret == AVERROR(EINTR)) { | |||
| if (ff_check_interrupt(&h->interrupt_callback)) { | |||
| ret = AVERROR_EXIT; | |||
| if (ret == AVERROR_EXIT) | |||
| goto fail1; | |||
| } | |||
| goto redo; | |||
| } | |||
| if (ret != AVERROR(EINPROGRESS) && | |||
| ret != AVERROR(EAGAIN)) | |||
| goto fail; | |||
| /* wait until we are connected or until abort */ | |||
| wait_started = av_gettime(); | |||
| do { | |||
| if (ff_check_interrupt(&h->interrupt_callback)) { | |||
| ret = AVERROR_EXIT; | |||
| goto fail1; | |||
| } | |||
| ret = poll(&p, 1, 100); | |||
| if (ret > 0) | |||
| break; | |||
| } while (!h->rw_timeout || (av_gettime() - wait_started < h->rw_timeout)); | |||
| if (ret <= 0) { | |||
| ret = AVERROR(ETIMEDOUT); | |||
| goto fail; | |||
| } | |||
| /* test error */ | |||
| optlen = sizeof(ret); | |||
| if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) | |||
| ret = AVUNERROR(ff_neterrno()); | |||
| if (ret != 0) { | |||
| char errbuf[100]; | |||
| ret = AVERROR(ret); | |||
| av_strerror(ret, errbuf, sizeof(errbuf)); | |||
| av_log(h, AV_LOG_ERROR, | |||
| "TCP connection to %s:%d failed: %s\n", | |||
| hostname, port, errbuf); | |||
| goto fail; | |||
| else | |||
| goto fail; | |||
| } | |||
| } | |||
| h->is_streamed = 1; | |||
| s->fd = fd; | |||
| freeaddrinfo(ai); | |||