refactor: parsing and validation

master
Sean McBride 3 years ago
parent 576f65d846
commit c3d0fe375a

@ -118,7 +118,10 @@
"route_config.h": "c",
"http_router.h": "c",
"admissions_info.h": "c",
"tcp_server.h": "c"
"tcp_server.h": "c",
"stdint.h": "c",
"scheduler_options.h": "c",
"route_config_parse.h": "c"
},
"files.exclude": {
"**/.git": true,

@ -22,13 +22,12 @@
VEC(u8)
struct http_session {
/* HTTP State */
struct sockaddr client_address; /* client requesting connection! */
int socket;
struct http_parser http_parser;
struct http_request http_request;
struct vec_u8 request;
struct vec_u8 response;
struct vec_u8 request_buffer;
struct vec_u8 response_buffer;
};
/**
@ -39,6 +38,7 @@ static inline int
http_session_init(struct http_session *session, int socket_descriptor, const struct sockaddr *socket_address)
{
assert(session != NULL);
assert(socket_descriptor >= 0);
assert(socket_address != NULL);
session->socket = socket_descriptor;
@ -46,17 +46,16 @@ http_session_init(struct http_session *session, int socket_descriptor, const str
http_parser_init(&session->http_parser, HTTP_REQUEST);
/* Set the session as the data the http-parser has access to */
/* Set the http_request member as the data pointer the http_parser callbacks receive */
session->http_parser.data = &session->http_request;
memset(&session->http_request, 0, sizeof(struct http_parser));
int rc;
rc = vec_u8_init(&session->request, HTTP_SESSION_DEFAULT_REQUEST_RESPONSE_SIZE);
int rc = vec_u8_init(&session->request_buffer, HTTP_SESSION_DEFAULT_REQUEST_RESPONSE_SIZE);
if (rc < 0) return -1;
/* Defer allocating response until we've matched a route */
session->response.buffer = NULL;
session->response_buffer.buffer = NULL;
return 0;
}
@ -65,19 +64,23 @@ static inline int
http_session_init_response_buffer(struct http_session *session, size_t capacity)
{
assert(session != NULL);
assert(session->response.buffer == NULL);
assert(session->response_buffer.buffer == NULL);
int rc = vec_u8_init(&session->response, capacity);
int rc = vec_u8_init(&session->response_buffer, capacity);
if (rc < 0) {
vec_u8_deinit(&session->request);
vec_u8_deinit(&session->request_buffer);
return -1;
}
return 0;
}
static inline struct http_session *
http_session_alloc(int socket_descriptor, const struct sockaddr *socket_address)
{
assert(socket_descriptor >= 0);
assert(socket_address != NULL);
struct http_session *session = calloc(sizeof(struct http_session), 1);
if (session == NULL) return NULL;
@ -98,14 +101,16 @@ static inline void
http_session_deinit(struct http_session *session)
{
assert(session);
vec_u8_deinit(&session->request);
vec_u8_deinit(&session->response);
vec_u8_deinit(&session->request_buffer);
vec_u8_deinit(&session->response_buffer);
}
static inline void
http_session_free(struct http_session *session)
{
assert(session);
http_session_deinit(session);
free(session);
}
@ -119,6 +124,9 @@ http_session_free(struct http_session *session)
static inline int
http_session_send_err(struct http_session *session, int status_code, void_cb on_eagain)
{
assert(session != NULL);
assert(status_code >= 100 && status_code <= 599);
return tcp_session_send(session->socket, http_header_build(status_code), http_header_len(status_code),
on_eagain);
}
@ -126,25 +134,29 @@ http_session_send_err(struct http_session *session, int status_code, void_cb on_
static inline int
http_session_send_err_oneshot(struct http_session *session, int status_code)
{
assert(session != NULL);
assert(status_code >= 100 && status_code <= 599);
return tcp_session_send_oneshot(session->socket, http_header_build(status_code), http_header_len(status_code));
}
static inline int
http_session_send_response(struct http_session *session, const char *response_content_type, void_cb on_eagain)
{
struct vec_u8 *response = &session->response;
assert(response != NULL);
assert(session != NULL);
assert(session->response_buffer.buffer != NULL);
assert(response_content_type != NULL);
int rc;
int rc = 0;
/* Determine values to template into our HTTP response */
const char *content_type = strlen(response_content_type) > 0 ? response_content_type : "text/plain";
struct vec_u8 *response_buffer = &session->response_buffer;
/* Send HTTP Response Header and Body */
rc = http_header_200_write(session->socket, content_type, response->length);
rc = http_header_200_write(session->socket, response_content_type, response_buffer->length);
if (rc < 0) goto err;
rc = tcp_session_send(session->socket, (const char *)response->buffer, response->length, on_eagain);
rc = tcp_session_send(session->socket, (const char *)response_buffer->buffer, response_buffer->length,
on_eagain);
if (rc < 0) goto err;
http_total_increment_2xx();
@ -161,6 +173,8 @@ err:
static inline void
http_session_close(struct http_session *session)
{
assert(session != NULL);
return tcp_session_close(session->socket, &session->client_address);
}
@ -170,15 +184,15 @@ http_session_close(struct http_session *session)
* @return 0 if message parsing complete, -1 on error, -2 if buffers run out of space
*/
static inline int
http_session_receive(struct http_session *session, void_cb on_eagain)
http_session_receive_request(struct http_session *session, void_cb on_eagain)
{
assert(session != NULL);
int rc = 0;
struct vec_u8 *request = &session->request;
assert(request->capacity > 0);
assert(request->length < request->capacity);
struct vec_u8 *request_buffer = &session->request_buffer;
assert(request_buffer->capacity > 0);
assert(request_buffer->length < request_buffer->capacity);
while (!session->http_request.message_end) {
/* Read from the Socket */
@ -189,20 +203,20 @@ http_session_receive(struct http_session *session, void_cb on_eagain)
/* If header parsing is complete, resize using content-length */
if (session->http_request.header_end && session->http_request.body != NULL) {
int header_size = (uint8_t *)session->http_request.body - session->request.buffer;
int header_size = (uint8_t *)session->http_request.body - session->request_buffer.buffer;
assert(header_size > 0);
int required_size = header_size + session->http_request.body_length;
assert(required_size > 0);
if (required_size > request->capacity) {
uint8_t *old_buffer = request->buffer;
if (vec_u8_resize(request, required_size) != 0) {
if (required_size > request_buffer->capacity) {
uint8_t *old_buffer = request_buffer->buffer;
if (vec_u8_resize(request_buffer, required_size) != 0) {
debuglog("Failed to resize request vector to %d bytes\n", required_size);
goto err_nobufs;
}
if (old_buffer != request->buffer) {
if (old_buffer != request_buffer->buffer) {
/* buffer moved, so invalidate to reparse */
memset(&session->http_request, 0, sizeof(struct http_request));
http_parser_init(&session->http_parser, HTTP_REQUEST);
@ -210,16 +224,16 @@ http_session_receive(struct http_session *session, void_cb on_eagain)
session->http_parser.data = &session->http_request;
}
}
} else if (request->length == request->capacity) {
} else if (request_buffer->length == request_buffer->capacity) {
/* Otherwise, we have a huge header and should just grow */
uint8_t *old_buffer = request->buffer;
uint8_t *old_buffer = request_buffer->buffer;
if (vec_u8_grow(request) != 0) {
if (vec_u8_grow(request_buffer) != 0) {
debuglog("Failed to grow request buffer\n");
goto err_nobufs;
}
if (old_buffer != request->buffer) {
if (old_buffer != request_buffer->buffer) {
/* buffer moved, so invalidate to reparse */
memset(&session->http_request, 0, sizeof(struct http_request));
http_parser_init(&session->http_parser, HTTP_REQUEST);
@ -228,8 +242,8 @@ http_session_receive(struct http_session *session, void_cb on_eagain)
}
}
ssize_t bytes_received = recv(session->socket, &request->buffer[request->length],
request->capacity - request->length, 0);
ssize_t bytes_received = recv(session->socket, &request_buffer->buffer[request_buffer->length],
request_buffer->capacity - request_buffer->length, 0);
if (bytes_received < 0) {
if (errno == EAGAIN) {
@ -260,16 +274,16 @@ http_session_receive(struct http_session *session, void_cb on_eagain)
}
assert(bytes_received > 0);
request->length += bytes_received;
request_buffer->length += bytes_received;
#ifdef LOG_HTTP_PARSER
debuglog("http_parser_execute(%p, %p, %p, %zu\n)", parser, settings,
&session->request.buffer[session->request.length], bytes_received);
&session->request_buffer.buffer[session->request_buffer.length], bytes_received);
#endif
size_t bytes_parsed =
http_parser_execute(parser, settings,
(const char *)&request->buffer[session->http_request.length_parsed],
(size_t)request->length - session->http_request.length_parsed);
(const char *)&request_buffer->buffer[session->http_request.length_parsed],
(size_t)request_buffer->length - session->http_request.length_parsed);
if (bytes_parsed < (size_t)bytes_received) {
debuglog("Error: %s, Description: %s\n",
@ -304,3 +318,31 @@ err:
rc = -1;
goto done;
}
/**
* Writes to the HTTP response buffer
* On success, the number of bytes written is returned. On error, -1 is returned,
*/
static inline int
http_session_write_response(struct http_session *session, const uint8_t *source, size_t n)
{
assert(session);
assert(session->response_buffer.buffer != NULL);
assert(source);
int rc = 0;
if (session->response_buffer.capacity - session->response_buffer.length < n) {
rc = vec_u8_grow(&session->response_buffer);
if (rc != 0) goto DONE;
}
assert(session->response_buffer.capacity - session->response_buffer.length >= n);
memcpy(&session->response_buffer.buffer[session->response_buffer.length], source, n);
session->response_buffer.length += n;
rc = n;
DONE:
return rc;
}

@ -4,9 +4,24 @@
#include <stdio.h>
#include <stdlib.h>
#include "runtime.h"
#include "scheduler_options.h"
enum route_config_member
{
route_config_member_route,
route_config_member_path,
route_config_member_admissions_percentile,
route_config_member_expected_execution_us,
route_config_member_relative_deadline_us,
route_config_member_http_resp_size,
route_config_member_http_resp_content_type,
route_config_member_len
};
struct route_config {
char *path;
char *route;
char *path;
uint8_t admissions_percentile;
uint32_t expected_execution_us;
uint32_t relative_deadline_us;
@ -33,3 +48,72 @@ route_config_print(struct route_config *config)
printf("[Route] HTTP Response Size: %u\n", config->http_resp_size);
printf("[Route] HTTP Response Content Type: %s\n", config->http_resp_content_type);
}
/**
* Validates a route config generated by a parser
* @param config
* @param did_set boolean array of size route_config_member_len indicating if parser set the associated member
*/
static inline int
route_config_validate(struct route_config *config, bool *did_set)
{
if (did_set[route_config_member_route] == false) {
fprintf(stderr, "path field is required\n");
return -1;
}
if (did_set[route_config_member_path] == false) {
fprintf(stderr, "path field is required\n");
return -1;
}
if (did_set[route_config_member_http_resp_content_type] == false) {
debuglog("http_resp_content_type not set, defaulting to text/plain\n");
config->http_resp_content_type = "text/plain";
return -1;
}
if (scheduler == SCHEDULER_EDF) {
if (did_set[route_config_member_relative_deadline_us] == false) {
fprintf(stderr, "relative_deadline_us is required\n");
return -1;
}
if (config->relative_deadline_us > (uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX) {
fprintf(stderr, "Relative-deadline-us must be between 0 and %u, was %u\n",
(uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX, config->relative_deadline_us);
return -1;
}
#ifdef ADMISSIONS_CONTROL
if (did_set[route_config_member_expected_execution_us] == false) {
fprintf(stderr, "expected-execution-us is required\n");
return -1;
}
if (did_set[route_config_member_admissions_percentile] == false) {
fprintf(stderr, "admissions_percentile is required\n");
return -1;
}
if (config->admissions_percentile > 99 || config->admissions_percentile < 50) {
fprintf(stderr, "admissions-percentile must be > 50 and <= 99 but was %u\n",
route_config->admissions_percentile);
return -1;
}
/* If the ratio is too big, admissions control is too coarse */
uint32_t ratio = route_config->relative_deadline_us / route_config->expected_execution_us;
if (ratio > ADMISSIONS_CONTROL_GRANULARITY) {
fprintf(stderr,
"Ratio of Deadline to Execution time cannot exceed admissions control "
"granularity of "
"%d\n",
ADMISSIONS_CONTROL_GRANULARITY);
return -1;
}
#endif
}
return 0;
}

@ -6,88 +6,101 @@
#include "json.h"
#include "route_config.h"
enum
static const char *route_config_json_keys[route_config_member_len] = { "route",
"path",
"admissions-percentile",
"expected-execution-us",
"relative-deadline-us",
"http-resp-size",
"http-resp-content-type" };
static inline int
route_config_set_key_once(bool *did_set, enum route_config_member member)
{
route_config_json_key_http_path,
route_config_json_key_module_path,
route_config_json_key_admissions_percentile,
route_config_json_key_expected_execution_us,
route_config_json_key_relative_deadline_us,
route_config_json_key_http_resp_size,
route_config_json_key_http_resp_content_type,
route_config_json_key_len
};
static const char *route_config_json_keys[route_config_json_key_len] = { "route",
"path",
"admissions-percentile",
"expected-execution-us",
"relative-deadline-us",
"http-resp-size",
"http-resp-content-type" };
if (did_set[member]) {
debuglog("Redundant key %s\n", route_config_json_keys[member]);
return -1;
}
did_set[member] = true;
return 0;
}
static inline int
route_config_parse(struct route_config *config, const char *json_buf, jsmntok_t *tokens, size_t tokens_base,
int tokens_size)
{
int i = tokens_base;
char key[32] = { 0 };
int i = tokens_base;
char key[32] = { 0 };
bool did_set[route_config_member_len] = { false };
if (!has_valid_type(tokens[i], "anonymous object in array", JSMN_OBJECT, json_buf)) return -1;
if (!has_valid_type(tokens[i], "Anonymous Route Config Object", JSMN_OBJECT, json_buf)) return -1;
if (!is_nonempty_object(tokens[i], "Anonymous Route Config Object")) return -1;
int route_keys_len = tokens[i].size;
int route_key_count = tokens[i].size;
if (tokens[i].size == 0) {
fprintf(stderr, "empty route object\n");
return -1;
}
for (int route_key_idx = 0; route_key_idx < route_keys_len; route_key_idx++) {
for (int route_key_idx = 0; route_key_idx < route_key_count; route_key_idx++) {
/* Advance to key */
i++;
if (!is_valid_key(tokens[i])) return -1;
if (!has_valid_size(tokens[i], key, 1)) return -1;
/* Copy Key */
sprintf(key, "%.*s", tokens[i].end - tokens[i].start, json_buf + tokens[i].start);
/* Advance to Value */
i++;
if (strcmp(key, route_config_json_keys[route_config_json_key_http_path]) == 0) {
if (strcmp(key, route_config_json_keys[route_config_member_route]) == 0) {
if (!is_nonempty_string(tokens[i], key)) return -1;
if (route_config_set_key_once(did_set, route_config_member_route) == -1) return -1;
config->route = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start);
} else if (strcmp(key, route_config_json_keys[route_config_json_key_module_path]) == 0) {
} else if (strcmp(key, route_config_json_keys[route_config_member_path]) == 0) {
if (!is_nonempty_string(tokens[i], key)) return -1;
if (route_config_set_key_once(did_set, route_config_member_path) == -1) return -1;
config->path = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start);
} else if (strcmp(key, route_config_json_keys[route_config_json_key_admissions_percentile]) == 0) {
} else if (strcmp(key, route_config_json_keys[route_config_member_admissions_percentile]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_admissions_percentile) == -1)
return -1;
int rc = parse_uint8_t(tokens[i], json_buf,
route_config_json_keys[route_config_json_key_admissions_percentile],
route_config_json_keys[route_config_member_admissions_percentile],
&config->admissions_percentile);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_json_key_expected_execution_us]) == 0) {
} else if (strcmp(key, route_config_json_keys[route_config_member_expected_execution_us]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_expected_execution_us) == -1)
return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_json_key_expected_execution_us],
route_config_json_keys[route_config_member_expected_execution_us],
&config->expected_execution_us);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_json_key_relative_deadline_us]) == 0) {
} else if (strcmp(key, route_config_json_keys[route_config_member_relative_deadline_us]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_relative_deadline_us) == -1)
return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_json_key_relative_deadline_us],
route_config_json_keys[route_config_member_relative_deadline_us],
&config->relative_deadline_us);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_json_key_http_resp_size]) == 0) {
} else if (strcmp(key, route_config_json_keys[route_config_member_http_resp_size]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (route_config_set_key_once(did_set, route_config_member_http_resp_size) == -1) return -1;
int rc = parse_uint32_t(tokens[i], json_buf,
route_config_json_keys[route_config_json_key_http_resp_size],
route_config_json_keys[route_config_member_http_resp_size],
&config->http_resp_size);
if (rc < 0) return -1;
} else if (strcmp(key, route_config_json_keys[route_config_json_key_http_resp_content_type]) == 0) {
} else if (strcmp(key, route_config_json_keys[route_config_member_http_resp_content_type]) == 0) {
if (!is_nonempty_string(tokens[i], key)) return -1;
if (route_config_set_key_once(did_set, route_config_member_http_resp_content_type) == -1)
return -1;
config->http_resp_content_type = strndup(json_buf + tokens[i].start,
tokens[i].end - tokens[i].start);
@ -97,5 +110,7 @@ route_config_parse(struct route_config *config, const char *json_buf, jsmntok_t
}
}
if (route_config_validate(config, did_set) < 0) return -1;
return i;
}

@ -13,5 +13,5 @@ sandbox_receive_request(struct sandbox *sandbox)
assert(sandbox != NULL);
struct http_session *session = sandbox->http;
return http_session_receive(session, current_sandbox_sleep);
return http_session_receive_request(session, current_sandbox_sleep);
}

@ -4,7 +4,17 @@
#include <stdio.h>
#include <stdlib.h>
#include "panic.h"
#include "route_config.h"
#include "runtime.h"
enum tenant_config_member
{
tenant_config_member_name,
tenant_config_member_port,
tenant_config_member_routes,
tenant_config_member_len
};
struct tenant_config {
char *name;
@ -32,3 +42,29 @@ tenant_config_print(struct tenant_config *config)
printf("[Tenant] Routes Size: %zu\n", config->routes_len);
for (int i = 0; i < config->routes_len; i++) { route_config_print(&config->routes[i]); }
}
static inline int
tenant_config_validate(struct tenant_config *config, bool *did_set)
{
if (did_set[tenant_config_member_name] == false) {
fprintf(stderr, "name field is required\n");
return -1;
}
if (strlen(config->name) == 0) {
fprintf(stderr, "name field is empty string\n");
return -1;
}
if (did_set[tenant_config_member_port] == false) {
fprintf(stderr, "port field is required\n");
return -1;
}
if (config->routes_len == 0) {
fprintf(stderr, "one or more routes are required\n");
return -1;
}
return 0;
}

@ -4,36 +4,38 @@
#include <stdlib.h>
#include <string.h>
#include "debuglog.h"
#include "json.h"
#include "route_config_parse.h"
#include "tenant_config.h"
enum
{
tenant_config_json_key_name,
tenant_config_json_key_port,
tenant_config_json_key_routes,
tenant_config_json_key_len
};
static const char *tenant_config_json_keys[tenant_config_json_key_len] = { "name", "port", "routes" };
static const char *tenant_config_json_keys[tenant_config_member_len] = { "name", "port", "routes" };
static inline int
tenant_config_set_key_once(bool *did_set, enum tenant_config_member member)
{
if (did_set[member]) {
debuglog("Redundant key %s\n", tenant_config_json_keys[member]);
return -1;
}
/* Tenant Config */
did_set[member] = true;
return 0;
}
static inline int
tenant_config_parse(struct tenant_config *config, const char *json_buf, jsmntok_t *tokens, size_t tokens_base,
int tokens_size)
{
int i = tokens_base;
char key[32] = { 0 };
int i = tokens_base;
char key[32] = { 0 };
bool did_set[tenant_config_member_len] = { false };
if (!has_valid_type(tokens[i], "Anonymous Tenant Config Object", JSMN_OBJECT, json_buf)) return -1;
if (!is_nonempty_object(tokens[i], "Anonymous Tenant Config Object")) return -1;
int tenant_key_count = tokens[i].size;
for (int tenant_key_idx = 0; tenant_key_idx < tenant_key_count; tenant_key_idx++) {
/* Advance to key */
i++;
@ -47,18 +49,21 @@ tenant_config_parse(struct tenant_config *config, const char *json_buf, jsmntok_
/* Advance to Value */
i++;
if (strcmp(key, tenant_config_json_keys[tenant_config_json_key_name]) == 0) {
if (strcmp(key, tenant_config_json_keys[tenant_config_member_name]) == 0) {
if (!is_nonempty_string(tokens[i], key)) return -1;
if (tenant_config_set_key_once(did_set, tenant_config_member_name) == -1) return -1;
config->name = strndup(json_buf + tokens[i].start, tokens[i].end - tokens[i].start);
} else if (strcmp(key, tenant_config_json_keys[tenant_config_json_key_port]) == 0) {
} else if (strcmp(key, tenant_config_json_keys[tenant_config_member_port]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_PRIMITIVE, json_buf)) return -1;
if (tenant_config_set_key_once(did_set, tenant_config_member_port) == -1) return -1;
int rc = parse_uint16_t(tokens[i], json_buf,
tenant_config_json_keys[tenant_config_json_key_port], &config->port);
int rc = parse_uint16_t(tokens[i], json_buf, tenant_config_json_keys[tenant_config_member_port],
&config->port);
if (rc < 0) return -1;
} else if (strcmp(key, tenant_config_json_keys[tenant_config_json_key_routes]) == 0) {
} else if (strcmp(key, tenant_config_json_keys[tenant_config_member_routes]) == 0) {
if (!has_valid_type(tokens[i], key, JSMN_ARRAY, json_buf)) return -1;
if (tenant_config_set_key_once(did_set, tenant_config_member_routes) == -1) return -1;
int routes_len = tokens[i].size;
config->routes_len = routes_len;
@ -77,6 +82,8 @@ tenant_config_parse(struct tenant_config *config, const char *json_buf, jsmntok_
}
}
if (tenant_config_validate(config, did_set) < 0) return -1;
return i;
}

@ -19,11 +19,6 @@ struct tenant *tenant_database_find_by_port(uint16_t port);
static inline struct tenant *
tenant_alloc(struct tenant_config *config)
{
/* Validate config */
if (strlen(config->name) == 0) panic("name field is required\n");
if (config->port == 0) panic("port field is required\n");
if (config->routes_len == 0) panic("one or more routesa are required\n");
struct tenant *existing_tenant = tenant_database_find_by_name(config->name);
if (existing_tenant != NULL) panic("Tenant %s is already initialized\n", existing_tenant->name);
@ -31,39 +26,6 @@ tenant_alloc(struct tenant_config *config)
if (existing_tenant != NULL)
panic("Tenant %s is already configured with port %u\n", existing_tenant->name, config->port);
for (int i = 0; i < config->routes_len; i++) {
struct route_config *route_config = &config->routes[i];
if (route_config->path == 0) panic("path field is required\n");
if (route_config->route == 0) panic("route field is required\n");
if (route_config->relative_deadline_us > (uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX)
panic("Relative-deadline-us must be between 0 and %u, was %u\n",
(uint32_t)RUNTIME_RELATIVE_DEADLINE_US_MAX, route_config->relative_deadline_us);
#ifdef ADMISSIONS_CONTROL
/* expected-execution-us and relative-deadline-us are required in case of admissions control */
if (route_config->expected_execution_us == 0) panic("expected-execution-us is required\n");
if (route_config->relative_deadline_us == 0) panic("relative_deadline_us is required\n");
if (route_config->admissions_percentile > 99 || route_config->admissions_percentile < 50)
panic("admissions-percentile must be > 50 and <= 99 but was %u\n",
route_config->admissions_percentile);
/* If the ratio is too big, admissions control is too coarse */
uint32_t ratio = route_config->relative_deadline_us / route_config->expected_execution_us;
if (ratio > ADMISSIONS_CONTROL_GRANULARITY)
panic("Ratio of Deadline to Execution time cannot exceed admissions control "
"granularity of "
"%d\n",
ADMISSIONS_CONTROL_GRANULARITY);
#else
/* relative-deadline-us is required if scheduler is EDF */
if (scheduler == SCHEDULER_EDF && route_config->relative_deadline_us == 0)
panic("relative_deadline_us is required\n");
#endif
}
struct tenant *tenant = (struct tenant *)calloc(1, sizeof(struct tenant));
/* Move name */

@ -786,32 +786,21 @@ wasi_snapshot_preview1_backing_fd_write(wasi_context_t *context, __wasi_fd_t fd,
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
struct sandbox *s = current_sandbox_get();
size_t buffer_remaining = 0;
size_t old_response_len = s->http->response.length;
__wasi_size_t sum = 0;
__wasi_size_t nwritten = 0;
int rc = 0;
for (size_t i = 0; i < iovs_len; i++) {
buffer_remaining = s->http->response.capacity - s->http->response.length;
if (buffer_remaining < iovs[i].buf_len) {
vec_u8_grow(&s->http->response);
buffer_remaining = s->http->response.capacity - s->http->response.length;
}
if (buffer_remaining == 0) {
*nwritten_retptr = s->http->response.length - old_response_len;
return __WASI_ERRNO_FBIG;
}
ssize_t to_write = buffer_remaining > iovs[i].buf_len ? iovs[i].buf_len : buffer_remaining;
memcpy(&s->http->response.buffer[s->http->response.length], iovs[i].buf, to_write);
#ifdef LOG_SANDBOX_STDERR
if (fd == STDERR_FILENO) {
debuglog("STDERR from Sandbox:");
write(2, iovs[i].buf, iovs[i].buf_len);
debuglog("STDERR from Sandbox: %.*s", iovs[i].buf_len, iovs[i].buf);
}
#endif
s->http->response.length += to_write;
rc = http_session_write_response(s->http, iovs[i].buf, iovs[i].buf_len);
if (rc < 0) return __WASI_ERRNO_FBIG;
nwritten += rc;
}
*nwritten_retptr = s->http->response.length - old_response_len;
*nwritten_retptr = nwritten;
return __WASI_ERRNO_SUCCESS;
}

@ -172,7 +172,7 @@ listener_thread_main(void *dummy)
/* Read HTTP request */
/* TODO: Use epoll on block instead of busy looping */
int rc = 0;
while ((rc = http_session_receive(session, NULL)) == -3)
while ((rc = http_session_receive_request(session, NULL)) == -3)
;
if (rc == -2) {

@ -96,7 +96,7 @@ sandbox_prepare_execution_environment(struct sandbox *sandbox)
rc = http_session_init_response_buffer(sandbox->http, sandbox->route->response_size);
if (rc < 0) {
error_message = "failed to response buffer";
error_message = "failed to allocate response buffer";
goto err_globals_allocation_failed;
}

Loading…
Cancel
Save