mirror of https://git.ffmpeg.org/ffmpeg.git
network: factor out connect-listening code
Introduce ff_listen_connect, to be shared with the other non-tcp network protocols.
This commit is contained in:
parent
28306e6d62
commit
f849a77e67
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "network.h"
|
||||
#include "url.h"
|
||||
#include "libavcodec/internal.h"
|
||||
#include "libavutil/mem.h"
|
||||
|
||||
|
@ -216,3 +217,48 @@ 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 timeout, URLContext *h)
|
||||
{
|
||||
struct pollfd p = {fd, POLLOUT, 0};
|
||||
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):
|
||||
while (timeout--) {
|
||||
if (ff_check_interrupt(&h->interrupt_callback))
|
||||
return AVERROR_EXIT;
|
||||
ret = poll(&p, 1, 100);
|
||||
if (ret > 0)
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "config.h"
|
||||
#include "libavutil/error.h"
|
||||
#include "os_support.h"
|
||||
#include "url.h"
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
|
@ -211,5 +212,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 */
|
||||
|
|
|
@ -42,7 +42,6 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
|
|||
const char *p;
|
||||
char buf[256];
|
||||
int ret;
|
||||
socklen_t optlen;
|
||||
int timeout = 100, listen_timeout = -1;
|
||||
char hostname[1024],proto[1024],path[1024];
|
||||
char portstr[10];
|
||||
|
@ -98,53 +97,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,
|
||||
timeout, h)) < 0) {
|
||||
|
||||
if (ret == AVERROR_EXIT)
|
||||
goto fail1;
|
||||
else
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
struct pollfd p = {fd, POLLOUT, 0};
|
||||
ret = ff_neterrno();
|
||||
if (ret == AVERROR(EINTR)) {
|
||||
if (ff_check_interrupt(&h->interrupt_callback)) {
|
||||
ret = AVERROR_EXIT;
|
||||
goto fail1;
|
||||
}
|
||||
goto redo;
|
||||
}
|
||||
if (ret != AVERROR(EINPROGRESS) &&
|
||||
ret != AVERROR(EAGAIN))
|
||||
goto fail;
|
||||
|
||||
/* wait until we are connected or until abort */
|
||||
while(timeout--) {
|
||||
if (ff_check_interrupt(&h->interrupt_callback)) {
|
||||
ret = AVERROR_EXIT;
|
||||
goto fail1;
|
||||
}
|
||||
ret = poll(&p, 1, 100);
|
||||
if (ret > 0)
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
h->is_streamed = 1;
|
||||
s->fd = fd;
|
||||
freeaddrinfo(ai);
|
||||
|
|
Loading…
Reference in New Issue