mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-06-30 08:18:30 +00:00
Add fixes performance and static web server
This commit is contained in:
parent
b6793d42d5
commit
c45e46f871
108 changed files with 2927 additions and 819 deletions
67
net/http/formathttpdatetime.c
Normal file
67
net/http/formathttpdatetime.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ 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 │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU 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 │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
/**
|
||||
* Formats HTTP timestamp, e.g.
|
||||
*
|
||||
* Sun, 04 Oct 2020 19:50:10 GMT
|
||||
*
|
||||
* @param tm must be zulu see gmtime_r() and nowl()
|
||||
* @see ParseHttpDateTime()
|
||||
*/
|
||||
char *FormatHttpDateTime(char p[hasatleast 30], struct tm *tm) {
|
||||
unsigned i;
|
||||
p = mempcpy(p, kWeekdayNameShort[tm->tm_wday], 3);
|
||||
*p++ = ',';
|
||||
*p++ = ' ';
|
||||
i = tm->tm_mday;
|
||||
*p++ = '0' + i / 10;
|
||||
*p++ = '0' + i % 10;
|
||||
*p++ = ' ';
|
||||
p = mempcpy(p, kMonthNameShort[tm->tm_mon], 3);
|
||||
*p++ = ' ';
|
||||
i = tm->tm_year + 1900;
|
||||
*p++ = '0' + i / 1000;
|
||||
*p++ = '0' + i / 100 % 10;
|
||||
*p++ = '0' + i / 10 % 10;
|
||||
*p++ = '0' + i % 10;
|
||||
*p++ = ' ';
|
||||
i = tm->tm_hour;
|
||||
*p++ = '0' + i / 10;
|
||||
*p++ = '0' + i % 10;
|
||||
*p++ = ':';
|
||||
i = tm->tm_min;
|
||||
*p++ = '0' + i / 10;
|
||||
*p++ = '0' + i % 10;
|
||||
*p++ = ':';
|
||||
i = tm->tm_sec;
|
||||
*p++ = '0' + i / 10;
|
||||
*p++ = '0' + i % 10;
|
||||
*p++ = ' ';
|
||||
*p++ = 'G';
|
||||
*p++ = 'M';
|
||||
*p++ = 'T';
|
||||
*p = '\0';
|
||||
return p;
|
||||
}
|
|
@ -58,5 +58,5 @@ Retry-After, kHttpRetryAfter
|
|||
Server, kHttpServer
|
||||
Vary, kHttpVary
|
||||
Warning, kHttpWarning
|
||||
WWW-Authenticate, kHttpWwwAuthenticate
|
||||
Www-Authenticate, kHttpWwwAuthenticate
|
||||
Last-Modified, kHttpLastModified
|
||||
|
|
|
@ -216,7 +216,7 @@ LookupHttpHeader (register const char *str, register size_t len)
|
|||
#line 43 "gethttpheader.gperf"
|
||||
{"Keep-Alive", kHttpKeepAlive},
|
||||
#line 61 "gethttpheader.gperf"
|
||||
{"WWW-Authenticate", kHttpWwwAuthenticate},
|
||||
{"Www-Authenticate", kHttpWwwAuthenticate},
|
||||
#line 35 "gethttpheader.gperf"
|
||||
{"Expires", kHttpExpires},
|
||||
#line 46 "gethttpheader.gperf"
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
%readonly-tables
|
||||
%struct-type
|
||||
%define lookup-function-name LookupHttpMethod
|
||||
struct HttpMethodSlot { char *name; char code; };
|
||||
struct HttpMethodSlot { char name[8]; char code; };
|
||||
%%
|
||||
DELETE, kHttpDelete
|
||||
GET, kHttpGet
|
||||
|
@ -20,17 +20,11 @@ CONNECT, kHttpConnect
|
|||
OPTIONS, kHttpOptions
|
||||
TRACE, kHttpTrace
|
||||
COPY, kHttpCopy
|
||||
CHECKOUT, kHttpCheckout
|
||||
LOCK, kHttpLock
|
||||
MERGE, kHttpMerge
|
||||
MKACTIVITY, kHttpMkactivity
|
||||
MKCOL, kHttpMkcol
|
||||
MOVE, kHttpMove
|
||||
NOTIFY, kHttpNotify
|
||||
PATCH, kHttpPatch
|
||||
PROPFIND, kHttpPropfind
|
||||
PROPPATCH, kHttpProppatch
|
||||
REPORT, kHttpReport
|
||||
SUBSCRIBE, kHttpSubscribe
|
||||
UNLOCK, kHttpUnlock
|
||||
UNSUBSCRIBE, kHttpUnsubscribe
|
||||
|
|
|
@ -35,14 +35,14 @@
|
|||
#include "net/http/http.h"
|
||||
#define GPERF_DOWNCASE
|
||||
#line 12 "gethttpmethod.gperf"
|
||||
struct HttpMethodSlot { char *name; char code; };
|
||||
struct HttpMethodSlot { char name[8]; char code; };
|
||||
|
||||
#define TOTAL_KEYWORDS 23
|
||||
#define TOTAL_KEYWORDS 17
|
||||
#define MIN_WORD_LENGTH 3
|
||||
#define MAX_WORD_LENGTH 11
|
||||
#define MIN_HASH_VALUE 4
|
||||
#define MAX_HASH_VALUE 34
|
||||
/* maximum key range = 31, duplicates = 0 */
|
||||
#define MAX_WORD_LENGTH 7
|
||||
#define MIN_HASH_VALUE 3
|
||||
#define MAX_HASH_VALUE 25
|
||||
/* maximum key range = 23, duplicates = 0 */
|
||||
|
||||
#ifndef GPERF_DOWNCASE
|
||||
#define GPERF_DOWNCASE 1
|
||||
|
@ -101,32 +101,32 @@ hash (register const char *str, register size_t len)
|
|||
{
|
||||
static const unsigned char asso_values[] =
|
||||
{
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 0, 35, 5, 10, 10,
|
||||
35, 5, 10, 35, 35, 0, 30, 15, 0, 0,
|
||||
0, 35, 5, 15, 0, 5, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 0, 35, 5,
|
||||
10, 10, 35, 5, 10, 35, 35, 0, 30, 15,
|
||||
0, 0, 0, 35, 5, 15, 0, 5, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35, 35, 35, 35, 35,
|
||||
35, 35, 35, 35, 35, 35
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 0, 26, 5, 15, 0,
|
||||
26, 5, 0, 26, 26, 10, 15, 10, 0, 5,
|
||||
0, 26, 10, 26, 5, 0, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 0, 26, 5,
|
||||
15, 0, 26, 5, 0, 26, 26, 10, 15, 10,
|
||||
0, 5, 0, 26, 10, 26, 5, 0, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
|
||||
26, 26, 26, 26, 26, 26
|
||||
};
|
||||
return len + asso_values[(unsigned char)str[1]] + asso_values[(unsigned char)str[0]];
|
||||
}
|
||||
|
@ -136,58 +136,46 @@ LookupHttpMethod (register const char *str, register size_t len)
|
|||
{
|
||||
static const struct HttpMethodSlot wordlist[] =
|
||||
{
|
||||
{""}, {""}, {""}, {""},
|
||||
#line 17 "gethttpmethod.gperf"
|
||||
{"POST", kHttpPost},
|
||||
#line 30 "gethttpmethod.gperf"
|
||||
{"PATCH", kHttpPatch},
|
||||
#line 29 "gethttpmethod.gperf"
|
||||
{"NOTIFY", kHttpNotify},
|
||||
#line 20 "gethttpmethod.gperf"
|
||||
{"OPTIONS", kHttpOptions},
|
||||
{""}, {""}, {""},
|
||||
#line 18 "gethttpmethod.gperf"
|
||||
{"PUT", kHttpPut},
|
||||
#line 22 "gethttpmethod.gperf"
|
||||
{"COPY", kHttpCopy},
|
||||
#line 21 "gethttpmethod.gperf"
|
||||
{"TRACE", kHttpTrace},
|
||||
#line 35 "gethttpmethod.gperf"
|
||||
#line 16 "gethttpmethod.gperf"
|
||||
{"HEAD", kHttpHead},
|
||||
#line 28 "gethttpmethod.gperf"
|
||||
{"PATCH", kHttpPatch},
|
||||
#line 30 "gethttpmethod.gperf"
|
||||
{"UNLOCK", kHttpUnlock},
|
||||
#line 19 "gethttpmethod.gperf"
|
||||
{"CONNECT", kHttpConnect},
|
||||
#line 31 "gethttpmethod.gperf"
|
||||
{"PROPFIND", kHttpPropfind},
|
||||
#line 32 "gethttpmethod.gperf"
|
||||
{"PROPPATCH", kHttpProppatch},
|
||||
{""},
|
||||
#line 36 "gethttpmethod.gperf"
|
||||
{"UNSUBSCRIBE", kHttpUnsubscribe},
|
||||
{""},
|
||||
#line 15 "gethttpmethod.gperf"
|
||||
{"GET", kHttpGet},
|
||||
#line 28 "gethttpmethod.gperf"
|
||||
{"MOVE", kHttpMove},
|
||||
#line 27 "gethttpmethod.gperf"
|
||||
{"MKCOL", kHttpMkcol},
|
||||
#line 33 "gethttpmethod.gperf"
|
||||
{"REPORT", kHttpReport},
|
||||
#line 17 "gethttpmethod.gperf"
|
||||
{"POST", kHttpPost},
|
||||
{""},
|
||||
#line 27 "gethttpmethod.gperf"
|
||||
{"NOTIFY", kHttpNotify},
|
||||
#line 20 "gethttpmethod.gperf"
|
||||
{"OPTIONS", kHttpOptions},
|
||||
{""},
|
||||
#line 22 "gethttpmethod.gperf"
|
||||
{"COPY", kHttpCopy},
|
||||
#line 24 "gethttpmethod.gperf"
|
||||
{"MERGE", kHttpMerge},
|
||||
#line 29 "gethttpmethod.gperf"
|
||||
{"REPORT", kHttpReport},
|
||||
#line 19 "gethttpmethod.gperf"
|
||||
{"CONNECT", kHttpConnect},
|
||||
{""},
|
||||
#line 23 "gethttpmethod.gperf"
|
||||
{"CHECKOUT", kHttpCheckout},
|
||||
#line 16 "gethttpmethod.gperf"
|
||||
{"HEAD", kHttpHead},
|
||||
#line 26 "gethttpmethod.gperf"
|
||||
{"MKACTIVITY", kHttpMkactivity},
|
||||
{"MOVE", kHttpMove},
|
||||
#line 21 "gethttpmethod.gperf"
|
||||
{"TRACE", kHttpTrace},
|
||||
#line 14 "gethttpmethod.gperf"
|
||||
{"DELETE", kHttpDelete},
|
||||
{""}, {""},
|
||||
#line 34 "gethttpmethod.gperf"
|
||||
{"SUBSCRIBE", kHttpSubscribe},
|
||||
#line 23 "gethttpmethod.gperf"
|
||||
{"LOCK", kHttpLock},
|
||||
#line 25 "gethttpmethod.gperf"
|
||||
{"MERGE", kHttpMerge},
|
||||
{""}, {""}, {""},
|
||||
#line 24 "gethttpmethod.gperf"
|
||||
{"LOCK", kHttpLock}
|
||||
{"MKCOL", kHttpMkcol}
|
||||
};
|
||||
|
||||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
||||
|
|
|
@ -1,30 +1,25 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_HTTP_HTTP_H_
|
||||
#define COSMOPOLITAN_LIBC_HTTP_HTTP_H_
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
|
||||
#define kHttpGet 0
|
||||
#define kHttpHead 1
|
||||
#define kHttpPost 2
|
||||
#define kHttpPut 3
|
||||
#define kHttpDelete 4
|
||||
#define kHttpConnect 5
|
||||
#define kHttpOptions 6
|
||||
#define kHttpTrace 7
|
||||
#define kHttpCopy 8
|
||||
#define kHttpCheckout 9
|
||||
#define kHttpLock 10
|
||||
#define kHttpMerge 11
|
||||
#define kHttpMkactivity 12
|
||||
#define kHttpMkcol 13
|
||||
#define kHttpMove 14
|
||||
#define kHttpNotify 15
|
||||
#define kHttpPatch 16
|
||||
#define kHttpPropfind 17
|
||||
#define kHttpProppatch 18
|
||||
#define kHttpReport 19
|
||||
#define kHttpSubscribe 20
|
||||
#define kHttpUnlock 21
|
||||
#define kHttpUnsubscribe 22
|
||||
#define kHttpGet 0
|
||||
#define kHttpHead 1
|
||||
#define kHttpPost 2
|
||||
#define kHttpPut 3
|
||||
#define kHttpDelete 4
|
||||
#define kHttpConnect 5
|
||||
#define kHttpOptions 6
|
||||
#define kHttpTrace 7
|
||||
#define kHttpCopy 8
|
||||
#define kHttpLock 9
|
||||
#define kHttpMerge 10
|
||||
#define kHttpMkcol 11
|
||||
#define kHttpMove 12
|
||||
#define kHttpNotify 13
|
||||
#define kHttpPatch 14
|
||||
#define kHttpReport 15
|
||||
#define kHttpUnlock 16
|
||||
|
||||
#define kHttpAccept 0
|
||||
#define kHttpAcceptCharset 1
|
||||
|
@ -86,17 +81,24 @@ struct HttpRequestSlice {
|
|||
|
||||
struct HttpRequest {
|
||||
int method;
|
||||
int length;
|
||||
struct HttpRequestSlice uri;
|
||||
struct HttpRequestSlice version;
|
||||
struct HttpRequestSlice scratch;
|
||||
struct HttpRequestSlice headers[kHttpHeadersMax];
|
||||
};
|
||||
|
||||
extern const char kHttpMethod[17][8];
|
||||
|
||||
int GetHttpHeader(const char *, size_t);
|
||||
int GetHttpMethod(const char *, size_t);
|
||||
int ParseHttpRequest(struct HttpRequest *, const char *, size_t);
|
||||
int NegotiateHttpRequest(int, const char *, uint32_t *, char *, uint32_t *,
|
||||
uint32_t *, bool, long double);
|
||||
char *FormatHttpDateTime(char[hasatleast 30], struct tm *);
|
||||
bool ParseHttpRange(const char *, size_t, long, long *, long *);
|
||||
unsigned ParseHttpVersion(const char *, size_t);
|
||||
int64_t ParseHttpDateTime(const char *, size_t);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -12,65 +12,70 @@ NET_HTTP_A_SRCS_S = $(filter %.S,$(NET_HTTP_A_FILES))
|
|||
NET_HTTP_A_SRCS_C = $(filter %.c,$(NET_HTTP_A_FILES))
|
||||
NET_HTTP_A_SRCS_R = $(filter %.rl,$(NET_HTTP_A_FILES))
|
||||
|
||||
NET_HTTP_A_SRCS = \
|
||||
$(NET_HTTP_A_SRCS_S) \
|
||||
$(NET_HTTP_A_SRCS_C) \
|
||||
NET_HTTP_A_SRCS = \
|
||||
$(NET_HTTP_A_SRCS_S) \
|
||||
$(NET_HTTP_A_SRCS_C) \
|
||||
$(NET_HTTP_A_SRCS_R)
|
||||
|
||||
NET_HTTP_A_OBJS = \
|
||||
$(NET_HTTP_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(NET_HTTP_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(NET_HTTP_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
NET_HTTP_A_OBJS = \
|
||||
$(NET_HTTP_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(NET_HTTP_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(NET_HTTP_A_SRCS_C:%.c=o/$(MODE)/%.o) \
|
||||
$(NET_HTTP_A_SRCS_R:%.rl=o/$(MODE)/%.o)
|
||||
|
||||
NET_HTTP_A_CHECKS = \
|
||||
$(NET_HTTP_A).pkg \
|
||||
NET_HTTP_A_CHECKS = \
|
||||
$(NET_HTTP_A).pkg \
|
||||
$(NET_HTTP_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
NET_HTTP_A_DIRECTDEPS = \
|
||||
LIBC_ALG \
|
||||
LIBC_CALLS \
|
||||
LIBC_CONV \
|
||||
LIBC_FMT \
|
||||
LIBC_LOG \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_TIME \
|
||||
NET_HTTP_A_DIRECTDEPS = \
|
||||
LIBC_ALG \
|
||||
LIBC_CALLS \
|
||||
LIBC_CONV \
|
||||
LIBC_FMT \
|
||||
LIBC_LOG \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_TIME \
|
||||
LIBC_X
|
||||
|
||||
NET_HTTP_A_DEPS := \
|
||||
NET_HTTP_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(NET_HTTP_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(NET_HTTP_A): net/http/ \
|
||||
$(NET_HTTP_A).pkg \
|
||||
$(NET_HTTP_A): net/http/ \
|
||||
$(NET_HTTP_A).pkg \
|
||||
$(NET_HTTP_A_OBJS)
|
||||
|
||||
$(NET_HTTP_A).pkg: \
|
||||
$(NET_HTTP_A_OBJS) \
|
||||
$(NET_HTTP_A).pkg: \
|
||||
$(NET_HTTP_A_OBJS) \
|
||||
$(foreach x,$(NET_HTTP_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/net/http/formathttpdatetime.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-O3
|
||||
|
||||
ifeq (,$(MODE))
|
||||
$(NET_HTTP_A_OBJS): \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-fsanitize=address
|
||||
endif
|
||||
|
||||
NET_HTTP_LIBS = $(foreach x,$(NET_HTTP_ARTIFACTS),$($(x)))
|
||||
NET_HTTP_SRCS = $(foreach x,$(NET_HTTP_ARTIFACTS),$($(x)_SRCS))
|
||||
NET_HTTP_HDRS = $(foreach x,$(NET_HTTP_ARTIFACTS),$($(x)_HDRS))
|
||||
NET_HTTP_CHECKS = $(foreach x,$(NET_HTTP_ARTIFACTS),$($(x)_CHECKS))
|
||||
NET_HTTP_OBJS = $(foreach x,$(NET_HTTP_ARTIFACTS),$($(x)_OBJS))
|
||||
|
||||
$(NET_HTTP_OBJS): $(BUILD_FILES) net/http/http.mk
|
||||
|
||||
.PRECIOUS: \
|
||||
$(NET_HTTP_A_SRCS_R:%.rl=build/bootstrap/%.c) \
|
||||
o/$(MODE)/net/http/uricspn.s \
|
||||
o/$(MODE)/net/http/uriparse.s \
|
||||
o/$(MODE)/net/http/uricspn.i \
|
||||
o/$(MODE)/net/http/uriparse.i \
|
||||
o/$(MODE)/net/http/uriparse.c \
|
||||
.PRECIOUS: \
|
||||
$(NET_HTTP_A_SRCS_R:%.rl=o/$(MODE)/%.c) \
|
||||
o/$(MODE)/net/http/uricspn.s \
|
||||
o/$(MODE)/net/http/uricspn.i \
|
||||
o/$(MODE)/net/http/uricspn.c
|
||||
|
||||
.PHONY: o/$(MODE)/net/http
|
||||
o/$(MODE)/net/http: \
|
||||
$(NET_HTTP_CHECKS) \
|
||||
o/$(MODE)/net/http: \
|
||||
$(NET_HTTP_CHECKS) \
|
||||
$(NET_HTTP_A_SRCS_R:%.rl=%.svgz)
|
||||
|
|
40
net/http/khttpmethod.c
Normal file
40
net/http/khttpmethod.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ 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 │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU 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 │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "net/http/http.h"
|
||||
|
||||
const char kHttpMethod[17][8] = {
|
||||
"GET", //
|
||||
"HEAD", //
|
||||
"POST", //
|
||||
"PUT", //
|
||||
"DELETE", //
|
||||
"CONNECT", //
|
||||
"OPTIONS", //
|
||||
"TRACE", //
|
||||
"COPY", //
|
||||
"LOCK", //
|
||||
"MERGE", //
|
||||
"MKCOL", //
|
||||
"MOVE", //
|
||||
"NOTIFY", //
|
||||
"PATCH", //
|
||||
"REPORT", //
|
||||
"UNLOCK", //
|
||||
};
|
57
net/http/parsehttpdatetime.c
Normal file
57
net/http/parsehttpdatetime.c
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ 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 │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU 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 │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
static unsigned ParseMonth(const char *p) {
|
||||
int i;
|
||||
for (i = 0; i < 12; ++i) {
|
||||
if ((READ32LE(p) & 0x00ffffff) == READ32LE(kMonthNameShort[i])) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses HTTP timestamp, e.g.
|
||||
*
|
||||
* Sun, 04 Oct 2020 19:50:10 GMT
|
||||
*
|
||||
* @return seconds from unix epoch
|
||||
* @see FormatHttpDateTime()
|
||||
*/
|
||||
int64_t ParseHttpDateTime(const char *p, size_t n) {
|
||||
unsigned weekday, year, month, day, hour, minute, second, yday, leap;
|
||||
if (n != 29) return 0;
|
||||
day = (p[5] - '0') * 10 + (p[6] - '0') - 1;
|
||||
month = ParseMonth(p + 8);
|
||||
year = (p[12] - '0') * 1000 + (p[13] - '0') * 100 + (p[14] - '0') * 10 +
|
||||
(p[15] - '0') - 1900;
|
||||
hour = (p[17] - '0') * 10 + (p[18] - '0');
|
||||
minute = (p[20] - '0') * 10 + (p[21] - '0');
|
||||
second = (p[23] - '0') * 10 + (p[24] - '0');
|
||||
leap = year % 4 == 0 && (year % 100 || year % 400 == 0);
|
||||
yday = day + kMonthYearDay[leap][month - 1];
|
||||
return second + minute * 60 + hour * 3600 + yday * 86400 +
|
||||
(year - 70) * 31536000ull + ((year - 69) / 4) * 86400ull -
|
||||
((year - 1) / 100) * 86400ull + ((year + 299) / 400) * 86400ull;
|
||||
}
|
72
net/http/parsehttprange.c
Normal file
72
net/http/parsehttprange.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ 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 │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU 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 │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
/**
|
||||
* Parses HTTP Range request header.
|
||||
*/
|
||||
bool ParseHttpRange(const char *p, size_t n, long resourcelength,
|
||||
long *out_start, long *out_length) {
|
||||
long start, length, ending;
|
||||
*out_start = 0;
|
||||
*out_length = 0;
|
||||
if (memchr(p, ',', n)) return false;
|
||||
if (n < 7 || memcmp(p, "bytes=", 6) != 0) return false;
|
||||
p += 6, n -= 6;
|
||||
if (n && *p == '-') {
|
||||
++p, --n;
|
||||
length = 0;
|
||||
while (n && '0' <= *p && *p <= '9') {
|
||||
if (__builtin_mul_overflow(length, 10, &length)) return false;
|
||||
if (__builtin_add_overflow(length, *p - '0', &length)) return false;
|
||||
++p, --n;
|
||||
}
|
||||
if (__builtin_sub_overflow(resourcelength, length, &start)) return false;
|
||||
} else {
|
||||
start = 0;
|
||||
while (n && '0' <= *p && *p <= '9') {
|
||||
if (__builtin_mul_overflow(start, 10, &start)) return false;
|
||||
if (__builtin_add_overflow(start, *p - '0', &start)) return false;
|
||||
++p, --n;
|
||||
}
|
||||
if (n && *p == '-') {
|
||||
++p, --n;
|
||||
length = 0;
|
||||
while (n && '0' <= *p && *p <= '9') {
|
||||
if (__builtin_mul_overflow(length, 10, &length)) return false;
|
||||
if (__builtin_add_overflow(length, *p - '0', &length)) return false;
|
||||
++p, --n;
|
||||
}
|
||||
if (__builtin_add_overflow(length, 1, &length)) return false;
|
||||
if (__builtin_sub_overflow(length, start, &length)) return false;
|
||||
} else if (__builtin_sub_overflow(resourcelength, start, &length)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (n) return false;
|
||||
if (start < 0) return false;
|
||||
if (length < 0) return false;
|
||||
*out_start = start;
|
||||
*out_length = length;
|
||||
if (__builtin_add_overflow(start, length, &ending)) return false;
|
||||
if (ending > resourcelength) return false;
|
||||
return true;
|
||||
}
|
|
@ -112,7 +112,10 @@ int ParseHttpRequest(struct HttpRequest *req, const char *p, size_t n) {
|
|||
}
|
||||
break;
|
||||
case LF2:
|
||||
if (c == '\n') return 0;
|
||||
if (c == '\n') {
|
||||
req->length = i + 1;
|
||||
return 0;
|
||||
}
|
||||
return ebadmsg();
|
||||
default:
|
||||
unreachable;
|
||||
|
|
33
net/http/parsehttpversion.c
Normal file
33
net/http/parsehttpversion.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*-*- 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 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ 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 │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU 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 │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
unsigned ParseHttpVersion(const char *p, size_t n) {
|
||||
unsigned x;
|
||||
if (n >= 8 && READ32LE(p) == ('H' | 'T' << 8 | 'T' << 16 | 'P' << 24)) {
|
||||
if (READ32LE(p + 4) == ('/' | '1' << 8 | '.' << 16 | '1' << 24)) {
|
||||
return 101;
|
||||
} else if (READ32LE(p + 4) == ('/' | '1' << 8 | '.' << 16 | '0' << 24)) {
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue