[vlc-commits] HTTP chunked transfer encoding "decoder"

Rémi Denis-Courmont git at videolan.org
Wed Dec 16 21:31:19 CET 2015


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Mon Dec 14 23:11:53 2015 +0200| [6ce7b4500c038a53a5f570a3cbacb6b3ffd4cad4] | committer: Rémi Denis-Courmont

HTTP chunked transfer encoding "decoder"

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

 modules/access/http/Makefile.am |    1 +
 modules/access/http/chunked.c   |  160 +++++++++++++++++++++++++++++++++++++++
 modules/access/http/h1conn.h    |   25 ++++++
 3 files changed, 186 insertions(+)

diff --git a/modules/access/http/Makefile.am b/modules/access/http/Makefile.am
index 35f0020..e2628af 100644
--- a/modules/access/http/Makefile.am
+++ b/modules/access/http/Makefile.am
@@ -10,6 +10,7 @@ libvlc_http_la_SOURCES = \
 	access/http/h2frame.c access/http/h2frame.h \
 	access/http/h2output.c access/http/h2output.h \
 	access/http/h2conn.c access/http/h2conn.h \
+	access/http/h1conn.h access/http/chunked.c \
 	access/http/connmgr.c access/http/connmgr.h
 libvlc_http_la_CPPFLAGS = -Dneedsomethinghere
 libvlc_http_la_LIBADD = \
diff --git a/modules/access/http/chunked.c b/modules/access/http/chunked.c
new file mode 100644
index 0000000..d7ed54c
--- /dev/null
+++ b/modules/access/http/chunked.c
@@ -0,0 +1,160 @@
+/*****************************************************************************
+ * chunked.c: HTTP 1.1 chunked encoding
+ *****************************************************************************
+ * Copyright © 2015 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <vlc_common.h>
+#include <vlc_block.h>
+#include <vlc_tls.h> /* FIXME: remove this and test */
+
+#include "message.h"
+#include "transport.h"
+#include "h1conn.h"
+
+struct vlc_chunked_stream
+{
+    struct vlc_http_stream stream;
+    struct vlc_http_stream *parent;
+    struct vlc_tls *tls;
+    uintmax_t chunk_length;
+    bool eof;
+    bool error;
+};
+
+static_assert(offsetof(struct vlc_chunked_stream, stream) == 0, "Cast error");
+
+static void *vlc_chunked_fatal(struct vlc_chunked_stream *s)
+{
+    assert(!s->error);
+    s->error = true;
+    return NULL;
+}
+
+static struct vlc_http_msg *vlc_chunked_wait(struct vlc_http_stream *stream)
+{
+    /* Request trailers are not supported so far.
+     * There cannot be headers during chunked encoding. */
+    (void) stream;
+    return NULL;
+}
+
+static block_t *vlc_chunked_read(struct vlc_http_stream *stream)
+{
+    struct vlc_chunked_stream *s = (struct vlc_chunked_stream *)stream;
+    block_t *block = NULL;
+
+    if (s->eof || s->error)
+        return NULL;
+
+    /* Read chunk size (hexadecimal length) */
+    if (s->chunk_length == 0)
+    {   /* NOTE: This accepts LF in addition to CRLF. No big deal. */
+        char *line = vlc_tls_GetLine(s->tls);
+        if (line == NULL)
+            return vlc_chunked_fatal(s);
+
+        int end;
+
+        if (sscanf(line, "%jx%n", &s->chunk_length, &end) < 1
+         || (line[end] != '\0' && line[end] != ';' /* ignore extension(s) */))
+            s->chunk_length = UINTMAX_MAX;
+
+        free(line);
+
+        if (s->chunk_length == UINTMAX_MAX)
+            return vlc_chunked_fatal(s);
+    }
+
+    /* Read chunk data */
+    if (s->chunk_length > 0)
+    {
+        size_t size = 1536; /* arbitrary */
+        if (size > s->chunk_length)
+            size = s->chunk_length;
+
+        block = block_Alloc(size);
+        if (unlikely(block == NULL))
+            return NULL;
+
+        ssize_t val = vlc_tls_Read(s->tls, block->p_buffer, size, false);
+        if (val <= 0)
+        {   /* Connection error (-) or unexpected end of connection (0) */
+            block_Release(block);
+            return vlc_chunked_fatal(s);
+        }
+
+        block->i_buffer = val;
+        s->chunk_length -= val;
+    }
+    else
+        s->eof = true;
+
+    /* Read chunk end (CRLF) */
+    if (s->chunk_length == 0)
+    {
+        char crlf[2];
+
+        if (vlc_https_recv(s->tls, crlf, 2) < 2 || memcmp(crlf, "\r\n", 2))
+            vlc_chunked_fatal(s);
+    }
+    return block;
+}
+
+static void vlc_chunked_close(struct vlc_http_stream *stream, bool abort)
+{
+    struct vlc_chunked_stream *s = (struct vlc_chunked_stream *)stream;
+
+    if (!s->eof) /* Abort connection if stream is closed before end */
+        vlc_chunked_fatal(s);
+
+    vlc_http_stream_close(s->parent, abort || s->error);
+    free(s);
+}
+
+static struct vlc_http_stream_cbs vlc_chunked_callbacks =
+{
+    vlc_chunked_wait,
+    vlc_chunked_read,
+    vlc_chunked_close,
+};
+
+struct vlc_http_stream *vlc_chunked_open(struct vlc_http_stream *parent,
+                                         struct vlc_tls *tls)
+{
+    struct vlc_chunked_stream *s = malloc(sizeof (*s));
+    if (unlikely(s == NULL))
+        return NULL;
+
+    s->stream.cbs = &vlc_chunked_callbacks;
+    s->parent = parent;
+    s->tls = tls;
+    s->chunk_length = 0;
+    s->eof = false;
+    s->error = false;
+    return &s->stream;
+}
diff --git a/modules/access/http/h1conn.h b/modules/access/http/h1conn.h
new file mode 100644
index 0000000..491a43b
--- /dev/null
+++ b/modules/access/http/h1conn.h
@@ -0,0 +1,25 @@
+/*****************************************************************************
+ * h1conn.h: HTTP 1.x connection handling
+ *****************************************************************************
+ * Copyright © 2015 Rémi Denis-Courmont
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+struct vlc_http_stream;
+struct vlc_tls;
+
+struct vlc_http_stream *vlc_chunked_open(struct vlc_http_stream *,
+                                         struct vlc_tls *);



More information about the vlc-commits mailing list