[FFmpeg-devel] [PATCH 1/2] lavf/http: Parse and/or expose various client data.

Stephan Holljes klaxa1337 at googlemail.com
Thu Aug 20 18:05:00 CEST 2015


Introduce the ability to set reply body and reply text and read the
url-query, http-version and host parameter.

Signed-off-by: Stephan Holljes <klaxa1337 at googlemail.com>
---
 libavformat/http.c | 32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

Does not export User-Agent, unlike the previous version.

diff --git a/libavformat/http.c b/libavformat/http.c
index 18df34e..0932e06 100644
--- a/libavformat/http.c
+++ b/libavformat/http.c
@@ -64,12 +64,14 @@ typedef struct HTTPContext {
     int64_t chunksize;
     int64_t off, end_off, filesize;
     char *location;
+    char *host;
     HTTPAuthState auth_state;
     HTTPAuthState proxy_auth_state;
     char *headers;
     char *mime_type;
     char *user_agent;
     char *content_type;
+    char *body;
     /* Set if the server correctly handles Connection: close and will close
      * the connection after feeding us the content. */
     int willclose;
@@ -107,7 +109,10 @@ typedef struct HTTPContext {
     int reconnect;
     int listen;
     char *resource;
+    char *query;
+    char *http_version;
     int reply_code;
+    char *reply_text;
     int is_multi_client;
     HandshakeState handshake_step;
     int is_connected_server;
@@ -123,6 +128,7 @@ static const AVOption options[] = {
     { "chunked_post", "use(s) chunked transfer-encoding for posts", OFFSET(chunked_post), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, D | E },
     { "headers", "set custom HTTP headers, can override built in default headers", OFFSET(headers), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D | E },
     { "content_type", "set a specific content type for the POST messages", OFFSET(content_type), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D | E },
+    { "body", "set the body of a simple HTTP reply", OFFSET(body), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
     { "user_agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D },
     { "user-agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, { .str = DEFAULT_USER_AGENT }, 0, 0, D },
     { "multiple_requests", "use persistent connections", OFFSET(multiple_requests), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, D | E },
@@ -141,10 +147,14 @@ static const AVOption options[] = {
     { "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 or set the expected HTTP method from a client", OFFSET(method), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D | E },
+    { "http_version", "The http version string received from a client.", OFFSET(http_version), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, D | AV_OPT_FLAG_READONLY },
     { "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, 2, D | E },
     { "resource", "The resource requested by a client", OFFSET(resource), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
+    { "query", "The query requested by a client", OFFSET(query), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
     { "reply_code", "The http status code to return to a client", OFFSET(reply_code), AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599, E},
+    { "reply_text", "Set a custom reply text to replace standard HTTP replies", OFFSET(reply_text), AV_OPT_TYPE_STRING, { .str = NULL}, 0, 0, E},
+    { "hostname", "The Host-parameter of an incoming HTTP request.", OFFSET(host), AV_OPT_TYPE_STRING, { .str = NULL}, 0, 0, E},
     { NULL }
 };
 
@@ -506,6 +516,7 @@ static int http_accept(URLContext *s, URLContext **c)
     HTTPContext *cc;
     URLContext *sl = sc->hd;
     URLContext *cl = NULL;
+    char *peeraddr;
 
     av_assert0(sc->listen);
     if ((ret = ffurl_alloc(c, s->filename, s->flags, &sl->interrupt_callback)) < 0)
@@ -702,7 +713,7 @@ static int process_line(URLContext *h, char *line, int line_count,
 {
     HTTPContext *s = h->priv_data;
     const char *auto_method =  h->flags & AVIO_FLAG_READ ? "POST" : "GET";
-    char *tag, *p, *end, *method, *resource, *version;
+    char *tag, *p, *end, *method, *resource, *query = NULL, *version;
     int ret;
 
     /* end of header */
@@ -720,6 +731,7 @@ static int process_line(URLContext *h, char *line, int line_count,
                 p++;
             *(p++) = '\0';
             av_log(h, AV_LOG_TRACE, "Received method: %s\n", method);
+            av_log(h, AV_LOG_TRACE, "Expected method: %s\n", s->method);
             if (s->method) {
                 if (av_strcasecmp(s->method, method)) {
                     av_log(h, AV_LOG_ERROR, "Received and expected HTTP method do not match. (%s expected, %s received)\n",
@@ -742,12 +754,22 @@ static int process_line(URLContext *h, char *line, int line_count,
             while (av_isspace(*p))
                 p++;
             resource = p;
-            while (!av_isspace(*p))
+            while (*p && !av_isspace(*p) && *p != '?')
                 p++;
+            if (*p == '?') {
+                *(p++) = '\0';
+                query = p;
+                while (*p && !av_isspace(*p))
+                    p++;
+                if (!(s->query = av_strdup(query)))
+                    return AVERROR(ENOMEM);
+            }
             *(p++) = '\0';
             av_log(h, AV_LOG_TRACE, "Requested resource: %s\n", resource);
             if (!(s->resource = av_strdup(resource)))
                 return AVERROR(ENOMEM);
+            if (query)
+                av_log(h, AV_LOG_TRACE, "Requested query: %s\n", query);
 
             // HTTP version
             while (av_isspace(*p))
@@ -761,6 +783,8 @@ static int process_line(URLContext *h, char *line, int line_count,
                 return ff_http_averror(400, AVERROR(EIO));
             }
             av_log(h, AV_LOG_TRACE, "HTTP version string: %s\n", version);
+            if (!(s->http_version = av_strdup(version)))
+                return AVERROR(ENOMEM);
         } else {
             while (!av_isspace(*p) && *p != '\0')
                 p++;
@@ -831,6 +855,10 @@ static int process_line(URLContext *h, char *line, int line_count,
         } else if (!av_strcasecmp(tag, "Content-Encoding")) {
             if ((ret = parse_content_encoding(h, p)) < 0)
                 return ret;
+        } else if (s->is_connected_server && !av_strcasecmp(tag, "Host")) {
+            av_log(s, AV_LOG_TRACE, "Host: %s\n", p);
+            if (!s->host && !(s->host = av_strdup(p)))
+                return AVERROR(ENOMEM);
         }
     }
     return 1;
-- 
2.1.0



More information about the ffmpeg-devel mailing list