diff options
Diffstat (limited to 'packages/bun-usockets')
-rw-r--r-- | packages/bun-usockets/src/bsd.c | 51 | ||||
-rw-r--r-- | packages/bun-usockets/src/context.c | 3 | ||||
-rw-r--r-- | packages/bun-usockets/src/crypto/openssl.c | 2 | ||||
-rw-r--r-- | packages/bun-usockets/src/eventing/epoll_kqueue.c | 37 | ||||
-rw-r--r-- | packages/bun-usockets/src/libusockets.h | 5 | ||||
-rw-r--r-- | packages/bun-usockets/src/loop.c | 2 | ||||
-rw-r--r-- | packages/bun-usockets/src/socket.c | 85 |
7 files changed, 109 insertions, 76 deletions
diff --git a/packages/bun-usockets/src/bsd.c b/packages/bun-usockets/src/bsd.c index 7683acd7d..fc501e4d9 100644 --- a/packages/bun-usockets/src/bsd.c +++ b/packages/bun-usockets/src/bsd.c @@ -665,9 +665,39 @@ int bsd_udp_packet_buffer_ecn(void *msgvec, int index) { return 0; // no ecn defaults to 0 } -static int bsd_do_connect(struct addrinfo *result, int fd) +static int bsd_do_connect_raw(struct addrinfo *rp, int fd) { - return connect(fd, result->ai_addr, (socklen_t) result->ai_addrlen); + do { + if (connect(fd, rp->ai_addr, rp->ai_addrlen) == 0 || errno == EINPROGRESS) { + return 0; + } + } while (errno == EINTR); + + return LIBUS_SOCKET_ERROR; +} + +static int bsd_do_connect(struct addrinfo *rp, int *fd) +{ + while (rp != NULL) { + if (bsd_do_connect_raw(rp, *fd) == 0) { + return 0; + } + + rp = rp->ai_next; + bsd_close_socket(*fd); + + if (rp == NULL) { + return LIBUS_SOCKET_ERROR; + } + + int resultFd = bsd_create_socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (resultFd < 0) { + return LIBUS_SOCKET_ERROR; + } + *fd = resultFd; + } + + return LIBUS_SOCKET_ERROR; } LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(const char *host, int port, const char *source_host, int options) { @@ -700,18 +730,21 @@ LIBUS_SOCKET_DESCRIPTOR bsd_create_connect_socket(const char *host, int port, co return LIBUS_SOCKET_ERROR; } } - } - - do { - if (bsd_do_connect(result, fd) != 0 && errno != EINPROGRESS) { + + if (bsd_do_connect_raw(result, fd) != 0) { bsd_close_socket(fd); freeaddrinfo(result); return LIBUS_SOCKET_ERROR; } - } while (errno == EINTR); - + } else { + if (bsd_do_connect(result, &fd) != 0) { + freeaddrinfo(result); + return LIBUS_SOCKET_ERROR; + } + } + + freeaddrinfo(result); - return fd; } diff --git a/packages/bun-usockets/src/context.c b/packages/bun-usockets/src/context.c index a4d243e85..9e0dd5356 100644 --- a/packages/bun-usockets/src/context.c +++ b/packages/bun-usockets/src/context.c @@ -29,6 +29,7 @@ int default_is_low_prio_handler(struct us_socket_t *s) { unsigned short us_socket_context_timestamp(int ssl, struct us_socket_context_t *context) { return context->timestamp; } +int us_internal_raw_root_certs(struct us_cert_string_t** out); int us_raw_root_certs(struct us_cert_string_t**out){ return us_internal_raw_root_certs(out); } @@ -568,7 +569,7 @@ void *us_socket_context_ext(int ssl, struct us_socket_context_t *context) { void us_socket_context_on_handshake(int ssl, struct us_socket_context_t *context, void (*on_handshake)(struct us_socket_context_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data), void* custom_data) { #ifndef LIBUS_NO_SSL if (ssl) { - us_internal_on_ssl_handshake((struct us_internal_ssl_socket_context_t *) context, on_handshake, custom_data); + us_internal_on_ssl_handshake((struct us_internal_ssl_socket_context_t *) context, (void (*)(struct us_internal_ssl_socket_t *, int success, struct us_bun_verify_error_t verify_error, void* custom_data))on_handshake, custom_data); return; } #endif diff --git a/packages/bun-usockets/src/crypto/openssl.c b/packages/bun-usockets/src/crypto/openssl.c index 0b55ca866..a03bf3520 100644 --- a/packages/bun-usockets/src/crypto/openssl.c +++ b/packages/bun-usockets/src/crypto/openssl.c @@ -45,7 +45,7 @@ void *sni_find(void *sni, const char *hostname); #include "./root_certs.h" #include <stdatomic.h> -static const root_certs_size = sizeof(root_certs) / sizeof(root_certs[0]); +static const size_t root_certs_size = sizeof(root_certs) / sizeof(root_certs[0]); static X509* root_cert_instances[root_certs_size] = {NULL}; static atomic_flag root_cert_instances_lock = ATOMIC_FLAG_INIT; static atomic_bool root_cert_instances_initialized = 0; diff --git a/packages/bun-usockets/src/eventing/epoll_kqueue.c b/packages/bun-usockets/src/eventing/epoll_kqueue.c index 7ab2be826..d051f5b5a 100644 --- a/packages/bun-usockets/src/eventing/epoll_kqueue.c +++ b/packages/bun-usockets/src/eventing/epoll_kqueue.c @@ -30,13 +30,13 @@ void Bun__internal_dispatch_ready_poll(void* loop, void* poll); #include <stdint.h> #endif -void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs); +void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs, void*); /* Pointer tags are used to indicate a Bun pointer versus a uSockets pointer */ #define UNSET_BITS_49_UNTIL_64 0x0000FFFFFFFFFFFF #define CLEAR_POINTER_TAG(p) ((void *) ((uintptr_t) (p) & UNSET_BITS_49_UNTIL_64)) -#define LIKELY(cond) __builtin_expect((uint64_t)(void*)cond, 1) -#define UNLIKELY(cond) __builtin_expect((uint64_t)(void*)cond, 0) +#define LIKELY(cond) __builtin_expect((uint64_t)(void*)(cond), 1) +#define UNLIKELY(cond) __builtin_expect((uint64_t)(void*)(cond), 0) #ifdef LIBUS_USE_EPOLL #define GET_READY_POLL(loop, index) (struct us_poll_t *) loop->ready_polls[index].data.ptr @@ -174,13 +174,20 @@ void us_loop_run(struct us_loop_t *loop) { } } +void bun_on_tick_before(void* ctx); +void bun_on_tick_after(void* ctx); -void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs) { + +void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs, void* tickCallbackContext) { us_loop_integrate(loop); if (loop->num_polls == 0) return; + if (tickCallbackContext) { + bun_on_tick_before(tickCallbackContext); + } + /* Emit pre callback */ us_internal_loop_pre(loop); @@ -202,6 +209,10 @@ void us_loop_run_bun_tick(struct us_loop_t *loop, int64_t timeoutMs) { } #endif + if (tickCallbackContext) { + bun_on_tick_after(tickCallbackContext); + } + /* Iterate ready polls, dispatching them by type */ for (loop->current_ready_poll = 0; loop->current_ready_poll < loop->num_ready_polls; loop->current_ready_poll++) { struct us_poll_t *poll = GET_READY_POLL(loop, loop->current_ready_poll); @@ -403,14 +414,18 @@ struct us_timer_t *us_create_timer(struct us_loop_t *loop, int fallthrough, unsi #endif #ifdef LIBUS_USE_EPOLL -void us_timer_close(struct us_timer_t *timer) { +void us_timer_close(struct us_timer_t *timer, int fallthrough) { struct us_internal_callback_t *cb = (struct us_internal_callback_t *) timer; us_poll_stop(&cb->p, cb->loop); close(us_poll_fd(&cb->p)); - /* (regular) sockets are the only polls which are not freed immediately */ - us_poll_free((struct us_poll_t *) timer, cb->loop); + /* (regular) sockets are the only polls which are not freed immediately */ + if(fallthrough){ + us_free(timer); + }else { + us_poll_free((struct us_poll_t *) timer, cb->loop); + } } void us_timer_set(struct us_timer_t *t, void (*cb)(struct us_timer_t *t), int ms, int repeat_ms) { @@ -427,7 +442,7 @@ void us_timer_set(struct us_timer_t *t, void (*cb)(struct us_timer_t *t), int ms us_poll_start((struct us_poll_t *) t, internal_cb->loop, LIBUS_SOCKET_READABLE); } #else -void us_timer_close(struct us_timer_t *timer) { +void us_timer_close(struct us_timer_t *timer, int fallthrough) { struct us_internal_callback_t *internal_cb = (struct us_internal_callback_t *) timer; struct kevent64_s event; @@ -435,7 +450,11 @@ void us_timer_close(struct us_timer_t *timer) { kevent64(internal_cb->loop->fd, &event, 1, NULL, 0, 0, NULL); /* (regular) sockets are the only polls which are not freed immediately */ - us_poll_free((struct us_poll_t *) timer, internal_cb->loop); + if(fallthrough){ + us_free(timer); + }else { + us_poll_free((struct us_poll_t *) timer, internal_cb->loop); + } } void us_timer_set(struct us_timer_t *t, void (*cb)(struct us_timer_t *t), int ms, int repeat_ms) { diff --git a/packages/bun-usockets/src/libusockets.h b/packages/bun-usockets/src/libusockets.h index 5f4563605..cff9a1bd2 100644 --- a/packages/bun-usockets/src/libusockets.h +++ b/packages/bun-usockets/src/libusockets.h @@ -132,7 +132,7 @@ struct us_timer_t *us_create_timer(struct us_loop_t *loop, int fallthrough, unsi void *us_timer_ext(struct us_timer_t *timer); /* */ -void us_timer_close(struct us_timer_t *timer); +void us_timer_close(struct us_timer_t *timer, int fallthrough); /* Arm a timer with a delay from now and eventually a repeat delay. * Specify 0 as repeat delay to disable repeating. Specify both 0 to disarm. */ @@ -382,16 +382,17 @@ int us_socket_local_port(int ssl, struct us_socket_t *s); /* Copy remote (IP) address of socket, or fail with zero length. */ void us_socket_remote_address(int ssl, struct us_socket_t *s, char *buf, int *length); +void us_socket_local_address(int ssl, struct us_socket_t *s, char *buf, int *length); /* Bun extras */ struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR* fds); struct us_socket_t *us_socket_from_fd(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR fd); -struct us_socket_t *us_socket_detach(int ssl, struct us_socket_t *s); struct us_socket_t *us_socket_attach(int ssl, LIBUS_SOCKET_DESCRIPTOR client_fd, struct us_socket_context_t *ctx, int flags, int socket_ext_size); struct us_socket_t *us_socket_wrap_with_tls(int ssl, struct us_socket_t *s, struct us_bun_socket_context_options_t options, struct us_socket_events_t events, int socket_ext_size); int us_socket_raw_write(int ssl, struct us_socket_t *s, const char *data, int length, int msg_more); struct us_socket_t* us_socket_open(int ssl, struct us_socket_t * s, int is_client, char* ip, int ip_length); int us_raw_root_certs(struct us_cert_string_t**out); +unsigned int us_get_remote_address_info(char *buf, struct us_socket_t *s, const char **dest, int *port, int *is_ipv6); #ifdef __cplusplus } diff --git a/packages/bun-usockets/src/loop.c b/packages/bun-usockets/src/loop.c index 9ad1e64bf..e230fa29b 100644 --- a/packages/bun-usockets/src/loop.c +++ b/packages/bun-usockets/src/loop.c @@ -47,7 +47,7 @@ void us_internal_loop_data_free(struct us_loop_t *loop) { free(loop->data.recv_buf); - us_timer_close(loop->data.sweep_timer); + us_timer_close(loop->data.sweep_timer, 0); us_internal_async_close(loop->data.wakeup_async); } diff --git a/packages/bun-usockets/src/socket.c b/packages/bun-usockets/src/socket.c index 5f5a91acb..d8371c2ff 100644 --- a/packages/bun-usockets/src/socket.c +++ b/packages/bun-usockets/src/socket.c @@ -48,6 +48,16 @@ void us_socket_remote_address(int ssl, struct us_socket_t *s, char *buf, int *le } } +void us_socket_local_address(int ssl, struct us_socket_t *s, char *buf, int *length) { + struct bsd_addr_t addr; + if (bsd_local_addr(us_poll_fd(&s->p), &addr) || *length < bsd_addr_get_ip_length(&addr)) { + *length = 0; + } else { + *length = bsd_addr_get_ip_length(&addr); + memcpy(buf, bsd_addr_get_ip(&addr), *length); + } +} + struct us_socket_context_t *us_socket_context(int ssl, struct us_socket_t *s) { return s->context; } @@ -140,59 +150,6 @@ struct us_socket_t *us_socket_close(int ssl, struct us_socket_t *s, int code, vo return s; } -// This function is the same as us_socket_close but: -// - does not emit on_close event -// - does not close -struct us_socket_t *us_socket_detach(int ssl, struct us_socket_t *s) { - if (!us_socket_is_closed(0, s)) { - if (s->low_prio_state == 1) { - /* Unlink this socket from the low-priority queue */ - if (!s->prev) s->context->loop->data.low_prio_head = s->next; - else s->prev->next = s->next; - - if (s->next) s->next->prev = s->prev; - - s->prev = 0; - s->next = 0; - s->low_prio_state = 0; - } else { - us_internal_socket_context_unlink(s->context, s); - } - us_poll_stop((struct us_poll_t *) s, s->context->loop); - - /* Link this socket to the close-list and let it be deleted after this iteration */ - s->next = s->context->loop->data.closed_head; - s->context->loop->data.closed_head = s; - - /* Any socket with prev = context is marked as closed */ - s->prev = (struct us_socket_t *) s->context; - - return s; - } - return s; -} - -// This function is used for moving a socket between two different event loops -struct us_socket_t *us_socket_attach(int ssl, LIBUS_SOCKET_DESCRIPTOR client_fd, struct us_socket_context_t *ctx, int flags, int socket_ext_size) { - struct us_poll_t *accepted_p = us_create_poll(ctx->loop, 0, sizeof(struct us_socket_t) - sizeof(struct us_poll_t) + socket_ext_size); - us_poll_init(accepted_p, client_fd, POLL_TYPE_SOCKET); - us_poll_start(accepted_p, ctx->loop, flags); - - struct us_socket_t *s = (struct us_socket_t *) accepted_p; - - s->context = ctx; - s->timeout = 0; - s->low_prio_state = 0; - - /* We always use nodelay */ - bsd_socket_nodelay(client_fd, 1); - us_internal_socket_context_link(ctx, s); - - if (ctx->on_open) ctx->on_open(s, 0, 0, 0); - - return s; -} - struct us_socket_t *us_socket_pair(struct us_socket_context_t *ctx, int socket_ext_size, LIBUS_SOCKET_DESCRIPTOR* fds) { #ifdef LIBUS_USE_LIBUV return 0; @@ -333,3 +290,25 @@ int us_socket_raw_write(int ssl, struct us_socket_t *s, const char *data, int le // non-TLS is always raw return us_socket_write(ssl, s, data, length, msg_more); } + +unsigned int us_get_remote_address_info(char *buf, struct us_socket_t *s, const char **dest, int *port, int *is_ipv6) +{ + // This function is manual inlining + modification of + // us_socket_remote_address + // AsyncSocket::getRemoteAddress + // To get { ip, port, is_ipv6 } for Bun.serve().requestIP() + struct bsd_addr_t addr; + if (bsd_remote_addr(us_poll_fd(&s->p), &addr)) { + return 0; + } + + int length = bsd_addr_get_ip_length(&addr); + if (!length) { + return 0; + } + + memcpy(buf, bsd_addr_get_ip(&addr), length); + *port = bsd_addr_get_port(&addr); + + return length; +} |