diff --git a/runtime/include/http_parser_settings.h b/runtime/include/http_parser_settings.h index 6f1feaa..859575f 100644 --- a/runtime/include/http_parser_settings.h +++ b/runtime/include/http_parser_settings.h @@ -1,184 +1,7 @@ #ifndef SRFT_HTTP_PARSER_SETTINGS_H #define SRFT_HTTP_PARSER_SETTINGS_H -#include -#include -#include -#include - -/*********************************************************************** - * http-parser Callbacks in lifecycle order * - **********************************************************************/ - -/** - * http-parser data callback called when a URL is called - * Sanity check to make sure that the path matches the name of the module - * TODO: Why does this not fail this assertion? To execute fibonacci, I just request localhost:10000, not - *localhost:10000/fibonacci - * @param parser - * @param at the start of the URL - * @param length the length of the URL - * @returns 0 - **/ -static inline int -http_parser_settings_on_url(http_parser *parser, const char *at, size_t length) -{ - struct sandbox *sandbox = (struct sandbox *)parser->data; - - assert(strncmp(sandbox->module->name, (at + 1), length - 1) == 0); - return 0; -} - -/** - * http-parser callback called when parsing of a new message begins - * Sets the HTTP Request's message_begin and last_was_value flags to true - * @param parser - **/ -static inline int -http_parser_settings_on_message_begin(http_parser *parser) -{ - struct sandbox * sandbox = (struct sandbox *)parser->data; - struct http_request *http_request = &sandbox->http_request; - - http_request->message_begin = 1; - http_request->last_was_value = 1; // should always start with a header.. - return 0; -} - -/** - * http-parser callback called when a header field is parsed - * Sets the key value of the latest header - * on a new header if last_was_value is true - * updating an existing header if last_was_value is false - * TODO: Is this logic correct? What is the relationship between fields and values? Is overwrite the correct logic if - *on_header executes twice in a row? - * @param parser - * @param at start address of the header field - * @param length length of the header field - * @returns 0 - **/ -static inline int -http_parser_settings_on_header_field(http_parser *parser, const char *at, size_t length) -{ - struct sandbox * sandbox = (struct sandbox *)parser->data; - struct http_request *http_request = &sandbox->http_request; - - if (http_request->last_was_value) http_request->header_count++; - assert(http_request->header_count <= HTTP_MAX_HEADER_COUNT); - assert(length < HTTP_MAX_HEADER_LENGTH); - - http_request->last_was_value = 0; - http_request->headers[http_request->header_count - 1].key = (char *) - at; // it is from the sandbox's request_response_data, should persist. - - return 0; -} - -/** - * http-parser callback called when a header value is parsed - * Writes the value to the latest header and sets last_was_value to true - * @param parser - * @param at start address of the header value - * @param length length of the header value - * @returns 0 - **/ -static inline int -http_parser_settings_on_header_value(http_parser *parser, const char *at, size_t length) -{ - struct sandbox * sandbox = (struct sandbox *)parser->data; - struct http_request *http_request = &sandbox->http_request; - - http_request->last_was_value = 1; - assert(http_request->header_count <= HTTP_MAX_HEADER_COUNT); - assert(length < HTTP_MAX_HEADER_VALUE_LENGTH); - - http_request->headers[http_request->header_count - 1].value = (char *) - at; // it is from the sandbox's request_response_data, should persist. - - return 0; -} - -/** - * http-parser callback called when header parsing is complete - * Just sets the HTTP Request's header_end flag to true - * @param parser - **/ -static inline int -http_parser_settings_on_header_end(http_parser *parser) -{ - struct sandbox * sandbox = (struct sandbox *)parser->data; - struct http_request *http_request = &sandbox->http_request; - - http_request->header_end = 1; - return 0; -} - -/** - * http-parser callback called for HTTP Bodies - * Assigns the parsed data to the http_request body of the sandbox struct - * @param parser - * @param at - * @param length - * @returns 0 - **/ -static inline int -http_parser_settings_on_body(http_parser *parser, const char *at, size_t length) -{ - struct sandbox * sandbox = (struct sandbox *)parser->data; - struct http_request *http_request = &sandbox->http_request; - - assert(http_request->body_length + length <= sandbox->module->max_request_size); - if (!http_request->body) - http_request->body = (char *)at; - else - assert(http_request->body + http_request->body_length == at); - - http_request->body_length += length; - - return 0; -} - -/** - * Sets the HTTP Request's message_end flag to true - * @param parser - **/ -static inline int -http_parser_settings_on_msg_end(http_parser *parser) -{ - struct sandbox * sandbox = (struct sandbox *)parser->data; - struct http_request *http_request = &sandbox->http_request; - - http_request->message_end = 1; - return 0; -} - -/*********************************************************************** - * http-parser Setup and Excute * - **********************************************************************/ - -/** - * The settings global with the Callback Functions for HTTP Events - */ -static inline void -http_parser_settings_register_callbacks(http_parser_settings *settings) -{ - settings->on_url = http_parser_settings_on_url; - settings->on_message_begin = http_parser_settings_on_message_begin; - settings->on_header_field = http_parser_settings_on_header_field; - settings->on_header_value = http_parser_settings_on_header_value; - settings->on_headers_complete = http_parser_settings_on_header_end; - settings->on_body = http_parser_settings_on_body; - settings->on_message_complete = http_parser_settings_on_msg_end; -} - -/** - * This is really the only function that should have to be called to setup this structure - **/ -void -http_parser_settings_initialize(http_parser_settings *settings) -{ - http_parser_settings_init(settings); - http_parser_settings_register_callbacks(settings); -} +void http_parser_settings_initialize(void); +http_parser_settings *http_parser_settings_get(); #endif /* SRFT_HTTP_PARSER_SETTINGS_H */ diff --git a/runtime/src/http_parser_settings.c b/runtime/src/http_parser_settings.c new file mode 100644 index 0000000..7b7bdc6 --- /dev/null +++ b/runtime/src/http_parser_settings.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include + +static http_parser_settings runtime_http_parser_settings; + +/*********************************************************************** + * http-parser Callbacks in lifecycle order * + **********************************************************************/ + +/** + * http-parser data callback called when a URL is called + * Sanity check to make sure that the path matches the name of the module + * TODO: Why does this not fail this assertion? To execute fibonacci, I just request localhost:10000, not + *localhost:10000/fibonacci + * @param parser + * @param at the start of the URL + * @param length the length of the URL + * @returns 0 + **/ +int +http_parser_settings_on_url(http_parser *parser, const char *at, size_t length) +{ + struct sandbox *sandbox = (struct sandbox *)parser->data; + + assert(strncmp(sandbox->module->name, (at + 1), length - 1) == 0); + return 0; +} + +/** + * http-parser callback called when parsing of a new message begins + * Sets the HTTP Request's message_begin and last_was_value flags to true + * @param parser + **/ +int +http_parser_settings_on_message_begin(http_parser *parser) +{ + struct sandbox * sandbox = (struct sandbox *)parser->data; + struct http_request *http_request = &sandbox->http_request; + + http_request->message_begin = 1; + http_request->last_was_value = 1; // should always start with a header.. + return 0; +} + +/** + * http-parser callback called when a header field is parsed + * Sets the key value of the latest header + * on a new header if last_was_value is true + * updating an existing header if last_was_value is false + * TODO: Is this logic correct? What is the relationship between fields and values? Is overwrite the correct logic if + *on_header executes twice in a row? + * @param parser + * @param at start address of the header field + * @param length length of the header field + * @returns 0 + **/ +int +http_parser_settings_on_header_field(http_parser *parser, const char *at, size_t length) +{ + struct sandbox * sandbox = (struct sandbox *)parser->data; + struct http_request *http_request = &sandbox->http_request; + + if (http_request->last_was_value) http_request->header_count++; + assert(http_request->header_count <= HTTP_MAX_HEADER_COUNT); + assert(length < HTTP_MAX_HEADER_LENGTH); + + http_request->last_was_value = 0; + http_request->headers[http_request->header_count - 1].key = (char *) + at; // it is from the sandbox's request_response_data, should persist. + + return 0; +} + +/** + * http-parser callback called when a header value is parsed + * Writes the value to the latest header and sets last_was_value to true + * @param parser + * @param at start address of the header value + * @param length length of the header value + * @returns 0 + **/ +int +http_parser_settings_on_header_value(http_parser *parser, const char *at, size_t length) +{ + struct sandbox * sandbox = (struct sandbox *)parser->data; + struct http_request *http_request = &sandbox->http_request; + + http_request->last_was_value = 1; + assert(http_request->header_count <= HTTP_MAX_HEADER_COUNT); + assert(length < HTTP_MAX_HEADER_VALUE_LENGTH); + + http_request->headers[http_request->header_count - 1].value = (char *) + at; // it is from the sandbox's request_response_data, should persist. + + return 0; +} + +/** + * http-parser callback called when header parsing is complete + * Just sets the HTTP Request's header_end flag to true + * @param parser + **/ +int +http_parser_settings_on_header_end(http_parser *parser) +{ + struct sandbox * sandbox = (struct sandbox *)parser->data; + struct http_request *http_request = &sandbox->http_request; + + http_request->header_end = 1; + return 0; +} + +/** + * http-parser callback called for HTTP Bodies + * Assigns the parsed data to the http_request body of the sandbox struct + * @param parser + * @param at + * @param length + * @returns 0 + **/ +int +http_parser_settings_on_body(http_parser *parser, const char *at, size_t length) +{ + struct sandbox * sandbox = (struct sandbox *)parser->data; + struct http_request *http_request = &sandbox->http_request; + + assert(http_request->body_length + length <= sandbox->module->max_request_size); + if (!http_request->body) + http_request->body = (char *)at; + else + assert(http_request->body + http_request->body_length == at); + + http_request->body_length += length; + + return 0; +} + +/** + * Sets the HTTP Request's message_end flag to true + * @param parser + **/ +int +http_parser_settings_on_msg_end(http_parser *parser) +{ + struct sandbox * sandbox = (struct sandbox *)parser->data; + struct http_request *http_request = &sandbox->http_request; + + http_request->message_end = 1; + return 0; +} + +/*********************************************************************** + * http-parser Setup and Excute * + **********************************************************************/ + +/** + * The settings global with the Callback Functions for HTTP Events + */ +static inline void +http_parser_settings_register_callbacks(http_parser_settings *settings) +{ + settings->on_url = http_parser_settings_on_url; + settings->on_message_begin = http_parser_settings_on_message_begin; + settings->on_header_field = http_parser_settings_on_header_field; + settings->on_header_value = http_parser_settings_on_header_value; + settings->on_headers_complete = http_parser_settings_on_header_end; + settings->on_body = http_parser_settings_on_body; + settings->on_message_complete = http_parser_settings_on_msg_end; +} + +/** + * This is really the only function that should have to be called to setup this structure + **/ +void +http_parser_settings_initialize() +{ + http_parser_settings_init(&runtime_http_parser_settings); + http_parser_settings_register_callbacks(&runtime_http_parser_settings); +} + +http_parser_settings * +http_parser_settings_get() +{ + return &runtime_http_parser_settings; +} diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index 860e7c7..1ff3f3e 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -31,8 +31,7 @@ * Shared Process State * **************************/ -int runtime_epoll_file_descriptor; -http_parser_settings runtime_http_parser_settings; +int runtime_epoll_file_descriptor; /****************************************** * Shared Process / Listener Thread Logic * @@ -56,7 +55,7 @@ runtime_initialize(void) software_interrupt_mask_signal(SIGALRM); // Initialize http_parser_settings global - http_parser_settings_initialize(&runtime_http_parser_settings); + http_parser_settings_initialize(); } /******************************** @@ -180,17 +179,15 @@ worker_thread_switch_to_sandbox(struct sandbox *next_sandbox) } /** - * If this sandbox is blocked, mark it as runnable and add to the head of the thread-local runqueue + * Mark a blocked sandbox as runnable and add it to the runqueue * @param sandbox the sandbox to check and update if blocked **/ void worker_thread_wakeup_sandbox(sandbox_t *sandbox) { software_interrupt_disable(); - debuglog("[%p: %s]\n", sandbox, sandbox->module->name); + // debuglog("[%p: %s]\n", sandbox, sandbox->module->name); if (sandbox->state != BLOCKED) goto done; - assert(sandbox->state == BLOCKED); - assert(ps_list_singleton_d(sandbox)); sandbox->state = RUNNABLE; sandbox_run_queue_append(sandbox); done: @@ -207,10 +204,13 @@ worker_thread_block_current_sandbox(void) { assert(worker_thread_is_in_callback == false); software_interrupt_disable(); + struct sandbox *current_sandbox = current_sandbox_get(); - ps_list_rem_d(current_sandbox); - current_sandbox->state = BLOCKED; + sandbox_run_queue_remove(current_sandbox); + current_sandbox->state = BLOCKED; + struct sandbox *next_sandbox = worker_thread_get_next_sandbox(false); + debuglog("[%p: %next_sandbox, %p: %next_sandbox]\n", current_sandbox, current_sandbox->module->name, next_sandbox, next_sandbox ? next_sandbox->module->name : ""); software_interrupt_enable(); diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index c845848..438bd7a 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -7,8 +7,7 @@ #include #include #include - -extern http_parser_settings runtime_http_parser_settings; +#include /** * Takes the arguments from the sandbox struct and writes them into the WebAssembly linear memory @@ -48,14 +47,13 @@ current_sandbox_setup_arguments(i32 argument_count) * @param length The size of the request_response_data that we want to parse * @returns 0 * - * Globals: runtime_http_parser_settings **/ int sandbox_parse_http_request(struct sandbox *sandbox, size_t length) { // Why is our start address sandbox->request_response_data + sandbox->request_response_data_length? // it's like a cursor to keep track of what we've read so far - http_parser_execute(&sandbox->http_parser, &runtime_http_parser_settings, + http_parser_execute(&sandbox->http_parser, http_parser_settings_get(), sandbox->request_response_data + sandbox->request_response_data_length, length); return 0; }