aboutsummaryrefslogtreecommitdiff
path: root/packages/bun-usockets
diff options
context:
space:
mode:
Diffstat (limited to 'packages/bun-usockets')
-rw-r--r--packages/bun-usockets/src/bsd.c51
-rw-r--r--packages/bun-usockets/src/context.c3
-rw-r--r--packages/bun-usockets/src/crypto/openssl.c2
-rw-r--r--packages/bun-usockets/src/eventing/epoll_kqueue.c37
-rw-r--r--packages/bun-usockets/src/libusockets.h5
-rw-r--r--packages/bun-usockets/src/loop.c2
-rw-r--r--packages/bun-usockets/src/socket.c85
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;
+}