diff options
author | 2022-03-20 04:38:04 -0700 | |
---|---|---|
committer | 2022-03-20 04:38:04 -0700 | |
commit | bc85dd2330763189e7f28941cc6e35903d6b49a9 (patch) | |
tree | f9ba5b865615c1f4a4032d28aea47e7b6fda4a7b | |
parent | a6b128590d104aa38a12ff20d820d02f0b6a8e6c (diff) | |
download | bun-bc85dd2330763189e7f28941cc6e35903d6b49a9.tar.gz bun-bc85dd2330763189e7f28941cc6e35903d6b49a9.tar.zst bun-bc85dd2330763189e7f28941cc6e35903d6b49a9.zip |
the events, they loop
24 files changed, 2391 insertions, 26 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json index dcd7498a0..bb90dc1fe 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -40,6 +40,7 @@ "src/deps/s2n-tls": true, "src/deps/boringssl": true, "src/deps/openssl": true, + "src/deps/uws": true, "src/deps/zlib": true, "src/deps/lol-html": true, "integration/snippets/package-json-exports/_node_modules_copy": true @@ -164,7 +164,7 @@ POSIX_PKG_MANAGER=sudo apt STRIP= ifeq ($(OS_NAME),darwin) -STRIP=strip +STRIP=/usr/bin/strip endif ifeq ($(OS_NAME),linux) @@ -188,7 +188,7 @@ MAC_INCLUDE_DIRS := -I$(WEBKIT_RELEASE_DIR)/JavaScriptCore/PrivateHeaders \ LINUX_INCLUDE_DIRS := -I$(JSC_INCLUDE_DIR) \ -Isrc/javascript/jsc/bindings/ -INCLUDE_DIRS := +INCLUDE_DIRS := -I$(BUN_DEPS_DIR)/uws @@ -243,7 +243,8 @@ CLANG_FLAGS = $(INCLUDE_DIRS) \ -DBUILDING_JSCONLY__ \ -DASSERT_ENABLED=0 \ -fvisibility=hidden \ - -fvisibility-inlines-hidden + -fvisibility-inlines-hidden \ + -fPIC -fno-semantic-interposition PLATFORM_LINKER_FLAGS = @@ -266,13 +267,13 @@ ARCHIVE_FILES_WITHOUT_LIBCRYPTO = $(MIMALLOC_FILE_PATH) \ $(BUN_DEPS_OUT_DIR)/libarchive.a \ $(BUN_DEPS_OUT_DIR)/libssl.a \ $(BUN_DEPS_OUT_DIR)/picohttpparser.o \ - $(BUN_DEPS_OUT_DIR)/liblolhtml.a + $(BUN_DEPS_OUT_DIR)/liblolhtml.a \ + $(BUN_DEPS_OUT_DIR)/uSockets.a \ + $(BUN_DEPS_OUT_DIR)/libuwsockets.o ARCHIVE_FILES = $(ARCHIVE_FILES_WITHOUT_LIBCRYPTO) $(BUN_DEPS_OUT_DIR)/libcrypto.boring.a - - STATIC_MUSL_FLAG ?= ifeq ($(OS_NAME), linux) @@ -289,7 +290,8 @@ PLATFORM_LINKER_FLAGS = \ -static-libgcc \ -fno-omit-frame-pointer $(CFLAGS) \ -Wl,--compress-debug-sections,zlib \ - ${STATIC_MUSL_FLAG} + ${STATIC_MUSL_FLAG} \ + -Wl,-Bsymbolic-functions ARCHIVE_FILES_WITHOUT_LIBCRYPTO += $(BUN_DEPS_OUT_DIR)/libbacktrace.a endif @@ -428,6 +430,19 @@ build-obj-wasm-small: build-obj-safe: $(ZIG) build obj -Drelease-safe +UWS_CC_FLAGS = -pthread -DLIBUS_USE_OPENSSL=1 -DLIBUS_USE_BORINGSSL=1 -DWITH_BORINGSSL=1 -Wpedantic -Wall -Wextra -Wsign-conversion -Wconversion -Isrc -IuSockets/src -DUWS_WITH_PROXY +UWS_CXX_FLAGS = $(UWS_CC_FLAGS) -std=gnu++17 +UWS_LDFLAGS = -I$(BUN_DEPS_DIR)/boringssl/include + +usockets: + rm -rf $(BUN_DEPS_DIR)/uws/uSockets/*.o $(BUN_DEPS_DIR)/uws/uSockets/*.a + cd $(BUN_DEPS_DIR)/uws/uSockets && \ + $(CC) $(CFLAGS) $(UWS_CC_FLAGS) $(UWS_LDFLAGS) $(DEFAULT_LINKER_FLAGS) $(PLATFORM_LINKER_FLAGS) -O3 -g -c -c src/*.c src/eventing/*.c src/crypto/*.c -flto && \ + $(CXX) $(CXXFLAGS) $(UWS_CXX_FLAGS) $(UWS_LDFLAGS) $(DEFAULT_LINKER_FLAGS) $(PLATFORM_LINKER_FLAGS) -O3 -g -c src/crypto/*.cpp && \ + ar rvs $(BUN_DEPS_OUT_DIR)/uSockets.a *.o + +uws: usockets + $(CXX) -I$(BUN_DEPS_DIR)/uws/uSockets/src $(CLANG_FLAGS) $(UWS_CXX_FLAGS) $(UWS_LDFLAGS) -c -flto -I$(BUN_DEPS_DIR) $(BUN_DEPS_OUT_DIR)/uSockets.a $(BUN_DEPS_DIR)/libuwsockets.cpp -o $(BUN_DEPS_OUT_DIR)/libuwsockets.o @@ -984,7 +999,8 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp -g \ -fno-exceptions \ -ffunction-sections -fdata-sections -g \ - -ferror-limit=1000 + -ferror-limit=1000 \ + -emit-llvm -flto -fno-semantic-interposition sizegen: $(CXX) src/javascript/jsc/headergen/sizegen.cpp -o $(BUN_TMP_DIR)/sizegen $(CLANG_FLAGS) -O1 @@ -116,6 +116,11 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar .path = pkgPath("src/jsc_stub.zig"), }; + var uws: std.build.Pkg = .{ + .name = "uws", + .path = pkgPath("src/deps/uws.zig"), + }; + var javascript_core = if (target.getOsTag() == .freestanding) javascript_core_stub else @@ -128,7 +133,7 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar io.dependencies = &.{analytics}; - javascript_core.dependencies = &.{ http, strings, picohttp, io }; + javascript_core.dependencies = &.{ http, strings, picohttp, io, uws }; http.dependencies = &.{ strings, picohttp, @@ -162,6 +167,7 @@ fn addInternalPackages(step: *std.build.LibExeObjStep, _: std.mem.Allocator, tar step.addPackage(crash_reporter); step.addPackage(datetime); step.addPackage(lol_html); + step.addPackage(uws); } var output_dir: []const u8 = ""; fn panicIfNotFound(comptime filepath: []const u8) []const u8 { @@ -519,6 +525,7 @@ pub fn linkObjectFiles(b: *std.build.Builder, obj: *std.build.LibExeObjStep, tar .{ "libbmalloc.a", "libbmalloc.a" }, .{ "libbacktrace.a", "libbacktrace.a" }, .{ "liblolhtml.a", "liblolhtml.a" }, + .{ "uSockets.a", "uSockets.a" }, }); for (dirs_to_search.slice()) |deps_path| { diff --git a/integration/scripts/bun.lockb b/integration/scripts/bun.lockb Binary files differindex 0dd841934..2d9937d57 100755 --- a/integration/scripts/bun.lockb +++ b/integration/scripts/bun.lockb diff --git a/packages/bun-error/bun.lockb b/packages/bun-error/bun.lockb Binary files differindex eede4f91d..1c7c459d1 100755 --- a/packages/bun-error/bun.lockb +++ b/packages/bun-error/bun.lockb diff --git a/src/bun_js.zig b/src/bun_js.zig index 716b1dfa7..618691afc 100644 --- a/src/bun_js.zig +++ b/src/bun_js.zig @@ -115,18 +115,14 @@ pub const Run = struct { pub fn start(this: *Run) void { var promise = this.vm.loadEntryPoint(this.entry_path) catch return; - this.vm.tick(); - - while (promise.status(this.vm.global.vm()) == .Pending) { - this.vm.tick(); - } if (promise.status(this.vm.global.vm()) == .Rejected) { this.vm.defaultErrorHandler(promise.result(this.vm.global.vm()), null); Global.exit(1); } - _ = promise.result(this.vm.global.vm()); + const result = promise.result(this.vm.global.vm()); + JSC.C.JSValueProtect(this.vm.global.ref(), result.asObjectRef()); if (this.vm.log.msgs.items.len > 0) { if (Output.enable_ansi_colors) { diff --git a/src/bundler/entry_points.zig b/src/bundler/entry_points.zig index 4fafbf4ec..376043122 100644 --- a/src/bundler/entry_points.zig +++ b/src/bundler/entry_points.zig @@ -185,9 +185,11 @@ pub const ServerEntryPoint = struct { \\//Auto-generated file \\import * as start from '{s}{s}'; \\export * from '{s}{s}'; + \\var entryNamespace = start; \\if ('default' in start && "__internalIsCommonJSNamespace" in globalThis && __internalIsCommonJSNamespace(start)) {{ - \\ start.default(); + \\ entryNamespace = start.default(); \\}} + \\if(entryNamespace && 'serverless' in entryNamespace) Bun.startServer(entryNamespace.serverless); , .{ dir_to_use, diff --git a/src/deps/_libusockets.h b/src/deps/_libusockets.h new file mode 100644 index 000000000..5456ff921 --- /dev/null +++ b/src/deps/_libusockets.h @@ -0,0 +1,289 @@ + +#ifndef LIBUWS_CAPI_HEADER +#define LIBUWS_CAPI_HEADER + +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <uws/uSockets/src/libusockets.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + /* These are not actual compression options */ + _COMPRESSOR_MASK = 0x00FF, + _DECOMPRESSOR_MASK = 0x0F00, + /* Disabled, shared, shared are "special" values */ + DISABLED = 0, + SHARED_COMPRESSOR = 1, + SHARED_DECOMPRESSOR = 1 << 8, + /* Highest 4 bits describe decompressor */ + DEDICATED_DECOMPRESSOR_32KB = 15 << 8, + DEDICATED_DECOMPRESSOR_16KB = 14 << 8, + DEDICATED_DECOMPRESSOR_8KB = 13 << 8, + DEDICATED_DECOMPRESSOR_4KB = 12 << 8, + DEDICATED_DECOMPRESSOR_2KB = 11 << 8, + DEDICATED_DECOMPRESSOR_1KB = 10 << 8, + DEDICATED_DECOMPRESSOR_512B = 9 << 8, + /* Same as 32kb */ + DEDICATED_DECOMPRESSOR = 15 << 8, + + /* Lowest 8 bit describe compressor */ + DEDICATED_COMPRESSOR_3KB = 9 << 4 | 1, + DEDICATED_COMPRESSOR_4KB = 9 << 4 | 2, + DEDICATED_COMPRESSOR_8KB = 10 << 4 | 3, + DEDICATED_COMPRESSOR_16KB = 11 << 4 | 4, + DEDICATED_COMPRESSOR_32KB = 12 << 4 | 5, + DEDICATED_COMPRESSOR_64KB = 13 << 4 | 6, + DEDICATED_COMPRESSOR_128KB = 14 << 4 | 7, + DEDICATED_COMPRESSOR_256KB = 15 << 4 | 8, + /* Same as 256kb */ + DEDICATED_COMPRESSOR = 15 << 4 | 8 +} uws_compress_options_t; + +typedef enum { + CONTINUATION = 0, + TEXT = 1, + BINARY = 2, + CLOSE = 8, + PING = 9, + PONG = 10 +} uws_opcode_t; + +typedef enum { BACKPRESSURE, SUCCESS, DROPPED } uws_sendstatus_t; + +typedef struct { + + int port; + const char *host; + int options; +} uws_app_listen_config_t; + +struct uws_app_s; +struct uws_req_s; +struct uws_res_s; +struct uws_websocket_s; +struct uws_header_iterator_s; +typedef struct uws_app_s uws_app_t; +typedef struct uws_req_s uws_req_t; +typedef struct uws_res_s uws_res_t; +typedef struct uws_socket_context_s uws_socket_context_t; +typedef struct uws_websocket_s uws_websocket_t; + +typedef void (*uws_websocket_handler)(uws_websocket_t *ws); +typedef void (*uws_websocket_message_handler)(uws_websocket_t *ws, + const char *message, + size_t length, + uws_opcode_t opcode); +typedef void (*uws_websocket_ping_pong_handler)(uws_websocket_t *ws, + const char *message, + size_t length); +typedef void (*uws_websocket_close_handler)(uws_websocket_t *ws, int code, + const char *message, size_t length); +typedef void (*uws_websocket_upgrade_handler)(uws_res_t *response, + uws_req_t *request, + uws_socket_context_t *context); + +typedef struct { + uws_compress_options_t compression; + /* Maximum message size we can receive */ + unsigned int maxPayloadLength; + /* 2 minutes timeout is good */ + unsigned short idleTimeout; + /* 64kb backpressure is probably good */ + unsigned int maxBackpressure; + bool closeOnBackpressureLimit; + /* This one depends on kernel timeouts and is a bad default */ + bool resetIdleTimeoutOnSend; + /* A good default, esp. for newcomers */ + bool sendPingsAutomatically; + /* Maximum socket lifetime in seconds before forced closure (defaults to + * disabled) */ + unsigned short maxLifetime; + + uws_websocket_upgrade_handler upgrade; + uws_websocket_handler open; + uws_websocket_message_handler message; + uws_websocket_handler drain; + uws_websocket_ping_pong_handler ping; + uws_websocket_ping_pong_handler pong; + uws_websocket_close_handler close; +} uws_socket_behavior_t; + +typedef void (*uws_listen_handler)(struct us_listen_socket_t *listen_socket, + uws_app_listen_config_t config, + void *user_data); +typedef void (*uws_method_handler)(uws_res_t *response, uws_req_t *request, + void *user_data); +typedef void (*uws_filter_handler)(uws_res_t *response, int, void *user_data); +typedef void (*uws_missing_server_handler)(const char *hostname, + void *user_data); +// Basic HTTP +uws_app_t *uws_create_app(int ssl, struct us_socket_context_options_t options); +void uws_app_destroy(int ssl, uws_app_t *app); +void uws_app_get(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data); +void uws_app_post(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data); +void uws_app_options(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data); +void uws_app_delete(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data); +void uws_app_patch(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data); +void uws_app_put(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data); +void uws_app_head(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data); +void uws_app_connect(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data); +void uws_app_trace(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data); +void uws_app_any(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data); + +void uws_app_run(int ssl, uws_app_t *); + +void uws_app_listen(int ssl, uws_app_t *app, int port, + uws_listen_handler handler, void *user_data); +void uws_app_listen_with_config(int ssl, uws_app_t *app, + uws_app_listen_config_t config, + uws_listen_handler handler, void *user_data); +bool uws_constructor_failed(int ssl, uws_app_t *app); +unsigned int uws_num_subscribers(int ssl, uws_app_t *app, const char *topic); +bool uws_publish(int ssl, uws_app_t *app, const char *topic, + size_t topic_length, const char *message, + size_t message_length, uws_opcode_t opcode, bool compress); +void *uws_get_native_handle(int ssl, uws_app_t *app); +void uws_remove_server_name(int ssl, uws_app_t *app, + const char *hostname_pattern); +void uws_add_server_name(int ssl, uws_app_t *app, const char *hostname_pattern); +void uws_add_server_name_with_options( + int ssl, uws_app_t *app, const char *hostname_pattern, + struct us_socket_context_options_t options); +void uws_missing_server_name(int ssl, uws_app_t *app, + uws_missing_server_handler handler, + void *user_data); +void uws_filter(int ssl, uws_app_t *app, uws_filter_handler handler, + void *user_data); + +// WebSocket +void uws_ws(int ssl, uws_app_t *app, const char *pattern, + uws_socket_behavior_t behavior); +void *uws_ws_get_user_data(int ssl, uws_websocket_t *ws); +void uws_ws_close(int ssl, uws_websocket_t *ws); +uws_sendstatus_t uws_ws_send(int ssl, uws_websocket_t *ws, const char *message, + size_t length, uws_opcode_t opcode); +uws_sendstatus_t uws_ws_send_with_options(int ssl, uws_websocket_t *ws, + const char *message, size_t length, + uws_opcode_t opcode, bool compress, + bool fin); +uws_sendstatus_t uws_ws_send_fragment(int ssl, uws_websocket_t *ws, + const char *message, size_t length, + bool compress); +uws_sendstatus_t uws_ws_send_first_fragment(int ssl, uws_websocket_t *ws, + const char *message, size_t length, + bool compress); +uws_sendstatus_t +uws_ws_send_first_fragment_with_opcode(int ssl, uws_websocket_t *ws, + const char *message, size_t length, + uws_opcode_t opcode, bool compress); +uws_sendstatus_t uws_ws_send_last_fragment(int ssl, uws_websocket_t *ws, + const char *message, size_t length, + bool compress); +void uws_ws_end(int ssl, uws_websocket_t *ws, int code, const char *message, + size_t length); +void uws_ws_cork(int ssl, uws_websocket_t *ws, void (*handler)(void *user_data), + void *user_data); +bool uws_ws_subscribe(int ssl, uws_websocket_t *ws, const char *topic, + size_t length); +bool uws_ws_unsubscribe(int ssl, uws_websocket_t *ws, const char *topic, + size_t length); +bool uws_ws_is_subscribed(int ssl, uws_websocket_t *ws, const char *topic, + size_t length); +void uws_ws_iterate_topics(int ssl, uws_websocket_t *ws, + void (*callback)(const char *topic, size_t length, + void *user_data), + void *user_data); +bool uws_ws_publish(int ssl, uws_websocket_t *ws, const char *topic, + size_t topic_length, const char *message, + size_t message_length); +bool uws_ws_publish_with_options(int ssl, uws_websocket_t *ws, + const char *topic, size_t topic_length, + const char *message, size_t message_length, + uws_opcode_t opcode, bool compress); +unsigned int uws_ws_get_buffered_amount(int ssl, uws_websocket_t *ws); +size_t uws_ws_get_remote_address(int ssl, uws_websocket_t *ws, + const char **dest); +size_t uws_ws_get_remote_address_as_text(int ssl, uws_websocket_t *ws, + const char **dest); + +// Response +void uws_res_end(int ssl, uws_res_t *res, const char *data, size_t length, + bool close_connection); +void uws_res_pause(int ssl, uws_res_t *res); +void uws_res_resume(int ssl, uws_res_t *res); +void uws_res_write_continue(int ssl, uws_res_t *res); +void uws_res_write_status(int ssl, uws_res_t *res, const char *status, + size_t length); +void uws_res_write_header(int ssl, uws_res_t *res, const char *key, + size_t key_length, const char *value, + size_t value_length); + +void uws_res_write_header_int(int ssl, uws_res_t *res, const char *key, + size_t key_length, uint64_t value); +void uws_res_end_without_body(int ssl, uws_res_t *res); +bool uws_res_write(int ssl, uws_res_t *res, const char *data, size_t length); +uintmax_t uws_res_get_write_offset(int ssl, uws_res_t *res); +bool uws_res_has_responded(int ssl, uws_res_t *res); +void uws_res_on_writable(int ssl, uws_res_t *res, + bool (*handler)(uws_res_t *res, uintmax_t, + void *opcional_data), + void *user_data); +void uws_res_on_aborted(int ssl, uws_res_t *res, + void (*handler)(uws_res_t *res, void *opcional_data), + void *opcional_data); +void uws_res_on_data(int ssl, uws_res_t *res, + void (*handler)(uws_res_t *res, const char *chunk, + size_t chunk_length, bool is_end, + void *opcional_data), + void *opcional_data); +void uws_res_upgrade(int ssl, uws_res_t *res, void *data, + const char *sec_web_socket_key, + size_t sec_web_socket_key_length, + const char *sec_web_socket_protocol, + size_t sec_web_socket_protocol_length, + const char *sec_web_socket_extensions, + size_t sec_web_socket_extensions_length, + uws_socket_context_t *ws); + +// Request +bool uws_req_is_ancient(uws_req_t *res); +bool uws_req_get_yield(uws_req_t *res); +void uws_req_set_field(uws_req_t *res, bool yield); +size_t uws_req_get_url(uws_req_t *res, const char **dest); +size_t uws_req_get_method(uws_req_t *res, const char **dest); +size_t uws_req_get_header(uws_req_t *res, const char *lower_case_header, + size_t lower_case_header_length, const char **dest); +size_t uws_req_get_query(uws_req_t *res, const char *key, size_t key_length, + const char **dest); +size_t uws_req_get_parameter(uws_req_t *res, unsigned short index, + const char **dest); + +struct us_loop_t *uws_get_loop(); + +void uws_loop_addPostHandler(us_loop_t *loop, void *ctx_, + void (*cb)(void *ctx, us_loop_t *loop)); +void uws_loop_removePostHandler(us_loop_t *loop, void *key); +void uws_loop_addPreHandler(us_loop_t *loop, void *key, + void (*cb)(void *ctx, us_loop_t *loop)); +void uws_loop_removePreHandler(us_loop_t *loop, void *ctx_); +void uws_loop_defer(us_loop_t *loop, void *ctx, void (*cb)(void *ctx)); + +#ifdef __cplusplus +} +#endif + +#endif
\ No newline at end of file diff --git a/src/deps/libuwsockets.cpp b/src/deps/libuwsockets.cpp new file mode 100644 index 000000000..ec082db43 --- /dev/null +++ b/src/deps/libuwsockets.cpp @@ -0,0 +1,984 @@ +#include "_libusockets.h" +#include <string_view> +#include <uws/src/App.h> + +extern "C" { + +uws_app_t *uws_create_app(int ssl, struct us_socket_context_options_t options) { + if (ssl) { + uWS::SocketContextOptions sco; + sco.ca_file_name = options.ca_file_name; + sco.cert_file_name = options.cert_file_name; + sco.dh_params_file_name = options.dh_params_file_name; + sco.key_file_name = options.key_file_name; + sco.passphrase = options.passphrase; + sco.ssl_prefer_low_memory_usage = options.ssl_prefer_low_memory_usage; + return (uws_app_t *)new uWS::SSLApp(sco); + } + + return (uws_app_t *)new uWS::App(); +} + +void uws_app_get(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->get(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->get(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } +} +void uws_app_post(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data) { + + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->post(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->post(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } +} +void uws_app_options(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->options(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->options(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } +} +void uws_app_delete(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->del(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->del(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } +} +void uws_app_patch(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->patch(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->patch(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } +} +void uws_app_put(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->put(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->put(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } +} +void uws_app_head(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->head(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->head(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } +} +void uws_app_connect(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->connect(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->connect(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } +} + +void uws_app_trace(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->trace(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->trace(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } +} +void uws_app_any(int ssl, uws_app_t *app, const char *pattern, + uws_method_handler handler, void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->any(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->any(pattern, [handler, user_data](auto *res, auto *req) { + handler((uws_res_t *)res, (uws_req_t *)req, user_data); + }); + } +} + +void uws_app_run(int ssl, uws_app_t *app) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->run(); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->run(); + } +} + +void uws_app_listen(int ssl, uws_app_t *app, int port, + uws_listen_handler handler, void *user_data) { + uws_app_listen_config_t config; + config.port = port; + config.host = nullptr; + config.options = 0; + + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->listen(port, [handler, config, + user_data](struct us_listen_socket_t *listen_socket) { + handler((struct us_listen_socket_t *)listen_socket, config, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + + uwsApp->listen(port, [handler, config, + user_data](struct us_listen_socket_t *listen_socket) { + handler((struct us_listen_socket_t *)listen_socket, config, user_data); + }); + } +} + +void uws_app_listen_with_config(int ssl, uws_app_t *app, + uws_app_listen_config_t config, + uws_listen_handler handler, void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->listen( + config.host, config.port, config.options, + [handler, config, user_data](struct us_listen_socket_t *listen_socket) { + handler((struct us_listen_socket_t *)listen_socket, config, + user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->listen( + config.host, config.port, config.options, + [handler, config, user_data](struct us_listen_socket_t *listen_socket) { + handler((struct us_listen_socket_t *)listen_socket, config, + user_data); + }); + } +} + +void uws_app_destroy(int ssl, uws_app_t *app) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + delete uwsApp; + } else { + + uWS::App *uwsApp = (uWS::App *)app; + delete uwsApp; + } +} + +bool uws_constructor_failed(int ssl, uws_app_t *app) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + if (!uwsApp) + return true; + return uwsApp->constructorFailed(); + } + uWS::App *uwsApp = (uWS::App *)app; + if (!uwsApp) + return true; + return uwsApp->constructorFailed(); +} + +unsigned int uws_num_subscribers(int ssl, uws_app_t *app, const char *topic) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + return uwsApp->numSubscribers(topic); + } + uWS::App *uwsApp = (uWS::App *)app; + return uwsApp->numSubscribers(topic); +} +bool uws_publish(int ssl, uws_app_t *app, const char *topic, + size_t topic_length, const char *message, + size_t message_length, uws_opcode_t opcode, bool compress) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + return uwsApp->publish(std::string_view(topic, topic_length), + std::string_view(message, message_length), + (unsigned char)opcode, compress); + } + uWS::App *uwsApp = (uWS::App *)app; + return uwsApp->publish(std::string_view(topic, topic_length), + std::string_view(message, message_length), + (unsigned char)opcode, compress); +} +void *uws_get_native_handle(int ssl, uws_app_t *app) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + return uwsApp->getNativeHandle(); + } + uWS::App *uwsApp = (uWS::App *)app; + return uwsApp->getNativeHandle(); +} +void uws_remove_server_name(int ssl, uws_app_t *app, + const char *hostname_pattern) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->removeServerName(hostname_pattern); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->removeServerName(hostname_pattern); + } +} +void uws_add_server_name(int ssl, uws_app_t *app, + const char *hostname_pattern) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->addServerName(hostname_pattern); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->addServerName(hostname_pattern); + } +} +void uws_add_server_name_with_options( + int ssl, uws_app_t *app, const char *hostname_pattern, + struct us_socket_context_options_t options) { + uWS::SocketContextOptions sco; + sco.ca_file_name = options.ca_file_name; + sco.cert_file_name = options.cert_file_name; + sco.dh_params_file_name = options.dh_params_file_name; + sco.key_file_name = options.key_file_name; + sco.passphrase = options.passphrase; + sco.ssl_prefer_low_memory_usage = options.ssl_prefer_low_memory_usage; + + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->addServerName(hostname_pattern, sco); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->addServerName(hostname_pattern, sco); + } +} + +void uws_missing_server_name(int ssl, uws_app_t *app, + uws_missing_server_handler handler, + void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->missingServerName( + [handler, user_data](auto hostname) { handler(hostname, user_data); }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->missingServerName( + [handler, user_data](auto hostname) { handler(hostname, user_data); }); + } +} +void uws_filter(int ssl, uws_app_t *app, uws_filter_handler handler, + void *user_data) { + if (ssl) { + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + uwsApp->filter([handler, user_data](auto res, auto i) { + handler((uws_res_t *)res, i, user_data); + }); + } else { + uWS::App *uwsApp = (uWS::App *)app; + + uwsApp->filter([handler, user_data](auto res, auto i) { + handler((uws_res_t *)res, i, user_data); + }); + } +} + +void uws_ws(int ssl, uws_app_t *app, const char *pattern, + uws_socket_behavior_t behavior) { + if (ssl) { + auto generic_handler = uWS::SSLApp::WebSocketBehavior<void *>{ + .compression = (uWS::CompressOptions)(uint64_t)behavior.compression, + .maxPayloadLength = behavior.maxPayloadLength, + .idleTimeout = behavior.idleTimeout, + .maxBackpressure = behavior.maxBackpressure, + .closeOnBackpressureLimit = behavior.closeOnBackpressureLimit, + .resetIdleTimeoutOnSend = behavior.resetIdleTimeoutOnSend, + .sendPingsAutomatically = behavior.sendPingsAutomatically, + .maxLifetime = behavior.maxLifetime, + }; + + if (behavior.upgrade) + generic_handler.upgrade = [behavior](auto *res, auto *req, + auto *context) { + behavior.upgrade((uws_res_t *)res, (uws_req_t *)req, + (uws_socket_context_t *)context); + }; + if (behavior.open) + generic_handler.open = [behavior](auto *ws) { + behavior.open((uws_websocket_t *)ws); + }; + if (behavior.message) + generic_handler.message = [behavior](auto *ws, auto message, + auto opcode) { + behavior.message((uws_websocket_t *)ws, message.data(), + message.length(), (uws_opcode_t)opcode); + }; + if (behavior.drain) + generic_handler.drain = [behavior](auto *ws) { + behavior.drain((uws_websocket_t *)ws); + }; + if (behavior.ping) + generic_handler.ping = [behavior](auto *ws, auto message) { + behavior.ping((uws_websocket_t *)ws, message.data(), message.length()); + }; + if (behavior.pong) + generic_handler.pong = [behavior](auto *ws, auto message) { + behavior.pong((uws_websocket_t *)ws, message.data(), message.length()); + }; + if (behavior.close) + generic_handler.close = [behavior](auto *ws, int code, auto message) { + behavior.close((uws_websocket_t *)ws, code, message.data(), + message.length()); + }; + uWS::SSLApp *uwsApp = (uWS::SSLApp *)app; + + uwsApp->ws<void *>(pattern, std::move(generic_handler)); + } else { + auto generic_handler = uWS::App::WebSocketBehavior<void *>{ + .compression = (uWS::CompressOptions)(uint64_t)behavior.compression, + .maxPayloadLength = behavior.maxPayloadLength, + .idleTimeout = behavior.idleTimeout, + .maxBackpressure = behavior.maxBackpressure, + .closeOnBackpressureLimit = behavior.closeOnBackpressureLimit, + .resetIdleTimeoutOnSend = behavior.resetIdleTimeoutOnSend, + .sendPingsAutomatically = behavior.sendPingsAutomatically, + .maxLifetime = behavior.maxLifetime, + }; + + if (behavior.upgrade) + generic_handler.upgrade = [behavior](auto *res, auto *req, + auto *context) { + behavior.upgrade((uws_res_t *)res, (uws_req_t *)req, + (uws_socket_context_t *)context); + }; + if (behavior.open) + generic_handler.open = [behavior](auto *ws) { + behavior.open((uws_websocket_t *)ws); + }; + if (behavior.message) + generic_handler.message = [behavior](auto *ws, auto message, + auto opcode) { + behavior.message((uws_websocket_t *)ws, message.data(), + message.length(), (uws_opcode_t)opcode); + }; + if (behavior.drain) + generic_handler.drain = [behavior](auto *ws) { + behavior.drain((uws_websocket_t *)ws); + }; + if (behavior.ping) + generic_handler.ping = [behavior](auto *ws, auto message) { + behavior.ping((uws_websocket_t *)ws, message.data(), message.length()); + }; + if (behavior.pong) + generic_handler.pong = [behavior](auto *ws, auto message) { + behavior.pong((uws_websocket_t *)ws, message.data(), message.length()); + }; + if (behavior.close) + generic_handler.close = [behavior](auto *ws, int code, auto message) { + behavior.close((uws_websocket_t *)ws, code, message.data(), + message.length()); + }; + uWS::App *uwsApp = (uWS::App *)app; + uwsApp->ws<void *>(pattern, std::move(generic_handler)); + } +} + +void *uws_ws_get_user_data(int ssl, uws_websocket_t *ws) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return *uws->getUserData(); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return *uws->getUserData(); +} + +void uws_ws_close(int ssl, uws_websocket_t *ws) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + uws->close(); + } else { + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + uws->close(); + } +} + +uws_sendstatus_t uws_ws_send(int ssl, uws_websocket_t *ws, const char *message, + size_t length, uws_opcode_t opcode) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return (uws_sendstatus_t)uws->send(std::string_view(message, length), + (uWS::OpCode)(unsigned char)opcode); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return (uws_sendstatus_t)uws->send(std::string_view(message, length), + (uWS::OpCode)(unsigned char)opcode); +} + +uws_sendstatus_t uws_ws_send_with_options(int ssl, uws_websocket_t *ws, + const char *message, size_t length, + uws_opcode_t opcode, bool compress, + bool fin) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return (uws_sendstatus_t)uws->send(std::string_view(message), + (uWS::OpCode)(unsigned char)opcode, + compress, fin); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return (uws_sendstatus_t)uws->send(std::string_view(message), + (uWS::OpCode)(unsigned char)opcode, + compress, fin); +} + +uws_sendstatus_t uws_ws_send_fragment(int ssl, uws_websocket_t *ws, + const char *message, size_t length, + bool compress) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return (uws_sendstatus_t)uws->sendFragment( + std::string_view(message, length), compress); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return (uws_sendstatus_t)uws->sendFragment(std::string_view(message, length), + compress); +} +uws_sendstatus_t uws_ws_send_first_fragment(int ssl, uws_websocket_t *ws, + const char *message, size_t length, + bool compress) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return (uws_sendstatus_t)uws->sendFirstFragment( + std::string_view(message), uWS::OpCode::BINARY, compress); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return (uws_sendstatus_t)uws->sendFirstFragment( + std::string_view(message), uWS::OpCode::BINARY, compress); +} +uws_sendstatus_t +uws_ws_send_first_fragment_with_opcode(int ssl, uws_websocket_t *ws, + const char *message, size_t length, + uws_opcode_t opcode, bool compress) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return (uws_sendstatus_t)uws->sendFirstFragment( + std::string_view(message, length), (uWS::OpCode)(unsigned char)opcode, + compress); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return (uws_sendstatus_t)uws->sendFirstFragment( + std::string_view(message, length), (uWS::OpCode)(unsigned char)opcode, + compress); +} +uws_sendstatus_t uws_ws_send_last_fragment(int ssl, uws_websocket_t *ws, + const char *message, size_t length, + bool compress) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return (uws_sendstatus_t)uws->sendLastFragment( + std::string_view(message, length), compress); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return (uws_sendstatus_t)uws->sendLastFragment( + std::string_view(message, length), compress); +} + +void uws_ws_end(int ssl, uws_websocket_t *ws, int code, const char *message, + size_t length) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + uws->end(code, std::string_view(message, length)); + } else { + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + uws->end(code, std::string_view(message, length)); + } +} + +void uws_ws_cork(int ssl, uws_websocket_t *ws, void (*handler)(void *user_data), + void *user_data) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + uws->cork([handler, user_data]() { handler(user_data); }); + } else { + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + + uws->cork([handler, user_data]() { handler(user_data); }); + } +} +bool uws_ws_subscribe(int ssl, uws_websocket_t *ws, const char *topic, + size_t length) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return uws->subscribe(std::string_view(topic, length)); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return uws->subscribe(std::string_view(topic, length)); +} +bool uws_ws_unsubscribe(int ssl, uws_websocket_t *ws, const char *topic, + size_t length) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return uws->unsubscribe(std::string_view(topic, length)); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return uws->unsubscribe(std::string_view(topic, length)); +} + +bool uws_ws_is_subscribed(int ssl, uws_websocket_t *ws, const char *topic, + size_t length) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return uws->isSubscribed(std::string_view(topic, length)); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return uws->isSubscribed(std::string_view(topic, length)); +} +void uws_ws_iterate_topics(int ssl, uws_websocket_t *ws, + void (*callback)(const char *topic, size_t length, + void *user_data), + void *user_data) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + uws->iterateTopics([callback, user_data](auto topic) { + callback(topic.data(), topic.length(), user_data); + }); + } else { + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + + uws->iterateTopics([callback, user_data](auto topic) { + callback(topic.data(), topic.length(), user_data); + }); + } +} + +bool uws_ws_publish(int ssl, uws_websocket_t *ws, const char *topic, + size_t topic_length, const char *message, + size_t message_length) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return uws->publish(std::string_view(topic, topic_length), + std::string_view(message, message_length)); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return uws->publish(std::string_view(topic, topic_length), + std::string_view(message, message_length)); +} + +bool uws_ws_publish_with_options(int ssl, uws_websocket_t *ws, + const char *topic, size_t topic_length, + const char *message, size_t message_length, + uws_opcode_t opcode, bool compress) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return uws->publish(std::string_view(topic, topic_length), + std::string_view(message, message_length), + (uWS::OpCode)(unsigned char)opcode, compress); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return uws->publish(std::string_view(topic, topic_length), + std::string_view(message, message_length), + (uWS::OpCode)(unsigned char)opcode, compress); +} + +unsigned int uws_ws_get_buffered_amount(int ssl, uws_websocket_t *ws) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + return uws->getBufferedAmount(); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + return uws->getBufferedAmount(); +} + +size_t uws_ws_get_remote_address(int ssl, uws_websocket_t *ws, + const char **dest) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + std::string_view value = uws->getRemoteAddress(); + *dest = value.data(); + return value.length(); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + + std::string_view value = uws->getRemoteAddress(); + *dest = value.data(); + return value.length(); +} + +size_t uws_ws_get_remote_address_as_text(int ssl, uws_websocket_t *ws, + const char **dest) { + if (ssl) { + uWS::WebSocket<true, true, void *> *uws = + (uWS::WebSocket<true, true, void *> *)ws; + + std::string_view value = uws->getRemoteAddressAsText(); + *dest = value.data(); + return value.length(); + } + uWS::WebSocket<false, true, void *> *uws = + (uWS::WebSocket<false, true, void *> *)ws; + + std::string_view value = uws->getRemoteAddressAsText(); + *dest = value.data(); + return value.length(); +} + +void uws_res_end(int ssl, uws_res_t *res, const char *data, size_t length, + bool close_connection) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + uwsRes->end(std::string_view(data, length), close_connection); + } else { + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + uwsRes->end(std::string_view(data, length), close_connection); + } +} + +void uws_res_pause(int ssl, uws_res_t *res) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + uwsRes->pause(); + } else { + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + uwsRes->pause(); + } +} + +void uws_res_resume(int ssl, uws_res_t *res) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + uwsRes->pause(); + } else { + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + uwsRes->pause(); + } +} + +void uws_res_write_continue(int ssl, uws_res_t *res) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + uwsRes->writeContinue(); + } else { + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + uwsRes->writeContinue(); + } +} + +void uws_res_write_status(int ssl, uws_res_t *res, const char *status, + size_t length) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + uwsRes->writeStatus(std::string_view(status, length)); + } else { + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + uwsRes->writeStatus(std::string_view(status, length)); + } +} + +void uws_res_write_header(int ssl, uws_res_t *res, const char *key, + size_t key_length, const char *value, + size_t value_length) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + uwsRes->writeHeader(std::string_view(key, key_length), + std::string_view(value, value_length)); + } else { + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + uwsRes->writeHeader(std::string_view(key, key_length), + std::string_view(value, value_length)); + } +} +void uws_res_write_header_int(int ssl, uws_res_t *res, const char *key, + size_t key_length, uint64_t value) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + uwsRes->writeHeader(std::string_view(key, key_length), value); + } else { + + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + uwsRes->writeHeader(std::string_view(key, key_length), value); + } +} + +void uws_res_end_without_body(int ssl, uws_res_t *res) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + uwsRes->endWithoutBody(0); + } else { + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + uwsRes->endWithoutBody(0); + } +} + +bool uws_res_write(int ssl, uws_res_t *res, const char *data, size_t length) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + return uwsRes->write(std::string_view(data)); + } + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + return uwsRes->write(std::string_view(data)); +} +uintmax_t uws_res_get_write_offset(int ssl, uws_res_t *res) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + return uwsRes->getWriteOffset(); + } + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + return uwsRes->getWriteOffset(); +} + +bool uws_res_has_responded(int ssl, uws_res_t *res) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + return uwsRes->hasResponded(); + } + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + return uwsRes->hasResponded(); +} + +void uws_res_on_writable(int ssl, uws_res_t *res, + bool (*handler)(uws_res_t *res, uintmax_t, + void *opcional_data), + void *opcional_data) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + uwsRes->onWritable([handler, res, opcional_data](uintmax_t a) { + return handler(res, a, opcional_data); + }); + } else { + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + uwsRes->onWritable([handler, res, opcional_data](uintmax_t a) { + return handler(res, a, opcional_data); + }); + } +} + +void uws_res_on_aborted(int ssl, uws_res_t *res, + void (*handler)(uws_res_t *res, void *opcional_data), + void *opcional_data) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + uwsRes->onAborted( + [handler, res, opcional_data] { handler(res, opcional_data); }); + } else { + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + uwsRes->onAborted( + [handler, res, opcional_data] { handler(res, opcional_data); }); + } +} + +void uws_res_on_data(int ssl, uws_res_t *res, + void (*handler)(uws_res_t *res, const char *chunk, + size_t chunk_length, bool is_end, + void *opcional_data), + void *opcional_data) { + if (ssl) { + uWS::HttpResponse<true> *uwsRes = (uWS::HttpResponse<true> *)res; + uwsRes->onData([handler, res, opcional_data](auto chunk, bool is_end) { + handler(res, chunk.data(), chunk.length(), is_end, opcional_data); + }); + } else { + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + uwsRes->onData([handler, res, opcional_data](auto chunk, bool is_end) { + handler(res, chunk.data(), chunk.length(), is_end, opcional_data); + }); + } +} + +bool uws_req_is_ancient(uws_req_t *res) { + uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; + return uwsReq->isAncient(); +} + +bool uws_req_get_yield(uws_req_t *res) { + uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; + return uwsReq->getYield(); +} + +void uws_req_set_field(uws_req_t *res, bool yield) { + uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; + return uwsReq->setYield(yield); +} + +size_t uws_req_get_url(uws_req_t *res, const char **dest) { + uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; + std::string_view value = uwsReq->getUrl(); + *dest = value.data(); + return value.length(); +} + +size_t uws_req_get_method(uws_req_t *res, const char **dest) { + uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; + std::string_view value = uwsReq->getMethod(); + *dest = value.data(); + return value.length(); +} + +size_t uws_req_get_header(uws_req_t *res, const char *lower_case_header, + size_t lower_case_header_length, const char **dest) { + uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; + + std::string_view value = uwsReq->getHeader( + std::string_view(lower_case_header, lower_case_header_length)); + *dest = value.data(); + return value.length(); +} + +size_t uws_req_get_query(uws_req_t *res, const char *key, size_t key_length, + const char **dest) { + uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; + + std::string_view value = uwsReq->getQuery(std::string_view(key, key_length)); + *dest = value.data(); + return value.length(); +} + +size_t uws_req_get_parameter(uws_req_t *res, unsigned short index, + const char **dest) { + uWS::HttpRequest *uwsReq = (uWS::HttpRequest *)res; + std::string_view value = uwsReq->getParameter(index); + *dest = value.data(); + return value.length(); +} + +void uws_res_upgrade(int ssl, uws_res_t *res, void *data, + const char *sec_web_socket_key, + size_t sec_web_socket_key_length, + const char *sec_web_socket_protocol, + size_t sec_web_socket_protocol_length, + const char *sec_web_socket_extensions, + size_t sec_web_socket_extensions_length, + uws_socket_context_t *ws) { + uWS::HttpResponse<false> *uwsRes = (uWS::HttpResponse<false> *)res; + + uwsRes->template upgrade<void *>( + data ? std::move(data) : NULL, + std::string_view(sec_web_socket_key, sec_web_socket_key_length), + std::string_view(sec_web_socket_protocol, sec_web_socket_protocol_length), + std::string_view(sec_web_socket_extensions, + sec_web_socket_extensions_length), + (struct us_socket_context_t *)ws); +} + +struct us_loop_t *uws_get_loop() { + return (struct us_loop_t *)uWS::Loop::get(); +} + +void uws_loop_addPostHandler(us_loop_t *loop, void *ctx_, + void (*cb)(void *ctx, us_loop_t *loop)) { + uWS::Loop *uwsLoop = (uWS::Loop *)loop; + uwsLoop->addPostHandler(ctx_, [ctx_, cb](uWS::Loop *uwsLoop_) { + cb(ctx_, (us_loop_t *)uwsLoop_); + }); +} +void uws_loop_removePostHandler(us_loop_t *loop, void *key) { + uWS::Loop *uwsLoop = (uWS::Loop *)loop; + uwsLoop->removePostHandler(key); +} +void uws_loop_addPreHandler(us_loop_t *loop, void *ctx_, + void (*cb)(void *ctx, us_loop_t *loop)) { + uWS::Loop *uwsLoop = (uWS::Loop *)loop; + uwsLoop->addPreHandler(ctx_, [ctx_, cb](uWS::Loop *uwsLoop_) { + cb(ctx_, (us_loop_t *)uwsLoop_); + }); +} +void uws_loop_removePreHandler(us_loop_t *loop, void *ctx_) { + uWS::Loop *uwsLoop = (uWS::Loop *)loop; + uwsLoop->removePreHandler(ctx_); +} +void uws_loop_defer(us_loop_t *loop, void *ctx, void (*cb)(void *ctx)) { + uWS::Loop *uwsLoop = (uWS::Loop *)loop; + uwsLoop->defer([ctx, cb]() { cb(ctx); }); +} +}
\ No newline at end of file diff --git a/src/deps/uws.zig b/src/deps/uws.zig new file mode 100644 index 000000000..fc7a32865 --- /dev/null +++ b/src/deps/uws.zig @@ -0,0 +1,626 @@ +pub const u_int8_t = u8; +pub const u_int16_t = c_ushort; +pub const u_int32_t = c_uint; +pub const u_int64_t = c_ulonglong; +pub const LIBUS_LISTEN_DEFAULT: c_int = 0; +pub const LIBUS_LISTEN_EXCLUSIVE_PORT: c_int = 1; +pub const us_socket_t = opaque {}; +pub const us_timer_t = opaque {}; +pub const us_socket_context_t = opaque {}; +pub const Loop = opaque { + pub fn get() ?*Loop { + return uws_get_loop(); + } + + pub fn wakeup(this: *Loop) void { + return us_wakeup_loop(this); + } + + pub fn nextTick(this: *Loop, comptime UserType: type, user_data: UserType, comptime deferCallback: fn (ctx: UserType) void) void { + const Handler = struct { + pub fn callback(data: *anyopaque) callconv(.C) void { + deferCallback(@ptrCast(UserType, @alignCast(@alignOf(UserType), data))); + } + }; + uws_loop_defer(this, user_data, Handler.callback); + } + + extern fn uws_loop_defer(loop: *Loop, ctx: *anyopaque, cb: fn (ctx: *anyopaque) callconv(.C) void) void; + + extern fn uws_get_loop() ?*Loop; + extern fn us_create_loop(hint: ?*anyopaque, wakeup_cb: ?fn (?*Loop) callconv(.C) void, pre_cb: ?fn (?*Loop) callconv(.C) void, post_cb: ?fn (?*Loop) callconv(.C) void, ext_size: c_uint) ?*Loop; + extern fn us_loop_free(loop: ?*Loop) void; + extern fn us_loop_ext(loop: ?*Loop) ?*anyopaque; + extern fn us_loop_run(loop: ?*Loop) void; + extern fn us_wakeup_loop(loop: ?*Loop) void; + extern fn us_loop_integrate(loop: ?*Loop) void; + extern fn us_loop_iteration_number(loop: ?*Loop) c_longlong; +}; +const uintmax_t = c_ulong; + +extern fn us_create_timer(loop: ?*Loop, fallthrough: c_int, ext_size: c_uint) ?*us_timer_t; +extern fn us_timer_ext(timer: ?*us_timer_t) ?*anyopaque; +extern fn us_timer_close(timer: ?*us_timer_t) void; +extern fn us_timer_set(timer: ?*us_timer_t, cb: ?fn (?*us_timer_t) callconv(.C) void, ms: c_int, repeat_ms: c_int) void; +extern fn us_timer_loop(t: ?*us_timer_t) ?*Loop; +pub const us_socket_context_options_t = extern struct { + key_file_name: [*c]const u8 = null, + cert_file_name: [*c]const u8 = null, + passphrase: [*c]const u8 = null, + dh_params_file_name: [*c]const u8 = null, + ca_file_name: [*c]const u8 = null, + ssl_prefer_low_memory_usage: c_int = 0, +}; + +extern fn us_socket_context_timestamp(ssl: c_int, context: ?*us_socket_context_t) c_ushort; +extern fn us_socket_context_add_server_name(ssl: c_int, context: ?*us_socket_context_t, hostname_pattern: [*c]const u8, options: us_socket_context_options_t) void; +extern fn us_socket_context_remove_server_name(ssl: c_int, context: ?*us_socket_context_t, hostname_pattern: [*c]const u8) void; +extern fn us_socket_context_on_server_name(ssl: c_int, context: ?*us_socket_context_t, cb: ?fn (?*us_socket_context_t, [*c]const u8) callconv(.C) void) void; +extern fn us_socket_context_get_native_handle(ssl: c_int, context: ?*us_socket_context_t) ?*anyopaque; +extern fn us_create_socket_context(ssl: c_int, loop: ?*Loop, ext_size: c_int, options: us_socket_context_options_t) ?*us_socket_context_t; +extern fn us_socket_context_free(ssl: c_int, context: ?*us_socket_context_t) void; +extern fn us_socket_context_on_open(ssl: c_int, context: ?*us_socket_context_t, on_open: ?fn (?*us_socket_t, c_int, [*c]u8, c_int) callconv(.C) ?*us_socket_t) void; +extern fn us_socket_context_on_close(ssl: c_int, context: ?*us_socket_context_t, on_close: ?fn (?*us_socket_t, c_int, ?*anyopaque) callconv(.C) ?*us_socket_t) void; +extern fn us_socket_context_on_data(ssl: c_int, context: ?*us_socket_context_t, on_data: ?fn (?*us_socket_t, [*c]u8, c_int) callconv(.C) ?*us_socket_t) void; +extern fn us_socket_context_on_writable(ssl: c_int, context: ?*us_socket_context_t, on_writable: ?fn (?*us_socket_t) callconv(.C) ?*us_socket_t) void; +extern fn us_socket_context_on_timeout(ssl: c_int, context: ?*us_socket_context_t, on_timeout: ?fn (?*us_socket_t) callconv(.C) ?*us_socket_t) void; +extern fn us_socket_context_on_connect_error(ssl: c_int, context: ?*us_socket_context_t, on_connect_error: ?fn (?*us_socket_t, c_int) callconv(.C) ?*us_socket_t) void; +extern fn us_socket_context_on_end(ssl: c_int, context: ?*us_socket_context_t, on_end: ?fn (?*us_socket_t) callconv(.C) ?*us_socket_t) void; +extern fn us_socket_context_ext(ssl: c_int, context: ?*us_socket_context_t) ?*anyopaque; + +extern fn us_socket_context_listen(ssl: c_int, context: ?*us_socket_context_t, host: [*c]const u8, port: c_int, options: c_int, socket_ext_size: c_int) ?*listen_socket_t; + +extern fn us_socket_context_connect(ssl: c_int, context: ?*us_socket_context_t, host: [*c]const u8, port: c_int, source_host: [*c]const u8, options: c_int, socket_ext_size: c_int) ?*us_socket_t; +extern fn us_socket_is_established(ssl: c_int, s: ?*us_socket_t) c_int; +extern fn us_socket_close_connecting(ssl: c_int, s: ?*us_socket_t) ?*us_socket_t; +extern fn us_socket_context_loop(ssl: c_int, context: ?*us_socket_context_t) ?*Loop; +extern fn us_socket_context_adopt_socket(ssl: c_int, context: ?*us_socket_context_t, s: ?*us_socket_t, ext_size: c_int) ?*us_socket_t; +extern fn us_create_child_socket_context(ssl: c_int, context: ?*us_socket_context_t, context_ext_size: c_int) ?*us_socket_context_t; + +pub const Poll = opaque { + extern fn us_create_poll(loop: ?*Loop, fallthrough: c_int, ext_size: c_uint) ?*Poll; + extern fn us_poll_free(p: ?*Poll, loop: ?*Loop) void; + extern fn us_poll_init(p: ?*Poll, fd: c_int, poll_type: c_int) void; + extern fn us_poll_start(p: ?*Poll, loop: ?*Loop, events: c_int) void; + extern fn us_poll_change(p: ?*Poll, loop: ?*Loop, events: c_int) void; + extern fn us_poll_stop(p: ?*Poll, loop: ?*Loop) void; + extern fn us_poll_events(p: ?*Poll) c_int; + extern fn us_poll_ext(p: ?*Poll) ?*anyopaque; + extern fn us_poll_fd(p: ?*Poll) c_int; + extern fn us_poll_resize(p: ?*Poll, loop: ?*Loop, ext_size: c_uint) ?*Poll; +}; + +extern fn us_socket_get_native_handle(ssl: c_int, s: ?*us_socket_t) ?*anyopaque; +extern fn us_socket_write(ssl: c_int, s: ?*us_socket_t, data: [*c]const u8, length: c_int, msg_more: c_int) c_int; +extern fn us_socket_timeout(ssl: c_int, s: ?*us_socket_t, seconds: c_uint) void; +extern fn us_socket_ext(ssl: c_int, s: ?*us_socket_t) ?*anyopaque; +extern fn us_socket_context(ssl: c_int, s: ?*us_socket_t) ?*us_socket_context_t; +extern fn us_socket_flush(ssl: c_int, s: ?*us_socket_t) void; +extern fn us_socket_shutdown(ssl: c_int, s: ?*us_socket_t) void; +extern fn us_socket_shutdown_read(ssl: c_int, s: ?*us_socket_t) void; +extern fn us_socket_is_shut_down(ssl: c_int, s: ?*us_socket_t) c_int; +extern fn us_socket_is_closed(ssl: c_int, s: ?*us_socket_t) c_int; +extern fn us_socket_close(ssl: c_int, s: ?*us_socket_t, code: c_int, reason: ?*anyopaque) ?*us_socket_t; +extern fn us_socket_local_port(ssl: c_int, s: ?*us_socket_t) c_int; +extern fn us_socket_remote_address(ssl: c_int, s: ?*us_socket_t, buf: [*c]u8, length: [*c]c_int) void; +pub const uws_app_s = opaque {}; +pub const uws_req_s = opaque {}; +pub const uws_websocket_s = opaque {}; +pub const uws_header_iterator_s = opaque {}; +pub const uws_app_t = uws_app_s; + +pub const uws_socket_context_s = opaque {}; +pub const uws_socket_context_t = uws_socket_context_s; +pub const uws_websocket_t = uws_websocket_s; +pub const uws_websocket_handler = ?fn (?*uws_websocket_t) callconv(.C) void; +pub const uws_websocket_message_handler = ?fn (?*uws_websocket_t, [*c]const u8, usize, uws_opcode_t) callconv(.C) void; +pub const uws_websocket_ping_pong_handler = ?fn (?*uws_websocket_t, [*c]const u8, usize) callconv(.C) void; +pub const uws_websocket_close_handler = ?fn (?*uws_websocket_t, c_int, [*c]const u8, usize) callconv(.C) void; +pub const uws_websocket_upgrade_handler = ?fn (*uws_res, ?*Request, ?*uws_socket_context_t) callconv(.C) void; +pub const uws_socket_behavior_t = extern struct { + compression: uws_compress_options_t, + maxPayloadLength: c_uint, + idleTimeout: c_ushort, + maxBackpressure: c_uint, + closeOnBackpressureLimit: bool, + resetIdleTimeoutOnSend: bool, + sendPingsAutomatically: bool, + maxLifetime: c_ushort, + upgrade: uws_websocket_upgrade_handler, + open: uws_websocket_handler, + message: uws_websocket_message_handler, + drain: uws_websocket_handler, + ping: uws_websocket_ping_pong_handler, + pong: uws_websocket_ping_pong_handler, + close: uws_websocket_close_handler, +}; +pub const uws_listen_handler = ?fn (?*listen_socket_t, uws_app_listen_config_t, ?*anyopaque) callconv(.C) void; +pub const uws_method_handler = ?fn (*uws_res, *Request, ?*anyopaque) callconv(.C) void; +pub const uws_filter_handler = ?fn (*uws_res, c_int, ?*anyopaque) callconv(.C) void; +pub const uws_missing_server_handler = ?fn ([*c]const u8, ?*anyopaque) callconv(.C) void; + +pub const Request = opaque { + pub fn isAncient(req: *Request) bool { + return uws_req_is_ancient(req); + } + pub fn getYield(req: *Request) bool { + return uws_req_get_yield(req); + } + pub fn setYield(req: *Request, yield: bool) void { + uws_req_set_field(req, yield); + } + pub fn url(req: *Request) []const u8 { + var ptr: [*]const u8 = undefined; + return ptr[0..req.uws_req_get_url(&ptr)]; + } + pub fn method(req: *Request) []const u8 { + var ptr: [*]const u8 = undefined; + return ptr[0..req.uws_req_get_method(&ptr)]; + } + pub fn header(req: *Request, name: []const u8) []const u8 { + var ptr: [*]const u8 = undefined; + return ptr[0..req.uws_req_get_header(req, name.ptr, name.len, &ptr)]; + } + pub fn query(req: *Request, name: []const u8) []const u8 { + var ptr: [*]const u8 = undefined; + return ptr[0..req.uws_req_get_query(req, name.ptr, name.len, &ptr)]; + } + pub fn parameter(req: *Request, index: u16) []const u8 { + var ptr: [*]const u8 = undefined; + return ptr[0..req.uws_req_get_parameter(@intCast(c_ushort, index), &ptr)]; + } + extern fn uws_req_is_ancient(res: *Request) bool; + extern fn uws_req_get_yield(res: *Request) bool; + extern fn uws_req_set_field(res: *Request, yield: bool) void; + extern fn uws_req_get_url(res: *Request, dest: *[*]const u8) usize; + extern fn uws_req_get_method(res: *Request, dest: *[*]const u8) usize; + extern fn uws_req_get_header(res: *Request, lower_case_header: *[*]const u8, lower_case_header_length: usize, dest: *[*]const u8) usize; + extern fn uws_req_get_query(res: *Request, key: [*c]const u8, key_length: usize, dest: *[*]const u8) usize; + extern fn uws_req_get_parameter(res: *Request, index: c_ushort, dest: *[*]const u8) usize; +}; + +const listen_socket_t = opaque {}; +extern fn us_listen_socket_close(ssl: c_int, ls: *listen_socket_t) void; + +pub fn NewApp(comptime ssl: bool) type { + return opaque { + const ssl_flag = @as(c_int, @boolToInt(ssl)); + const ThisApp = @This(); + + pub fn create(opts: us_socket_context_options_t) *ThisApp { + return @ptrCast(*ThisApp, uws_create_app(ssl_flag, opts)); + } + pub fn destroy(app: *ThisApp) void { + return uws_app_destroy(ssl_flag, @ptrCast(*uws_app_s, app)); + } + + fn RouteHandler(comptime UserDataType: type, comptime handler: fn (UserDataType, *Request, *Response) void) type { + return struct { + pub fn handle(res: *uws_res, req: *Request, user_data: ?*anyopaque) callconv(.C) void { + if (comptime UserDataType == void) { + return @call( + .{ .modifier = .always_inline }, + handler, + .{ + void{}, + req, + @ptrCast(*Response, @alignCast(@alignOf(*Response), res)), + }, + ); + } else { + return @call( + .{ .modifier = .always_inline }, + handler, + .{ + @ptrCast(UserDataType, @alignCast(@alignOf(UserDataType), user_data.?)), + req, + @ptrCast(*Response, @alignCast(@alignOf(*Response), res)), + }, + ); + } + } + }; + } + + pub const ListenSocket = opaque { + pub inline fn close(this: *ListenSocket) void { + return us_listen_socket_close(ssl_flag, @ptrCast(*listen_socket_t, this)); + } + }; + + pub fn get( + app: *ThisApp, + pattern: [:0]const u8, + comptime UserDataType: type, + user_data: UserDataType, + comptime handler: (fn (UserDataType, *Request, *Response) void), + ) void { + uws_app_get(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data); + } + pub fn post( + app: *ThisApp, + pattern: [:0]const u8, + comptime UserDataType: type, + user_data: UserDataType, + comptime handler: (fn (UserDataType, *Request, *Response) void), + ) void { + uws_app_post(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data); + } + pub fn options( + app: *ThisApp, + pattern: [:0]const u8, + comptime UserDataType: type, + user_data: UserDataType, + comptime handler: (fn (UserDataType, *Request, *Response) void), + ) void { + uws_app_options(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data); + } + pub fn delete( + app: *ThisApp, + pattern: [:0]const u8, + comptime UserDataType: type, + user_data: UserDataType, + comptime handler: (fn (UserDataType, *Request, *Response) void), + ) void { + uws_app_delete(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data); + } + pub fn patch( + app: *ThisApp, + pattern: [:0]const u8, + comptime UserDataType: type, + user_data: UserDataType, + comptime handler: (fn (UserDataType, *Request, *Response) void), + ) void { + uws_app_patch(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data); + } + pub fn put( + app: *ThisApp, + pattern: [:0]const u8, + comptime UserDataType: type, + user_data: UserDataType, + comptime handler: (fn (UserDataType, *Request, *Response) void), + ) void { + uws_app_put(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data); + } + pub fn head( + app: *ThisApp, + pattern: [:0]const u8, + comptime UserDataType: type, + user_data: UserDataType, + comptime handler: (fn (UserDataType, *Request, *Response) void), + ) void { + uws_app_head(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data); + } + pub fn connect( + app: *ThisApp, + pattern: [:0]const u8, + comptime UserDataType: type, + user_data: UserDataType, + comptime handler: (fn (UserDataType, *Request, *Response) void), + ) void { + uws_app_connect(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data); + } + pub fn trace( + app: *ThisApp, + pattern: [:0]const u8, + comptime UserDataType: type, + user_data: UserDataType, + comptime handler: (fn (UserDataType, *Request, *Response) void), + ) void { + uws_app_trace(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data); + } + pub fn any( + app: *ThisApp, + pattern: [:0]const u8, + comptime UserDataType: type, + user_data: UserDataType, + comptime handler: (fn (UserDataType, *Request, *Response) void), + ) void { + uws_app_any(ssl_flag, @ptrCast(*uws_app_t, app), pattern, RouteHandler(UserDataType, handler).handle, user_data); + } + pub fn run(app: *ThisApp) void { + return uws_app_run(ssl_flag, @ptrCast(*uws_app_t, app)); + } + pub fn listen( + app: *ThisApp, + port: c_int, + comptime UserData: type, + user_data: UserData, + comptime handler: fn (UserData, ?*ListenSocket, uws_app_listen_config_t) void, + ) void { + const Wrapper = struct { + pub fn handle(socket: ?*listen_socket_t, conf: uws_app_listen_config_t, data: ?*anyopaque) callconv(.C) void { + if (comptime UserData == void) { + @call(.{ .modifier = .always_inline }, handler, .{ void{}, @ptrCast(?*ListenSocket, socket), conf }); + } else { + @call(.{ .modifier = .always_inline }, handler, .{ + @ptrCast(UserData, @alignCast(@alignOf(UserData), data.?)), + @ptrCast(?*ListenSocket, socket), + conf, + }); + } + } + }; + return uws_app_listen(ssl_flag, @ptrCast(*uws_app_t, app), port, Wrapper.handle, user_data); + } + + pub fn listenWithConfig( + app: *ThisApp, + comptime UserData: type, + user_data: UserData, + comptime handler: fn (UserData, ?*ListenSocket, uws_app_listen_config_t) void, + config: uws_app_listen_config_t, + ) void { + const Wrapper = struct { + pub fn handle(socket: ?*listen_socket_t, conf: uws_app_listen_config_t, data: ?*anyopaque) callconv(.C) void { + if (comptime UserData == void) { + @call(.{ .modifier = .always_inline }, handler, .{ void{}, @ptrCast(?*ListenSocket, socket), conf }); + } else { + @call(.{ .modifier = .always_inline }, handler, .{ + @ptrCast(UserData, @alignCast(@alignOf(UserData), data.?)), + @ptrCast(?*ListenSocket, socket), + conf, + }); + } + } + }; + return uws_app_listen_with_config(ssl_flag, @ptrCast(*uws_app_t, app), config, Wrapper.handle, user_data); + } + pub fn constructorFailed(app: *ThisApp) bool { + return uws_constructor_failed(ssl_flag, app); + } + pub fn num_subscribers(app: *ThisApp, topic: [:0]const u8) c_uint { + return uws_num_subscribers(ssl_flag, @ptrCast(*uws_app_t, app), topic); + } + pub fn publish(app: *ThisApp, topic: []const u8, message: []const u8, opcode: uws_opcode_t, compress: bool) bool { + return uws_publish(ssl_flag, @ptrCast(*uws_app_t, app), topic.ptr, topic.len, message.ptr, message.len, opcode, compress); + } + pub fn getNativeHandle(app: *ThisApp) ?*anyopaque { + return uws_get_native_handle(ssl_flag, app); + } + pub fn removeServerName(app: *ThisApp, hostname_pattern: [:0]const u8) void { + return uws_remove_server_name(ssl_flag, @ptrCast(*uws_app_t, app), hostname_pattern); + } + pub fn addServerName(app: *ThisApp, hostname_pattern: [:0]const u8) void { + return uws_add_server_name(ssl_flag, @ptrCast(*uws_app_t, app), hostname_pattern); + } + pub fn addServerNameWithOptions(app: *ThisApp, hostname_pattern: [:0]const u8, opts: us_socket_context_options_t) void { + return uws_add_server_name_with_options(ssl_flag, @ptrCast(*uws_app_t, app), hostname_pattern, opts); + } + pub fn missingServerName(app: *ThisApp, handler: uws_missing_server_handler, user_data: ?*anyopaque) void { + return uws_missing_server_name(ssl_flag, @ptrCast(*uws_app_t, app), handler, user_data); + } + pub fn filter(app: *ThisApp, handler: uws_filter_handler, user_data: ?*anyopaque) void { + return uws_filter(ssl_flag, @ptrCast(*uws_app_t, app), handler, user_data); + } + pub fn ws(app: *ThisApp, pattern: [:0]const u8, behavior: uws_socket_behavior_t) void { + return uws_ws(ssl_flag, @ptrCast(*uws_app_t, app), pattern, behavior); + } + + pub const Response = opaque { + inline fn castRes(res: *uws_res) *Response { + return @ptrCast(*Response, @alignCast(@alignOf(*Response), res)); + } + + pub inline fn downcast(res: *Response) *uws_res { + return @ptrCast(*uws_res, @alignCast(@alignOf(*uws_res), res)); + } + + pub fn end(res: *Response, data: []const u8, close_connection: bool) void { + uws_res_end(ssl_flag, res.downcast(), data.ptr, data.len, close_connection); + } + pub fn pause(res: *Response) void { + uws_res_pause(ssl_flag, res.downcast()); + } + pub fn @"resume"(res: *Response) void { + uws_res_resume(ssl_flag, res.downcast()); + } + pub fn writeContinue(res: *Response) void { + uws_res_write_continue(ssl_flag, res.downcast()); + } + pub fn writeStatus(res: *Response, status: []const u8) void { + uws_res_write_status(ssl_flag, res.downcast(), status.ptr, status.len); + } + pub fn writeHeader(res: *Response, key: []const u8, value: []const u8) void { + uws_res_write_header(ssl_flag, res.downcast(), key.ptr, key.len, value.ptr, value.len); + } + pub fn writeHeaderInt(res: *Response, key: []const u8, value: u64) void { + uws_res_write_header(ssl_flag, res.downcast(), key.ptr, key.len, value); + } + pub fn endWithoutBody(res: *Response) void { + uws_res_end_without_body(ssl_flag, res.downcast()); + } + pub fn write(res: *Response, data: []const u8) bool { + return uws_res_write(ssl_flag, res.downcast(), data.ptr, data.len); + } + pub fn getWriteOffset(res: *Response) uintmax_t { + return uws_res_get_write_offset(ssl_flag, res.downcast()); + } + pub fn hasResponded(res: *Response) bool { + return uws_res_has_responded(ssl_flag, res.downcast()); + } + pub fn onWritable( + res: *Response, + comptime UserDataType: type, + comptime handler: fn (*Response, uintmax_t, UserDataType) callconv(.C) bool, + user_data: UserDataType, + ) void { + const Wrapper = struct { + pub fn handle(this: *uws_res, amount: uintmax_t, data: ?*anyopaque) callconv(.C) void { + if (comptime UserDataType == void) { + @call(.{ .modifier = .always_inline }, handler, .{ void{}, castRes(this), amount }); + } else { + @call(.{ .modifier = .always_inline }, handler, .{ @ptrCast(UserDataType, @alignCast(@alignOf(UserDataType), data.?)), castRes(this), amount }); + } + } + }; + uws_res_on_writable(ssl_flag, res.downcast(), Wrapper.handle, user_data); + } + pub fn onAborted(res: *Response, comptime UserDataType: type, comptime handler: fn (UserDataType, *Response) void, opcional_data: UserDataType) void { + const Wrapper = struct { + pub fn handle(this: *uws_res, user_data: ?*anyopaque) callconv(.C) void { + if (comptime UserDataType == void) { + @call(.{ .modifier = .always_inline }, handler, .{ void{}, castRes(this), void{} }); + } else { + @call(.{ .modifier = .always_inline }, handler, .{ @ptrCast(UserDataType, @alignCast(@alignOf(UserDataType), user_data.?)), castRes(this) }); + } + } + }; + uws_res_on_aborted(ssl_flag, res.downcast(), Wrapper.handle, opcional_data); + } + + pub fn onData( + res: *Response, + comptime UserDataType: type, + comptime handler: fn (*Response, chunk: []const u8, last: bool, UserDataType) void, + opcional_data: UserDataType, + ) void { + const Wrapper = struct { + pub fn handle(this: *uws_res, chunk_ptr: [*c]const u8, len: usize, last: bool, user_data: ?*anyopaque) callconv(.C) void { + if (comptime UserDataType == void) { + @call(.{ .modifier = .always_inline }, handler, .{ + void{}, + castRes(this), + chunk_ptr[0..len], + last, + }); + } else { + @call(.{ .modifier = .always_inline }, handler, .{ + @ptrCast(UserDataType, @alignCast(@alignOf(UserDataType), user_data.?)), + castRes(this), + chunk_ptr[0..len], + last, + }); + } + } + }; + + uws_res_on_data(ssl_flag, res.downcast(), Wrapper.handle, opcional_data); + } + }; + }; +} + +extern fn uws_create_app(ssl: c_int, options: us_socket_context_options_t) *uws_app_t; +extern fn uws_app_destroy(ssl: c_int, app: *uws_app_t) void; +extern fn uws_app_get(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void; +extern fn uws_app_post(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void; +extern fn uws_app_options(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void; +extern fn uws_app_delete(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void; +extern fn uws_app_patch(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void; +extern fn uws_app_put(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void; +extern fn uws_app_head(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void; +extern fn uws_app_connect(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void; +extern fn uws_app_trace(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void; +extern fn uws_app_any(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, handler: uws_method_handler, user_data: ?*anyopaque) void; +extern fn uws_app_run(ssl: c_int, *uws_app_t) void; +extern fn uws_app_listen(ssl: c_int, app: *uws_app_t, port: c_int, handler: uws_listen_handler, user_data: ?*anyopaque) void; +extern fn uws_app_listen_with_config(ssl: c_int, app: *uws_app_t, config: uws_app_listen_config_t, handler: uws_listen_handler, user_data: ?*anyopaque) void; +extern fn uws_constructor_failed(ssl: c_int, app: *uws_app_t) bool; +extern fn uws_num_subscribers(ssl: c_int, app: *uws_app_t, topic: [*c]const u8) c_uint; +extern fn uws_publish(ssl: c_int, app: *uws_app_t, topic: [*c]const u8, topic_length: usize, message: [*c]const u8, message_length: usize, opcode: uws_opcode_t, compress: bool) bool; +extern fn uws_get_native_handle(ssl: c_int, app: *uws_app_t) ?*anyopaque; +extern fn uws_remove_server_name(ssl: c_int, app: *uws_app_t, hostname_pattern: [*c]const u8) void; +extern fn uws_add_server_name(ssl: c_int, app: *uws_app_t, hostname_pattern: [*c]const u8) void; +extern fn uws_add_server_name_with_options(ssl: c_int, app: *uws_app_t, hostname_pattern: [*c]const u8, options: us_socket_context_options_t) void; +extern fn uws_missing_server_name(ssl: c_int, app: *uws_app_t, handler: uws_missing_server_handler, user_data: ?*anyopaque) void; +extern fn uws_filter(ssl: c_int, app: *uws_app_t, handler: uws_filter_handler, user_data: ?*anyopaque) void; +extern fn uws_ws(ssl: c_int, app: *uws_app_t, pattern: [*c]const u8, behavior: uws_socket_behavior_t) void; + +extern fn uws_ws_get_user_data(ssl: c_int, ws: ?*uws_websocket_t) ?*anyopaque; +extern fn uws_ws_close(ssl: c_int, ws: ?*uws_websocket_t) void; +extern fn uws_ws_send(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, opcode: uws_opcode_t) uws_sendstatus_t; +extern fn uws_ws_send_with_options(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, opcode: uws_opcode_t, compress: bool, fin: bool) uws_sendstatus_t; +extern fn uws_ws_send_fragment(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, compress: bool) uws_sendstatus_t; +extern fn uws_ws_send_first_fragment(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, compress: bool) uws_sendstatus_t; +extern fn uws_ws_send_first_fragment_with_opcode(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, opcode: uws_opcode_t, compress: bool) uws_sendstatus_t; +extern fn uws_ws_send_last_fragment(ssl: c_int, ws: ?*uws_websocket_t, message: [*c]const u8, length: usize, compress: bool) uws_sendstatus_t; +extern fn uws_ws_end(ssl: c_int, ws: ?*uws_websocket_t, code: c_int, message: [*c]const u8, length: usize) void; +extern fn uws_ws_cork(ssl: c_int, ws: ?*uws_websocket_t, handler: ?fn (?*anyopaque) callconv(.C) void, user_data: ?*anyopaque) void; +extern fn uws_ws_subscribe(ssl: c_int, ws: ?*uws_websocket_t, topic: [*c]const u8, length: usize) bool; +extern fn uws_ws_unsubscribe(ssl: c_int, ws: ?*uws_websocket_t, topic: [*c]const u8, length: usize) bool; +extern fn uws_ws_is_subscribed(ssl: c_int, ws: ?*uws_websocket_t, topic: [*c]const u8, length: usize) bool; +extern fn uws_ws_iterate_topics(ssl: c_int, ws: ?*uws_websocket_t, callback: ?fn ([*c]const u8, usize, ?*anyopaque) callconv(.C) void, user_data: ?*anyopaque) void; +extern fn uws_ws_publish(ssl: c_int, ws: ?*uws_websocket_t, topic: [*c]const u8, topic_length: usize, message: [*c]const u8, message_length: usize) bool; +extern fn uws_ws_publish_with_options(ssl: c_int, ws: ?*uws_websocket_t, topic: [*c]const u8, topic_length: usize, message: [*c]const u8, message_length: usize, opcode: uws_opcode_t, compress: bool) bool; +extern fn uws_ws_get_buffered_amount(ssl: c_int, ws: ?*uws_websocket_t) c_uint; +extern fn uws_ws_get_remote_address(ssl: c_int, ws: ?*uws_websocket_t, dest: [*c][*c]const u8) usize; +extern fn uws_ws_get_remote_address_as_text(ssl: c_int, ws: ?*uws_websocket_t, dest: [*c][*c]const u8) usize; +const uws_res = opaque {}; +extern fn uws_res_end(ssl: c_int, res: *uws_res, data: [*c]const u8, length: usize, close_connection: bool) void; +extern fn uws_res_pause(ssl: c_int, res: *uws_res) void; +extern fn uws_res_resume(ssl: c_int, res: *uws_res) void; +extern fn uws_res_write_continue(ssl: c_int, res: *uws_res) void; +extern fn uws_res_write_status(ssl: c_int, res: *uws_res, status: [*c]const u8, length: usize) void; +extern fn uws_res_write_header(ssl: c_int, res: *uws_res, key: [*c]const u8, key_length: usize, value: [*c]const u8, value_length: usize) void; +extern fn uws_res_write_header_int(ssl: c_int, res: *uws_res, key: [*c]const u8, key_length: usize, value: u64) void; +extern fn uws_res_end_without_body(ssl: c_int, res: *uws_res) void; +extern fn uws_res_write(ssl: c_int, res: *uws_res, data: [*c]const u8, length: usize) bool; +extern fn uws_res_get_write_offset(ssl: c_int, res: *uws_res) uintmax_t; +extern fn uws_res_has_responded(ssl: c_int, res: *uws_res) bool; +extern fn uws_res_on_writable(ssl: c_int, res: *uws_res, handler: ?fn (*uws_res, uintmax_t, ?*anyopaque) callconv(.C) bool, user_data: ?*anyopaque) void; +extern fn uws_res_on_aborted(ssl: c_int, res: *uws_res, handler: ?fn (*uws_res, ?*anyopaque) callconv(.C) void, opcional_data: ?*anyopaque) void; +extern fn uws_res_on_data( + ssl: c_int, + res: *uws_res, + handler: ?fn (*uws_res, [*c]const u8, usize, bool, ?*anyopaque) callconv(.C) void, + opcional_data: ?*anyopaque, +) void; +extern fn uws_res_upgrade( + ssl: c_int, + res: *uws_res, + data: ?*anyopaque, + sec_web_socket_key: [*c]const u8, + sec_web_socket_key_length: usize, + sec_web_socket_protocol: [*c]const u8, + sec_web_socket_protocol_length: usize, + sec_web_socket_extensions: [*c]const u8, + sec_web_socket_extensions_length: usize, + ws: ?*uws_socket_context_t, +) void; + +pub const LIBUS_RECV_BUFFER_LENGTH = @import("std").zig.c_translation.promoteIntLiteral(c_int, 524288, .decimal); +pub const LIBUS_TIMEOUT_GRANULARITY = @as(c_int, 4); +pub const LIBUS_RECV_BUFFER_PADDING = @as(c_int, 32); +pub const LIBUS_EXT_ALIGNMENT = @as(c_int, 16); +pub const LIBUS_SOCKET_DESCRIPTOR = c_int; + +pub const _COMPRESSOR_MASK: c_int = 255; +pub const _DECOMPRESSOR_MASK: c_int = 3840; +pub const DISABLED: c_int = 0; +pub const SHARED_COMPRESSOR: c_int = 1; +pub const SHARED_DECOMPRESSOR: c_int = 256; +pub const DEDICATED_DECOMPRESSOR_32KB: c_int = 3840; +pub const DEDICATED_DECOMPRESSOR_16KB: c_int = 3584; +pub const DEDICATED_DECOMPRESSOR_8KB: c_int = 3328; +pub const DEDICATED_DECOMPRESSOR_4KB: c_int = 3072; +pub const DEDICATED_DECOMPRESSOR_2KB: c_int = 2816; +pub const DEDICATED_DECOMPRESSOR_1KB: c_int = 2560; +pub const DEDICATED_DECOMPRESSOR_512B: c_int = 2304; +pub const DEDICATED_DECOMPRESSOR: c_int = 3840; +pub const DEDICATED_COMPRESSOR_3KB: c_int = 145; +pub const DEDICATED_COMPRESSOR_4KB: c_int = 146; +pub const DEDICATED_COMPRESSOR_8KB: c_int = 163; +pub const DEDICATED_COMPRESSOR_16KB: c_int = 180; +pub const DEDICATED_COMPRESSOR_32KB: c_int = 197; +pub const DEDICATED_COMPRESSOR_64KB: c_int = 214; +pub const DEDICATED_COMPRESSOR_128KB: c_int = 231; +pub const DEDICATED_COMPRESSOR_256KB: c_int = 248; +pub const DEDICATED_COMPRESSOR: c_int = 248; +pub const uws_compress_options_t = c_uint; +pub const CONTINUATION: c_int = 0; +pub const TEXT: c_int = 1; +pub const BINARY: c_int = 2; +pub const CLOSE: c_int = 8; +pub const PING: c_int = 9; +pub const PONG: c_int = 10; +pub const uws_opcode_t = c_uint; +pub const BACKPRESSURE: c_int = 0; +pub const SUCCESS: c_int = 1; +pub const DROPPED: c_int = 2; +pub const uws_sendstatus_t = c_uint; +pub const uws_app_listen_config_t = extern struct { + port: c_int, + host: [*c]const u8 = null, + options: c_int, +}; diff --git a/src/http_client_async.zig b/src/http_client_async.zig index 0f29b7638..27a046a9b 100644 --- a/src/http_client_async.zig +++ b/src/http_client_async.zig @@ -11,7 +11,7 @@ const stringZ = bun.stringZ; const C = bun.C; const std = @import("std"); const URL = @import("./url.zig").URL; -const Method = @import("./http/method.zig").Method; +pub const Method = @import("./http/method.zig").Method; const Api = @import("./api/schema.zig").Api; const Lock = @import("./lock.zig").Lock; const HTTPClient = @This(); diff --git a/src/javascript/jsc/api/bun.zig b/src/javascript/jsc/api/bun.zig index 64cc72ecc..d3b230243 100644 --- a/src/javascript/jsc/api/bun.zig +++ b/src/javascript/jsc/api/bun.zig @@ -954,6 +954,10 @@ pub const Class = NewClass( .rfn = Bun.readAllStdinSync, .ts = d.ts{}, }, + .startServer = .{ + .rfn = Bun.startServer, + .ts = d.ts{}, + }, }, .{ .main = .{ @@ -1001,6 +1005,28 @@ pub const Class = NewClass( }, ); +pub fn startServer( + _: void, + ctx: js.JSContextRef, + _: js.JSObjectRef, + _: js.JSObjectRef, + arguments: []const js.JSValueRef, + _: js.ExceptionRef, +) js.JSValueRef { + var vm = JSC.VirtualMachine.vm; + const handler = if (arguments.len > 0) JSC.JSValue.fromRef(arguments[0]) else JSC.JSValue.zero; + if (handler.isEmpty() or handler.isUndefinedOrNull() or !handler.isCell() or !handler.isCallable(ctx.ptr().vm())) { + Output.prettyWarnln("\"serverless\" export should be a function", .{}); + Output.flush(); + return JSC.JSValue.jsUndefined().asObjectRef(); + } + + JSC.C.JSValueProtect(ctx.ptr().ref(), handler.asObjectRef()); + var server = JSC.API.Server.init(vm.bundler.options.origin.getPortAuto(), handler, ctx.ptr()); + server.listen(); + return JSC.JSValue.jsUndefined().asObjectRef(); +} + pub fn allocUnsafe( _: void, ctx: js.JSContextRef, diff --git a/src/javascript/jsc/api/server.zig b/src/javascript/jsc/api/server.zig new file mode 100644 index 000000000..4b7805adb --- /dev/null +++ b/src/javascript/jsc/api/server.zig @@ -0,0 +1,320 @@ +const Bun = @This(); +const default_allocator = @import("../../../global.zig").default_allocator; +const bun = @import("../../../global.zig"); +const Environment = bun.Environment; +const NetworkThread = @import("http").NetworkThread; +const Global = bun.Global; +const strings = bun.strings; +const string = bun.string; +const Output = @import("../../../global.zig").Output; +const MutableString = @import("../../../global.zig").MutableString; +const std = @import("std"); +const Allocator = std.mem.Allocator; +const IdentityContext = @import("../../../identity_context.zig").IdentityContext; +const Fs = @import("../../../fs.zig"); +const Resolver = @import("../../../resolver/resolver.zig"); +const ast = @import("../../../import_record.zig"); +const NodeModuleBundle = @import("../../../node_module_bundle.zig").NodeModuleBundle; +const MacroEntryPoint = @import("../../../bundler.zig").MacroEntryPoint; +const logger = @import("../../../logger.zig"); +const Api = @import("../../../api/schema.zig").Api; +const options = @import("../../../options.zig"); +const Bundler = @import("../../../bundler.zig").Bundler; +const ServerEntryPoint = @import("../../../bundler.zig").ServerEntryPoint; +const js_printer = @import("../../../js_printer.zig"); +const js_parser = @import("../../../js_parser.zig"); +const js_ast = @import("../../../js_ast.zig"); +const hash_map = @import("../../../hash_map.zig"); +const http = @import("../../../http.zig"); +const NodeFallbackModules = @import("../../../node_fallbacks.zig"); +const ImportKind = ast.ImportKind; +const Analytics = @import("../../../analytics/analytics_thread.zig"); +const ZigString = @import("../../../jsc.zig").ZigString; +const Runtime = @import("../../../runtime.zig"); +const Router = @import("./router.zig"); +const ImportRecord = ast.ImportRecord; +const DotEnv = @import("../../../env_loader.zig"); +const ParseResult = @import("../../../bundler.zig").ParseResult; +const PackageJSON = @import("../../../resolver/package_json.zig").PackageJSON; +const MacroRemap = @import("../../../resolver/package_json.zig").MacroMap; +const WebCore = @import("../../../jsc.zig").WebCore; +const Request = WebCore.Request; +const Response = WebCore.Response; +const Headers = WebCore.Headers; +const Fetch = WebCore.Fetch; +const HTTP = @import("http"); +const FetchEvent = WebCore.FetchEvent; +const js = @import("../../../jsc.zig").C; +const JSC = @import("../../../jsc.zig"); +const JSError = @import("../base.zig").JSError; +const d = @import("../base.zig").d; +const MarkedArrayBuffer = @import("../base.zig").MarkedArrayBuffer; +const getAllocator = @import("../base.zig").getAllocator; +const JSValue = @import("../../../jsc.zig").JSValue; +const NewClass = @import("../base.zig").NewClass; +const Microtask = @import("../../../jsc.zig").Microtask; +const JSGlobalObject = @import("../../../jsc.zig").JSGlobalObject; +const ExceptionValueRef = @import("../../../jsc.zig").ExceptionValueRef; +const JSPrivateDataPtr = @import("../../../jsc.zig").JSPrivateDataPtr; +const ZigConsoleClient = @import("../../../jsc.zig").ZigConsoleClient; +const Node = @import("../../../jsc.zig").Node; +const ZigException = @import("../../../jsc.zig").ZigException; +const ZigStackTrace = @import("../../../jsc.zig").ZigStackTrace; +const ErrorableResolvedSource = @import("../../../jsc.zig").ErrorableResolvedSource; +const ResolvedSource = @import("../../../jsc.zig").ResolvedSource; +const JSPromise = @import("../../../jsc.zig").JSPromise; +const JSInternalPromise = @import("../../../jsc.zig").JSInternalPromise; +const JSModuleLoader = @import("../../../jsc.zig").JSModuleLoader; +const JSPromiseRejectionOperation = @import("../../../jsc.zig").JSPromiseRejectionOperation; +const Exception = @import("../../../jsc.zig").Exception; +const ErrorableZigString = @import("../../../jsc.zig").ErrorableZigString; +const ZigGlobalObject = @import("../../../jsc.zig").ZigGlobalObject; +const VM = @import("../../../jsc.zig").VM; +const JSFunction = @import("../../../jsc.zig").JSFunction; +const Config = @import("../config.zig"); +const URL = @import("../../../url.zig").URL; +const Transpiler = @import("./transpiler.zig"); +const VirtualMachine = @import("../javascript.zig").VirtualMachine; +const IOTask = JSC.IOTask; +const is_bindgen = JSC.is_bindgen; +const uws = @import("uws"); + +pub fn NewServer(comptime ssl_enabled: bool) type { + return struct { + const ThisServer = @This(); + const RequestContextStackAllocator = std.heap.StackFallbackAllocator(@sizeOf(RequestContext) * 2048 + 4096); + + pub const App = uws.NewApp(ssl_enabled); + + listener: ?*App.ListenSocket = null, + callback: JSC.JSValue = JSC.JSValue.zero, + port: u16 = 3000, + app: *App = undefined, + globalThis: *JSGlobalObject, + default_server: URL = URL{ .host = "localhost", .port = "3000" }, + + request_pool_allocator: std.mem.Allocator = undefined, + + pub fn init(port: u16, callback: JSC.JSValue, globalThis: *JSGlobalObject) *ThisServer { + var server = bun.default_allocator.create(ThisServer) catch @panic("Out of memory!"); + server.* = .{ + .port = port, + .callback = callback, + .globalThis = globalThis, + }; + RequestContext.pool = bun.default_allocator.create(RequestContextStackAllocator) catch @panic("Out of memory!"); + server.request_pool_allocator = RequestContext.pool.get(); + return server; + } + + pub fn onListen(this: *ThisServer, socket: ?*App.ListenSocket, _: uws.uws_app_listen_config_t) void { + if (socket == null) { + Output.prettyErrorln("Failed to start socket", .{}); + Output.flush(); + return; + } + + this.listener = socket; + VirtualMachine.vm.uws_event_loop = uws.Loop.get(); + this.app.run(); + } + + pub const RequestContext = struct { + server: *ThisServer, + resp: *App.Response, + req: *uws.Request, + url: string, + method: HTTP.Method, + aborted: bool = false, + response_jsvalue: JSC.JSValue = JSC.JSValue.zero, + blob: JSC.WebCore.Blob = JSC.WebCore.Blob{}, + promise: ?*JSC.JSValue = null, + response_headers: ?*JSC.WebCore.Headers.RefCountedHeaders = null, + + pub threadlocal var pool: *RequestContextStackAllocator = undefined; + + pub fn onResolve( + ctx: *RequestContext, + _: *JSC.JSGlobalObject, + arguments: []const JSC.JSValue, + ) void { + if (ctx.aborted) { + ctx.finalize(); + return; + } + + if (arguments.len == 0) { + ctx.req.setYield(true); + ctx.finalize(); + return; + } + + var response = arguments[0].as(JSC.WebCore.Response) orelse { + Output.prettyErrorln("Expected serverless to return a Response", .{}); + ctx.req.setYield(true); + ctx.finalize(); + return; + }; + ctx.render(response); + } + + pub fn onReject( + ctx: *RequestContext, + _: *JSC.JSGlobalObject, + arguments: []const JSC.JSValue, + ) void { + if (ctx.aborted) { + ctx.finalize(); + return; + } + + JSC.VirtualMachine.vm.defaultErrorHandler(arguments[0], null); + ctx.req.setYield(true); + ctx.finalize(); + } + + pub fn create(this: *RequestContext, server: *ThisServer, req: *uws.Request, resp: *App.Response) void { + this.* = .{ + .resp = resp, + .req = req, + .url = req.url(), + .method = HTTP.Method.which(req.method()) orelse .GET, + .server = server, + }; + resp.onAborted(*RequestContext, onAbort, this); + } + + pub fn onAbort(this: *RequestContext, _: *App.Response) void { + this.aborted = true; + this.req = undefined; + if (!this.response_jsvalue.isEmpty()) { + JSC.C.JSValueUnprotect(this.server.globalThis.ref(), this.response_jsvalue.asObjectRef()); + this.response_jsvalue = JSC.JSValue.zero; + } + } + + pub fn finalize(this: *RequestContext) void { + this.blob.detach(); + if (!this.response_jsvalue.isEmpty()) { + JSC.C.JSValueUnprotect(this.server.globalThis.ref(), this.response_jsvalue.asObjectRef()); + this.response_jsvalue = JSC.JSValue.zero; + } + + if (this.promise != null) { + JSC.C.JSValueUnprotect(this.server.globalThis.ref(), this.promise.?.asObjectRef()); + this.promise = null; + } + + if (this.response_headers != null) { + this.response_headers.?.deref(); + this.response_headers = null; + } + + this.server.request_pool_allocator.destroy(this); + } + + pub fn render(this: *RequestContext, response: *JSC.WebCore.Response) void { + if (this.aborted) { + return; + } + + this.blob = response.body.use(); + const status = response.statusCode(); + + if (response.body.init.headers) |headers_| { + var headers: *JSC.WebCore.Headers = headers_.get(); + defer headers_.deref(); + var entries = headers.entries.slice(); + const names = entries.items(.name); + const values = entries.items(.value); + + var status_text_buf: [48]u8 = undefined; + + if (status == 302) { + this.resp.writeStatus("302 Found"); + } else { + this.resp.writeStatus(std.fmt.bufPrint(&status_text_buf, "{d} HM", .{response.body.init.status_code}) catch unreachable); + } + + for (names) |name, i| { + this.resp.writeHeader(headers.asStr(name), headers.asStr(values[i])); + } + } + + if (status == 302 or status == 202 or this.blob.size == 0) { + this.resp.endWithoutBody(); + this.finalize(); + return; + } + + this.resp.end(this.blob.sharedView(), false); + this.finalize(); + } + }; + + pub fn onRequest(this: *ThisServer, req: *uws.Request, resp: *App.Response) void { + req.setYield(false); + var ctx = this.request_pool_allocator.create(RequestContext) catch @panic("ran out of memory"); + ctx.create(this, req, resp); + + var request_object = bun.default_allocator.create(JSC.WebCore.Request) catch unreachable; + request_object.* = .{ + .url = JSC.ZigString.init(ctx.url), + .method = ctx.method, + }; + var args = [_]JSC.C.JSValueRef{JSC.WebCore.Request.Class.make(this.globalThis.ref(), request_object)}; + ctx.response_jsvalue = JSC.C.JSObjectCallAsFunctionReturnValue(this.globalThis.ref(), this.callback.asObjectRef(), null, 1, &args); + defer JSC.VirtualMachine.vm.tick(); + if (ctx.aborted) { + ctx.finalize(); + + return; + } + + if (ctx.response_jsvalue.isUndefinedOrNull()) { + req.setYield(true); + ctx.finalize(); + return; + } + + JSC.C.JSValueProtect(this.globalThis.ref(), ctx.response_jsvalue.asObjectRef()); + + if (ctx.response_jsvalue.as(JSC.WebCore.Response)) |response| { + ctx.render(response); + + return; + } + + if (ctx.response_jsvalue.jsTypeLoose() == .JSPromise) { + JSC.VirtualMachine.vm.tick(); + + ctx.response_jsvalue.then( + this.globalThis, + RequestContext, + ctx, + RequestContext.onResolve, + RequestContext.onReject, + ); + } + + // switch (ctx.response_jsvalue.jsTypeLoose()) { + // .JSPromise => { + // JSPromise. + // }, + // } + } + + pub fn listen(this: *ThisServer) void { + this.app = App.create(.{}); + this.app.any("/*", *ThisServer, this, onRequest); + this.app.listenWithConfig(*ThisServer, this, onListen, .{ + .port = this.default_server.getPort().?, + .host = bun.default_allocator.dupeZ(u8, this.default_server.displayHostname()) catch unreachable, + .options = 0, + }); + } + }; +} + +pub const Server = NewServer(false); +pub const SSLServer = NewServer(true); diff --git a/src/javascript/jsc/bindings/BunBuiltinNames.h b/src/javascript/jsc/bindings/BunBuiltinNames.h index 709ab28a5..9619f62a6 100644 --- a/src/javascript/jsc/bindings/BunBuiltinNames.h +++ b/src/javascript/jsc/bindings/BunBuiltinNames.h @@ -72,6 +72,14 @@ using namespace JSC; macro(delimiter) \ macro(toNamespacedPath) \ macro(isWindows) \ + macro(get) \ + macro(put) \ + macro(post) \ + macro(patch) \ + macro(trace) \ + macro(connect) \ + macro(options) \ + macro(port) \ BUN_ADDITIONAL_PRIVATE_IDENTIFIERS(macro) \ class BunBuiltinNames { diff --git a/src/javascript/jsc/bindings/ZigGlobalObject.cpp b/src/javascript/jsc/bindings/ZigGlobalObject.cpp index 4c6a0f9c2..cf853e2d4 100644 --- a/src/javascript/jsc/bindings/ZigGlobalObject.cpp +++ b/src/javascript/jsc/bindings/ZigGlobalObject.cpp @@ -557,7 +557,8 @@ static JSC_DEFINE_HOST_FUNCTION(functionImportMeta__resolve, } } -extern "C" void Bun__reportError(JSC::JSGlobalObject*, JSC__JSValue); +extern "C" void Bun__reportError(JSC__JSGlobalObject*, JSC__JSValue); + static JSC_DECLARE_HOST_FUNCTION(functionReportError); static JSC_DEFINE_HOST_FUNCTION(functionReportError, (JSC::JSGlobalObject * globalObject, JSC::CallFrame* callFrame)) diff --git a/src/javascript/jsc/bindings/bindings.cpp b/src/javascript/jsc/bindings/bindings.cpp index 112ca81b7..85f7e6f1e 100644 --- a/src/javascript/jsc/bindings/bindings.cpp +++ b/src/javascript/jsc/bindings/bindings.cpp @@ -246,6 +246,45 @@ unsigned char JSC__JSValue__jsType(JSC__JSValue JSValue0) return 0; } +// TODO: prevent this from allocating so much memory +void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* globalObject, void* ctx, void (*ArgFn3)(JSC__JSGlobalObject* arg0, void* arg1, JSC__JSValue arg2, size_t arg3), void (*ArgFn4)(JSC__JSGlobalObject* arg0, void* arg1, JSC__JSValue arg2, size_t arg3)) +{ + + JSC::JSNativeStdFunction* resolverFunction = JSC::JSNativeStdFunction::create( + globalObject->vm(), globalObject, 1, String(), [ctx, ArgFn3](JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -> JSC::EncodedJSValue { + auto argCount = static_cast<uint16_t>(callFrame->argumentCount()); + WTF::Vector<JSC::EncodedJSValue, 16> arguments; + arguments.reserveInitialCapacity(argCount); + if (argCount) { + for (uint16_t i = 0; i < argCount; ++i) { + arguments.uncheckedAppend(JSC::JSValue::encode(callFrame->uncheckedArgument(i))); + } + } + + ArgFn3(globalObject, ctx, reinterpret_cast<JSC__JSValue>(arguments.data()), argCount); + return JSC::JSValue::encode(JSC::jsUndefined()); + }); + JSC::JSNativeStdFunction* rejecterFunction = JSC::JSNativeStdFunction::create( + globalObject->vm(), globalObject, 1, String(), + [ctx, ArgFn4](JSC::JSGlobalObject* globalObject, JSC::CallFrame* callFrame) -> JSC::EncodedJSValue { + auto argCount = static_cast<uint16_t>(callFrame->argumentCount()); + WTF::Vector<JSC::EncodedJSValue, 16> arguments; + arguments.reserveInitialCapacity(argCount); + if (argCount) { + for (uint16_t i = 0; i < argCount; ++i) { + arguments.uncheckedAppend(JSC::JSValue::encode(callFrame->uncheckedArgument(i))); + } + } + + ArgFn4(globalObject, ctx, reinterpret_cast<JSC__JSValue>(arguments.data()), argCount); + return JSC::JSValue::encode(JSC::jsUndefined()); + }); + + globalObject->vm().drainMicrotasks(); + JSC::JSPromise* promise = JSC::jsDynamicCast<JSC::JSPromise*>(globalObject->vm(), JSC::JSValue::decode(JSValue0).asCell()); + promise->performPromiseThen(globalObject, resolverFunction, rejecterFunction, JSC::jsUndefined()); +} + JSC__JSValue JSC__JSValue__parseJSON(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1) { JSC::JSValue jsValue = JSC::JSValue::decode(JSValue0); @@ -728,10 +767,8 @@ JSC__JSValue JSC__JSGlobalObject__createAggregateError(JSC__JSGlobalObject* glob } JSC::Structure* errorStructure = globalObject->errorStructure(JSC::ErrorType::AggregateError); - scope.release(); - return JSC::JSValue::encode(JSC::createAggregateError( - globalObject, vm, errorStructure, array, message, options, nullptr, JSC::TypeNothing, false)); + RELEASE_AND_RETURN(scope, JSC::JSValue::encode(JSC::createAggregateError(globalObject, vm, errorStructure, array, message, options, nullptr, JSC::TypeNothing, false))); } // static JSC::JSNativeStdFunction* resolverFunction; // static JSC::JSNativeStdFunction* rejecterFunction; diff --git a/src/javascript/jsc/bindings/bindings.zig b/src/javascript/jsc/bindings/bindings.zig index 88ecb6bfe..da65d38d5 100644 --- a/src/javascript/jsc/bindings/bindings.zig +++ b/src/javascript/jsc/bindings/bindings.zig @@ -2179,6 +2179,48 @@ pub const JSValue = enum(u64) { return cppFn("symbolKeyFor", .{ this, global, str }); } + const Thenable = fn ( + global: [*c]JSGlobalObject, + ctx: ?*anyopaque, + arguments_ptr: JSC.JSValue, + arguments_len: usize, + ) callconv(.C) void; + pub fn _then(this: JSValue, global: *JSGlobalObject, ctx: ?*anyopaque, resolve: Thenable, reject: Thenable) void { + return cppFn("_then", .{ this, global, ctx, resolve, reject }); + } + pub fn then(this: JSValue, global: *JSGlobalObject, comptime Then: type, ctx: *Then, comptime onResolve: fn (*Then, globalThis: *JSGlobalObject, args: []const JSC.JSValue) void, comptime onReject: fn (*Then, globalThis: *JSGlobalObject, args: []const JSC.JSValue) void) void { + const Handler = struct { + fn resolve( + globalThis: [*c]JSGlobalObject, + ptr: ?*anyopaque, + arguments_ptr_: JSC.JSValue, + arguments_len: usize, + ) callconv(.C) void { + @setRuntimeSafety(false); + var arguments_ptr = @intToPtr([*]const JSC.JSValue, @enumToInt(arguments_ptr_)); + onResolve(bun.cast(*Then, ptr.?), globalThis, arguments_ptr[0..arguments_len]); + } + + pub fn reject( + globalThis: [*c]JSGlobalObject, + ptr: ?*anyopaque, + arguments_ptr_: JSC.JSValue, + arguments_len: usize, + ) callconv(.C) void { + @setRuntimeSafety(false); + var arguments_ptr = @intToPtr([*]const JSC.JSValue, @enumToInt(arguments_ptr_)); + onReject(bun.cast(*Then, ptr.?), globalThis, arguments_ptr[0..arguments_len]); + } + }; + + this._then( + global, + ctx, + Handler.resolve, + Handler.reject, + ); + } + pub fn getDescription(this: JSValue, global: *JSGlobalObject) ZigString { var zig_str = ZigString.init(""); getSymbolDescription(this, global, &zig_str); @@ -2314,7 +2356,7 @@ pub const JSValue = enum(u64) { return @intToPtr(*anyopaque, @enumToInt(this)); } - pub const Extern = [_][]const u8{ "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "getReadableStreamState", "getWritableStreamState", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" }; + pub const Extern = [_][]const u8{ "_then", "put", "makeWithNameAndPrototype", "parseJSON", "symbolKeyFor", "symbolFor", "getSymbolDescription", "createInternalPromise", "asInternalPromise", "asArrayBuffer_", "getReadableStreamState", "getWritableStreamState", "fromEntries", "createTypeError", "createRangeError", "createObject2", "getIfPropertyExistsImpl", "jsType", "jsonStringify", "kind_", "isTerminationException", "isSameValue", "getLengthOfArray", "toZigString", "createStringArray", "createEmptyObject", "putRecord", "asPromise", "isClass", "getNameProperty", "getClassName", "getErrorsProperty", "toInt32", "toBoolean", "isInt32", "isIterable", "forEach", "isAggregateError", "toZigException", "isException", "toWTFString", "hasProperty", "getPropertyNames", "getDirect", "putDirect", "getIfExists", "asString", "asObject", "asNumber", "isError", "jsNull", "jsUndefined", "jsTDZValue", "jsBoolean", "jsDoubleNumber", "jsNumberFromDouble", "jsNumberFromChar", "jsNumberFromU16", "jsNumberFromInt32", "jsNumberFromInt64", "jsNumberFromUint64", "isBoolean", "isAnyInt", "isUInt32AsAnyInt", "isInt32AsAnyInt", "isNumber", "isString", "isBigInt", "isHeapBigInt", "isBigInt32", "isSymbol", "isPrimitive", "isGetterSetter", "isCustomGetterSetter", "isObject", "isCell", "asCell", "toString", "toStringOrNull", "toPropertyKey", "toPropertyKeyValue", "toObject", "toString", "getPrototype", "getPropertyByPropertyName", "eqlValue", "eqlCell", "isCallable" }; }; extern "c" fn Microtask__run(*Microtask, *JSGlobalObject) void; diff --git a/src/javascript/jsc/bindings/headers-cpp.h b/src/javascript/jsc/bindings/headers-cpp.h index ba8175a74..3e8e7af5d 100644 --- a/src/javascript/jsc/bindings/headers-cpp.h +++ b/src/javascript/jsc/bindings/headers-cpp.h @@ -1,4 +1,4 @@ -//-- AUTOGENERATED FILE -- 1647600299 +//-- AUTOGENERATED FILE -- 1647769923 // clang-format off #pragma once diff --git a/src/javascript/jsc/bindings/headers.h b/src/javascript/jsc/bindings/headers.h index 1d36062da..fb72e3798 100644 --- a/src/javascript/jsc/bindings/headers.h +++ b/src/javascript/jsc/bindings/headers.h @@ -1,5 +1,5 @@ // clang-format: off -//-- AUTOGENERATED FILE -- 1647600299 +//-- AUTOGENERATED FILE -- 1647769923 #pragma once #include <stddef.h> @@ -426,6 +426,7 @@ CPP_DECL size_t WTF__String__length(WTF__String* arg0); #pragma mark - JSC::JSValue +CPP_DECL void JSC__JSValue___then(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, void* arg2, void (* ArgFn3)(JSC__JSGlobalObject* arg0, void* arg1, JSC__JSValue arg2, size_t arg3), void (* ArgFn4)(JSC__JSGlobalObject* arg0, void* arg1, JSC__JSValue arg2, size_t arg3)); CPP_DECL bool JSC__JSValue__asArrayBuffer_(JSC__JSValue JSValue0, JSC__JSGlobalObject* arg1, Bun__ArrayBuffer* arg2); CPP_DECL JSC__JSCell* JSC__JSValue__asCell(JSC__JSValue JSValue0); CPP_DECL JSC__JSInternalPromise* JSC__JSValue__asInternalPromise(JSC__JSValue JSValue0); diff --git a/src/javascript/jsc/bindings/headers.zig b/src/javascript/jsc/bindings/headers.zig index f9d09821a..f920c74d9 100644 --- a/src/javascript/jsc/bindings/headers.zig +++ b/src/javascript/jsc/bindings/headers.zig @@ -274,6 +274,7 @@ pub extern fn WTF__String__isEmpty(arg0: [*c]WTF__String) bool; pub extern fn WTF__String__isExternal(arg0: [*c]WTF__String) bool; pub extern fn WTF__String__isStatic(arg0: [*c]WTF__String) bool; pub extern fn WTF__String__length(arg0: [*c]WTF__String) usize; +pub extern fn JSC__JSValue___then(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: ?*anyopaque, ArgFn3: ?fn ([*c]JSC__JSGlobalObject, ?*anyopaque, JSC__JSValue, usize) callconv(.C) void, ArgFn4: ?fn ([*c]JSC__JSGlobalObject, ?*anyopaque, JSC__JSValue, usize) callconv(.C) void) void; pub extern fn JSC__JSValue__asArrayBuffer_(JSValue0: JSC__JSValue, arg1: [*c]JSC__JSGlobalObject, arg2: [*c]Bun__ArrayBuffer) bool; pub extern fn JSC__JSValue__asCell(JSValue0: JSC__JSValue) [*c]JSC__JSCell; pub extern fn JSC__JSValue__asInternalPromise(JSValue0: JSC__JSValue) [*c]JSC__JSInternalPromise; diff --git a/src/javascript/jsc/javascript.zig b/src/javascript/jsc/javascript.zig index 7bd8e0244..4a8fefd3c 100644 --- a/src/javascript/jsc/javascript.zig +++ b/src/javascript/jsc/javascript.zig @@ -422,6 +422,7 @@ pub const SavedSourceMap = struct { return SourceMap.Mapping.find(mappings, line, column); } }; +const uws = @import("uws"); // If you read JavascriptCore/API/JSVirtualMachine.mm - https://github.com/WebKit/WebKit/blob/acff93fb303baa670c055cb24c2bad08691a01a0/Source/JavaScriptCore/API/JSVirtualMachine.mm#L101 // We can see that it's sort of like std.mem.Allocator but for JSGlobalContextRef, to support Automatic Reference Counting @@ -450,6 +451,7 @@ pub const VirtualMachine = struct { node_fs: ?*Node.NodeFS = null, has_loaded_node_modules: bool = false, timer: Bun.Timer = Bun.Timer{}, + uws_event_loop: ?*uws.Loop = null, arena: *Arena = undefined, has_loaded: bool = false, @@ -596,6 +598,9 @@ pub const VirtualMachine = struct { this.concurrent_lock.lock(); defer this.concurrent_lock.unlock(); this.concurrent_tasks.writeItem(task) catch unreachable; + if (this.virtual_machine.uws_event_loop) |loop| { + loop.nextTick(*EventLoop, this, EventLoop.tick); + } _ = this.ready_tasks_count.fetchAdd(1, .Monotonic); } }; @@ -728,7 +733,6 @@ pub const VirtualMachine = struct { .origin_timer = std.time.Timer.start() catch @panic("Please don't mess with timers."), .ref_strings = JSC.RefString.Map.init(allocator), }; - VirtualMachine.vm.regular_event_loop.tasks = EventLoop.Queue.init( default_allocator, ); diff --git a/src/javascript/jsc/node/node_fs.zig b/src/javascript/jsc/node/node_fs.zig index 0c47d3aa9..b7aacbf97 100644 --- a/src/javascript/jsc/node/node_fs.zig +++ b/src/javascript/jsc/node/node_fs.zig @@ -2168,7 +2168,7 @@ const Arguments = struct { }; }; -pub const Constants = struct { +const Constants = struct { // File Access Constants /// Constant for fs.access(). File is visible to the calling process. pub const F_OK = std.os.F_OK; diff --git a/src/jsc.zig b/src/jsc.zig index cd1744f21..e159441bb 100644 --- a/src/jsc.zig +++ b/src/jsc.zig @@ -21,6 +21,8 @@ pub const Cloudflare = struct { pub const Jest = @import("./javascript/jsc/test/jest.zig"); pub const API = struct { pub const Transpiler = @import("./javascript/jsc/api/transpiler.zig"); + pub const Server = @import("./javascript/jsc/api/server.zig").Server; + pub const SSLServer = @import("./javascript/jsc/api/server.zig").SSLServer; pub const Bun = @import("./javascript/jsc/api/bun.zig"); pub const Router = @import("./javascript/jsc/api/router.zig"); }; diff --git a/src/runtime.footer.bun.js b/src/runtime.footer.bun.js index a7f7942bd..9415ede08 100644 --- a/src/runtime.footer.bun.js +++ b/src/runtime.footer.bun.js @@ -15,3 +15,5 @@ export var $$bun_runtime_json_parse = JSON.parse; export var __internalIsCommonJSNamespace = BUN_RUNTIME.__internalIsCommonJSNamespace; globalThis.require ||= BUN_RUNTIME.__require; +globalThis.__internalIsCommonJSNamespace ||= + BUN_RUNTIME.__internalIsCommonJSNamespace; |