Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
url = https://github.com/gwsystems/aWsm
ignore = dirty
branch = master
[submodule "http-parser"]
path = runtime/thirdparty/http-parser
url = https://github.com/gwsystems/http-parser.git
[submodule "ck"]
path = runtime/thirdparty/ck
url = https://github.com/gwsystems/ck.git
Expand Down
2 changes: 1 addition & 1 deletion .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"/usr/include/",
"${workspaceFolder}/runtime/include/",
"${workspaceFolder}/runtime/thirdparty/ck/include/",
"${workspaceFolder}/runtime/thirdparty/http-parser/",
"${workspaceFolder}/runtime/thirdparty/llhttp/include/",
"${workspaceFolder}/runtime/thirdparty/jsmn/",
"${workspaceFolder}/awsm/runtime/libc/wasi/include/",
"${workspaceFolder}/libsledge/include"
Expand Down
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"http_total.h": "c",
"http_request.h": "c",
"http.h": "c",
"http_parser.h": "c",
"llhttp.h": "c",
"http_parser_settings.h": "c",
"client_socket.h": "c",
"context.h": "c",
Expand Down Expand Up @@ -205,7 +205,7 @@
"**/awsm/target/**": true,
"**/runtime/thirdparty/**": true,
"**/runtime/thirdparty/ck/**": true,
"**/runtime/thirdparty/http-parser/**": true,
"**/runtime/thirdparty/llhttp/**": true,
"**/runtime/thirdparty/jsmn/**": true,
"**/runtime/thirdparty/dist/**": true,
"*.o": true,
Expand Down
8 changes: 6 additions & 2 deletions runtime/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ INCLUDES += -Iinclude/ -Ithirdparty/dist/include/ -I../libsledge/include/
CFILES += src/*.c
CFILES += src/arch/${ARCH}/*.c
CFILES += src/libc/*.c
CFILES += thirdparty/dist/lib/http_parser.o
CFILES += thirdparty/dist/lib/llhttp.o
CFILES += thirdparty/dist/lib/llhttp_api.o
CFILES += thirdparty/dist/lib/llhttp_http.o

# Configuring Jasmine
JSMNCFLAGS += -DJSMN_STATIC
Expand Down Expand Up @@ -157,7 +159,9 @@ runtime.clean:
@rm -f bin/${BINARY_NAME}

# Thirdparty Dependency Rules
thirdparty/dist/lib/http_parser.o: thirdparty
thirdparty/dist/lib/llhttp.o: thirdparty
thirdparty/dist/lib/llhttp_api.o: thirdparty
thirdparty/dist/lib/llhttp_http.o: thirdparty
thirdparty/dist/include/*.h: thirdparty

.PHONY: thirdparty
Expand Down
6 changes: 3 additions & 3 deletions runtime/include/http_parser_settings.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#pragma once

#include "http_parser.h"
#include "llhttp.h"

extern http_parser_settings runtime_http_parser_settings;
extern llhttp_settings_t runtime_http_parser_settings;

void http_parser_settings_initialize(void);

static inline http_parser_settings *
static inline llhttp_settings_t *
http_parser_settings_get()
{
return &runtime_http_parser_settings;
Expand Down
40 changes: 23 additions & 17 deletions runtime/include/http_session.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include "auto_buf.h"
#include "debuglog.h"
#include "epoll_tag.h"
#include "http_parser.h"
#include "llhttp.h"
#include "http_parser_settings.h"
#include "http_request.h"
#include "http_route_total.h"
Expand Down Expand Up @@ -44,7 +44,7 @@ struct http_session {
enum http_session_state state;
struct sockaddr client_address; /* client requesting connection! */
int socket;
struct http_parser http_parser;
llhttp_t http_parser;
struct http_request http_request;
struct auto_buf request_buffer;
struct auto_buf response_header;
Expand Down Expand Up @@ -73,8 +73,9 @@ static inline void
http_session_parser_init(struct http_session *session)
{
memset(&session->http_request, 0, sizeof(struct http_request));
http_parser_init(&session->http_parser, HTTP_REQUEST);
/* Set the session as the data the http-parser has access to */
/* llhttp binds the callback settings at init time (unlike http-parser, which took them at execute) */
llhttp_init(&session->http_parser, HTTP_REQUEST, http_parser_settings_get());
/* Set the session as the data the parser has access to */
session->http_parser.data = &session->http_request;
}

Expand Down Expand Up @@ -293,22 +294,27 @@ http_session_parse(struct http_session *session, ssize_t bytes_received)
assert(session != 0);
assert(bytes_received > 0);

const http_parser_settings *settings = http_parser_settings_get();
const char *parse_start = (const char *)&session->request_buffer.data[session->http_request.length_parsed];
size_t parse_length = (size_t)session->request_buffer.size - session->http_request.length_parsed;

#ifdef LOG_HTTP_PARSER
debuglog("http_parser_execute(%p, %p, %p, %zu\n)", &session->http_parser, settings,
&session->request_buffer.buffer[session->request_buffer.length], bytes_received);
debuglog("llhttp_execute(%p, %p, %zu)\n", &session->http_parser, parse_start, parse_length);
#endif
size_t bytes_parsed =
http_parser_execute(&session->http_parser, settings,
(const char *)&session->request_buffer.data[session->http_request.length_parsed],
(size_t)session->request_buffer.size - session->http_request.length_parsed);

if (session->http_parser.http_errno != HPE_OK) {
debuglog("Error: %s, Description: %s\n",
http_errno_name((enum http_errno)session->http_parser.http_errno),
http_errno_description((enum http_errno)session->http_parser.http_errno));
debuglog("Length Parsed %zu, Length Read %zu\n", bytes_parsed, (size_t)bytes_received);

/* Unlike http_parser_execute (which returned a byte count), llhttp_execute returns an error code and
* binds its callback settings at init time. On HPE_OK the whole buffer was consumed. */
enum llhttp_errno err = llhttp_execute(&session->http_parser, parse_start, parse_length);

size_t bytes_parsed;
if (likely(err == HPE_OK)) {
bytes_parsed = parse_length;
} else if (err == HPE_PAUSED || err == HPE_PAUSED_UPGRADE) {
/* Parser stopped early (e.g. on an upgrade); count only the bytes it consumed. */
bytes_parsed = (size_t)(llhttp_get_error_pos(&session->http_parser) - parse_start);
} else {
debuglog("Error: %s, Description: %s\n", llhttp_errno_name(err),
llhttp_get_error_reason(&session->http_parser));
debuglog("Length Read %zu\n", (size_t)bytes_received);
debuglog("Error parsing socket %d\n", session->socket);
return -1;
}
Expand Down
30 changes: 18 additions & 12 deletions runtime/src/http_parser_settings.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "http_request.h"
#include "likely.h"

http_parser_settings runtime_http_parser_settings;
llhttp_settings_t runtime_http_parser_settings;

/***********************************************************************
* http-parser Callbacks in lifecycle order *
Expand All @@ -22,7 +22,7 @@ http_parser_settings runtime_http_parser_settings;
* @returns 0
*/
int
http_parser_settings_on_url(http_parser *parser, const char *at, size_t length)
http_parser_settings_on_url(llhttp_t *parser, const char *at, size_t length)
{
struct http_request *http_request = (struct http_request *)parser->data;

Expand Down Expand Up @@ -84,7 +84,7 @@ http_parser_settings_on_url(http_parser *parser, const char *at, size_t length)
* @param parser
*/
int
http_parser_settings_on_message_begin(http_parser *parser)
http_parser_settings_on_message_begin(llhttp_t *parser)
{
struct http_request *http_request = (struct http_request *)parser->data;

Expand All @@ -111,7 +111,7 @@ http_parser_settings_on_message_begin(http_parser *parser)
* @returns 0
*/
int
http_parser_settings_on_header_field(http_parser *parser, const char *at, size_t length)
http_parser_settings_on_header_field(llhttp_t *parser, const char *at, size_t length)
{
struct http_request *http_request = (struct http_request *)parser->data;

Expand Down Expand Up @@ -153,7 +153,7 @@ http_parser_settings_on_header_field(http_parser *parser, const char *at, size_t
* @returns 0
*/
int
http_parser_settings_on_header_value(http_parser *parser, const char *at, size_t length)
http_parser_settings_on_header_value(llhttp_t *parser, const char *at, size_t length)
{
struct http_request *http_request = (struct http_request *)parser->data;

Expand Down Expand Up @@ -187,7 +187,7 @@ http_parser_settings_on_header_value(http_parser *parser, const char *at, size_t
* @param parser
*/
int
http_parser_settings_on_header_end(http_parser *parser)
http_parser_settings_on_header_end(llhttp_t *parser)
{
struct http_request *http_request = (struct http_request *)parser->data;

Expand All @@ -207,7 +207,9 @@ http_parser_settings_on_header_end(http_parser *parser)
return 0;
} else {
http_request->body_length = 0;
return 2;
/* Returning 1 tells llhttp to assume no body and proceed straight to
* on_message_complete (http-parser used 2 for the same intent). */
return 1;
}
}

Expand All @@ -223,7 +225,7 @@ const char *http_methods[] = {"OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE",
* @returns 0
*/
int
http_parser_settings_on_body(http_parser *parser, const char *at, size_t length)
http_parser_settings_on_body(llhttp_t *parser, const char *at, size_t length)
{
struct http_request *http_request = (struct http_request *)parser->data;

Expand Down Expand Up @@ -260,7 +262,7 @@ http_parser_settings_on_body(http_parser *parser, const char *at, size_t length)
* @returns 0
*/
int
http_parser_settings_on_msg_end(http_parser *parser)
http_parser_settings_on_msg_end(llhttp_t *parser)
{
struct http_request *http_request = (struct http_request *)parser->data;

Expand All @@ -273,7 +275,11 @@ http_parser_settings_on_msg_end(http_parser *parser)

http_request->message_end = true;

return 0;
/* Pause once a full message is parsed so llhttp stops cleanly instead of trying to parse any trailing
* bytes as a pipelined next message (which would re-enter on_message_begin and trip its asserts). This
* mirrors http-parser, which returned immediately after firing on_message_complete for our requests.
* http_session_parse treats HPE_PAUSED as a normal stop. */
return HPE_PAUSED;
}

/***********************************************************************
Expand All @@ -284,7 +290,7 @@ http_parser_settings_on_msg_end(http_parser *parser)
* The settings global with the Callback Functions for HTTP Events
*/
static inline void
http_parser_settings_register_callbacks(http_parser_settings *settings)
http_parser_settings_register_callbacks(llhttp_settings_t *settings)
{
settings->on_url = http_parser_settings_on_url;
settings->on_message_begin = http_parser_settings_on_message_begin;
Expand All @@ -301,6 +307,6 @@ http_parser_settings_register_callbacks(http_parser_settings *settings)
void
http_parser_settings_initialize()
{
http_parser_settings_init(&runtime_http_parser_settings);
llhttp_settings_init(&runtime_http_parser_settings);
http_parser_settings_register_callbacks(&runtime_http_parser_settings);
}
30 changes: 19 additions & 11 deletions runtime/thirdparty/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ DIST_PREFIX=${CURR_DIR}/dist/
all: clean build

.PHONY: build
build: ck jsmn http-parser
build: ck jsmn llhttp

# Concurrency Kit
ck/Makefile: ck/Makefile.in ck/configure
Expand All @@ -17,20 +17,28 @@ ${DIST_PREFIX}/lib/libck.so: ck/Makefile
.PHONY: ck
ck: ${DIST_PREFIX}/lib/libck.so

# HTTP Parser
${DIST_PREFIX}/include/http_parser.h: http-parser/http_parser.h
mkdir -p ${DIST_PREFIX}
# llhttp HTTP Parser (pre-generated C release of nodejs/llhttp, vendored in llhttp/)
# We compile the release's three C sources directly so the build needs no Node/npm/llparse toolchain.
LLHTTP_CFLAGS = -O3 -Illhttp/include

${DIST_PREFIX}/include/llhttp.h: llhttp/include/llhttp.h
mkdir -p ${DIST_PREFIX}/include/
cp http-parser/http_parser.h ${DIST_PREFIX}/include/
cp llhttp/include/llhttp.h ${DIST_PREFIX}/include/

${DIST_PREFIX}/lib/http_parser.o: http-parser/http_parser.c http-parser/http_parser.h
mkdir -p ${DIST_PREFIX}
${DIST_PREFIX}/lib/llhttp.o: llhttp/src/llhttp.c llhttp/include/llhttp.h
mkdir -p ${DIST_PREFIX}/lib/
$(CC) $(CFLAGS) $(LLHTTP_CFLAGS) -c llhttp/src/llhttp.c -o $@

${DIST_PREFIX}/lib/llhttp_api.o: llhttp/src/api.c llhttp/include/llhttp.h
mkdir -p ${DIST_PREFIX}/lib/
$(CC) $(CFLAGS) $(LLHTTP_CFLAGS) -c llhttp/src/api.c -o $@

${DIST_PREFIX}/lib/llhttp_http.o: llhttp/src/http.c llhttp/include/llhttp.h
mkdir -p ${DIST_PREFIX}/lib/
cd http-parser; $(CC) $(CFLAGS) -I. -c http_parser.c
mv http-parser/http_parser.o ${DIST_PREFIX}/lib/
$(CC) $(CFLAGS) $(LLHTTP_CFLAGS) -c llhttp/src/http.c -o $@

.PHONY: http-parser
http-parser: ${DIST_PREFIX}/lib/http_parser.o ${DIST_PREFIX}/include/http_parser.h
.PHONY: llhttp
llhttp: ${DIST_PREFIX}/lib/llhttp.o ${DIST_PREFIX}/lib/llhttp_api.o ${DIST_PREFIX}/lib/llhttp_http.o ${DIST_PREFIX}/include/llhttp.h

# Jasmine JSON Parser
${DIST_PREFIX}/include/jsmn.h: jsmn/jsmn.h
Expand Down
1 change: 0 additions & 1 deletion runtime/thirdparty/http-parser
Submodule http-parser deleted from 2343fd
22 changes: 22 additions & 0 deletions runtime/thirdparty/llhttp/LICENSE-MIT
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
This software is licensed under the MIT License.

Copyright Fedor Indutny, 2018.

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.
Loading
Loading