From 11795d277253d8ed2705db0959a1fa5b841b6e70 Mon Sep 17 00:00:00 2001 From: ading2210 Date: Sun, 30 Jun 2024 23:14:44 -0700 Subject: [PATCH] update wisp server, fix some memory issues --- README.md | 1 - client/javascript/http.js | 5 ++- client/javascript/session.js | 70 ++++++++++++++++++++-------------- client/javascript/websocket.js | 7 ---- client/libcurl/request.c | 9 +++-- client/libcurl/types.h | 5 ++- server/run.sh | 4 +- server/wisp_server | 2 +- 8 files changed, 57 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index dcbdd68..ed28743 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,6 @@ This is an experimental port of [libcurl](https://curl.se/libcurl/) to WebAssemb - Works in all major browsers (Chromium >= 64, Firefox >= 65, Safari >= 14) - Has the ability to create multiple independent sessions - Small footprint size (800kb after compression) and low runtime memory usage -- Support for running inside a web worker - Support for Brotli and gzip compressed responses ## Building: diff --git a/client/javascript/http.js b/client/javascript/http.js index ee2ed6f..ec4456b 100644 --- a/client/javascript/http.js +++ b/client/javascript/http.js @@ -55,7 +55,10 @@ class HTTPSession extends CurlSession { resolve(response); } let finish_callback = (error) => { - _free(body_ptr); + if (body_ptr != null) { + _free(body_ptr); + body_ptr = null; + } if (error > 0) { error_msg(`Request "${url}" failed with error code ${error}: ${get_error_str(error)}`); reject(`Request failed with error code ${error}: ${get_error_str(error)}`); diff --git a/client/javascript/session.js b/client/javascript/session.js index d028c17..e3e0574 100644 --- a/client/javascript/session.js +++ b/client/javascript/session.js @@ -8,6 +8,18 @@ class CurlSession { this.event_loop = null; this.requests_list = []; this.to_remove = []; + + this.end_callback_ptr = Module.addFunction((request_id, error) => { + this.end_callback(request_id, error); + }, "vii"); + this.headers_callback_ptr = Module.addFunction((request_id, chunk_ptr, chunk_size) => { + this.headers_callback(request_id, chunk_ptr, chunk_size) + }, "viii"); + this.data_callback_ptr = Module.addFunction((request_id, chunk_ptr, chunk_size) => { + this.data_callback(request_id, chunk_ptr, chunk_size) + }, "viii"); + this.request_callbacks = {}; + this.last_request_id = 0; } assert_ready() { @@ -21,37 +33,36 @@ class CurlSession { _session_set_options(this.session_ptr, connections_limit, cache_limit); } + end_callback(request_id, error) { + this.active_requests--; + this.request_callbacks[request_id].end(error); + delete this.request_callbacks[request_id]; + } + + data_callback(request_id, chunk_ptr, chunk_size) { + let data = Module.HEAPU8.subarray(chunk_ptr, chunk_ptr + chunk_size); + let chunk = new Uint8Array(data); + this.request_callbacks[request_id].data(chunk); + } + + headers_callback(request_id, chunk_ptr, chunk_size) { + let data = Module.HEAPU8.subarray(chunk_ptr, chunk_ptr + chunk_size); + let chunk = new Uint8Array(data); + this.request_callbacks[request_id].headers(chunk); + } + create_request(url, js_data_callback, js_end_callback, js_headers_callback) { this.assert_ready(); - let end_callback_ptr; - let data_callback_ptr; - let headers_callback_ptr; - - let end_callback = (error) => { - Module.removeFunction(end_callback_ptr); - Module.removeFunction(data_callback_ptr); - - this.active_requests--; - js_end_callback(error); + let request_id = this.last_request_id++; + this.request_callbacks[request_id] = { + end: js_end_callback, + data: js_data_callback, + headers: js_headers_callback } - let data_callback = (chunk_ptr, chunk_size) => { - let data = Module.HEAPU8.subarray(chunk_ptr, chunk_ptr + chunk_size); - let chunk = new Uint8Array(data); - js_data_callback(chunk); - } - - let headers_callback = (chunk_ptr, chunk_size) => { - let data = Module.HEAPU8.subarray(chunk_ptr, chunk_ptr + chunk_size); - let chunk = new Uint8Array(data); - js_headers_callback(chunk); - } - - end_callback_ptr = Module.addFunction(end_callback, "vi"); - headers_callback_ptr = Module.addFunction(headers_callback, "vii"); - data_callback_ptr = Module.addFunction(data_callback, "vii"); - let request_ptr = c_func(_create_request, [url, data_callback_ptr, end_callback_ptr, headers_callback_ptr]); - + let request_ptr = c_func(_create_request, [ + url, request_id, this.data_callback_ptr, this.end_callback_ptr, this.headers_callback_ptr + ]); return request_ptr; } @@ -109,6 +120,9 @@ class CurlSession { } _session_cleanup(this.session_ptr); this.session_ptr = null; + Module.removeFunction(this.end_callback_ptr); + Module.removeFunction(this.headers_callback_ptr); + Module.removeFunction(this.data_callback_ptr); } close() { @@ -137,7 +151,7 @@ class CurlSession { if (headers_received) { stream_controller.error("The operation was aborted."); } - real_abort_callback(); + real_end_callback(-1); }); } diff --git a/client/javascript/websocket.js b/client/javascript/websocket.js index e371582..9c32f54 100644 --- a/client/javascript/websocket.js +++ b/client/javascript/websocket.js @@ -65,13 +65,6 @@ class CurlWebSocket extends CurlSession { //CURLE_OK - data received if (result_code === 0 && !result_closed) { - if (_get_result_closed(result_ptr)) { - _free(data_ptr); - _free(result_ptr); - this.cleanup(); - return returned_data; - } - let data_size = _get_result_size(result_ptr); let data_heap = Module.HEAPU8.subarray(data_ptr, data_ptr + data_size); let data = new Uint8Array(data_heap); diff --git a/client/libcurl/request.c b/client/libcurl/request.c index 534dd87..77d57b2 100644 --- a/client/libcurl/request.c +++ b/client/libcurl/request.c @@ -18,17 +18,17 @@ struct curl_blob cacert_blob; size_t write_function(char *data, size_t size, size_t nmemb, struct RequestInfo *request_info) { size_t real_size = size * nmemb; - (*request_info->data_callback)(data, real_size); + (*request_info->data_callback)(request_info->request_id, data, real_size); return real_size; } size_t header_function(char *data, size_t size, size_t nmemb, struct RequestInfo *request_info) { size_t real_size = size * nmemb; - (*request_info->headers_callback)(data, real_size); + (*request_info->headers_callback)(request_info->request_id, data, real_size); return real_size; } -CURL* create_request(const char* url, DataCallback data_callback, EndCallback end_callback, DataCallback headers_callback) { +CURL* create_request(const char* url, int request_id, DataCallback data_callback, EndCallback end_callback, DataCallback headers_callback) { CURL *http_handle = curl_easy_init(); //create request metadata struct @@ -36,6 +36,7 @@ CURL* create_request(const char* url, DataCallback data_callback, EndCallback en request_info->http_handle = http_handle; request_info->curl_msg = NULL; request_info->headers_list = NULL; + request_info->request_id = request_id; request_info->end_callback = end_callback; request_info->data_callback = data_callback; request_info->headers_callback = headers_callback; @@ -71,7 +72,7 @@ void finish_request(CURLMsg *curl_msg) { if (request_info->headers_list != NULL) { curl_slist_free_all(request_info->headers_list); } - (*request_info->end_callback)(error); + (*request_info->end_callback)(request_info->request_id, error); } unsigned char* get_cacert() { diff --git a/client/libcurl/types.h b/client/libcurl/types.h index a0642bd..9c6869d 100644 --- a/client/libcurl/types.h +++ b/client/libcurl/types.h @@ -1,12 +1,13 @@ #include "curl/curl.h" -typedef void(*DataCallback)(char* chunk_ptr, int chunk_size); -typedef void(*EndCallback)(int error); +typedef void(*DataCallback)(int request_id, char* chunk_ptr, int chunk_size); +typedef void(*EndCallback)(int request_id, int error); struct RequestInfo { CURL* http_handle; struct CURLMsg *curl_msg; struct curl_slist* headers_list; + int request_id; DataCallback data_callback; DataCallback headers_callback; EndCallback end_callback; diff --git a/server/run.sh b/server/run.sh index ed89516..aa59930 100755 --- a/server/run.sh +++ b/server/run.sh @@ -14,7 +14,7 @@ fi source $SERVER_PATH/.venv/bin/activate if ! python3 -c "import websockets, asyncudp" 2> /dev/null; then - pip3 install -r $SERVER_PATH/requirements.txt + pip3 install -e $SERVER_PATH fi -python3 $SERVER_PATH/main.py "$@" \ No newline at end of file +python3 -m wisp.server "$@" \ No newline at end of file diff --git a/server/wisp_server b/server/wisp_server index 351682f..b7cfab0 160000 --- a/server/wisp_server +++ b/server/wisp_server @@ -1 +1 @@ -Subproject commit 351682f7e19c8a7a58d261ba666abaae95f04f6a +Subproject commit b7cfab072b04dbd4345aedaf5e47c9e0d57ab873