Browse code

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

Luca Barbato authored on 2011/03/04 09:41:22
Showing 2 changed files
... ...
@@ -402,6 +402,23 @@ ffplay sap://[ff0e::2:7ffe]
402 402
 
403 403
 Trasmission Control Protocol.
404 404
 
405
+The required syntax for a TCP url is:
406
+@example
407
+tcp://@var{hostname}:@var{port}[?@var{options}]
408
+@end example
409
+
410
+@table @option
411
+
412
+@item listen
413
+Listen for an incoming connection
414
+
415
+@example
416
+ffmpeg -i @var{input} -f @var{format} tcp://@var{hostname}:@var{port}?listen
417
+ffplay tcp://@var{hostname}:@var{port}
418
+@end example
419
+
420
+@end table
421
+
405 422
 @section udp
406 423
 
407 424
 User Datagram Protocol.
... ...
@@ -19,6 +19,7 @@
19 19
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 20
  */
21 21
 #include "avformat.h"
22
+#include "libavutil/parseutils.h"
22 23
 #include <unistd.h>
23 24
 #include "internal.h"
24 25
 #include "network.h"
... ...
@@ -38,6 +39,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
38 38
     struct addrinfo hints, *ai, *cur_ai;
39 39
     int port, fd = -1;
40 40
     TCPContext *s = NULL;
41
+    int listen_socket = 0;
42
+    const char *p;
43
+    char buf[256];
41 44
     int ret;
42 45
     socklen_t optlen;
43 46
     char hostname[1024],proto[1024],path[1024];
... ...
@@ -48,6 +52,11 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
48 48
     if (strcmp(proto,"tcp") || port <= 0 || port >= 65536)
49 49
         return AVERROR(EINVAL);
50 50
 
51
+    p = strchr(uri, '?');
52
+    if (p) {
53
+        if (av_find_info_tag(buf, sizeof(buf), "listen", p))
54
+            listen_socket = 1;
55
+    }
51 56
     memset(&hints, 0, sizeof(hints));
52 57
     hints.ai_family = AF_UNSPEC;
53 58
     hints.ai_socktype = SOCK_STREAM;
... ...
@@ -66,10 +75,21 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
66 66
     fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol);
67 67
     if (fd < 0)
68 68
         goto fail;
69
-    ff_socket_nonblock(fd, 1);
70 69
 
70
+    if (listen_socket) {
71
+        int fd1;
72
+        ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
73
+        listen(fd, 1);
74
+        fd1 = accept(fd, NULL, NULL);
75
+        closesocket(fd);
76
+        fd = fd1;
77
+    } else {
71 78
  redo:
72
-    ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
79
+        ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
80
+    }
81
+
82
+    ff_socket_nonblock(fd, 1);
83
+
73 84
     if (ret < 0) {
74 85
         struct pollfd p = {fd, POLLOUT, 0};
75 86
         if (ff_neterrno() == AVERROR(EINTR)) {