diff --git a/libavformat/tcp.c b/libavformat/tcp.c index bc5406292d..d4b81c88e9 100644 --- a/libavformat/tcp.c +++ b/libavformat/tcp.c @@ -28,6 +28,8 @@ # include "barpainet.h" #endif #include +#include +#include typedef struct TCPContext { int fd; @@ -55,7 +57,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags) int port, fd = -1; TCPContext *s; const char *p; - + fd_set wfds; + int fd_max, ret; + struct timeval tv; + socklen_t optlen; + s = av_malloc(sizeof(TCPContext)); if (!s) return -ENOMEM; @@ -85,32 +91,72 @@ static int tcp_open(URLContext *h, const char *uri, int flags) fd = socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) goto fail; + fcntl(fd, F_SETFL, O_NONBLOCK); + + redo: + ret = connect(fd, (struct sockaddr *)&dest_addr, + sizeof(dest_addr)); + if (ret < 0) { + if (errno == EINTR) + goto redo; + if (errno != EINPROGRESS) + goto fail; - if (connect(fd, (struct sockaddr *)&dest_addr, - sizeof(dest_addr)) < 0) - goto fail; - + /* wait until we are connected or until abort */ + for(;;) { + if (url_interrupt_cb()) { + ret = -EINTR; + goto fail1; + } + fd_max = fd; + FD_ZERO(&wfds); + FD_SET(fd, &wfds); + tv.tv_sec = 0; + tv.tv_usec = 100 * 1000; + ret = select(fd_max + 1, NULL, &wfds, NULL, &tv); + if (ret > 0 && FD_ISSET(fd, &wfds)) + break; + } + + /* test error */ + optlen = sizeof(ret); + getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen); + if (ret != 0) + goto fail; + } s->fd = fd; return 0; fail: + ret = -EIO; + fail1: if (fd >= 0) close(fd); av_free(s); - return -EIO; + return ret; } static int tcp_read(URLContext *h, uint8_t *buf, int size) { TCPContext *s = h->priv_data; - int size1, len; + int size1, len, fd_max; + fd_set rfds; + struct timeval tv; size1 = size; while (size > 0) { -#ifdef CONFIG_BEOS_NETSERVER - len = recv (s->fd, buf, size, 0); + if (url_interrupt_cb()) + return -EINTR; + fd_max = s->fd; + FD_ZERO(&rfds); + FD_SET(s->fd, &rfds); + tv.tv_sec = 0; + tv.tv_usec = 100 * 1000; + select(fd_max + 1, &rfds, NULL, NULL, &tv); +#ifdef __BEOS__ + len = recv(s->fd, buf, size, 0); #else - len = read (s->fd, buf, size); + len = read(s->fd, buf, size); #endif if (len < 0) { if (errno != EINTR && errno != EAGAIN) @@ -133,14 +179,24 @@ static int tcp_read(URLContext *h, uint8_t *buf, int size) static int tcp_write(URLContext *h, uint8_t *buf, int size) { TCPContext *s = h->priv_data; - int ret, size1; + int ret, size1, fd_max; + fd_set wfds; + struct timeval tv; size1 = size; while (size > 0) { -#ifdef CONFIG_BEOS_NETSERVER - ret = send (s->fd, buf, size, 0); + if (url_interrupt_cb()) + return -EINTR; + fd_max = s->fd; + FD_ZERO(&wfds); + FD_SET(s->fd, &wfds); + tv.tv_sec = 0; + tv.tv_usec = 100 * 1000; + select(fd_max + 1, NULL, &wfds, NULL, &tv); +#ifdef __BEOS__ + ret = send(s->fd, buf, size, 0); #else - ret = write (s->fd, buf, size); + ret = write(s->fd, buf, size); #endif if (ret < 0 && errno != EINTR && errno != EAGAIN) #ifdef __BEOS__