mirror of
https://github.com/ading2210/libcurl.js.git
synced 2025-05-13 14:30:02 -04:00
add old v0.4 code
This commit is contained in:
parent
582bbd4ecd
commit
9205ae1507
14 changed files with 340 additions and 180 deletions
|
@ -80,11 +80,14 @@ VERSION=$(cat package.json | jq -r '.version')
|
||||||
sed -i "s/__library_version__/$VERSION/" $OUT_FILE
|
sed -i "s/__library_version__/$VERSION/" $OUT_FILE
|
||||||
|
|
||||||
#add extra libraries
|
#add extra libraries
|
||||||
|
sed -i "/__extra_libraries__/r $JAVSCRIPT_DIR/copyright.js" $OUT_FILE
|
||||||
sed -i "/__extra_libraries__/r $WISP_CLIENT/polyfill.js" $OUT_FILE
|
sed -i "/__extra_libraries__/r $WISP_CLIENT/polyfill.js" $OUT_FILE
|
||||||
sed -i "/__extra_libraries__/r $WISP_CLIENT/wisp.js" $OUT_FILE
|
sed -i "/__extra_libraries__/r $WISP_CLIENT/wisp.js" $OUT_FILE
|
||||||
sed -i "/__extra_libraries__/r $JAVSCRIPT_DIR/messages.js" $OUT_FILE
|
sed -i "/__extra_libraries__/r $JAVSCRIPT_DIR/messages.js" $OUT_FILE
|
||||||
|
sed -i "/__extra_libraries__/r $JAVSCRIPT_DIR/tls_socket.js" $OUT_FILE
|
||||||
sed -i "/__extra_libraries__/r $JAVSCRIPT_DIR/websocket.js" $OUT_FILE
|
sed -i "/__extra_libraries__/r $JAVSCRIPT_DIR/websocket.js" $OUT_FILE
|
||||||
sed -i "/__extra_libraries__/r $JAVSCRIPT_DIR/copyright.js" $OUT_FILE
|
sed -i "/__extra_libraries__/r $JAVSCRIPT_DIR/custom_websocket.js" $OUT_FILE
|
||||||
|
sed -i "/__extra_libraries__/r $JAVSCRIPT_DIR/util.js" $OUT_FILE
|
||||||
|
|
||||||
#apply patches
|
#apply patches
|
||||||
python3 tools/patch_js.py $FRAGMENTS_DIR $OUT_FILE
|
python3 tools/patch_js.py $FRAGMENTS_DIR $OUT_FILE
|
||||||
|
|
|
@ -8,7 +8,7 @@ get_version
|
||||||
recv_from_websocket
|
recv_from_websocket
|
||||||
send_to_websocket
|
send_to_websocket
|
||||||
close_websocket
|
close_websocket
|
||||||
cleanup_websocket
|
cleanup_handle
|
||||||
get_result_size
|
get_result_size
|
||||||
get_result_buffer
|
get_result_buffer
|
||||||
get_result_code
|
get_result_code
|
||||||
|
@ -16,4 +16,7 @@ get_result_closed
|
||||||
get_result_bytes_left
|
get_result_bytes_left
|
||||||
get_result_is_text
|
get_result_is_text
|
||||||
|
|
||||||
|
recv_from_socket
|
||||||
|
send_to_socket
|
||||||
|
|
||||||
free
|
free
|
|
@ -6,7 +6,7 @@
|
||||||
<script defer src="./out/libcurl.js" onload="libcurl.load_wasm('/out/libcurl.wasm');"></script>
|
<script defer src="./out/libcurl.js" onload="libcurl.load_wasm('/out/libcurl.wasm');"></script>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("libcurl_load", ()=>{
|
document.addEventListener("libcurl_load", ()=>{
|
||||||
libcurl.set_websocket(`wss://${location.hostname}/ws/`);
|
libcurl.set_websocket(location.href.replace("http", "ws"));
|
||||||
console.log(`loaded libcurl.js v${libcurl.version.lib}`);
|
console.log(`loaded libcurl.js v${libcurl.version.lib}`);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
112
client/javascript/custom_websocket.js
Normal file
112
client/javascript/custom_websocket.js
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
//class for custom websocket
|
||||||
|
//multiple classes attempt to replicate the websocket API
|
||||||
|
//so this prevents code duplication
|
||||||
|
|
||||||
|
class CustomWebSocket extends EventTarget {
|
||||||
|
constructor(url, protocols=[]) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.url = url;
|
||||||
|
this.protocols = protocols;
|
||||||
|
this.binaryType = "blob";
|
||||||
|
|
||||||
|
//legacy event handlers
|
||||||
|
this.onopen = () => {};
|
||||||
|
this.onerror = () => {};
|
||||||
|
this.onmessage = () => {};
|
||||||
|
this.onclose = () => {};
|
||||||
|
|
||||||
|
this.CONNECTING = 0;
|
||||||
|
this.OPEN = 1;
|
||||||
|
this.CLOSING = 2;
|
||||||
|
this.CLOSED = 3;
|
||||||
|
|
||||||
|
this.status = this.CONNECTING;
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_recv() {}
|
||||||
|
recv() {
|
||||||
|
let {success, data, is_text} = this.custom_recv();
|
||||||
|
if (!success) return;
|
||||||
|
|
||||||
|
let converted;
|
||||||
|
if (is_text) {
|
||||||
|
converted = new TextDecoder().decode(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (this.binaryType == "blob") {
|
||||||
|
converted = new Blob(data);
|
||||||
|
}
|
||||||
|
else if (this.binaryType == "arraybuffer") {
|
||||||
|
converted = data.buffer;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "invalid binaryType string";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let msg_event = new MessageEvent("message", {data: converted});
|
||||||
|
this.onmessage(msg_event);
|
||||||
|
this.dispatchEvent(msg_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
recv_loop() {
|
||||||
|
this.event_loop = setInterval(() => {
|
||||||
|
this.recv();
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
close_callback(error) {
|
||||||
|
if (this.status == this.CLOSED) return;
|
||||||
|
this.status = this.CLOSED;
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
let error_event = new Event("error");
|
||||||
|
this.dispatchEvent(error_event);
|
||||||
|
this.onerror(error_event);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let close_event = new CloseEvent("close");
|
||||||
|
this.dispatchEvent(close_event);
|
||||||
|
this.onclose(close_event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open_callback() {
|
||||||
|
this.status = this.OPEN;
|
||||||
|
let open_event = new Event("open");
|
||||||
|
this.onopen(open_event);
|
||||||
|
this.dispatchEvent(open_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
send(data) {
|
||||||
|
let is_text = typeof data === "string";
|
||||||
|
if (this.status === this.CONNECTING) {
|
||||||
|
throw new DOMException("ws not ready yet");
|
||||||
|
}
|
||||||
|
if (this.status === this.CLOSED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let data_array = any_to_array(data);
|
||||||
|
this.custom_send(data_array, is_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this.status = this.CLOSING;
|
||||||
|
this.custom_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
get readyState() {
|
||||||
|
return this.status;
|
||||||
|
}
|
||||||
|
get bufferedAmount() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
get protocol() {
|
||||||
|
return this.protocols;
|
||||||
|
}
|
||||||
|
get extensions() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,42 +45,6 @@ function check_loaded(check_websocket) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//a case insensitive dictionary for request headers
|
|
||||||
class HeadersDict {
|
|
||||||
constructor(obj) {
|
|
||||||
for (let key in obj) {
|
|
||||||
this[key] = obj[key];
|
|
||||||
}
|
|
||||||
return new Proxy(this, this);
|
|
||||||
}
|
|
||||||
get(target, prop) {
|
|
||||||
let keys = Object.keys(this);
|
|
||||||
for (let key of keys) {
|
|
||||||
if (key.toLowerCase() === prop.toLowerCase()) {
|
|
||||||
return this[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
set(target, prop, value) {
|
|
||||||
let keys = Object.keys(this);
|
|
||||||
for (let key of keys) {
|
|
||||||
if (key.toLowerCase() === prop.toLowerCase()) {
|
|
||||||
this[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this[prop] = value;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function allocate_str(str) {
|
|
||||||
return allocate(intArrayFromString(str), ALLOC_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
function allocate_array(array) {
|
|
||||||
return allocate(array, ALLOC_NORMAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
//low level interface with c code
|
//low level interface with c code
|
||||||
function perform_request(url, params, js_data_callback, js_end_callback, body=null) {
|
function perform_request(url, params, js_data_callback, js_end_callback, body=null) {
|
||||||
let params_str = JSON.stringify(params);
|
let params_str = JSON.stringify(params);
|
||||||
|
@ -313,15 +277,17 @@ return {
|
||||||
load_wasm: load_wasm,
|
load_wasm: load_wasm,
|
||||||
wisp: _wisp_connections,
|
wisp: _wisp_connections,
|
||||||
WebSocket: CurlWebSocket,
|
WebSocket: CurlWebSocket,
|
||||||
|
TLSSocket: TLSSocket,
|
||||||
|
|
||||||
get copyright() {return copyright_notice},
|
get copyright() {return copyright_notice},
|
||||||
get version() {return get_version()},
|
get version() {return get_version()},
|
||||||
get ready() {return wasm_ready},
|
get ready() {return wasm_ready},
|
||||||
|
get websocket_url() {return websocket_url},
|
||||||
|
|
||||||
get stdout() {return out},
|
get stdout() {return out},
|
||||||
set stdout(callback) {out = callback},
|
set stdout(callback) {out = callback},
|
||||||
get stderr() {return err},
|
get stderr() {return err},
|
||||||
set stderr(callback) {err = callback}
|
set stderr(callback) {err = callback},
|
||||||
}
|
}
|
||||||
|
|
||||||
})()
|
})()
|
73
client/javascript/tls_socket.js
Normal file
73
client/javascript/tls_socket.js
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
class TLSSocket extends CustomWebSocket {
|
||||||
|
constructor(hostname, port, debug) {
|
||||||
|
super();
|
||||||
|
this.hostname = hostname;
|
||||||
|
this.port = port;
|
||||||
|
this.url = `https://${hostname}:${port}`;
|
||||||
|
this.debug = debug;
|
||||||
|
|
||||||
|
this.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
let data_callback = () => {};
|
||||||
|
let finish_callback = (error, response_info) => {
|
||||||
|
this.status = this.OPEN;
|
||||||
|
if (error === 0) {
|
||||||
|
this.open_callback();
|
||||||
|
this.recv_loop();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.cleanup(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let options = {
|
||||||
|
_connect_only: 1,
|
||||||
|
}
|
||||||
|
if (this.debug) options._libcurl_verbose = 1;
|
||||||
|
|
||||||
|
this.http_handle = perform_request(this.url, options, data_callback, finish_callback, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_recv() {
|
||||||
|
let buffer_size = 64*1024;
|
||||||
|
let result_ptr = _recv_from_socket(this.http_handle, buffer_size);
|
||||||
|
let data_ptr = _get_result_buffer(result_ptr);
|
||||||
|
let result_code = _get_result_code(result_ptr);
|
||||||
|
|
||||||
|
if (result_code == 0) { //CURLE_OK - data received
|
||||||
|
if (_get_result_closed(result_ptr)) {
|
||||||
|
this.close_callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
let message_event = new MessageEvent("message", {data: data});
|
||||||
|
this.dispatchEvent(message_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
_free(data_ptr);
|
||||||
|
_free(result_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_send(data_array) {
|
||||||
|
let data_ptr = allocate_array(data_array);
|
||||||
|
let data_len = data_array.length;
|
||||||
|
_send_to_socket(this.http_handle, data_ptr, data_len);
|
||||||
|
_free(data_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup(error=false) {
|
||||||
|
if (this.http_handle) _cleanup_handle(this.http_handle);
|
||||||
|
clearInterval(this.event_loop);
|
||||||
|
this.close_callback(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_close() {
|
||||||
|
this.cleanup();
|
||||||
|
this.status = this.CLOSED;
|
||||||
|
}
|
||||||
|
}
|
70
client/javascript/util.js
Normal file
70
client/javascript/util.js
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
//a case insensitive dictionary for request headers
|
||||||
|
class HeadersDict {
|
||||||
|
constructor(obj) {
|
||||||
|
for (let key in obj) {
|
||||||
|
this[key] = obj[key];
|
||||||
|
}
|
||||||
|
return new Proxy(this, this);
|
||||||
|
}
|
||||||
|
get(target, prop) {
|
||||||
|
let keys = Object.keys(this);
|
||||||
|
for (let key of keys) {
|
||||||
|
if (key.toLowerCase() === prop.toLowerCase()) {
|
||||||
|
return this[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set(target, prop, value) {
|
||||||
|
let keys = Object.keys(this);
|
||||||
|
for (let key of keys) {
|
||||||
|
if (key.toLowerCase() === prop.toLowerCase()) {
|
||||||
|
this[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this[prop] = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function allocate_str(str) {
|
||||||
|
return allocate(intArrayFromString(str), ALLOC_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
function allocate_array(array) {
|
||||||
|
return allocate(array, ALLOC_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//convert any data to a uint8array
|
||||||
|
function any_to_array(data) {
|
||||||
|
let data_array;
|
||||||
|
if (typeof data === "string") {
|
||||||
|
data_array = new TextEncoder().encode(data);
|
||||||
|
}
|
||||||
|
else if (data instanceof Blob) {
|
||||||
|
data.arrayBuffer().then(array_buffer => {
|
||||||
|
data_array = new Uint8Array(array_buffer);
|
||||||
|
this.send(data_array);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//any typedarray
|
||||||
|
else if (data instanceof ArrayBuffer) {
|
||||||
|
//dataview objects
|
||||||
|
if (ArrayBuffer.isView(data) && data instanceof DataView) {
|
||||||
|
data_array = new Uint8Array(data.buffer);
|
||||||
|
}
|
||||||
|
//regular arraybuffers
|
||||||
|
else {
|
||||||
|
data_array = new Uint8Array(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//regular typed arrays
|
||||||
|
else if (ArrayBuffer.isView(data)) {
|
||||||
|
data_array = Uint8Array.from(data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw "invalid data type";
|
||||||
|
}
|
||||||
|
|
||||||
|
return data_array;
|
||||||
|
}
|
|
@ -1,38 +1,30 @@
|
||||||
//class for custom websocket
|
class CurlWebSocket extends CustomWebSocket {
|
||||||
|
constructor(url, protocols=[], debug=false) {
|
||||||
class CurlWebSocket extends EventTarget {
|
super(url, protocols);
|
||||||
constructor(url, protocols=[], websocket_debug=false) {
|
|
||||||
super();
|
|
||||||
check_loaded(true);
|
check_loaded(true);
|
||||||
if (!url.startsWith("wss://") && !url.startsWith("ws://")) {
|
if (!url.startsWith("wss://") && !url.startsWith("ws://")) {
|
||||||
throw new SyntaxError("invalid url");
|
throw new SyntaxError("invalid url");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.url = url;
|
|
||||||
this.protocols = protocols;
|
this.protocols = protocols;
|
||||||
this.binaryType = "blob";
|
this.debug = debug;
|
||||||
this.recv_buffer = [];
|
this.recv_buffer = [];
|
||||||
this.websocket_debug = websocket_debug;
|
|
||||||
|
|
||||||
//legacy event handlers
|
|
||||||
this.onopen = () => {};
|
|
||||||
this.onerror = () => {};
|
|
||||||
this.onmessage = () => {};
|
|
||||||
this.onclose = () => {};
|
|
||||||
|
|
||||||
this.CONNECTING = 0;
|
|
||||||
this.OPEN = 1;
|
|
||||||
this.CLOSING = 2;
|
|
||||||
this.CLOSED = 3;
|
|
||||||
|
|
||||||
this.connect();
|
this.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
this.status = this.CONNECTING;
|
|
||||||
let data_callback = () => {};
|
let data_callback = () => {};
|
||||||
let finish_callback = (error, response_info) => {
|
let finish_callback = (error, response_info) => {
|
||||||
this.finish_callback(error, response_info);
|
if (error === 0) {
|
||||||
|
this.status = this.OPEN;
|
||||||
|
this.open_callback();
|
||||||
|
this.recv_loop();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.status = this.CLOSED;
|
||||||
|
this.cleanup(error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let options = {};
|
let options = {};
|
||||||
if (this.protocols) {
|
if (this.protocols) {
|
||||||
|
@ -40,23 +32,23 @@ class CurlWebSocket extends EventTarget {
|
||||||
"Sec-Websocket-Protocol": this.protocols.join(", "),
|
"Sec-Websocket-Protocol": this.protocols.join(", "),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (this.websocket_debug) {
|
if (this.debug) {
|
||||||
options._libcurl_verbose = 1;
|
options._libcurl_verbose = 1;
|
||||||
}
|
}
|
||||||
this.http_handle = perform_request(this.url, options, data_callback, finish_callback, null);
|
this.http_handle = perform_request(this.url, options, data_callback, finish_callback, null);
|
||||||
this.recv_loop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
recv() {
|
custom_recv() {
|
||||||
let buffer_size = 64*1024;
|
let buffer_size = 64*1024;
|
||||||
let result_ptr = _recv_from_websocket(this.http_handle, buffer_size);
|
let result_ptr = _recv_from_websocket(this.http_handle, buffer_size);
|
||||||
let data_ptr = _get_result_buffer(result_ptr);
|
let data_ptr = _get_result_buffer(result_ptr);
|
||||||
let result_code = _get_result_code(result_ptr);
|
let result_code = _get_result_code(result_ptr);
|
||||||
|
|
||||||
if (result_code == 0) { //CURLE_OK - data recieved
|
if (result_code == 0) { //CURLE_OK - data received
|
||||||
if (_get_result_closed(result_ptr)) {
|
if (_get_result_closed(result_ptr)) {
|
||||||
//this.pass_buffer();
|
_free(data_ptr);
|
||||||
this.close_callback();
|
_free(result_ptr);
|
||||||
|
this.cleanup();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,133 +61,43 @@ class CurlWebSocket extends EventTarget {
|
||||||
let full_data = merge_arrays(this.recv_buffer);
|
let full_data = merge_arrays(this.recv_buffer);
|
||||||
let is_text = _get_result_is_text(result_ptr)
|
let is_text = _get_result_is_text(result_ptr)
|
||||||
this.recv_buffer = [];
|
this.recv_buffer = [];
|
||||||
this.recv_callback(full_data, is_text);
|
return {
|
||||||
|
success: true,
|
||||||
|
data: full_data,
|
||||||
|
is_text: is_text
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result_code == 52) { //CURLE_GOT_NOTHING - socket closed
|
if (result_code == 52) { //CURLE_GOT_NOTHING - socket closed
|
||||||
this.close_callback();
|
this.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
_free(data_ptr);
|
_free(data_ptr);
|
||||||
_free(result_ptr);
|
_free(result_ptr);
|
||||||
}
|
|
||||||
|
|
||||||
recv_loop() {
|
return {
|
||||||
this.event_loop = setInterval(() => {
|
success: false,
|
||||||
this.recv();
|
data: null,
|
||||||
}, 1);
|
is_text: false
|
||||||
}
|
|
||||||
|
|
||||||
recv_callback(data, is_text=false) {
|
|
||||||
let converted;
|
|
||||||
if (is_text) {
|
|
||||||
converted = new TextDecoder().decode(data);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (this.binaryType == "blob") {
|
|
||||||
converted = new Blob(data);
|
|
||||||
}
|
|
||||||
else if (this.binaryType == "arraybuffer") {
|
|
||||||
converted = data.buffer;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw "invalid binaryType string";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let msg_event = new MessageEvent("message", {data: converted});
|
|
||||||
this.onmessage(msg_event);
|
|
||||||
this.dispatchEvent(msg_event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close_callback(error=false) {
|
cleanup(error=false) {
|
||||||
if (this.status == this.CLOSED) return;
|
if (this.http_handle) _cleanup_handle(this.http_handle);
|
||||||
this.status = this.CLOSED;
|
|
||||||
|
|
||||||
clearInterval(this.event_loop);
|
clearInterval(this.event_loop);
|
||||||
_cleanup_websocket();
|
this.close_callback(error);
|
||||||
|
|
||||||
if (error) {
|
|
||||||
let error_event = new Event("error");
|
|
||||||
this.dispatchEvent(error_event);
|
|
||||||
this.onerror(error_event);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let close_event = new CloseEvent("close");
|
|
||||||
this.dispatchEvent(close_event);
|
|
||||||
this.onclose(close_event);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
finish_callback(error, response_info) {
|
custom_send(data_array, is_text) {
|
||||||
this.status = this.OPEN;
|
|
||||||
if (error != 0) this.close_callback(true);
|
|
||||||
let open_event = new Event("open");
|
|
||||||
this.onopen(open_event);
|
|
||||||
this.dispatchEvent(open_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
send(data) {
|
|
||||||
let is_text = false;
|
|
||||||
if (this.status === this.CONNECTING) {
|
|
||||||
throw new DOMException("ws not ready yet");
|
|
||||||
}
|
|
||||||
if (this.status === this.CLOSED) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let data_array;
|
|
||||||
if (typeof data === "string") {
|
|
||||||
data_array = new TextEncoder().encode(data);
|
|
||||||
is_text = true;
|
|
||||||
}
|
|
||||||
else if (data instanceof Blob) {
|
|
||||||
data.arrayBuffer().then(array_buffer => {
|
|
||||||
data_array = new Uint8Array(array_buffer);
|
|
||||||
this.send(data_array);
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//any typedarray
|
|
||||||
else if (data instanceof ArrayBuffer) {
|
|
||||||
//dataview objects
|
|
||||||
if (ArrayBuffer.isView(data) && data instanceof DataView) {
|
|
||||||
data_array = new Uint8Array(data.buffer);
|
|
||||||
}
|
|
||||||
//regular arraybuffers
|
|
||||||
else {
|
|
||||||
data_array = new Uint8Array(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//regular typed arrays
|
|
||||||
else if (ArrayBuffer.isView(data)) {
|
|
||||||
data_array = Uint8Array.from(data);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw "invalid data type to be sent";
|
|
||||||
}
|
|
||||||
|
|
||||||
let data_ptr = allocate_array(data_array);
|
let data_ptr = allocate_array(data_array);
|
||||||
let data_len = data.length;
|
let data_len = data_array.length;
|
||||||
_send_to_websocket(this.http_handle, data_ptr, data_len, is_text);
|
_send_to_websocket(this.http_handle, data_ptr, data_len, is_text);
|
||||||
_free(data_ptr);
|
_free(data_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
close() {
|
custom_close() {
|
||||||
_close_websocket(this.http_handle);
|
this.cleanup();
|
||||||
}
|
this.status = this.CLOSED;
|
||||||
|
|
||||||
get readyState() {
|
|
||||||
return this.status;
|
|
||||||
}
|
|
||||||
get bufferedAmount() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
get protocol() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
get extensions() {
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -83,6 +83,13 @@ CURL* start_request(const char* url, const char* json_params, DataCallback data_
|
||||||
curl_easy_setopt(http_handle, CURLOPT_VERBOSE, 1L);
|
curl_easy_setopt(http_handle, CURLOPT_VERBOSE, 1L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcmp(key, "_connect_only") == 0) {
|
||||||
|
curl_easy_setopt(http_handle, CURLOPT_CONNECT_ONLY, 1L);
|
||||||
|
curl_easy_setopt(http_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||||
|
curl_easy_setopt(http_handle, CURLOPT_SSL_ENABLE_ALPN, 0L);
|
||||||
|
prevent_cleanup = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (strcmp(key, "method") == 0 && cJSON_IsString(item)) {
|
if (strcmp(key, "method") == 0 && cJSON_IsString(item)) {
|
||||||
curl_easy_setopt(http_handle, CURLOPT_CUSTOMREQUEST, item->valuestring);
|
curl_easy_setopt(http_handle, CURLOPT_CUSTOMREQUEST, item->valuestring);
|
||||||
}
|
}
|
||||||
|
|
24
client/libcurl/tls_socket.c
Normal file
24
client/libcurl/tls_socket.c
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "curl/curl.h"
|
||||||
|
#include "curl/easy.h"
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
struct WSResult* recv_from_socket(CURL* http_handle, int buffer_size) {
|
||||||
|
size_t nread;
|
||||||
|
char* buffer = malloc(buffer_size);
|
||||||
|
CURLcode res = curl_easy_recv(http_handle, buffer, buffer_size, &nread);
|
||||||
|
|
||||||
|
struct WSResult* result = malloc(sizeof(struct WSResult));
|
||||||
|
result->buffer_size = nread;
|
||||||
|
result->buffer = buffer;
|
||||||
|
result->res = (int) res;
|
||||||
|
result->closed = (nread == 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int send_to_socket(CURL* http_handle, const char* data, int data_len) {
|
||||||
|
size_t sent;
|
||||||
|
CURLcode res = curl_easy_send(http_handle, data, data_len, &sent);
|
||||||
|
return (int) res;
|
||||||
|
}
|
|
@ -37,7 +37,7 @@ void close_websocket(CURL* http_handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//clean up the http handle associated with the websocket, since the main loop can't do this automatically
|
//clean up the http handle associated with the websocket, since the main loop can't do this automatically
|
||||||
void cleanup_websocket(CURL* http_handle) {
|
void cleanup_handle(CURL* http_handle) {
|
||||||
struct RequestInfo *request_info;
|
struct RequestInfo *request_info;
|
||||||
curl_easy_getinfo(http_handle, CURLINFO_PRIVATE, &request_info);
|
curl_easy_getinfo(http_handle, CURLINFO_PRIVATE, &request_info);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "libcurl.js",
|
"name": "libcurl.js",
|
||||||
"version": "0.3.3",
|
"version": "0.4.0",
|
||||||
"description": "An experimental port of libcurl to WebAssembly for use in the browser.",
|
"description": "An experimental port of libcurl to WebAssembly for use in the browser.",
|
||||||
"main": "libcurl.mjs",
|
"main": "libcurl.mjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 51ad95a6d912ec404c20284f0cded40c0b5c4e62
|
Subproject commit 84b71a2882378dcb48d6d421fdb19290ebe0df23
|
|
@ -1 +1 @@
|
||||||
Subproject commit 65d312414aa896d8f9e18f48e8fe37b72d75ee5c
|
Subproject commit 3b0d432e89cff7eaa850ba8605b180189e237f1b
|
Loading…
Add table
Add a link
Reference in a new issue