diff --git a/client/build.sh b/client/build.sh index 119cea6..b054404 100755 --- a/client/build.sh +++ b/client/build.sh @@ -5,9 +5,10 @@ LIB_DIR="build/curl-wasm/lib/" CACERT_FILE="cacert.pem" OUT_FILE="out/libcurl.js" -EXPORTED_FUNCS="_main,_do_request" +EXPORTED_FUNCS="_main,_perform_request,_copy_bytes" +RUNTIME_METHODS="addFunction,removeFunction" COMPILER_OPTIONS="-o $OUT_FILE -lcurl -lssl -lcrypto -I $INCLUDE_DIR -L $LIB_DIR" -EMSCRIPTEN_OPTIONS="-lwebsocket.js -sWEBSOCKET_URL=wss://debug.ading.dev/ws -sASYNCIFY -sALLOW_UNIMPLEMENTED_SYSCALLS -sEXPORTED_FUNCTIONS=$EXPORTED_FUNCS --preload-file $CACERT_FILE" +EMSCRIPTEN_OPTIONS="-lwebsocket.js -sWEBSOCKET_URL=wss://debug.ading.dev/ws -sASYNCIFY -sALLOW_TABLE_GROWTH -sEXPORTED_FUNCTIONS=$EXPORTED_FUNCS -sEXPORTED_RUNTIME_METHODS=$RUNTIME_METHODS --preload-file $CACERT_FILE" if [ ! -f $CACERT_FILE ]; then wget "https://curl.se/ca/cacert.pem" -O $CACERT_FILE diff --git a/client/main.c b/client/main.c index 5215a9e..8fe9cb0 100644 --- a/client/main.c +++ b/client/main.c @@ -1,9 +1,19 @@ -#include "emscripten/emscripten.h" +#include #include #include #include +#include + +int write_function(void *data, size_t size, size_t nmemb, void(*data_callback)(char* chunk_ptr, int chunk_size)) { + long real_size = size * nmemb; + char* chunk = malloc(real_size); + memcpy(chunk, data, real_size); + data_callback(chunk, real_size); + free(chunk); + return real_size; +} -int do_request(const char* url) { +void perform_request(const char* url, void(*data_callback)(char* chunk_ptr, int chunk_size), void(*end_callback)()) { printf("downloading %s\n", url); CURL *http_handle; @@ -18,6 +28,11 @@ int do_request(const char* url) { curl_easy_setopt(http_handle, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); curl_easy_setopt(http_handle, CURLOPT_CAINFO, "/cacert.pem"); curl_easy_setopt(http_handle, CURLOPT_CAPATH, "/cacert.pem"); + + //callbacks to pass the response data back to js + curl_easy_setopt(http_handle, CURLOPT_WRITEFUNCTION, &write_function); + curl_easy_setopt(http_handle, CURLOPT_WRITEDATA, data_callback); + multi_handle = curl_multi_init(); curl_multi_add_handle(multi_handle, http_handle); @@ -42,11 +57,16 @@ int do_request(const char* url) { curl_easy_cleanup(http_handle); curl_multi_cleanup(multi_handle); curl_global_cleanup(); - - return 0; + + (*end_callback)(); +} + +char* copy_bytes(const char* ptr, const int size) { + char* new_ptr = malloc(size); + memcpy(new_ptr, ptr, size); + return new_ptr; } int main() { printf("emscripten libcurl module loaded\n"); - do_request("https://ifconfig.me/all"); } \ No newline at end of file diff --git a/client/main.js b/client/main.js index 03b568e..e9d7a53 100644 --- a/client/main.js +++ b/client/main.js @@ -5,8 +5,55 @@ function allocate_str(str) { return allocate(intArrayFromString(str), ALLOC_NORMAL); } -async function main() { +//low level interface with c code +function perform_request(url, js_data_callback, js_end_callback) { + let end_callback_ptr; + let data_callback_ptr; + let url_ptr = allocate_str(url); + let end_callback = () => { + Module.removeFunction(end_callback_ptr); + Module.removeFunction(data_callback_ptr); + _free(url_ptr); + + js_end_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); + } + + end_callback_ptr = Module.addFunction(end_callback, "v"); + data_callback_ptr = Module.addFunction(data_callback, "vii"); + _perform_request(url_ptr, data_callback_ptr, end_callback_ptr); +} + +function merge_arrays(arrays) { + let total_len = arrays.reduce((acc, val) => acc + val.length, 0); + let new_array = new Uint8Array(total_len); + let offset = 0; + for (let array of arrays) { + new_array.set(array, offset); + offset += array.length; + } + return new_array; +} + +async function main() { + let chunks = []; + perform_request("https://ading.dev", (new_data) => { + chunks.push(new_data); + }, () => { + for (let chunk of chunks) { + console.log(chunk); + } + + let response_data = merge_arrays(chunks); + let response_str = new TextDecoder().decode(response_data); + console.log(response_str); + }); } window.onload = () => {