mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-28 15:28:30 +00:00
Add chunked transfer decoding to redbean
This commit is contained in:
parent
8d5f60a9cd
commit
58fb2fb3d3
13 changed files with 693 additions and 292 deletions
|
@ -81,7 +81,6 @@ TE, kHttpTe
|
|||
Trailer, kHttpTrailer
|
||||
Transfer-Encoding, kHttpTransferEncoding
|
||||
Upgrade, kHttpUpgrade
|
||||
Uri, kHttpUri
|
||||
Warning, kHttpWarning
|
||||
WWW-Authenticate, kHttpWwwAuthenticate
|
||||
Via, kHttpVia
|
||||
|
@ -93,3 +92,9 @@ Referrer-Policy, kHttpReferrerPolicy
|
|||
X-XSS-Protection, kHttpXXssProtection
|
||||
Accept-Ranges, kHttpAcceptRanges
|
||||
Set-Cookie, kHttpSetCookie
|
||||
Sec-CH-UA, kHttpSecChUa
|
||||
Sec-CH-UA-Mobile, kHttpSecChUaMobile
|
||||
Sec-Fetch-Site, kHttpSecFetchSite
|
||||
Sec-Fetch-Mode, kHttpSecFetchMode
|
||||
Sec-Fetch-User, kHttpSecFetchUser
|
||||
Sec-Fetch-Dest, kHttpSecFetchDest
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* ANSI-C code produced by gperf version 3.1 */
|
||||
/* Command-line: gperf gethttpheader.gperf */
|
||||
/* Computed positions: -k'1,10,22,$' */
|
||||
/* Computed positions: -k'5,10-11,22,$' */
|
||||
/* clang-format off */
|
||||
|
||||
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
||||
|
@ -38,12 +38,12 @@
|
|||
#line 12 "gethttpheader.gperf"
|
||||
struct thatispacked HttpHeaderSlot { char *name; char code; };
|
||||
|
||||
#define TOTAL_KEYWORDS 82
|
||||
#define TOTAL_KEYWORDS 87
|
||||
#define MIN_WORD_LENGTH 2
|
||||
#define MAX_WORD_LENGTH 32
|
||||
#define MIN_HASH_VALUE 6
|
||||
#define MAX_HASH_VALUE 133
|
||||
/* maximum key range = 128, duplicates = 0 */
|
||||
#define MIN_HASH_VALUE 3
|
||||
#define MAX_HASH_VALUE 198
|
||||
/* maximum key range = 196, duplicates = 0 */
|
||||
|
||||
#ifndef GPERF_DOWNCASE
|
||||
#define GPERF_DOWNCASE 1
|
||||
|
@ -102,32 +102,32 @@ hash (register const char *str, register size_t len)
|
|||
{
|
||||
static const unsigned char asso_values[] =
|
||||
{
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 20, 134, 134, 134, 134,
|
||||
134, 134, 134, 0, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 0, 134, 20, 95, 5,
|
||||
10, 70, 15, 30, 134, 5, 15, 20, 0, 75,
|
||||
40, 134, 35, 20, 0, 50, 25, 30, 0, 30,
|
||||
134, 134, 134, 134, 134, 134, 134, 0, 134, 20,
|
||||
95, 5, 10, 70, 15, 30, 134, 5, 15, 20,
|
||||
0, 75, 40, 134, 35, 20, 0, 50, 25, 30,
|
||||
0, 30, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134, 134, 134, 134, 134,
|
||||
134, 134, 134, 134, 134, 134
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 55, 199, 199, 199, 199,
|
||||
199, 199, 199, 20, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 15, 199, 30, 35, 10,
|
||||
25, 15, 0, 70, 199, 55, 25, 40, 0, 45,
|
||||
15, 20, 50, 0, 0, 5, 199, 0, 199, 20,
|
||||
199, 199, 199, 199, 199, 199, 199, 15, 199, 30,
|
||||
35, 10, 25, 15, 0, 70, 199, 55, 25, 40,
|
||||
0, 45, 15, 20, 50, 0, 0, 5, 199, 0,
|
||||
199, 20, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
|
||||
199, 199, 199, 199, 199, 199
|
||||
};
|
||||
register unsigned int hval = len;
|
||||
|
||||
|
@ -147,6 +147,8 @@ hash (register const char *str, register size_t len)
|
|||
case 13:
|
||||
case 12:
|
||||
case 11:
|
||||
hval += asso_values[(unsigned char)str[10]];
|
||||
/*FALLTHROUGH*/
|
||||
case 10:
|
||||
hval += asso_values[(unsigned char)str[9]];
|
||||
/*FALLTHROUGH*/
|
||||
|
@ -155,11 +157,11 @@ hash (register const char *str, register size_t len)
|
|||
case 7:
|
||||
case 6:
|
||||
case 5:
|
||||
hval += asso_values[(unsigned char)str[4]];
|
||||
/*FALLTHROUGH*/
|
||||
case 4:
|
||||
case 3:
|
||||
case 2:
|
||||
case 1:
|
||||
hval += asso_values[(unsigned char)str[0]];
|
||||
break;
|
||||
}
|
||||
return hval + asso_values[(unsigned char)str[len - 1]];
|
||||
|
@ -170,193 +172,220 @@ LookupHttpHeader (register const char *str, register size_t len)
|
|||
{
|
||||
static const struct thatispacked HttpHeaderSlot wordlist[] =
|
||||
{
|
||||
{""}, {""}, {""}, {""}, {""}, {""},
|
||||
#line 17 "gethttpheader.gperf"
|
||||
{"Accept", kHttpAccept},
|
||||
{""}, {""}, {""},
|
||||
#line 27 "gethttpheader.gperf"
|
||||
{"DNT", kHttpDnt},
|
||||
#line 14 "gethttpheader.gperf"
|
||||
{"Host", kHttpHost},
|
||||
#line 46 "gethttpheader.gperf"
|
||||
{"Allow", kHttpAllow},
|
||||
{""}, {""},
|
||||
#line 73 "gethttpheader.gperf"
|
||||
{"Location", kHttpLocation},
|
||||
{""}, {""}, {""},
|
||||
#line 80 "gethttpheader.gperf"
|
||||
{"TE", kHttpTe},
|
||||
#line 58 "gethttpheader.gperf"
|
||||
{"Age", kHttpAge},
|
||||
{""}, {""},
|
||||
#line 66 "gethttpheader.gperf"
|
||||
{"Expect", kHttpExpect},
|
||||
{""},
|
||||
#line 59 "gethttpheader.gperf"
|
||||
{"Authorization", kHttpAuthorization},
|
||||
#line 48 "gethttpheader.gperf"
|
||||
{"Accept-Charset", kHttpAcceptCharset},
|
||||
{""},
|
||||
#line 93 "gethttpheader.gperf"
|
||||
{"X-XSS-Protection", kHttpXXssProtection},
|
||||
#line 34 "gethttpheader.gperf"
|
||||
{"X-CSRF-Token", kHttpXCsrfToken},
|
||||
{""},
|
||||
#line 14 "gethttpheader.gperf"
|
||||
{"Host", kHttpHost},
|
||||
#line 18 "gethttpheader.gperf"
|
||||
{"Accept-Language", kHttpAcceptLanguage},
|
||||
#line 32 "gethttpheader.gperf"
|
||||
{"X-Forwarded-Host", kHttpXForwardedHost},
|
||||
{""},
|
||||
#line 73 "gethttpheader.gperf"
|
||||
{"Location", kHttpLocation},
|
||||
#line 72 "gethttpheader.gperf"
|
||||
{"Link", kHttpLink},
|
||||
#line 71 "gethttpheader.gperf"
|
||||
{"Keep-Alive", kHttpKeepAlive},
|
||||
#line 53 "gethttpheader.gperf"
|
||||
{"Access-Control-MaxAge", kHttpAccessControlMaxAge},
|
||||
#line 91 "gethttpheader.gperf"
|
||||
{"Alt-Svc", kHttpAltSvc},
|
||||
#line 87 "gethttpheader.gperf"
|
||||
#line 40 "gethttpheader.gperf"
|
||||
{"Date", kHttpDate},
|
||||
{""}, {""}, {""},
|
||||
#line 86 "gethttpheader.gperf"
|
||||
{"Via", kHttpVia},
|
||||
#line 35 "gethttpheader.gperf"
|
||||
{"Save-Data", kHttpSaveData},
|
||||
#line 45 "gethttpheader.gperf"
|
||||
{"ETag", kHttpEtag},
|
||||
#line 16 "gethttpheader.gperf"
|
||||
{"Connection", kHttpConnection},
|
||||
#line 26 "gethttpheader.gperf"
|
||||
{"Cookie", kHttpCookie},
|
||||
#line 42 "gethttpheader.gperf"
|
||||
{"Expires", kHttpExpires},
|
||||
#line 94 "gethttpheader.gperf"
|
||||
#line 17 "gethttpheader.gperf"
|
||||
{"Accept", kHttpAccept},
|
||||
{""},
|
||||
#line 67 "gethttpheader.gperf"
|
||||
{"If-Match", kHttpIfMatch},
|
||||
#line 39 "gethttpheader.gperf"
|
||||
{"Vary", kHttpVary},
|
||||
#line 36 "gethttpheader.gperf"
|
||||
{"Range", kHttpRange},
|
||||
#line 92 "gethttpheader.gperf"
|
||||
{"X-XSS-Protection", kHttpXXssProtection},
|
||||
{""},
|
||||
#line 50 "gethttpheader.gperf"
|
||||
{"Access-Control-Allow-Headers", kHttpAccessControlAllowHeaders},
|
||||
#line 55 "gethttpheader.gperf"
|
||||
{"Access-Control-RequestHeaders", kHttpAccessControlRequestHeaders},
|
||||
#line 57 "gethttpheader.gperf"
|
||||
{"Access-Control-Request-Methods", kHttpAccessControlRequestMethods},
|
||||
#line 53 "gethttpheader.gperf"
|
||||
{"Access-Control-MaxAge", kHttpAccessControlMaxAge},
|
||||
#line 83 "gethttpheader.gperf"
|
||||
{"Upgrade", kHttpUpgrade},
|
||||
#line 69 "gethttpheader.gperf"
|
||||
{"If-Range", kHttpIfRange},
|
||||
#line 37 "gethttpheader.gperf"
|
||||
{"Content-Length", kHttpContentLength},
|
||||
{""},
|
||||
#line 66 "gethttpheader.gperf"
|
||||
{"Expect", kHttpExpect},
|
||||
#line 90 "gethttpheader.gperf"
|
||||
{"Alt-Svc", kHttpAltSvc},
|
||||
{""},
|
||||
#line 61 "gethttpheader.gperf"
|
||||
{"Content-Description", kHttpContentDescription},
|
||||
{""},
|
||||
#line 85 "gethttpheader.gperf"
|
||||
{"WWW-Authenticate", kHttpWwwAuthenticate},
|
||||
#line 82 "gethttpheader.gperf"
|
||||
{"Transfer-Encoding", kHttpTransferEncoding},
|
||||
#line 93 "gethttpheader.gperf"
|
||||
{"Accept-Ranges", kHttpAcceptRanges},
|
||||
#line 29 "gethttpheader.gperf"
|
||||
{"From", kHttpFrom},
|
||||
#line 46 "gethttpheader.gperf"
|
||||
{"Allow", kHttpAllow},
|
||||
#line 31 "gethttpheader.gperf"
|
||||
{"X-Requested-With", kHttpXRequestedWith},
|
||||
#line 88 "gethttpheader.gperf"
|
||||
{"X-Frame-Options", kHttpXFrameOptions},
|
||||
#line 77 "gethttpheader.gperf"
|
||||
{"Proxy-Connection", kHttpProxyConnection},
|
||||
#line 60 "gethttpheader.gperf"
|
||||
{"Content-Base", kHttpContentBase},
|
||||
#line 47 "gethttpheader.gperf"
|
||||
{"Content-Range", kHttpContentRange},
|
||||
{""},
|
||||
#line 95 "gethttpheader.gperf"
|
||||
{"Set-Cookie", kHttpSetCookie},
|
||||
#line 24 "gethttpheader.gperf"
|
||||
{"Upgrade-Insecure-Requests", kHttpUpgradeInsecureRequests},
|
||||
#line 63 "gethttpheader.gperf"
|
||||
{"Content-Language", kHttpContentLanguage},
|
||||
#line 81 "gethttpheader.gperf"
|
||||
{"Trailer", kHttpTrailer},
|
||||
#line 69 "gethttpheader.gperf"
|
||||
{"If-Range", kHttpIfRange},
|
||||
#line 61 "gethttpheader.gperf"
|
||||
{"Content-Description", kHttpContentDescription},
|
||||
#line 36 "gethttpheader.gperf"
|
||||
{"Range", kHttpRange},
|
||||
#line 25 "gethttpheader.gperf"
|
||||
{"Pragma", kHttpPragma},
|
||||
#line 28 "gethttpheader.gperf"
|
||||
{"Sec-GPC", kHttpSecGpc},
|
||||
#line 15 "gethttpheader.gperf"
|
||||
{"Cache-Control", kHttpCacheControl},
|
||||
#line 55 "gethttpheader.gperf"
|
||||
{"Access-Control-RequestHeaders", kHttpAccessControlRequestHeaders},
|
||||
#line 57 "gethttpheader.gperf"
|
||||
{"Access-Control-Request-Methods", kHttpAccessControlRequestMethods},
|
||||
#line 86 "gethttpheader.gperf"
|
||||
{"WWW-Authenticate", kHttpWwwAuthenticate},
|
||||
{""},
|
||||
#line 67 "gethttpheader.gperf"
|
||||
{"If-Match", kHttpIfMatch},
|
||||
#line 37 "gethttpheader.gperf"
|
||||
{"Content-Length", kHttpContentLength},
|
||||
#line 22 "gethttpheader.gperf"
|
||||
{"X-Forwarded-For", kHttpXForwardedFor},
|
||||
#line 77 "gethttpheader.gperf"
|
||||
{"Proxy-Connection", kHttpProxyConnection},
|
||||
#line 30 "gethttpheader.gperf"
|
||||
{"If-Modified-Since", kHttpIfModifiedSince},
|
||||
#line 68 "gethttpheader.gperf"
|
||||
{"If-None-Match", kHttpIfNoneMatch},
|
||||
#line 39 "gethttpheader.gperf"
|
||||
{"Vary", kHttpVary},
|
||||
#line 95 "gethttpheader.gperf"
|
||||
{"Sec-CH-UA", kHttpSecChUa},
|
||||
#line 18 "gethttpheader.gperf"
|
||||
{"Accept-Language", kHttpAcceptLanguage},
|
||||
#line 54 "gethttpheader.gperf"
|
||||
{"Access-Control-Method", kHttpAccessControlMethod},
|
||||
#line 42 "gethttpheader.gperf"
|
||||
{"Expires", kHttpExpires},
|
||||
#line 75 "gethttpheader.gperf"
|
||||
{"Proxy-Authenticate", kHttpProxyAuthenticate},
|
||||
#line 72 "gethttpheader.gperf"
|
||||
{"Link", kHttpLink},
|
||||
#line 94 "gethttpheader.gperf"
|
||||
{"Set-Cookie", kHttpSetCookie},
|
||||
#line 25 "gethttpheader.gperf"
|
||||
{"Pragma", kHttpPragma},
|
||||
#line 49 "gethttpheader.gperf"
|
||||
{"Access-Control-Allow-Credentials", kHttpAccessControlAllowCredentials},
|
||||
{""},
|
||||
#line 56 "gethttpheader.gperf"
|
||||
{"Access-Control-Request-Method", kHttpAccessControlRequestMethod},
|
||||
#line 20 "gethttpheader.gperf"
|
||||
{"User-Agent", kHttpUserAgent},
|
||||
#line 41 "gethttpheader.gperf"
|
||||
{"Server", kHttpServer},
|
||||
#line 83 "gethttpheader.gperf"
|
||||
{"Upgrade", kHttpUpgrade},
|
||||
#line 50 "gethttpheader.gperf"
|
||||
{"Access-Control-Allow-Headers", kHttpAccessControlAllowHeaders},
|
||||
#line 70 "gethttpheader.gperf"
|
||||
{"If-Unmodified-Since", kHttpIfUnmodifiedSince},
|
||||
{""},
|
||||
#line 78 "gethttpheader.gperf"
|
||||
{"Public", kHttpPublic},
|
||||
#line 38 "gethttpheader.gperf"
|
||||
{"Content-Type", kHttpContentType},
|
||||
#line 51 "gethttpheader.gperf"
|
||||
{"Access-Control-Allow-Methods", kHttpAccessControlAllowMethods},
|
||||
#line 62 "gethttpheader.gperf"
|
||||
{"Content-Disposition", kHttpContentDisposition},
|
||||
{""}, {""},
|
||||
#line 49 "gethttpheader.gperf"
|
||||
{"Access-Control-Allow-Credentials", kHttpAccessControlAllowCredentials},
|
||||
#line 43 "gethttpheader.gperf"
|
||||
{"Content-Encoding", kHttpContentEncoding},
|
||||
#line 52 "gethttpheader.gperf"
|
||||
{"Access-Control-Allow-Origin", kHttpAccessControlAllowOrigin},
|
||||
#line 68 "gethttpheader.gperf"
|
||||
{"If-None-Match", kHttpIfNoneMatch},
|
||||
{""}, {""},
|
||||
#line 23 "gethttpheader.gperf"
|
||||
{"Origin", kHttpOrigin},
|
||||
#line 89 "gethttpheader.gperf"
|
||||
{"X-Content-Type-Options", kHttpXContentTypeOptions},
|
||||
{""},
|
||||
#line 35 "gethttpheader.gperf"
|
||||
{"Save-Data", kHttpSaveData},
|
||||
{""},
|
||||
#line 31 "gethttpheader.gperf"
|
||||
{"X-Requested-With", kHttpXRequestedWith},
|
||||
#line 81 "gethttpheader.gperf"
|
||||
{"Trailer", kHttpTrailer},
|
||||
{""},
|
||||
#line 76 "gethttpheader.gperf"
|
||||
{"Proxy-Authorization", kHttpProxyAuthorization},
|
||||
#line 89 "gethttpheader.gperf"
|
||||
{"X-Frame-Options", kHttpXFrameOptions},
|
||||
{""},
|
||||
#line 21 "gethttpheader.gperf"
|
||||
{"Referer", kHttpReferer},
|
||||
#line 75 "gethttpheader.gperf"
|
||||
{"Proxy-Authenticate", kHttpProxyAuthenticate},
|
||||
#line 45 "gethttpheader.gperf"
|
||||
{"ETag", kHttpEtag},
|
||||
{""},
|
||||
#line 23 "gethttpheader.gperf"
|
||||
{"Origin", kHttpOrigin},
|
||||
#line 90 "gethttpheader.gperf"
|
||||
{"X-Content-Type-Options", kHttpXContentTypeOptions},
|
||||
#line 71 "gethttpheader.gperf"
|
||||
{"Keep-Alive", kHttpKeepAlive},
|
||||
#line 26 "gethttpheader.gperf"
|
||||
{"Cookie", kHttpCookie},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
#line 84 "gethttpheader.gperf"
|
||||
{"Uri", kHttpUri},
|
||||
{""}, {""},
|
||||
#line 79 "gethttpheader.gperf"
|
||||
{"Retry-After", kHttpRetryAfter},
|
||||
#line 74 "gethttpheader.gperf"
|
||||
{"Max-Forwards", kHttpMaxForwards},
|
||||
{""}, {""}, {""}, {""},
|
||||
#line 82 "gethttpheader.gperf"
|
||||
{"Transfer-Encoding", kHttpTransferEncoding},
|
||||
{""}, {""}, {""}, {""},
|
||||
#line 33 "gethttpheader.gperf"
|
||||
{"X-Forwarded-Proto", kHttpXForwardedProto},
|
||||
#line 27 "gethttpheader.gperf"
|
||||
{"DNT", kHttpDnt},
|
||||
{""},
|
||||
#line 24 "gethttpheader.gperf"
|
||||
{"Upgrade-Insecure-Requests", kHttpUpgradeInsecureRequests},
|
||||
{""},
|
||||
#line 52 "gethttpheader.gperf"
|
||||
{"Access-Control-Allow-Origin", kHttpAccessControlAllowOrigin},
|
||||
{""},
|
||||
#line 40 "gethttpheader.gperf"
|
||||
{"Date", kHttpDate},
|
||||
#line 19 "gethttpheader.gperf"
|
||||
{"Accept-Encoding", kHttpAcceptEncoding},
|
||||
#line 43 "gethttpheader.gperf"
|
||||
{"Content-Encoding", kHttpContentEncoding},
|
||||
#line 85 "gethttpheader.gperf"
|
||||
{"Warning", kHttpWarning},
|
||||
{""}, {""},
|
||||
#line 88 "gethttpheader.gperf"
|
||||
{"Strict-Transport-Security", kHttpStrictTransportSecurity},
|
||||
#line 64 "gethttpheader.gperf"
|
||||
{"Content-Location", kHttpContentLocation},
|
||||
{""}, {""}, {""}, {""},
|
||||
#line 54 "gethttpheader.gperf"
|
||||
{"Access-Control-Method", kHttpAccessControlMethod},
|
||||
{""}, {""}, {""},
|
||||
#line 92 "gethttpheader.gperf"
|
||||
{"Referrer-Policy", kHttpReferrerPolicy},
|
||||
{""}, {""}, {""},
|
||||
#line 56 "gethttpheader.gperf"
|
||||
{"Access-Control-Request-Method", kHttpAccessControlRequestMethod},
|
||||
{""},
|
||||
#line 48 "gethttpheader.gperf"
|
||||
{"Accept-Charset", kHttpAcceptCharset},
|
||||
{""},
|
||||
#line 65 "gethttpheader.gperf"
|
||||
{"Content-MD5", kHttpContentMd5},
|
||||
{""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""},
|
||||
#line 15 "gethttpheader.gperf"
|
||||
{"Cache-Control", kHttpCacheControl},
|
||||
#line 62 "gethttpheader.gperf"
|
||||
{"Content-Disposition", kHttpContentDisposition},
|
||||
{""},
|
||||
#line 64 "gethttpheader.gperf"
|
||||
{"Content-Location", kHttpContentLocation},
|
||||
{""}, {""},
|
||||
#line 97 "gethttpheader.gperf"
|
||||
{"Sec-Fetch-Site", kHttpSecFetchSite},
|
||||
{""},
|
||||
#line 78 "gethttpheader.gperf"
|
||||
{"Public", kHttpPublic},
|
||||
#line 21 "gethttpheader.gperf"
|
||||
{"Referer", kHttpReferer},
|
||||
{""}, {""}, {""},
|
||||
#line 32 "gethttpheader.gperf"
|
||||
{"X-Forwarded-Host", kHttpXForwardedHost},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
#line 30 "gethttpheader.gperf"
|
||||
{"If-Modified-Since", kHttpIfModifiedSince},
|
||||
{""}, {""},
|
||||
#line 19 "gethttpheader.gperf"
|
||||
{"Accept-Encoding", kHttpAcceptEncoding},
|
||||
{""},
|
||||
#line 74 "gethttpheader.gperf"
|
||||
{"Max-Forwards", kHttpMaxForwards},
|
||||
{""},
|
||||
#line 70 "gethttpheader.gperf"
|
||||
{"If-Unmodified-Since", kHttpIfUnmodifiedSince},
|
||||
{""}, {""},
|
||||
#line 34 "gethttpheader.gperf"
|
||||
{"X-CSRF-Token", kHttpXCsrfToken},
|
||||
#line 59 "gethttpheader.gperf"
|
||||
{"Authorization", kHttpAuthorization},
|
||||
#line 100 "gethttpheader.gperf"
|
||||
{"Sec-Fetch-Dest", kHttpSecFetchDest},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""},
|
||||
#line 87 "gethttpheader.gperf"
|
||||
{"Strict-Transport-Security", kHttpStrictTransportSecurity},
|
||||
#line 79 "gethttpheader.gperf"
|
||||
{"Retry-After", kHttpRetryAfter},
|
||||
{""}, {""},
|
||||
#line 98 "gethttpheader.gperf"
|
||||
{"Sec-Fetch-Mode", kHttpSecFetchMode},
|
||||
#line 91 "gethttpheader.gperf"
|
||||
{"Referrer-Policy", kHttpReferrerPolicy},
|
||||
{""}, {""}, {""},
|
||||
#line 99 "gethttpheader.gperf"
|
||||
{"Sec-Fetch-User", kHttpSecFetchUser},
|
||||
{""},
|
||||
#line 96 "gethttpheader.gperf"
|
||||
{"Sec-CH-UA-Mobile", kHttpSecChUaMobile},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
#line 33 "gethttpheader.gperf"
|
||||
{"X-Forwarded-Proto", kHttpXForwardedProto},
|
||||
{""}, {""},
|
||||
#line 22 "gethttpheader.gperf"
|
||||
{"X-Forwarded-For", kHttpXForwardedFor},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""},
|
||||
#line 44 "gethttpheader.gperf"
|
||||
{"Last-Modified", kHttpLastModified}
|
||||
};
|
||||
|
|
|
@ -160,8 +160,6 @@ const char *GetHttpHeaderName(int h) {
|
|||
return "Transfer-Encoding";
|
||||
case kHttpUpgrade:
|
||||
return "Upgrade";
|
||||
case kHttpUri:
|
||||
return "Uri";
|
||||
case kHttpWarning:
|
||||
return "Warning";
|
||||
case kHttpWwwAuthenticate:
|
||||
|
@ -184,6 +182,18 @@ const char *GetHttpHeaderName(int h) {
|
|||
return "Accept-Ranges";
|
||||
case kHttpSetCookie:
|
||||
return "Set-Cookie";
|
||||
case kHttpSecChUa:
|
||||
return "Sec-CH-UA";
|
||||
case kHttpSecChUaMobile:
|
||||
return "Sec-CH-UA-Mobile";
|
||||
case kHttpSecFetchSite:
|
||||
return "Sec-Fetch-Site";
|
||||
case kHttpSecFetchMode:
|
||||
return "Sec-Fetch-Mode";
|
||||
case kHttpSecFetchUser:
|
||||
return "Sec-Fetch-User";
|
||||
case kHttpSecFetchDest:
|
||||
return "Sec-Fetch-Dest";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,31 @@
|
|||
#define kHttpReport 16
|
||||
#define kHttpUnlock 17
|
||||
|
||||
#define kHttpStateStart 0
|
||||
#define kHttpStateMethod 1
|
||||
#define kHttpStateUri 2
|
||||
#define kHttpStateVersion 3
|
||||
#define kHttpStateStatus 4
|
||||
#define kHttpStateMessage 5
|
||||
#define kHttpStateName 6
|
||||
#define kHttpStateColon 7
|
||||
#define kHttpStateValue 8
|
||||
#define kHttpStateCr 9
|
||||
#define kHttpStateLf1 10
|
||||
#define kHttpStateLf2 11
|
||||
|
||||
#define kHttpStateChunkStart 0
|
||||
#define kHttpStateChunkSize 1
|
||||
#define kHttpStateChunkExt 2
|
||||
#define kHttpStateChunkLf1 3
|
||||
#define kHttpStateChunk 4
|
||||
#define kHttpStateChunkCr2 5
|
||||
#define kHttpStateChunkLf2 6
|
||||
#define kHttpStateTrailerStart 7
|
||||
#define kHttpStateTrailer 8
|
||||
#define kHttpStateTrailerLf1 9
|
||||
#define kHttpStateTrailerLf2 10
|
||||
|
||||
#define kHttpHost 0
|
||||
#define kHttpCacheControl 1
|
||||
#define kHttpConnection 2
|
||||
|
@ -93,19 +118,24 @@
|
|||
#define kHttpTrailer 67
|
||||
#define kHttpTransferEncoding 68
|
||||
#define kHttpUpgrade 69
|
||||
#define kHttpUri 70
|
||||
#define kHttpWarning 71
|
||||
#define kHttpWwwAuthenticate 72
|
||||
#define kHttpVia 73
|
||||
#define kHttpStrictTransportSecurity 74
|
||||
#define kHttpXFrameOptions 75
|
||||
#define kHttpXContentTypeOptions 76
|
||||
#define kHttpAltSvc 77
|
||||
#define kHttpReferrerPolicy 78
|
||||
#define kHttpXXssProtection 79
|
||||
#define kHttpAcceptRanges 80
|
||||
#define kHttpSetCookie 81
|
||||
#define kHttpHeadersMax 82
|
||||
#define kHttpWarning 70
|
||||
#define kHttpWwwAuthenticate 71
|
||||
#define kHttpVia 72
|
||||
#define kHttpStrictTransportSecurity 73
|
||||
#define kHttpXFrameOptions 74
|
||||
#define kHttpXContentTypeOptions 75
|
||||
#define kHttpAltSvc 76
|
||||
#define kHttpReferrerPolicy 77
|
||||
#define kHttpXXssProtection 78
|
||||
#define kHttpAcceptRanges 79
|
||||
#define kHttpSetCookie 80
|
||||
#define kHttpSecChUa 81
|
||||
#define kHttpSecChUaMobile 82
|
||||
#define kHttpSecFetchSite 83
|
||||
#define kHttpSecFetchMode 84
|
||||
#define kHttpSecFetchUser 85
|
||||
#define kHttpSecFetchDest 86
|
||||
#define kHttpHeadersMax 87
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
@ -139,6 +169,13 @@ struct HttpMessage {
|
|||
struct HttpHeaders xheaders;
|
||||
};
|
||||
|
||||
struct HttpUnchunker {
|
||||
int t;
|
||||
size_t i;
|
||||
size_t j;
|
||||
ssize_t m;
|
||||
};
|
||||
|
||||
extern const char kHttpToken[256];
|
||||
extern const char kHttpMethod[18][8];
|
||||
extern const bool kHttpRepeatable[kHttpHeadersMax];
|
||||
|
@ -163,6 +200,7 @@ bool IsReasonablePath(const char *, size_t);
|
|||
int64_t ParseIp(const char *, size_t);
|
||||
int ParseForwarded(const char *, size_t, uint32_t *, uint16_t *);
|
||||
bool IsMimeType(const char *, size_t, const char *);
|
||||
ssize_t Unchunk(struct HttpUnchunker *, char *, size_t, size_t *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -73,7 +73,6 @@ const bool kHttpRepeatable[kHttpHeadersMax] = {
|
|||
[kHttpTrailer] = true,
|
||||
[kHttpTransferEncoding] = true,
|
||||
[kHttpUpgrade] = true,
|
||||
[kHttpUri] = true,
|
||||
[kHttpVary] = true,
|
||||
[kHttpVia] = true,
|
||||
[kHttpWarning] = true,
|
||||
|
|
|
@ -31,21 +31,6 @@
|
|||
|
||||
#define LIMIT (SHRT_MAX - 2)
|
||||
|
||||
enum HttpMessageState {
|
||||
START,
|
||||
METHOD,
|
||||
URI,
|
||||
VERSION,
|
||||
STATUS,
|
||||
MESSAGE,
|
||||
HKEY,
|
||||
HSEP,
|
||||
HVAL,
|
||||
CR1,
|
||||
LF1,
|
||||
LF2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Initializes HTTP message parser.
|
||||
*/
|
||||
|
@ -78,8 +63,8 @@ void DestroyHttpMessage(struct HttpMessage *r) {
|
|||
*
|
||||
* This parser assumes ISO-8859-1 and guarantees no C0 or C1 control
|
||||
* codes are present in message fields, with the exception of tab.
|
||||
* Please note that fields like URI may use UTF-8 percent encoding. This
|
||||
* parser doesn't care if you choose ASA X3.4-1963 or MULTICS newlines.
|
||||
* Please note that fields like kHttpStateUri may use UTF-8 percent encoding.
|
||||
* This parser doesn't care if you choose ASA X3.4-1963 or MULTICS newlines.
|
||||
*
|
||||
* kHttpRepeatable defines which standard header fields are O(1) and
|
||||
* which ones may have comma entries spilled over into xheaders. For
|
||||
|
@ -105,20 +90,20 @@ int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) {
|
|||
for (n = MIN(n, LIMIT); r->i < n; ++r->i) {
|
||||
c = p[r->i] & 0xff;
|
||||
switch (r->t) {
|
||||
case START:
|
||||
case kHttpStateStart:
|
||||
if (c == '\r' || c == '\n') break; /* RFC7230 § 3.5 */
|
||||
if (!kHttpToken[c]) return ebadmsg();
|
||||
r->t = r->type == kHttpRequest ? METHOD : VERSION;
|
||||
r->t = r->type == kHttpRequest ? kHttpStateMethod : kHttpStateVersion;
|
||||
r->a = r->i;
|
||||
break;
|
||||
case METHOD:
|
||||
case kHttpStateMethod:
|
||||
for (;;) {
|
||||
if (c == ' ') {
|
||||
r->method = GetHttpMethod(p + r->a, r->i - r->a);
|
||||
r->xmethod.a = r->a;
|
||||
r->xmethod.b = r->i;
|
||||
r->a = r->i + 1;
|
||||
r->t = URI;
|
||||
r->t = kHttpStateUri;
|
||||
break;
|
||||
} else if (!kHttpToken[c]) {
|
||||
return ebadmsg();
|
||||
|
@ -127,7 +112,7 @@ int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) {
|
|||
c = p[r->i] & 0xff;
|
||||
}
|
||||
break;
|
||||
case URI:
|
||||
case kHttpStateUri:
|
||||
for (;;) {
|
||||
if (c == ' ' || c == '\r' || c == '\n') {
|
||||
if (r->i == r->a) return ebadmsg();
|
||||
|
@ -135,10 +120,10 @@ int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) {
|
|||
r->uri.b = r->i;
|
||||
if (c == ' ') {
|
||||
r->a = r->i + 1;
|
||||
r->t = VERSION;
|
||||
r->t = kHttpStateVersion;
|
||||
} else {
|
||||
r->version = 9;
|
||||
r->t = c == '\r' ? CR1 : LF1;
|
||||
r->t = c == '\r' ? kHttpStateCr : kHttpStateLf1;
|
||||
}
|
||||
break;
|
||||
} else if (c < 0x20 || (0x7F <= c && c < 0xA0)) {
|
||||
|
@ -148,31 +133,31 @@ int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) {
|
|||
c = p[r->i] & 0xff;
|
||||
}
|
||||
break;
|
||||
case VERSION:
|
||||
case kHttpStateVersion:
|
||||
if (c == ' ' || c == '\r' || c == '\n') {
|
||||
if (r->i - r->a == 8 &&
|
||||
(READ64BE(p + r->a) & 0xFFFFFFFFFF00FF00) == 0x485454502F002E00 &&
|
||||
isdigit(p[r->a + 5]) && isdigit(p[r->a + 7])) {
|
||||
r->version = (p[r->a + 5] - '0') * 10 + (p[r->a + 7] - '0');
|
||||
if (r->type == kHttpRequest) {
|
||||
r->t = c == '\r' ? CR1 : LF1;
|
||||
r->t = c == '\r' ? kHttpStateCr : kHttpStateLf1;
|
||||
} else {
|
||||
r->t = STATUS;
|
||||
r->t = kHttpStateStatus;
|
||||
}
|
||||
} else {
|
||||
return ebadmsg();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATUS:
|
||||
case kHttpStateStatus:
|
||||
for (;;) {
|
||||
if (c == ' ' || c == '\r' || c == '\n') {
|
||||
if (r->status < 100) return ebadmsg();
|
||||
if (c == ' ') {
|
||||
r->a = r->i + 1;
|
||||
r->t = MESSAGE;
|
||||
r->t = kHttpStateMessage;
|
||||
} else {
|
||||
r->t = c == '\r' ? CR1 : LF1;
|
||||
r->t = c == '\r' ? kHttpStateCr : kHttpStateLf1;
|
||||
}
|
||||
break;
|
||||
} else if ('0' <= c && c <= '9') {
|
||||
|
@ -186,12 +171,12 @@ int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) {
|
|||
c = p[r->i] & 0xff;
|
||||
}
|
||||
break;
|
||||
case MESSAGE:
|
||||
case kHttpStateMessage:
|
||||
for (;;) {
|
||||
if (c == '\r' || c == '\n') {
|
||||
r->message.a = r->a;
|
||||
r->message.b = r->i;
|
||||
r->t = c == '\r' ? CR1 : LF1;
|
||||
r->t = c == '\r' ? kHttpStateCr : kHttpStateLf1;
|
||||
break;
|
||||
} else if (c < 0x20 || (0x7F <= c && c < 0xA0)) {
|
||||
return ebadmsg();
|
||||
|
@ -200,27 +185,31 @@ int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) {
|
|||
c = p[r->i] & 0xff;
|
||||
}
|
||||
break;
|
||||
case CR1:
|
||||
case kHttpStateCr:
|
||||
if (c != '\n') return ebadmsg();
|
||||
r->t = LF1;
|
||||
r->t = kHttpStateLf1;
|
||||
break;
|
||||
case LF1:
|
||||
case kHttpStateLf1:
|
||||
if (c == '\r') {
|
||||
r->t = LF2;
|
||||
r->t = kHttpStateLf2;
|
||||
break;
|
||||
} else if (c == '\n') {
|
||||
return ++r->i;
|
||||
} else if (!kHttpToken[c]) {
|
||||
return ebadmsg(); /* RFC7230 § 3.2.4 */
|
||||
/*
|
||||
* 1. Forbid empty header name (RFC2616 §2.2)
|
||||
* 2. Forbid line folding (RFC7230 §3.2.4)
|
||||
*/
|
||||
return ebadmsg();
|
||||
}
|
||||
r->k.a = r->i;
|
||||
r->t = HKEY;
|
||||
r->t = kHttpStateName;
|
||||
break;
|
||||
case HKEY:
|
||||
case kHttpStateName:
|
||||
for (;;) {
|
||||
if (c == ':') {
|
||||
r->k.b = r->i;
|
||||
r->t = HSEP;
|
||||
r->t = kHttpStateColon;
|
||||
break;
|
||||
} else if (!kHttpToken[c]) {
|
||||
return ebadmsg();
|
||||
|
@ -229,12 +218,12 @@ int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) {
|
|||
c = p[r->i] & 0xff;
|
||||
}
|
||||
break;
|
||||
case HSEP:
|
||||
case kHttpStateColon:
|
||||
if (c == ' ' || c == '\t') break;
|
||||
r->a = r->i;
|
||||
r->t = HVAL;
|
||||
r->t = kHttpStateValue;
|
||||
/* fallthrough */
|
||||
case HVAL:
|
||||
case kHttpStateValue:
|
||||
for (;;) {
|
||||
if (c == '\r' || c == '\n') {
|
||||
i = r->i;
|
||||
|
@ -252,7 +241,7 @@ int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) {
|
|||
r->xheaders.p = x;
|
||||
++r->xheaders.n;
|
||||
}
|
||||
r->t = c == '\r' ? CR1 : LF1;
|
||||
r->t = c == '\r' ? kHttpStateCr : kHttpStateLf1;
|
||||
break;
|
||||
} else if ((c < 0x20 && c != '\t') || (0x7F <= c && c < 0xA0)) {
|
||||
return ebadmsg();
|
||||
|
@ -261,7 +250,7 @@ int ParseHttpMessage(struct HttpMessage *r, const char *p, size_t n) {
|
|||
c = p[r->i] & 0xff;
|
||||
}
|
||||
break;
|
||||
case LF2:
|
||||
case kHttpStateLf2:
|
||||
if (c == '\n') {
|
||||
return ++r->i;
|
||||
}
|
||||
|
|
115
net/http/unchunk.c
Normal file
115
net/http/unchunk.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "net/http/escape.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
/**
|
||||
* Removes chunk transfer encoding from message body in place.
|
||||
*
|
||||
* @param p is modified in place
|
||||
* @param l receives content length if not null
|
||||
* @return bytes processed, 0 if need more data, or -1 on failure
|
||||
*/
|
||||
ssize_t Unchunk(struct HttpUnchunker *u, char *p, size_t n, size_t *l) {
|
||||
int c, h;
|
||||
size_t s;
|
||||
while (u->i < n) {
|
||||
c = p[u->i++] & 255;
|
||||
switch (u->t) {
|
||||
case kHttpStateChunkStart:
|
||||
if ((u->m = kHexToInt[c]) == -1) return ebadmsg();
|
||||
u->t = kHttpStateChunkSize;
|
||||
break;
|
||||
case kHttpStateChunkSize:
|
||||
if ((h = kHexToInt[c]) != -1) {
|
||||
u->m *= 16;
|
||||
u->m += h;
|
||||
if (u->i + u->m >= n) return ebadmsg();
|
||||
break;
|
||||
}
|
||||
u->t = kHttpStateChunkExt;
|
||||
/* fallthrough */
|
||||
case kHttpStateChunkExt:
|
||||
if (c == '\r') {
|
||||
u->t = kHttpStateChunkLf1;
|
||||
break;
|
||||
} else if (c != '\n') {
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case kHttpStateChunkLf1:
|
||||
if (c != '\n') return ebadmsg();
|
||||
u->t = u->m ? kHttpStateChunk : kHttpStateTrailerStart;
|
||||
break;
|
||||
case kHttpStateChunk:
|
||||
p[u->j++] = c, --u->m;
|
||||
s = MIN(u->m, n - u->i);
|
||||
memmove(p + u->j, p + u->i, s);
|
||||
u->i += s;
|
||||
u->j += s;
|
||||
u->m -= s;
|
||||
if (!u->m) u->t = kHttpStateChunkCr2;
|
||||
break;
|
||||
case kHttpStateChunkCr2:
|
||||
if (c == '\r') {
|
||||
u->t = kHttpStateChunkLf2;
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case kHttpStateChunkLf2:
|
||||
if (c != '\n') return ebadmsg();
|
||||
u->t = kHttpStateChunkStart;
|
||||
break;
|
||||
case kHttpStateTrailerStart:
|
||||
if (c == '\r') {
|
||||
u->t = kHttpStateTrailerLf2;
|
||||
break;
|
||||
} else if (c == '\n') {
|
||||
goto Finished;
|
||||
}
|
||||
u->t = kHttpStateTrailer;
|
||||
/* fallthrough */
|
||||
case kHttpStateTrailer:
|
||||
if (c == '\r') {
|
||||
u->t = kHttpStateTrailerLf1;
|
||||
break;
|
||||
} else if (c != '\n') {
|
||||
break;
|
||||
}
|
||||
/* fallthrough */
|
||||
case kHttpStateTrailerLf1:
|
||||
if (c != '\n') return ebadmsg();
|
||||
u->t = kHttpStateTrailerStart;
|
||||
break;
|
||||
case kHttpStateTrailerLf2:
|
||||
if (c != '\n') return ebadmsg();
|
||||
Finished:
|
||||
if (l) *l = u->j;
|
||||
if (u->j < n) p[u->j] = 0;
|
||||
return u->i;
|
||||
break;
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue