summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/deps/picohttpparser
diff options
context:
space:
mode:
Diffstat (limited to 'web/server/h2o/libh2o/deps/picohttpparser')
-rw-r--r--web/server/h2o/libh2o/deps/picohttpparser/.clang-format7
-rw-r--r--web/server/h2o/libh2o/deps/picohttpparser/.gitattributes1
-rw-r--r--web/server/h2o/libh2o/deps/picohttpparser/.gitmodules3
-rw-r--r--web/server/h2o/libh2o/deps/picohttpparser/.travis.yml6
-rw-r--r--web/server/h2o/libh2o/deps/picohttpparser/Jamfile7
-rw-r--r--web/server/h2o/libh2o/deps/picohttpparser/Makefile40
-rw-r--r--web/server/h2o/libh2o/deps/picohttpparser/README.md116
-rw-r--r--web/server/h2o/libh2o/deps/picohttpparser/bench.c66
-rw-r--r--web/server/h2o/libh2o/deps/picohttpparser/picohttpparser.c620
-rw-r--r--web/server/h2o/libh2o/deps/picohttpparser/picohttpparser.h89
-rw-r--r--web/server/h2o/libh2o/deps/picohttpparser/test.c419
11 files changed, 0 insertions, 1374 deletions
diff --git a/web/server/h2o/libh2o/deps/picohttpparser/.clang-format b/web/server/h2o/libh2o/deps/picohttpparser/.clang-format
deleted file mode 100644
index 9640123c7..000000000
--- a/web/server/h2o/libh2o/deps/picohttpparser/.clang-format
+++ /dev/null
@@ -1,7 +0,0 @@
-# requires clang-format >= 3.6
-BasedOnStyle: "LLVM"
-IndentWidth: 4
-ColumnLimit: 132
-BreakBeforeBraces: Linux
-AllowShortFunctionsOnASingleLine: None
-SortIncludes: false
diff --git a/web/server/h2o/libh2o/deps/picohttpparser/.gitattributes b/web/server/h2o/libh2o/deps/picohttpparser/.gitattributes
deleted file mode 100644
index 03d9eec36..000000000
--- a/web/server/h2o/libh2o/deps/picohttpparser/.gitattributes
+++ /dev/null
@@ -1 +0,0 @@
-picohttpparser.* ident
diff --git a/web/server/h2o/libh2o/deps/picohttpparser/.gitmodules b/web/server/h2o/libh2o/deps/picohttpparser/.gitmodules
deleted file mode 100644
index e1434dacc..000000000
--- a/web/server/h2o/libh2o/deps/picohttpparser/.gitmodules
+++ /dev/null
@@ -1,3 +0,0 @@
-[submodule "picotest"]
- path = picotest
- url = https://github.com/h2o/picotest.git
diff --git a/web/server/h2o/libh2o/deps/picohttpparser/.travis.yml b/web/server/h2o/libh2o/deps/picohttpparser/.travis.yml
deleted file mode 100644
index 78af54bc2..000000000
--- a/web/server/h2o/libh2o/deps/picohttpparser/.travis.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-language: c
-compiler:
- - gcc
- - clang
-script:
- - make test
diff --git a/web/server/h2o/libh2o/deps/picohttpparser/Jamfile b/web/server/h2o/libh2o/deps/picohttpparser/Jamfile
deleted file mode 100644
index 5acbe55d0..000000000
--- a/web/server/h2o/libh2o/deps/picohttpparser/Jamfile
+++ /dev/null
@@ -1,7 +0,0 @@
-project picohttpparser ;
-
-lib picohttpparser : picohttpparser.c ;
-
-unit-test test
- : picohttpparser picotest/picotest.c test.c
- : <testing.launcher>prove ;
diff --git a/web/server/h2o/libh2o/deps/picohttpparser/Makefile b/web/server/h2o/libh2o/deps/picohttpparser/Makefile
deleted file mode 100644
index 9e42298d3..000000000
--- a/web/server/h2o/libh2o/deps/picohttpparser/Makefile
+++ /dev/null
@@ -1,40 +0,0 @@
-#
-# Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
-# Shigeo Mitsunari
-#
-# The software is licensed under either the MIT License (below) or the Perl
-# license.
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to
-# deal in the Software without restriction, including without limitation the
-# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-# sell copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-# IN THE SOFTWARE.
-
-CC?=gcc
-PROVE?=prove
-
-all:
-
-test: test-bin
- $(PROVE) -v ./test-bin
-
-test-bin: picohttpparser.c picotest/picotest.c test.c
- $(CC) -Wall $(CFLAGS) $(LDFLAGS) -o $@ $^
-
-clean:
- rm -f test-bin
-
-.PHONY: test
diff --git a/web/server/h2o/libh2o/deps/picohttpparser/README.md b/web/server/h2o/libh2o/deps/picohttpparser/README.md
deleted file mode 100644
index cb32f58e1..000000000
--- a/web/server/h2o/libh2o/deps/picohttpparser/README.md
+++ /dev/null
@@ -1,116 +0,0 @@
-PicoHTTPParser
-=============
-
-Copyright (c) 2009-2014 [Kazuho Oku](https://github.com/kazuho), [Tokuhiro Matsuno](https://github.com/tokuhirom), [Daisuke Murase](https://github.com/typester), [Shigeo Mitsunari](https://github.com/herumi)
-
-PicoHTTPParser is a tiny, primitive, fast HTTP request/response parser.
-
-Unlike most parsers, it is stateless and does not allocate memory by itself.
-All it does is accept pointer to buffer and the output structure, and setups the pointers in the latter to point at the necessary portions of the buffer.
-
-The code is widely deployed within Perl applications through popular modules that use it, including [Plack](https://metacpan.org/pod/Plack), [Starman](https://metacpan.org/pod/Starman), [Starlet](https://metacpan.org/pod/Starlet), [Furl](https://metacpan.org/pod/Furl). It is also the HTTP/1 parser of [H2O](https://github.com/h2o/h2o).
-
-Check out [test.c] to find out how to use the parser.
-
-The software is dual-licensed under the Perl License or the MIT License.
-
-Usage
------
-
-The library exposes four functions: `phr_parse_request`, `phr_parse_response`, `phr_parse_headers`, `phr_decode_chunked`.
-
-### phr_parse_request
-
-The example below reads an HTTP request from socket `sock` using `read(2)`, parses it using `phr_parse_request`, and prints the details.
-
-```c
-char buf[4096], *method, *path;
-int pret, minor_version;
-struct phr_header headers[100];
-size_t buflen = 0, prevbuflen = 0, method_len, path_len, num_headers;
-ssize_t rret;
-
-while (1) {
- /* read the request */
- while ((rret = read(sock, buf + buflen, sizeof(buf) - buflen)) == -1 && errno == EINTR)
- ;
- if (rret <= 0)
- return IOError;
- prevbuflen = buflen;
- buflen += rret;
- /* parse the request */
- num_headers = sizeof(headers) / sizeof(headers[0]);
- pret = phr_parse_request(buf, buflen, &method, &method_len, &path, &path_len,
- &minor_version, headers, &num_headers, prevbuflen);
- if (pret > 0)
- break; /* successfully parsed the request */
- else if (pret == -1)
- return ParseError;
- /* request is incomplete, continue the loop */
- assert(pret == -2);
- if (buflen == sizeof(buf))
- return RequestIsTooLongError;
-}
-
-printf("request is %d bytes long\n", pret);
-printf("method is %.*s\n", (int)method_len, method);
-printf("path is %.*s\n", (int)path_len, path);
-printf("HTTP version is 1.%d\n", minor_version);
-printf("headers:\n");
-for (i = 0; i != num_headers; ++i) {
- printf("%.*s: %.*s\n", (int)headers[i].name_len, headers[i].name,
- (int)headers[i].value_len, headers[i].value);
-}
-```
-
-### phr_parse_response, phr_parse_headers
-
-`phr_parse_response` and `phr_parse_headers` provide similar interfaces as `phr_parse_request`. `phr_parse_response` parses an HTTP response, and `phr_parse_headers` parses the headers only.
-
-### phr_decode_chunked
-
-The example below decodes incoming data in chunked-encoding. The data is decoded in-place.
-
-```c
-struct phr_chunked_decoder decoder = {}; /* zero-clear */
-char *buf = malloc(4096);
-size_t size = 0, capacity = 4096, rsize;
-ssize_t rret, pret;
-
-/* set consume_trailer to 1 to discard the trailing header, or the application
- * should call phr_parse_headers to parse the trailing header */
-decoder.consume_trailer = 1;
-
-do {
- /* expand the buffer if necessary */
- if (size == capacity) {
- capacity *= 2;
- buf = realloc(buf, capacity);
- assert(buf != NULL);
- }
- /* read */
- while ((rret = read(sock, buf + size, capacity - size)) == -1 && errno == EINTR)
- ;
- if (rret <= 0)
- return IOError;
- /* decode */
- rsize = rret;
- pret = phr_decode_chunked(&decoder, buf + size, &rsize);
- if (pret == -1)
- return ParseError;
- size += rsize;
-} while (pret == -2);
-
-/* successfully decoded the chunked data */
-assert(pret >= 0);
-printf("decoded data is at %p (%zu bytes)\n", buf, size);
-```
-
-Benchmark
----------
-
-![benchmark results](http://i.gyazo.com/a85c18d3162dfb46b485bb41e0ad443a.png)
-
-The benchmark code is from [fukamachi/fast-http@6b91103](https://github.com/fukamachi/fast-http/tree/6b9110347c7a3407310c08979aefd65078518478).
-
-The internals of picohttpparser has been described to some extent in [my blog entry]( http://blog.kazuhooku.com/2014/11/the-internals-h2o-or-how-to-write-fast.html).
diff --git a/web/server/h2o/libh2o/deps/picohttpparser/bench.c b/web/server/h2o/libh2o/deps/picohttpparser/bench.c
deleted file mode 100644
index 8dec06c4e..000000000
--- a/web/server/h2o/libh2o/deps/picohttpparser/bench.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
- * Shigeo Mitsunari
- *
- * The software is licensed under either the MIT License (below) or the Perl
- * license.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include "picohttpparser.h"
-
-#define REQ \
- "GET /wp-content/uploads/2010/03/hello-kitty-darth-vader-pink.jpg HTTP/1.1\r\n" \
- "Host: www.kittyhell.com\r\n" \
- "User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 " \
- "Pathtraq/0.9\r\n" \
- "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n" \
- "Accept-Language: ja,en-us;q=0.7,en;q=0.3\r\n" \
- "Accept-Encoding: gzip,deflate\r\n" \
- "Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7\r\n" \
- "Keep-Alive: 115\r\n" \
- "Connection: keep-alive\r\n" \
- "Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx; " \
- "__utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x; " \
- "__utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral\r\n" \
- "\r\n"
-
-int main(void)
-{
- const char *method;
- size_t method_len;
- const char *path;
- size_t path_len;
- int minor_version;
- struct phr_header headers[32];
- size_t num_headers;
- int i, ret;
-
- for (i = 0; i < 10000000; i++) {
- num_headers = sizeof(headers) / sizeof(headers[0]);
- ret = phr_parse_request(REQ, sizeof(REQ) - 1, &method, &method_len, &path, &path_len, &minor_version, headers, &num_headers,
- 0);
- assert(ret == sizeof(REQ) - 1);
- }
-
- return 0;
-}
diff --git a/web/server/h2o/libh2o/deps/picohttpparser/picohttpparser.c b/web/server/h2o/libh2o/deps/picohttpparser/picohttpparser.c
deleted file mode 100644
index a707070d1..000000000
--- a/web/server/h2o/libh2o/deps/picohttpparser/picohttpparser.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
- * Shigeo Mitsunari
- *
- * The software is licensed under either the MIT License (below) or the Perl
- * license.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stddef.h>
-#include <string.h>
-#ifdef __SSE4_2__
-#ifdef _MSC_VER
-#include <nmmintrin.h>
-#else
-#include <x86intrin.h>
-#endif
-#endif
-#include "picohttpparser.h"
-
-/* $Id$ */
-
-#if __GNUC__ >= 3
-#define likely(x) __builtin_expect(!!(x), 1)
-#define unlikely(x) __builtin_expect(!!(x), 0)
-#else
-#define likely(x) (x)
-#define unlikely(x) (x)
-#endif
-
-#ifdef _MSC_VER
-#define ALIGNED(n) _declspec(align(n))
-#else
-#define ALIGNED(n) __attribute__((aligned(n)))
-#endif
-
-#define IS_PRINTABLE_ASCII(c) ((unsigned char)(c)-040u < 0137u)
-
-#define CHECK_EOF() \
- if (buf == buf_end) { \
- *ret = -2; \
- return NULL; \
- }
-
-#define EXPECT_CHAR_NO_CHECK(ch) \
- if (*buf++ != ch) { \
- *ret = -1; \
- return NULL; \
- }
-
-#define EXPECT_CHAR(ch) \
- CHECK_EOF(); \
- EXPECT_CHAR_NO_CHECK(ch);
-
-#define ADVANCE_TOKEN(tok, toklen) \
- do { \
- const char *tok_start = buf; \
- static const char ALIGNED(16) ranges2[] = "\000\040\177\177"; \
- int found2; \
- buf = findchar_fast(buf, buf_end, ranges2, sizeof(ranges2) - 1, &found2); \
- if (!found2) { \
- CHECK_EOF(); \
- } \
- while (1) { \
- if (*buf == ' ') { \
- break; \
- } else if (unlikely(!IS_PRINTABLE_ASCII(*buf))) { \
- if ((unsigned char)*buf < '\040' || *buf == '\177') { \
- *ret = -1; \
- return NULL; \
- } \
- } \
- ++buf; \
- CHECK_EOF(); \
- } \
- tok = tok_start; \
- toklen = buf - tok_start; \
- } while (0)
-
-static const char *token_char_map = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\1\0\1\1\1\1\1\0\0\1\1\0\1\1\0\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0"
- "\0\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\1\1"
- "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\1\0\1\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
- "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
-
-static const char *findchar_fast(const char *buf, const char *buf_end, const char *ranges, size_t ranges_size, int *found)
-{
- *found = 0;
-#if __SSE4_2__
- if (likely(buf_end - buf >= 16)) {
- __m128i ranges16 = _mm_loadu_si128((const __m128i *)ranges);
-
- size_t left = (buf_end - buf) & ~15;
- do {
- __m128i b16 = _mm_loadu_si128((const __m128i *)buf);
- int r = _mm_cmpestri(ranges16, ranges_size, b16, 16, _SIDD_LEAST_SIGNIFICANT | _SIDD_CMP_RANGES | _SIDD_UBYTE_OPS);
- if (unlikely(r != 16)) {
- buf += r;
- *found = 1;
- break;
- }
- buf += 16;
- left -= 16;
- } while (likely(left != 0));
- }
-#else
- /* suppress unused parameter warning */
- (void)buf_end;
- (void)ranges;
- (void)ranges_size;
-#endif
- return buf;
-}
-
-static const char *get_token_to_eol(const char *buf, const char *buf_end, const char **token, size_t *token_len, int *ret)
-{
- const char *token_start = buf;
-
-#ifdef __SSE4_2__
- static const char ranges1[] = "\0\010"
- /* allow HT */
- "\012\037"
- /* allow SP and up to but not including DEL */
- "\177\177"
- /* allow chars w. MSB set */
- ;
- int found;
- buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found);
- if (found)
- goto FOUND_CTL;
-#else
- /* find non-printable char within the next 8 bytes, this is the hottest code; manually inlined */
- while (likely(buf_end - buf >= 8)) {
-#define DOIT() \
- do { \
- if (unlikely(!IS_PRINTABLE_ASCII(*buf))) \
- goto NonPrintable; \
- ++buf; \
- } while (0)
- DOIT();
- DOIT();
- DOIT();
- DOIT();
- DOIT();
- DOIT();
- DOIT();
- DOIT();
-#undef DOIT
- continue;
- NonPrintable:
- if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) {
- goto FOUND_CTL;
- }
- ++buf;
- }
-#endif
- for (;; ++buf) {
- CHECK_EOF();
- if (unlikely(!IS_PRINTABLE_ASCII(*buf))) {
- if ((likely((unsigned char)*buf < '\040') && likely(*buf != '\011')) || unlikely(*buf == '\177')) {
- goto FOUND_CTL;
- }
- }
- }
-FOUND_CTL:
- if (likely(*buf == '\015')) {
- ++buf;
- EXPECT_CHAR('\012');
- *token_len = buf - 2 - token_start;
- } else if (*buf == '\012') {
- *token_len = buf - token_start;
- ++buf;
- } else {
- *ret = -1;
- return NULL;
- }
- *token = token_start;
-
- return buf;
-}
-
-static const char *is_complete(const char *buf, const char *buf_end, size_t last_len, int *ret)
-{
- int ret_cnt = 0;
- buf = last_len < 3 ? buf : buf + last_len - 3;
-
- while (1) {
- CHECK_EOF();
- if (*buf == '\015') {
- ++buf;
- CHECK_EOF();
- EXPECT_CHAR('\012');
- ++ret_cnt;
- } else if (*buf == '\012') {
- ++buf;
- ++ret_cnt;
- } else {
- ++buf;
- ret_cnt = 0;
- }
- if (ret_cnt == 2) {
- return buf;
- }
- }
-
- *ret = -2;
- return NULL;
-}
-
-#define PARSE_INT(valp_, mul_) \
- if (*buf < '0' || '9' < *buf) { \
- buf++; \
- *ret = -1; \
- return NULL; \
- } \
- *(valp_) = (mul_) * (*buf++ - '0');
-
-#define PARSE_INT_3(valp_) \
- do { \
- int res_ = 0; \
- PARSE_INT(&res_, 100) \
- *valp_ = res_; \
- PARSE_INT(&res_, 10) \
- *valp_ += res_; \
- PARSE_INT(&res_, 1) \
- *valp_ += res_; \
- } while (0)
-
-/* returned pointer is always within [buf, buf_end), or null */
-static const char *parse_http_version(const char *buf, const char *buf_end, int *minor_version, int *ret)
-{
- /* we want at least [HTTP/1.<two chars>] to try to parse */
- if (buf_end - buf < 9) {
- *ret = -2;
- return NULL;
- }
- EXPECT_CHAR_NO_CHECK('H');
- EXPECT_CHAR_NO_CHECK('T');
- EXPECT_CHAR_NO_CHECK('T');
- EXPECT_CHAR_NO_CHECK('P');
- EXPECT_CHAR_NO_CHECK('/');
- EXPECT_CHAR_NO_CHECK('1');
- EXPECT_CHAR_NO_CHECK('.');
- PARSE_INT(minor_version, 1);
- return buf;
-}
-
-static const char *parse_headers(const char *buf, const char *buf_end, struct phr_header *headers, size_t *num_headers,
- size_t max_headers, int *ret)
-{
- for (;; ++*num_headers) {
- CHECK_EOF();
- if (*buf == '\015') {
- ++buf;
- EXPECT_CHAR('\012');
- break;
- } else if (*buf == '\012') {
- ++buf;
- break;
- }
- if (*num_headers == max_headers) {
- *ret = -1;
- return NULL;
- }
- if (!(*num_headers != 0 && (*buf == ' ' || *buf == '\t'))) {
- /* parsing name, but do not discard SP before colon, see
- * http://www.mozilla.org/security/announce/2006/mfsa2006-33.html */
- headers[*num_headers].name = buf;
- static const char ALIGNED(16) ranges1[] = "\x00 " /* control chars and up to SP */
- "\"\"" /* 0x22 */
- "()" /* 0x28,0x29 */
- ",," /* 0x2c */
- "//" /* 0x2f */
- ":@" /* 0x3a-0x40 */
- "[]" /* 0x5b-0x5d */
- "{\377"; /* 0x7b-0xff */
- int found;
- buf = findchar_fast(buf, buf_end, ranges1, sizeof(ranges1) - 1, &found);
- if (!found) {
- CHECK_EOF();
- }
- while (1) {
- if (*buf == ':') {
- break;
- } else if (!token_char_map[(unsigned char)*buf]) {
- *ret = -1;
- return NULL;
- }
- ++buf;
- CHECK_EOF();
- }
- if ((headers[*num_headers].name_len = buf - headers[*num_headers].name) == 0) {
- *ret = -1;
- return NULL;
- }
- ++buf;
- for (;; ++buf) {
- CHECK_EOF();
- if (!(*buf == ' ' || *buf == '\t')) {
- break;
- }
- }
- } else {
- headers[*num_headers].name = NULL;
- headers[*num_headers].name_len = 0;
- }
- if ((buf = get_token_to_eol(buf, buf_end, &headers[*num_headers].value, &headers[*num_headers].value_len, ret)) == NULL) {
- return NULL;
- }
- }
- return buf;
-}
-
-static const char *parse_request(const char *buf, const char *buf_end, const char **method, size_t *method_len, const char **path,
- size_t *path_len, int *minor_version, struct phr_header *headers, size_t *num_headers,
- size_t max_headers, int *ret)
-{
- /* skip first empty line (some clients add CRLF after POST content) */
- CHECK_EOF();
- if (*buf == '\015') {
- ++buf;
- EXPECT_CHAR('\012');
- } else if (*buf == '\012') {
- ++buf;
- }
-
- /* parse request line */
- ADVANCE_TOKEN(*method, *method_len);
- ++buf;
- ADVANCE_TOKEN(*path, *path_len);
- ++buf;
- if ((buf = parse_http_version(buf, buf_end, minor_version, ret)) == NULL) {
- return NULL;
- }
- if (*buf == '\015') {
- ++buf;
- EXPECT_CHAR('\012');
- } else if (*buf == '\012') {
- ++buf;
- } else {
- *ret = -1;
- return NULL;
- }
-
- return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
-}
-
-int phr_parse_request(const char *buf_start, size_t len, const char **method, size_t *method_len, const char **path,
- size_t *path_len, int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len)
-{
- const char *buf = buf_start, *buf_end = buf_start + len;
- size_t max_headers = *num_headers;
- int r;
-
- *method = NULL;
- *method_len = 0;
- *path = NULL;
- *path_len = 0;
- *minor_version = -1;
- *num_headers = 0;
-
- /* if last_len != 0, check if the request is complete (a fast countermeasure
- againt slowloris */
- if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
- return r;
- }
-
- if ((buf = parse_request(buf, buf_end, method, method_len, path, path_len, minor_version, headers, num_headers, max_headers,
- &r)) == NULL) {
- return r;
- }
-
- return (int)(buf - buf_start);
-}
-
-static const char *parse_response(const char *buf, const char *buf_end, int *minor_version, int *status, const char **msg,
- size_t *msg_len, struct phr_header *headers, size_t *num_headers, size_t max_headers, int *ret)
-{
- /* parse "HTTP/1.x" */
- if ((buf = parse_http_version(buf, buf_end, minor_version, ret)) == NULL) {
- return NULL;
- }
- /* skip space */
- if (*buf++ != ' ') {
- *ret = -1;
- return NULL;
- }
- /* parse status code, we want at least [:digit:][:digit:][:digit:]<other char> to try to parse */
- if (buf_end - buf < 4) {
- *ret = -2;
- return NULL;
- }
- PARSE_INT_3(status);
-
- /* skip space */
- if (*buf++ != ' ') {
- *ret = -1;
- return NULL;
- }
- /* get message */
- if ((buf = get_token_to_eol(buf, buf_end, msg, msg_len, ret)) == NULL) {
- return NULL;
- }
-
- return parse_headers(buf, buf_end, headers, num_headers, max_headers, ret);
-}
-
-int phr_parse_response(const char *buf_start, size_t len, int *minor_version, int *status, const char **msg, size_t *msg_len,
- struct phr_header *headers, size_t *num_headers, size_t last_len)
-{
- const char *buf = buf_start, *buf_end = buf + len;
- size_t max_headers = *num_headers;
- int r;
-
- *minor_version = -1;
- *status = 0;
- *msg = NULL;
- *msg_len = 0;
- *num_headers = 0;
-
- /* if last_len != 0, check if the response is complete (a fast countermeasure
- against slowloris */
- if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
- return r;
- }
-
- if ((buf = parse_response(buf, buf_end, minor_version, status, msg, msg_len, headers, num_headers, max_headers, &r)) == NULL) {
- return r;
- }
-
- return (int)(buf - buf_start);
-}
-
-int phr_parse_headers(const char *buf_start, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len)
-{
- const char *buf = buf_start, *buf_end = buf + len;
- size_t max_headers = *num_headers;
- int r;
-
- *num_headers = 0;
-
- /* if last_len != 0, check if the response is complete (a fast countermeasure
- against slowloris */
- if (last_len != 0 && is_complete(buf, buf_end, last_len, &r) == NULL) {
- return r;
- }
-
- if ((buf = parse_headers(buf, buf_end, headers, num_headers, max_headers, &r)) == NULL) {
- return r;
- }
-
- return (int)(buf - buf_start);
-}
-
-enum {
- CHUNKED_IN_CHUNK_SIZE,
- CHUNKED_IN_CHUNK_EXT,
- CHUNKED_IN_CHUNK_DATA,
- CHUNKED_IN_CHUNK_CRLF,
- CHUNKED_IN_TRAILERS_LINE_HEAD,
- CHUNKED_IN_TRAILERS_LINE_MIDDLE
-};
-
-static int decode_hex(int ch)
-{
- if ('0' <= ch && ch <= '9') {
- return ch - '0';
- } else if ('A' <= ch && ch <= 'F') {
- return ch - 'A' + 0xa;
- } else if ('a' <= ch && ch <= 'f') {
- return ch - 'a' + 0xa;
- } else {
- return -1;
- }
-}
-
-ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *_bufsz)
-{
- size_t dst = 0, src = 0, bufsz = *_bufsz;
- ssize_t ret = -2; /* incomplete */
-
- while (1) {
- switch (decoder->_state) {
- case CHUNKED_IN_CHUNK_SIZE:
- for (;; ++src) {
- int v;
- if (src == bufsz)
- goto Exit;
- if ((v = decode_hex(buf[src])) == -1) {
- if (decoder->_hex_count == 0) {
- ret = -1;
- goto Exit;
- }
- break;
- }
- if (decoder->_hex_count == sizeof(size_t) * 2) {
- ret = -1;
- goto Exit;
- }
- decoder->bytes_left_in_chunk = decoder->bytes_left_in_chunk * 16 + v;
- ++decoder->_hex_count;
- }
- decoder->_hex_count = 0;
- decoder->_state = CHUNKED_IN_CHUNK_EXT;
- /* fallthru */
- case CHUNKED_IN_CHUNK_EXT:
- /* RFC 7230 A.2 "Line folding in chunk extensions is disallowed" */
- for (;; ++src) {
- if (src == bufsz)
- goto Exit;
- if (buf[src] == '\012')
- break;
- }
- ++src;
- if (decoder->bytes_left_in_chunk == 0) {
- if (decoder->consume_trailer) {
- decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD;
- break;
- } else {
- goto Complete;
- }
- }
- decoder->_state = CHUNKED_IN_CHUNK_DATA;
- /* fallthru */
- case CHUNKED_IN_CHUNK_DATA: {
- size_t avail = bufsz - src;
- if (avail < decoder->bytes_left_in_chunk) {
- if (dst != src)
- memmove(buf + dst, buf + src, avail);
- src += avail;
- dst += avail;
- decoder->bytes_left_in_chunk -= avail;
- goto Exit;
- }
- if (dst != src)
- memmove(buf + dst, buf + src, decoder->bytes_left_in_chunk);
- src += decoder->bytes_left_in_chunk;
- dst += decoder->bytes_left_in_chunk;
- decoder->bytes_left_in_chunk = 0;
- decoder->_state = CHUNKED_IN_CHUNK_CRLF;
- }
- /* fallthru */
- case CHUNKED_IN_CHUNK_CRLF:
- for (;; ++src) {
- if (src == bufsz)
- goto Exit;
- if (buf[src] != '\015')
- break;
- }
- if (buf[src] != '\012') {
- ret = -1;
- goto Exit;
- }
- ++src;
- decoder->_state = CHUNKED_IN_CHUNK_SIZE;
- break;
- case CHUNKED_IN_TRAILERS_LINE_HEAD:
- for (;; ++src) {
- if (src == bufsz)
- goto Exit;
- if (buf[src] != '\015')
- break;
- }
- if (buf[src++] == '\012')
- goto Complete;
- decoder->_state = CHUNKED_IN_TRAILERS_LINE_MIDDLE;
- /* fallthru */
- case CHUNKED_IN_TRAILERS_LINE_MIDDLE:
- for (;; ++src) {
- if (src == bufsz)
- goto Exit;
- if (buf[src] == '\012')
- break;
- }
- ++src;
- decoder->_state = CHUNKED_IN_TRAILERS_LINE_HEAD;
- break;
- default:
- assert(!"decoder is corrupt");
- }
- }
-
-Complete:
- ret = bufsz - src;
-Exit:
- if (dst != src)
- memmove(buf + dst, buf + src, bufsz - src);
- *_bufsz = dst;
- return ret;
-}
-
-int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder)
-{
- return decoder->_state == CHUNKED_IN_CHUNK_DATA;
-}
-
-#undef CHECK_EOF
-#undef EXPECT_CHAR
-#undef ADVANCE_TOKEN
diff --git a/web/server/h2o/libh2o/deps/picohttpparser/picohttpparser.h b/web/server/h2o/libh2o/deps/picohttpparser/picohttpparser.h
deleted file mode 100644
index 67fd3ee74..000000000
--- a/web/server/h2o/libh2o/deps/picohttpparser/picohttpparser.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
- * Shigeo Mitsunari
- *
- * The software is licensed under either the MIT License (below) or the Perl
- * license.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#ifndef picohttpparser_h
-#define picohttpparser_h
-
-#include <sys/types.h>
-
-#ifdef _MSC_VER
-#define ssize_t intptr_t
-#endif
-
-/* $Id$ */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* contains name and value of a header (name == NULL if is a continuing line
- * of a multiline header */
-struct phr_header {
- const char *name;
- size_t name_len;
- const char *value;
- size_t value_len;
-};
-
-/* returns number of bytes consumed if successful, -2 if request is partial,
- * -1 if failed */
-int phr_parse_request(const char *buf, size_t len, const char **method, size_t *method_len, const char **path, size_t *path_len,
- int *minor_version, struct phr_header *headers, size_t *num_headers, size_t last_len);
-
-/* ditto */
-int phr_parse_response(const char *_buf, size_t len, int *minor_version, int *status, const char **msg, size_t *msg_len,
- struct phr_header *headers, size_t *num_headers, size_t last_len);
-
-/* ditto */
-int phr_parse_headers(const char *buf, size_t len, struct phr_header *headers, size_t *num_headers, size_t last_len);
-
-/* should be zero-filled before start */
-struct phr_chunked_decoder {
- size_t bytes_left_in_chunk; /* number of bytes left in current chunk */
- char consume_trailer; /* if trailing headers should be consumed */
- char _hex_count;
- char _state;
-};
-
-/* the function rewrites the buffer given as (buf, bufsz) removing the chunked-
- * encoding headers. When the function returns without an error, bufsz is
- * updated to the length of the decoded data available. Applications should
- * repeatedly call the function while it returns -2 (incomplete) every time
- * supplying newly arrived data. If the end of the chunked-encoded data is
- * found, the function returns a non-negative number indicating the number of
- * octets left undecoded at the tail of the supplied buffer. Returns -1 on
- * error.
- */
-ssize_t phr_decode_chunked(struct phr_chunked_decoder *decoder, char *buf, size_t *bufsz);
-
-/* returns if the chunked decoder is in middle of chunked data */
-int phr_decode_chunked_is_in_data(struct phr_chunked_decoder *decoder);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/web/server/h2o/libh2o/deps/picohttpparser/test.c b/web/server/h2o/libh2o/deps/picohttpparser/test.c
deleted file mode 100644
index 8f808fdfc..000000000
--- a/web/server/h2o/libh2o/deps/picohttpparser/test.c
+++ /dev/null
@@ -1,419 +0,0 @@
-/* use `make test` to run the test */
-/*
- * Copyright (c) 2009-2014 Kazuho Oku, Tokuhiro Matsuno, Daisuke Murase,
- * Shigeo Mitsunari
- *
- * The software is licensed under either the MIT License (below) or the Perl
- * license.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- * IN THE SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "picotest/picotest.h"
-#include "picohttpparser.h"
-
-static int bufis(const char *s, size_t l, const char *t)
-{
- return strlen(t) == l && memcmp(s, t, l) == 0;
-}
-
-static void test_request(void)
-{
- const char *method;
- size_t method_len;
- const char *path;
- size_t path_len;
- int minor_version;
- struct phr_header headers[4];
- size_t num_headers;
-
-#define PARSE(s, last_len, exp, comment) \
- do { \
- note(comment); \
- num_headers = sizeof(headers) / sizeof(headers[0]); \
- ok(phr_parse_request(s, sizeof(s) - 1, &method, &method_len, &path, &path_len, &minor_version, headers, &num_headers, \
- last_len) == (exp == 0 ? strlen(s) : exp)); \
- } while (0)
-
- PARSE("GET / HTTP/1.0\r\n\r\n", 0, 0, "simple");
- ok(num_headers == 0);
- ok(bufis(method, method_len, "GET"));
- ok(bufis(path, path_len, "/"));
- ok(minor_version == 0);
-
- PARSE("GET / HTTP/1.0\r\n\r", 0, -2, "partial");
-
- PARSE("GET /hoge HTTP/1.1\r\nHost: example.com\r\nCookie: \r\n\r\n", 0, 0, "parse headers");
- ok(num_headers == 2);
- ok(bufis(method, method_len, "GET"));
- ok(bufis(path, path_len, "/hoge"));
- ok(minor_version == 1);
- ok(bufis(headers[0].name, headers[0].name_len, "Host"));
- ok(bufis(headers[0].value, headers[0].value_len, "example.com"));
- ok(bufis(headers[1].name, headers[1].name_len, "Cookie"));
- ok(bufis(headers[1].value, headers[1].value_len, ""));
-
- PARSE("GET /hoge HTTP/1.1\r\nHost: example.com\r\nUser-Agent: \343\201\262\343/1.0\r\n\r\n", 0, 0, "multibyte included");
- ok(num_headers == 2);
- ok(bufis(method, method_len, "GET"));
- ok(bufis(path, path_len, "/hoge"));
- ok(minor_version == 1);
- ok(bufis(headers[0].name, headers[0].name_len, "Host"));
- ok(bufis(headers[0].value, headers[0].value_len, "example.com"));
- ok(bufis(headers[1].name, headers[1].name_len, "User-Agent"));
- ok(bufis(headers[1].value, headers[1].value_len, "\343\201\262\343/1.0"));
-
- PARSE("GET / HTTP/1.0\r\nfoo: \r\nfoo: b\r\n \tc\r\n\r\n", 0, 0, "parse multiline");
- ok(num_headers == 3);
- ok(bufis(method, method_len, "GET"));
- ok(bufis(path, path_len, "/"));
- ok(minor_version == 0);
- ok(bufis(headers[0].name, headers[0].name_len, "foo"));
- ok(bufis(headers[0].value, headers[0].value_len, ""));
- ok(bufis(headers[1].name, headers[1].name_len, "foo"));
- ok(bufis(headers[1].value, headers[1].value_len, "b"));
- ok(headers[2].name == NULL);
- ok(bufis(headers[2].value, headers[2].value_len, " \tc"));
-
- PARSE("GET / HTTP/1.0\r\nfoo : ab\r\n\r\n", 0, -1, "parse header name with trailing space");
-
- PARSE("GET", 0, -2, "incomplete 1");
- ok(method == NULL);
- PARSE("GET ", 0, -2, "incomplete 2");
- ok(bufis(method, method_len, "GET"));
- PARSE("GET /", 0, -2, "incomplete 3");
- ok(path == NULL);
- PARSE("GET / ", 0, -2, "incomplete 4");
- ok(bufis(path, path_len, "/"));
- PARSE("GET / H", 0, -2, "incomplete 5");
- PARSE("GET / HTTP/1.", 0, -2, "incomplete 6");
- PARSE("GET / HTTP/1.0", 0, -2, "incomplete 7");
- ok(minor_version == -1);
- PARSE("GET / HTTP/1.0\r", 0, -2, "incomplete 8");
- ok(minor_version == 0);
-
- PARSE("GET /hoge HTTP/1.0\r\n\r", strlen("GET /hoge HTTP/1.0\r\n\r") - 1, -2, "slowloris (incomplete)");
- PARSE("GET /hoge HTTP/1.0\r\n\r\n", strlen("GET /hoge HTTP/1.0\r\n\r\n") - 1, 0, "slowloris (complete)");
-
- PARSE("GET / HTTP/1.0\r\n:a\r\n\r\n", 0, -1, "empty header name");
- PARSE("GET / HTTP/1.0\r\n :a\r\n\r\n", 0, -1, "header name (space only)");
-
- PARSE("G\0T / HTTP/1.0\r\n\r\n", 0, -1, "NUL in method");
- PARSE("G\tT / HTTP/1.0\r\n\r\n", 0, -1, "tab in method");
- PARSE("GET /\x7fhello HTTP/1.0\r\n\r\n", 0, -1, "DEL in uri-path");
- PARSE("GET / HTTP/1.0\r\na\0b: c\r\n\r\n", 0, -1, "NUL in header name");
- PARSE("GET / HTTP/1.0\r\nab: c\0d\r\n\r\n", 0, -1, "NUL in header value");
- PARSE("GET / HTTP/1.0\r\na\033b: c\r\n\r\n", 0, -1, "CTL in header name");
- PARSE("GET / HTTP/1.0\r\nab: c\033\r\n\r\n", 0, -1, "CTL in header value");
- PARSE("GET / HTTP/1.0\r\n/: 1\r\n\r\n", 0, -1, "invalid char in header value");
- PARSE("GET /\xa0 HTTP/1.0\r\nh: c\xa2y\r\n\r\n", 0, 0, "accept MSB chars");
- ok(num_headers == 1);
- ok(bufis(method, method_len, "GET"));
- ok(bufis(path, path_len, "/\xa0"));
- ok(minor_version == 0);
- ok(bufis(headers[0].name, headers[0].name_len, "h"));
- ok(bufis(headers[0].value, headers[0].value_len, "c\xa2y"));
-
- PARSE("GET / HTTP/1.0\r\n\x7c\x7e: 1\r\n\r\n", 0, 0, "accept |~ (though forbidden by SSE)");
- ok(num_headers == 1);
- ok(bufis(headers[0].name, headers[0].name_len, "\x7c\x7e"));
- ok(bufis(headers[0].value, headers[0].value_len, "1"));
-
- PARSE("GET / HTTP/1.0\r\n\x7b: 1\r\n\r\n", 0, -1, "disallow {");
-
-#undef PARSE
-}
-
-static void test_response(void)
-{
- int minor_version;
- int status;
- const char *msg;
- size_t msg_len;
- struct phr_header headers[4];
- size_t num_headers;
-
-#define PARSE(s, last_len, exp, comment) \
- do { \
- note(comment); \
- num_headers = sizeof(headers) / sizeof(headers[0]); \
- ok(phr_parse_response(s, strlen(s), &minor_version, &status, &msg, &msg_len, headers, &num_headers, last_len) == \
- (exp == 0 ? strlen(s) : exp)); \
- } while (0)
-
- PARSE("HTTP/1.0 200 OK\r\n\r\n", 0, 0, "simple");
- ok(num_headers == 0);
- ok(status == 200);
- ok(minor_version == 0);
- ok(bufis(msg, msg_len, "OK"));
-
- PARSE("HTTP/1.0 200 OK\r\n\r", 0, -2, "partial");
-
- PARSE("HTTP/1.1 200 OK\r\nHost: example.com\r\nCookie: \r\n\r\n", 0, 0, "parse headers");
- ok(num_headers == 2);
- ok(minor_version == 1);
- ok(status == 200);
- ok(bufis(msg, msg_len, "OK"));
- ok(bufis(headers[0].name, headers[0].name_len, "Host"));
- ok(bufis(headers[0].value, headers[0].value_len, "example.com"));
- ok(bufis(headers[1].name, headers[1].name_len, "Cookie"));
- ok(bufis(headers[1].value, headers[1].value_len, ""));
-
- PARSE("HTTP/1.0 200 OK\r\nfoo: \r\nfoo: b\r\n \tc\r\n\r\n", 0, 0, "parse multiline");
- ok(num_headers == 3);
- ok(minor_version == 0);
- ok(status == 200);
- ok(bufis(msg, msg_len, "OK"));
- ok(bufis(headers[0].name, headers[0].name_len, "foo"));
- ok(bufis(headers[0].value, headers[0].value_len, ""));
- ok(bufis(headers[1].name, headers[1].name_len, "foo"));
- ok(bufis(headers[1].value, headers[1].value_len, "b"));
- ok(headers[2].name == NULL);
- ok(bufis(headers[2].value, headers[2].value_len, " \tc"));
-
- PARSE("HTTP/1.0 500 Internal Server Error\r\n\r\n", 0, 0, "internal server error");
- ok(num_headers == 0);
- ok(minor_version == 0);
- ok(status == 500);
- ok(bufis(msg, msg_len, "Internal Server Error"));
- ok(msg_len == sizeof("Internal Server Error") - 1);
-
- PARSE("H", 0, -2, "incomplete 1");
- PARSE("HTTP/1.", 0, -2, "incomplete 2");
- PARSE("HTTP/1.1", 0, -2, "incomplete 3");
- ok(minor_version == -1);
- PARSE("HTTP/1.1 ", 0, -2, "incomplete 4");
- ok(minor_version == 1);
- PARSE("HTTP/1.1 2", 0, -2, "incomplete 5");
- PARSE("HTTP/1.1 200", 0, -2, "incomplete 6");
- ok(status == 0);
- PARSE("HTTP/1.1 200 ", 0, -2, "incomplete 7");
- ok(status == 200);
- PARSE("HTTP/1.1 200 O", 0, -2, "incomplete 8");
- PARSE("HTTP/1.1 200 OK\r", 0, -2, "incomplete 9");
- ok(msg == NULL);
- PARSE("HTTP/1.1 200 OK\r\n", 0, -2, "incomplete 10");
- ok(bufis(msg, msg_len, "OK"));
- PARSE("HTTP/1.1 200 OK\n", 0, -2, "incomplete 11");
- ok(bufis(msg, msg_len, "OK"));
-
- PARSE("HTTP/1.1 200 OK\r\nA: 1\r", 0, -2, "incomplete 11");
- ok(num_headers == 0);
- PARSE("HTTP/1.1 200 OK\r\nA: 1\r\n", 0, -2, "incomplete 12");
- ok(num_headers == 1);
- ok(bufis(headers[0].name, headers[0].name_len, "A"));
- ok(bufis(headers[0].value, headers[0].value_len, "1"));
-
- PARSE("HTTP/1.0 200 OK\r\n\r", strlen("HTTP/1.0 200 OK\r\n\r") - 1, -2, "slowloris (incomplete)");
- PARSE("HTTP/1.0 200 OK\r\n\r\n", strlen("HTTP/1.0 200 OK\r\n\r\n") - 1, 0, "slowloris (complete)");
-
- PARSE("HTTP/1. 200 OK\r\n\r\n", 0, -1, "invalid http version");
- PARSE("HTTP/1.2z 200 OK\r\n\r\n", 0, -1, "invalid http version 2");
- PARSE("HTTP/1.1 OK\r\n\r\n", 0, -1, "no status code");
-
-#undef PARSE
-}
-
-static void test_headers(void)
-{
- /* only test the interface; the core parser is tested by the tests above */
-
- struct phr_header headers[4];
- size_t num_headers;
-
-#define PARSE(s, last_len, exp, comment) \
- do { \
- note(comment); \
- num_headers = sizeof(headers) / sizeof(headers[0]); \
- ok(phr_parse_headers(s, strlen(s), headers, &num_headers, last_len) == (exp == 0 ? strlen(s) : exp)); \
- } while (0)
-
- PARSE("Host: example.com\r\nCookie: \r\n\r\n", 0, 0, "simple");
- ok(num_headers == 2);
- ok(bufis(headers[0].name, headers[0].name_len, "Host"));
- ok(bufis(headers[0].value, headers[0].value_len, "example.com"));
- ok(bufis(headers[1].name, headers[1].name_len, "Cookie"));
- ok(bufis(headers[1].value, headers[1].value_len, ""));
-
- PARSE("Host: example.com\r\nCookie: \r\n\r\n", 1, 0, "slowloris");
- ok(num_headers == 2);
- ok(bufis(headers[0].name, headers[0].name_len, "Host"));
- ok(bufis(headers[0].value, headers[0].value_len, "example.com"));
- ok(bufis(headers[1].name, headers[1].name_len, "Cookie"));
- ok(bufis(headers[1].value, headers[1].value_len, ""));
-
- PARSE("Host: example.com\r\nCookie: \r\n\r", 0, -2, "partial");
-
- PARSE("Host: e\7fample.com\r\nCookie: \r\n\r", 0, -1, "error");
-
-#undef PARSE
-}
-
-static void test_chunked_at_once(int line, int consume_trailer, const char *encoded, const char *decoded, ssize_t expected)
-{
- struct phr_chunked_decoder dec = {0};
- char *buf;
- size_t bufsz;
- ssize_t ret;
-
- dec.consume_trailer = consume_trailer;
-
- note("testing at-once, source at line %d", line);
-
- buf = strdup(encoded);
- bufsz = strlen(buf);
-
- ret = phr_decode_chunked(&dec, buf, &bufsz);
-
- ok(ret == expected);
- ok(bufsz == strlen(decoded));
- ok(bufis(buf, bufsz, decoded));
- if (expected >= 0) {
- if (ret == expected)
- ok(bufis(buf + bufsz, ret, encoded + strlen(encoded) - ret));
- else
- ok(0);
- }
-
- free(buf);
-}
-
-static void test_chunked_per_byte(int line, int consume_trailer, const char *encoded, const char *decoded, ssize_t expected)
-{
- struct phr_chunked_decoder dec = {0};
- char *buf = malloc(strlen(encoded) + 1);
- size_t bytes_to_consume = strlen(encoded) - (expected >= 0 ? expected : 0), bytes_ready = 0, bufsz, i;
- ssize_t ret;
-
- dec.consume_trailer = consume_trailer;
-
- note("testing per-byte, source at line %d", line);
-
- for (i = 0; i < bytes_to_consume - 1; ++i) {
- buf[bytes_ready] = encoded[i];
- bufsz = 1;
- ret = phr_decode_chunked(&dec, buf + bytes_ready, &bufsz);
- if (ret != -2) {
- ok(0);
- goto cleanup;
- }
- bytes_ready += bufsz;
- }
- strcpy(buf + bytes_ready, encoded + bytes_to_consume - 1);
- bufsz = strlen(buf + bytes_ready);
- ret = phr_decode_chunked(&dec, buf + bytes_ready, &bufsz);
- ok(ret == expected);
- bytes_ready += bufsz;
- ok(bytes_ready == strlen(decoded));
- ok(bufis(buf, bytes_ready, decoded));
- if (expected >= 0) {
- if (ret == expected)
- ok(bufis(buf + bytes_ready, expected, encoded + bytes_to_consume));
- else
- ok(0);
- }
-
-cleanup:
- free(buf);
-}
-
-static void test_chunked_failure(int line, const char *encoded, ssize_t expected)
-{
- struct phr_chunked_decoder dec = {0};
- char *buf = strdup(encoded);
- size_t bufsz, i;
- ssize_t ret;
-
- note("testing failure at-once, source at line %d", line);
- bufsz = strlen(buf);
- ret = phr_decode_chunked(&dec, buf, &bufsz);
- ok(ret == expected);
-
- note("testing failure per-byte, source at line %d", line);
- memset(&dec, 0, sizeof(dec));
- for (i = 0; encoded[i] != '\0'; ++i) {
- buf[0] = encoded[i];
- bufsz = 1;
- ret = phr_decode_chunked(&dec, buf, &bufsz);
- if (ret == -1) {
- ok(ret == expected);
- goto cleanup;
- } else if (ret == -2) {
- /* continue */
- } else {
- ok(0);
- goto cleanup;
- }
- }
- ok(ret == expected);
-
-cleanup:
- free(buf);
-}
-
-static void (*chunked_test_runners[])(int, int, const char *, const char *, ssize_t) = {test_chunked_at_once, test_chunked_per_byte,
- NULL};
-
-static void test_chunked(void)
-{
- size_t i;
-
- for (i = 0; chunked_test_runners[i] != NULL; ++i) {
- chunked_test_runners[i](__LINE__, 0, "b\r\nhello world\r\n0\r\n", "hello world", 0);
- chunked_test_runners[i](__LINE__, 0, "6\r\nhello \r\n5\r\nworld\r\n0\r\n", "hello world", 0);
- chunked_test_runners[i](__LINE__, 0, "6;comment=hi\r\nhello \r\n5\r\nworld\r\n0\r\n", "hello world", 0);
- chunked_test_runners[i](__LINE__, 0, "6\r\nhello \r\n5\r\nworld\r\n0\r\na: b\r\nc: d\r\n\r\n", "hello world",
- sizeof("a: b\r\nc: d\r\n\r\n") - 1);
- chunked_test_runners[i](__LINE__, 0, "b\r\nhello world\r\n0\r\n", "hello world", 0);
- }
-
- note("failures");
- test_chunked_failure(__LINE__, "z\r\nabcdefg", -1);
- if (sizeof(size_t) == 8) {
- test_chunked_failure(__LINE__, "6\r\nhello \r\nffffffffffffffff\r\nabcdefg", -2);
- test_chunked_failure(__LINE__, "6\r\nhello \r\nfffffffffffffffff\r\nabcdefg", -1);
- }
-}
-
-static void test_chunked_consume_trailer(void)
-{
- size_t i;
-
- for (i = 0; chunked_test_runners[i] != NULL; ++i) {
- chunked_test_runners[i](__LINE__, 1, "b\r\nhello world\r\n0\r\n", "hello world", -2);
- chunked_test_runners[i](__LINE__, 1, "6\r\nhello \r\n5\r\nworld\r\n0\r\n", "hello world", -2);
- chunked_test_runners[i](__LINE__, 1, "6;comment=hi\r\nhello \r\n5\r\nworld\r\n0\r\n", "hello world", -2);
- chunked_test_runners[i](__LINE__, 1, "b\r\nhello world\r\n0\r\n\r\n", "hello world", 0);
- chunked_test_runners[i](__LINE__, 1, "b\nhello world\n0\n\n", "hello world", 0);
- chunked_test_runners[i](__LINE__, 1, "6\r\nhello \r\n5\r\nworld\r\n0\r\na: b\r\nc: d\r\n\r\n", "hello world", 0);
- }
-}
-
-int main(int argc, char **argv)
-{
- subtest("request", test_request);
- subtest("response", test_response);
- subtest("headers", test_headers);
- subtest("chunked", test_chunked);
- subtest("chunked-consume-trailer", test_chunked_consume_trailer);
- return done_testing();
-}