Commit 54ddbb47 authored by Michael Niedermayer's avatar Michael Niedermayer

Merge remote-tracking branch 'qatar/master'

* qatar/master:
  network: factor out connect-listening code

Conflicts:
	libavformat/network.h
	libavformat/tcp.c
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents 4d4f5911 f849a77e
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment