refactor: http header cleanup

main
Sean McBride 4 years ago
parent cb26514ad3
commit faacc5c785

@ -31,33 +31,6 @@ arch_context_init(struct arch_context *actx, reg_t ip, reg_t sp)
actx->regs[UREG_IP] = ip; 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 a - the registers and context of the thing running
* @param b - the registers and context of what we're switching to * @param b - the registers and context of what we're switching to

@ -11,7 +11,8 @@
* @param ip value to set instruction pointer to * @param ip value to set instruction pointer to
* @param sp value to set stack 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); assert(actx != NULL);
@ -46,33 +47,6 @@ static void __attribute__((noinline)) arch_context_init(struct arch_context *act
actx->regs[UREG_IP] = ip; 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 * Load a new sandbox that preempted an existing sandbox, restoring only the
* instruction pointer and stack pointer registers. * instruction pointer and stack pointer registers.

@ -1,7 +1,80 @@
#pragma once #pragma once
#include <assert.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <unistd.h>
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;
}

@ -3,3 +3,12 @@
#define HTTP_MAX_HEADER_COUNT 16 #define HTTP_MAX_HEADER_COUNT 16
#define HTTP_MAX_HEADER_LENGTH 32 #define HTTP_MAX_HEADER_LENGTH 32
#define HTTP_MAX_HEADER_VALUE_LENGTH 64 #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"

@ -2,5 +2,12 @@
#include "http_parser.h" #include "http_parser.h"
extern http_parser_settings runtime_http_parser_settings;
void http_parser_settings_initialize(void); void http_parser_settings_initialize(void);
http_parser_settings *http_parser_settings_get();
static inline http_parser_settings *
http_parser_settings_get()
{
return &runtime_http_parser_settings;
}

@ -27,5 +27,4 @@ struct http_request {
bool message_end; /* boolean flag set when body processing is complete */ 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); void http_request_print(struct http_request *self);

@ -1,38 +0,0 @@
#pragma once
#include <http_parser.h>
#include <sys/uio.h>
#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);

@ -17,8 +17,41 @@ extern _Atomic uint32_t http_total_2XX;
extern _Atomic uint32_t http_total_4XX; extern _Atomic uint32_t http_total_4XX;
#endif #endif
void http_total_init(); static inline void
void http_total_increment_request(); http_total_init()
void http_total_increment_2xx(); {
void http_total_increment_4XX(); atomic_init(&http_total_requests, 0);
void http_total_increment_5XX(); 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);
}

@ -57,14 +57,6 @@ struct module {
struct admissions_info admissions_info; struct admissions_info admissions_info;
int port; 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; unsigned long max_request_size;
char request_headers[HTTP_MAX_HEADER_COUNT][HTTP_MAX_HEADER_LENGTH]; char request_headers[HTTP_MAX_HEADER_COUNT][HTTP_MAX_HEADER_LENGTH];
int request_header_count; int request_header_count;

@ -6,8 +6,8 @@
#include "arch/context.h" #include "arch/context.h"
#include "client_socket.h" #include "client_socket.h"
#include "deque.h" #include "deque.h"
#include "http_parser.h"
#include "http_request.h" #include "http_request.h"
#include "http_response.h"
#include "module.h" #include "module.h"
#include "ps_list.h" #include "ps_list.h"
#include "sandbox_request.h" #include "sandbox_request.h"
@ -84,7 +84,6 @@ struct sandbox {
bool is_repeat_header; bool is_repeat_header;
http_parser http_parser; http_parser http_parser;
struct http_request http_request; struct http_request http_request;
struct http_response http_response;
char * read_buffer; char * read_buffer;
ssize_t read_length, read_size; ssize_t read_length, read_size;

@ -1,78 +0,0 @@
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#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;
}

@ -1,11 +1,10 @@
#include "debuglog.h" #include "debuglog.h"
#include "http.h" #include "http.h"
#include "http_request.h" #include "http_request.h"
#include "http_response.h"
#include "http_parser_settings.h" #include "http_parser_settings.h"
#include "sandbox.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 * * 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_register_callbacks(&runtime_http_parser_settings);
} }
http_parser_settings *
http_parser_settings_get()
{
return &runtime_http_parser_settings;
}

@ -6,19 +6,6 @@
* General HTTP Request Functions * * 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 void
http_request_print(struct http_request *self) http_request_print(struct http_request *self)
{ {

@ -1,91 +0,0 @@
#include <assert.h>
#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;
}

@ -13,46 +13,7 @@ _Atomic uint32_t http_total_2XX = 0;
_Atomic uint32_t http_total_4XX = 0; _Atomic uint32_t http_total_4XX = 0;
#endif #endif
void /* Primarily intended to be called via GDB */
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);
}
void void
http_total_log() http_total_log()
{ {

@ -38,18 +38,6 @@ local_runqueue_minheap_add(struct sandbox *sandbox)
if (return_code == -ENOSPC) panic("Thread Runqueue is full!\n"); 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 * Deletes a sandbox from the runqueue
* @param sandbox to delete * @param sandbox to delete

@ -17,7 +17,6 @@
#include "global_request_scheduler_deque.h" #include "global_request_scheduler_deque.h"
#include "global_request_scheduler_minheap.h" #include "global_request_scheduler_minheap.h"
#include "http_parser_settings.h" #include "http_parser_settings.h"
#include "http_response.h"
#include "listener_thread.h" #include "listener_thread.h"
#include "module.h" #include "module.h"
#include "runtime.h" #include "runtime.h"

Loading…
Cancel
Save