chore: encapsulte http_parser_settings

main
Sean McBride 5 years ago
parent d08e3b7f54
commit 307f7c0d59

@ -1,184 +1,7 @@
#ifndef SRFT_HTTP_PARSER_SETTINGS_H #ifndef SRFT_HTTP_PARSER_SETTINGS_H
#define SRFT_HTTP_PARSER_SETTINGS_H #define SRFT_HTTP_PARSER_SETTINGS_H
#include <http_request.h> void http_parser_settings_initialize(void);
#include <http_response.h> http_parser_settings *http_parser_settings_get();
#include <sandbox.h>
#include <uv.h>
/***********************************************************************
* 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);
}
#endif /* SRFT_HTTP_PARSER_SETTINGS_H */ #endif /* SRFT_HTTP_PARSER_SETTINGS_H */

@ -0,0 +1,188 @@
#include <http_request.h>
#include <http_response.h>
#include <http_parser_settings.h>
#include <sandbox.h>
#include <uv.h>
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;
}

@ -31,8 +31,7 @@
* Shared Process State * * Shared Process State *
**************************/ **************************/
int runtime_epoll_file_descriptor; int runtime_epoll_file_descriptor;
http_parser_settings runtime_http_parser_settings;
/****************************************** /******************************************
* Shared Process / Listener Thread Logic * * Shared Process / Listener Thread Logic *
@ -56,7 +55,7 @@ runtime_initialize(void)
software_interrupt_mask_signal(SIGALRM); software_interrupt_mask_signal(SIGALRM);
// Initialize http_parser_settings global // 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 * @param sandbox the sandbox to check and update if blocked
**/ **/
void void
worker_thread_wakeup_sandbox(sandbox_t *sandbox) worker_thread_wakeup_sandbox(sandbox_t *sandbox)
{ {
software_interrupt_disable(); 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; if (sandbox->state != BLOCKED) goto done;
assert(sandbox->state == BLOCKED);
assert(ps_list_singleton_d(sandbox));
sandbox->state = RUNNABLE; sandbox->state = RUNNABLE;
sandbox_run_queue_append(sandbox); sandbox_run_queue_append(sandbox);
done: done:
@ -207,10 +204,13 @@ worker_thread_block_current_sandbox(void)
{ {
assert(worker_thread_is_in_callback == false); assert(worker_thread_is_in_callback == false);
software_interrupt_disable(); software_interrupt_disable();
struct sandbox *current_sandbox = current_sandbox_get(); struct sandbox *current_sandbox = current_sandbox_get();
ps_list_rem_d(current_sandbox); sandbox_run_queue_remove(current_sandbox);
current_sandbox->state = BLOCKED; current_sandbox->state = BLOCKED;
struct sandbox *next_sandbox = worker_thread_get_next_sandbox(false); struct sandbox *next_sandbox = worker_thread_get_next_sandbox(false);
debuglog("[%p: %next_sandbox, %p: %next_sandbox]\n", current_sandbox, current_sandbox->module->name, debuglog("[%p: %next_sandbox, %p: %next_sandbox]\n", current_sandbox, current_sandbox->module->name,
next_sandbox, next_sandbox ? next_sandbox->module->name : ""); next_sandbox, next_sandbox ? next_sandbox->module->name : "");
software_interrupt_enable(); software_interrupt_enable();

@ -7,8 +7,7 @@
#include <uv.h> #include <uv.h>
#include <libuv_callbacks.h> #include <libuv_callbacks.h>
#include <current_sandbox.h> #include <current_sandbox.h>
#include <http_parser_settings.h>
extern http_parser_settings runtime_http_parser_settings;
/** /**
* Takes the arguments from the sandbox struct and writes them into the WebAssembly linear memory * 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 * @param length The size of the request_response_data that we want to parse
* @returns 0 * @returns 0
* *
* Globals: runtime_http_parser_settings
**/ **/
int int
sandbox_parse_http_request(struct sandbox *sandbox, size_t length) sandbox_parse_http_request(struct sandbox *sandbox, size_t length)
{ {
// Why is our start address sandbox->request_response_data + sandbox->request_response_data_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 // 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); sandbox->request_response_data + sandbox->request_response_data_length, length);
return 0; return 0;
} }

Loading…
Cancel
Save