diff --git a/runtime/include/http_api.h b/runtime/include/http_api.h index a6bec3e4..2961920b 100644 --- a/runtime/include/http_api.h +++ b/runtime/include/http_api.h @@ -16,7 +16,7 @@ int http_request_body_get_sb(struct sandbox *sandbox, char **body); static inline int http_request_body_get(char **body) { - return http_request_body_get_sb(sandbox_current(), body); + return http_request_body_get_sb(get_current_sandbox(), body); } /*************************************************** @@ -36,7 +36,7 @@ int http_response_vector_sb(struct sandbox *sandbox); static inline int http_response_header_set(char *header, int length) { - return http_response_header_set_sb(sandbox_current(), header, length); + return http_response_header_set_sb(get_current_sandbox(), header, length); } /** @@ -48,7 +48,7 @@ http_response_header_set(char *header, int length) static inline int http_response_body_set(char *body, int length) { - return http_response_body_set_sb(sandbox_current(), body, length); + return http_response_body_set_sb(get_current_sandbox(), body, length); } /** @@ -60,7 +60,7 @@ http_response_body_set(char *body, int length) static inline int http_response_status_set(char *status, int length) { - return http_response_status_set_sb(sandbox_current(), status, length); + return http_response_status_set_sb(get_current_sandbox(), status, length); } /** @@ -70,7 +70,7 @@ http_response_status_set(char *status, int length) static inline int http_response_vector(void) { - return http_response_vector_sb(sandbox_current()); + return http_response_vector_sb(get_current_sandbox()); } /*********************************************************************** @@ -80,14 +80,14 @@ void http_init(void); int http_request_parse_sb(struct sandbox *sandbox, size_t l); /** - * Parse the current sandbox's req_resp_data up to length + * Parse the current sandbox's request_response_data up to length * @param length * @returns 0 **/ static inline int http_request_parse(size_t length) { - return http_request_parse_sb(sandbox_current(), length); + return http_request_parse_sb(get_current_sandbox(), length); } #endif /* SRFT_HTTP_API_H */ diff --git a/runtime/include/module.h b/runtime/include/module.h index d569868b..054826fb 100644 --- a/runtime/include/module.h +++ b/runtime/include/module.h @@ -50,7 +50,7 @@ struct module { }; struct module *module_find_by_name(char *name); -struct module *module_find_by_socket_descriptor(int sock); +struct module *module_find_by_socket_descriptor(int socket_descriptor); struct module *module_alloc(char *mod_name, char *mod_path, i32 argument_count, u32 stack_sz, u32 max_heap, u32 timeout, int port, int req_sz, int resp_sz); void module_free(struct module *module); @@ -120,10 +120,10 @@ module_table_init(struct module *module) * @param module **/ static inline void -module_libc_init(struct module *module, i32 env, i32 args) +module_libc_init(struct module *module, i32 env, i32 arguments) { // called in a sandbox. - module->initialize_libc(env, args); + module->initialize_libc(env, arguments); } /** diff --git a/runtime/include/runtime.h b/runtime/include/runtime.h index 19617569..018a3307 100644 --- a/runtime/include/runtime.h +++ b/runtime/include/runtime.h @@ -11,15 +11,15 @@ extern int epoll_file_descriptor; extern struct deque_sandbox *global_deque; extern pthread_mutex_t global_deque_mutex; -extern __thread uv_loop_t uvio; +extern __thread uv_loop_t uvio_handle; void alloc_linear_memory(void); void expand_memory(void); void free_linear_memory(void *base, u32 bound, u32 max); INLINE char *get_function_from_table(u32 idx, u32 type_id); INLINE char *get_memory_ptr_for_runtime(u32 offset, u32 bounds_check); -void runtime_init(void); -void runtime_thd_init(void); +void initialize_runtime(void); +void initialize_listener_thread(void); void stub_init(i32 offset); /** @@ -61,7 +61,7 @@ get_memory_string(u32 offset) static inline uv_loop_t * runtime_uvio(void) { - return &uvio; + return &uvio_handle; } /** diff --git a/runtime/include/sandbox.h b/runtime/include/sandbox.h index 9316de56..363563a5 100644 --- a/runtime/include/sandbox.h +++ b/runtime/include/sandbox.h @@ -11,18 +11,15 @@ #include struct io_handle { - int fd; - struct stat s_cache; - union uv_any_handle uvh; + int file_descriptor; + union uv_any_handle libuv_handle; }; typedef enum { - SANDBOX_FREE, - SANDBOX_RUNNABLE, - SANDBOX_BLOCKED, - SANDBOX_WOKEN, // for race in block()/wakeup() - SANDBOX_RETURNED, // waiting for parent to read status? + RUNNABLE, + BLOCKED, + RETURNED } sandbox_state_t; /* @@ -31,67 +28,72 @@ typedef enum */ extern void __attribute__((noreturn)) sandbox_switch_preempt(void); +// TODO: linear_memory_max_size is not really used + struct sandbox { sandbox_state_t state; - void *linear_start; // after sandbox struct - u32 linear_size; // from after sandbox struct - u32 linear_max_size; - u32 sandbox_size; + u32 sandbox_size; // The struct plus enough buffer to hold the request or response (sized off largest) + + void *linear_memory_start; // after sandbox struct + u32 linear_memory_size; // from after sandbox struct + u32 linear_memory_max_size; void *stack_start; // guess we need a mechanism for stack allocation. u32 stack_size; // and to set the size of it. arch_context_t ctxt; // register context for context switch. - // TODO: are all these necessary? + // TODO: Refactor to usefully track across scheduler u64 actual_deadline; u64 expected_deadline; u64 total_time; u64 remaining_time; u64 start_time; - struct module *module; // which module is this an instance of? + struct module *module; // the module this is an instance of - i32 args_offset; // actual placement of args in the sandbox. - void *args; // args from request, must be of module->argument_count size. - i32 retval; + i32 arguments_offset; // actual placement of arguments in the sandbox. + void *arguments; // arguments from request, must be of module->argument_count size. + i32 return_value; struct io_handle handles[SBOX_MAX_OPEN]; - struct sockaddr client; // client requesting connection! - int csock; - uv_tcp_t cuv; - uv_shutdown_t cuvsr; + struct sockaddr client_address; // client requesting connection! + int client_socket_descriptor; + uv_tcp_t client_libuv_stream; + uv_shutdown_t client_libuv_shutdown_request; + http_parser http_parser; struct http_request http_request; struct http_response http_response; - char * read_buf; - ssize_t read_len, read_size; + char * read_buffer; + ssize_t read_length, read_size; + // TODO: Is this used? struct ps_list list; - ssize_t rr_data_len; // <= max(module->max_request_or_response_size) - char req_resp_data[1]; // of rr_data_sz, following sandbox mem.. + ssize_t request_response_data_length; // <= max(module->max_request_or_response_size) + char request_response_data[1]; // of rr_data_sz, following sandbox mem.. } PAGE_ALIGNED; struct sandbox_request { struct module * module; - char * args; - int sock; - struct sockaddr *addr; + char * arguments; + int socket_descriptor; + struct sockaddr *socket_address; u64 start_time; // cycles }; -typedef struct sandbox_request sbox_request_t; +typedef struct sandbox_request sandbox_request_t; -DEQUE_PROTOTYPE(sandbox, sbox_request_t *); +DEQUE_PROTOTYPE(sandbox, sandbox_request_t *); -static inline int sandbox_deque_push(sbox_request_t *sandbox_request); +static inline int add_sandbox_request_to_global_dequeue(sandbox_request_t *sandbox_request); // a runtime resource, malloc on this! -struct sandbox *sandbox_alloc(struct module *module, char *args, int sock, const struct sockaddr *addr, u64 start_time); +struct sandbox *allocate_sandbox(struct module *module, char *arguments, int socket_descriptor, const struct sockaddr *socket_address, u64 start_time); // should free stack and heap resources.. also any I/O handles. -void sandbox_free(struct sandbox *sandbox); +void free_sandbox(struct sandbox *sandbox); extern __thread struct sandbox *current_sandbox; // next_sandbox only used in SIGUSR1 @@ -102,25 +104,25 @@ typedef struct sandbox sandbox_t; /** * Allocates a new Sandbox Request and places it on the Global Deque * @param module the module we want to request - * @param args the arguments that we'll pass to the serverless function - * @param sock - * @param addr + * @param arguments the arguments that we'll pass to the serverless function + * @param socket_descriptor + * @param socket_address * @param start_time the timestamp of when we receives the request from the network (in cycles) * @return the new sandbox request **/ -static inline sbox_request_t * -sbox_request_alloc(struct module *module, char *args, int sock, const struct sockaddr *addr, u64 start_time) +static inline sandbox_request_t * +allocate_sandbox_request(struct module *module, char *arguments, int socket_descriptor, const struct sockaddr *socket_address, u64 start_time) { - sbox_request_t *sandbox_request = malloc(sizeof(sbox_request_t)); + sandbox_request_t *sandbox_request = malloc(sizeof(sandbox_request_t)); assert(sandbox_request); sandbox_request->module = module; - sandbox_request->args = args; - sandbox_request->sock = sock; - sandbox_request->addr = (struct sockaddr *)addr; + sandbox_request->arguments = arguments; + sandbox_request->socket_descriptor = socket_descriptor; + sandbox_request->socket_address = (struct sockaddr *)socket_address; sandbox_request->start_time = start_time; debuglog("[%p: %s]\n", sandbox_request, sandbox_request->module->name); - sandbox_deque_push(sandbox_request); + add_sandbox_request_to_global_dequeue(sandbox_request); return sandbox_request; } @@ -129,7 +131,7 @@ sbox_request_alloc(struct module *module, char *args, int sock, const struct soc * @returns the current sandbox executing on this thread **/ static inline struct sandbox * -sandbox_current(void) +get_current_sandbox(void) { return current_sandbox; } @@ -139,15 +141,15 @@ sandbox_current(void) * @param sandbox the sandbox we are setting this thread to run **/ static inline void -sandbox_current_set(struct sandbox *sandbox) +set_current_sandbox(struct sandbox *sandbox) { // FIXME: critical-section. current_sandbox = sandbox; if (sandbox == NULL) return; // Thread Local State about the Current Sandbox - sandbox_lmbase = sandbox->linear_start; - sandbox_lmbound = sandbox->linear_size; + sandbox_lmbase = sandbox->linear_memory_start; + sandbox_lmbound = sandbox->linear_memory_size; // TODO: module table or sandbox table? module_indirect_table = sandbox->module->indirect_table; } @@ -157,10 +159,10 @@ sandbox_current_set(struct sandbox *sandbox) * This includes lmbase, lmbound, and module_indirect_table */ static inline void -sandbox_current_check(void) +check_current_sandbox(void) { - struct sandbox *sandbox = sandbox_current(); - assert(sandbox && sandbox->linear_start == sandbox_lmbase && sandbox->linear_size == sandbox_lmbound); + struct sandbox *sandbox = get_current_sandbox(); + assert(sandbox && sandbox->linear_memory_start == sandbox_lmbase && sandbox->linear_memory_size == sandbox_lmbound); assert(sandbox->module->indirect_table == module_indirect_table); } @@ -170,13 +172,13 @@ sandbox_current_check(void) * @return the module of the provided sandbox */ static inline struct module * -sandbox_module(struct sandbox *sandbox) +get_sandbox_module(struct sandbox *sandbox) { if (!sandbox) return NULL; return sandbox->module; } -extern void sandbox_local_end(struct sandbox *sandbox); +extern void add_sandbox_to_completion_queue(struct sandbox *sandbox); /** * @brief Switches to the next sandbox, placing the current sandbox of the completion queue if in RETURNED state @@ -184,15 +186,15 @@ extern void sandbox_local_end(struct sandbox *sandbox); * @return void */ static inline void -sandbox_switch(struct sandbox *next_sandbox) +switch_to_sandbox(struct sandbox *next_sandbox) { arch_context_t *next_register_context = next_sandbox == NULL ? NULL : &next_sandbox->ctxt; softint_disable(); - struct sandbox *current_sandbox = sandbox_current(); + struct sandbox *current_sandbox = get_current_sandbox(); arch_context_t *current_register_context = current_sandbox == NULL ? NULL : ¤t_sandbox->ctxt; - sandbox_current_set(next_sandbox); + set_current_sandbox(next_sandbox); // If the current sandbox we're switching from is in a RETURNED state, add to completion queue - if (current_sandbox && current_sandbox->state == SANDBOX_RETURNED) sandbox_local_end(current_sandbox); + if (current_sandbox && current_sandbox->state == RETURNED) add_sandbox_to_completion_queue(current_sandbox); next_context = next_register_context; arch_context_switch(current_register_context, next_register_context); softint_enable(); @@ -203,35 +205,35 @@ sandbox_switch(struct sandbox *next_sandbox) * @return the arguments of the current sandbox */ static inline char * -sandbox_args(void) +get_current_sandbox_arguments(void) { - struct sandbox *sandbox = sandbox_current(); - return (char *)sandbox->args; + struct sandbox *sandbox = get_current_sandbox(); + return (char *)sandbox->arguments; } -void * sandbox_run_func(void *data); -struct sandbox *sandbox_schedule(int interrupt); -void sandbox_block(void); -void sandbox_wakeup(sandbox_t *sb); -// called in sandbox_entry() before and after fn() execution +void * sandbox_worker_main(void *data); +struct sandbox *get_next_sandbox_from_local_run_queue(int interrupt); +void block_current_sandbox(void); +void wakeup_sandbox(sandbox_t *sb); +// called in sandbox_main() before and after fn() execution // for http request/response processing using uvio void sandbox_block_http(void); void sandbox_response(void); // should be the entry-point for each sandbox so it can do per-sandbox mem/etc init. -// should have been called with stack allocated and sandbox_current() set! -void sandbox_entry(void); -void sandbox_exit(void); +// should have been called with stack allocated and get_current_sandbox() set! +void sandbox_main(void); +void exit_current_sandbox(void); extern struct deque_sandbox *global_deque; extern pthread_mutex_t global_deque_mutex; /** * Pushes a sandbox request to the global deque - * @para + * @param sandbox_request **/ static inline int -sandbox_deque_push(sbox_request_t *sandbox_request) +add_sandbox_request_to_global_dequeue(sandbox_request_t *sandbox_request) { int return_code; @@ -246,8 +248,12 @@ sandbox_deque_push(sbox_request_t *sandbox_request) return return_code; } +/** + * Pops a sandbox request from the global deque + * @param sandbox_request the pointer which we want to set to the sandbox request + **/ static inline int -sandbox_deque_pop(sbox_request_t **sandbox_request) +pop_sandbox_request_from_global_dequeue(sandbox_request_t **sandbox_request) { int return_code; @@ -258,20 +264,20 @@ sandbox_deque_pop(sbox_request_t **sandbox_request) #if NCORES == 1 pthread_mutex_unlock(&global_deque_mutex); #endif - return return_code; } /** + * TODO: What does this do? * @returns A Sandbox Request or NULL **/ -static inline sbox_request_t * -sandbox_deque_steal(void) +static inline sandbox_request_t * +steal_sandbox_request_from_global_dequeue(void) { - sbox_request_t *sandbox_request = NULL; + sandbox_request_t *sandbox_request = NULL; #if NCORES == 1 - sandbox_deque_pop(&sandbox_request); + pop_sandbox_request_from_global_dequeue(&sandbox_request); #else // TODO: check! is there a sandboxing thread on same core as udp-server thread? int r = deque_steal_sandbox(global_deque, &sandbox_request); @@ -281,83 +287,93 @@ sandbox_deque_steal(void) return sandbox_request; } +/** + * Initializes and returns an IO handle on the current sandbox ready for use + * @return index of handle we preopened or -1 if all handles are exhausted + **/ static inline int -io_handle_preopen(void) +initialize_io_handle_in_current_sandbox(void) { - struct sandbox *sandbox = sandbox_current(); - int i; - for (i = 0; i < SBOX_MAX_OPEN; i++) { - if (sandbox->handles[i].fd < 0) break; + struct sandbox *sandbox = get_current_sandbox(); + int handle_index; + for (handle_index = 0; handle_index < SBOX_MAX_OPEN; handle_index++) { + if (sandbox->handles[handle_index].file_descriptor < 0) break; } - if (i == SBOX_MAX_OPEN) return -1; - sandbox->handles[i].fd = SBOX_PREOPEN_MAGIC; - memset(&sandbox->handles[i].uvh, 0, sizeof(union uv_any_handle)); - return i; + if (handle_index == SBOX_MAX_OPEN) return -1; + sandbox->handles[handle_index].file_descriptor = SBOX_PREOPEN_MAGIC; + memset(&sandbox->handles[handle_index].libuv_handle, 0, sizeof(union uv_any_handle)); + return handle_index; } +/** + * Initializes and returns an IO handle on the current sandbox ready for use + * @param file_descriptor what we'll set on the IO handle after initialization + * @return index of handle we preopened or -1 if all handles are exhausted + **/ static inline int -io_handle_open(int fd) +initialize_io_handle_and_set_file_descriptor_in_current_sandbox(int file_descriptor) { - struct sandbox *sandbox = sandbox_current(); - if (fd < 0) return fd; - int i = io_handle_preopen(); - sandbox->handles[i].fd = fd; // well, per sandbox.. so synchronization necessary! - return i; + struct sandbox *sandbox = get_current_sandbox(); + if (file_descriptor < 0) return file_descriptor; + int handle_index = initialize_io_handle_in_current_sandbox(); + if (handle_index != -1) sandbox->handles[handle_index].file_descriptor = file_descriptor; // well, per sandbox.. so synchronization necessary! + return handle_index; } /** * Sets the file descriptor of the sandbox's ith io_handle - * Returns error condition if the fd to set does not contain sandbox preopen magin - * @param idx index of the sandbox handles we want to set - * @param fd the file descripter we want to set it to - * @returns the idx that was set or -1 in case of error + * Returns error condition if the file_descriptor to set does not contain sandbox preopen magin + * @param handle_index index of the sandbox handles we want to set + * @param file_descriptor the file descripter we want to set it to + * @returns the index that was set or -1 in case of error **/ static inline int -io_handle_preopen_set(int idx, int fd) +set_current_sandbox_file_descriptor(int handle_index, int file_descriptor) { - struct sandbox *sandbox = sandbox_current(); - if (idx >= SBOX_MAX_OPEN || idx < 0) return -1; - if (fd < 0 || sandbox->handles[idx].fd != SBOX_PREOPEN_MAGIC) return -1; - sandbox->handles[idx].fd = fd; - return idx; + struct sandbox *sandbox = get_current_sandbox(); + if (handle_index >= SBOX_MAX_OPEN || handle_index < 0) return -1; + if (file_descriptor < 0 || sandbox->handles[handle_index].file_descriptor != SBOX_PREOPEN_MAGIC) return -1; + sandbox->handles[handle_index].file_descriptor = file_descriptor; + return handle_index; } /** * Get the file descriptor of the sandbox's ith io_handle - * @param idx index into the sandbox's handles table - * @returns any libuv handle + * @param handle_index index into the sandbox's handles table + * @returns file descriptor **/ static inline int -io_handle_fd(int idx) +get_current_sandbox_file_descriptor(int handle_index) { - struct sandbox *sandbox = sandbox_current(); - if (idx >= SBOX_MAX_OPEN || idx < 0) return -1; - return sandbox->handles[idx].fd; + struct sandbox *sandbox = get_current_sandbox(); + if (handle_index >= SBOX_MAX_OPEN || handle_index < 0) return -1; + return sandbox->handles[handle_index].file_descriptor; } /** * Close the sandbox's ith io_handle - * @param idx index of the handle to close + * @param handle_index index of the handle to close **/ static inline void -io_handle_close(int idx) +close_current_sandbox_file_descriptor(int handle_index) { - struct sandbox *sandbox = sandbox_current(); - if (idx >= SBOX_MAX_OPEN || idx < 0) return; - sandbox->handles[idx].fd = -1; + struct sandbox *sandbox = get_current_sandbox(); + if (handle_index >= SBOX_MAX_OPEN || handle_index < 0) return; + // TODO: Do we actually need to call some sort of close function here? + sandbox->handles[handle_index].file_descriptor = -1; } /** * Get the Libuv handle located at idx of the sandbox ith io_handle - * @param idx index of the handle containing uvh??? + * @param handle_index index of the handle containing libuv_handle??? * @returns any libuv handle **/ static inline union uv_any_handle * -io_handle_uv_get(int idx) +get_current_sandbox_libuv_handle(int handle_index) { - struct sandbox *sandbox = sandbox_current(); - if (idx >= SBOX_MAX_OPEN || idx < 0) return NULL; - return &sandbox->handles[idx].uvh; + struct sandbox *sandbox = get_current_sandbox(); + if (handle_index >= SBOX_MAX_OPEN || handle_index < 0) return NULL; + return &sandbox->handles[handle_index].libuv_handle; } #endif /* SFRT_SANDBOX_H */ diff --git a/runtime/src/http.c b/runtime/src/http.c index d573cfc6..327f5167 100644 --- a/runtime/src/http.c +++ b/runtime/src/http.c @@ -38,7 +38,7 @@ http_request_body_get_sb(struct sandbox *sandbox, char **body) int http_response_header_set_sb(struct sandbox *sandbox, char *header, int length) { - // by now, req_resp_data should only be containing response! + // by now, request_response_data should only be containing response! struct http_response *http_response = &sandbox->http_response; assert(http_response->header_count < HTTP_HEADERS_MAX); @@ -197,7 +197,7 @@ http_on_header_field(http_parser *parser, const char *at, size_t length) assert(length < HTTP_HEADER_MAXSZ); http_request->last_was_value = 0; - http_request->headers[http_request->header_count - 1].key = (char *)at; // it is from the sandbox's req_resp_data, should persist. + http_request->headers[http_request->header_count - 1].key = (char *)at; // it is from the sandbox's request_response_data, should persist. return 0; } @@ -220,7 +220,7 @@ http_on_header_value(http_parser *parser, const char *at, size_t length) assert(http_request->header_count <= HTTP_HEADERS_MAX); assert(length < HTTP_HEADERVAL_MAXSZ); - http_request->headers[http_request->header_count - 1].value = (char *)at; // it is from the sandbox's req_resp_data, should persist. + http_request->headers[http_request->header_count - 1].value = (char *)at; // it is from the sandbox's request_response_data, should persist. return 0; } @@ -300,9 +300,9 @@ http_init(void) } /** - * Run the http-parser on the sandbox's req_resp_data using the configured settings global + * Run the http-parser on the sandbox's request_response_data using the configured settings global * @param sandbox the sandbox containing the req_resp data that we want to parse - * @param length The size of the req_resp_data that we want to parse + * @param length The size of the request_response_data that we want to parse * @returns 0 * * Global State: settings @@ -310,7 +310,7 @@ http_init(void) int http_request_parse_sb(struct sandbox *sandbox, size_t length) { - // TODO: Why is our start address sandbox->req_resp_data + sandbox->rr_data_len? - http_parser_execute(&sandbox->http_parser, &settings, sandbox->req_resp_data + sandbox->rr_data_len, length); + // TODO: Why is our start address sandbox->request_response_data + sandbox->request_response_data_length? + http_parser_execute(&sandbox->http_parser, &settings, sandbox->request_response_data + sandbox->request_response_data_length, length); return 0; } diff --git a/runtime/src/libc/uvio.c b/runtime/src/libc/uvio.c index 5711c6cc..11039546 100644 --- a/runtime/src/libc/uvio.c +++ b/runtime/src/libc/uvio.c @@ -33,7 +33,7 @@ void stub_init(i32 offset) { // What program name will we put in the auxiliary vectors - char *program_name = sandbox_current()->module->name; + char *program_name = get_current_sandbox()->module->name; // Copy the program name into WASM accessible memory i32 program_name_offset = offset; strcpy(get_memory_ptr_for_runtime(offset, sizeof(program_name)), program_name); @@ -64,7 +64,7 @@ stub_init(i32 offset) i32 env_vec_offset = offset; memcpy(get_memory_ptr_for_runtime(env_vec_offset, sizeof(env_vec)), env_vec, sizeof(env_vec)); - module_libc_init(sandbox_current()->module, env_vec_offset, program_name_offset); + module_libc_init(get_current_sandbox()->module, env_vec_offset, program_name_offset); } // Emulated syscall implementations @@ -88,14 +88,14 @@ uv_fs_get_type(uv_fs_t *req) #define UV_FS_REQ_INIT() \ { \ - .data = sandbox_current(), .result = 0 \ + .data = get_current_sandbox(), .result = 0 \ } static void wasm_fs_callback(uv_fs_t *req) { debuglog("[%p]\n", req->data); - sandbox_wakeup((sandbox_t *)req->data); + wakeup_sandbox((sandbox_t *)req->data); } // We define our own syscall numbers, because WASM uses x86_64 values even on systems that are not x86_64 @@ -105,7 +105,7 @@ wasm_read(i32 filedes, i32 buf_offset, i32 nbyte) { if (filedes == 0) { char * buffer = get_memory_ptr_void(buf_offset, nbyte); - struct sandbox * s = sandbox_current(); + struct sandbox * s = get_current_sandbox(); struct http_request *r = &s->http_request; if (r->body_length <= 0) return 0; int l = nbyte > r->body_length ? r->body_length : nbyte; @@ -114,7 +114,7 @@ wasm_read(i32 filedes, i32 buf_offset, i32 nbyte) r->body_length -= l; return l; } - int f = io_handle_fd(filedes); + int f = get_current_sandbox_file_descriptor(filedes); // TODO: read on other file types uv_fs_t req = UV_FS_REQ_INIT(); char * buffer = get_memory_ptr_void(buf_offset, nbyte); @@ -122,7 +122,7 @@ wasm_read(i32 filedes, i32 buf_offset, i32 nbyte) debuglog("[%p] start[%d:%d, n%d]\n", uv_fs_get_data(&req), filedes, f, nbyte); uv_buf_t bufv = uv_buf_init(buffer, nbyte); uv_fs_read(runtime_uvio(), &req, f, &bufv, 1, -1, wasm_fs_callback); - sandbox_block(); + block_current_sandbox(); int ret = uv_fs_get_result(&req); debuglog("[%p] end[%d]\n", uv_fs_get_data(&req), ret); @@ -133,27 +133,27 @@ wasm_read(i32 filedes, i32 buf_offset, i32 nbyte) #define SYS_WRITE 1 i32 -wasm_write(i32 fd, i32 buf_offset, i32 buf_size) +wasm_write(i32 file_descriptor, i32 buf_offset, i32 buf_size) { - if (fd == 1 || fd == 2) { + if (file_descriptor == 1 || file_descriptor == 2) { char * buffer = get_memory_ptr_void(buf_offset, buf_size); - struct sandbox *s = sandbox_current(); - int l = s->module->max_response_size - s->rr_data_len; + struct sandbox *s = get_current_sandbox(); + int l = s->module->max_response_size - s->request_response_data_length; l = l > buf_size ? buf_size : l; if (l == 0) return 0; - memcpy(s->req_resp_data + s->rr_data_len, buffer, l); - s->rr_data_len += l; + memcpy(s->request_response_data + s->request_response_data_length, buffer, l); + s->request_response_data_length += l; return l; } - int f = io_handle_fd(fd); + int f = get_current_sandbox_file_descriptor(file_descriptor); // TODO: read on other file types uv_fs_t req = UV_FS_REQ_INIT(); char * buffer = get_memory_ptr_void(buf_offset, buf_size); uv_buf_t bufv = uv_buf_init(buffer, buf_size); uv_fs_write(runtime_uvio(), &req, f, &bufv, 1, -1, wasm_fs_callback); - sandbox_block(); + block_current_sandbox(); int ret = uv_fs_get_result(&req); uv_fs_req_cleanup(&req); @@ -184,7 +184,7 @@ wasm_open(i32 path_off, i32 flags, i32 mode) uv_fs_t req = UV_FS_REQ_INIT(); char * path = get_memory_string(path_off); - int iofd = io_handle_preopen(); + int iofd = initialize_io_handle_in_current_sandbox(); if (iofd < 0) return -1; i32 modified_flags = 0; if (flags & WO_RDONLY) modified_flags |= O_RDONLY; @@ -196,29 +196,29 @@ wasm_open(i32 path_off, i32 flags, i32 mode) debuglog("[%p] start[%s:%d:%d]\n", uv_fs_get_data(&req), path, flags, modified_flags); uv_fs_open(runtime_uvio(), &req, path, modified_flags, mode, wasm_fs_callback); - sandbox_block(); + block_current_sandbox(); int ret = uv_fs_get_result(&req); debuglog("[%p] end[%d]\n", uv_fs_get_data(&req), ret); uv_fs_req_cleanup(&req); if (ret < 0) - io_handle_close(iofd); + close_current_sandbox_file_descriptor(iofd); else - io_handle_preopen_set(iofd, ret); + set_current_sandbox_file_descriptor(iofd, ret); return iofd; } #define SYS_CLOSE 3 i32 -wasm_close(i32 fd) +wasm_close(i32 file_descriptor) { - if (fd >= 0 && fd <= 2) { return 0; } - struct sandbox * c = sandbox_current(); - int d = io_handle_fd(fd); - union uv_any_handle *h = io_handle_uv_get(fd); + if (file_descriptor >= 0 && file_descriptor <= 2) { return 0; } + struct sandbox * c = get_current_sandbox(); + int d = get_current_sandbox_file_descriptor(file_descriptor); + union uv_any_handle *h = get_current_sandbox_libuv_handle(file_descriptor); uv_handle_type type = ((uv_handle_t *)h)->type; - debuglog("[%p] [%d,%d]\n", c, fd, d); + debuglog("[%p] [%d,%d]\n", c, file_descriptor, d); if (type == UV_TCP) { debuglog("[%p] close tcp\n", c); @@ -231,14 +231,14 @@ wasm_close(i32 fd) } uv_fs_t req = UV_FS_REQ_INIT(); - debuglog("[%p] file[%d,%d]\n", uv_fs_get_data(&req), fd, d); + debuglog("[%p] file[%d,%d]\n", uv_fs_get_data(&req), file_descriptor, d); uv_fs_close(runtime_uvio(), &req, d, wasm_fs_callback); - sandbox_block(); + block_current_sandbox(); int ret = uv_fs_get_result(&req); debuglog("[%p] end[%d]\n", uv_fs_get_data(&req), ret); uv_fs_req_cleanup(&req); - if (ret == 0) io_handle_close(fd); + if (ret == 0) close_current_sandbox_file_descriptor(file_descriptor); return ret; } @@ -344,7 +344,7 @@ wasm_fstat(i32 filedes, i32 stat_offset) struct wasm_stat *stat_ptr = get_memory_ptr_void(stat_offset, sizeof(struct wasm_stat)); struct stat stat; - int d = io_handle_fd(filedes); + int d = get_current_sandbox_file_descriptor(filedes); i32 res = fstat(d, &stat); if (res == -1) return -errno; @@ -434,7 +434,7 @@ wasm_lstat(i32 path_str_offset, i32 stat_offset) i32 wasm_lseek(i32 filedes, i32 file_offset, i32 whence) { - int d = io_handle_fd(filedes); + int d = get_current_sandbox_file_descriptor(filedes); i32 res = (i32)lseek(d, file_offset, whence); if (res == -1) return -errno; @@ -444,10 +444,10 @@ wasm_lseek(i32 filedes, i32 file_offset, i32 whence) #define SYS_MMAP 9 u32 -wasm_mmap(i32 addr, i32 len, i32 prot, i32 flags, i32 fd, i32 offset) +wasm_mmap(i32 addr, i32 len, i32 prot, i32 flags, i32 file_descriptor, i32 offset) { - int d = io_handle_fd(fd); - if (fd >= 0) assert(d >= 0); + int d = get_current_sandbox_file_descriptor(file_descriptor); + if (file_descriptor >= 0) assert(d >= 0); if (addr != 0) { printf("parameter void *addr is not supported!\n"); assert(0); @@ -476,9 +476,9 @@ wasm_mmap(i32 addr, i32 len, i32 prot, i32 flags, i32 fd, i32 offset) #define SYS_IOCTL 16 i32 -wasm_ioctl(i32 fd, i32 request, i32 data_offet) +wasm_ioctl(i32 file_descriptor, i32 request, i32 data_offet) { - // int d = io_handle_fd(fd); + // int d = get_current_sandbox_file_descriptor(file_descriptor); // musl libc does some ioctls to stdout, so just allow these to silently go through // FIXME: The above is idiotic // assert(d == 1); @@ -492,13 +492,13 @@ struct wasm_iovec { }; i32 -wasm_readv(i32 fd, i32 iov_offset, i32 iovcnt) +wasm_readv(i32 file_descriptor, i32 iov_offset, i32 iovcnt) { - if (fd == 0) { + if (file_descriptor == 0) { // both 1 and 2 go to client. int len = 0; struct wasm_iovec * iov = get_memory_ptr_void(iov_offset, iovcnt * sizeof(struct wasm_iovec)); - struct sandbox * s = sandbox_current(); + struct sandbox * s = get_current_sandbox(); struct http_request *r = &s->http_request; if (r->body_length <= 0) return 0; for (int i = 0; i < iovcnt; i++) { @@ -516,7 +516,7 @@ wasm_readv(i32 fd, i32 iov_offset, i32 iovcnt) } // TODO: read on other file types int gret = 0; - int d = io_handle_fd(fd); + int d = get_current_sandbox_file_descriptor(file_descriptor); struct wasm_iovec *iov = get_memory_ptr_void(iov_offset, iovcnt * sizeof(struct wasm_iovec)); for (int i = 0; i < iovcnt; i += RDWR_VEC_MAX) { @@ -528,9 +528,9 @@ wasm_readv(i32 fd, i32 iov_offset, i32 iovcnt) bufs[j] = uv_buf_init(get_memory_ptr_void(iov[i + j].base_offset, iov[i + j].len), iov[i + j].len); } - debuglog("[%p] start[%d,%d, n%d:%d]\n", uv_fs_get_data(&req), fd, d, i, j); + debuglog("[%p] start[%d,%d, n%d:%d]\n", uv_fs_get_data(&req), file_descriptor, d, i, j); uv_fs_read(runtime_uvio(), &req, d, bufs, j, -1, wasm_fs_callback); - sandbox_block(); + block_current_sandbox(); int ret = uv_fs_get_result(&req); debuglog("[%p] end[%d]\n", uv_fs_get_data(&req), ret); @@ -545,24 +545,24 @@ wasm_readv(i32 fd, i32 iov_offset, i32 iovcnt) #define SYS_WRITEV 20 i32 -wasm_writev(i32 fd, i32 iov_offset, i32 iovcnt) +wasm_writev(i32 file_descriptor, i32 iov_offset, i32 iovcnt) { - struct sandbox *c = sandbox_current(); - if (fd == 1 || fd == 2) { + struct sandbox *c = get_current_sandbox(); + if (file_descriptor == 1 || file_descriptor == 2) { // both 1 and 2 go to client. int len = 0; struct wasm_iovec *iov = get_memory_ptr_void(iov_offset, iovcnt * sizeof(struct wasm_iovec)); for (int i = 0; i < iovcnt; i++) { char *b = get_memory_ptr_void(iov[i].base_offset, iov[i].len); - memcpy(c->req_resp_data + c->rr_data_len, b, iov[i].len); - c->rr_data_len += iov[i].len; + memcpy(c->request_response_data + c->request_response_data_length, b, iov[i].len); + c->request_response_data_length += iov[i].len; len += iov[i].len; } return len; } // TODO: read on other file types - int d = io_handle_fd(fd); + int d = get_current_sandbox_file_descriptor(file_descriptor); int gret = 0; struct wasm_iovec *iov = get_memory_ptr_void(iov_offset, iovcnt * sizeof(struct wasm_iovec)); @@ -575,9 +575,9 @@ wasm_writev(i32 fd, i32 iov_offset, i32 iovcnt) bufs[j] = uv_buf_init(get_memory_ptr_void(iov[i + j].base_offset, iov[i + j].len), iov[i + j].len); } - debuglog("[%p] start[%d,%d, n%d:%d]\n", uv_fs_get_data(&req), fd, d, i, j); + debuglog("[%p] start[%d,%d, n%d:%d]\n", uv_fs_get_data(&req), file_descriptor, d, i, j); uv_fs_write(runtime_uvio(), &req, d, bufs, j, -1, wasm_fs_callback); - sandbox_block(); + block_current_sandbox(); int ret = uv_fs_get_result(&req); debuglog("[%p] end[%d]\n", uv_fs_get_data(&req), ret); @@ -617,9 +617,9 @@ wasm_getpid() #define SYS_FCNTL 72 u32 -wasm_fcntl(u32 fd, u32 cmd, u32 arg_or_lock_ptr) +wasm_fcntl(u32 file_descriptor, u32 cmd, u32 arg_or_lock_ptr) { - int d = io_handle_fd(fd); + int d = get_current_sandbox_file_descriptor(file_descriptor); switch (cmd) { case WF_SETFD: // return fcntl(d, F_SETFD, arg_or_lock_ptr); @@ -633,13 +633,13 @@ wasm_fcntl(u32 fd, u32 cmd, u32 arg_or_lock_ptr) #define SYS_FSYNC 74 u32 -wasm_fsync(u32 fd) +wasm_fsync(u32 file_descriptor) { - int d = io_handle_fd(fd); + int d = get_current_sandbox_file_descriptor(file_descriptor); uv_fs_t req = UV_FS_REQ_INIT(); - debuglog("[%p] start[%d,%d]\n", uv_fs_get_data(&req), fd, d); + debuglog("[%p] start[%d,%d]\n", uv_fs_get_data(&req), file_descriptor, d); uv_fs_fsync(runtime_uvio(), &req, d, wasm_fs_callback); - sandbox_block(); + block_current_sandbox(); int ret = uv_fs_get_result(&req); debuglog("[%p] end[%d]\n", uv_fs_get_data(&req), ret); @@ -667,7 +667,7 @@ wasm_unlink(u32 path_str_offset) uv_fs_t req = UV_FS_REQ_INIT(); debuglog("[%p] start[%s]\n", uv_fs_get_data(&req), str); uv_fs_unlink(runtime_uvio(), &req, str, wasm_fs_callback); - sandbox_block(); + block_current_sandbox(); int ret = uv_fs_get_result(&req); debuglog("[%p] end[%d]\n", uv_fs_get_data(&req), ret); @@ -733,13 +733,13 @@ wasm_exit_group(i32 status) #define SYS_FCHOWN 93 i32 -wasm_fchown(i32 fd, u32 owner, u32 group) +wasm_fchown(i32 file_descriptor, u32 owner, u32 group) { - int d = io_handle_fd(fd); + int d = get_current_sandbox_file_descriptor(file_descriptor); uv_fs_t req = UV_FS_REQ_INIT(); - debuglog("[%p] start[%d,%d]\n", uv_fs_get_data(&req), fd, d); + debuglog("[%p] start[%d,%d]\n", uv_fs_get_data(&req), file_descriptor, d); uv_fs_fchown(runtime_uvio(), &req, d, owner, group, wasm_fs_callback); - sandbox_block(); + block_current_sandbox(); int ret = uv_fs_get_result(&req); debuglog("[%p] end[%d]\n", uv_fs_get_data(&req), ret); @@ -760,8 +760,8 @@ wasm_connection_callback(uv_stream_t *srv, int status) { sandbox_t *s = srv->data; debuglog(" [%p]\n", s); - s->retval = status; - sandbox_wakeup(s); + s->return_value = status; + wakeup_sandbox(s); } static void @@ -770,19 +770,19 @@ wasm_connect_callback(uv_connect_t *req, int status) // TODO: how do we use the handle in uv_connect_t ?? sandbox_t *s = req->data; debuglog(" [%p]\n", s); - s->retval = status; - sandbox_wakeup(s); + s->return_value = status; + wakeup_sandbox(s); } i32 wasm_socket(i32 domain, i32 type, i32 protocol) { - struct sandbox *c = sandbox_current(); - int pfd = io_handle_preopen(), fd = -1; + struct sandbox *c = get_current_sandbox(); + int pfd = initialize_io_handle_in_current_sandbox(), file_descriptor = -1; // TODO: use domain, type and protocol in libuv? debuglog("[%p] => %d %d %d\n", c, domain, type, protocol); if (pfd < 0) return pfd; - union uv_any_handle *h = io_handle_uv_get(pfd); + union uv_any_handle *h = get_current_sandbox_libuv_handle(pfd); if (type & SOCK_DGRAM) { uv_udp_t *uh = (uv_udp_t *)h; @@ -804,10 +804,10 @@ wasm_socket(i32 domain, i32 type, i32 protocol) i32 wasm_connect(i32 sockfd, i32 sockaddr_offset, i32 addrlen) { - struct sandbox *c = sandbox_current(); - int fd = io_handle_fd(sockfd); - debuglog("[%p] [%d, %d]\n", c, sockfd, fd); - union uv_any_handle *h = io_handle_uv_get(sockfd); + struct sandbox *c = get_current_sandbox(); + int file_descriptor = get_current_sandbox_file_descriptor(sockfd); + debuglog("[%p] [%d, %d]\n", c, sockfd, file_descriptor); + union uv_any_handle *h = get_current_sandbox_libuv_handle(sockfd); uv_handle_type t = ((uv_handle_t *)h)->type; if (t == UV_TCP) { @@ -815,10 +815,10 @@ wasm_connect(i32 sockfd, i32 sockaddr_offset, i32 addrlen) debuglog("[%p] connect\n", c); int r = uv_tcp_connect(&req, (uv_tcp_t *)h, get_memory_ptr_void(sockaddr_offset, addrlen), wasm_connect_callback); - sandbox_block(); + block_current_sandbox(); - debuglog("[%p] %d\n", c, c->retval); - return c->retval; + debuglog("[%p] %d\n", c, c->return_value); + return c->return_value; } else if (t == UV_UDP) { debuglog(" UDP connect not implemented!\n"); // TODO: this api is in the doc online but not in the libuv installed.. perhaps update?? @@ -834,28 +834,28 @@ wasm_accept(i32 sockfd, i32 sockaddr_offset, i32 addrlen_offset) { // what do we do with the sockaddr ???? socklen_t * addrlen = get_memory_ptr_void(addrlen_offset, sizeof(socklen_t)); - struct sockaddr * addr = get_memory_ptr_void(sockaddr_offset, *addrlen); - union uv_any_handle *s = io_handle_uv_get(sockfd); - int cfd = io_handle_preopen(); + struct sockaddr * socket_address = get_memory_ptr_void(sockaddr_offset, *addrlen); + union uv_any_handle *s = get_current_sandbox_libuv_handle(sockfd); + int cfd = initialize_io_handle_in_current_sandbox(); if (cfd < 0) return -1; - struct sandbox *c = sandbox_current(); - debuglog("[%p] [%d, %d]\n", c, sockfd, io_handle_fd(sockfd)); + struct sandbox *c = get_current_sandbox(); + debuglog("[%p] [%d, %d]\n", c, sockfd, get_current_sandbox_file_descriptor(sockfd)); // assert so we can look into whether we need to implement UDP or others.. assert(((uv_handle_t *)s)->type == UV_TCP); - union uv_any_handle *h = io_handle_uv_get(cfd); + union uv_any_handle *h = get_current_sandbox_libuv_handle(cfd); uv_tcp_init(runtime_uvio(), (uv_tcp_t *)h); debuglog("[%p] tcp init %d\n", c, cfd); int r = uv_accept((uv_stream_t *)s, (uv_stream_t *)h); if (r < 0) return r; // TODO: if accept fails, what do we do with the preopened handle? - // if (r < 0) io_handle_close(cfd); + // if (r < 0) close_current_sandbox_file_descriptor(cfd); // we've to also remove it from the runtime loop?? int r2 = -1, f = -1; r2 = uv_fileno((uv_handle_t *)h, &f); if (r2 < 0 || f < 0) assert(0); - io_handle_preopen_set(cfd, f); + set_current_sandbox_file_descriptor(cfd, f); debuglog("[%p] done[%d,%d]\n", c, cfd, f); return cfd; @@ -864,30 +864,30 @@ wasm_accept(i32 sockfd, i32 sockaddr_offset, i32 addrlen_offset) i32 wasm_bind(i32 sockfd, i32 sockaddr_offset, i32 addrlen) { - struct sandbox *c = sandbox_current(); - int fd = io_handle_fd(sockfd); - debuglog("[%p] [%d,%d]\n", c, sockfd, fd); - union uv_any_handle *h = io_handle_uv_get(sockfd); + struct sandbox *c = get_current_sandbox(); + int file_descriptor = get_current_sandbox_file_descriptor(sockfd); + debuglog("[%p] [%d,%d]\n", c, sockfd, file_descriptor); + union uv_any_handle *h = get_current_sandbox_libuv_handle(sockfd); uv_handle_type t = ((uv_handle_t *)h)->type; if (t == UV_TCP) { debuglog("[%p] tcp\n", c); int r1 = uv_tcp_bind((uv_tcp_t *)h, get_memory_ptr_void(sockaddr_offset, addrlen), 0 /* TODO: flags */); - if (fd == SBOX_PREOPEN_MAGIC) { + if (file_descriptor == SBOX_PREOPEN_MAGIC) { int r2 = -1, f = -1; r2 = uv_fileno((uv_handle_t *)h, &f); - debuglog("[%p] [%d,%d]\n", c, f, fd); - io_handle_preopen_set(sockfd, f); + debuglog("[%p] [%d,%d]\n", c, f, file_descriptor); + set_current_sandbox_file_descriptor(sockfd, f); } return r1; } else if (t == UV_UDP) { debuglog("[%p] udp\n", c); int r1 = uv_udp_bind((uv_udp_t *)h, get_memory_ptr_void(sockaddr_offset, addrlen), 0 /* TODO: flags */); - if (fd == SBOX_PREOPEN_MAGIC) { + if (file_descriptor == SBOX_PREOPEN_MAGIC) { int r2 = -1, f = -1; r2 = uv_fileno((uv_handle_t *)h, &f); - debuglog("[%p] [%d,%d]\n", c, f, fd); - io_handle_preopen_set(sockfd, f); + debuglog("[%p] [%d,%d]\n", c, f, file_descriptor); + set_current_sandbox_file_descriptor(sockfd, f); } return r1; } @@ -899,20 +899,20 @@ wasm_bind(i32 sockfd, i32 sockaddr_offset, i32 addrlen) i32 wasm_listen(i32 sockfd, i32 backlog) { - struct sandbox * c = sandbox_current(); - union uv_any_handle *h = io_handle_uv_get(sockfd); + struct sandbox * c = get_current_sandbox(); + union uv_any_handle *h = get_current_sandbox_libuv_handle(sockfd); assert(c == (struct sandbox *)(((uv_tcp_t *)h)->data)); - debuglog("[%p] [%d,%d]\n", c, sockfd, io_handle_fd(sockfd)); + debuglog("[%p] [%d,%d]\n", c, sockfd, get_current_sandbox_file_descriptor(sockfd)); uv_handle_type t = ((uv_handle_t *)h)->type; // assert so we can look into whether we need to implement UDP or others.. assert(t == UV_TCP); int r = uv_listen((uv_stream_t *)h, backlog, wasm_connection_callback); - sandbox_block(); + block_current_sandbox(); - debuglog("[%p] %d\n", c, c->retval); - return c->retval; + debuglog("[%p] %d\n", c, c->return_value); + return c->return_value; } #define SYS_SENDTO 44 @@ -924,56 +924,56 @@ wasm_read_callback(uv_stream_t *s, ssize_t nread, const uv_buf_t *buffer) struct sandbox *c = s->data; debuglog("[%p] %ld %p\n", c, nread, buffer); - if (nread < 0) c->retval = -EIO; - c->read_len = nread; - debuglog("[%p] %ld\n", c, c->read_len); + if (nread < 0) c->return_value = -EIO; + c->read_length = nread; + debuglog("[%p] %ld\n", c, c->read_length); uv_read_stop(s); - sandbox_wakeup(c); + wakeup_sandbox(c); } void wasm_write_callback(uv_write_t *req, int status) { struct sandbox *c = req->data; - c->retval = status; + c->return_value = status; debuglog("[%p] %d\n", c, status); - sandbox_wakeup(c); + wakeup_sandbox(c); } void -wasm_udp_recv_callback(uv_udp_t *h, ssize_t nread, const uv_buf_t *buffer, const struct sockaddr *addr, unsigned flags) +wasm_udp_recv_callback(uv_udp_t *h, ssize_t nread, const uv_buf_t *buffer, const struct sockaddr *socket_address, unsigned flags) { struct sandbox *c = h->data; debuglog("[%p] %ld %p\n", c, nread, buffer); - if (nread < 0) c->retval = -EIO; - c->read_len = nread; - debuglog("[%p] %ld\n", c, c->read_len); + if (nread < 0) c->return_value = -EIO; + c->read_length = nread; + debuglog("[%p] %ld\n", c, c->read_length); uv_udp_recv_stop(h); - sandbox_wakeup(c); + wakeup_sandbox(c); } void wasm_udp_send_callback(uv_udp_send_t *req, int status) { struct sandbox *c = req->data; - c->retval = status; + c->return_value = status; debuglog("[%p] %d\n", c, status); - sandbox_wakeup(c); + wakeup_sandbox(c); } i32 -wasm_sendto(i32 fd, i32 buff_offset, i32 len, i32 flags, i32 sockaddr_offset, i32 sockaddr_len) +wasm_sendto(i32 file_descriptor, i32 buff_offset, i32 len, i32 flags, i32 sockaddr_offset, i32 sockaddr_len) { char *buffer = get_memory_ptr_void(buff_offset, len); // TODO: only support "send" api for now assert(sockaddr_len == 0); - struct sandbox * c = sandbox_current(); - union uv_any_handle *h = io_handle_uv_get(fd); + struct sandbox * c = get_current_sandbox(); + union uv_any_handle *h = get_current_sandbox_libuv_handle(file_descriptor); uv_handle_type t = ((uv_handle_t *)h)->type; - debuglog("[%p] [%d,%d]\n", c, fd, io_handle_fd(fd)); + debuglog("[%p] [%d,%d]\n", c, file_descriptor, get_current_sandbox_file_descriptor(file_descriptor)); if (t == UV_TCP) { uv_write_t req = { @@ -982,10 +982,10 @@ wasm_sendto(i32 fd, i32 buff_offset, i32 len, i32 flags, i32 sockaddr_offset, i3 uv_buf_t b = uv_buf_init(buffer, len); debuglog("[%p] tcp\n", c); int ret = uv_write(&req, (uv_stream_t *)h, &b, 1, wasm_write_callback); - sandbox_block(); + block_current_sandbox(); - debuglog("[%p] %d\n", c, c->retval); - return c->retval; + debuglog("[%p] %d\n", c, c->return_value); + return c->return_value; } else if (t == UV_UDP) { uv_udp_send_t req = { .data = c, @@ -994,10 +994,10 @@ wasm_sendto(i32 fd, i32 buff_offset, i32 len, i32 flags, i32 sockaddr_offset, i3 debuglog("[%p] udp\n", c); // TODO: sockaddr! int r = uv_udp_send(&req, (uv_udp_t *)h, &b, 1, NULL, wasm_udp_send_callback); - sandbox_block(); + block_current_sandbox(); - debuglog("[%p] %d\n", c, c->retval); - return c->retval; + debuglog("[%p] %d\n", c, c->return_value); + return c->return_value; } debuglog("[%p] unimplemented\n", c); assert(0); @@ -1010,53 +1010,53 @@ wasm_alloc_callback(uv_handle_t *h, size_t suggested, uv_buf_t *buffer) struct sandbox *s = h->data; // just let it use what is passed from caller! - buffer->base = s->read_buf; + buffer->base = s->read_buffer; buffer->len = s->read_size; } i32 -wasm_recvfrom(i32 fd, i32 buff_offset, i32 size, i32 flags, i32 sockaddr_offset, i32 socklen_offset) +wasm_recvfrom(i32 file_descriptor, i32 buff_offset, i32 size, i32 flags, i32 sockaddr_offset, i32 socklen_offset) { char * buffer = get_memory_ptr_void(buff_offset, size); socklen_t *len = get_memory_ptr_void(socklen_offset, sizeof(socklen_t)); // TODO: only support "recv" api for now assert(*len == 0); - struct sandbox * c = sandbox_current(); - union uv_any_handle *h = io_handle_uv_get(fd); + struct sandbox * c = get_current_sandbox(); + union uv_any_handle *h = get_current_sandbox_libuv_handle(file_descriptor); uv_handle_type t = ((uv_handle_t *)h)->type; - debuglog("[%p] [%d,%d]\n", c, fd, io_handle_fd(fd)); + debuglog("[%p] [%d,%d]\n", c, file_descriptor, get_current_sandbox_file_descriptor(file_descriptor)); // uv stream API are not simple wrappers on read/write.. // and there will only be one system call pending.. // so we keep the read buffer pointers in sandbox structure.. // for use in the callbacks.. - c->read_buf = buffer; + c->read_buffer = buffer; c->read_size = size; - c->read_len = 0; - c->retval = 0; + c->read_length = 0; + c->return_value = 0; // TODO: what if stream read more than what "size" is here?? if (t == UV_TCP) { ((uv_stream_t *)h)->data = c; debuglog("[%p] tcp\n", c); int r = uv_read_start((uv_stream_t *)h, wasm_alloc_callback, wasm_read_callback); - sandbox_block(); - debuglog("[%p] %d\n", c, c->retval); - if (c->retval == -EIO) { + block_current_sandbox(); + debuglog("[%p] %d\n", c, c->return_value); + if (c->return_value == -EIO) { // TODO: buffer errors?? } - if (r >= 0 && c->retval == 0) { return c->read_len; } + if (r >= 0 && c->return_value == 0) { return c->read_length; } return -EIO; } else if (t == UV_UDP) { ((uv_udp_t *)h)->data = c; debuglog("[%p] udp\n", c); int r = uv_udp_recv_start((uv_udp_t *)h, wasm_alloc_callback, wasm_udp_recv_callback); - sandbox_block(); - debuglog("[%p] %d\n", c, c->retval); - if (c->retval == -EIO) { + block_current_sandbox(); + debuglog("[%p] %d\n", c, c->return_value); + if (c->return_value == -EIO) { // TODO: buffer errors?? } - if (r >= 0 && c->retval == 0) { return c->read_len; } + if (r >= 0 && c->return_value == 0) { return c->read_length; } return -EIO; } debuglog("[%p] unimplemented\n", c); diff --git a/runtime/src/main.c b/runtime/src/main.c index a6704af5..a8c9c9d5 100644 --- a/runtime/src/main.c +++ b/runtime/src/main.c @@ -125,7 +125,7 @@ void start_worker_threads() { for (int i = 0; i < total_worker_processors; i++) { - int ret = pthread_create(&worker_threads[i], NULL, sandbox_run_func, + int ret = pthread_create(&worker_threads[i], NULL, sandbox_worker_main, (void *)&worker_threads_argument[i]); if (ret) { errno = ret; @@ -168,7 +168,7 @@ main(int argc, char **argv) set_resource_limits_to_max(); allocate_available_cores(); process_nostio(); - runtime_init(); + initialize_runtime(); debuglog("Parsing modules file [%s]\n", argv[1]); if (util_parse_modules_file_json(argv[1])) { @@ -176,6 +176,6 @@ main(int argc, char **argv) exit(-1); } - runtime_thd_init(); + initialize_listener_thread(); start_worker_threads(); } diff --git a/runtime/src/memory/64bit_nix.c b/runtime/src/memory/64bit_nix.c index 5414ea43..7d72625b 100644 --- a/runtime/src/memory/64bit_nix.c +++ b/runtime/src/memory/64bit_nix.c @@ -11,19 +11,19 @@ void alloc_linear_memory(void) { - // mmaped memory in sandbox_alloc. + // mmaped memory in allocate_sandbox. } void free_linear_memory(void *base, u32 bound, u32 max) { - // frees on sandbox_free + // frees on free_sandbox } void expand_memory(void) { - struct sandbox *sandbox = sandbox_current(); + struct sandbox *sandbox = get_current_sandbox(); // max_pages = 0 => no limit: FIXME assert((sandbox->sandbox_size + sandbox_lmbound) / WASM_PAGE_SIZE < WASM_MAX_PAGES); @@ -38,9 +38,9 @@ expand_memory(void) exit(1); } - // TODO: check sandbox->linear_max_size + // TODO: check sandbox->linear_memory_max_size sandbox_lmbound += WASM_PAGE_SIZE; - sandbox->linear_size = sandbox_lmbound; + sandbox->linear_memory_size = sandbox_lmbound; } INLINE char * diff --git a/runtime/src/runtime.c b/runtime/src/runtime.c index e200314c..683a9ef3 100644 --- a/runtime/src/runtime.c +++ b/runtime/src/runtime.c @@ -37,23 +37,12 @@ __thread arch_context_t *next_context = NULL; __thread arch_context_t base_context; // libuv i/o loop handle per sandboxing thread! -__thread uv_loop_t uvio; +__thread uv_loop_t uvio_handle; // Flag to signify if the thread is currently running callbacks in the libuv event loop static __thread unsigned int in_callback; -/** - * Append the sandbox to the local_run_queue - * @param sandbox sandbox to add - */ -static inline void -sandbox_local_run(struct sandbox *sandbox) -{ - assert(ps_list_singleton_d(sandbox)); - // fprintf(stderr, "(%d,%lu) %s: run %p, %s\n", sched_getcpu(), pthread_self(), __func__, s, - // s->module->name); - ps_list_head_append_d(&local_run_queue, sandbox); -} +static inline void add_sandbox_to_local_run_queue(struct sandbox *sandbox); /** * Pulls up to 1..n sandbox requests, allocates them as sandboxes, sets them as runnable and places them on the local @@ -61,22 +50,22 @@ sandbox_local_run(struct sandbox *sandbox) * @return the number of sandbox requests pulled */ static inline int -sandbox_pull(void) +pull_sandbox_requests_from_global_runqueue(void) { int total_sandboxes_pulled = 0; while (total_sandboxes_pulled < SBOX_PULL_MAX) { - sbox_request_t *sandbox_request; - if ((sandbox_request = sandbox_deque_steal()) == NULL) break; + sandbox_request_t *sandbox_request; + if ((sandbox_request = steal_sandbox_request_from_global_dequeue()) == NULL) break; // Actually allocate the sandbox for the requests that we've pulled - struct sandbox *sandbox = sandbox_alloc(sandbox_request->module, sandbox_request->args, - sandbox_request->sock, sandbox_request->addr, + struct sandbox *sandbox = allocate_sandbox(sandbox_request->module, sandbox_request->arguments, + sandbox_request->socket_descriptor, sandbox_request->socket_address, sandbox_request->start_time); assert(sandbox); free(sandbox_request); // Set the sandbox as runnable and place on the local runqueue - sandbox->state = SANDBOX_RUNNABLE; - sandbox_local_run(sandbox); + sandbox->state = RUNNABLE; + add_sandbox_to_local_run_queue(sandbox); total_sandboxes_pulled++; } @@ -87,7 +76,7 @@ sandbox_pull(void) * Run all outstanding events in the libuv event loop **/ void -sandbox_io_nowait(void) +execute_libuv_event_loop(void) { in_callback = 1; int n = uv_run(runtime_uvio(), UV_RUN_NOWAIT), i = 0; @@ -98,6 +87,30 @@ sandbox_io_nowait(void) in_callback = 0; } +/** + * Append the sandbox to the local_run_queue + * @param sandbox sandbox to add + */ +static inline void +add_sandbox_to_local_run_queue(struct sandbox *sandbox) +{ + assert(ps_list_singleton_d(sandbox)); + // fprintf(stderr, "(%d,%lu) %s: run %p, %s\n", sched_getcpu(), pthread_self(), __func__, s, + // s->module->name); + ps_list_head_append_d(&local_run_queue, sandbox); +} + +/** + * Removes the thread from the thread-local runqueue + * TODO: is this correct? + * @param sandbox sandbox + **/ +static inline void +remove_sandbox_from_local_run_queue(struct sandbox *sandbox) +{ + ps_list_rem_d(sandbox); +} + /** * Execute the sandbox at the head of the thread local runqueue * If the runqueue is empty, pull a fresh batch of sandbox requests, instantiate them, and then execute the new head @@ -105,14 +118,14 @@ sandbox_io_nowait(void) * @return the sandbox to execute or NULL if none are available **/ struct sandbox * -sandbox_schedule(int in_interrupt) +get_next_sandbox_from_local_run_queue(int in_interrupt) { // If the thread local runqueue is empty and we're not running in the context of an interupt, // pull a fresh batch of sandbox requests from the global queue if (ps_list_head_empty(&local_run_queue)) { // this is in an interrupt context, don't steal work here! if (in_interrupt) return NULL; - if (sandbox_pull() == 0) { + if (pull_sandbox_requests_from_global_runqueue() == 0) { // debuglog("[null: null]\n"); return NULL; } @@ -121,68 +134,56 @@ sandbox_schedule(int in_interrupt) // Execute Round Robin Scheduling Logic // Grab the sandbox at the head of the thread local runqueue, add it to the end, and return it struct sandbox *sandbox = ps_list_head_first_d(&local_run_queue, struct sandbox); - // We are assuming that any sandboxed in the SANDBOX_RETURNED state should have been pulled from the local runqueue by now! - assert(sandbox->state != SANDBOX_RETURNED); + // We are assuming that any sandboxed in the RETURNED state should have been pulled from the local runqueue by now! + assert(sandbox->state != RETURNED); ps_list_rem_d(sandbox); ps_list_head_append_d(&local_run_queue, sandbox); debuglog("[%p: %s]\n", sandbox, sandbox->module->name); return sandbox; } +/** + * Adds sandbox to the completion queue + * @param sandbox + **/ +void +add_sandbox_to_completion_queue(struct sandbox *sandbox) +{ + assert(ps_list_singleton_d(sandbox)); + ps_list_head_append_d(&local_completion_queue, sandbox); +} + + /** * @brief Remove and free n sandboxes from the thread local completion queue * @param number_to_free The number of sandboxes to free * @return void */ static inline void -sandbox_local_free(unsigned int number_to_free) +free_sandboxes_from_completion_queue(unsigned int number_to_free) { for (int i = 0; i < number_to_free; i++) { if (ps_list_head_empty(&local_completion_queue)) break; struct sandbox *sandbox = ps_list_head_first_d(&local_completion_queue, struct sandbox); if (!sandbox) break; ps_list_rem_d(sandbox); - sandbox_free(sandbox); + free_sandbox(sandbox); } } - -/** - * Tries to free a completed request, executes libuv callbacks, and then gets - * and returns the standbox at the head of the thread-local runqueue - * @return sandbox or NULL - **/ -struct sandbox * -sandbox_schedule_io(void) -{ - assert(sandbox_current() == NULL); - // Try to free one sandbox from the completion queue - sandbox_local_free(1); - // Execute libuv callbacks - if (!in_callback) sandbox_io_nowait(); - - // Get and return the sandbox at the head of the thread local runqueue - softint_disable(); - struct sandbox *sandbox = sandbox_schedule(0); - softint_enable(); - assert(sandbox == NULL || sandbox->state == SANDBOX_RUNNABLE); - return sandbox; -} - - /** * If this sandbox is blocked, mark it as runnable and add to the head of the thread-local runqueue * @param sandbox the sandbox to check and update if blocked **/ void -sandbox_wakeup(sandbox_t *sandbox) +wakeup_sandbox(sandbox_t *sandbox) { softint_disable(); debuglog("[%p: %s]\n", sandbox, sandbox->module->name); - if (sandbox->state != SANDBOX_BLOCKED) goto done; - assert(sandbox->state == SANDBOX_BLOCKED); + if (sandbox->state != BLOCKED) goto done; + assert(sandbox->state == BLOCKED); assert(ps_list_singleton_d(sandbox)); - sandbox->state = SANDBOX_RUNNABLE; + sandbox->state = RUNNABLE; ps_list_head_append_d(&local_run_queue, sandbox); done: softint_enable(); @@ -193,18 +194,18 @@ done: * Mark the currently executing sandbox as blocked, remove it from the local runqueue, and pull the sandbox at the head of the runqueue **/ void -sandbox_block(void) +block_current_sandbox(void) { assert(in_callback == 0); softint_disable(); - struct sandbox *current_sandbox = sandbox_current(); + struct sandbox *current_sandbox = get_current_sandbox(); // TODO: What is this getting removed from again? the thread-local runqueue? ps_list_rem_d(current_sandbox); - current_sandbox->state = SANDBOX_BLOCKED; - struct sandbox *next_sandbox = sandbox_schedule(0); + current_sandbox->state = BLOCKED; + struct sandbox *next_sandbox = get_next_sandbox_from_local_run_queue(0); debuglog("[%p: %next_sandbox, %p: %next_sandbox]\n", current_sandbox, current_sandbox->module->name, next_sandbox, next_sandbox ? next_sandbox->module->name : ""); softint_enable(); - sandbox_switch(next_sandbox); + switch_to_sandbox(next_sandbox); } @@ -221,7 +222,7 @@ sandbox_block_http(void) // async block! uv_run(runtime_uvio(), UV_RUN_DEFAULT); #else /* USE_HTTP_SYNC */ - sandbox_block(); + block_current_sandbox(); #endif /* USE_HTTP_UVIO */ #else assert(0); @@ -243,25 +244,25 @@ void __attribute__((noinline)) __attribute__((noreturn)) sandbox_switch_preempt( } /** - * Removes the thread from the thread-local runqueue - * TODO: is this correct? - * @param sandbox sandbox + * Tries to free a completed request, executes libuv callbacks, and then gets + * and returns the standbox at the head of the thread-local runqueue + * @return sandbox or NULL **/ -static inline void -sandbox_local_stop(struct sandbox *sandbox) +struct sandbox * +sandbox_worker_single_loop(void) { - ps_list_rem_d(sandbox); -} + assert(get_current_sandbox() == NULL); + // Try to free one sandbox from the completion queue + free_sandboxes_from_completion_queue(1); + // Execute libuv callbacks + if (!in_callback) execute_libuv_event_loop(); -/** - * Adds sandbox to the completion queue - * @param sandbox - **/ -void -sandbox_local_end(struct sandbox *sandbox) -{ - assert(ps_list_singleton_d(sandbox)); - ps_list_head_append_d(&local_completion_queue, sandbox); + // Get and return the sandbox at the head of the thread local runqueue + softint_disable(); + struct sandbox *sandbox = get_next_sandbox_from_local_run_queue(0); + softint_enable(); + assert(sandbox == NULL || sandbox->state == RUNNABLE); + return sandbox; } /** @@ -270,7 +271,7 @@ sandbox_local_end(struct sandbox *sandbox) * @param return_code - argument provided by pthread API. We set to -1 on error **/ void * -sandbox_run_func(void *return_code) +sandbox_worker_main(void *return_code) { arch_context_init(&base_context, 0, 0); @@ -282,14 +283,14 @@ sandbox_run_func(void *return_code) softint_unmask(SIGALRM); softint_unmask(SIGUSR1); #endif - uv_loop_init(&uvio); + uv_loop_init(&uvio_handle); in_callback = 0; while (true) { - struct sandbox *sandbox = sandbox_schedule_io(); + struct sandbox *sandbox = sandbox_worker_single_loop(); while (sandbox) { - sandbox_switch(sandbox); - sandbox = sandbox_schedule_io(); + switch_to_sandbox(sandbox); + sandbox = sandbox_worker_single_loop(); } } @@ -304,22 +305,22 @@ sandbox_run_func(void *return_code) * TODO: Why are we not adding to the completion queue here? That logic is commented out. **/ void -sandbox_exit(void) +exit_current_sandbox(void) { - struct sandbox *current_sandbox = sandbox_current(); + struct sandbox *current_sandbox = get_current_sandbox(); assert(current_sandbox); softint_disable(); - // Remove from the runqueue - sandbox_local_stop(current_sandbox); - current_sandbox->state = SANDBOX_RETURNED; - // free resources from "main function execution", as stack still in use. - struct sandbox *next_sandbox = sandbox_schedule(0); + remove_sandbox_from_local_run_queue(current_sandbox); + current_sandbox->state = RETURNED; + + struct sandbox *next_sandbox = get_next_sandbox_from_local_run_queue(0); assert(next_sandbox != current_sandbox); softint_enable(); + // free resources from "main function execution", as stack still in use. // unmap linear memory only! - munmap(current_sandbox->linear_start, SBOX_MAX_MEM + PAGE_SIZE); - // sandbox_local_end(current_sandbox); - sandbox_switch(next_sandbox); + munmap(current_sandbox->linear_memory_start, SBOX_MAX_MEM + PAGE_SIZE); + // add_sandbox_to_completion_queue(current_sandbox); + switch_to_sandbox(next_sandbox); } /** @@ -333,7 +334,7 @@ sandbox_exit(void) * */ void * -runtime_accept_thdfn(void *dummy) +listener_thread_main(void *dummy) { struct epoll_event *epoll_events = (struct epoll_event *)malloc(EPOLL_MAX * sizeof(struct epoll_event)); int total_requests = 0; @@ -347,12 +348,12 @@ runtime_accept_thdfn(void *dummy) assert(0); } - struct sockaddr_in client; - socklen_t client_length = sizeof(client); + struct sockaddr_in client_address; + socklen_t client_length = sizeof(client_address); struct module * module = (struct module *)epoll_events[i].data.ptr; assert(module); int es = module->socket_descriptor; - int socket_descriptor = accept(es, (struct sockaddr *)&client, &client_length); + int socket_descriptor = accept(es, (struct sockaddr *)&client_address, &client_length); if (socket_descriptor < 0) { perror("accept"); assert(0); @@ -360,15 +361,15 @@ runtime_accept_thdfn(void *dummy) total_requests++; printf("Received Request %d at %lu\n", total_requests, start_time); - sbox_request_t *sandbox_request = sbox_request_alloc( + sandbox_request_t *sandbox_request = allocate_sandbox_request( module, module->name, socket_descriptor, - (const struct sockaddr *)&client, + (const struct sockaddr *)&client_address, start_time); assert(sandbox_request); - // TODO: Refactor sbox_request_alloc to not add to global request queue and do this here + // TODO: Refactor allocate_sandbox_request to not add to global request queue and do this here } } @@ -378,10 +379,10 @@ runtime_accept_thdfn(void *dummy) } /** - * Initialize runtime global state, mask signals, and init http server + * Initialize runtime global state, mask signals, and init http parser */ void -runtime_init(void) +initialize_runtime(void) { epoll_file_descriptor = epoll_create1(0); assert(epoll_file_descriptor >= 0); @@ -396,6 +397,7 @@ runtime_init(void) softint_mask(SIGUSR1); softint_mask(SIGALRM); + // Initialize http-parser http_init(); } @@ -403,17 +405,17 @@ runtime_init(void) * Initializes the listener thread, pinned to core 0, and starts to listen for requests */ void -runtime_thd_init(void) +initialize_listener_thread(void) { cpu_set_t cs; CPU_ZERO(&cs); CPU_SET(MOD_REQ_CORE, &cs); - pthread_t iothd; - int ret = pthread_create(&iothd, NULL, runtime_accept_thdfn, NULL); + pthread_t listener_thread; + int ret = pthread_create(&listener_thread, NULL, listener_thread_main, NULL); assert(ret == 0); - ret = pthread_setaffinity_np(iothd, sizeof(cpu_set_t), &cs); + ret = pthread_setaffinity_np(listener_thread, sizeof(cpu_set_t), &cs); assert(ret == 0); ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cs); assert(ret == 0); diff --git a/runtime/src/sandbox.c b/runtime/src/sandbox.c index 01550bbc..0d5b944a 100644 --- a/runtime/src/sandbox.c +++ b/runtime/src/sandbox.c @@ -7,13 +7,98 @@ #include #include +/*********************************** + * Libuv Callbacks + ***********************************/ + +/** + * TODO: is there some weird edge case where a UNICODE character might be split between reads? Do we care? + * Called after libuv has read a chunk of data + * Parses data read by the libuv stream chunk-by-chunk until the message is complete + * Then stops the stream and wakes up the sandbox + * @param stream + * @param number_read bytes read + * @param buffer unused + **/ +static inline void +on_libuv_read_parse_http_request(uv_stream_t *stream, ssize_t number_read, const uv_buf_t *buffer) +{ + struct sandbox *sandbox = stream->data; + + // Parse the chunks libuv has read on our behalf until we've parse to message end + if (number_read > 0) { + if (http_request_parse_sb(sandbox, number_read) != 0) return; + sandbox->request_response_data_length += number_read; + struct http_request *rh = &sandbox->http_request; + if (!rh->message_end) return; + } + + // When the entire message has been read, stop the stream and wakeup the sandbox + uv_read_stop(stream); + wakeup_sandbox(sandbox); +} + +/** + * On libuv close, executes this callback to wake the blocked sandbox back up + * @param stream + **/ +static inline void +on_libuv_close_wakeup_sakebox(uv_handle_t *stream) +{ + struct sandbox *sandbox = stream->data; + wakeup_sandbox(sandbox); +} + +/** + * On libuv shutdown, executes this callback to wake the blocked sandbox back up + * @param req shutdown request + * @param status unused in callback + **/ +static inline void +on_libuv_shutdown_wakeup_sakebox(uv_shutdown_t *req, int status) +{ + struct sandbox *sandbox = req->data; + wakeup_sandbox(sandbox); +} + +/** + * On libuv write, executes this callback to wake the blocked sandbox back up + * In case of error, shutdown the sandbox + * @param write shutdown request + * @param status status code + **/ +static inline void +on_libuv_write_wakeup_sandbox(uv_write_t *write, int status) +{ + struct sandbox *sandbox = write->data; + if (status < 0) { + sandbox->client_libuv_shutdown_request.data = sandbox; + uv_shutdown(&sandbox->client_libuv_shutdown_request, (uv_stream_t *)&sandbox->client_libuv_stream, on_libuv_shutdown_wakeup_sakebox); + return; + } + wakeup_sandbox(sandbox); +} + +static inline void +on_libuv_allocate_setup_request_response_data(uv_handle_t *h, size_t suggested, uv_buf_t *buf) +{ + struct sandbox *sandbox = h->data; + size_t l = (sandbox->module->max_request_or_response_size - sandbox->request_response_data_length); + buf->base = (sandbox->request_response_data + sandbox->request_response_data_length); + buf->len = l > suggested ? suggested : l; +} + +/*********************************** + * End of Libuv Callbacks + ***********************************/ + /** * Allocates the memory for a sandbox to run a module * @param module the module that we want to run * @returns the resulting sandbox or NULL if mmap failed **/ static inline struct sandbox * -sandbox_memory_map(struct module *module) +allocate_sandbox_memory(struct module *module) { unsigned long memory_size = SBOX_MAX_MEM; // 4GB @@ -24,7 +109,7 @@ sandbox_memory_map(struct module *module) if (linear_memory_size + sandbox_size > memory_size) return NULL; assert(round_up_to_page(sandbox_size) == sandbox_size); - // What does mmap do exactly with fd -1? + // What does mmap do exactly with file_descriptor -1? void *addr = mmap(NULL, sandbox_size + memory_size + /* guard page */ PAGE_SIZE, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (addr == MAP_FAILED) return NULL; @@ -38,8 +123,8 @@ sandbox_memory_map(struct module *module) struct sandbox *sandbox = (struct sandbox *)addr; // can it include sandbox as well? - sandbox->linear_start = (char *)addr + sandbox_size; - sandbox->linear_size = linear_memory_size; + sandbox->linear_memory_start = (char *)addr + sandbox_size; + sandbox->linear_memory_size = linear_memory_size; sandbox->module = module; sandbox->sandbox_size = sandbox_size; module_acquire(module); @@ -47,22 +132,27 @@ sandbox_memory_map(struct module *module) return sandbox; } +/** + * Takes the arguments from the sandbox struct and writes them into the WebAssembly linear memory + * TODO: why do we have to pass argument count explicitly? Can't we just get this off the sandbox? + * @param argument_count + **/ static inline void -sandbox_args_setup(i32 argument_count) +setup_sandbox_arguments(i32 argument_count) { - struct sandbox *curr = sandbox_current(); - char * args = sandbox_args(); + struct sandbox *curr = get_current_sandbox(); + char * arguments = get_current_sandbox_arguments(); - // whatever gregor has, to be able to pass args to a module! - curr->args_offset = sandbox_lmbound; - assert(sandbox_lmbase == curr->linear_start); + // whatever gregor has, to be able to pass arguments to a module! + curr->arguments_offset = sandbox_lmbound; + assert(sandbox_lmbase == curr->linear_memory_start); expand_memory(); - i32 *array_ptr = get_memory_ptr_void(curr->args_offset, argument_count * sizeof(i32)); - i32 string_off = curr->args_offset + (argument_count * sizeof(i32)); + i32 *array_ptr = get_memory_ptr_void(curr->arguments_offset, argument_count * sizeof(i32)); + i32 string_off = curr->arguments_offset + (argument_count * sizeof(i32)); for (int i = 0; i < argument_count; i++) { - char * arg = args + (i * MOD_ARG_MAX_SZ); + char * arg = arguments + (i * MOD_ARG_MAX_SZ); size_t str_sz = strlen(arg) + 1; array_ptr[i] = string_off; @@ -74,86 +164,40 @@ sandbox_args_setup(i32 argument_count) stub_init(string_off); } -static inline void -sb_read_callback(uv_stream_t *s, ssize_t nr, const uv_buf_t *b) -{ - struct sandbox *sandbox = s->data; - - if (nr > 0) { - if (http_request_parse_sb(sandbox, nr) != 0) return; - sandbox->rr_data_len += nr; - struct http_request *rh = &sandbox->http_request; - if (!rh->message_end) return; - } - - uv_read_stop(s); - sandbox_wakeup(sandbox); -} - -static inline void -sb_close_callback(uv_handle_t *s) -{ - struct sandbox *sandbox = s->data; - sandbox_wakeup(sandbox); -} - -static inline void -sb_shutdown_callback(uv_shutdown_t *req, int status) -{ - struct sandbox *sandbox = req->data; - sandbox_wakeup(sandbox); -} - -static inline void -sb_write_callback(uv_write_t *w, int status) -{ - struct sandbox *sandbox = w->data; - if (status < 0) { - sandbox->cuvsr.data = sandbox; - uv_shutdown(&sandbox->cuvsr, (uv_stream_t *)&sandbox->cuv, sb_shutdown_callback); - return; - } - sandbox_wakeup(sandbox); -} - -static inline void -sb_alloc_callback(uv_handle_t *h, size_t suggested, uv_buf_t *buf) -{ - struct sandbox *sandbox = h->data; - size_t l = (sandbox->module->max_request_or_response_size - sandbox->rr_data_len); - buf->base = (sandbox->req_resp_data + sandbox->rr_data_len); - buf->len = l > suggested ? suggested : l; -} - +/** + * Receive and Parse the Request for the current sandbox + * @return 1 on success, < 0 on failure. + * TODO: What does 0 mean? + **/ static inline int -sandbox_client_request_get(void) +receive_and_parse_current_sandbox_client_request(void) { - struct sandbox *curr = sandbox_current(); - curr->rr_data_len = 0; + struct sandbox *curr = get_current_sandbox(); + curr->request_response_data_length = 0; #ifndef USE_HTTP_UVIO int r = 0; - r = recv(curr->csock, (curr->req_resp_data), curr->module->max_request_size, 0); + r = recv(curr->client_socket_descriptor, (curr->request_response_data), curr->module->max_request_size, 0); if (r <= 0) { if (r < 0) perror("recv1"); return r; } while (r > 0) { if (http_request_parse(r) != 0) return -1; - curr->rr_data_len += r; + curr->request_response_data_length += r; struct http_request *rh = &curr->http_request; if (rh->message_end) break; - r = recv(curr->csock, (curr->req_resp_data + curr->rr_data_len), - curr->module->max_request_size - curr->rr_data_len, 0); + r = recv(curr->client_socket_descriptor, (curr->request_response_data + curr->request_response_data_length), + curr->module->max_request_size - curr->request_response_data_length, 0); if (r < 0) { perror("recv2"); return r; } } #else - int r = uv_read_start((uv_stream_t *)&curr->cuv, sb_alloc_callback, sb_read_callback); + int r = uv_read_start((uv_stream_t *)&curr->client_libuv_stream, on_libuv_allocate_setup_request_response_data, on_libuv_read_parse_http_request); sandbox_block_http(); - if (curr->rr_data_len == 0) return 0; + if (curr->request_response_data_length == 0) return 0; #endif return 1; } @@ -163,49 +207,49 @@ sandbox_client_request_get(void) * @return RC. -1 on Failure **/ static inline int -sandbox_client_response_set(void) +build_and_send_current_sandbox_client_response(void) { int sndsz = 0; - struct sandbox *curr = sandbox_current(); - int rsp_hdr_len = strlen(HTTP_RESP_200OK) + strlen(HTTP_RESP_CONTTYPE) + strlen(HTTP_RESP_CONTLEN); - int body_length = curr->rr_data_len - rsp_hdr_len; + struct sandbox *curr = get_current_sandbox(); + int response_header_length = strlen(HTTP_RESP_200OK) + strlen(HTTP_RESP_CONTTYPE) + strlen(HTTP_RESP_CONTLEN); + int body_length = curr->request_response_data_length - response_header_length; - memset(curr->req_resp_data, 0, + memset(curr->request_response_data, 0, strlen(HTTP_RESP_200OK) + strlen(HTTP_RESP_CONTTYPE) + strlen(HTTP_RESP_CONTLEN)); - strncpy(curr->req_resp_data, HTTP_RESP_200OK, strlen(HTTP_RESP_200OK)); + strncpy(curr->request_response_data, HTTP_RESP_200OK, strlen(HTTP_RESP_200OK)); sndsz += strlen(HTTP_RESP_200OK); if (body_length == 0) goto done; - strncpy(curr->req_resp_data + sndsz, HTTP_RESP_CONTTYPE, strlen(HTTP_RESP_CONTTYPE)); + strncpy(curr->request_response_data + sndsz, HTTP_RESP_CONTTYPE, strlen(HTTP_RESP_CONTTYPE)); if (strlen(curr->module->response_content_type) <= 0) { - strncpy(curr->req_resp_data + sndsz + strlen("Content-type: "), HTTP_RESP_CONTTYPE_PLAIN, + strncpy(curr->request_response_data + sndsz + strlen("Content-type: "), HTTP_RESP_CONTTYPE_PLAIN, strlen(HTTP_RESP_CONTTYPE_PLAIN)); } else { - strncpy(curr->req_resp_data + sndsz + strlen("Content-type: "), curr->module->response_content_type, + strncpy(curr->request_response_data + sndsz + strlen("Content-type: "), curr->module->response_content_type, strlen(curr->module->response_content_type)); } sndsz += strlen(HTTP_RESP_CONTTYPE); char len[10] = { 0 }; sprintf(len, "%d", body_length); - strncpy(curr->req_resp_data + sndsz, HTTP_RESP_CONTLEN, strlen(HTTP_RESP_CONTLEN)); - strncpy(curr->req_resp_data + sndsz + strlen("Content-length: "), len, strlen(len)); + strncpy(curr->request_response_data + sndsz, HTTP_RESP_CONTLEN, strlen(HTTP_RESP_CONTLEN)); + strncpy(curr->request_response_data + sndsz + strlen("Content-length: "), len, strlen(len)); sndsz += strlen(HTTP_RESP_CONTLEN); sndsz += body_length; done: - assert(sndsz == curr->rr_data_len); + assert(sndsz == curr->request_response_data_length); // Get End Timestamp curr->total_time = rdtsc() - curr->start_time; printf("Function returned in %lu cycles\n", curr->total_time); #ifndef USE_HTTP_UVIO - int r = send(curr->csock, curr->req_resp_data, sndsz, 0); + int r = send(curr->client_socket_descriptor, curr->request_response_data, sndsz, 0); if (r < 0) { perror("send"); return -1; } while (r < sndsz) { - int s = send(curr->csock, curr->req_resp_data + r, sndsz - r, 0); + int s = send(curr->client_socket_descriptor, curr->request_response_data + r, sndsz - r, 0); if (s < 0) { perror("send"); return -1; @@ -216,84 +260,115 @@ done: uv_write_t req = { .data = curr, }; - uv_buf_t bufv = uv_buf_init(curr->req_resp_data, sndsz); - int r = uv_write(&req, (uv_stream_t *)&curr->cuv, &bufv, 1, sb_write_callback); + uv_buf_t bufv = uv_buf_init(curr->request_response_data, sndsz); + int r = uv_write(&req, (uv_stream_t *)&curr->client_libuv_stream, &bufv, 1, on_libuv_write_wakeup_sandbox); sandbox_block_http(); #endif return 0; } +/** + * Sandbox execution logic + * Handles setup, request parsing, WebAssembly initialization, function execution, response building and sending, and cleanup + **/ void -sandbox_entry(void) +sandbox_main(void) { - struct sandbox *curr = sandbox_current(); + struct sandbox *current_sandbox = get_current_sandbox(); // FIXME: is this right? this is the first time this sandbox is running.. so it wont - // return to sandbox_switch() api.. - // we'd potentially do what we'd in sandbox_switch() api here for cleanup.. + // return to switch_to_sandbox() api.. + // we'd potentially do what we'd in switch_to_sandbox() api here for cleanup.. if (!softint_enabled()) { - arch_context_init(&curr->ctxt, 0, 0); + arch_context_init(¤t_sandbox->ctxt, 0, 0); next_context = NULL; softint_enable(); } - struct module *curr_mod = sandbox_module(curr); - int argument_count = module_argument_count(curr_mod); + struct module *current_module = get_sandbox_module(current_sandbox); + int argument_count = module_argument_count(current_module); // for stdio - int f = io_handle_open(0); + + // Try to initialize file descriptors 0, 1, and 2 as io handles 0, 1, 2 + // We need to check that we get what we expect, as these IO handles may theoretically have been taken + // TODO: why do the file descriptors have to match the io handles? + int f = initialize_io_handle_and_set_file_descriptor_in_current_sandbox(0); assert(f == 0); - f = io_handle_open(1); + f = initialize_io_handle_and_set_file_descriptor_in_current_sandbox(1); assert(f == 1); - f = io_handle_open(2); + f = initialize_io_handle_and_set_file_descriptor_in_current_sandbox(2); assert(f == 2); - http_parser_init(&curr->http_parser, HTTP_REQUEST); - curr->http_parser.data = curr; + // Initialize the HTTP-Parser for a request + http_parser_init(¤t_sandbox->http_parser, HTTP_REQUEST); + + // Set the current_sandbox as the data the http-parser has access to + current_sandbox->http_parser.data = current_sandbox; + // NOTE: if more headers, do offset by that! - int rsp_hdr_len = strlen(HTTP_RESP_200OK) + strlen(HTTP_RESP_CONTTYPE) + strlen(HTTP_RESP_CONTLEN); + int response_header_length = strlen(HTTP_RESP_200OK) + strlen(HTTP_RESP_CONTTYPE) + strlen(HTTP_RESP_CONTLEN); + #ifdef USE_HTTP_UVIO - int r = uv_tcp_init(runtime_uvio(), (uv_tcp_t *)&curr->cuv); + + // Initialize libuv TCP stream + int r = uv_tcp_init(runtime_uvio(), (uv_tcp_t *)¤t_sandbox->client_libuv_stream); assert(r == 0); - curr->cuv.data = curr; - r = uv_tcp_open((uv_tcp_t *)&curr->cuv, curr->csock); + + // Set the current sandbox as the data the libuv callbacks have access to + current_sandbox->client_libuv_stream.data = current_sandbox; + + // Open the libuv TCP stream + r = uv_tcp_open((uv_tcp_t *)¤t_sandbox->client_libuv_stream, current_sandbox->client_socket_descriptor); assert(r == 0); #endif - if (sandbox_client_request_get() > 0) { - curr->rr_data_len = rsp_hdr_len; // TODO: do this on first write to body. + + // If the HTTP Request returns 1, we've successfully received and parsed the HTTP request, so execute it! + if (receive_and_parse_current_sandbox_client_request() > 0) { + + // + current_sandbox->request_response_data_length = response_header_length; // TODO: do this on first write to body. + + // Allocate the WebAssembly Sandbox alloc_linear_memory(); // perhaps only initialized for the first instance? or TODO! - // module_table_init(curr_mod); - module_globals_init(curr_mod); - module_memory_init(curr_mod); - sandbox_args_setup(argument_count); + // module_table_init(current_module); + module_globals_init(current_module); + module_memory_init(current_module); - curr->retval = module_entry(curr_mod, argument_count, curr->args_offset); + // Copy the arguments into the WebAssembly sandbox + setup_sandbox_arguments(argument_count); - sandbox_client_response_set(); + // Executing the function within the WebAssembly sandbox + current_sandbox->return_value = module_entry(current_module, argument_count, current_sandbox->arguments_offset); + + // Retrieve the result from the WebAssembly sandbox, construct the HTTP response, and send to client + build_and_send_current_sandbox_client_response(); } + // Cleanup connection and exit sandbox + #ifdef USE_HTTP_UVIO - uv_close((uv_handle_t *)&curr->cuv, sb_close_callback); + uv_close((uv_handle_t *)¤t_sandbox->client_libuv_stream, on_libuv_close_wakeup_sakebox); sandbox_block_http(); #else - close(curr->csock); + close(current_sandbox->client_socket_descriptor); #endif - sandbox_exit(); + exit_current_sandbox(); } struct sandbox * -sandbox_alloc(struct module *module, char *args, int sock, const struct sockaddr *addr, u64 start_time) +allocate_sandbox(struct module *module, char *arguments, int socket_descriptor, const struct sockaddr *socket_address, u64 start_time) { if (!module_is_valid(module)) return NULL; // FIXME: don't use malloc. huge security problem! // perhaps, main should be in its own sandbox, when it is not running any sandbox. - struct sandbox *sandbox = (struct sandbox *)sandbox_memory_map(module); + struct sandbox *sandbox = (struct sandbox *)allocate_sandbox_memory(module); if (!sandbox) return NULL; // Assign the start time from the request sandbox->start_time = start_time; // actual module instantiation! - sandbox->args = (void *)args; + sandbox->arguments = (void *)arguments; sandbox->stack_size = module->stack_size; sandbox->stack_start = mmap(NULL, sandbox->stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0); @@ -301,38 +376,39 @@ sandbox_alloc(struct module *module, char *args, int sock, const struct sockaddr perror("mmap"); assert(0); } - sandbox->csock = sock; - if (addr) memcpy(&sandbox->client, addr, sizeof(struct sockaddr)); - for (int i = 0; i < SBOX_MAX_OPEN; i++) sandbox->handles[i].fd = -1; + sandbox->client_socket_descriptor = socket_descriptor; + if (socket_address) memcpy(&sandbox->client_address, socket_address, sizeof(struct sockaddr)); + for (int i = 0; i < SBOX_MAX_OPEN; i++) sandbox->handles[i].file_descriptor = -1; ps_list_init_d(sandbox); - arch_context_init(&sandbox->ctxt, (reg_t)sandbox_entry, (reg_t)(sandbox->stack_start + sandbox->stack_size)); + // Setup the sandbox's context, stack, and instruction pointer + arch_context_init(&sandbox->ctxt, (reg_t)sandbox_main, (reg_t)(sandbox->stack_start + sandbox->stack_size)); return sandbox; } void -sandbox_free(struct sandbox *sandbox) +free_sandbox(struct sandbox *sandbox) { int ret; // you have to context switch away to free a sandbox. - if (!sandbox || sandbox == sandbox_current()) return; + if (!sandbox || sandbox == get_current_sandbox()) return; // again sandbox should be done and waiting for the parent. // TODO: this needs to be enhanced. you may be killing a sandbox when its in any other execution states. - if (sandbox->state != SANDBOX_RETURNED) return; + if (sandbox->state != RETURNED) return; int sz = sizeof(struct sandbox); sz += sandbox->module->max_request_or_response_size; module_release(sandbox->module); - // TODO free(sandbox->args); + // TODO free(sandbox->arguments); void * stkaddr = sandbox->stack_start; size_t stksz = sandbox->stack_size; // depending on the memory type - // free_linear_memory(sandbox->linear_start, sandbox->linear_size, sandbox->linear_max_size); + // free_linear_memory(sandbox->linear_memory_start, sandbox->linear_memory_size, sandbox->linear_memory_max_size); // mmaped memory includes sandbox structure in there. ret = munmap(sandbox, sz); diff --git a/runtime/src/softint.c b/runtime/src/softint.c index 235e3540..d845fe58 100644 --- a/runtime/src/softint.c +++ b/runtime/src/softint.c @@ -69,21 +69,21 @@ softint_alarm_schedule(void *user_context_raw) { softint_disable(); // no nesting! - struct sandbox *curr = sandbox_current(); + struct sandbox *curr = get_current_sandbox(); ucontext_t * user_context = (ucontext_t *)user_context_raw; // no sandboxes running..so nothing to preempt..let the "main" scheduler run its course. if (curr == NULL) goto done; // find a next sandbox to run.. - struct sandbox *next = sandbox_schedule(1); + struct sandbox *next = get_next_sandbox_from_local_run_queue(1); if (next == NULL) goto done; if (next == curr) goto done; // only this sandbox to schedule.. return to it! // save the current sandbox, state from user_context! arch_mcontext_save(&curr->ctxt, &user_context->uc_mcontext); - // sandbox_current_set on it. restore through *user_context.. - sandbox_current_set(next); + // set_current_sandbox on it. restore through *user_context.. + set_current_sandbox(next); if (arch_mcontext_restore(&user_context->uc_mcontext, &next->ctxt)) goto skip; // reset if SIGALRM happens before SIGUSR1 and if don't preempt..OR @@ -113,7 +113,7 @@ softint_handler(int signal_type, siginfo_t *signal_info, void *user_context_raw) #ifdef PREEMPT_DISABLE assert(0); #else - struct sandbox *curr = sandbox_current(); + struct sandbox *curr = get_current_sandbox(); ucontext_t * user_context = (ucontext_t *)user_context_raw; switch (signal_type) { @@ -137,7 +137,7 @@ softint_handler(int signal_type, siginfo_t *signal_info, void *user_context_raw) SIGALRM_count++; // softints per-core.. - if (curr && curr->state == SANDBOX_RETURNED) return; + if (curr && curr->state == RETURNED) return; if (next_context) return; if (!softint_enabled()) return; softint_alarm_schedule(user_context_raw); diff --git a/runtime/tools/httpclient/client.c b/runtime/tools/httpclient/client.c index 230a9351..a4b7729d 100644 --- a/runtime/tools/httpclient/client.c +++ b/runtime/tools/httpclient/client.c @@ -167,9 +167,9 @@ char img[] = { int connect_n_send(void) { - int sock; + int socket_descriptor; - if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + if ((socket_descriptor = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); return -1; } @@ -179,13 +179,13 @@ connect_n_send(void) socket_address.sin_port = htons(SERVER_PORT); if (inet_aton(SERVER_ADDR, &socket_address.sin_addr) == 0) { perror("inet_addr"); - close(sock); + close(socket_descriptor); return -1; } - if (connect(sock, (struct sockaddr *)&socket_address, sizeof(socket_address)) < 0) { + if (connect(socket_descriptor, (struct sockaddr *)&socket_address, sizeof(socket_address)) < 0) { perror("connect"); - close(sock); + close(socket_descriptor); return -1; } @@ -205,29 +205,29 @@ connect_n_send(void) assert(resp); memset(resp, 0, RESP_MAX); - // int fd = open("tmp_cli.png", O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXO | S_IRWXG); - // if (fd < 0) { + // int file_descriptor = open("tmp_cli.png", O_CREAT | O_RDWR | O_TRUNC, S_IRWXU | S_IRWXO | S_IRWXG); + // if (file_descriptor < 0) { // perror("open"); // goto skip; // } // - // int sz = write(fd, img, sizeof(img)); + // int sz = write(file_descriptor, img, sizeof(img)); // if (sz < 0) { // perror("write"); // } - // close(fd); + // close(file_descriptor); skip: printf("Sending..\n"); - if (send(sock, req, len, 0) < 0) { + if (send(socket_descriptor, req, len, 0) < 0) { perror("send"); - close(sock); + close(socket_descriptor); return -1; } printf("Receiving..\n"); int r = 0, rcvd = 0; - while ((r = recv(sock, resp + rcvd, RESP_MAX, 0)) > 0) { + while ((r = recv(socket_descriptor, resp + rcvd, RESP_MAX, 0)) > 0) { rcvd += r; if (r < RESP_MAX) break; resp = (char *)realloc(resp, rcvd + RESP_MAX); @@ -238,7 +238,7 @@ skip: printf("Response: %s\n", resp); free(resp); free(req); - close(sock); + close(socket_descriptor); return 0; } diff --git a/runtime/tools/udpclient/udpclient.c b/runtime/tools/udpclient/udpclient.c index c2aad19f..48527bc2 100644 --- a/runtime/tools/udpclient/udpclient.c +++ b/runtime/tools/udpclient/udpclient.c @@ -43,27 +43,27 @@ send_fn(void *d) struct request *r = (struct request *)d; char resp[STR_MAX] = { 0 }; - int fd = -1; + int file_descriptor = -1; struct sockaddr_in sa; sa.sin_family = AF_INET; sa.sin_port = htons(atoi(r->port)); sa.sin_addr.s_addr = inet_addr(r->ip); - if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { + if ((file_descriptor = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { perror("Establishing socket"); return NULL; } - if (sendto(fd, r->msg, strlen(r->msg), 0, (struct sockaddr *)&sa, sizeof(sa)) < 0 && errno != EINTR) { + if (sendto(file_descriptor, r->msg, strlen(r->msg), 0, (struct sockaddr *)&sa, sizeof(sa)) < 0 && errno != EINTR) { perror("sendto"); return NULL; } // todo: select rcv from! int sa_len = sizeof(sa); - if (recvfrom(fd, resp, STR_MAX, 0, (struct sockaddr *)&sa, &sa_len) < 0) { perror("recvfrom"); } + if (recvfrom(file_descriptor, resp, STR_MAX, 0, (struct sockaddr *)&sa, &sa_len) < 0) { perror("recvfrom"); } printf("Done[%s]!\n", resp); - close(fd); + close(file_descriptor); free(r); return NULL;