[vlc-commits] https: simplify HTTP/2 headers parsing

Rémi Denis-Courmont git at videolan.org
Sun Dec 20 17:12:27 CET 2015


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Sun Dec 20 18:11:27 2015 +0200| [750d5ebcdfc362c504c52039e851c224be41ac7b] | committer: Rémi Denis-Courmont

https: simplify HTTP/2 headers parsing

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=750d5ebcdfc362c504c52039e851c224be41ac7b
---

 modules/access/http/h2conn.c       |    3 ++-
 modules/access/http/h2frame.c      |   31 ++++++++++++++++++-------------
 modules/access/http/h2frame.h      |    3 ++-
 modules/access/http/h2frame_test.c |    5 ++---
 modules/access/http/message.c      |    9 ++-------
 modules/access/http/message.h      |    3 ++-
 modules/access/http/message_test.c |   14 +++++++-------
 7 files changed, 35 insertions(+), 33 deletions(-)

diff --git a/modules/access/http/h2conn.c b/modules/access/http/h2conn.c
index a1a1b72..535ecbe 100644
--- a/modules/access/http/h2conn.c
+++ b/modules/access/http/h2conn.c
@@ -113,7 +113,8 @@ static int vlc_h2_stream_fatal(struct vlc_h2_stream *s, uint_fast32_t code)
 }
 
 /** Reports received stream headers */
-static void vlc_h2_stream_headers(void *ctx, unsigned count, char *hdrs[][2])
+static void vlc_h2_stream_headers(void *ctx, unsigned count,
+                                  const char *const hdrs[][2])
 {
     struct vlc_h2_stream *s = ctx;
 
diff --git a/modules/access/http/h2frame.c b/modules/access/http/h2frame.c
index c5ff0d6..acaa5ab 100644
--- a/modules/access/http/h2frame.c
+++ b/modules/access/http/h2frame.c
@@ -522,41 +522,46 @@ static int vlc_h2_parse_headers_end(struct vlc_h2_parser *p)
     char *headers[VLC_H2_MAX_HEADERS][2];
 
     /* TODO: limit total decompressed size of the headers list */
-    int val = hpack_decode(p->headers.decoder, p->headers.buf, p->headers.len,
-                           headers, VLC_H2_MAX_HEADERS);
-    if (val > VLC_H2_MAX_HEADERS)
+    int n = hpack_decode(p->headers.decoder, p->headers.buf, p->headers.len,
+                         headers, VLC_H2_MAX_HEADERS);
+    if (n > VLC_H2_MAX_HEADERS)
     {
         for (unsigned i = 0; i < VLC_H2_MAX_HEADERS; i++)
         {
             free(headers[i][0]);
             free(headers[i][1]);
         }
-        val = -1;
+        n = -1;
     }
-    if (val < 0)
+    if (n < 0)
         return vlc_h2_parse_error(p, VLC_H2_COMPRESSION_ERROR);
 
     void *s = vlc_h2_stream_lookup(p, p->headers.sid);
+    int val = 0;
+
     if (s != NULL)
     {
-        p->cbs->stream_headers(s, val, headers);
-        val = 0;
+        const char *ch[n ? n : 1][2];
+
+        for (int i = 0; i < n; i++)
+            ch[i][0] = headers[i][0], ch[i][1] = headers[i][1];
+
+        p->cbs->stream_headers(s, n, ch);
 
         if (p->headers.eos)
             p->cbs->stream_end(s);
     }
     else
-    {
-        for (int i = 0; i < val; i++)
-        {
-            free(headers[i][0]);
-            free(headers[i][1]);
-        }
         /* NOTE: The specification implies that the error should be sent for
          * the first header frame. But we actually want to receive the whole
          * fragmented headers block, to preserve the HPACK decoder state.
          * So we send the error at the last header frame instead. */
         val = vlc_h2_stream_error(p, p->headers.sid, VLC_H2_REFUSED_STREAM);
+
+    for (int i = 0; i < n; i++)
+    {
+        free(headers[i][0]);
+        free(headers[i][1]);
     }
 
     p->parser = vlc_h2_parse_generic;
diff --git a/modules/access/http/h2frame.h b/modules/access/http/h2frame.h
index d25e43a..49a5c1f 100644
--- a/modules/access/http/h2frame.h
+++ b/modules/access/http/h2frame.h
@@ -106,7 +106,8 @@ struct vlc_h2_parser_cbs
 
     void *(*stream_lookup)(void *ctx, uint_fast32_t id);
     int  (*stream_error)(void *ctx, uint_fast32_t id, uint_fast32_t code);
-    void (*stream_headers)(void *ctx, unsigned count, char *headers[][2]);
+    void (*stream_headers)(void *ctx, unsigned count,
+                           const char *const headers[][2]);
     int  (*stream_data)(void *ctx, struct vlc_h2_frame *f);
     void (*stream_end)(void *ctx);
     int  (*stream_reset)(void *ctx, uint_fast32_t code);
diff --git a/modules/access/http/h2frame_test.c b/modules/access/http/h2frame_test.c
index 4557aa6..2cbb082 100644
--- a/modules/access/http/h2frame_test.c
+++ b/modules/access/http/h2frame_test.c
@@ -142,7 +142,8 @@ static const unsigned resp_hdrc = sizeof (resp_hdrv) / sizeof (resp_hdrv[0]);
 
 static unsigned stream_header_tables;
 
-static void vlc_h2_stream_headers(void *ctx, unsigned count, char *hdrs[][2])
+static void vlc_h2_stream_headers(void *ctx, unsigned count,
+                                  const char *const hdrs[][2])
 {
     assert(ctx == &stream_cookie);
     assert(count == resp_hdrc);
@@ -151,8 +152,6 @@ static void vlc_h2_stream_headers(void *ctx, unsigned count, char *hdrs[][2])
     {
         assert(!strcmp(hdrs[i][0], resp_hdrv[i][0]));
         assert(!strcmp(hdrs[i][1], resp_hdrv[i][1]));
-        free(hdrs[i][1]);
-        free(hdrs[i][0]);
     }
 
     stream_header_tables++;
diff --git a/modules/access/http/message.c b/modules/access/http/message.c
index f7137de..33b500b 100644
--- a/modules/access/http/message.c
+++ b/modules/access/http/message.c
@@ -427,7 +427,8 @@ struct vlc_h2_frame *vlc_http_msg_h2_frame(const struct vlc_http_msg *m,
     return f;
 }
 
-struct vlc_http_msg *vlc_http_msg_h2_headers(unsigned n, char *hdrs[][2])
+struct vlc_http_msg *vlc_http_msg_h2_headers(unsigned n,
+                                             const char *const hdrs[][2])
 {
     struct vlc_http_msg *m = vlc_http_resp_create(0);
     if (unlikely(m == NULL))
@@ -507,12 +508,6 @@ error:
         vlc_http_msg_destroy(m);
         m = NULL;
     }
-
-    for (unsigned i = 0; i < n; i++)
-    {
-        free(hdrs[i][0]);
-        free(hdrs[i][1]);
-    }
     return m;
 }
 
diff --git a/modules/access/http/message.h b/modules/access/http/message.h
index 7e57177..b514e85 100644
--- a/modules/access/http/message.h
+++ b/modules/access/http/message.h
@@ -257,4 +257,5 @@ struct vlc_h2_frame;
 
 struct vlc_h2_frame *vlc_http_msg_h2_frame(const struct vlc_http_msg *m,
                                            uint_fast32_t stream_id, bool eos);
-struct vlc_http_msg *vlc_http_msg_h2_headers(unsigned n, char *hdrs[][2]);
+struct vlc_http_msg *vlc_http_msg_h2_headers(unsigned count,
+                                             const char *const headers[][2]);
diff --git a/modules/access/http/message_test.c b/modules/access/http/message_test.c
index 2fec662..92883dc 100644
--- a/modules/access/http/message_test.c
+++ b/modules/access/http/message_test.c
@@ -255,10 +255,10 @@ int main(void)
 
     vlc_http_msg_destroy(m);
 
-    char *bad1[][2] = {
-        { strdup(":status"), strdup("200") },
-        { strdup(":status"), strdup("200") },
-        { strdup("Server"),  strdup("BigBad/1.0") },
+    const char *bad1[][2] = {
+        { ":status", "200" },
+        { ":status", "200" },
+        { "Server",  "BigBad/1.0" },
     };
 
     m = vlc_http_msg_h2_headers(3, bad1);
@@ -288,12 +288,12 @@ vlc_h2_frame_headers(uint_fast32_t id, uint_fast32_t mtu, bool eos,
     assert(mtu == VLC_H2_DEFAULT_MAX_FRAME);
     assert(eos);
 
-    char *headers[VLC_H2_MAX_HEADERS][2];
+    const char *headers[VLC_H2_MAX_HEADERS][2];
 
     for (unsigned i = 0; i < count; i++)
     {
-        headers[i][0] = strdup(tab[i][0]);
-        headers[i][1] = strdup(tab[i][1]);
+        headers[i][0] = tab[i][0];
+        headers[i][1] = tab[i][1];
     }
 
     m = vlc_http_msg_h2_headers(count, headers);



More information about the vlc-commits mailing list