From faacc5c785eb10fed92c1e429eadf7441db726bd Mon Sep 17 00:00:00 2001 From: Sean McBride Date: Fri, 7 May 2021 16:48:22 -0400 Subject: [PATCH] refactor: http header cleanup --- runtime/include/arch/aarch64/context.h | 27 -------- runtime/include/arch/x86_64/context.h | 30 +-------- runtime/include/client_socket.h | 77 +++++++++++++++++++++- runtime/include/http.h | 9 +++ runtime/include/http_parser_settings.h | 11 +++- runtime/include/http_request.h | 1 - runtime/include/http_response.h | 38 ----------- runtime/include/http_total.h | 43 ++++++++++-- runtime/include/module.h | 8 --- runtime/include/sandbox.h | 9 ++- runtime/src/client_socket.c | 78 ---------------------- runtime/src/http_parser_settings.c | 8 +-- runtime/src/http_request.c | 13 ---- runtime/src/http_response.c | 91 -------------------------- runtime/src/http_total.c | 41 +----------- runtime/src/local_runqueue_minheap.c | 12 ---- runtime/src/runtime.c | 1 - 17 files changed, 139 insertions(+), 358 deletions(-) delete mode 100644 runtime/include/http_response.h delete mode 100644 runtime/src/client_socket.c delete mode 100644 runtime/src/http_response.c diff --git a/runtime/include/arch/aarch64/context.h b/runtime/include/arch/aarch64/context.h index addc382..7bb99dc 100644 --- a/runtime/include/arch/aarch64/context.h +++ b/runtime/include/arch/aarch64/context.h @@ -31,33 +31,6 @@ arch_context_init(struct arch_context *actx, reg_t ip, reg_t sp) actx->regs[UREG_IP] = ip; } -/** - * Restore a sandbox saved using a fastpath switch, restoring only the - * instruction pointer and stack pointer registers rather than - * a full mcontext, so it is less expensive than arch_mcontext_restore. - * @param active_context - the context of the current worker thread - * @param sandbox_context - the context that we want to restore - */ -static void -arch_context_restore(mcontext_t *active_context, struct arch_context *sandbox_context) -{ - assert(active_context != NULL); - assert(sandbox_context != NULL); - - /* Assumption: Base Context is only ever used by arch_context_switch */ - assert(sandbox_context != &worker_thread_base_context); - - assert(sandbox_context->regs[UREG_SP]); - assert(sandbox_context->regs[UREG_IP]); - - /* Transitioning from Fast -> Running */ - assert(sandbox_context->variant == ARCH_CONTEXT_VARIANT_FAST); - sandbox_context->variant = ARCH_CONTEXT_VARIANT_RUNNING; - - active_context->sp = sandbox_context->regs[UREG_SP]; - active_context->pc = sandbox_context->regs[UREG_IP] + ARCH_SIG_JMP_OFF; -} - /** * @param a - the registers and context of the thing running * @param b - the registers and context of what we're switching to diff --git a/runtime/include/arch/x86_64/context.h b/runtime/include/arch/x86_64/context.h index b033079..7cf9685 100644 --- a/runtime/include/arch/x86_64/context.h +++ b/runtime/include/arch/x86_64/context.h @@ -11,7 +11,8 @@ * @param ip value to set instruction pointer to * @param sp value to set stack pointer to */ -static void __attribute__((noinline)) arch_context_init(struct arch_context *actx, reg_t ip, reg_t sp) +static inline void +arch_context_init(struct arch_context *actx, reg_t ip, reg_t sp) { assert(actx != NULL); @@ -46,33 +47,6 @@ static void __attribute__((noinline)) arch_context_init(struct arch_context *act actx->regs[UREG_IP] = ip; } -/** - * Restore a sandbox saved using a fastpath switch, restoring only the - * instruction pointer and stack pointer registers rather than - * a full mcontext, so it is less expensive than arch_mcontext_restore. - * @param active_context - the context of the current worker thread - * @param sandbox_context - the context that we want to restore - */ -static void -arch_context_restore(mcontext_t *active_context, struct arch_context *sandbox_context) -{ - assert(active_context != NULL); - assert(sandbox_context != NULL); - - /* Assumption: Base Context is only ever used by arch_context_switch */ - assert(sandbox_context != &worker_thread_base_context); - - assert(sandbox_context->regs[UREG_SP]); - assert(sandbox_context->regs[UREG_IP]); - - /* Transitioning from Fast -> Running */ - assert(sandbox_context->variant == ARCH_CONTEXT_VARIANT_FAST); - sandbox_context->variant = ARCH_CONTEXT_VARIANT_RUNNING; - - active_context->gregs[REG_RSP] = sandbox_context->regs[UREG_SP]; - active_context->gregs[REG_RIP] = sandbox_context->regs[UREG_IP] + ARCH_SIG_JMP_OFF; -} - /** * Load a new sandbox that preempted an existing sandbox, restoring only the * instruction pointer and stack pointer registers. diff --git a/runtime/include/client_socket.h b/runtime/include/client_socket.h index 974d04e..b862601 100644 --- a/runtime/include/client_socket.h +++ b/runtime/include/client_socket.h @@ -1,7 +1,80 @@ #pragma once +#include +#include +#include +#include #include +#include -void client_socket_close(int client_socket, struct sockaddr *client_address); +#include "debuglog.h" +#include "http.h" +#include "http_total.h" +#include "panic.h" +#include "likely.h" -int client_socket_send(int client_socket, int status_code); + +static inline void +client_socket_close(int client_socket, struct sockaddr *client_address) +{ + /* Should never close 0, 1, or 2 */ + assert(client_socket != STDIN_FILENO); + assert(client_socket != STDOUT_FILENO); + assert(client_socket != STDERR_FILENO); + + if (unlikely(close(client_socket) < 0)) { + char client_address_text[INET6_ADDRSTRLEN] = {}; + if (unlikely(inet_ntop(AF_INET, &client_address, client_address_text, INET6_ADDRSTRLEN) == NULL)) { + debuglog("Failed to log client_address: %s", strerror(errno)); + } + debuglog("Error closing client socket %d associated with %s - %s", client_socket, client_address_text, + strerror(errno)); + } +} + +/** + * Rejects request due to admission control or error + * @param client_socket - the client we are rejecting + * @param status_code - either 503 or 400 + */ +static inline int +client_socket_send(int client_socket, int status_code) +{ + const char *response; + int rc; + switch (status_code) { + case 503: + response = HTTP_RESPONSE_503_SERVICE_UNAVAILABLE; + http_total_increment_5XX(); + break; + case 400: + response = HTTP_RESPONSE_400_BAD_REQUEST; + http_total_increment_4XX(); + break; + default: + panic("%d is not a valid status code\n", status_code); + } + + int sent = 0; + int to_send = strlen(response); + + while (sent < to_send) { + rc = write(client_socket, &response[sent], to_send - sent); + if (rc < 0) { + if (errno == EAGAIN) { debuglog("Unexpectedly blocking on write of %s\n", response); } + + debuglog("Error with %s\n", strerror(errno)); + + goto send_err; + } + sent += rc; + }; + + rc = 0; +done: + return rc; +send_err: + debuglog("Error sending to client: %s", strerror(errno)); + rc = -1; + goto done; +} diff --git a/runtime/include/http.h b/runtime/include/http.h index bb42eae..f938826 100644 --- a/runtime/include/http.h +++ b/runtime/include/http.h @@ -3,3 +3,12 @@ #define HTTP_MAX_HEADER_COUNT 16 #define HTTP_MAX_HEADER_LENGTH 32 #define HTTP_MAX_HEADER_VALUE_LENGTH 64 + +#define HTTP_RESPONSE_200_OK "HTTP/1.1 200 OK\r\n" +#define HTTP_RESPONSE_503_SERVICE_UNAVAILABLE "HTTP/1.1 503 Service Unavailable\r\n\r\n" +#define HTTP_RESPONSE_400_BAD_REQUEST "HTTP/1.1 400 Bad Request\r\n\r\n" +#define HTTP_RESPONSE_CONTENT_LENGTH "Content-Length: " +#define HTTP_RESPONSE_CONTENT_LENGTH_TERMINATOR "\r\n\r\n" /* content body follows this */ +#define HTTP_RESPONSE_CONTENT_TYPE "Content-Type: " +#define HTTP_RESPONSE_CONTENT_TYPE_PLAIN "text/plain" +#define HTTP_RESPONSE_CONTENT_TYPE_TERMINATOR " \r\n" diff --git a/runtime/include/http_parser_settings.h b/runtime/include/http_parser_settings.h index 8038630..e50edea 100644 --- a/runtime/include/http_parser_settings.h +++ b/runtime/include/http_parser_settings.h @@ -2,5 +2,12 @@ #include "http_parser.h" -void http_parser_settings_initialize(void); -http_parser_settings *http_parser_settings_get(); +extern http_parser_settings runtime_http_parser_settings; + +void http_parser_settings_initialize(void); + +static inline http_parser_settings * +http_parser_settings_get() +{ + return &runtime_http_parser_settings; +} diff --git a/runtime/include/http_request.h b/runtime/include/http_request.h index 21e4146..53beeae 100644 --- a/runtime/include/http_request.h +++ b/runtime/include/http_request.h @@ -27,5 +27,4 @@ struct http_request { bool message_end; /* boolean flag set when body processing is complete */ }; -int http_request_get_body(struct http_request *http_request, char **body); void http_request_print(struct http_request *self); diff --git a/runtime/include/http_response.h b/runtime/include/http_response.h deleted file mode 100644 index fec4b6f..0000000 --- a/runtime/include/http_response.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include -#include - -#include "http.h" - -#define HTTP_RESPONSE_200_OK "HTTP/1.1 200 OK\r\n" -#define HTTP_RESPONSE_503_SERVICE_UNAVAILABLE "HTTP/1.1 503 Service Unavailable\r\n\r\n" -#define HTTP_RESPONSE_400_BAD_REQUEST "HTTP/1.1 400 Bad Request\r\n\r\n" -#define HTTP_RESPONSE_CONTENT_LENGTH "Content-Length: " -#define HTTP_RESPONSE_CONTENT_LENGTH_TERMINATOR "\r\n\r\n" /* content body follows this */ -#define HTTP_RESPONSE_CONTENT_TYPE "Content-Type: " -#define HTTP_RESPONSE_CONTENT_TYPE_PLAIN "text/plain" -#define HTTP_RESPONSE_CONTENT_TYPE_TERMINATOR " \r\n" - -struct http_response_header { - char *header; - int length; -}; - -struct http_response { - struct http_response_header headers[HTTP_MAX_HEADER_COUNT]; - int header_count; - char * body; - int body_length; - char * status; - int status_length; - struct iovec bufs[HTTP_MAX_HEADER_COUNT * 2 + 3]; -}; - -/*************************************************** - * General HTTP Response Functions * - **************************************************/ -int http_response_encode_as_vector(struct http_response *http_response); -int http_response_set_body(struct http_response *http_response, char *body, int length); -int http_response_set_header(struct http_response *http_response, char *h, int length); -int http_response_set_status(struct http_response *http_response, char *status, int length); diff --git a/runtime/include/http_total.h b/runtime/include/http_total.h index d7ee1cb..2f74cad 100644 --- a/runtime/include/http_total.h +++ b/runtime/include/http_total.h @@ -17,8 +17,41 @@ extern _Atomic uint32_t http_total_2XX; extern _Atomic uint32_t http_total_4XX; #endif -void http_total_init(); -void http_total_increment_request(); -void http_total_increment_2xx(); -void http_total_increment_4XX(); -void http_total_increment_5XX(); +static inline void +http_total_init() +{ + atomic_init(&http_total_requests, 0); + atomic_init(&http_total_5XX, 0); +#ifdef LOG_TOTAL_REQS_RESPS + atomic_init(&http_total_2XX, 0); + atomic_init(&http_total_4XX, 0); +#endif +} + +static inline void +http_total_increment_request() +{ + atomic_fetch_add(&http_total_requests, 1); +} + +static inline void +http_total_increment_2xx() +{ +#ifdef LOG_TOTAL_REQS_RESPS + atomic_fetch_add(&http_total_2XX, 1); +#endif +} + +static inline void +http_total_increment_4XX() +{ +#ifdef LOG_TOTAL_REQS_RESPS + atomic_fetch_add(&http_total_4XX, 1); +#endif +} + +static inline void +http_total_increment_5XX() +{ + atomic_fetch_add(&http_total_5XX, 1); +} diff --git a/runtime/include/module.h b/runtime/include/module.h index e366be7..1aed4db 100644 --- a/runtime/include/module.h +++ b/runtime/include/module.h @@ -57,14 +57,6 @@ struct module { struct admissions_info admissions_info; int port; - /* - * unfortunately, using UV for accepting connections is not great! - * on_connection, to create a new accepted connection, will have to init a tcp handle, - * which requires a uvloop. cannot use main as rest of the connection is handled in - * sandboxing threads, with per-core(per-thread) tls data-structures. - * so, using direct epoll for accepting connections. - */ - unsigned long max_request_size; char request_headers[HTTP_MAX_HEADER_COUNT][HTTP_MAX_HEADER_LENGTH]; int request_header_count; diff --git a/runtime/include/sandbox.h b/runtime/include/sandbox.h index 73b8c48..f360fbe 100644 --- a/runtime/include/sandbox.h +++ b/runtime/include/sandbox.h @@ -6,8 +6,8 @@ #include "arch/context.h" #include "client_socket.h" #include "deque.h" +#include "http_parser.h" #include "http_request.h" -#include "http_response.h" #include "module.h" #include "ps_list.h" #include "sandbox_request.h" @@ -81,10 +81,9 @@ struct sandbox { struct sockaddr client_address; /* client requesting connection! */ int client_socket_descriptor; - bool is_repeat_header; - http_parser http_parser; - struct http_request http_request; - struct http_response http_response; + bool is_repeat_header; + http_parser http_parser; + struct http_request http_request; char * read_buffer; ssize_t read_length, read_size; diff --git a/runtime/src/client_socket.c b/runtime/src/client_socket.c deleted file mode 100644 index e1fdc06..0000000 --- a/runtime/src/client_socket.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "client_socket.h" -#include "debuglog.h" -#include "http_response.h" -#include "http_total.h" -#include "likely.h" -#include "panic.h" - -void -client_socket_close(int client_socket, struct sockaddr *client_address) -{ - /* Should never close 0, 1, or 2 */ - assert(client_socket != STDIN_FILENO); - assert(client_socket != STDOUT_FILENO); - assert(client_socket != STDERR_FILENO); - - if (unlikely(close(client_socket) < 0)) { - char client_address_text[INET6_ADDRSTRLEN] = {}; - if (unlikely(inet_ntop(AF_INET, &client_address, client_address_text, INET6_ADDRSTRLEN) == NULL)) { - debuglog("Failed to log client_address: %s", strerror(errno)); - } - debuglog("Error closing client socket %d associated with %s - %s", client_socket, client_address_text, - strerror(errno)); - } -} - -/** - * Rejects request due to admission control or error - * @param client_socket - the client we are rejecting - * @param status_code - either 503 or 400 - */ -int -client_socket_send(int client_socket, int status_code) -{ - const char *response; - int rc; - switch (status_code) { - case 503: - response = HTTP_RESPONSE_503_SERVICE_UNAVAILABLE; - http_total_increment_5XX(); - break; - case 400: - response = HTTP_RESPONSE_400_BAD_REQUEST; - http_total_increment_4XX(); - break; - default: - panic("%d is not a valid status code\n", status_code); - } - - int sent = 0; - int to_send = strlen(response); - - while (sent < to_send) { - rc = write(client_socket, &response[sent], to_send - sent); - if (rc < 0) { - if (errno == EAGAIN) { debuglog("Unexpectedly blocking on write of %s\n", response); } - - debuglog("Error with %s\n", strerror(errno)); - - goto send_err; - } - sent += rc; - }; - - rc = 0; -done: - return rc; -send_err: - debuglog("Error sending to client: %s", strerror(errno)); - rc = -1; - goto done; -} diff --git a/runtime/src/http_parser_settings.c b/runtime/src/http_parser_settings.c index f06c52e..7190bd2 100644 --- a/runtime/src/http_parser_settings.c +++ b/runtime/src/http_parser_settings.c @@ -1,11 +1,10 @@ #include "debuglog.h" #include "http.h" #include "http_request.h" -#include "http_response.h" #include "http_parser_settings.h" #include "sandbox.h" -static http_parser_settings runtime_http_parser_settings; +http_parser_settings runtime_http_parser_settings; /*********************************************************************** * http-parser Callbacks in lifecycle order * @@ -261,8 +260,3 @@ http_parser_settings_initialize() 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/http_request.c b/runtime/src/http_request.c index 2489a5b..8c9a71b 100644 --- a/runtime/src/http_request.c +++ b/runtime/src/http_request.c @@ -6,19 +6,6 @@ * General HTTP Request Functions * **************************************************/ -/** - * Gets the HTTP Request body from a Sandbox - * @param sandbox the sandbox we want the body from - * @param body pointer that we'll assign to the http_request body - * @returns the length of the http_request's body - */ -int -http_request_get_body(struct http_request *http_request, char **body) -{ - *body = http_request->body; - return http_request->body_length; -} - void http_request_print(struct http_request *self) { diff --git a/runtime/src/http_response.c b/runtime/src/http_response.c deleted file mode 100644 index 61d8cea..0000000 --- a/runtime/src/http_response.c +++ /dev/null @@ -1,91 +0,0 @@ -#include - -#include "http_response.h" - -/*************************************************** - * General HTTP Response Functions * - **************************************************/ - -/** - * Encodes a sandbox's HTTP Response as an array of buffers - * @param sandbox the sandbox containing the HTTP response we want to encode as buffers - * @returns the number of buffers used to store the HTTP Response - */ -int -http_response_encode_as_vector(struct http_response *http_response) -{ - int buffer_count = 0; - - http_response->bufs[buffer_count].iov_base = http_response->status; - http_response->bufs[buffer_count].iov_len = http_response->status_length; - buffer_count++; - - for (int i = 0; i < http_response->header_count; i++) { - http_response->bufs[buffer_count].iov_base = http_response->headers[i].header; - http_response->bufs[buffer_count].iov_len = http_response->headers[i].length; - buffer_count++; - } - - if (http_response->body) { - http_response->bufs[buffer_count].iov_base = http_response->body; - http_response->bufs[buffer_count].iov_len = http_response->body_length; - buffer_count++; - - http_response->bufs[buffer_count].iov_base = http_response->status + http_response->status_length - 2; - http_response->bufs[buffer_count].iov_len = 2; - buffer_count++; - } - - return buffer_count; -} - -/** - * Set an HTTP Response Body on a Sandbox - * @param sandbox the sandbox we want to set the request header on - * @param body string of the body that we want to set - * @param length the length of the header string - * @returns 0 (abends program in case of error) - */ -int -http_response_set_body(struct http_response *http_response, char *body, int length) -{ - // assert(length <= sandbox->module->max_response_size); - http_response->body = body; - http_response->body_length = length; - - return 0; -} - -/** - * Append a header to the HTTP Response of a Sandbox - * @param sandbox the sandbox we want to set the request header on - * @param header string containing the header that we want to append - * @param length the length of the header string - * @returns 0 (abends program in case of error) - */ -int -http_response_set_header(struct http_response *http_response, char *header, int length) -{ - assert(http_response->header_count < HTTP_MAX_HEADER_COUNT); - http_response->header_count++; - http_response->headers[http_response->header_count - 1].header = header; - http_response->headers[http_response->header_count - 1].length = length; - - return 0; -} - -/** - * Set an HTTP Response Status on a Sandbox - * @param sandbox the sandbox we want to set the request status on - * @param status string of the status we want to set - * @param length the length of the status - * @returns 0 (abends program in case of error) - */ -int -http_response_set_status(struct http_response *http_response, char *status, int length) -{ - http_response->status = status; - http_response->status_length = length; - - return 0; -} diff --git a/runtime/src/http_total.c b/runtime/src/http_total.c index c4e4ee0..68d4ca9 100644 --- a/runtime/src/http_total.c +++ b/runtime/src/http_total.c @@ -13,46 +13,7 @@ _Atomic uint32_t http_total_2XX = 0; _Atomic uint32_t http_total_4XX = 0; #endif -void -http_total_init() -{ - atomic_init(&http_total_requests, 0); - atomic_init(&http_total_5XX, 0); -#ifdef LOG_TOTAL_REQS_RESPS - atomic_init(&http_total_2XX, 0); - atomic_init(&http_total_4XX, 0); -#endif -} - -void -http_total_increment_request() -{ - atomic_fetch_add(&http_total_requests, 1); -} - -void -http_total_increment_2xx() -{ -#ifdef LOG_TOTAL_REQS_RESPS - atomic_fetch_add(&http_total_2XX, 1); -#endif -} - -void -http_total_increment_4XX() -{ -#ifdef LOG_TOTAL_REQS_RESPS - atomic_fetch_add(&http_total_4XX, 1); -#endif -} - -void -http_total_increment_5XX() -{ - atomic_fetch_add(&http_total_5XX, 1); -} - - +/* Primarily intended to be called via GDB */ void http_total_log() { diff --git a/runtime/src/local_runqueue_minheap.c b/runtime/src/local_runqueue_minheap.c index f9d3787..491df86 100644 --- a/runtime/src/local_runqueue_minheap.c +++ b/runtime/src/local_runqueue_minheap.c @@ -38,18 +38,6 @@ local_runqueue_minheap_add(struct sandbox *sandbox) if (return_code == -ENOSPC) panic("Thread Runqueue is full!\n"); } -/** - * Removes the highest priority sandbox from the run queue - * @param pointer to test to address of removed sandbox if successful - * @returns RC 0 if successfully set dequeued_element, -ENOENT if empty - */ -static int -local_runqueue_minheap_remove(struct sandbox **to_remove) -{ - assert(!software_interrupt_is_enabled()); - return priority_queue_dequeue_nolock(local_runqueue_minheap, (void **)to_remove); -} - /** * Deletes a sandbox from the runqueue * @param sandbox to delete diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index fc9cefc..ee20437 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -17,7 +17,6 @@ #include "global_request_scheduler_deque.h" #include "global_request_scheduler_minheap.h" #include "http_parser_settings.h" -#include "http_response.h" #include "listener_thread.h" #include "module.h" #include "runtime.h"