On Mon, Jun 1, 2015 at 10:52 PM, Nicolas George <geo...@nsup.org> wrote:
> Le tridi 13 prairial, an CCXXIII, Stephan Holljes a écrit :
>> After looking at the ffserver code, I'm wondering if maintaining a
>> list of clients as HTTPContext or custom wrapper structs would make
>> sense.
>> For the time being it would only contain the singular client context
>> which can be accepted right now, but in the future could contain an
>> arbitrary number of clients.
>> Before I start implementing that I would like to know if it is a good
>> choice to do this.
>
> Have you considered the more traditional approach: when a client is
> accepted, create a new AVFormatContext for it?
>
> It seems simpler, and more adapted for various uses, for example if an
> application wants to handle clients in separate threads or even forks. But
> maybe there are benefits to your idea that I have not seen.
>
> Also, that choice seems orthogonal to the question at hand: what do you want
> to do with the method and other connection options?

I agree, I have probably thought a little bit too far ahead.

I hope the attached patches are okay.
I'm somewhat unsure about the first patch, because it checks ret and
sets it explicitly if no other error occurred.
I also added documentation for the method option in HTTPContext.

A related issue is how to autodetect which method is to be expected
when it is not explicitly set.
For example, when listening for a client as an input, a POST request
should be expected, but how do I know that inside http.c?

>
> Regards,
>
> --
>   Nicolas George
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
From 8188b8a3b0cf21df7b80e410fd58b26f974db29e Mon Sep 17 00:00:00 2001
From: Stephan Holljes <klaxa1...@googlemail.com>
Date: Tue, 2 Jun 2015 01:35:26 +0200
Subject: [PATCH 1/2] lavf/http: Process client HTTP request header before
 sending response and handle bad requests.

Signed-off-by: Stephan Holljes <klaxa1...@googlemail.com>
---
 libavformat/http.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/libavformat/http.c b/libavformat/http.c
index 4f6716a..6c18243 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -304,6 +304,7 @@ static int http_listen(URLContext *h, const char *uri, int flags,
     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";
+    static const char bad_request[] = "HTTP/1.1 400 Bad Request\r\n\r\n";
     char hostname[1024], proto[10];
     char lower_url[100];
     const char *lower_proto = "tcp";
@@ -318,13 +319,18 @@ static int http_listen(URLContext *h, const char *uri, int flags,
     if ((ret = ffurl_open(&s->hd, lower_url, AVIO_FLAG_READ_WRITE,
                           &h->interrupt_callback, options)) < 0)
         goto fail;
-    if ((ret = ffurl_write(s->hd, header, strlen(header))) < 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;
 
 fail:
+    if (ret == AVERROR_HTTP_BAD_REQUEST) {
+        if ((ret = ffurl_write(s->hd, bad_request, strlen(bad_request))) < 0)
+            goto fail;
+        ret = AVERROR_HTTP_BAD_REQUEST;
+    }
     av_dict_free(&s->chained_options);
     return ret;
 }
-- 
2.1.0

From 3263509fa862c944acc95fd61ba524b1c31545ca Mon Sep 17 00:00:00 2001
From: Stephan Holljes <klaxa1...@googlemail.com>
Date: Tue, 2 Jun 2015 01:37:47 +0200
Subject: [PATCH 2/2] lavf/http: Process client HTTP methods and document
 method option.

Signed-off-by: Stephan Holljes <klaxa1...@googlemail.com>
---
 doc/protocols.texi | 10 ++++++++++
 libavformat/http.c | 16 +++++++++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/doc/protocols.texi b/doc/protocols.texi
index f822d81..d5ae332 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -278,6 +278,16 @@ Set initial byte offset.
 @item end_offset
 Try to limit the request to bytes preceding this offset.
 
+@item method
+When used as a client option it sets the HTTP method for the request.
+
+When used as a server option it sets the HTTP method that is going to be
+expected by the client(s).
+If the expected and the received HTTP method do not match the client will
+be given a Bad Request response.
+When unset the HTTP method used by the first client will be used for
+comparison to later clients.
+
 @item listen
 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
diff --git a/libavformat/http.c b/libavformat/http.c
index 6c18243..6ef9f0c 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -126,7 +126,7 @@ static const AVOption options[] = {
     { "location", "The actual location of the data received", OFFSET(location), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D | E },
     { "offset", "initial byte offset", OFFSET(off), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, INT64_MAX, D },
     { "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", OFFSET(method), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
+    { "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 },
     { NULL }
@@ -562,6 +562,20 @@ static int process_line(URLContext *h, char *line, int line_count,
 
     p = line;
     if (line_count == 0) {
+        if (s->listen) {
+            if (s->method) {
+                if (av_strncasecmp(s->method, line, strlen(s->method))) {
+                    av_log(h, AV_LOG_ERROR, "Received and expected HTTP method do not match.\n");
+                    return ff_http_averror(400, AVERROR(EIO));
+                }
+                return 0;
+            }
+            while (!av_isspace(*p))
+                p++;
+            if (!(s->method = av_strndup(line, p - line)))
+                return AVERROR(ENOMEM);
+            return 0;
+        }
         while (!av_isspace(*p) && *p != '\0')
             p++;
         while (av_isspace(*p))
-- 
2.1.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to