proto: introduce listen option in tcp

This way is possible to have simple micro-server act like

ffmpeg -i file.nut -vcodec copy -acodec copy -f nut tcp://foo:1234?listen
This commit is contained in:
Luca Barbato 2011-03-04 01:41:22 +01:00
parent a013291d26
commit 3d42d4937b
2 changed files with 39 additions and 2 deletions

View File

@ -402,6 +402,23 @@ ffplay sap://[ff0e::2:7ffe]
Trasmission Control Protocol. Trasmission Control Protocol.
The required syntax for a TCP url is:
@example
tcp://@var{hostname}:@var{port}[?@var{options}]
@end example
@table @option
@item listen
Listen for an incoming connection
@example
ffmpeg -i @var{input} -f @var{format} tcp://@var{hostname}:@var{port}?listen
ffplay tcp://@var{hostname}:@var{port}
@end example
@end table
@section udp @section udp
User Datagram Protocol. User Datagram Protocol.

View File

@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include "avformat.h" #include "avformat.h"
#include "libavutil/parseutils.h"
#include <unistd.h> #include <unistd.h>
#include "internal.h" #include "internal.h"
#include "network.h" #include "network.h"
@ -38,6 +39,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
struct addrinfo hints, *ai, *cur_ai; struct addrinfo hints, *ai, *cur_ai;
int port, fd = -1; int port, fd = -1;
TCPContext *s = NULL; TCPContext *s = NULL;
int listen_socket = 0;
const char *p;
char buf[256];
int ret; int ret;
socklen_t optlen; socklen_t optlen;
char hostname[1024],proto[1024],path[1024]; char hostname[1024],proto[1024],path[1024];
@ -48,6 +52,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
if (strcmp(proto,"tcp") || port <= 0 || port >= 65536) if (strcmp(proto,"tcp") || port <= 0 || port >= 65536)
return AVERROR(EINVAL); return AVERROR(EINVAL);
p = strchr(uri, '?');
if (p) {
if (av_find_info_tag(buf, sizeof(buf), "listen", p))
listen_socket = 1;
}
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
@ -66,10 +75,21 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol);
if (fd < 0) if (fd < 0)
goto fail; goto fail;
ff_socket_nonblock(fd, 1);
if (listen_socket) {
int fd1;
ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
listen(fd, 1);
fd1 = accept(fd, NULL, NULL);
closesocket(fd);
fd = fd1;
} else {
redo: redo:
ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
}
ff_socket_nonblock(fd, 1);
if (ret < 0) { if (ret < 0) {
struct pollfd p = {fd, POLLOUT, 0}; struct pollfd p = {fd, POLLOUT, 0};
if (ff_neterrno() == AVERROR(EINTR)) { if (ff_neterrno() == AVERROR(EINTR)) {