On Wed, Jul 1, 2015 at 4:10 PM, Nicolas George <geo...@nsup.org> wrote: > Le duodi 12 messidor, an CCXXIII, Stephan Holljes a écrit : >> This might be a stupid question, but how would I go about that? Just >> use open() and read() from stdio.h or are there structs that allow me >> to do that even more easily? > > You must use the avio family of function, not the OS functions directly. You > can have a look at tools/aviocat.c, it is rather simple and does a good > chunk of what your server needs to do per client. > >> From b0f0caa700b8cbd0352304de703d8191bf0ac922 Mon Sep 17 00:00:00 2001 >> From: Stephan Holljes <klaxa1...@googlemail.com> >> Date: Tue, 30 Jun 2015 07:42:14 +0200 >> Subject: [PATCH 1/8] lavf/network: split ff_listen_bind into ff_listen and >> ff_accept >> >> Signed-off-by: Stephan Holljes <klaxa1...@googlemail.com> >> --- >> libavformat/network.c | 27 +++++++++++++++++++++------ >> libavformat/network.h | 21 +++++++++++++++++++++ >> 2 files changed, 42 insertions(+), 6 deletions(-) >> >> diff --git a/libavformat/network.c b/libavformat/network.c >> index 47ade8c..8d61746 100644 >> --- a/libavformat/network.c >> +++ b/libavformat/network.c >> @@ -187,12 +187,11 @@ int ff_socket(int af, int type, int proto) >> return fd; >> } >> >> -int ff_listen_bind(int fd, const struct sockaddr *addr, >> - socklen_t addrlen, int timeout, URLContext *h) >> +int ff_listen(int fd, const struct sockaddr *addr, >> + socklen_t addrlen) >> { >> int ret; >> int reuse = 1; >> - struct pollfd lp = { fd, POLLIN, 0 }; >> if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) { >> av_log(NULL, AV_LOG_WARNING, "setsockopt(SO_REUSEADDR) failed\n"); >> } >> @@ -203,6 +202,13 @@ int ff_listen_bind(int fd, const struct sockaddr *addr, >> ret = listen(fd, 1); >> if (ret) >> return ff_neterrno(); >> + return ret; >> +} >> + >> +int ff_accept(int fd, int timeout, URLContext *h) >> +{ >> + int ret; >> + struct pollfd lp = { fd, POLLIN, 0 }; >> >> ret = ff_poll_interrupt(&lp, 1, timeout, &h->interrupt_callback); >> if (ret < 0) >> @@ -211,15 +217,24 @@ int ff_listen_bind(int fd, const struct sockaddr *addr, >> ret = accept(fd, NULL, NULL); >> if (ret < 0) >> return ff_neterrno(); >> - >> - closesocket(fd); >> - >> if (ff_socket_nonblock(ret, 1) < 0) >> av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n"); >> >> return ret; >> } >> >> +int ff_listen_bind(int fd, const struct sockaddr *addr, >> + socklen_t addrlen, int timeout, URLContext *h) >> +{ >> + int ret; >> + if ((ret = ff_listen(fd, addr, addrlen)) < 0) >> + return ret; > >> + ret = ff_accept(fd, timeout, h); >> + closesocket(fd); >> + return ret; > > I believe you are slightly changing the behaviour here: in the old code, if > accept() fails, the server is not closed. > >> + >> +} >> + >> int ff_listen_connect(int fd, const struct sockaddr *addr, >> socklen_t addrlen, int timeout, URLContext *h, >> int will_try_next) >> diff --git a/libavformat/network.h b/libavformat/network.h >> index 86fb656..e684787 100644 >> --- a/libavformat/network.h >> +++ b/libavformat/network.h >> @@ -255,6 +255,27 @@ int ff_listen_bind(int fd, const struct sockaddr *addr, >> URLContext *h); >> >> /** > >> + * Bind to a file descriptor and return a listening socket without >> accepting connections. >> + * @param fd First argument of bind(). >> + * @param addr Second argument of bind(). >> + * @param addrlen Third argument of bind(). >> + * @return A blocking file descriptor on success >> + * or an AVERROR on failure. > > I believe the summary and @return statements are wrong: the new code always > returns 0 for success, which is fine. > >> + */ >> +int ff_listen(int fd, const struct sockaddr *addr, socklen_t addrlen); >> + >> +/** >> + * Poll for a single connection on the passed file descriptor. >> + * @param fd The listening socket file descriptor. >> + * @param timeout Polling timeout in milliseconds. >> + * @param h URLContext providing interrupt check >> + * callback and logging context. >> + * @return A non-blocking file descriptor on success >> + * or an AVERROR on failure. >> + */ >> +int ff_accept(int fd, int timeout, URLContext *h); >> + >> +/** >> * Connect to a file descriptor and poll for result. >> * >> * @param fd First argument of connect(), >> -- >> 2.1.0 >> > >> From 330c0eedaede961e52a4a4d93b2211156bc15a69 Mon Sep 17 00:00:00 2001 >> From: Stephan Holljes <klaxa1...@googlemail.com> >> Date: Tue, 30 Jun 2015 08:16:37 +0200 >> Subject: [PATCH 2/8] lavf/avio: add ffurl_accept and ffurl_handshake >> >> Signed-off-by: Stephan Holljes <klaxa1...@googlemail.com> >> --- >> libavformat/avio.c | 17 +++++++++++++++++ >> libavformat/url.h | 18 ++++++++++++++++++ >> 2 files changed, 35 insertions(+) >> >> diff --git a/libavformat/avio.c b/libavformat/avio.c >> index c188adc..63c8b75 100644 >> --- a/libavformat/avio.c >> +++ b/libavformat/avio.c >> @@ -211,6 +211,23 @@ int ffurl_connect(URLContext *uc, AVDictionary >> **options) >> return 0; >> } >> >> +int ffurl_accept(URLContext *s, URLContext **c) >> +{ >> + int ret; > >> + if ((ret = s->prot->url_accept(s, c)) < 0) >> + return ret; > > This will crash if called on a non-server socket. A test on > s->prot->url_accept with a clear error message and a return code would be a > good idea. av_assert0() would probably be acceptable too, as it only happens > in case of clear application error.
I hope I fixed this apropriately. > > Another solution would be to have a "listen" field in the URLContext > structure and test it, changing it to reflect the listen status (normal > client, server, client during handshake, single-shot server), but that can > be done later. > >> + (*c)->is_connected = 1; > > Maybe this should go in url_handshake(). > >> + return ret; >> + >> +} > > Stray empty line. > >> + >> +int ffurl_handshake(URLContext *c) >> +{ >> + if (c->prot->url_handshake) >> + return c->prot->url_handshake(c); >> + return 0; >> +} >> + >> #define URL_SCHEME_CHARS \ >> "abcdefghijklmnopqrstuvwxyz" \ >> "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ >> diff --git a/libavformat/url.h b/libavformat/url.h >> index 99a3201..4cf6892 100644 >> --- a/libavformat/url.h >> +++ b/libavformat/url.h >> @@ -58,6 +58,8 @@ typedef struct URLProtocol { >> * for those nested protocols. >> */ >> int (*url_open2)(URLContext *h, const char *url, int flags, >> AVDictionary **options); >> + int (*url_accept)(URLContext *s, URLContext **c); >> + int (*url_handshake)(URLContext *c); >> >> /** >> * Read data from the protocol. >> @@ -140,6 +142,22 @@ int ffurl_open(URLContext **puc, const char *filename, >> int flags, >> const AVIOInterruptCB *int_cb, AVDictionary **options); >> >> /** >> + * Accept an URLContext c on an URLContext s >> + * @param s server context >> + * @param c client context > >> + * @return the accepted filedescriptor on success, ff_neterrno() on failure. > > The return value is not a file descriptor. Probably just ">= 0 on success". > >> + */ >> +int ffurl_accept(URLContext *s, URLContext **c); >> + >> +/** > >> + * Performs a protocl handshake on the passed client context. > > Inconsistent spelling: most of the doxy are in an impersonal form: > "perform". > >> + * @param c the client context >> + * @return >= 0 on success or a negative value corresponding >> + * to an AVERROR code on failure >> + */ >> +int ffurl_handshake(URLContext *c); >> + >> +/** >> * Read up to size bytes from the resource accessed by h, and store >> * the read bytes in buf. >> * >> -- >> 2.1.0 >> > >> From 8d8cb5e32a12aedb489a36cf9a26d961244d36a0 Mon Sep 17 00:00:00 2001 >> From: Stephan Holljes <klaxa1...@googlemail.com> >> Date: Tue, 30 Jun 2015 08:24:09 +0200 >> Subject: [PATCH 3/8] lavf/avio: add avio_accept and avio_handshake >> >> Signed-off-by: Stephan Holljes <klaxa1...@googlemail.com> >> --- >> libavformat/avio.h | 16 ++++++++++++++++ >> libavformat/aviobuf.c | 17 +++++++++++++++++ >> 2 files changed, 33 insertions(+) >> >> diff --git a/libavformat/avio.h b/libavformat/avio.h >> index d3d9bbd..667e3c5 100644 >> --- a/libavformat/avio.h >> +++ b/libavformat/avio.h >> @@ -648,4 +648,20 @@ struct AVBPrint; >> */ >> int avio_read_to_bprint(AVIOContext *h, struct AVBPrint *pb, size_t >> max_size); >> >> +/** > >> + * Accepts and allocates a client context on a server context. > > Ditto. > >> + * @param s the server context >> + * @param c the client context >> + * @return >= 0 on success or a negative value corresponding >> + * to an AVERROR on failure >> + */ >> +int avio_accept(AVIOContext *s, AVIOContext **c); >> + >> +/** > >> + * Performs a protocol dependent handshake > > Ditto. > >> + * @param c the client context to perform the handshake on >> + * @return >= 0 on success or a negative value corresponding >> + * to an AVERROR on failure >> + */ > >> +int avio_handshake(AVIOContext *c); >> #endif /* AVFORMAT_AVIO_H */ >> diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c >> index ff85081..0591ba5 100644 >> --- a/libavformat/aviobuf.c >> +++ b/libavformat/aviobuf.c >> @@ -1021,6 +1021,23 @@ int avio_read_to_bprint(AVIOContext *h, AVBPrint *pb, >> size_t max_size) >> return 0; >> } >> >> +int avio_accept(AVIOContext *s, AVIOContext **c) >> +{ >> + int ret; >> + URLContext *sc = s->opaque; >> + URLContext *cc; >> + ret = ffurl_accept(sc, &cc); >> + if (ret > 0) >> + ret = ffio_fdopen(c, cc); >> + return ret; >> +} >> + >> +int avio_handshake(AVIOContext *c) >> +{ >> + URLContext *cc = c->opaque; >> + return ffurl_handshake(cc); >> +} >> + >> /* output in a dynamic buffer */ >> >> typedef struct DynBuffer { >> -- >> 2.1.0 >> > >> From b8071e7b6416c37fb05cfae29dd4a29ea71bc41e Mon Sep 17 00:00:00 2001 >> From: Stephan Holljes <klaxa1...@googlemail.com> >> Date: Tue, 30 Jun 2015 09:28:48 +0200 >> Subject: [PATCH 4/8] lavf/tcp: add tcp_accept >> >> Signed-off-by: Stephan Holljes <klaxa1...@googlemail.com> >> --- >> libavformat/tcp.c | 17 +++++++++++++++++ >> 1 file changed, 17 insertions(+) >> >> diff --git a/libavformat/tcp.c b/libavformat/tcp.c >> index f24cad2..ddaecc9 100644 >> --- a/libavformat/tcp.c >> +++ b/libavformat/tcp.c >> @@ -163,6 +163,22 @@ static int tcp_open(URLContext *h, const char *uri, int >> flags) >> return ret; >> } >> >> +static int tcp_accept(URLContext *s, URLContext **c) >> +{ >> + TCPContext *sc = s->priv_data; >> + TCPContext *cc; >> + int ret; >> + if ((ret = ffurl_alloc(c, s->filename, AVIO_FLAG_READ_WRITE, >> &s->interrupt_callback)) < 0) >> + return ret; >> + cc = (*c)->priv_data; >> + ret = accept(sc->fd, NULL, NULL); >> + if (ret < 0) { >> + return ff_neterrno(); >> + } >> + cc->fd = ret; > >> + return ret; > > File descriptors are meaningless outside the actual implementation, so > "return 0" would probably be better. > >> +} >> + >> static int tcp_read(URLContext *h, uint8_t *buf, int size) >> { >> TCPContext *s = h->priv_data; >> @@ -223,6 +239,7 @@ static int tcp_get_file_handle(URLContext *h) >> URLProtocol ff_tcp_protocol = { >> .name = "tcp", >> .url_open = tcp_open, >> + .url_accept = tcp_accept, >> .url_read = tcp_read, >> .url_write = tcp_write, >> .url_close = tcp_close, >> -- >> 2.1.0 >> > >> From e493cad7d123025a27f04721ba236593ea44738b Mon Sep 17 00:00:00 2001 >> From: Stephan Holljes <klaxa1...@googlemail.com> >> Date: Tue, 30 Jun 2015 09:29:16 +0200 >> Subject: [PATCH 5/8] lavf/tcp: increase range for listen and call the >> underlying socket operations accordingly >> >> Signed-off-by: Stephan Holljes <klaxa1...@googlemail.com> >> --- >> libavformat/tcp.c | 13 +++++++++---- >> 1 file changed, 9 insertions(+), 4 deletions(-) >> >> diff --git a/libavformat/tcp.c b/libavformat/tcp.c >> index ddaecc9..a7a5d74 100644 >> --- a/libavformat/tcp.c >> +++ b/libavformat/tcp.c >> @@ -44,7 +44,7 @@ typedef struct TCPContext { >> #define D AV_OPT_FLAG_DECODING_PARAM >> #define E AV_OPT_FLAG_ENCODING_PARAM >> static const AVOption options[] = { >> - { "listen", "Listen for incoming connections", >> OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, >> .flags = D|E }, >> + { "listen", "Listen for incoming connections", >> OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, >> .flags = D|E }, >> { "timeout", "set timeout (in microseconds) of socket I/O >> operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, >> -1, INT_MAX, .flags = D|E }, >> { "listen_timeout", "Connection awaiting timeout (in milliseconds)", >> OFFSET(listen_timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, >> INT_MAX, .flags = D|E }, >> { NULL } >> @@ -125,12 +125,17 @@ static int tcp_open(URLContext *h, const char *uri, >> int flags) >> goto fail; >> } >> >> - if (s->listen) { >> - if ((ret = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, >> + if (s->listen == 2) { >> + // multi-client >> + if ((ret = ff_listen(fd, cur_ai->ai_addr, cur_ai->ai_addrlen)) < 0) >> { >> + goto fail1; >> + } >> + } else if (s->listen == 1) { >> + // single client > >> + if ((fd = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, >> s->listen_timeout, h)) < 0) { >> goto fail1; > > This code goes to fail1 without setting ret. > >> } >> - fd = ret; >> } else { >> if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, >> cur_ai->ai_addrlen, >> s->open_timeout / 1000, h, >> !!cur_ai->ai_next)) < 0) { >> -- >> 2.1.0 >> > >> From c8622b35795ea52dc0b25ce1d5d196d1d561e250 Mon Sep 17 00:00:00 2001 >> From: Stephan Holljes <klaxa1...@googlemail.com> >> Date: Tue, 30 Jun 2015 09:58:09 +0200 >> Subject: [PATCH 6/8] lavf/http: add http_accept and http_handshake >> >> Signed-off-by: Stephan Holljes <klaxa1...@googlemail.com> >> --- >> libavformat/http.c | 38 ++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 38 insertions(+) >> >> diff --git a/libavformat/http.c b/libavformat/http.c >> index 676bfd5..9b67b0b 100644 >> --- a/libavformat/http.c >> +++ b/libavformat/http.c >> @@ -316,6 +316,21 @@ static void handle_http_errors(URLContext *h, int error) >> } >> } >> >> +static int http_handshake(URLContext *c) { >> + int ret, err, new_location; >> + HTTPContext *ch = c->priv_data; >> + URLContext *cl = ch->hd; >> + static const char header[] = "HTTP/1.1 200 OK\r\nContent-Type: >> application/octet-stream\r\nTransfer-Encoding: chunked\r\n\r\n"; > >> + ffurl_handshake(cl); > > Needs error check. > >> + if ((err = http_read_header(c, &new_location)) < 0) >> + goto fail; >> + if ((ret = ffurl_write(cl, header, strlen(header))) < 0) >> + goto fail; >> +fail: >> + handle_http_errors(c, err); >> + return ret; >> +} >> + >> static int http_listen(URLContext *h, const char *uri, int flags, >> AVDictionary **options) { >> HTTPContext *s = h->priv_data; >> @@ -382,6 +397,23 @@ static int http_open(URLContext *h, const char *uri, >> int flags, >> return ret; >> } >> >> +static int http_accept(URLContext *s, URLContext **c) >> +{ >> + int ret; >> + HTTPContext *sc = s->priv_data; >> + HTTPContext *cc; >> + URLContext *sl = sc->hd; >> + URLContext *cl; > >> + if ((ret = ffurl_alloc(c, s->filename, AVIO_FLAG_READ_WRITE, >> &sl->interrupt_callback)) < 0) > > AVIO_FLAG_READ_WRITE seems wrong. Changed to AVIO_FLAG_WRITE, but don't we read the request data from the client? Why does it work as intended with AVIO_FLAG_WRITE? > >> + goto fail; >> + cc = (*c)->priv_data; >> + if ((ret = ffurl_accept(sl, &cl)) < 0) >> + goto fail; >> + cc->hd = cl; >> +fail: >> + return ret; >> +} >> + >> static int http_getc(HTTPContext *s) >> { >> int len; >> @@ -1346,6 +1378,8 @@ HTTP_CLASS(http); >> URLProtocol ff_http_protocol = { >> .name = "http", >> .url_open2 = http_open, >> + .url_accept = http_accept, >> + .url_handshake = http_handshake, >> .url_read = http_read, >> .url_write = http_write, >> .url_seek = http_seek, >> @@ -1364,6 +1398,8 @@ HTTP_CLASS(https); >> URLProtocol ff_https_protocol = { > >> .name = "https", >> .url_open2 = http_open, >> + .url_accept = http_accept, >> + .url_handshake = http_handshake, > > Did you test this one? My guess is it will not work because the > accept/handshake callbacks are not implemented for the TLS code. Removed in the new patch. I just blindly added the fields without testing, my bad. > >> .url_read = http_read, >> .url_write = http_write, >> .url_seek = http_seek, >> @@ -1477,6 +1513,8 @@ static int http_proxy_write(URLContext *h, const >> uint8_t *buf, int size) > >> URLProtocol ff_httpproxy_protocol = { >> .name = "httpproxy", >> .url_open = http_proxy_open, >> + .url_accept = http_accept, >> + .url_handshake = http_handshake, > > I am not sure the proxy client code needs a server side. Also removed, this, too, was added blindly. > >> .url_read = http_buf_read, >> .url_write = http_proxy_write, >> .url_close = http_proxy_close, >> -- >> 2.1.0 >> > >> From b183b01c2bd1978d922f9516f59b200415285823 Mon Sep 17 00:00:00 2001 >> From: Stephan Holljes <klaxa1...@googlemail.com> >> Date: Tue, 30 Jun 2015 11:12:15 +0200 >> Subject: [PATCH 7/8] lavf/http: increase range for listen, add http_handshake >> and move handshake logic there >> >> Signed-off-by: Stephan Holljes <klaxa1...@googlemail.com> >> --- >> libavformat/http.c | 24 +++++++++++------------- >> 1 file changed, 11 insertions(+), 13 deletions(-) >> >> diff --git a/libavformat/http.c b/libavformat/http.c >> index 9b67b0b..f6a6620 100644 >> --- a/libavformat/http.c >> +++ b/libavformat/http.c >> @@ -128,7 +128,7 @@ static const AVOption options[] = { >> { "end_offset", "try to limit the request to bytes preceding this >> offset", OFFSET(end_off), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, D }, >> { "method", "Override the HTTP method or set the expected HTTP method >> from a client", OFFSET(method), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D >> | E }, >> { "reconnect", "auto reconnect after disconnect before EOF", >> OFFSET(reconnect), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D }, >> - { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = >> 0 }, 0, 1, D | E }, >> + { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = >> 0 }, 0, 2, D | E }, >> { NULL } >> }; >> >> @@ -306,6 +306,8 @@ static void handle_http_errors(URLContext *h, int error) >> HTTPContext *s = h->priv_data; >> if (h->is_connected) { >> switch(error) { > >> + case 0: >> + break; > > I suspect this belongs in patch #6. > >> case AVERROR_HTTP_BAD_REQUEST: >> ffurl_write(s->hd, bad_request, strlen(bad_request)); >> break; >> @@ -335,11 +337,10 @@ static int http_listen(URLContext *h, const char *uri, >> int flags, >> AVDictionary **options) { >> HTTPContext *s = h->priv_data; >> int ret; >> - static const char header[] = "HTTP/1.1 200 OK\r\nContent-Type: >> application/octet-stream\r\nTransfer-Encoding: chunked\r\n\r\n"; >> char hostname[1024], proto[10]; >> char lower_url[100]; >> const char *lower_proto = "tcp"; >> - int port, new_location; >> + int port; >> s->chunked_post = 1; >> av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), >> &port, >> NULL, 0, uri); >> @@ -347,20 +348,17 @@ static int http_listen(URLContext *h, const char *uri, >> int flags, >> lower_proto = "tls"; >> ff_url_join(lower_url, sizeof(lower_url), lower_proto, NULL, hostname, >> port, >> NULL); >> - av_dict_set(options, "listen", "1", 0); > >> + av_dict_set_int(options, "listen", s->listen, 0); > > Needs error check since not all underlying protocols support listen=2 yet. > >> if ((ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE, >> &h->interrupt_callback, options)) < 0) >> goto fail; >> - if ((ret = http_read_header(h, &new_location)) < 0) >> - goto fail; >> - if ((ret = ffurl_write(s->hd, header, strlen(header))) < 0) >> - goto fail; >> - return 0; >> - >> + if (s->listen == 1) { >> + // single client >> + ret = http_handshake(h); >> + } >> fail: >> - handle_http_errors(h, ret); >> av_dict_free(&s->chained_options); >> - return ret; >> + return 0; >> } >> >> static int http_open(URLContext *h, const char *uri, int flags, >> @@ -1295,7 +1293,7 @@ static int http_close(URLContext *h) >> av_freep(&s->inflate_buffer); >> #endif /* CONFIG_ZLIB */ >> >> - if (!s->end_chunked_post) >> + if ((s->listen != 2 && !s->end_chunked_post)) >> /* Close the write direction by sending the end of chunked >> encoding. */ >> ret = http_shutdown(h, h->flags); >> >> -- >> 2.1.0 >> > >> From 803a41609cf37ee44763ada91ae31142873a845a Mon Sep 17 00:00:00 2001 >> From: Stephan Holljes <klaxa1...@googlemail.com> >> Date: Tue, 30 Jun 2015 11:12:58 +0200 >> Subject: [PATCH 8/8] doc/protocols: document experimental mutli-client api >> >> Signed-off-by: Stephan Holljes <klaxa1...@googlemail.com> >> --- >> doc/protocols.texi | 2 ++ >> 1 file changed, 2 insertions(+) >> >> diff --git a/doc/protocols.texi b/doc/protocols.texi >> index 453dbcf..39a132a 100644 >> --- a/doc/protocols.texi >> +++ b/doc/protocols.texi >> @@ -292,6 +292,8 @@ autodetection in the future. >> If set to 1 enables experimental HTTP server. This can be used to send data >> when >> used as an output option, or read data from a client with HTTP POST when >> used as >> an input option. >> +If set to 2 enables experimental mutli-client HTTP server. This is not yet >> implemented >> +in ffmpeg.c or ffserver.c and thus must not be used as a command line >> option. >> @example >> # Server side (sending): >> ffmpeg -i somefile.ogg -c copy -listen 1 -f ogg >> http://@var{server}:@var{port} > > This is all for now. I would say it is looking rather promising. > > Regards, > > -- > Nicolas George > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel Since I was told on IRC that sending git send-email patches is preferred over attached patch-files, I will send the patches in a series of follow-up emails. Thanks again for your feedback! Regards, Stephan _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel