refactor: http-session

master
Sean McBride 3 years ago
parent cbb004cae6
commit ee24d1f5b0

@ -17,7 +17,7 @@ CFLAGS+=-D_GNU_SOURCE
CFLAGS+=-O3 -flto CFLAGS+=-O3 -flto
# Debugging Flags # Debugging Flags
# CFLAGS+=-O0 -g # CFLAGS+=-O0 -g3
# CFI Sanitizer # CFI Sanitizer
# CFLAGS+=-fvisibility=default -fsanitize=cfi # CFLAGS+=-fvisibility=default -fsanitize=cfi

@ -25,7 +25,7 @@ current_sandbox_send_response()
{ {
struct sandbox *sandbox = current_sandbox_get(); struct sandbox *sandbox = current_sandbox_get();
assert(sandbox != NULL); assert(sandbox != NULL);
struct vec_u8 *response = &sandbox->response; struct vec_u8 *response = &sandbox->http->response;
assert(response != NULL); assert(response != NULL);
int rc; int rc;
@ -40,11 +40,11 @@ current_sandbox_send_response()
sandbox->total_time = end_time - sandbox->timestamp_of.request_arrival; sandbox->total_time = end_time - sandbox->timestamp_of.request_arrival;
/* Send HTTP Response Header and Body */ /* Send HTTP Response Header and Body */
rc = http_header_200_write(sandbox->client_socket_descriptor, content_type, response_body_size); rc = http_header_200_write(sandbox->http->client_socket_descriptor, content_type, response_body_size);
if (rc < 0) goto err; if (rc < 0) goto err;
rc = client_socket_send(sandbox->client_socket_descriptor, (const char *)response->buffer, response_body_size, rc = client_socket_send(sandbox->http->client_socket_descriptor, (const char *)response->buffer,
current_sandbox_sleep); response_body_size, current_sandbox_sleep);
if (rc < 0) goto err; if (rc < 0) goto err;
http_total_increment_2xx(); http_total_increment_2xx();

@ -0,0 +1,21 @@
#pragma once
#include <sys/socket.h>
#include <stdint.h>
#include "http_request.h"
#include "http_parser.h"
#include "vec.h"
#define u8 uint8_t
VEC(u8)
struct http_session {
/* HTTP State */
struct sockaddr client_address; /* client requesting connection! */
int client_socket_descriptor;
http_parser http_parser;
struct http_request http_request;
struct vec_u8 request;
struct vec_u8 response;
};

@ -23,10 +23,11 @@ sandbox_close_http(struct sandbox *sandbox)
{ {
assert(sandbox != NULL); assert(sandbox != NULL);
int rc = epoll_ctl(worker_thread_epoll_file_descriptor, EPOLL_CTL_DEL, sandbox->client_socket_descriptor, NULL); int rc = epoll_ctl(worker_thread_epoll_file_descriptor, EPOLL_CTL_DEL, sandbox->http->client_socket_descriptor,
NULL);
if (unlikely(rc < 0)) panic_err(); if (unlikely(rc < 0)) panic_err();
client_socket_close(sandbox->client_socket_descriptor, &sandbox->client_address); client_socket_close(sandbox->http->client_socket_descriptor, &sandbox->http->client_address);
} }
/** /**
@ -50,8 +51,8 @@ static inline void
sandbox_deinit_http_buffers(struct sandbox *sandbox) sandbox_deinit_http_buffers(struct sandbox *sandbox)
{ {
assert(sandbox); assert(sandbox);
vec_u8_deinit(&sandbox->request); vec_u8_deinit(&sandbox->http->request);
vec_u8_deinit(&sandbox->response); vec_u8_deinit(&sandbox->http->response);
} }
/** /**
@ -78,16 +79,16 @@ sandbox_open_http(struct sandbox *sandbox)
{ {
assert(sandbox != NULL); assert(sandbox != NULL);
http_parser_init(&sandbox->http_parser, HTTP_REQUEST); http_parser_init(&sandbox->http->http_parser, HTTP_REQUEST);
/* Set the sandbox as the data the http-parser has access to */ /* Set the sandbox as the data the http-parser has access to */
sandbox->http_parser.data = sandbox; sandbox->http->http_parser.data = sandbox;
/* Freshly allocated sandbox going runnable for first time, so register client socket with epoll */ /* Freshly allocated sandbox going runnable for first time, so register client socket with epoll */
struct epoll_event accept_evt; struct epoll_event accept_evt;
accept_evt.data.ptr = (void *)sandbox; accept_evt.data.ptr = (void *)sandbox;
accept_evt.events = EPOLLIN | EPOLLOUT | EPOLLET; accept_evt.events = EPOLLIN | EPOLLOUT | EPOLLET;
int rc = epoll_ctl(worker_thread_epoll_file_descriptor, EPOLL_CTL_ADD, sandbox->client_socket_descriptor, int rc = epoll_ctl(worker_thread_epoll_file_descriptor, EPOLL_CTL_ADD, sandbox->http->client_socket_descriptor,
&accept_evt); &accept_evt);
if (unlikely(rc < 0)) panic_err(); if (unlikely(rc < 0)) panic_err();
} }

@ -27,15 +27,15 @@ sandbox_receive_request(struct sandbox *sandbox)
int rc = 0; int rc = 0;
struct vec_u8 *request = &sandbox->request; struct vec_u8 *request = &sandbox->http->request;
assert(request->length == 0); assert(request->length == 0);
assert(request->capacity > 0); assert(request->capacity > 0);
while (!sandbox->http_request.message_end) { while (!sandbox->http->http_request.message_end) {
/* Read from the Socket */ /* Read from the Socket */
/* Structured to closely follow usage example at https://github.com/nodejs/http-parser */ /* Structured to closely follow usage example at https://github.com/nodejs/http-parser */
http_parser *parser = &sandbox->http_parser; http_parser *parser = &sandbox->http->http_parser;
const http_parser_settings *settings = http_parser_settings_get(); const http_parser_settings *settings = http_parser_settings_get();
size_t request_length = request->length; size_t request_length = request->length;
@ -46,7 +46,7 @@ sandbox_receive_request(struct sandbox *sandbox)
goto err_nobufs; goto err_nobufs;
} }
ssize_t bytes_received = recv(sandbox->client_socket_descriptor, &request->buffer[request_length], ssize_t bytes_received = recv(sandbox->http->client_socket_descriptor, &request->buffer[request_length],
request_capacity - request_length, 0); request_capacity - request_length, 0);
if (bytes_received < 0) { if (bytes_received < 0) {
@ -54,23 +54,25 @@ sandbox_receive_request(struct sandbox *sandbox)
current_sandbox_sleep(); current_sandbox_sleep();
continue; continue;
} else { } else {
debuglog("Error reading socket %d - %s\n", sandbox->client_socket_descriptor, debuglog("Error reading socket %d - %s\n", sandbox->http->client_socket_descriptor,
strerror(errno)); strerror(errno));
goto err; goto err;
} }
} }
/* If we received an EOF before we were able to parse a complete HTTP header, request is malformed */ /* If we received an EOF before we were able to parse a complete HTTP header, request is malformed */
if (bytes_received == 0 && !sandbox->http_request.message_end) { if (bytes_received == 0 && !sandbox->http->http_request.message_end) {
char client_address_text[INET6_ADDRSTRLEN] = {}; char client_address_text[INET6_ADDRSTRLEN] = {};
if (unlikely(inet_ntop(AF_INET, &sandbox->client_address, client_address_text, INET6_ADDRSTRLEN) if (unlikely(
== NULL)) { inet_ntop(AF_INET, &sandbox->http->client_address, client_address_text, INET6_ADDRSTRLEN)
== NULL)) {
debuglog("Failed to log client_address: %s", strerror(errno)); debuglog("Failed to log client_address: %s", strerror(errno));
} }
debuglog("Sandbox %lu: recv returned 0 before a complete request was received\n", sandbox->id); debuglog("Sandbox %lu: recv returned 0 before a complete request was received\n", sandbox->id);
debuglog("Socket: %d. Address: %s\n", sandbox->client_socket_descriptor, client_address_text); debuglog("Socket: %d. Address: %s\n", sandbox->http->client_socket_descriptor,
http_request_print(&sandbox->http_request); client_address_text);
http_request_print(&sandbox->http->http_request);
goto err; goto err;
} }
@ -86,10 +88,10 @@ sandbox_receive_request(struct sandbox *sandbox)
if (bytes_parsed != (size_t)bytes_received) { if (bytes_parsed != (size_t)bytes_received) {
debuglog("Error: %s, Description: %s\n", debuglog("Error: %s, Description: %s\n",
http_errno_name((enum http_errno)sandbox->http_parser.http_errno), http_errno_name((enum http_errno)sandbox->http->http_parser.http_errno),
http_errno_description((enum http_errno)sandbox->http_parser.http_errno)); http_errno_description((enum http_errno)sandbox->http->http_parser.http_errno));
debuglog("Length Parsed %zu, Length Read %zu\n", bytes_parsed, (size_t)bytes_received); debuglog("Length Parsed %zu, Length Read %zu\n", bytes_parsed, (size_t)bytes_received);
debuglog("Error parsing socket %d\n", sandbox->client_socket_descriptor); debuglog("Error parsing socket %d\n", sandbox->http->client_socket_descriptor);
goto err; goto err;
} }
@ -97,10 +99,10 @@ sandbox_receive_request(struct sandbox *sandbox)
} }
#ifdef LOG_HTTP_PARSER #ifdef LOG_HTTP_PARSER
for (int i = 0; i < sandbox->http_request.query_params_count; i++) { for (int i = 0; i < sandbox->http->http_request.query_params_count; i++) {
debuglog("Argument %d, Len: %d, %.*s\n", i, sandbox->http_request.query_params[i].value_length, debuglog("Argument %d, Len: %d, %.*s\n", i, sandbox->http->http_request.query_params[i].value_length,
sandbox->http_request.query_params[i].value_length, sandbox->http->http_request.query_params[i].value_length,
sandbox->http_request.query_params[i].value); sandbox->http->http_request.query_params[i].value);
} }
#endif #endif

@ -2,27 +2,21 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <sys/socket.h>
#include <ucontext.h> #include <ucontext.h>
#include <unistd.h> #include <unistd.h>
#include "arch/context.h" #include "arch/context.h"
#include "http_parser.h" #include "http_session.h"
#include "http_request.h"
#include "module.h" #include "module.h"
#include "ps_list.h" #include "ps_list.h"
#include "sandbox_state.h" #include "sandbox_state.h"
#include "sandbox_state_history.h" #include "sandbox_state_history.h"
#include "vec.h"
#include "wasm_memory.h" #include "wasm_memory.h"
#include "wasm_types.h" #include "wasm_types.h"
#include "wasm_stack.h" #include "wasm_stack.h"
#include "wasm_globals.h" #include "wasm_globals.h"
#include "wasi.h" #include "wasi.h"
#define u8 uint8_t
VEC(u8)
/********************* /*********************
* Structs and Types * * Structs and Types *
********************/ ********************/
@ -47,12 +41,7 @@ struct sandbox {
struct ps_list list; /* used by ps_list's default name-based MACROS for the scheduling runqueue */ struct ps_list list; /* used by ps_list's default name-based MACROS for the scheduling runqueue */
/* HTTP State */ /* HTTP State */
struct sockaddr client_address; /* client requesting connection! */ struct http_session *http;
int client_socket_descriptor;
http_parser http_parser;
struct http_request http_request;
struct vec_u8 request;
struct vec_u8 response;
/* WebAssembly Module State */ /* WebAssembly Module State */
struct module *module; /* the module this is an instance of */ struct module *module; /* the module this is an instance of */

@ -61,7 +61,7 @@ scheduler_execute_epoll_loop(void)
case SANDBOX_ERROR: case SANDBOX_ERROR:
panic("Expected to have closed socket"); panic("Expected to have closed socket");
default: default:
client_socket_send_oneshot(sandbox->client_socket_descriptor, client_socket_send_oneshot(sandbox->http->client_socket_descriptor,
http_header_build(503), http_header_len(503)); http_header_build(503), http_header_len(503));
sandbox_close_http(sandbox); sandbox_close_http(sandbox);
sandbox_set_as_error(sandbox, sandbox->state); sandbox_set_as_error(sandbox, sandbox->state);

@ -82,40 +82,42 @@ current_sandbox_wasm_trap_handler(int trapno)
struct sandbox *sandbox = current_sandbox_get(); struct sandbox *sandbox = current_sandbox_get();
sandbox_syscall(sandbox); sandbox_syscall(sandbox);
int client_socket_descriptor = sandbox->http->client_socket_descriptor;
switch (trapno) { switch (trapno) {
case WASM_TRAP_INVALID_INDEX: case WASM_TRAP_INVALID_INDEX:
error_message = "WebAssembly Trap: Invalid Index\n"; error_message = "WebAssembly Trap: Invalid Index\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500), client_socket_send(client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep); current_sandbox_sleep);
break; break;
case WASM_TRAP_MISMATCHED_TYPE: case WASM_TRAP_MISMATCHED_TYPE:
error_message = "WebAssembly Trap: Mismatched Type\n"; error_message = "WebAssembly Trap: Mismatched Type\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500), client_socket_send(client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep); current_sandbox_sleep);
break; break;
case WASM_TRAP_PROTECTED_CALL_STACK_OVERFLOW: case WASM_TRAP_PROTECTED_CALL_STACK_OVERFLOW:
error_message = "WebAssembly Trap: Protected Call Stack Overflow\n"; error_message = "WebAssembly Trap: Protected Call Stack Overflow\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500), client_socket_send(client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep); current_sandbox_sleep);
break; break;
case WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY: case WASM_TRAP_OUT_OF_BOUNDS_LINEAR_MEMORY:
error_message = "WebAssembly Trap: Out of Bounds Linear Memory Access\n"; error_message = "WebAssembly Trap: Out of Bounds Linear Memory Access\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500), client_socket_send(client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep); current_sandbox_sleep);
break; break;
case WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION: case WASM_TRAP_ILLEGAL_ARITHMETIC_OPERATION:
error_message = "WebAssembly Trap: Illegal Arithmetic Operation\n"; error_message = "WebAssembly Trap: Illegal Arithmetic Operation\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500), client_socket_send(client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep); current_sandbox_sleep);
break; break;
case WASM_TRAP_UNREACHABLE: case WASM_TRAP_UNREACHABLE:
error_message = "WebAssembly Trap: Unreachable Instruction\n"; error_message = "WebAssembly Trap: Unreachable Instruction\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500), client_socket_send(client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep); current_sandbox_sleep);
break; break;
default: default:
error_message = "WebAssembly Trap: Unknown Trapno\n"; error_message = "WebAssembly Trap: Unknown Trapno\n";
client_socket_send(sandbox->client_socket_descriptor, http_header_build(500), http_header_len(500), client_socket_send(client_socket_descriptor, http_header_build(500), http_header_len(500),
current_sandbox_sleep); current_sandbox_sleep);
break; break;
} }
@ -144,12 +146,12 @@ current_sandbox_init()
if (rc == -2) { if (rc == -2) {
error_message = "Request size exceeded Buffer\n"; error_message = "Request size exceeded Buffer\n";
/* Request size exceeded Buffer, send 413 Payload Too Large */ /* Request size exceeded Buffer, send 413 Payload Too Large */
client_socket_send(sandbox->client_socket_descriptor, http_header_build(413), http_header_len(413), client_socket_send(sandbox->http->client_socket_descriptor, http_header_build(413),
current_sandbox_sleep); http_header_len(413), current_sandbox_sleep);
goto err; goto err;
} else if (rc == -1) { } else if (rc == -1) {
client_socket_send(sandbox->client_socket_descriptor, http_header_build(400), http_header_len(400), client_socket_send(sandbox->http->client_socket_descriptor, http_header_build(400),
current_sandbox_sleep); http_header_len(400), current_sandbox_sleep);
goto err; goto err;
} }
@ -164,10 +166,10 @@ current_sandbox_init()
/* Initialize Arguments. First arg is the module name. Subsequent args are query parameters */ /* Initialize Arguments. First arg is the module name. Subsequent args are query parameters */
char *args[HTTP_MAX_QUERY_PARAM_COUNT + 1]; char *args[HTTP_MAX_QUERY_PARAM_COUNT + 1];
args[0] = sandbox->module->name; args[0] = sandbox->module->name;
for (int i = 0; i < sandbox->http_request.query_params_count; i++) for (int i = 0; i < sandbox->http->http_request.query_params_count; i++)
args[i + 1] = (char *)sandbox->http_request.query_params[i].value; args[i + 1] = (char *)sandbox->http->http_request.query_params[i].value;
options.argc = sandbox->http_request.query_params_count + 1; options.argc = sandbox->http->http_request.query_params_count + 1;
options.argv = (const char **)&args; options.argv = (const char **)&args;
sandbox->wasi_context = wasi_context_init(&options); sandbox->wasi_context = wasi_context_init(&options);
sledge_abi__current_wasm_module_instance.wasi_context = sandbox->wasi_context; sledge_abi__current_wasm_module_instance.wasi_context = sandbox->wasi_context;

@ -21,10 +21,11 @@ http_parser_settings runtime_http_parser_settings;
int int
http_parser_settings_on_url(http_parser *parser, const char *at, size_t length) http_parser_settings_on_url(http_parser *parser, const char *at, size_t length)
{ {
struct sandbox *sandbox = (struct sandbox *)parser->data; struct sandbox *sandbox = (struct sandbox *)parser->data;
struct http_request *http_request = &sandbox->http->http_request;
assert(!sandbox->http_request.message_end); assert(!http_request->message_end);
assert(!sandbox->http_request.header_end); assert(!http_request->header_end);
#ifdef LOG_HTTP_PARSER #ifdef LOG_HTTP_PARSER
debuglog("sandbox: %lu, length: %zu, Content \"%.*s\"\n", sandbox->id, length, (int)length, at); debuglog("sandbox: %lu, length: %zu, Content \"%.*s\"\n", sandbox->id, length, (int)length, at);
@ -36,31 +37,27 @@ http_parser_settings_on_url(http_parser *parser, const char *at, size_t length)
char *prev = query_params + 1; char *prev = query_params + 1;
char *cur = NULL; char *cur = NULL;
while ((cur = strchr(prev, '&')) != NULL while ((cur = strchr(prev, '&')) != NULL
&& sandbox->http_request.query_params_count < HTTP_MAX_QUERY_PARAM_COUNT) { && http_request->query_params_count < HTTP_MAX_QUERY_PARAM_COUNT) {
cur++; cur++;
size_t len = cur - prev - 1; size_t len = cur - prev - 1;
sandbox->http_request.query_params[sandbox->http_request.query_params_count].value_length = http_request->query_params[http_request->query_params_count].value_length =
len < HTTP_MAX_QUERY_PARAM_LENGTH - 1 ? len : HTTP_MAX_QUERY_PARAM_LENGTH - 1; len < HTTP_MAX_QUERY_PARAM_LENGTH - 1 ? len : HTTP_MAX_QUERY_PARAM_LENGTH - 1;
strncpy(sandbox->http_request.query_params[sandbox->http_request.query_params_count].value, strncpy(http_request->query_params[http_request->query_params_count].value, prev,
prev, http_request->query_params[http_request->query_params_count].value_length);
sandbox->http_request.query_params[sandbox->http_request.query_params_count]
.value_length);
sandbox->http_request.query_params_count++; http_request->query_params_count++;
prev = cur; prev = cur;
} }
if (prev != NULL && sandbox->http_request.query_params_count < HTTP_MAX_QUERY_PARAM_COUNT) { if (prev != NULL && http_request->query_params_count < HTTP_MAX_QUERY_PARAM_COUNT) {
size_t len = &at[length] - prev; size_t len = &at[length] - prev;
sandbox->http_request.query_params[sandbox->http_request.query_params_count].value_length = http_request->query_params[http_request->query_params_count].value_length =
len < HTTP_MAX_QUERY_PARAM_LENGTH - 1 ? len : HTTP_MAX_QUERY_PARAM_LENGTH - 1; len < HTTP_MAX_QUERY_PARAM_LENGTH - 1 ? len : HTTP_MAX_QUERY_PARAM_LENGTH - 1;
strncpy(sandbox->http_request.query_params[sandbox->http_request.query_params_count].value, strncpy(http_request->query_params[http_request->query_params_count].value, prev,
prev, http_request->query_params[http_request->query_params_count].value_length);
sandbox->http_request.query_params[sandbox->http_request.query_params_count]
.value_length);
sandbox->http_request.query_params_count++; http_request->query_params_count++;
} }
} }
@ -76,10 +73,10 @@ int
http_parser_settings_on_message_begin(http_parser *parser) http_parser_settings_on_message_begin(http_parser *parser)
{ {
struct sandbox *sandbox = (struct sandbox *)parser->data; struct sandbox *sandbox = (struct sandbox *)parser->data;
struct http_request *http_request = &sandbox->http_request; struct http_request *http_request = &sandbox->http->http_request;
assert(!sandbox->http_request.message_end); assert(!http_request->message_end);
assert(!sandbox->http_request.header_end); assert(!http_request->header_end);
#ifdef LOG_HTTP_PARSER #ifdef LOG_HTTP_PARSER
debuglog("sandbox: %lu\n", sandbox->id); debuglog("sandbox: %lu\n", sandbox->id);
@ -104,14 +101,14 @@ int
http_parser_settings_on_header_field(http_parser *parser, const char *at, size_t length) http_parser_settings_on_header_field(http_parser *parser, const char *at, size_t length)
{ {
struct sandbox *sandbox = (struct sandbox *)parser->data; struct sandbox *sandbox = (struct sandbox *)parser->data;
struct http_request *http_request = &sandbox->http_request; struct http_request *http_request = &sandbox->http->http_request;
#ifdef LOG_HTTP_PARSER #ifdef LOG_HTTP_PARSER
debuglog("sandbox: %lu, length: %zu, Content \"%.*s\"\n", sandbox->id, length, (int)length, at); debuglog("sandbox: %lu, length: %zu, Content \"%.*s\"\n", sandbox->id, length, (int)length, at);
#endif #endif
assert(!sandbox->http_request.message_end); assert(!http_request->message_end);
assert(!sandbox->http_request.header_end); assert(!http_request->header_end);
if (http_request->last_was_value == false) { if (http_request->last_was_value == false) {
/* Previous key continues */ /* Previous key continues */
@ -147,15 +144,15 @@ int
http_parser_settings_on_header_value(http_parser *parser, const char *at, size_t length) http_parser_settings_on_header_value(http_parser *parser, const char *at, size_t length)
{ {
struct sandbox *sandbox = (struct sandbox *)parser->data; struct sandbox *sandbox = (struct sandbox *)parser->data;
struct http_request *http_request = &sandbox->http_request; struct http_request *http_request = &sandbox->http->http_request;
#ifdef LOG_HTTP_PARSER #ifdef LOG_HTTP_PARSER
debuglog("sandbox: %lu, length: %zu, Content \"%.*s\"\n", sandbox->id, length, (int)length, at); debuglog("sandbox: %lu, length: %zu, Content \"%.*s\"\n", sandbox->id, length, (int)length, at);
#endif #endif
assert(!sandbox->http_request.message_end); assert(!http_request->message_end);
assert(!sandbox->http_request.header_end); assert(!http_request->header_end);
if (!http_request->last_was_value) { if (!http_request->last_was_value) {
if (unlikely(length >= HTTP_MAX_HEADER_VALUE_LENGTH)) return -1; if (unlikely(length >= HTTP_MAX_HEADER_VALUE_LENGTH)) return -1;
@ -179,10 +176,10 @@ int
http_parser_settings_on_header_end(http_parser *parser) http_parser_settings_on_header_end(http_parser *parser)
{ {
struct sandbox *sandbox = (struct sandbox *)parser->data; struct sandbox *sandbox = (struct sandbox *)parser->data;
struct http_request *http_request = &sandbox->http_request; struct http_request *http_request = &sandbox->http->http_request;
assert(!sandbox->http_request.message_end); assert(!http_request->message_end);
assert(!sandbox->http_request.header_end); assert(!http_request->header_end);
#ifdef LOG_HTTP_PARSER #ifdef LOG_HTTP_PARSER
debuglog("sandbox: %lu\n", sandbox->id); debuglog("sandbox: %lu\n", sandbox->id);
@ -208,10 +205,10 @@ int
http_parser_settings_on_body(http_parser *parser, const char *at, size_t length) http_parser_settings_on_body(http_parser *parser, const char *at, size_t length)
{ {
struct sandbox *sandbox = (struct sandbox *)parser->data; struct sandbox *sandbox = (struct sandbox *)parser->data;
struct http_request *http_request = &sandbox->http_request; struct http_request *http_request = &sandbox->http->http_request;
assert(sandbox->http_request.header_end); assert(http_request->header_end);
assert(!sandbox->http_request.message_end); assert(!http_request->message_end);
/* Assumption: We should never exceed the buffer we're reusing */ /* Assumption: We should never exceed the buffer we're reusing */
@ -250,10 +247,10 @@ int
http_parser_settings_on_msg_end(http_parser *parser) http_parser_settings_on_msg_end(http_parser *parser)
{ {
struct sandbox *sandbox = (struct sandbox *)parser->data; struct sandbox *sandbox = (struct sandbox *)parser->data;
struct http_request *http_request = &sandbox->http_request; struct http_request *http_request = &sandbox->http->http_request;
assert(sandbox->http_request.header_end); assert(http_request->header_end);
assert(!sandbox->http_request.message_end); assert(!http_request->message_end);
#ifdef LOG_HTTP_PARSER #ifdef LOG_HTTP_PARSER
debuglog("sandbox: %lu\n", sandbox->id); debuglog("sandbox: %lu\n", sandbox->id);

@ -659,7 +659,7 @@ wasi_snapshot_preview1_backing_fd_read(wasi_context_t *context, __wasi_fd_t fd,
/* Non-blocking copy on stdin */ /* Non-blocking copy on stdin */
if (fd == STDIN_FILENO) { if (fd == STDIN_FILENO) {
struct sandbox *current_sandbox = current_sandbox_get(); struct sandbox *current_sandbox = current_sandbox_get();
struct http_request *current_request = &current_sandbox->http_request; struct http_request *current_request = &current_sandbox->http->http_request;
int old_read = current_request->body_read_length; int old_read = current_request->body_read_length;
int bytes_to_read = current_request->body_length - old_read; int bytes_to_read = current_request->body_length - old_read;
@ -786,26 +786,26 @@ wasi_snapshot_preview1_backing_fd_write(wasi_context_t *context, __wasi_fd_t fd,
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) { if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
struct sandbox *s = current_sandbox_get(); struct sandbox *s = current_sandbox_get();
size_t buffer_remaining = 0; size_t buffer_remaining = 0;
size_t old_response_len = s->response.length; size_t old_response_len = s->http->response.length;
__wasi_size_t sum = 0; __wasi_size_t sum = 0;
for (size_t i = 0; i < iovs_len; i++) { for (size_t i = 0; i < iovs_len; i++) {
buffer_remaining = s->module->max_response_size - s->response.length; buffer_remaining = s->module->max_response_size - s->http->response.length;
if (buffer_remaining == 0) { if (buffer_remaining == 0) {
*nwritten_retptr = s->response.length - old_response_len; *nwritten_retptr = s->http->response.length - old_response_len;
return __WASI_ERRNO_FBIG; return __WASI_ERRNO_FBIG;
} }
ssize_t to_write = buffer_remaining > iovs[i].buf_len ? iovs[i].buf_len : buffer_remaining; ssize_t to_write = buffer_remaining > iovs[i].buf_len ? iovs[i].buf_len : buffer_remaining;
memcpy(&s->response.buffer[s->response.length], iovs[i].buf, to_write); memcpy(&s->http->response.buffer[s->http->response.length], iovs[i].buf, to_write);
#ifdef LOG_SANDBOX_STDERR #ifdef LOG_SANDBOX_STDERR
if (fd == STDERR_FILENO) { if (fd == STDERR_FILENO) {
debuglog("STDERR from Sandbox:"); debuglog("STDERR from Sandbox:");
write(2, iovs[i].buf, iovs[i].buf_len); write(2, iovs[i].buf, iovs[i].buf_len);
} }
#endif #endif
s->response.length += to_write; s->http->response.length += to_write;
} }
*nwritten_retptr = s->response.length - old_response_len; *nwritten_retptr = s->http->response.length - old_response_len;
return __WASI_ERRNO_SUCCESS; return __WASI_ERRNO_SUCCESS;
} }

@ -183,19 +183,19 @@ listener_thread_main(void *dummy)
(const struct sockaddr *)&client_address, (const struct sockaddr *)&client_address,
request_arrival_timestamp, work_admitted); request_arrival_timestamp, work_admitted);
if (unlikely(sandbox == NULL)) { if (unlikely(sandbox == NULL)) {
client_socket_send_oneshot(sandbox->client_socket_descriptor, client_socket_send_oneshot(sandbox->http->client_socket_descriptor,
http_header_build(503), http_header_len(503)); http_header_build(503), http_header_len(503));
client_socket_close(sandbox->client_socket_descriptor, client_socket_close(sandbox->http->client_socket_descriptor,
&sandbox->client_address); &sandbox->http->client_address);
} }
/* If the global request scheduler is full, return a 429 to the client */ /* If the global request scheduler is full, return a 429 to the client */
sandbox = global_request_scheduler_add(sandbox); sandbox = global_request_scheduler_add(sandbox);
if (unlikely(sandbox == NULL)) { if (unlikely(sandbox == NULL)) {
client_socket_send_oneshot(sandbox->client_socket_descriptor, client_socket_send_oneshot(sandbox->http->client_socket_descriptor,
http_header_build(429), http_header_len(429)); http_header_build(429), http_header_len(429));
client_socket_close(sandbox->client_socket_descriptor, client_socket_close(sandbox->http->client_socket_descriptor,
&sandbox->client_address); &sandbox->http->client_address);
} }
} /* while true */ } /* while true */

@ -89,12 +89,12 @@ static inline int
sandbox_allocate_http_buffers(struct sandbox *sandbox) sandbox_allocate_http_buffers(struct sandbox *sandbox)
{ {
int rc; int rc;
rc = vec_u8_init(&sandbox->request, sandbox->module->max_request_size); rc = vec_u8_init(&sandbox->http->request, sandbox->module->max_request_size);
if (rc < 0) return -1; if (rc < 0) return -1;
rc = vec_u8_init(&sandbox->response, sandbox->module->max_response_size); rc = vec_u8_init(&sandbox->http->response, sandbox->module->max_response_size);
if (rc < 0) { if (rc < 0) {
vec_u8_deinit(&sandbox->request); vec_u8_deinit(&sandbox->http->request);
return -1; return -1;
} }
@ -150,8 +150,9 @@ err_stack_allocation_failed:
err_memory_allocation_failed: err_memory_allocation_failed:
err_globals_allocation_failed: err_globals_allocation_failed:
err_http_allocation_failed: err_http_allocation_failed:
client_socket_send_oneshot(sandbox->client_socket_descriptor, http_header_build(503), http_header_len(503)); client_socket_send_oneshot(sandbox->http->client_socket_descriptor, http_header_build(503),
client_socket_close(sandbox->client_socket_descriptor, &sandbox->client_address); http_header_len(503));
client_socket_close(sandbox->http->client_socket_descriptor, &sandbox->http->client_address);
sandbox_set_as_error(sandbox, SANDBOX_ALLOCATED); sandbox_set_as_error(sandbox, SANDBOX_ALLOCATED);
perror(error_message); perror(error_message);
rc = -1; rc = -1;
@ -170,8 +171,12 @@ sandbox_init(struct sandbox *sandbox, struct module *module, int socket_descript
/* Initialize Parsec control structures */ /* Initialize Parsec control structures */
ps_list_init_d(sandbox); ps_list_init_d(sandbox);
sandbox->client_socket_descriptor = socket_descriptor; /* Allocate HTTP session structure */
memcpy(&sandbox->client_address, socket_address, sizeof(struct sockaddr)); sandbox->http = calloc(sizeof(struct http_session), 1);
assert(sandbox->http);
sandbox->http->client_socket_descriptor = socket_descriptor;
memcpy(&sandbox->http->client_address, socket_address, sizeof(struct sockaddr));
sandbox->timestamp_of.request_arrival = request_arrival_timestamp; sandbox->timestamp_of.request_arrival = request_arrival_timestamp;
sandbox->absolute_deadline = request_arrival_timestamp + module->relative_deadline; sandbox->absolute_deadline = request_arrival_timestamp + module->relative_deadline;
@ -222,6 +227,9 @@ sandbox_deinit(struct sandbox *sandbox)
module_release(sandbox->module); module_release(sandbox->module);
/* TODO: Validate lifetime and cleanup of pointer members in this struct */
free(sandbox->http);
/* Linear Memory and Guard Page should already have been munmaped and set to NULL */ /* Linear Memory and Guard Page should already have been munmaped and set to NULL */
assert(sandbox->memory == NULL); assert(sandbox->memory == NULL);

Loading…
Cancel
Save