diff --git a/modules/access/http/Makefile.am b/modules/access/http/Makefile.am index 35f002084441c4701b45df4f7433d3730798784f..e2628af42cf94189384c022266fbd244dba2e85b 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 0000000000000000000000000000000000000000..d7ed54cb82a6c396b36cceda44ab66111ad34aaa --- /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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* 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 0000000000000000000000000000000000000000..491a43b49efa35d5500f8bd3584e1678fc33d89d --- /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 *);