Re: [FFmpeg-devel] GSoC update
Hi, I have moved the client code in the sample application into a separate function, I hope I did this correctly. I also annotated the patch files with the changes that occurred over the past few iterations of these exchanges. They will be sent shortly as git send-email patches. I also tested the sample application numerous times with wget, nc and siege. I also constantly tested that sending data as a POST client still works (with wget). Regards, Stephan ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] GSoC update
Le quintidi 15 messidor, an CCXXIII, Stephan Holljes a écrit : +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? You are mixing the modes for the HTTP context and for the TCP context. For the TCP context, it must be READ_WRITE, of course, in order to read the request and send the reply. But for the HTTP context, it only determines what methods are automatically accepted by the logic you wrote a bit earlier: GET to write to clients, POST to read from clients. 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. I will look at them presently. Regards, -- Nicolas George signature.asc Description: Digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] GSoC update
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 addrSecond argument of bind(). + * @param addrlen Third argument of bind(). + * @returnA 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. + * @returnA 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,
Re: [FFmpeg-devel] GSoC update
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 addrSecond argument of bind(). + * @param addrlen Third argument of bind(). + * @returnA 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. + * @returnA 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
Re: [FFmpeg-devel] GSoC update
Le decadi 10 messidor, an CCXXIII, Stephan Holljes a écrit : Hi, attached patches are the current state of work. It's probably still a bit rough around the edges, but I think I made some progress. The sample code in doc/examples does not write any data as of yet, but the HTTP handshake works. A few quick remarks, without entering into the fine details since the patch series will likely evolve still quite a bit. From b43aeaa27f6ca7df476aa194b2f78aa1b49516d0 Mon Sep 17 00:00:00 2001 From: Stephan Holljes klaxa1...@googlemail.com Date: Sun, 28 Jun 2015 06:06:16 +0200 Subject: [PATCH 01/10] 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 | 4 2 files changed, 25 insertions(+), 6 deletions(-) This one looks good to me, except a small doxy would be nice for the two new functions. From 39faa1ea315bb51452446e291fd5d93d7eb3a988 Mon Sep 17 00:00:00 2001 From: Stephan Holljes klaxa1...@googlemail.com Date: Sun, 28 Jun 2015 06:12:37 +0200 Subject: [PATCH 02/10] lavf/avio: add ffurl_accept and ffurl_handshake Signed-off-by: Stephan Holljes klaxa1...@googlemail.com --- libavformat/avio.c | 15 +++ libavformat/url.h | 12 2 files changed, 27 insertions(+) ffurl_accept() requires two arguments, but I suspect ffurl_handshake() only requires one, the client. A doxy would be nice for ffurl_handshake(). Also, the client argument of ffurl_accept() and url_accept() should probably a pointer to pointer, like ffurl_alloc(), so that it can allocate the context itself. From 8b473ba9acffecf98f8252eeccb413bcfbbf38c5 Mon Sep 17 00:00:00 2001 From: Stephan Holljes klaxa1...@googlemail.com Date: Sun, 28 Jun 2015 06:13:36 +0200 Subject: [PATCH 03/10] lavf/avio: add avio_accept and avio_handshake Signed-off-by: Stephan Holljes klaxa1...@googlemail.com --- libavformat/avio.h| 2 ++ libavformat/aviobuf.c | 21 + 2 files changed, 23 insertions(+) That part looks mostly good. From 8ba3d1ef528cdd9209764b0f696b8df81ea46870 Mon Sep 17 00:00:00 2001 From: Stephan Holljes klaxa1...@googlemail.com Date: Sun, 28 Jun 2015 06:16:02 +0200 Subject: [PATCH 04/10] 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(+) I believe this patch can not come before the one for TCP. diff --git a/libavformat/http.c b/libavformat/http.c index 676bfd5..7219f08 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -382,6 +382,38 @@ static int http_open(URLContext *h, const char *uri, int flags, return ret; } +static int http_accept(URLContext *s, URLContext *c) +{ +int ret; +HTTPContext *sh = s-priv_data; +HTTPContext *ch = c-priv_data; +URLContext *sl = sh-hd; +URLContext *cl; +if ((ret = ffurl_alloc(cl, sl-filename, AVIO_FLAG_READ_WRITE, sl-interrupt_callback)) 0) +goto fail; +if ((ret = ffurl_accept(sl, cl)) 0) +goto fail; +ch-hd = cl; +fail: +return ret; +} This looks mostly correct, but I suspect it would be more convenient to make url_accept() responsible for allocating the client context. Otherwise, the application is responsible for allocating a client context with the correct protocol and settings, this is fragile. + +static int http_handshake(URLContext *s, URLContext *c) { +int ret, err, new_location; +HTTPContext *sh = s-priv_data; +HTTPContext *ch = c-priv_data; +URLContext *sl = sh-hd; +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; +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; +} As you can see, the s argument is never used. Also, it should probably call ffurl_handshake() on the underlying socket: for TCP it is a nop, but for TLS, for example, it is blocking. + 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, .url_read
Re: [FFmpeg-devel] GSoC update
Hi, attached patches are the current state of work. It's probably still a bit rough around the edges, but I think I made some progress. The sample code in doc/examples does not write any data as of yet, but the HTTP handshake works. From b43aeaa27f6ca7df476aa194b2f78aa1b49516d0 Mon Sep 17 00:00:00 2001 From: Stephan Holljes klaxa1...@googlemail.com Date: Sun, 28 Jun 2015 06:06:16 +0200 Subject: [PATCH 01/10] 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 | 4 2 files changed, 25 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; + +} + 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..44e109c 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -254,6 +254,10 @@ 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 ff_accept(int fd, int timeout, URLContext *h); + /** * Connect to a file descriptor and poll for result. * -- 2.1.0 From 39faa1ea315bb51452446e291fd5d93d7eb3a988 Mon Sep 17 00:00:00 2001 From: Stephan Holljes klaxa1...@googlemail.com Date: Sun, 28 Jun 2015 06:12:37 +0200 Subject: [PATCH 02/10] lavf/avio: add ffurl_accept and ffurl_handshake Signed-off-by: Stephan Holljes klaxa1...@googlemail.com --- libavformat/avio.c | 15 +++ libavformat/url.h | 12 2 files changed, 27 insertions(+) diff --git a/libavformat/avio.c b/libavformat/avio.c index aff8d10..cb8126d 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -211,6 +211,21 @@ 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; +c-is_connected = 1; +return ret; + +} + +int ffurl_handshake(URLContext *s, URLContext *c) +{ +return s-prot-url_handshake(s, c); +} + #define URL_SCHEME_CHARS\ abcdefghijklmnopqrstuvwxyz\ ABCDEFGHIJKLMNOPQRSTUVWXYZ\ diff --git a/libavformat/url.h b/libavformat/url.h index 99a3201..78613c5 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 *s, URLContext *c); /** * Read data from the protocol. @@ -140,6 +142,16 @@ 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. + */ +int ffurl_accept(URLContext *s, URLContext *c); + +int
Re: [FFmpeg-devel] GSoC update
Le septidi 7 messidor, an CCXXIII, Stephan Holljes a écrit : Thanks, I understand the datastructures and their interaction a lot better now. I discussed it with a friend yesterday too and there a lot of the things started to make more sense. I'm currently working on the implementation, when questions arise I will ask again. Good. Please try to pose a WIP patch today to make sure you are really in the right track. Regards, -- Nicolas George signature.asc Description: Digital signature ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
Re: [FFmpeg-devel] GSoC update
L'octidi 8 messidor, an CCXXIII, Stephan Holljes a écrit : I think I implemented everything necessary, but I don't know how to test it. The old behaviour of accepting a single client is now also broken. Since that behaviour was already established, breaking it without notice is not an option :( How do I detect which behaviour the user wants? Should I introduce a new option for http and tcp connections or make the listen field take more values than just 0 and 1? Increasing the range for listen is a good idea. I am afraid it will make the accept functions a but awkward, having to work with either two contexts (server and client) or only one (server that will become client). Attached are patches with the changes I made so far. It compiles, but breaks http server capabilities for now. To actually test multi-client code, it will be necessary to write a multi-client sample application. Fortunately, that should not be very hard. From 22f958ad8d0058865c94847ca8cd2488e2a61c9e Mon Sep 17 00:00:00 2001 From: Stephan Holljes klaxa1...@googlemail.com Date: Fri, 26 Jun 2015 20:48:49 +0200 Subject: [PATCH 1/6] 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 | 4 2 files changed, 25 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; + +} + 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..44e109c 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -254,6 +254,10 @@ 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 ff_accept(int fd, int timeout, URLContext *h); + /** * Connect to a file descriptor and poll for result. * -- 2.1.0 From 4d0b5e42882f180d76a3a64da96dc87bf0ba0635 Mon Sep 17 00:00:00 2001 From: Stephan Holljes klaxa1...@googlemail.com Date: Fri, 26 Jun 2015 20:50:35 +0200 Subject: [PATCH 2/6] lavf/avio: add ffurl_accept Signed-off-by: Stephan Holljes klaxa1...@googlemail.com --- libavformat/avio.c | 5 + libavformat/url.h | 9 + 2 files changed, 14 insertions(+) diff --git a/libavformat/avio.c b/libavformat/avio.c index aff8d10..153230f 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -211,6 +211,11 @@ int ffurl_connect(URLContext *uc, AVDictionary **options) return 0; } +int ffurl_accept(URLContext *sc, URLContext *cc) +{ +return sc-prot-url_accept(sc, cc); +} + #define URL_SCHEME_CHARS\ abcdefghijklmnopqrstuvwxyz\ ABCDEFGHIJKLMNOPQRSTUVWXYZ\ diff --git a/libavformat/url.h b/libavformat/url.h index 99a3201..34fdea2 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -58,6 +58,7 @@ typedef struct URLProtocol { * for those nested protocols. */ int (*url_open2)(URLContext *h, const char *url, int
Re: [FFmpeg-devel] GSoC update
On Fri, Jun 26, 2015 at 10:51 AM, Nicolas George geo...@nsup.org wrote: Le septidi 7 messidor, an CCXXIII, Stephan Holljes a écrit : Thanks, I understand the datastructures and their interaction a lot better now. I discussed it with a friend yesterday too and there a lot of the things started to make more sense. I'm currently working on the implementation, when questions arise I will ask again. Good. Please try to pose a WIP patch today to make sure you are really in the right track. Regards, -- Nicolas George ___ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel I think I implemented everything necessary, but I don't know how to test it. The old behaviour of accepting a single client is now also broken. How do I detect which behaviour the user wants? Should I introduce a new option for http and tcp connections or make the listen field take more values than just 0 and 1? Attached are patches with the changes I made so far. It compiles, but breaks http server capabilities for now. From 22f958ad8d0058865c94847ca8cd2488e2a61c9e Mon Sep 17 00:00:00 2001 From: Stephan Holljes klaxa1...@googlemail.com Date: Fri, 26 Jun 2015 20:48:49 +0200 Subject: [PATCH 1/6] 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 | 4 2 files changed, 25 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; + +} + 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..44e109c 100644 --- a/libavformat/network.h +++ b/libavformat/network.h @@ -254,6 +254,10 @@ 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 ff_accept(int fd, int timeout, URLContext *h); + /** * Connect to a file descriptor and poll for result. * -- 2.1.0 From 4d0b5e42882f180d76a3a64da96dc87bf0ba0635 Mon Sep 17 00:00:00 2001 From: Stephan Holljes klaxa1...@googlemail.com Date: Fri, 26 Jun 2015 20:50:35 +0200 Subject: [PATCH 2/6] lavf/avio: add ffurl_accept Signed-off-by: Stephan Holljes klaxa1...@googlemail.com --- libavformat/avio.c | 5 + libavformat/url.h | 9 + 2 files changed, 14 insertions(+) diff --git a/libavformat/avio.c b/libavformat/avio.c index aff8d10..153230f 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -211,6 +211,11 @@ int ffurl_connect(URLContext *uc, AVDictionary **options) return 0; } +int ffurl_accept(URLContext *sc, URLContext *cc) +{ +return sc-prot-url_accept(sc, cc); +} + #define URL_SCHEME_CHARS\ abcdefghijklmnopqrstuvwxyz\ ABCDEFGHIJKLMNOPQRSTUVWXYZ\ diff --git a/libavformat/url.h b/libavformat/url.h index 99a3201..34fdea2 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -58,6 +58,7 @@ typedef struct URLProtocol { * for those nested protocols. */ int
Re: [FFmpeg-devel] GSoC update
This has better go to the mailing list. Le quintidi 5 messidor, an CCXXIII, Stephan Holljes a écrit : So far I have split ff_listen_bind() into ff_listen_bind() and ff_accept() and added an url_accept field to URLProtocol (see attached patch). I do not believe this is the correct approach. ff_listen_bind() is an internal helper that works specifically for sockets. I read our past exchanges for a number of times and I am somewhat at a loss as to where to allocate my additional Client(-Contexts). No sourcefile I have looked at stores multiple AVIOContexts or AVFormatContexts (or I have not seen it). I also could not find out how ffmpeg would even accept multiple clients. The ff_listen_bind() call is blocking on accept() and it is only called once. Maybe I'm also overlooking some documentation. Maybe I am also looking in the wrong place. The files I have looked at the most have been: url.h network.c/h, avio.c/h aviobuf.c and tcp.c. You need to understand very well how it happens for plain Unix TCP clients. First, the server create and prepares the server socket s, with socket(), bind() and mostly listen(). There is also a list of client sockets c[i], initially empty. Then, indefinitely and in parallel: * call accept() on s: this returns a new c[i] added to the list; * perform read() / write() on each c[i], remove them from the list if they are finished. Here, in parallel means either threads, forked processes, or emulated parallelism with poll() and non-blocking operations. For lavf, non-blocking operations do not work, so you can assume parallelism between multiple clients is achieved with threads; although I very much would like that all new networking code is input-driven and therefore ready for non-blocking. Now, as for how to transpose it into lavf terms: * Creating and preparing the server socket: avio_open2() with various options for the address and the listen option set. * Accepting a new client: a new function that you have to design, probably avio_accept(). There are a few caveats for avio_accept(): * Creating a new AVFormatContext, like accept() creates a new socket. That is not really difficult, IMHO. It just means the API will look somewhat like that: int avio_accept(AVIOContext *s, AVIOContext **c, ...); The c parameter is just like the s parameter to avio_open2(): it allocates a new context if necessary and populates it. * Except, the current API accepts a single client by replacing the server context. This must still be possible after the change. Maybe just overwriting the server context will work, but it must be considered. * If you remember, a full TCP accept() requires three handshake packets: SYN from the client, ACK-SYN from the server and then ACK from the client. The kernel handles this in the background and accept() returns a new client only when the full handshake is done. In lavf, we do not have a kernel working in the background, so it must be explicit. We can look at how non-blocking connect() works: first call connect() on the socket, it returns EINPROGRESS immediately, the repeatedly call getsockopt(SO_ERROR) to check the status of the connection until it stops returning EAGAIN. I believe we can do the same: avio_accept(s, c) to initiate the accept, and then avio_accept_connect(c) or something (feel free to suggest better names) to finish the handshake. For the particular case of the HTTP server, the avio_accept() part would call avio_accept() on the underlying socket (or TLS context), and the avio_accept_connect() would call avio_accept_connect() on the underlying context and then perform the handshake. In terms of application, the code would probably look something like this (error checks and stuff removed): av_dict_set(options, listen, 1); avio_open2(server, http://:8080;, options); while (1) { avio_accept(server, client); thread_run { avio_accept_connect(client); communicate_with_the_client(client); avio_close(client); }; } Hope this helps. Regards, -- Nicolas George From 234199a18e0c3bfede5f04a9ade0a11c71061285 Mon Sep 17 00:00:00 2001 From: Stephan Holljes klaxa1...@googlemail.com Date: Tue, 23 Jun 2015 16:41:51 +0200 Subject: [PATCH] lavf: Split ff_listen_bind into ff_listen_bind and ff_accept and implement its usage in tcp. Signed-off-by: Stephan Holljes klaxa1...@googlemail.com --- libavformat/network.c | 7 --- libavformat/network.h | 12 +++- libavformat/tcp.c | 10 ++ libavformat/url.h | 1 + 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/libavformat/network.c b/libavformat/network.c index 47ade8c..8d9434f 100644 --- a/libavformat/network.c +++ b/libavformat/network.c @@ -204,10 +204,11 @@ int ff_listen_bind(int fd, const struct sockaddr *addr, if (ret) return ff_neterrno(); -ret = ff_poll_interrupt(lp, 1, timeout,
Re: [FFmpeg-devel] GSoC update
Thank you for the detailed reply. It has helped me understand the structures a lot better than before. Comments inline. On Tue, Jun 23, 2015 at 5:25 PM, Nicolas George geo...@nsup.org wrote: This has better go to the mailing list. Le quintidi 5 messidor, an CCXXIII, Stephan Holljes a écrit : So far I have split ff_listen_bind() into ff_listen_bind() and ff_accept() and added an url_accept field to URLProtocol (see attached patch). I do not believe this is the correct approach. ff_listen_bind() is an internal helper that works specifically for sockets. I read our past exchanges for a number of times and I am somewhat at a loss as to where to allocate my additional Client(-Contexts). No sourcefile I have looked at stores multiple AVIOContexts or AVFormatContexts (or I have not seen it). I also could not find out how ffmpeg would even accept multiple clients. The ff_listen_bind() call is blocking on accept() and it is only called once. Maybe I'm also overlooking some documentation. Maybe I am also looking in the wrong place. The files I have looked at the most have been: url.h network.c/h, avio.c/h aviobuf.c and tcp.c. You need to understand very well how it happens for plain Unix TCP clients. First, the server create and prepares the server socket s, with socket(), bind() and mostly listen(). There is also a list of client sockets c[i], initially empty. Then, indefinitely and in parallel: * call accept() on s: this returns a new c[i] added to the list; * perform read() / write() on each c[i], remove them from the list if they are finished. Here, in parallel means either threads, forked processes, or emulated parallelism with poll() and non-blocking operations. For lavf, non-blocking operations do not work, so you can assume parallelism between multiple clients is achieved with threads; although I very much would like that all new networking code is input-driven and therefore ready for non-blocking. Now, as for how to transpose it into lavf terms: * Creating and preparing the server socket: avio_open2() with various options for the address and the listen option set. Am I correct to understand that this has to return immediately, because if avio_open2() does not return, I have no (server) AVIOContext to call avio_accept() with? The HTTPContext will then not have any clients connected to it, which is different from the current behaviour. * Accepting a new client: a new function that you have to design, probably avio_accept(). There are a few caveats for avio_accept(): * Creating a new AVFormatContext, like accept() creates a new socket. That is not really difficult, IMHO. It just means the API will look somewhat like that: int avio_accept(AVIOContext *s, AVIOContext **c, ...); The c parameter is just like the s parameter to avio_open2(): it allocates a new context if necessary and populates it. * Except, the current API accepts a single client by replacing the server context. This must still be possible after the change. Maybe just overwriting the server context will work, but it must be considered. * If you remember, a full TCP accept() requires three handshake packets: SYN from the client, ACK-SYN from the server and then ACK from the client. The kernel handles this in the background and accept() returns a new client only when the full handshake is done. In lavf, we do not have a kernel working in the background, so it must be explicit. We can look at how non-blocking connect() works: first call connect() on the socket, it returns EINPROGRESS immediately, the repeatedly call getsockopt(SO_ERROR) to check the status of the connection until it stops returning EAGAIN. I believe we can do the same: avio_accept(s, c) to initiate the accept, and then avio_accept_connect(c) or something (feel free to suggest better names) to finish the handshake. For the particular case of the HTTP server, the avio_accept() part would call avio_accept() on the underlying socket (or TLS context), and the avio_accept_connect() would call avio_accept_connect() on the underlying context and then perform the handshake. In terms of application, the code would probably look something like this (error checks and stuff removed): av_dict_set(options, listen, 1); avio_open2(server, http://:8080;, options); while (1) { avio_accept(server, client); thread_run { avio_accept_connect(client); communicate_with_the_client(client); avio_close(client); }; } Would this still be in http.c? If my thinking is correct, this should be in http_open() then, but only if http_listen() returns without accepting an initial client. Hope this helps. Regards, -- Nicolas George A lot of this I still can't wrap my head around. I am still not sure about a lot of things, for example how and where to use threading to serve clients in parallel, or